pygtk.require('2.0')
import gtk
import pango
+from FukuiNoNamariExt import thread_view_extend
+
+
+class Line:
+
+ HEIGHT = 15
+
+ def __init__(self, start_index, end_index, rectangle):
+ self.start_index = start_index
+ self.end_index = end_index
+ self.rectangle = rectangle
+
+ def is_on_xy(self, x, y):
+ left = self.rectangle.x
+ right = left + self.rectangle.width
+ top = self.rectangle.y
+ bottom = top + self.rectangle.height
+ return x >= left and x < right and y >= top and y < bottom
+
+
+class ElementEmpty:
+
+ def __init__(self):
+ self.initialize()
+
+ def initialize(self):
+ self.line_list = []
+
+ def is_on_xy(self, x, y):
+ for line in self.line_list:
+ if line.is_on_xy(x, y):
+ return True
+ return False
+
+ def xy_to_index(self, x, y):
+ return 0
+
+ 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))
+ self.line_list.append(line)
+
+ return width, y
+
+ def get_text(self, selection=False, start_index=0, end_index=0xffffff):
+ return ""
+
+ def draw(self, drawingarea, y_offset, pango_layout,
+ selection=False, start_index=0, end_index=0xffffff):
+ pass
+
+
+class ElementText:
+
+ def __init__(self, text, pango_layout):
+ self.text = text
+
+ attrlist = self._get_attrs()
+ self.widths = thread_view_extend.get_char_width(
+ pango_layout.get_context(), text, attrlist)
+
+ self.line_list = []
+
+ def _get_attrs(self):
+ attrs = pango.AttrList()
+ return attrs
+
+ def is_on_xy(self, x, y):
+ for line in self.line_list:
+ if line.is_on_xy(x, y):
+ return True
+ return False
+
+ def xy_to_index(self, x, y):
+ for line in self.line_list:
+ top = line.rectangle.y
+ bottom = top + line.rectangle.height
+ if y >= top and y < bottom:
+ sum_of_widths = line.rectangle.x
+ index = line.start_index
+ for width in self.widths[line.start_index:line.end_index]:
+ if sum_of_widths + width/2 > x:
+ break
+ sum_of_widths += width
+ index += 1
+ return index
+
+ def build_line_list(self, x, y, width, left_margin):
+ self.line_list = []
+
+ current_line_start_index = 0
+ current_line_x = x
+ current_line_y = y
+ current_line_width = 0
+
+ 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))
+ self.line_list.append(line)
+
+ current_line_start_index = index
+ current_line_x = left_margin
+ current_line_y += Line.HEIGHT
+ current_line_width = ch_w
+ else:
+ current_line_width += ch_w
+
+ if current_line_start_index < len(self.text):
+ line = Line(current_line_start_index, len(self.text),
+ gtk.gdk.Rectangle(current_line_x,
+ current_line_y,
+ current_line_width,
+ Line.HEIGHT))
+ self.line_list.append(line)
+
+ current_line_x += current_line_width
+
+ return current_line_x, current_line_y
+
+ def get_text(self, selection=False, start_index=0, end_index=0xffffff):
+
+ text = ""
+
+ for line in self.line_list:
+
+ t = self.text[line.start_index:line.end_index]
+ if selection:
+ s = start_index - line.start_index
+ s = max(s, 0)
+ s = min(s, line.end_index - line.start_index)
+
+ e = end_index - line.start_index
+ e = min(e, line.end_index - line.start_index)
+ e = max(e, 0)
+
+ t = t[s:e]
+
+ text += t
+
+ return text
+
+ def draw(self, drawingarea, y_offset, pango_layout,
+ selection=False, start_index=0, end_index=0xffffff):
+
+ selection_fg = drawingarea.style.fg[3]
+ selection_bg = drawingarea.style.bg[3]
+
+ for line in self.line_list:
+
+ text = self.text[line.start_index:line.end_index]
+ u_text = text.encode("utf8")
+ gc = drawingarea.window.new_gc()
+ attrs = self._get_attrs()
+ if selection:
+
+ s = start_index - line.start_index
+ s = max(s, 0)
+ s = min(s, line.end_index - line.start_index)
+ s = len(text[:s].encode("utf8"))
+
+ e = end_index - line.start_index
+ e = min(e, line.end_index - line.start_index)
+ e = max(e, 0)
+ e = len(text[:e].encode("utf8"))
+
+ selection_all_attr_fg = pango.AttrForeground(
+ selection_fg.red, selection_fg.green, selection_fg.blue,
+ s, e)
+ selection_all_attr_bg= pango.AttrBackground(
+ selection_bg.red, selection_bg.green, selection_bg.blue,
+ s, e)
+ attrs.insert(selection_all_attr_fg)
+ attrs.insert(selection_all_attr_bg)
+
+ pango_layout.set_text(u_text)
+ pango_layout.set_attributes(attrs)
+ drawingarea.window.draw_layout(
+ gc, line.rectangle.x, line.rectangle.y + y_offset,
+ pango_layout)
+
+
+class ElementBoldText(ElementText):
+
+ def _get_attrs(self):
+ attrlist = pango.AttrList()
+ attr = pango.AttrWeight(pango.WEIGHT_BOLD,
+ end_index=0xffffff)
+ attrlist.insert(attr)
+ return attrlist
+
+
+class ElementLink(ElementText):
+
+ def __init__(self, text, href, pango_layout):
+ self.href = href
+ ElementText.__init__(self, text, pango_layout)
+
+ def _get_attrs(self):
+ attrlist = pango.AttrList()
+ attr = pango.AttrUnderline(pango.UNDERLINE_SINGLE,
+ end_index=0xffffff)
+ attrlist.insert(attr)
+ return attrlist
+
+
+class ResLayout:
+# represent one line
+
+ def __init__(self, left_margin, resnum, pango_layout):
+ self.element_list = [ElementEmpty()]
+ self.width = 0
+ self.height = 0
+ self.pango_layout = pango_layout
+ self.left_margin = left_margin
+ self.resnum = resnum
+ self.posY = 0
+ self.list_index = 0
+
+ def add_text(self, text, bold, href):
+ if isinstance(self.element_list[0], ElementEmpty):
+ self.element_list = []
+
+ if href:
+ element = ElementLink(text, href, self.pango_layout)
+ self.element_list.append(element)
+ elif bold:
+ element = ElementBoldText(text, self.pango_layout)
+ self.element_list.append(element)
+ else:
+ element = ElementText(text, self.pango_layout)
+ self.element_list.append(element)
+
+ def get_element_from_xy(self, x, y):
+ for element in self.element_list:
+ if element.is_on_xy(x, y):
+ return element
+ return None
+
+ def get_close_element_from_xy(self, x, y):
+ x= max(x, self.left_margin)
+ element = self.get_element_from_xy(x, y)
+ if element is None and len(self.element_list) != 0:
+ element = self.element_list[len(self.element_list) - 1]
+ return element
+
+ def set_width(self, width):
+
+ self.width = width
+
+ current_x = self.left_margin
+ current_y = 0
+
+ for element in self.element_list:
+ current_x, current_y = element.build_line_list(
+ current_x, current_y, width, self.left_margin)
+
+ self.height = current_y + Line.HEIGHT
+
+ def get_pixel_size(self):
+ return self.width, self.height
+
+ def get_text(self, selection_start, selection_end):
+ s_s = selection_start
+ e_s = selection_end
+ s_l, s_e, s_i = selection_start
+ e_l, e_e, e_i = selection_end
+
+ text = ""
+
+ if (s_l is None or s_e is None or s_i is None or
+ e_l is None or e_e is None or e_i is None or
+ self.posY < s_l.posY or self.posY > e_l.posY):
+
+ # nothing to do
+ pass
+
+ elif self.posY > s_s[0].posY and self.posY < e_s[0].posY:
+
+ for element in self.element_list:
+ text += element.get_text(selection=True)
+
+ elif self == s_s[0] and self == e_s[0]:
+
+ selection = False
+
+ for element in self.element_list:
+ if s_e == element:
+ selection = True
+ start = s_i
+ end = 0xffffff
+ if e_e == element:
+ end = e_i
+ selection = False
+ text += element.get_text(selection=True, start_index=start,
+ end_index=end)
+ elif e_e == element:
+ end = e_i
+ selection = False
+ text += element.get_text(
+ selection=True, end_index=end)
+ elif selection:
+ text += element.get_text(selection=True)
+
+ elif self == s_s[0]:
+
+ selection = False
+
+ for element in self.element_list:
+ if s_e == element:
+ selection = True
+ start = s_i
+ text += element.get_text(selection=True, start_index=start)
+ elif selection:
+ text += element.get_text(selection=True)
+
+ elif self == e_s[0]:
+
+ selection = True
+
+ for element in self.element_list:
+ if e_e == element:
+ end = e_i
+ text += element.get_text(selection=True, end_index=e_i)
+ selection = False
+ elif selection:
+ text += element.get_text(selection=True)
+
+ else:
+ # nothing to do
+ pass
+
+ return text
+
+
+ def draw(self, drawingarea, x_offset, y_offset,
+ start_selection, end_selection):
+
+ s_s = start_selection
+ e_s = end_selection
+
+ s_l, s_e, s_i = s_s
+ e_l, e_e, e_i = e_s
+
+ if (s_l is None or s_e is None or s_i is None or
+ e_l is None or e_e is None or e_i is None or
+ self.posY < s_l.posY or self.posY > e_l.posY):
+
+ for element in self.element_list:
+ element.draw(drawingarea, y_offset, self.pango_layout)
+
+ elif self.posY > s_s[0].posY and self.posY < e_s[0].posY:
+
+ for element in self.element_list:
+ element.draw(drawingarea, y_offset, self.pango_layout,
+ selection=True)
+
+ elif self == s_s[0] and self == e_s[0]:
+
+ selection = False
+
+ for element in self.element_list:
+ if s_e == element:
+ selection = True
+ start = s_i
+ end = 0xffffff
+ if e_e == element:
+ end = e_i
+ selection = False
+ element.draw(drawingarea, y_offset, self.pango_layout,
+ selection=True,
+ start_index=start,
+ end_index=end)
+ elif e_e == element:
+ end = e_i
+ selection = False
+ element.draw(drawingarea, y_offset, self.pango_layout,
+ selection=True, end_index=end)
+ else:
+ element.draw(drawingarea, y_offset, self.pango_layout,
+ selection=selection)
+
+ elif self == s_s[0]:
+
+ selection = False
+
+ for element in self.element_list:
+ if s_e == element:
+ selection = True
+ start = s_i
+ element.draw(drawingarea, y_offset, self.pango_layout,
+ selection=selection, start_index = start)
+ else:
+ element.draw(drawingarea, y_offset, self.pango_layout,
+ selection=selection)
+
+ elif self == e_s[0]:
+
+ selection = True
+
+ for element in self.element_list:
+ if e_e == element:
+ end = e_i
+ element.draw(drawingarea, y_offset, self.pango_layout,
+ selection=selection, end_index=e_i)
+ selection = False
+ else:
+ element.draw(drawingarea, y_offset, self.pango_layout,
+ selection=selection)
+
+ else:
+ for element in self.element_list:
+ element.draw(drawingarea, y_offset, self.pango_layout)
+
class ThreadView(gtk.HBox):
gtk.gdk.BUTTON_PRESS_MASK |
gtk.gdk.BUTTON_RELEASE_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)
+ "configure-event", self.on_drawingarea_configure_event)
self.drawingarea.connect(
"scroll-event", self.on_drawingarea_scroll_event)
self.drawingarea.connect(
"motion-notify-event", self.on_drawingrarea_motion_notify_event)
self.drawingarea.connect(
- "button-press-event", self.on_drawingrarea_button_press_event)
+ "button-press-event", self.on_drawingarea_button_press_event)
self.drawingarea.connect(
- "button-release-event", self.on_drawingrarea_button_release_event)
+ "button-release-event", self.on_drawingarea_button_release_event)
self.vscrollbar.connect(
"value-changed", self.on_vscrollbar_value_changed)
+ self.pango_layout = self.drawingarea.create_pango_layout("")
+
self.initialize_buffer()
self.on_uri_clicked = self._on_uri_clicked
self.menud_uri = None
+ # for selection
+ self.button_pressed_pt = (None, None, None)
+ self.button_moving_pt = (None, None, None)
+
def _on_uri_clicked(self, uri):
print uri, "clicked!!!!"
def initialize_buffer(self):
- self.pangolayout = []
+ self.res_layout_list = []
+ self.layout_posY_map = [(0, [])]
- def add_layout(self, pangolayout):
- if (len(self.pangolayout) != 0):
- last = self.pangolayout[len(self.pangolayout)-1]
+ def add_layout(self, res_layout):
+ if (len(self.res_layout_list) != 0):
+ last = self.res_layout_list[len(self.res_layout_list)-1]
x, y = last.get_pixel_size()
- pangolayout.posY = last.posY + y
- self.set_layout_width(pangolayout)
- self.pangolayout.append(pangolayout)
- x, y = pangolayout.get_pixel_size()
- self.adjustment.upper = pangolayout.posY + y
- self.prevent_adjustment_overflow()
+ res_layout.posY = last.posY + y
+ self.set_layout_width(res_layout)
+ res_layout.list_index = len(self.res_layout_list)
+ self.res_layout_list.append(res_layout)
+
+ if len(self.layout_posY_map[len(self.layout_posY_map)-1][1]) == 128:
+ self.layout_posY_map.append((res_layout.posY, []))
+ self.layout_posY_map[len(self.layout_posY_map)-1][1].append(res_layout)
+
+ x, y = res_layout.get_pixel_size()
+ self.adjustment.upper = res_layout.posY + y
self.redraw()
self.change_vscrollbar_visible()
- def create_pango_layout(self, text):
- return self.drawingarea.create_pango_layout(text)
+ def create_res_layout(self, left_margin, resnum):
+ return ResLayout(left_margin, resnum, self.pango_layout)
def set_layout_width(self, layout):
width = self.drawingarea.allocation.width
- layout.set_width((width - layout.marginleft) * pango.SCALE)
+ layout.set_width(width)
def redraw(self):
self.drawingarea.queue_draw()
def relayout(self):
+ self.layout_posY_map = [(0, [])]
+
width = self.drawingarea.allocation.width
sum_height = 0
- for layout in self.pangolayout:
- layout.set_width((width - layout.marginleft) * pango.SCALE)
+ for layout in self.res_layout_list:
+ layout.set_width(width)
layout.posY = sum_height
x, y = layout.get_pixel_size()
sum_height += y
- self.adjustment.upper = sum_height
- self.prevent_adjustment_overflow()
+
+ if len(self.layout_posY_map[len(self.layout_posY_map)-1][1])==128:
+ self.layout_posY_map.append((layout.posY, []))
+ self.layout_posY_map[len(self.layout_posY_map)-1][1].append(layout)
+
+ self.vscrollbar.set_range(0, sum_height)
self.change_vscrollbar_visible()
def change_vscrollbar_visible(self):
self.vscrollbar.show()
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)
+ self.vscrollbar.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)
+ self.vscrollbar.set_value(value)
def jump_to_res(self, resnum):
- for layout in self.pangolayout:
+ for layout in self.res_layout_list:
if layout.resnum == resnum:
self.jump_to_layout(layout)
return True
return False
- def draw_viewport(self):
- view_y = self.adjustment.get_value()
+
+ def _get_selection_start_end(self):
+ pressed_layout, pressed_element, pressed_index = self.button_pressed_pt
+ moving_layout, moving_element, moving_index = self.button_moving_pt
+
+ if (pressed_layout is None or pressed_element is None or
+ pressed_index is None or moving_layout is None or
+ moving_element is None or moving_index is None):
+ return (None, None, None), (None, None, None)
+
+ if pressed_layout == moving_layout:
+ if pressed_element == moving_element:
+ if moving_index < pressed_index:
+ return self.button_moving_pt, self.button_pressed_pt
+ else:
+ pressed_element_index = pressed_layout.element_list.index(
+ pressed_element)
+ moving_element_index = moving_layout.element_list.index(
+ moving_element)
+ if moving_element_index < pressed_element_index:
+ return self.button_moving_pt, self.button_pressed_pt
+ elif moving_layout.posY < pressed_layout.posY:
+ return self.button_moving_pt, self.button_pressed_pt
+
+ return self.button_pressed_pt, self.button_moving_pt
+
+ def draw_viewport(self, area):
+ view_y = self.vscrollbar.get_value()
self.drawingarea.window.draw_rectangle(
self.drawingarea.style.base_gc[0],
- True, 0, 0,
- self.drawingarea.allocation.width,
- self.drawingarea.allocation.height)
+ True, area.x, area.y, area.width, area.height)
+
+ selection_start, selection_end = self._get_selection_start_end()
+
- gc = self.drawingarea.window.new_gc()
- for layout in self.pangolayout:
+ top_layout = self.get_layout_on_y(view_y)
+ index = 0
+ if top_layout:
+ index = top_layout.list_index
+ while index < len(self.res_layout_list):
+ layout = self.res_layout_list[index]
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
+ area_top = view_y + area.y
+ area_bottom = view_y + area.y + area.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)
+ layout.draw(self.drawingarea,
+ 0, layout.posY - int(view_y),
+ selection_start, selection_end)
+ if layout_top > area_bottom:
+ break
+
+ index += 1
def transform_coordinate_gdk_to_adj(self, y):
- return y + self.adjustment.value
+ return y + self.vscrollbar.get_value()
def transform_coordinate_adj_to_layout(self, x, y, layout):
- return x - layout.marginleft, y - layout.posY
+ return x, y - layout.posY
def transform_coordinate_gdk_to_layout(self, x, y, layout):
return self.transform_coordinate_adj_to_layout(
x, self.transform_coordinate_gdk_to_adj(y), layout)
+ def get_layout_on_y(self, y):
+ layout_list = None
+ for pos, lay_lst in self.layout_posY_map:
+ if pos > y:
+ break
+ layout_list = lay_lst
+ if layout_list:
+ layout = None
+ for lay in layout_list:
+ if lay.posY > y:
+ break
+ layout = lay
+ return layout
+ return None
+
def ptrpos_to_layout(self, x, y):
# transform coordinate, GdkWindow -> adjustment
- adj_x = x
adj_y = self.transform_coordinate_gdk_to_adj(y)
- for lay in self.pangolayout:
- width, height = lay.get_pixel_size()
- if (adj_y >= lay.posY and adj_y < lay.posY + height and
- adj_x >= lay.marginleft):
- return lay
- return None
+ return self.get_layout_on_y(adj_y)
def ptrpos_to_uri(self, x, y):
# x, y is GdkWindow coordinate
if layout is None:
return None, None, None
- # transform coordinate, GdkWindow -> pangolayout
+ # transform coordinate, GdkWindow -> res_layout_list
lay_x, lay_y = self.transform_coordinate_gdk_to_layout(x, y, layout)
- # xy -> index
- idx, clk = layout.xy_to_index(
- int(lay_x)*pango.SCALE, int(lay_y)*pango.SCALE)
+ # xy -> element
+ element = layout.get_element_from_xy(lay_x, lay_y)
+ if isinstance(element, ElementLink):
+ return element.href, layout, element
- x, y, width, height = layout.index_to_pos(idx)
- x /= pango.SCALE
- y /= pango.SCALE
- width /= pango.SCALE
- height /= pango.SCALE
- if (lay_x >= x and lay_x < x + width and
- lay_y >= y and lay_y < y + height):
+ return None, layout, None
- for i, (start, end, href) in enumerate(layout.urilist):
- if idx >= start and idx < end:
- return href, layout, i
+ def get_selected_text(self):
+ selection_start, selection_end = self._get_selection_start_end()
+ s_l, s_e, s_i = selection_start
+ e_l, e_e, e_i = selection_end
- return None, layout, None
+ if (s_l is None or s_e is None or s_i is None or
+ e_l is None or e_e is None or e_i is None):
+ return ""
+
+ text = ""
+ index = s_l.list_index
+ end = e_l.list_index
+
+ while index <= end:
+ layout = self.res_layout_list[index]
+
+ text += layout.get_text(selection_start, selection_end)
+ if index != end:
+ text += "\n"
+
+ index += 1
+
+ return text
+
+ def _set_button_pressed_pt(self, pt):
+ self.button_pressed_pt = (None, None, None)
+ if pt == None:
+ return
+
+ x, y = pt
+ layout = self.ptrpos_to_layout(x, y)
+ if layout is None:
+ return
+
+ x, y = self.transform_coordinate_gdk_to_layout(x, y, layout)
+ element = layout.get_element_from_xy(x, y)
+ if element is None:
+ element = layout.get_close_element_from_xy(x, y)
+
+ if element is None:
+ return
+
+ index = element.xy_to_index(x, y)
+ if index is None:
+ return
+
+ self.button_pressed_pt = (layout, element, index)
+
+ def _set_button_moving_pt(self, pt):
+ self.button_moving_pt = (None, None, None)
+ if pt == None:
+ return
+
+ x, y = pt
+ layout = self.ptrpos_to_layout(x, y)
+ if layout is None:
+ return
+
+ x, y = self.transform_coordinate_gdk_to_layout(x, y, layout)
+ element = layout.get_element_from_xy(x, y)
+ if element is None:
+ element = layout.get_close_element_from_xy(x, y)
+
+ if element is None:
+ return
+
+ index = element.xy_to_index(x, y)
+ if index is None:
+ return
+
+ self.button_moving_pt = (layout, element, index)
def on_drawingarea_expose_event(self, widget, event, data=None):
- self.draw_viewport()
+ self.draw_viewport(event.area)
- 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_configure_event(self, widget, event, data=None):
+ if event.width != self.drawingarea_prev_width:
- self.prevent_adjustment_overflow()
- self.change_vscrollbar_visible()
+ # 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
- def prevent_adjustment_overflow(self):
- if (self.adjustment.value >
- self.adjustment.upper - self.adjustment.page_size):
- self.adjustment.value = (self.adjustment.upper -
- self.adjustment.page_size)
+ if top_layout is not None:
+ delta = top_layout.posY - self.vscrollbar.get_value()
- if self.adjustment.value < 0:
- self.adjustment.value = 0
+ self.relayout()
+ self.drawingarea_prev_width = event.width
- def on_drawingarea_button_press_event(self, widget, event, data=None):
- self.drawingarea.queue_draw()
+ # 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.adjustment.page_size = self.drawingarea.allocation.height
+ self.vscrollbar.set_increments(20, self.drawingarea.allocation.height)
+
+ # re-set 'value' for prevent overflow
+ self.vscrollbar.set_value(self.vscrollbar.get_value())
+ self.change_vscrollbar_visible()
def on_vscrollbar_value_changed(self, widget, data=None):
self.drawingarea.queue_draw()
if event.state & gtk.gdk.BUTTON1_MASK != gtk.gdk.BUTTON1_MASK:
self.button1_pressed = False
+ if self.button1_pressed and self.current_pressed_uri is None:
+ old_lay, old_elem, old_idx = self.button_moving_pt
+ self._set_button_moving_pt((event.x, event.y))
+ new_lay, new_elem, new_idx = self.button_moving_pt
+ if (old_lay != new_lay
+ or old_elem != new_elem
+ or old_idx != new_idx):
+ view_y = self.vscrollbar.get_value()
+ o_y = old_lay.posY
+ n_y = new_lay.posY
+ o_width, o_height = old_lay.get_pixel_size()
+ n_width, n_height = new_lay.get_pixel_size()
+
+ y = min(o_y, n_y)
+ height = max(o_y, n_y) - y
+ if o_y > n_y: height += o_height
+ else: height += n_height
+
+ y -= view_y
+
+ self.drawingarea.queue_draw_area(0, y, n_width, height+1)
+ #self.drawingarea.window.process_updates(False)
+
cursor = ThreadView.regular_cursor
- uri, layout, index = self.ptrpos_to_uri(event.x, event.y)
+ uri, layout, element = self.ptrpos_to_uri(event.x, event.y)
if layout is None:
cursor = ThreadView.arrow_cursor
else:
self.drawingarea.window.set_cursor(cursor)
- def on_drawingrarea_button_press_event(self, widget, event, data=None):
+ def on_drawingarea_button_press_event(self, widget, event, data=None):
if event.button == 1:
self.current_pressed_uri = None
self.button1_pressed = True
- uri, layout, index = self.ptrpos_to_uri(event.x, event.y)
- if uri is not None and layout is not None and index is not None:
- self.current_pressed_uri = (uri, layout, index)
+ uri, layout, element = self.ptrpos_to_uri(event.x, event.y)
+ if uri is not None and layout is not None and element is not None:
+ self.current_pressed_uri = (uri, layout, element)
+ else:
+ self._set_button_moving_pt((event.x, event.y))
+ self._set_button_pressed_pt((event.x, event.y))
+ self.drawingarea.queue_draw()
+
elif event.button == 3:
time = event.time
- uri, layout, index = self.ptrpos_to_uri(event.x, event.y)
- if uri is not None and layout is not None and index is not None:
+ uri, layout, element = self.ptrpos_to_uri(event.x, event.y)
+ if uri is not None and layout is not None and element is not None:
self.menu_openuri.show()
self.menu_copylinkaddress.show()
self.menu_separator_link.show()
self.menu_openuri.uri = None
self.menu_copylinkaddress.uri = None
- self.menu_copyselection.hide()
- self.menu_openasuri.hide()
- self.menu_separator_selection.hide()
+ text = self.get_selected_text()
+ if text and len(text) > 0:
+ self.menu_copyselection.show()
+ self.menu_openasuri.show()
+ self.menu_separator_selection.show()
+ else:
+ self.menu_copyselection.hide()
+ self.menu_openasuri.hide()
+ self.menu_separator_selection.hide()
self.popupmenu.popup(None, None, None, event.button, time)
return True
- def on_drawingrarea_button_release_event(self, widget, event, data=None):
+ def on_drawingarea_button_release_event(self, widget, event, data=None):
if event.button == 1:
button1_pressed = self.button1_pressed
self.button1_pressed = False
if button1_pressed and self.current_pressed_uri is not None:
- uri, layout, index = self.ptrpos_to_uri(event.x, event.y)
- p_uri, p_layout, p_index = self.current_pressed_uri
- self.current_preesed_uri = None
- if uri == p_uri and layout == p_layout and index == p_index:
+ uri, layout, element = self.ptrpos_to_uri(event.x, event.y)
+ p_uri, p_layout, p_element = self.current_pressed_uri
+ self.current_pressed_uri = None
+ if (uri == p_uri and layout == p_layout and
+ element == p_element):
self.on_uri_clicked(uri)