from FukuiNoNamariExt import thread_view_extend
+def get_approximate_char_height(pango_context):
+ desc = pango_context.get_font_description()
+ font = pango_context.load_font(desc)
+ ink, log = font.get_glyph_extents(0)
+ return log[3] / pango.SCALE + 2
+
+
class Line:
HEIGHT = 15
class ElementEmpty:
- def __init__(self):
+ def __init__(self, pango_layout):
+ self.pango_layout = pango_layout
self.initialize()
+ def recalc_char_widths(self):
+ pass
+
def initialize(self):
self.line_list = []
def build_line_list(self, x, y, width, left_margin):
self.initialize()
- line = Line(0, 0, gtk.gdk.Rectangle(x, y, width - x, Line.HEIGHT))
+ line = Line(0, 0, gtk.gdk.Rectangle(
+ x, y, width - x,
+ get_approximate_char_height(self.pango_layout.get_context())))
self.line_list.append(line)
return width, y
def __init__(self, text, pango_layout):
self.text = text
+ self.pango_layout = pango_layout
attrlist = self._get_attrs()
self.widths = thread_view_extend.get_char_width(
self.line_list = []
+ def recalc_char_widths(self):
+ attrlist = self._get_attrs()
+ self.widths = thread_view_extend.get_char_width(
+ self.pango_layout.get_context(), self.text, attrlist)
+
def _get_attrs(self):
attrs = pango.AttrList()
return attrs
current_line_y = y
current_line_width = 0
+ ch_h = get_approximate_char_height(self.pango_layout.get_context())
+
for index, ch in enumerate(self.text):
ch_w = self.widths[index]
- ch_h = Line.HEIGHT
if current_line_x + current_line_width + ch_w > width:
line = Line(
current_line_start_index, index,
gtk.gdk.Rectangle(
current_line_x, current_line_y,
- current_line_width, Line.HEIGHT))
+ current_line_width, ch_h))
self.line_list.append(line)
current_line_start_index = index
current_line_x = left_margin
- current_line_y += Line.HEIGHT
+ current_line_y += ch_h
current_line_width = ch_w
else:
current_line_width += ch_w
gtk.gdk.Rectangle(current_line_x,
current_line_y,
current_line_width,
- Line.HEIGHT))
+ ch_h))
self.line_list.append(line)
current_line_x += current_line_width
# represent one line
def __init__(self, left_margin, resnum, pango_layout):
- self.element_list = [ElementEmpty()]
+ self.element_list = [ElementEmpty(pango_layout)]
self.width = 0
self.height = 0
self.pango_layout = pango_layout
element = self.element_list[len(self.element_list) - 1]
return element
+ def recalc_char_widths(self):
+ for element in self.element_list:
+ element.recalc_char_widths()
+
def set_width(self, width):
self.width = width
current_x, current_y = element.build_line_list(
current_x, current_y, width, self.left_margin)
- self.height = current_y + Line.HEIGHT
+ self.height = current_y + get_approximate_char_height(self.pango_layout.get_context())
def get_pixel_size(self):
return self.width, self.height
"button-press-event", self.on_drawingarea_button_press_event)
self.drawingarea.connect(
"button-release-event", self.on_drawingarea_button_release_event)
+ self.drawingarea.connect(
+ "style-set", self.on_drawingarea_style_set)
self.vscrollbar.connect(
"value-changed", self.on_vscrollbar_value_changed)
def redraw(self):
self.drawingarea.queue_draw()
+ def wrap_relayout(self):
+ # before relayout, find top layout on gdkwindow
+ top_layout = self.get_layout_on_y(self.adjustment.value)
+ delta = 0
+
+ if top_layout is not None:
+ delta = top_layout.posY - self.vscrollbar.get_value()
+
+ self.relayout()
+ self.drawingarea_prev_width = self.drawingarea.allocation.width
+
+ # after relayout, set vscrollbar.value to top layout's posY
+ if top_layout is not None:
+ self.vscrollbar.set_value(top_layout.posY - delta)
+
def relayout(self):
self.layout_posY_map = [(0, [])]
def on_drawingarea_configure_event(self, widget, event, data=None):
if event.width != self.drawingarea_prev_width:
-
- # before relayout, find top layout on gdkwindow
- top_layout = None
- delta = 0
- for lay in self.res_layout_list:
- if lay.posY > self.adjustment.value:
- break
- top_layout = lay
-
- if top_layout is not None:
- delta = top_layout.posY - self.vscrollbar.get_value()
-
- self.relayout()
- self.drawingarea_prev_width = event.width
-
- # after relayout, set vscrollbar.value to top layout's posY
- if top_layout is not None:
- self.vscrollbar.set_value(top_layout.posY - delta)
+ self.wrap_relayout()
self.adjustment.page_size = self.drawingarea.allocation.height
self.vscrollbar.set_increments(20, self.drawingarea.allocation.height)
if (uri == p_uri and layout == p_layout and
element == p_element):
self.on_uri_clicked(uri)
+
+ def on_drawingarea_style_set(self, widget, previous_style, data=None):
+ if previous_style is None:
+ return False
+
+ new = widget.style.font_desc.hash()
+ old = previous_style.font_desc.hash()
+ if new != old:
+ for layout in self.res_layout_list:
+ layout.recalc_char_widths()
+ self.wrap_relayout()