Only redraw needed nodes
[pysize.git] / pysize / ui / gtk / pysize_widget_mouse.py
blob16ab14eb5a4979871e95c1c86404eae93232967c
1 # This program is free software; you can redistribute it and/or modify
2 # it under the terms of the GNU General Public License as published by
3 # the Free Software Foundation; either version 2 of the License, or
4 # (at your option) any later version.
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # GNU Library General Public License for more details.
11 # You should have received a copy of the GNU General Public License
12 # along with this program; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 # See the COPYING file for license information.
17 # Copyright (c) 2006 Guillaume Chazarain <guichaz@yahoo.fr>
19 import pygtk
20 pygtk.require('2.0')
21 import gtk
22 assert gtk.pygtk_version >= (2, 8)
24 class _point(object):
25 def __init__(self, x, y):
26 self.x = x
27 self.y = y
29 def _event_point(event):
30 if event.is_hint:
31 x, y, state = event.window.get_pointer()
32 point = _point(x, y)
33 else:
34 point = _point(event.x, event.y)
35 return point
37 class PysizeWidget_Mouse(object):
38 def __init__(self, options, args):
39 self.connect('motion-notify-event', type(self)._motion_notify_event)
40 self.connect('button-press-event', type(self)._button_press_event)
41 self.connect('button-release-event', type(self)._button_release_event)
42 self.connect('building-tree-state-changed', type(self)._reset_mouse)
43 self.cursor_node = None
44 self.button_press_node = None
45 self.set_cursor_node(None)
47 def set_cursor_node(self, cursor_node):
48 self.cursor_node = cursor_node
49 self.emit('hover-changed', cursor_node)
51 def _reset_mouse(self, unused_tree):
52 self.set_cursor_node(None)
53 self.button_press_node = None
55 def _get_node_here(self, event):
56 point = _point(event.x, event.y)
57 for node in self.tree.root:
58 if node.contains_point(point):
59 return node
61 def _motion_notify_event(self, event):
62 point = _event_point(event)
63 prev_selection = new_selection = self.cursor_node
64 if not (self.cursor_node and self.cursor_node.contains_point(point)):
65 # The cursor is no more in the same node
66 mask = 0x00
67 for node in self.tree.root:
68 if node.contains_point(point) != (node == prev_selection):
69 if node == prev_selection:
70 new_selection = None
71 mask |= 0x1
72 else:
73 new_selection = node
74 mask |= 0x2
75 if mask == 0x3:
76 break
77 if prev_selection != new_selection:
78 self.set_cursor_node(new_selection)
79 self.queue_node_redraw(prev_selection)
80 self.queue_node_redraw(new_selection)
81 return True
83 def _handle_double_click(self, node):
84 if node:
85 self.set_paths(node.get_fullpaths())
86 return node is not None
88 def _button_press_event(self, event):
89 if event.button == 1:
90 node = self._get_node_here(event)
91 if event.type == gtk.gdk._2BUTTON_PRESS:
92 return self._handle_double_click(node)
93 if node != self.button_press_node:
94 self.queue_node_redraw(self.button_press_node)
95 self.queue_node_redraw(node)
96 self.button_press_node = node
97 return True
98 return False
100 def _button_release_event(self, event):
101 if event.button == 1:
102 node = self._get_node_here(event)
103 if node == self.button_press_node:
104 if event.state & gtk.gdk.CONTROL_MASK:
105 if node:
106 node_fullpaths = set(node.get_fullpaths())
107 if node_fullpaths <= self.selected_paths:
108 self.selected_paths -= node_fullpaths
109 else:
110 self.selected_paths |= node_fullpaths
111 else:
112 for n in self.get_selected_nodes():
113 self.queue_node_redraw(n)
114 if node:
115 self.selected_paths = set(node.get_fullpaths())
116 else:
117 self.selected_paths = set()
118 self.queue_node_redraw(node)
119 else:
120 self.queue_node_redraw(self.button_press_node)
121 self.button_press_node = None
122 return True
124 def get_selected_nodes(self):
125 if self.cursor_node:
126 cursor_fullpaths = set(self.cursor_node.get_fullpaths())
127 else:
128 cursor_fullpaths = set()
129 sel = self.selected_paths | cursor_fullpaths
130 nodes = [n for n in self.tree.root if set(n.get_fullpaths()) <= sel]
131 return nodes