]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/tools/XRCed/tools.py
Yield causes premature redrawing of the test window
[wxWidgets.git] / wxPython / wx / tools / XRCed / tools.py
CommitLineData
d14a1e28
RD
1# Name: tools.py
2# Purpose: XRC editor, toolbar
3# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
4# Created: 19.03.2003
5# RCS-ID: $Id$
1fded56b 6
d14a1e28
RD
7from xxx import * # xxx imports globals and params
8from tree import ID_NEW
1fded56b 9
d14a1e28
RD
10# Icons
11import images
12
13# Groups of controls
14GROUPNUM = 4
15GROUP_WINDOWS, GROUP_MENUS, GROUP_SIZERS, GROUP_CONTROLS = range(GROUPNUM)
16
17# States depending on current selection and Control/Shift keys
c032d94e 18STATE_ROOT, STATE_MENUBAR, STATE_TOOLBAR, STATE_MENU, STATE_STDDLGBTN, STATE_ELSE = range(6)
d14a1e28 19# Left toolbar for GUI elements
29a41103 20class Tools(wx.Panel):
d14a1e28
RD
21 TOOL_SIZE = (30, 30)
22 def __init__(self, parent):
29a41103
RD
23 if wx.Platform == '__WXGTK__':
24 wx.Panel.__init__(self, parent, -1,
25 style=wx.RAISED_BORDER|wx.WANTS_CHARS)
d14a1e28 26 else:
29a41103 27 wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS)
d14a1e28 28 # Create sizer for groups
29a41103 29 self.sizer = wx.BoxSizer(wx.VERTICAL)
d14a1e28
RD
30 # Data to create buttons
31 pullDownMenu = g.pullDownMenu
32 self.groups = []
33 self.ctrl = self.shift = False
34 # Current state (what to enable/disable)
35 self.state = None
36 groups = [
37 ["Windows",
38 (ID_NEW.FRAME, images.getToolFrameBitmap()),
39 (ID_NEW.DIALOG, images.getToolDialogBitmap()),
40 (ID_NEW.PANEL, images.getToolPanelBitmap())],
41 ["Menus",
42 (ID_NEW.TOOL_BAR, images.getToolToolBarBitmap()),
43 (ID_NEW.MENU_BAR, images.getToolMenuBarBitmap()),
44 (ID_NEW.MENU, images.getToolMenuBitmap()),
45 (ID_NEW.TOOL, images.getToolToolBitmap()),
46 (ID_NEW.MENU_ITEM, images.getToolMenuItemBitmap()),
47 (ID_NEW.SEPARATOR, images.getToolSeparatorBitmap())],
48 ["Sizers",
49 (ID_NEW.BOX_SIZER, images.getToolBoxSizerBitmap()),
50 (ID_NEW.STATIC_BOX_SIZER, images.getToolStaticBoxSizerBitmap()),
51 (ID_NEW.GRID_SIZER, images.getToolGridSizerBitmap()),
52 (ID_NEW.FLEX_GRID_SIZER, images.getToolFlexGridSizerBitmap()),
a4c013b2 53 (ID_NEW.GRID_BAG_SIZER, images.getToolGridBagSizerBitmap()),
d14a1e28
RD
54 (ID_NEW.SPACER, images.getToolSpacerBitmap())],
55 ["Controls",
56 (ID_NEW.STATIC_TEXT, images.getToolStaticTextBitmap()),
57 (ID_NEW.STATIC_BITMAP, images.getToolStaticBitmapBitmap()),
58 (ID_NEW.STATIC_LINE, images.getToolStaticLineBitmap()),
59
60 (ID_NEW.BUTTON, images.getToolButtonBitmap()),
61 (ID_NEW.BITMAP_BUTTON, images.getToolBitmapButtonBitmap()),
62 (ID_NEW.STATIC_BOX, images.getToolStaticBoxBitmap()),
63
64 (ID_NEW.TEXT_CTRL, images.getToolTextCtrlBitmap()),
65 (ID_NEW.COMBO_BOX, images.getToolComboBoxBitmap()),
66 (ID_NEW.CHOICE, images.getToolChoiceBitmap()),
67
68 (ID_NEW.RADIO_BUTTON, images.getToolRadioButtonBitmap()),
69 (ID_NEW.CHECK_BOX, images.getToolCheckBoxBitmap()),
70 (ID_NEW.RADIO_BOX, images.getToolRadioBoxBitmap()),
71
72 (ID_NEW.SPIN_CTRL, images.getToolSpinCtrlBitmap()),
73 (ID_NEW.SPIN_BUTTON, images.getToolSpinButtonBitmap()),
74 (ID_NEW.SCROLL_BAR, images.getToolScrollBarBitmap()),
75
76 (ID_NEW.SLIDER, images.getToolSliderBitmap()),
77 (ID_NEW.GAUGE, images.getToolGaugeBitmap()),
78 (ID_NEW.TREE_CTRL, images.getToolTreeCtrlBitmap()),
79
80 (ID_NEW.LIST_BOX, images.getToolListBoxBitmap()),
81 (ID_NEW.CHECK_LIST, images.getToolCheckListBitmap()),
82 (ID_NEW.LIST_CTRL, images.getToolListCtrlBitmap()),
83
84 (ID_NEW.NOTEBOOK, images.getToolNotebookBitmap()),
68ae5821 85 (ID_NEW.SPLITTER_WINDOW, images.getToolSplitterWindowBitmap()),
d14a1e28
RD
86
87 (ID_NEW.UNKNOWN, images.getToolUnknownBitmap())]
88 ]
552240ce 89 self.boxes = {}
d14a1e28
RD
90 for grp in groups:
91 self.AddGroup(grp[0])
92 for b in grp[1:]:
93 self.AddButton(b[0], b[1], g.pullDownMenu.createMap[b[0]])
d14a1e28
RD
94 self.SetSizerAndFit(self.sizer)
95 # Allow to be resized in vertical direction only
96 self.SetSizeHints(self.GetSize()[0], -1)
97 # Events
29a41103 98 wx.EVT_COMMAND_RANGE(self, ID_NEW.PANEL, ID_NEW.LAST,
5c82ed90 99 wx.wxEVT_COMMAND_BUTTON_CLICKED, g.frame.OnCreate)
29a41103
RD
100 wx.EVT_KEY_DOWN(self, self.OnKeyDown)
101 wx.EVT_KEY_UP(self, self.OnKeyUp)
62602fbd
RR
102 # wxMSW does not generate click events for StaticBox
103 if wx.Platform == '__WXMSW__':
104 self.Bind(wx.EVT_LEFT_DOWN, self.OnClickBox)
d14a1e28 105
ed650677
RR
106 self.drag = None
107
d14a1e28 108 def AddButton(self, id, image, text):
29a41103
RD
109 from wx.lib import buttons
110 button = buttons.GenBitmapButton(self, id, image, size=self.TOOL_SIZE,
5c82ed90 111 style=wx.NO_BORDER|wx.WANTS_CHARS)
5e8b10e9 112 button.SetBezelWidth(0)
29a41103
RD
113 wx.EVT_KEY_DOWN(button, self.OnKeyDown)
114 wx.EVT_KEY_UP(button, self.OnKeyUp)
ed650677
RR
115 wx.EVT_LEFT_DOWN(button, self.OnLeftDownOnButton)
116 wx.EVT_MOTION(button, self.OnMotionOnButton)
d14a1e28
RD
117 button.SetToolTipString(text)
118 self.curSizer.Add(button)
119 self.groups[-1][1][id] = button
120
121 def AddGroup(self, name):
122 # Each group is inside box
552240ce
RR
123 id = wx.NewId()
124 box = wx.StaticBox(self, id, '[+] '+name, style=wx.WANTS_CHARS)
9e20825c
RR
125 box.SetForegroundColour(wx.Colour(64, 64, 64))
126# box.SetFont(g.smallerFont())
552240ce
RR
127 box.show = True
128 box.name = name
129 box.gnum = len(self.groups)
552240ce 130 box.Bind(wx.EVT_LEFT_DOWN, self.OnClickBox)
29a41103 131 boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
d14a1e28 132 boxSizer.Add((0, 4))
552240ce 133 self.boxes[id] = box
29a41103 134 self.curSizer = wx.GridSizer(0, 3)
d14a1e28 135 boxSizer.Add(self.curSizer)
552240ce 136 self.sizer.Add(boxSizer, 0, wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND, 4)
d14a1e28
RD
137 self.groups.append((box,{}))
138
139 # Enable/disable group
140 def EnableGroup(self, gnum, enable = True):
141 grp = self.groups[gnum]
9e20825c 142 #grp[0].Enable(enable)
d14a1e28
RD
143 for b in grp[1].values(): b.Enable(enable)
144
552240ce
RR
145 # Show/hide group
146 def ShowGroup(self, gnum, show = True):
147 grp = self.groups[gnum]
148 grp[0].show = show
149 for b in grp[1].values(): b.Show(show)
150
d14a1e28
RD
151 # Enable/disable group item
152 def EnableGroupItem(self, gnum, id, enable = True):
153 grp = self.groups[gnum]
154 grp[1][id].Enable(enable)
155
156 # Enable/disable group items
157 def EnableGroupItems(self, gnum, ids, enable = True):
158 grp = self.groups[gnum]
159 for id in ids:
160 grp[1][id].Enable(enable)
161
552240ce 162 def OnClickBox(self, evt):
9e20825c
RR
163 if wx.Platform == '__WXMSW__':
164 box = None
165 for id,b in self.boxes.items():
62602fbd 166 # How to detect a click on a label?
9e20825c
RR
167 if b.GetRect().Inside(evt.GetPosition()):
168 box = b
169 break
62602fbd
RR
170 if not box:
171 evt.Skip()
172 return
9e20825c
RR
173 else:
174 box = self.boxes[evt.GetId()]
552240ce
RR
175 # Collapse/restore static box, change label
176 self.ShowGroup(box.gnum, not box.show)
177 if box.show: box.SetLabel('[+] ' + box.name)
178 else: box.SetLabel('[-] ' + box.name)
179 self.Layout()
9e20825c
RR
180 self.Refresh()
181 #for b in self.boxes.items():
552240ce 182
ed650677
RR
183 # DaD
184 def OnLeftDownOnButton(self, evt):
185 self.posDown = evt.GetPosition()
186 self.idDown = evt.GetId()
187 self.btnDown = evt.GetEventObject()
188 evt.Skip()
189
190 def OnMotionOnButton(self, evt):
191 # Detect dragging
192 if evt.Dragging() and evt.LeftIsDown():
193 d = evt.GetPosition() - self.posDown
194 if max(abs(d[0]), abs(d[1])) >= 5:
195 if self.btnDown.HasCapture():
196 # Generate up event to release mouse
197 evt = wx.MouseEvent(wx.EVT_LEFT_UP.typeId)
198 evt.SetId(self.idDown)
199 # Set flag to prevent normal button operation this time
200 self.drag = True
201 self.btnDown.ProcessEvent(evt)
202 self.StartDrag()
203 evt.Skip()
204
205 def StartDrag(self):
5c82ed90 206 do = MyDataObject()
ed650677
RR
207 do.SetData(str(self.idDown))
208 bm = self.btnDown.GetBitmapLabel()
a7d8ec1e
RR
209 # wxGTK requires wxIcon cursor, wxWIN and wxMAC require wxCursor
210 if wx.Platform == '__WXGTK__':
5c82ed90
RR
211 icon = wx.EmptyIcon()
212 icon.CopyFromBitmap(bm)
213 dragSource = wx.DropSource(self, icon)
a7d8ec1e 214 else:
5c82ed90
RR
215 curs = wx.CursorFromImage(wx.ImageFromBitmap(bm))
216 dragSource = wx.DropSource(self, curs)
217 dragSource.SetData(do)
218 g.frame.SetStatusText('Release the mouse button over the test window')
219 dragSource.DoDragDrop()
220
d14a1e28
RD
221 # Process key events
222 def OnKeyDown(self, evt):
29a41103 223 if evt.GetKeyCode() == wx.WXK_CONTROL:
d14a1e28 224 g.tree.ctrl = True
29a41103 225 elif evt.GetKeyCode() == wx.WXK_SHIFT:
d14a1e28
RD
226 g.tree.shift = True
227 self.UpdateIfNeeded()
228 evt.Skip()
229
230 def OnKeyUp(self, evt):
29a41103 231 if evt.GetKeyCode() == wx.WXK_CONTROL:
d14a1e28 232 g.tree.ctrl = False
29a41103 233 elif evt.GetKeyCode() == wx.WXK_SHIFT:
d14a1e28
RD
234 g.tree.shift = False
235 self.UpdateIfNeeded()
236 evt.Skip()
237
238 def OnMouse(self, evt):
239 # Update control and shift states
240 g.tree.ctrl = evt.ControlDown()
241 g.tree.shift = evt.ShiftDown()
242 self.UpdateIfNeeded()
243 evt.Skip()
244
245 # Update UI after key presses, if necessary
246 def UpdateIfNeeded(self):
247 tree = g.tree
248 if self.ctrl != tree.ctrl or self.shift != tree.shift:
249 # Enabling is needed only for ctrl
250 if self.ctrl != tree.ctrl: self.UpdateUI()
251 self.ctrl = tree.ctrl
252 self.shift = tree.shift
253 if tree.ctrl:
254 status = 'SBL'
255 elif tree.shift:
256 status = 'INS'
257 else:
258 status = ''
259 g.frame.SetStatusText(status, 1)
260
261 # Update interface
262 def UpdateUI(self):
263 if not self.IsShown(): return
264 # Update status bar
265 pullDownMenu = g.pullDownMenu
266 tree = g.tree
267 item = tree.selection
268 # If nothing selected, disable everything and return
269 if not item:
270 # Disable everything
271 for grp in range(GROUPNUM):
272 self.EnableGroup(grp, False)
273 self.state = None
274 return
275 if tree.ctrl: needInsert = True
276 else: needInsert = tree.NeedInsert(item)
277 # Enable depending on selection
278 if item == tree.root or needInsert and tree.GetItemParent(item) == tree.root:
279 state = STATE_ROOT
280 else:
281 xxx = tree.GetPyData(item).treeObject()
282 # Check parent for possible child nodes if inserting sibling
283 if needInsert: xxx = xxx.parent
284 if xxx.__class__ == xxxMenuBar:
285 state = STATE_MENUBAR
286 elif xxx.__class__ in [xxxToolBar, xxxTool] or \
287 xxx.__class__ == xxxSeparator and xxx.parent.__class__ == xxxToolBar:
288 state = STATE_TOOLBAR
289 elif xxx.__class__ in [xxxMenu, xxxMenuItem]:
290 state = STATE_MENU
c032d94e
RR
291 elif xxx.__class__ == xxxStdDialogButtonSizer:
292 state = STATE_STDDLGBTN
d14a1e28
RD
293 else:
294 state = STATE_ELSE
295
296 # Enable depending on selection
297 if state != self.state:
298 # Disable everything
299 for grp in range(GROUPNUM):
300 self.EnableGroup(grp, False)
301 # Enable some
302 if state == STATE_ROOT:
303 self.EnableGroup(GROUP_WINDOWS, True)
304 self.EnableGroup(GROUP_MENUS, True)
305 # But disable items
306 self.EnableGroupItems(GROUP_MENUS,
307 [ ID_NEW.TOOL,
308 ID_NEW.MENU_ITEM,
309 ID_NEW.SEPARATOR ],
310 False)
306b6fe9 311 elif state == STATE_STDDLGBTN:
c032d94e 312 pass # nothing can be added from toolbar
d14a1e28
RD
313 elif state == STATE_MENUBAR:
314 self.EnableGroup(GROUP_MENUS)
315 self.EnableGroupItems(GROUP_MENUS,
316 [ ID_NEW.TOOL_BAR,
317 ID_NEW.MENU_BAR,
318 ID_NEW.TOOL ],
319 False)
320 elif state == STATE_TOOLBAR:
321 self.EnableGroup(GROUP_MENUS)
322 self.EnableGroupItems(GROUP_MENUS,
323 [ ID_NEW.TOOL_BAR,
324 ID_NEW.MENU,
325 ID_NEW.MENU_BAR,
326 ID_NEW.MENU_ITEM ],
327 False)
328 self.EnableGroup(GROUP_CONTROLS)
329 self.EnableGroupItems(GROUP_CONTROLS,
330 [ ID_NEW.TREE_CTRL,
68ae5821
RD
331 ID_NEW.NOTEBOOK,
332 ID_NEW.SPLITTER_WINDOW ],
d14a1e28
RD
333 False)
334 elif state == STATE_MENU:
335 self.EnableGroup(GROUP_MENUS)
336 self.EnableGroupItems(GROUP_MENUS,
337 [ ID_NEW.TOOL_BAR,
338 ID_NEW.MENU_BAR,
339 ID_NEW.TOOL ],
340 False)
341 else:
342 self.EnableGroup(GROUP_WINDOWS)
343 self.EnableGroupItems(GROUP_WINDOWS,
344 [ ID_NEW.FRAME,
345 ID_NEW.DIALOG ],
346 False)
347 self.EnableGroup(GROUP_MENUS)
348 self.EnableGroupItems(GROUP_MENUS,
349 [ ID_NEW.MENU_BAR,
350 ID_NEW.MENU_BAR,
351 ID_NEW.MENU,
352 ID_NEW.MENU_ITEM,
353 ID_NEW.TOOL,
354 ID_NEW.SEPARATOR ],
355 False)
356 self.EnableGroup(GROUP_SIZERS)
357 self.EnableGroup(GROUP_CONTROLS)
306b6fe9 358 # Special case for *book (always executed)
d14a1e28 359 if state == STATE_ELSE:
306b6fe9 360 if xxx.__class__ in [xxxNotebook, xxxChoicebook, xxxListbook]:
d14a1e28
RD
361 self.EnableGroup(GROUP_SIZERS, False)
362 else:
363 self.EnableGroup(GROUP_SIZERS)
364 if not (xxx.isSizer or xxx.parent and xxx.parent.isSizer):
365 self.EnableGroupItem(GROUP_SIZERS, ID_NEW.SPACER, False)
f65bb0f8
RD
366 if xxx.__class__ == xxxFrame:
367 self.EnableGroupItem(GROUP_MENUS, ID_NEW.MENU_BAR)
d14a1e28
RD
368 # Save state
369 self.state = state