1 # Copyright (C) 2009 by Aiwota Programmer
2 # aiwotaprog@tetteke.tk
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 def get_approximate_char_height(pango_context):
25 desc = pango_context.get_font_description()
26 font = pango_context.load_font(desc)
27 ink, log = font.get_glyph_extents(0)
28 return log[3] / pango.SCALE + 2
32 def __init__(self, x, y, width, height):
43 def __init__(self, start_index, end_index, rectangle):
44 self.start_index = start_index
45 self.end_index = end_index
46 self.rectangle = rectangle
48 def is_on_xy(self, x, y):
49 left = self.rectangle.x
50 right = left + self.rectangle.width
51 top = self.rectangle.y
52 bottom = top + self.rectangle.height
53 return x >= left and x < right and y >= top and y < bottom
58 def __init__(self, pango_layout):
59 self.pango_layout = pango_layout
62 def recalc_char_widths(self):
68 def is_on_xy(self, x, y):
69 for line in self.line_list:
70 if line.is_on_xy(x, y):
74 def xy_to_index(self, x, y):
77 def build_line_list(self, x, y, width, left_margin):
80 line = Line(0, 0, Rectangle(
82 get_approximate_char_height(self.pango_layout.get_context())))
83 self.line_list.append(line)
87 def get_text(self, selection=False, start_index=0, end_index=0xffffff):
90 def draw(self, drawingarea, y_offset, pango_layout,
91 selection=False, start_index=0, end_index=0xffffff):
97 ch_width_dict = {} # key: char, value: width
99 def __init__(self, text, pango_layout):
101 self.pango_layout = pango_layout
103 self.recalc_char_widths()
107 def recalc_char_widths(self):
108 self.widths = [i for i in itertools.repeat(0, len(self.text))]
110 dict = self._get_ch_width_dict()
111 for index, ch in enumerate(self.text):
113 self.pango_layout.set_attributes(self._get_attrs())
114 self.pango_layout.set_text(ch)
115 a, logi = self.pango_layout.get_extents()
116 width = 1.0 * Rectangle(*logi).width / pango.SCALE
117 self.widths[index] = width
121 self.widths[index] = width
123 def _get_ch_width_dict(self):
124 return ElementText.ch_width_dict
126 def _get_attrs(self):
127 attrs = pango.AttrList()
130 def is_on_xy(self, x, y):
131 for line in self.line_list:
132 if line.is_on_xy(x, y):
136 def xy_to_index(self, x, y):
137 for line in self.line_list:
138 top = line.rectangle.y
139 bottom = top + line.rectangle.height
140 if y >= top and y < bottom:
141 sum_of_widths = line.rectangle.x
142 index = line.start_index
143 for width in self.widths[line.start_index:line.end_index]:
144 if sum_of_widths + width/2 > x:
146 sum_of_widths += width
150 def build_line_list(self, x, y, width, left_margin):
153 current_line_start_index = 0
156 current_line_width = 0
158 ch_h = get_approximate_char_height(self.pango_layout.get_context())
160 for index, ch in enumerate(self.text):
161 ch_w = self.widths[index]
162 if current_line_x + current_line_width + ch_w > width:
164 current_line_start_index, index,
166 current_line_x, current_line_y,
167 current_line_width, ch_h))
168 self.line_list.append(line)
170 current_line_start_index = index
171 current_line_x = left_margin
172 current_line_y += ch_h
173 current_line_width = ch_w
175 current_line_width += ch_w
177 if current_line_start_index < len(self.text):
178 line = Line(current_line_start_index, len(self.text),
179 Rectangle(current_line_x,
183 self.line_list.append(line)
185 current_line_x += current_line_width
187 return current_line_x, current_line_y
189 def get_text(self, selection=False, start_index=0, end_index=0xffffff):
193 for line in self.line_list:
195 t = self.text[line.start_index:line.end_index]
197 s = start_index - line.start_index
199 s = min(s, line.end_index - line.start_index)
201 e = end_index - line.start_index
202 e = min(e, line.end_index - line.start_index)
211 def draw(self, drawingarea, y_offset, pango_layout,
212 selection=False, start_index=0, end_index=0xffffff):
214 if drawingarea.get_property("has-focus"):
215 selection_fg = drawingarea.style.text[gtk.STATE_SELECTED]
216 selection_bg = drawingarea.style.base[gtk.STATE_SELECTED]
218 selection_fg = drawingarea.style.text[gtk.STATE_ACTIVE]
219 selection_bg = drawingarea.style.base[gtk.STATE_ACTIVE]
221 for line in self.line_list:
223 text = self.text[line.start_index:line.end_index]
224 u_text = text.encode("utf8")
225 gc = drawingarea.window.new_gc()
226 gc.set_foreground(drawingarea.style.text[gtk.STATE_NORMAL])
227 gc.set_background(drawingarea.style.base[gtk.STATE_NORMAL])
228 attrs = self._get_attrs()
231 s = start_index - line.start_index
233 s = min(s, line.end_index - line.start_index)
234 s = len(text[:s].encode("utf8"))
236 e = end_index - line.start_index
237 e = min(e, line.end_index - line.start_index)
239 e = len(text[:e].encode("utf8"))
241 selection_all_attr_fg = pango.AttrForeground(
242 selection_fg.red, selection_fg.green, selection_fg.blue,
244 selection_all_attr_bg= pango.AttrBackground(
245 selection_bg.red, selection_bg.green, selection_bg.blue,
247 attrs.insert(selection_all_attr_fg)
248 attrs.insert(selection_all_attr_bg)
250 pango_layout.set_text(u_text)
251 pango_layout.set_attributes(attrs)
252 drawingarea.window.draw_layout(
253 gc, int(line.rectangle.x), line.rectangle.y + y_offset,
257 class ElementBoldText(ElementText):
259 ch_width_dict = {} # key: char, value: width
261 def _get_attrs(self):
262 attrlist = pango.AttrList()
263 attr = pango.AttrWeight(pango.WEIGHT_BOLD,
265 attrlist.insert(attr)
268 def _get_ch_width_dict(self):
269 return ElementBoldText.ch_width_dict
272 class ElementLink(ElementText):
274 def __init__(self, text, href, pango_layout):
276 ElementText.__init__(self, text, pango_layout)
278 def _get_attrs(self):
279 attrlist = pango.AttrList()
280 attr = pango.AttrUnderline(pango.UNDERLINE_SINGLE,
282 attrlist.insert(attr)