root/gaphor/tags/gaphor-0.12.5/gaphor/ui/groupingtools.py

Revision 1679, 6.2 kB (checked in by arj..@yirdis.nl, 1 year ago)

Changed matrix conversion methods to new names.

Line 
1 from zope import component
2
3 import gtk
4
5 from gaphor.diagram.interfaces import IGroup
6 from gaphor.ui.diagramtools import PlacementTool
7 from gaphas.tool import ItemTool
8
9 # cursor to indicate grouping
10 IN_CURSOR = gtk.gdk.Cursor(gtk.gdk.DIAMOND_CROSS)
11
12 # cursor to indicate ungrouping
13 OUT_CURSOR = gtk.gdk.Cursor(gtk.gdk.SIZING)
14
15 class GroupPlacementTool(PlacementTool):
16     """
17     Try to group items when placing them on diagram.
18     """
19
20     def __init__(self, item_factory, after_handler=None, handle_index=-1):
21         super(GroupPlacementTool, self).__init__(item_factory,
22                 after_handler,
23                 handle_index)
24
25         self._parent = None
26
27
28     def on_button_press(self, context, event):
29         """
30         If new item was placed onto diagram, then try to group it with
31         parent using grouping adapter.
32         """
33
34         # first get parent
35         self._parent = None
36         if event.button == 1:
37             context.ungrab()
38             view = context.view
39             self._parent = view.get_item_at_point(event.x, event.y)
40
41         # now, place the new item
42         placed = PlacementTool.on_button_press(self, context, event)
43
44         # if there is a parent, then try to group item and parent
45         if placed and self._parent:
46             view = context.view
47             item = view.focused_item
48            
49             adapter = component.queryMultiAdapter((self._parent, item), IGroup)
50             if adapter and adapter.can_contain():
51                 adapter.group()
52
53         return placed
54
55
56     def on_motion_notify(self, context, event):
57         """
58         Change parent item to dropzone state if it can accept diagram item
59         object to be created.
60         """
61         view = context.view
62
63         if view.focused_item:
64             view.unselect_item(view.focused_item)
65             view.focused_item = None
66
67         try:
68             parent = view.get_item_at_point(event.x, event.y)
69         except KeyError:
70             # No bounding box yet.
71             return
72
73         if parent:
74             adapter = component.queryMultiAdapter((parent, self._factory.item_class), IGroup)
75             if adapter and adapter.pre_can_contain():
76                 view.dropzone_item = parent
77                 view.window.set_cursor(IN_CURSOR)
78             else:
79                 view.dropzone_item = None
80                 view.window.set_cursor(None)
81         else:
82             view.dropzone_item = None
83             view.window.set_cursor(None)
84
85
86     def _create_item(self, context, x, y):
87         """
88         Create diagram item and place it within parent's boundaries.
89         """
90         # if no parent, then create with parent placement tool
91         if not self._parent:
92             return super(GroupPlacementTool, self)._create_item(context, x, y)
93
94         item = self._factory(self._parent)
95        
96         view = context.view
97         # get item position through parent world
98         x, y = view.canvas.get_matrix_c2i(self._parent).transform_point(x, y)
99         item.matrix.translate(x, y)
100
101         view.dropzone_item = None
102         view.window.set_cursor(None)
103
104         return item
105
106
107 class GroupItemTool(ItemTool):
108     """
109     Group diagram item by dropping it on another item.
110
111     Works only for one selected item, now.
112     """
113
114     def on_motion_notify(self, context, event):
115         """
116         Indicate possibility of grouping/ungrouping of selected item.
117         """
118         super(GroupItemTool, self).on_motion_notify(context, event)
119         view = context.view
120
121         if event.state & gtk.gdk.BUTTON_PRESS_MASK and len(view.selected_items) == 1:
122             item = list(view.selected_items)[0]
123             parent = view.canvas.get_parent(item)
124
125             over = view.get_item_at_point(event.x, event.y, selected=False)
126             assert over is not item
127
128             if over is parent: # do nothing when item is over parent
129                 view.dropzone_item = None
130                 view.window.set_cursor(None)
131                 return
132
133             if parent and not over:  # are we going to remove from parent?
134                 adapter = component.queryMultiAdapter((parent, item.__class__), IGroup)
135                 if adapter and adapter.pre_can_contain():
136                     view.window.set_cursor(OUT_CURSOR)
137                     view.dropzone_item = parent
138
139             if over:       # are we going to add to parent?
140                 adapter = component.queryMultiAdapter((over, item.__class__), IGroup)
141                 if adapter and adapter.pre_can_contain():
142                     view.dropzone_item = over
143                     view.window.set_cursor(IN_CURSOR)
144
145
146     def on_button_release(self, context, event):
147         """
148         Group item if it is dropped on parent's item. Ungroup item if it is
149         moved out of its parent boundaries. Method also moves item from old
150         parent to new one (regrouping).
151         """
152         super(GroupItemTool, self).on_button_release(context, event)
153         view = context.view
154         if event.button == 1 and len(view.selected_items) == 1:
155             item = list(view.selected_items)[0]
156             parent = view.canvas.get_parent(item)
157             over = view.get_item_at_point(event.x, event.y, selected=False)
158             assert over is not item
159
160             if over is parent:
161                 return
162
163             if parent: # remove from parent
164                 adapter = component.queryMultiAdapter((parent, item), IGroup)
165                 if adapter and adapter.can_contain():
166                     adapter.ungroup()
167
168                     canvas = view.canvas
169                     canvas.reparent(item, None)
170
171                     # reset item's position
172                     px, py = canvas.get_matrix_c2i(parent).transform_point(0, 0)
173                     item.matrix.translate(-px, -py)
174
175
176             if over: # add to over (over becomes parent)
177                 adapter = component.queryMultiAdapter((over, item), IGroup)
178                 if adapter and adapter.can_contain():
179                     adapter.group()
180
181                     canvas = view.canvas
182                     canvas.reparent(item, over)
183
184                     # reset item's position
185                     x, y = canvas.get_matrix_i2c(over).transform_point(0, 0)
186                     item.matrix.translate(-x, -y)
187
188
189         view.dropzone_item = None
190         view.window.set_cursor(None)
191
192
193 # vim:sw=4:et:ai
Note: See TracBrowser for help on using the browser.