+# Copyright (C) 2007 by Aiwota Programmer
+# aiwotaprog@tetteke.tk
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import pango
+
+
+class ThreadView(gtk.HBox):
+
+ def __init__(self):
+ gtk.HBox.__init__(self, False, 0)
+ self.drawingarea = gtk.DrawingArea()
+ self.vscrollbar = gtk.VScrollbar()
+ self.pack_start(self.drawingarea)
+ self.pack_start(self.vscrollbar, expand=False)
+ self.adjustment = self.vscrollbar.get_adjustment()
+
+ self.drawingarea.add_events(gtk.gdk.SCROLL_MASK)
+
+ self.adjustment.step_increment = 20
+ self.drawingarea_prev_width = 0
+
+ self.drawingarea.connect(
+ "expose-event", self.on_drawingarea_expose_event)
+ self.drawingarea.connect(
+ "size-allocate", self.on_drawingarea_size_allocate)
+ self.drawingarea.connect(
+ "button-press-event", self.on_drawingarea_button_press_event)
+ self.drawingarea.connect(
+ "scroll-event", self.on_drawingarea_scroll_event)
+ self.vscrollbar.connect(
+ "value-changed", self.on_vscrollbar_value_changed)
+
+ self.initialize_buffer()
+
+ def initialize_buffer(self):
+ self.pangolayout = []
+
+ def add_layout(self, pangolayout):
+ self.pangolayout.append(pangolayout)
+
+ def create_pango_layout(self, text):
+ return self.drawingarea.create_pango_layout(text)
+
+ def redraw(self):
+ self.drawingarea.queue_draw()
+
+ def relayout(self):
+ width = self.drawingarea.allocation.width
+ sum_height = 0
+ for layout in self.pangolayout:
+ layout.set_width((width - layout.marginleft) * pango.SCALE)
+ layout.posY = sum_height
+ x, y = layout.get_pixel_size()
+ sum_height += y
+ self.adjustment.upper = sum_height
+
+ def jump(self, value):
+ if value > self.adjustment.upper - self.adjustment.page_size:
+ value = self.adjustment.upper - self.adjustment.page_size
+ self.adjustment.set_value(value)
+
+ def jump_to_layout(self, layout):
+ self.jump(layout.posY)
+
+ def jump_to_the_end(self):
+ value = self.adjustment.upper - self.adjustment.page_size
+ self.adjustment.set_value(value)
+
+ def jump_to_res(self, resnum):
+ for layout in self.pangolayout:
+ if layout.resnum == resnum:
+ self.jump_to_layout(layout)
+ return True
+ return False
+
+ def draw_viewport(self):
+ view_y = self.adjustment.get_value()
+ self.drawingarea.window.draw_rectangle(
+ self.drawingarea.style.base_gc[0],
+ True, 0, 0,
+ self.drawingarea.allocation.width,
+ self.drawingarea.allocation.height)
+
+ gc = self.drawingarea.window.new_gc()
+ for layout in self.pangolayout:
+ w, h = layout.get_pixel_size()
+ layout_top = layout.posY
+ layout_bottom = layout.posY + h
+ area_top = view_y
+ area_bottom = view_y + self.drawingarea.allocation.height
+ if layout_top <= area_bottom and layout_bottom >= area_top:
+ self.drawingarea.window.draw_layout(
+ gc, layout.marginleft, layout.posY - int(view_y), layout)
+
+ def on_drawingarea_expose_event(self, widget, event, data=None):
+ self.draw_viewport()
+
+ def on_drawingarea_size_allocate(self, widget, allocation, data=None):
+ if allocation.width != self.drawingarea_prev_width:
+ self.relayout()
+ self.drawingarea_prev_width = allocation.width
+ self.adjustment.page_size = self.drawingarea.allocation.height
+ self.adjustment.page_increment = self.drawingarea.allocation.height
+
+ def on_drawingarea_button_press_event(self, widget, event, data=None):
+ self.drawingarea.queue_draw()
+
+ def on_vscrollbar_value_changed(self, widget, data=None):
+ self.drawingarea.queue_draw()
+
+ def on_drawingarea_scroll_event(self, widget, event, data=None):
+ if event.direction == gtk.gdk.SCROLL_UP:
+ self.adjustment.value -= 66.476200804
+ if self.adjustment.value < self.adjustment.lower:
+ self.adjustment.value = self.adjustment.lower
+ if event.direction == gtk.gdk.SCROLL_DOWN:
+ self.adjustment.value += 66.476200804
+ max_value = self.adjustment.upper - self.adjustment.page_size
+ if self.adjustment.value > max_value:
+ self.adjustment.value = max_value