OSDN Git Service

120bd6435fd1cf2e11d5472c78a4d54ab8f84df6
[fukui-no-namari/fukui-no-namari.git] / src / FukuiNoNamari / thread_view.py
1 # Copyright (C) 2007 by Aiwota Programmer
2 # aiwotaprog@tetteke.tk
3 #
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.
8 #
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.
13 #
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
17
18 import pygtk
19 pygtk.require('2.0')
20 import gtk
21 import pango
22
23
24 class ThreadView(gtk.HBox):
25
26     def __init__(self):
27         gtk.HBox.__init__(self, False, 0)
28         self.drawingarea = gtk.DrawingArea()
29         self.vscrollbar = gtk.VScrollbar()
30         self.pack_start(self.drawingarea)
31         self.pack_start(self.vscrollbar, expand=False)
32         self.adjustment  = self.vscrollbar.get_adjustment()
33
34         self.drawingarea.add_events(gtk.gdk.SCROLL_MASK)
35
36         self.adjustment.step_increment = 20
37         self.drawingarea_prev_width = 0
38
39         self.drawingarea.connect(
40             "expose-event", self.on_drawingarea_expose_event)
41         self.drawingarea.connect(
42             "size-allocate", self.on_drawingarea_size_allocate)
43         self.drawingarea.connect(
44             "button-press-event", self.on_drawingarea_button_press_event)
45         self.drawingarea.connect(
46             "scroll-event", self.on_drawingarea_scroll_event)
47         self.vscrollbar.connect(
48             "value-changed", self.on_vscrollbar_value_changed)
49
50         self.initialize_buffer()
51
52     def initialize_buffer(self):
53         self.pangolayout = []
54
55     def add_layout(self, pangolayout):
56         if (len(self.pangolayout) != 0):
57             last = self.pangolayout[len(self.pangolayout)-1]
58             x, y = last.get_pixel_size()
59             pangolayout.posY = last.posY + y
60         self.set_layout_width(pangolayout)
61         self.pangolayout.append(pangolayout)
62         x, y = pangolayout.get_pixel_size()
63         self.adjustment.upper = pangolayout.posY + y
64         self.prevent_adjustment_overflow()
65         self.redraw()
66         self.change_vscrollbar_visible()
67
68     def create_pango_layout(self, text):
69         return self.drawingarea.create_pango_layout(text)
70
71     def set_layout_width(self, layout):
72         width = self.drawingarea.allocation.width
73         layout.set_width((width - layout.marginleft) * pango.SCALE)
74         
75     def redraw(self):
76         self.drawingarea.queue_draw()
77
78     def relayout(self):
79         width = self.drawingarea.allocation.width
80         sum_height = 0
81         for layout in self.pangolayout:
82             layout.set_width((width - layout.marginleft) * pango.SCALE)
83             layout.posY = sum_height
84             x, y = layout.get_pixel_size()
85             sum_height += y
86         self.adjustment.upper = sum_height
87         self.prevent_adjustment_overflow()
88         self.change_vscrollbar_visible()
89
90     def change_vscrollbar_visible(self):
91         if self.adjustment.upper < self.adjustment.page_size:
92             self.vscrollbar.hide()
93         else:
94             self.vscrollbar.show()
95
96     def jump(self, value):
97         if value > self.adjustment.upper - self.adjustment.page_size:
98             value = self.adjustment.upper - self.adjustment.page_size
99         self.adjustment.set_value(value)
100
101     def jump_to_layout(self, layout):
102         self.jump(layout.posY)
103         
104     def jump_to_the_end(self):
105         value = self.adjustment.upper - self.adjustment.page_size
106         self.adjustment.set_value(value)
107
108     def jump_to_res(self, resnum):
109         for layout in self.pangolayout:
110             if layout.resnum == resnum:
111                 self.jump_to_layout(layout)
112                 return True
113         return False
114
115     def draw_viewport(self):
116         view_y = self.adjustment.get_value()
117         self.drawingarea.window.draw_rectangle(
118             self.drawingarea.style.base_gc[0],
119             True, 0, 0,
120             self.drawingarea.allocation.width,
121             self.drawingarea.allocation.height)
122
123         gc = self.drawingarea.window.new_gc()
124         for layout in self.pangolayout:
125             w, h = layout.get_pixel_size()
126             layout_top = layout.posY
127             layout_bottom = layout.posY + h
128             area_top = view_y
129             area_bottom = view_y + self.drawingarea.allocation.height
130             if layout_top <= area_bottom and layout_bottom >= area_top:
131                 self.drawingarea.window.draw_layout(
132                     gc, layout.marginleft, layout.posY - int(view_y), layout)
133
134     def on_drawingarea_expose_event(self, widget, event, data=None):
135         self.draw_viewport()
136
137     def on_drawingarea_size_allocate(self, widget, allocation, data=None):
138         if allocation.width != self.drawingarea_prev_width:
139             self.relayout()
140             self.drawingarea_prev_width = allocation.width
141         self.adjustment.page_size = self.drawingarea.allocation.height
142         self.adjustment.page_increment = self.drawingarea.allocation.height
143
144         self.prevent_adjustment_overflow()
145         self.change_vscrollbar_visible()
146
147     def prevent_adjustment_overflow(self):
148         if (self.adjustment.value >
149             self.adjustment.upper - self.adjustment.page_size):
150             self.adjustment.value = (self.adjustment.upper -
151                                      self.adjustment.page_size)
152
153         if self.adjustment.value < 0:
154             self.adjustment.value = 0
155
156     def on_drawingarea_button_press_event(self, widget, event, data=None):
157         self.drawingarea.queue_draw()
158
159     def on_vscrollbar_value_changed(self, widget, data=None):
160         self.drawingarea.queue_draw()
161
162     def on_drawingarea_scroll_event(self, widget, event, data=None):
163         if event.direction == gtk.gdk.SCROLL_UP:
164             self.adjustment.value -= 66.476200804
165             if self.adjustment.value < self.adjustment.lower:
166                 self.adjustment.value = self.adjustment.lower
167         if event.direction == gtk.gdk.SCROLL_DOWN:
168             self.adjustment.value += 66.476200804
169             max_value = self.adjustment.upper - self.adjustment.page_size
170             if self.adjustment.value > max_value:
171                 self.adjustment.value = max_value
172         self.prevent_adjustment_overflow()