]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/tools/XRCed/tree.py
ec093e40553e7e86eafa87243fca43a3e17c462d
[wxWidgets.git] / wxPython / wx / tools / XRCed / tree.py
1 # Name: tree.py
2 # Purpose: XRC editor, XML_tree class
3 # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
4 # Created: 02.12.2002
5 # RCS-ID: $Id$
6
7 from xxx import * # xxx imports globals and params
8 import types
9 import traceback
10
11 # Constant to define standart window name
12 STD_NAME = '_XRCED_T_W'
13
14 # Icons
15 import images
16
17 class MemoryFile:
18 def __init__(self, name):
19 self.name = name
20 self.buffer = ''
21 def write(self, data):
22 if g.currentEncoding:
23 encoding = g.currentEncoding
24 else:
25 encoding = wx.GetDefaultPyEncoding()
26 try:
27 self.buffer += data.encode(encoding)
28 except UnicodeEncodeError:
29 self.buffer += data.encode(encoding, 'xmlcharrefreplace')
30
31 def close(self):
32 wx.MemoryFSHandler.AddFile(self.name, self.buffer)
33
34 ################################################################################
35
36 # Redefine writing to include encoding
37 class MyDocument(minidom.Document):
38 def __init__(self):
39 minidom.Document.__init__(self)
40 self.encoding = ''
41 def writexml(self, writer, indent="", addindent="", newl="", encoding=""):
42 if encoding: encdstr = 'encoding="%s"' % encoding
43 else: encdstr = ''
44 writer.write('<?xml version="1.0" %s?>\n' % encdstr)
45 for node in self.childNodes:
46 node.writexml(writer, indent, addindent, newl)
47
48 ################################################################################
49
50 # Ids for menu commands
51 class ID_NEW:
52 PANEL = wx.NewId()
53 DIALOG = wx.NewId()
54 FRAME = wx.NewId()
55 TOOL_BAR = wx.NewId()
56 TOOL = wx.NewId()
57 MENU_BAR = wx.NewId()
58 MENU = wx.NewId()
59 STATUS_BAR = wx.NewId()
60
61 STATIC_TEXT = wx.NewId()
62 TEXT_CTRL = wx.NewId()
63
64 BUTTON = wx.NewId()
65 BITMAP_BUTTON = wx.NewId()
66 RADIO_BUTTON = wx.NewId()
67 SPIN_BUTTON = wx.NewId()
68 TOGGLE_BUTTON = wx.NewId()
69
70 STATIC_BOX = wx.NewId()
71 CHECK_BOX = wx.NewId()
72 RADIO_BOX = wx.NewId()
73 COMBO_BOX = wx.NewId()
74 LIST_BOX = wx.NewId()
75
76 STATIC_LINE = wx.NewId()
77 STATIC_BITMAP = wx.NewId()
78 CHOICE = wx.NewId()
79 SLIDER = wx.NewId()
80 GAUGE = wx.NewId()
81 SCROLL_BAR = wx.NewId()
82 TREE_CTRL = wx.NewId()
83 LIST_CTRL = wx.NewId()
84 CHECK_LIST = wx.NewId()
85 NOTEBOOK = wx.NewId()
86 CHOICEBOOK = wx.NewId()
87 LISTBOOK = wx.NewId()
88 SPLITTER_WINDOW = wx.NewId()
89 GRID = wx.NewId()
90 SCROLLED_WINDOW = wx.NewId()
91 HTML_WINDOW = wx.NewId()
92 CALENDAR_CTRL = wx.NewId()
93 DATE_CTRL = wx.NewId()
94 FILE_PICKER_CTRL = wx.NewId()
95 GENERIC_DIR_CTRL = wx.NewId()
96 SPIN_CTRL = wx.NewId()
97 UNKNOWN = wx.NewId()
98 WIZARD = wx.NewId()
99 WIZARD_PAGE = wx.NewId()
100 WIZARD_PAGE_SIMPLE = wx.NewId()
101 BITMAP = wx.NewId()
102 ICON = wx.NewId()
103 STATUS_BAR = wx.NewId()
104
105 BOX_SIZER = wx.NewId()
106 STATIC_BOX_SIZER = wx.NewId()
107 GRID_SIZER = wx.NewId()
108 FLEX_GRID_SIZER = wx.NewId()
109 GRID_BAG_SIZER = wx.NewId()
110 STD_DIALOG_BUTTON_SIZER = wx.NewId()
111 SPACER = wx.NewId()
112
113 TOOL_BAR = wx.NewId()
114 TOOL = wx.NewId()
115 MENU = wx.NewId()
116 MENU_ITEM = wx.NewId()
117 SEPARATOR = wx.NewId()
118
119 OK_BUTTON = wx.NewId()
120 YES_BUTTON = wx.NewId()
121 SAVE_BUTTON = wx.NewId()
122 APPLY_BUTTON = wx.NewId()
123 NO_BUTTON = wx.NewId()
124 CANCEL_BUTTON = wx.NewId()
125 HELP_BUTTON = wx.NewId()
126 CONTEXT_HELP_BUTTON = wx.NewId()
127
128 REF = wx.NewId()
129 COMMENT = wx.NewId()
130
131 LAST = wx.NewId()
132
133
134
135 class PullDownMenu:
136 ID_EXPAND = wx.NewId()
137 ID_COLLAPSE = wx.NewId()
138 ID_PASTE_SIBLING = wx.NewId()
139 ID_TOOL_PASTE = wx.NewId()
140 ID_SUBCLASS = wx.NewId()
141
142 def __init__(self, parent):
143 self.ID_DELETE = parent.ID_DELETE
144 wx.EVT_MENU_RANGE(parent, ID_NEW.PANEL, ID_NEW.LAST, parent.OnCreate)
145 wx.EVT_MENU_RANGE(parent, 1000 + ID_NEW.PANEL, 1000 + ID_NEW.LAST, parent.OnReplace)
146 wx.EVT_MENU(parent, self.ID_COLLAPSE, parent.OnCollapse)
147 wx.EVT_MENU(parent, self.ID_EXPAND, parent.OnExpand)
148 wx.EVT_MENU(parent, self.ID_PASTE_SIBLING, parent.OnPaste)
149 wx.EVT_MENU(parent, self.ID_SUBCLASS, parent.OnSubclass)
150 # We connect to tree, but process in frame
151 wx.EVT_MENU_HIGHLIGHT_ALL(g.tree, parent.OnPullDownHighlight)
152
153 # Mapping from IDs to element names
154 self.createMap = {
155 ID_NEW.PANEL: 'wxPanel',
156 ID_NEW.DIALOG: 'wxDialog',
157 ID_NEW.FRAME: 'wxFrame',
158 ID_NEW.WIZARD: 'wxWizard',
159 ID_NEW.WIZARD_PAGE: 'wxWizardPage',
160 ID_NEW.WIZARD_PAGE_SIMPLE: 'wxWizardPageSimple',
161 ID_NEW.TOOL_BAR: 'wxToolBar',
162 ID_NEW.TOOL: 'tool',
163 ID_NEW.STATUS_BAR: 'wxStatusBar',
164 ID_NEW.MENU_BAR: 'wxMenuBar',
165 ID_NEW.MENU: 'wxMenu',
166 ID_NEW.MENU_ITEM: 'wxMenuItem',
167 ID_NEW.BITMAP: 'wxBitmap',
168 ID_NEW.ICON: 'wxIcon',
169 ID_NEW.SEPARATOR: 'separator',
170
171 ID_NEW.STATIC_TEXT: 'wxStaticText',
172 ID_NEW.TEXT_CTRL: 'wxTextCtrl',
173
174 ID_NEW.BUTTON: 'wxButton',
175 ID_NEW.BITMAP_BUTTON: 'wxBitmapButton',
176 ID_NEW.RADIO_BUTTON: 'wxRadioButton',
177 ID_NEW.SPIN_BUTTON: 'wxSpinButton',
178 ID_NEW.TOGGLE_BUTTON: 'wxToggleButton',
179
180 ID_NEW.STATIC_BOX: 'wxStaticBox',
181 ID_NEW.CHECK_BOX: 'wxCheckBox',
182 ID_NEW.RADIO_BOX: 'wxRadioBox',
183 ID_NEW.COMBO_BOX: 'wxComboBox',
184 ID_NEW.LIST_BOX: 'wxListBox',
185 ID_NEW.CHECK_LIST: 'wxCheckListBox',
186
187 ID_NEW.STATIC_LINE: 'wxStaticLine',
188 ID_NEW.STATIC_BITMAP: 'wxStaticBitmap',
189 ID_NEW.CHOICE: 'wxChoice',
190 ID_NEW.SLIDER: 'wxSlider',
191 ID_NEW.GAUGE: 'wxGauge',
192 ID_NEW.SCROLL_BAR: 'wxScrollBar',
193 ID_NEW.TREE_CTRL: 'wxTreeCtrl',
194 ID_NEW.LIST_CTRL: 'wxListCtrl',
195 ID_NEW.NOTEBOOK: 'wxNotebook',
196 ID_NEW.CHOICEBOOK: 'wxChoicebook',
197 ID_NEW.LISTBOOK: 'wxListbook',
198 ID_NEW.SPLITTER_WINDOW: 'wxSplitterWindow',
199 ID_NEW.GRID: 'wxGrid',
200 ID_NEW.SCROLLED_WINDOW: 'wxScrolledWindow',
201 ID_NEW.HTML_WINDOW: 'wxHtmlWindow',
202 ID_NEW.CALENDAR_CTRL: 'wxCalendarCtrl',
203 ID_NEW.DATE_CTRL: 'wxDatePickerCtrl',
204 ID_NEW.FILE_PICKER_CTRL: 'wxFilePickerCtrl',
205 ID_NEW.GENERIC_DIR_CTRL: 'wxGenericDirCtrl',
206 ID_NEW.SPIN_CTRL: 'wxSpinCtrl',
207
208 ID_NEW.BOX_SIZER: 'wxBoxSizer',
209 ID_NEW.STATIC_BOX_SIZER: 'wxStaticBoxSizer',
210 ID_NEW.GRID_SIZER: 'wxGridSizer',
211 ID_NEW.FLEX_GRID_SIZER: 'wxFlexGridSizer',
212 ID_NEW.GRID_BAG_SIZER: 'wxGridBagSizer',
213 ID_NEW.STD_DIALOG_BUTTON_SIZER: 'wxStdDialogButtonSizer',
214 ID_NEW.SPACER: 'spacer',
215 ID_NEW.UNKNOWN: 'unknown',
216
217 ID_NEW.OK_BUTTON: 'wxButton',
218 ID_NEW.YES_BUTTON: 'wxButton',
219 ID_NEW.SAVE_BUTTON: 'wxButton',
220 ID_NEW.APPLY_BUTTON: 'wxButton',
221 ID_NEW.NO_BUTTON: 'wxButton',
222 ID_NEW.CANCEL_BUTTON: 'wxButton',
223 ID_NEW.HELP_BUTTON: 'wxButton',
224 ID_NEW.CONTEXT_HELP_BUTTON: 'wxButton',
225 }
226 self.topLevel = [
227 (ID_NEW.PANEL, 'Panel', 'Create panel'),
228 (ID_NEW.DIALOG, 'Dialog', 'Create dialog'),
229 (ID_NEW.FRAME, 'Frame', 'Create frame'),
230 (ID_NEW.WIZARD, 'Wizard', 'Create wizard'),
231 None,
232 (ID_NEW.TOOL_BAR, 'ToolBar', 'Create toolbar'),
233 (ID_NEW.MENU_BAR, 'MenuBar', 'Create menubar'),
234 (ID_NEW.MENU, 'Menu', 'Create menu'),
235 None,
236 (ID_NEW.BITMAP, 'Bitmap', 'Create bitmap'),
237 (ID_NEW.ICON, 'Icon', 'Create icon'),
238 ]
239 self.containers = [
240 (ID_NEW.PANEL, 'Panel', 'Create panel'),
241 (ID_NEW.NOTEBOOK, 'Notebook', 'Create notebook control'),
242 (ID_NEW.CHOICEBOOK, 'Choicebook', 'Create choicebook control'),
243 (ID_NEW.LISTBOOK, 'Listbook', 'Create listbook control'),
244 (ID_NEW.SPLITTER_WINDOW, 'SplitterWindow', 'Create splitter window'),
245 (ID_NEW.TOOL_BAR, 'ToolBar', 'Create toolbar'),
246 (ID_NEW.STATUS_BAR, 'StatusBar', 'Create status bar'),
247 # (ID_NEW.WIZARD_PAGE, 'WizardPage', 'Create wizard page'),
248 (ID_NEW.WIZARD_PAGE_SIMPLE, 'WizardPageSimple', 'Create simple wizard page'),
249 ]
250 self.sizers = [
251 (ID_NEW.BOX_SIZER, 'BoxSizer', 'Create box sizer'),
252 (ID_NEW.STATIC_BOX_SIZER, 'StaticBoxSizer',
253 'Create static box sizer'),
254 (ID_NEW.GRID_SIZER, 'GridSizer', 'Create grid sizer'),
255 (ID_NEW.FLEX_GRID_SIZER, 'FlexGridSizer',
256 'Create flexgrid sizer'),
257 (ID_NEW.GRID_BAG_SIZER, 'GridBagSizer',
258 'Create gridbag sizer'),
259 # (ID_NEW.STD_DIALOG_BUTTON_SIZER, 'StdDialogButtonSizer',
260 # 'Create standard button sizer'),
261 (ID_NEW.SPACER, 'Spacer', 'Create spacer'),
262 ]
263 self.controls = [
264 ['control', 'Various controls',
265 (ID_NEW.STATIC_TEXT, 'Label', 'Create label'),
266 (ID_NEW.STATIC_BITMAP, 'Bitmap', 'Create bitmap'),
267 (ID_NEW.STATIC_LINE, 'Line', 'Create line'),
268 (ID_NEW.TEXT_CTRL, 'TextBox', 'Create text box'),
269 (ID_NEW.CHOICE, 'Choice', 'Create choice'),
270 (ID_NEW.SLIDER, 'Slider', 'Create slider'),
271 (ID_NEW.GAUGE, 'Gauge', 'Create gauge'),
272 (ID_NEW.SPIN_CTRL, 'SpinCtrl', 'Create spin'),
273 (ID_NEW.SCROLL_BAR, 'ScrollBar', 'Create scroll bar'),
274 (ID_NEW.TREE_CTRL, 'TreeCtrl', 'Create tree'),
275 (ID_NEW.LIST_CTRL, 'ListCtrl', 'Create list'),
276 # (ID_NEW.GRID, 'Grid', 'Create grid'),
277 (ID_NEW.SCROLLED_WINDOW, 'ScrolledWindow', 'Create scrolled window'),
278 (ID_NEW.HTML_WINDOW, 'HtmlWindow', 'Create HTML window'),
279 (ID_NEW.CALENDAR_CTRL, 'CalendarCtrl', 'Create calendar control'),
280 (ID_NEW.DATE_CTRL, 'DatePickerCtrl', 'Create date picker control'),
281 # (ID_NEW.FILE_PICKER_CTRL, 'FilePickerCtrl', 'Create file picker control'),
282 (ID_NEW.GENERIC_DIR_CTRL, 'GenericDirCtrl', 'Create generic dir control'),
283 (ID_NEW.UNKNOWN, 'Unknown', 'Create custom control placeholder'),
284 ],
285 ['button', 'Buttons',
286 (ID_NEW.BUTTON, 'Button', 'Create button'),
287 (ID_NEW.BITMAP_BUTTON, 'BitmapButton', 'Create bitmap button'),
288 (ID_NEW.RADIO_BUTTON, 'RadioButton', 'Create radio button'),
289 (ID_NEW.SPIN_BUTTON, 'SpinButton', 'Create spin button'),
290 (ID_NEW.TOGGLE_BUTTON, 'ToggleButton', 'Create toggle button'),
291 ],
292 ['box', 'Boxes',
293 (ID_NEW.STATIC_BOX, 'StaticBox', 'Create static box'),
294 (ID_NEW.CHECK_BOX, 'CheckBox', 'Create check box'),
295 (ID_NEW.RADIO_BOX, 'RadioBox', 'Create radio box'),
296 (ID_NEW.COMBO_BOX, 'ComboBox', 'Create combo box'),
297 (ID_NEW.LIST_BOX, 'ListBox', 'Create list box'),
298 (ID_NEW.CHECK_LIST, 'CheckListBox', 'Create checklist box'),
299 ],
300 ['container', 'Containers',
301 (ID_NEW.PANEL, 'Panel', 'Create panel'),
302 (ID_NEW.NOTEBOOK, 'Notebook', 'Create notebook control'),
303 (ID_NEW.CHOICEBOOK, 'Choicebook', 'Create choicebook control'),
304 (ID_NEW.LISTBOOK, 'Listbook', 'Create listbook control'),
305 (ID_NEW.SPLITTER_WINDOW, 'SplitterWindow', 'Create splitter window'),
306 (ID_NEW.TOOL_BAR, 'ToolBar', 'Create toolbar'),
307 (ID_NEW.STATUS_BAR, 'StatusBar', 'Create status bar'),
308 (ID_NEW.MENU_BAR, 'MenuBar', 'Create menubar'),
309 # (ID_NEW.WIZARD_PAGE, 'Wizard Page', 'Create wizard page'),
310 (ID_NEW.WIZARD_PAGE_SIMPLE, 'WizardPageSimple', 'Create simple wizard page'),
311 ],
312 ['sizer', 'Sizers',
313 (ID_NEW.BOX_SIZER, 'BoxSizer', 'Create box sizer'),
314 (ID_NEW.STATIC_BOX_SIZER, 'StaticBoxSizer',
315 'Create static box sizer'),
316 (ID_NEW.GRID_SIZER, 'GridSizer', 'Create grid sizer'),
317 (ID_NEW.FLEX_GRID_SIZER, 'FlexGridSizer',
318 'Create flexgrid sizer'),
319 (ID_NEW.GRID_BAG_SIZER, 'GridBagSizer',
320 'Create gridbag sizer'),
321 (ID_NEW.SPACER, 'Spacer', 'Create spacer'),
322 (ID_NEW.STD_DIALOG_BUTTON_SIZER, 'StdDialogButtonSizer',
323 'Create standard button sizer'),
324 ]
325 ]
326 self.menuControls = [
327 (ID_NEW.MENU, 'Menu', 'Create menu'),
328 (ID_NEW.MENU_ITEM, 'MenuItem', 'Create menu item'),
329 (ID_NEW.SEPARATOR, 'Separator', 'Create separator'),
330 ]
331 self.toolBarControls = [
332 (ID_NEW.TOOL, 'Tool', 'Create tool'),
333 (ID_NEW.SEPARATOR, 'Separator', 'Create separator'),
334 ['control', 'Various controls',
335 (ID_NEW.STATIC_TEXT, 'Label', 'Create label'),
336 (ID_NEW.STATIC_BITMAP, 'Bitmap', 'Create bitmap'),
337 (ID_NEW.STATIC_LINE, 'Line', 'Create line'),
338 (ID_NEW.TEXT_CTRL, 'TextBox', 'Create text box'),
339 (ID_NEW.CHOICE, 'Choice', 'Create choice'),
340 (ID_NEW.SLIDER, 'Slider', 'Create slider'),
341 (ID_NEW.GAUGE, 'Gauge', 'Create gauge'),
342 (ID_NEW.SCROLL_BAR, 'ScrollBar', 'Create scroll bar'),
343 (ID_NEW.LIST_CTRL, 'ListCtrl', 'Create list control'),
344 ],
345 ['button', 'Buttons',
346 (ID_NEW.BUTTON, 'Button', 'Create button'),
347 (ID_NEW.BITMAP_BUTTON, 'BitmapButton', 'Create bitmap button'),
348 (ID_NEW.RADIO_BUTTON, 'RadioButton', 'Create radio button'),
349 (ID_NEW.SPIN_BUTTON, 'SpinButton', 'Create spin button'),
350 ],
351 ['box', 'Boxes',
352 (ID_NEW.STATIC_BOX, 'StaticBox', 'Create static box'),
353 (ID_NEW.CHECK_BOX, 'CheckBox', 'Create check box'),
354 (ID_NEW.RADIO_BOX, 'RadioBox', 'Create radio box'),
355 (ID_NEW.COMBO_BOX, 'ComboBox', 'Create combo box'),
356 (ID_NEW.LIST_BOX, 'ListBox', 'Create list box'),
357 (ID_NEW.CHECK_LIST, 'CheckListBox', 'Create checklist box'),
358 ],
359 ]
360 self.stdButtons = [
361 (ID_NEW.OK_BUTTON, 'OK Button', 'Create standard button'),
362 (ID_NEW.YES_BUTTON, 'YES Button', 'Create standard button'),
363 (ID_NEW.SAVE_BUTTON, 'SAVE Button', 'Create standard button'),
364 (ID_NEW.APPLY_BUTTON, 'APPLY Button', 'Create standard button'),
365 (ID_NEW.NO_BUTTON, 'NO Button', 'Create standard button'),
366 (ID_NEW.CANCEL_BUTTON, 'CANCEL Button', 'Create standard button'),
367 (ID_NEW.HELP_BUTTON, 'HELP Button', 'Create standard button'),
368 (ID_NEW.CONTEXT_HELP_BUTTON, 'CONTEXT HELP Button', 'Create standard button'),
369 ]
370 self.stdButtonIDs = {
371 ID_NEW.OK_BUTTON: ('wxID_OK', '&Ok'),
372 ID_NEW.YES_BUTTON: ('wxID_YES', '&Yes'),
373 ID_NEW.SAVE_BUTTON: ('wxID_SAVE', '&Save'),
374 ID_NEW.APPLY_BUTTON: ('wxID_APPLY', '&Apply'),
375 ID_NEW.NO_BUTTON: ('wxID_NO', '&No'),
376 ID_NEW.CANCEL_BUTTON: ('wxID_CANCEL', '&Cancel'),
377 ID_NEW.HELP_BUTTON: ('wxID_HELP', '&Help'),
378 ID_NEW.CONTEXT_HELP_BUTTON: ('wxID_CONTEXT_HELP', '&Help'),
379 }
380
381
382
383 ################################################################################
384
385 # Set menu to list items.
386 # Each menu command is a tuple (id, label, help)
387 # submenus are lists [id, label, help, submenu]
388 # and separators are any other type. Shift is for making
389 # alternative sets of IDs. (+1000).
390 def SetMenu(m, list, shift=False):
391 for l in list:
392 if type(l) == types.TupleType:
393 # Shift ID
394 if shift: l = (1000 + l[0],) + l[1:]
395 apply(m.Append, l)
396 elif type(l) == types.ListType:
397 subMenu = wx.Menu()
398 SetMenu(subMenu, l[2:], shift)
399 m.AppendMenu(wx.NewId(), l[0], subMenu, l[1])
400 else: # separator
401 m.AppendSeparator()
402
403 ################################################################################
404
405 class HighLightBox:
406 def __init__(self, pos, size):
407 if size.width == -1: size.width = 0
408 if size.height == -1: size.height = 0
409 w = g.testWin.panel
410 l1 = wx.Window(w, -1, pos, wx.Size(size.width, 2))
411 l1.SetBackgroundColour(wx.RED)
412 l2 = wx.Window(w, -1, pos, wx.Size(2, size.height))
413 l2.SetBackgroundColour(wx.RED)
414 l3 = wx.Window(w, -1, wx.Point(pos.x + size.width - 2, pos.y), wx.Size(2, size.height))
415 l3.SetBackgroundColour(wx.RED)
416 l4 = wx.Window(w, -1, wx.Point(pos.x, pos.y + size.height - 2), wx.Size(size.width, 2))
417 l4.SetBackgroundColour(wx.RED)
418 self.lines = [l1, l2, l3, l4]
419 # Move highlight to a new position
420 def Replace(self, pos, size):
421 if size.width == -1: size.width = 0
422 if size.height == -1: size.height = 0
423 self.lines[0].SetDimensions(pos.x, pos.y, size.width, 2)
424 self.lines[1].SetDimensions(pos.x, pos.y, 2, size.height)
425 self.lines[2].SetDimensions(pos.x + size.width - 2, pos.y, 2, size.height)
426 self.lines[3].SetDimensions(pos.x, pos.y + size.height - 2, size.width, 2)
427 # Remove it
428 def Remove(self):
429 map(wx.Window.Destroy, self.lines)
430 g.testWin.highLight = None
431 def Refresh(self):
432 map(wx.Window.Refresh, self.lines)
433
434 ################################################################################
435
436 class XML_Tree(wx.TreeCtrl):
437 def __init__(self, parent, id):
438 wx.TreeCtrl.__init__(self, parent, id,
439 style = wx.TR_HAS_BUTTONS | wx.TR_MULTIPLE | wx.TR_EDIT_LABELS)
440 self.SetBackgroundColour(wx.Colour(224, 248, 224))
441 self.fontComment = wx.FFont(self.GetFont().GetPointSize(),
442 self.GetFont().GetFamily(),
443 wx.FONTFLAG_ITALIC)
444 # Register events
445 wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
446 # One works on Linux, another on Windows
447 if wx.Platform == '__WXGTK__':
448 wx.EVT_TREE_ITEM_ACTIVATED(self, self.GetId(), self.OnItemActivated)
449 else:
450 wx.EVT_LEFT_DCLICK(self, self.OnDClick)
451 wx.EVT_RIGHT_DOWN(self, self.OnRightDown)
452 wx.EVT_TREE_ITEM_EXPANDED(self, self.GetId(), self.OnItemExpandedCollapsed)
453 wx.EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemExpandedCollapsed)
454 self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnBeginLabelEdit)
455 self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEndLabelEdit)
456
457 self.selection = None
458 self.selectionChanging = False
459 self.needUpdate = False
460 self.pendingHighLight = None
461 self.ctrl = self.shift = False
462 self.dom = None
463 # Create image list
464 il = wx.ImageList(16, 16, True)
465 self.rootImage = il.Add(images.getTreeRootImage().Scale(16,16).ConvertToBitmap())
466 xxxComment.image = il.Add(images.getTreeCommentImage().Scale(16,16).ConvertToBitmap())
467 xxxObject.image = il.Add(images.getTreeDefaultImage().Scale(16,16).ConvertToBitmap())
468 xxxPanel.image = il.Add(images.getTreePanelImage().Scale(16,16).ConvertToBitmap())
469 xxxDialog.image = il.Add(images.getTreeDialogImage().Scale(16,16).ConvertToBitmap())
470 xxxFrame.image = il.Add(images.getTreeFrameImage().Scale(16,16).ConvertToBitmap())
471 xxxMenuBar.image = il.Add(images.getTreeMenuBarImage().Scale(16,16).ConvertToBitmap())
472 xxxMenu.image = il.Add(images.getTreeMenuImage().Scale(16,16).ConvertToBitmap())
473 xxxMenuItem.image = il.Add(images.getTreeMenuItemImage().Scale(16,16).ConvertToBitmap())
474 xxxToolBar.image = il.Add(images.getTreeToolBarImage().Scale(16,16).ConvertToBitmap())
475 xxxTool.image = il.Add(images.getTreeToolImage().Scale(16,16).ConvertToBitmap())
476 xxxSeparator.image = il.Add(images.getTreeSeparatorImage().Scale(16,16).ConvertToBitmap())
477 xxxSizer.imageH = il.Add(images.getTreeSizerHImage().Scale(16,16).ConvertToBitmap())
478 xxxSizer.imageV = il.Add(images.getTreeSizerVImage().Scale(16,16).ConvertToBitmap())
479 xxxStaticBoxSizer.imageH = il.Add(images.getTreeStaticBoxSizerHImage().Scale(16,16).ConvertToBitmap())
480 xxxStaticBoxSizer.imageV = il.Add(images.getTreeStaticBoxSizerVImage().Scale(16,16).ConvertToBitmap())
481 xxxGridSizer.image = il.Add(images.getTreeSizerGridImage().Scale(16,16).ConvertToBitmap())
482 xxxFlexGridSizer.image = il.Add(images.getTreeSizerFlexGridImage().Scale(16,16).ConvertToBitmap())
483 self.il = il
484 self.SetImageList(il)
485
486 def RegisterKeyEvents(self):
487 wx.EVT_KEY_DOWN(self, g.tools.OnKeyDown)
488 wx.EVT_KEY_UP(self, g.tools.OnKeyUp)
489 wx.EVT_ENTER_WINDOW(self, g.tools.OnMouse)
490 wx.EVT_LEAVE_WINDOW(self, g.tools.OnMouse)
491
492 def ExpandAll(self, item):
493 if self.ItemHasChildren(item):
494 self.Expand(item)
495 i, cookie = self.GetFirstChild(item)
496 children = []
497 while i.IsOk():
498 children.append(i)
499 i, cookie = self.GetNextChild(item, cookie)
500 for i in children:
501 self.ExpandAll(i)
502 def CollapseAll(self, item):
503 if self.ItemHasChildren(item):
504 i, cookie = self.GetFirstChild(item)
505 children = []
506 while i.IsOk():
507 children.append(i)
508 i, cookie = self.GetNextChild(item, cookie)
509 for i in children:
510 self.CollapseAll(i)
511 self.Collapse(item)
512
513 # Clear tree
514 def Clear(self):
515 self.selection = None
516 self.UnselectAll()
517 self.DeleteAllItems()
518 # Add minimal structure
519 if self.dom: self.dom.unlink()
520 self.dom = MyDocument()
521 self.dummyNode = self.dom.createComment('dummy node')
522 # Create main node
523 self.mainNode = self.dom.createElement('resource')
524 self.dom.appendChild(self.mainNode)
525 self.rootObj = xxxMainNode(self.dom)
526 self.root = self.AddRoot('XML tree', self.rootImage,
527 data=wx.TreeItemData(self.rootObj))
528 self.SetItemHasChildren(self.root)
529 self.testElem = self.dom.createElement('dummy')
530 self.mainNode.appendChild(self.testElem)
531 self.Expand(self.root)
532
533 # Clear old data and set new
534 def SetData(self, dom):
535 self.selection = None
536 self.UnselectAll()
537 self.DeleteAllItems()
538 # Add minimal structure
539 if self.dom: self.dom.unlink()
540 self.dom = dom
541 self.dummyNode = self.dom.createComment('dummy node')
542 # Find 'resource' child, add it's children
543 self.mainNode = dom.documentElement
544 self.rootObj = xxxMainNode(self.dom)
545 self.root = self.AddRoot('XML tree', self.rootImage,
546 data=wx.TreeItemData(self.rootObj))
547 self.SetItemHasChildren(self.root)
548 nodes = self.mainNode.childNodes[:]
549 for node in nodes:
550 if IsObject(node):
551 self.AddNode(self.root, None, node)
552 else:
553 self.mainNode.removeChild(node)
554 node.unlink()
555 if self.mainNode.firstChild:
556 self.testElem = self.dom.createElement('dummy')
557 self.mainNode.insertBefore(self.testElem, self.mainNode.firstChild)
558 else:
559 self.testElem = self.dom.createElement('dummy')
560 self.mainNode.appendChild(self.testElem)
561 self.Expand(self.root)
562
563 # Add tree item for given parent item if node is DOM element node with
564 # object/object_ref tag. xxxParent is parent xxx object
565 def AddNode(self, itemParent, xxxParent, node):
566 # Set item data to current node
567 try:
568 xxx = MakeXXXFromDOM(xxxParent, node)
569 except:
570 print 'ERROR: MakeXXXFromDom(%s, %s)' % (xxxParent, node)
571 raise
572 treeObj = xxx.treeObject()
573 # Append tree item
574 item = self.AppendItem(itemParent, treeObj.treeName(),
575 image=treeObj.treeImage(),
576 data=wx.TreeItemData(xxx))
577 # Different color for comments and references
578 if xxx.className == 'comment':
579 self.SetItemTextColour(item, 'Blue')
580 self.SetItemFont(item, self.fontComment)
581 elif treeObj.ref:
582 self.SetItemTextColour(item, 'DarkGreen')
583 elif treeObj.hasStyle and treeObj.params.get('hidden', False):
584 self.SetItemTextColour(item, 'Grey')
585 # Try to find children objects
586 if treeObj.hasChildren:
587 nodes = treeObj.node.childNodes[:]
588 for n in nodes:
589 if IsObject(n):
590 self.AddNode(item, treeObj, n)
591 elif n.nodeType != minidom.Node.ELEMENT_NODE:
592 treeObj.node.removeChild(n)
593 n.unlink()
594
595 # Insert new item at specific position
596 def InsertNode(self, itemParent, parent, elem, nextItem):
597 # Insert in XML tree and wxWin
598 xxx = MakeXXXFromDOM(parent, elem)
599 # If nextItem is None, we append to parent, otherwise insert before it
600 if nextItem.IsOk():
601 node = self.GetPyData(nextItem).node
602 parent.node.insertBefore(elem, node)
603 # Inserting before is difficult, se we insert after or first child
604 index = self.ItemIndex(nextItem)
605 newItem = self.InsertItemBefore(itemParent, index,
606 xxx.treeName(), image=xxx.treeImage())
607 self.SetPyData(newItem, xxx)
608 else:
609 parent.node.appendChild(elem)
610 newItem = self.AppendItem(itemParent, xxx.treeName(), image=xxx.treeImage(),
611 data=wx.TreeItemData(xxx))
612 treeObj = xxx.treeObject()
613 # Different color for references and comments
614 if xxx.className == 'comment':
615 self.SetItemTextColour(newItem, 'Blue')
616 self.SetItemFont(newItem, self.fontComment)
617 elif treeObj.ref:
618 self.SetItemTextColour(newItem, 'DarkGreen')
619 elif treeObj.hasStyle and treeObj.params.get('hidden', False):
620 self.SetItemTextColour(newItem, 'Grey')
621 # Add children items
622 if xxx.hasChildren:
623 treeObj = xxx.treeObject()
624 for n in treeObj.node.childNodes:
625 if IsObject(n):
626 self.AddNode(newItem, treeObj, n)
627 return newItem
628
629 # Remove leaf of tree, return it's data object
630 def RemoveLeaf(self, leaf):
631 xxx = self.GetPyData(leaf)
632 node = xxx.node
633 parent = node.parentNode
634 parent.removeChild(node)
635 self.Delete(leaf)
636 # Reset selection object
637 self.selection = None
638 return node
639
640 # Find position relative to the top-level window
641 def FindNodePos(self, item, obj=None):
642 # Root at (0,0)
643 if item == g.testWin.item: return wx.Point(0, 0)
644 itemParent = self.GetItemParent(item)
645 # Select book page
646 if not obj: obj = self.FindNodeObject(item)
647 if self.GetPyData(itemParent).treeObject().__class__ in \
648 [xxxNotebook, xxxChoicebook, xxxListbook]:
649 book = self.FindNodeObject(itemParent)
650 # Find position
651 for i in range(book.GetPageCount()):
652 if book.GetPage(i) == obj:
653 if book.GetSelection() != i:
654 book.SetSelection(i)
655 # Remove highlight - otherwise highlight window won't be visible
656 if g.testWin.highLight:
657 g.testWin.highLight.Remove()
658 break
659 # For sizers and notebooks we must select the first window-like parent
660 winParent = itemParent
661 while self.GetPyData(winParent).isSizer:
662 winParent = self.GetItemParent(winParent)
663 # Notebook children are layed out in a little strange way
664 # wxGTK places NB panels relative to the NB parent
665 if wx.Platform == '__WXGTK__':
666 if self.GetPyData(itemParent).treeObject().__class__ == xxxNotebook:
667 winParent = self.GetItemParent(winParent)
668 parentPos = self.FindNodePos(winParent)
669 pos = obj.GetPosition()
670 # Position (-1,-1) is really (0,0)
671 if pos == (-1,-1): pos = (0,0)
672 return parentPos + pos
673
674 # Find window (or sizer) corresponding to a tree item.
675 def FindNodeObject(self, item):
676 testWin = g.testWin
677 # If top-level, return testWin (or panel its panel)
678 if item == testWin.item: return testWin.panel
679 itemParent = self.GetItemParent(item)
680 xxx = self.GetPyData(item).treeObject()
681 parentWin = self.FindNodeObject(itemParent)
682 # Top-level sizer? return window's sizer
683 if xxx.isSizer and isinstance(parentWin, wx.Window):
684 return parentWin.GetSizer()
685 elif xxx.__class__ in [xxxMenu, xxxMenuItem, xxxSeparator]: return None
686 elif xxx.__class__ in [xxxToolBar, xxxMenuBar]:
687 # If it's the main toolbar or menubar, we can't really select it
688 if xxx.parent.__class__ == xxxFrame: return None
689 elif isinstance(xxx.parent, xxxToolBar):
690 # Select complete toolbar
691 return parentWin
692 elif isinstance(xxx.parent, xxxStdDialogButtonSizer):
693 # This sizer returns non-existing children
694 for ch in parentWin.GetChildren():
695 if ch.GetWindow() and ch.GetWindow().GetName() == xxx.name:
696 return ch.GetWindow()
697 return None
698 elif xxx.parent.__class__ in [xxxChoicebook, xxxListbook]:
699 # First window is controld
700 return parentWin.GetChildren()[self.ItemIndex(item)+1]
701 # Otherwise get parent's object and it's child
702 child = parentWin.GetChildren()[self.WindowIndex(item)]
703 # Return window or sizer for sizer items
704 if child.GetClassName() == 'wxSizerItem':
705 if child.IsWindow(): child = child.GetWindow()
706 elif child.IsSizer():
707 child = child.GetSizer()
708 return child
709
710 def OnSelChanged(self, evt):
711 if self.selectionChanging: return
712 self.selectionChanging = True
713 self.UnselectAll()
714 self.SelectItem(evt.GetItem())
715 self.selectionChanging = False
716
717 def ChangeSelection(self, item):
718 # Apply changes
719 # !!! problem with wxGTK - GetOldItem is Ok if nothing selected
720 #oldItem = evt.GetOldItem()
721 status = ''
722 oldItem = self.selection
723 # use GetItemParent as a way to determine if the itemId is still valid
724 if oldItem and self.GetItemParent(oldItem):
725 xxx = self.GetPyData(oldItem)
726 # If some data was modified, apply changes
727 if g.panel.IsModified():
728 self.Apply(xxx, oldItem)
729 if g.testWin:
730 if g.testWin.highLight:
731 g.testWin.highLight.Remove()
732 self.needUpdate = True
733 status = 'Changes were applied'
734 g.frame.SetStatusText(status)
735 # Generate view
736 self.selection = item
737 if not self.selection.IsOk():
738 self.selection = None
739 return
740 xxx = self.GetPyData(self.selection)
741 # Update panel
742 g.panel.SetData(xxx)
743 # Update tools
744 g.tools.UpdateUI()
745 # Highlighting is done in OnIdle
746 self.pendingHighLight = self.selection
747
748 # Check if item is in testWin subtree
749 def IsHighlatable(self, item):
750 if item == g.testWin.item: return False
751 while item != self.root:
752 item = self.GetItemParent(item)
753 if item == g.testWin.item:
754 return True
755 return False
756
757 # Highlight selected item
758 def HighLight(self, item):
759 self.pendingHighLight = None
760 # Can highlight only with some top-level windows
761 if not g.testWin or self.GetPyData(g.testWin.item).treeObject().__class__ \
762 not in [xxxDialog, xxxPanel, xxxFrame]:
763 return
764 # If a control from another window is selected, remove highlight
765 if not self.IsHighlatable(item):
766 if g.testWin.highLight: g.testWin.highLight.Remove()
767 return
768 # Get window/sizer object
769 obj = self.FindNodeObject(item)
770 xxx = self.GetPyData(item).treeObject()
771 # Remove existing HL if item not found or is hidden
772 if not obj or xxx.hasStyle and xxx.params.get('hidden', False):
773 if g.testWin.highLight: g.testWin.highLight.Remove()
774 return
775 pos = self.FindNodePos(item, obj)
776 size = obj.GetSize()
777 # Highlight
778 # Negative positions are not working quite well
779 if g.testWin.highLight:
780 g.testWin.highLight.Replace(pos, size)
781 else:
782 g.testWin.highLight = HighLightBox(pos, size)
783 g.testWin.highLight.Refresh()
784 g.testWin.highLight.item = item
785
786 def ShowTestWindow(self, item):
787 xxx = self.GetPyData(item)
788 if g.panel.IsModified():
789 self.Apply(xxx, item) # apply changes
790 availableViews = ['wxFrame', 'wxPanel', 'wxDialog',
791 'wxMenuBar', 'wxToolBar', 'wxWizard',
792 'wxWizardPageSimple']
793 originalItem = item
794 # Walk up the tree until we find an item that has a view
795 while item and self.GetPyData(item).treeObject().className not in availableViews:
796 item = self.GetItemParent(item)
797 if not item or not item.IsOk():
798 wx.LogMessage('No view for this element (yet)')
799 return
800 # Show item in bold
801 if g.testWin: # Reset old
802 self.UnselectAll()
803 self.SetItemBold(g.testWin.item, False)
804 try:
805 wx.BeginBusyCursor()
806 self.CreateTestWin(item)
807 finally:
808 wx.EndBusyCursor()
809 # Maybe an error occurred, so we need to test
810 if g.testWin:
811 self.SetItemBold(g.testWin.item)
812 # Select original item
813 self.ChangeSelection(originalItem)
814
815 # Double-click on Linux
816 def OnItemActivated(self, evt):
817 if evt.GetItem() != self.root:
818 self.ShowTestWindow(evt.GetItem())
819
820 # Double-click on Windows
821 def OnDClick(self, evt):
822 item, flags = self.HitTest(evt.GetPosition())
823 if flags in [wx.TREE_HITTEST_ONITEMBUTTON, wx.TREE_HITTEST_ONITEMLABEL]:
824 if item != self.root: self.ShowTestWindow(item)
825 else:
826 evt.Skip()
827
828 def OnItemExpandedCollapsed(self, evt):
829 # Update tool palette
830 g.tools.UpdateUI()
831 evt.Skip()
832
833 # (re)create test window
834 def CreateTestWin(self, item):
835 testWin = g.testWin
836 # Create a window with this resource
837 xxx = self.GetPyData(item).treeObject()
838
839 # If frame
840 # if xxx.__class__ == xxxFrame:
841 # Frame can't have many children,
842 # but it's first child possibly can...
843 # child = self.GetFirstChild(item)[0]
844 # if child.IsOk() and self.GetPyData(child).__class__ == xxxPanel:
845 # # Clean-up before recursive call or error
846 # wx.MemoryFSHandler.RemoveFile('xxx.xrc')
847 # wx.EndBusyCursor()
848 # self.CreateTestWin(child)
849 # return
850
851 # Close old window, remember where it was
852 highLight = None
853 if testWin:
854 pos = testWin.GetPosition()
855 if item == testWin.item:
856 # Remember highlight if same top-level window
857 if testWin.highLight:
858 highLight = testWin.highLight.item
859 if xxx.className == 'wxPanel':
860 if testWin.highLight:
861 testWin.pendingHighLight = highLight
862 testWin.highLight.Remove()
863 testWin.panel.Destroy()
864 testWin.panel = None
865 else:
866 testWin.Destroy()
867 testWin = g.testWin = None
868 else:
869 testWin.Destroy()
870 testWin = g.testWin = None
871 else:
872 pos = g.testWinPos
873 # Save in memory FS
874 memFile = MemoryFile('xxx.xrc')
875 # Create memory XML file
876 elem = xxx.node.cloneNode(True)
877 if not xxx.name:
878 name = 'noname'
879 else:
880 name = xxx.name
881 elem.setAttribute('name', STD_NAME)
882 oldTestNode = self.testElem
883 self.testElem = elem
884 self.mainNode.replaceChild(elem, oldTestNode)
885 oldTestNode.unlink()
886 # Replace wizard page class temporarily
887 if xxx.__class__ in [xxxWizardPage, xxxWizardPageSimple]:
888 oldCl = elem.getAttribute('class')
889 elem.setAttribute('class', 'wxPanel')
890 parent = elem.parentNode
891 encd = self.rootObj.params['encoding'].value()
892 if not encd: encd = None
893 try:
894 self.dom.writexml(memFile, encoding=encd)
895 except:
896 inf = sys.exc_info()
897 wx.LogError(traceback.format_exception(inf[0], inf[1], None)[-1])
898 wx.LogError('Error writing temporary file')
899 memFile.close() # write to wxMemoryFS
900 xmlFlags = xrc.XRC_NO_SUBCLASSING
901 # Use translations if encoding is not specified
902 if not g.currentEncoding:
903 xmlFlags != xrc.XRC_USE_LOCALE
904 res = xrc.XmlResource('', xmlFlags)
905 res.Load('memory:xxx.xrc')
906 try:
907 if xxx.__class__ == xxxFrame:
908 # Frame can't have many children,
909 # but it's first child possibly can...
910 # child = self.GetFirstChild(item)[0]
911 # if child.IsOk() and self.GetPyData(child).__class__ == xxxPanel:
912 # # Clean-up before recursive call or error
913 # wx.MemoryFSHandler.RemoveFile('xxx.xrc')
914 # wx.EndBusyCursor()
915 # self.CreateTestWin(child)
916 # return
917 # This currently works under GTK, but not under MSW
918 testWin = g.testWin = wx.PreFrame()
919 res.LoadOnFrame(testWin, g.frame, STD_NAME)
920 # Create status bar
921 testWin.panel = testWin
922 #testWin.CreateStatusBar()
923 testWin.SetClientSize(testWin.GetBestSize())
924 testWin.SetPosition(pos)
925 testWin.Show(True)
926 elif xxx.__class__ == xxxPanel:
927 # Create new frame
928 if not testWin:
929 testWin = g.testWin = wx.Frame(g.frame, -1, 'Panel: ' + name,
930 pos=pos, name=STD_NAME)
931 testWin.panel = res.LoadPanel(testWin, STD_NAME)
932 testWin.SetClientSize(testWin.GetBestSize())
933 testWin.Show(True)
934 elif xxx.__class__ == xxxDialog:
935 testWin = g.testWin = res.LoadDialog(g.frame, STD_NAME)
936 testWin.panel = testWin
937 testWin.Layout()
938 testWin.SetPosition(pos)
939 testWin.Show(True)
940 # Dialog's default code does not produce wx.EVT_CLOSE
941 wx.EVT_BUTTON(testWin, wx.ID_OK, self.OnCloseTestWin)
942 wx.EVT_BUTTON(testWin, wx.ID_CANCEL, self.OnCloseTestWin)
943 elif xxx.__class__ == xxxWizard:
944 wiz = wx.wizard.PreWizard()
945 res.LoadOnObject(wiz, g.frame, STD_NAME, 'wxWizard')
946 # Find first page (don't know better way)
947 firstPage = None
948 for w in wiz.GetChildren():
949 if isinstance(w, wx.wizard.WizardPage):
950 firstPage = w
951 break
952 if not firstPage:
953 wx.LogError('Wizard is empty')
954 else:
955 # Wizard should be modal
956 self.SetItemBold(item)
957 wiz.RunWizard(w)
958 self.SetItemBold(item, False)
959 wiz.Destroy()
960 elif xxx.__class__ in [xxxWizardPage, xxxWizardPageSimple]:
961 # Create new frame
962 if not testWin:
963 testWin = g.testWin = wx.Frame(g.frame, -1, 'Wizard page: ' + name,
964 pos=pos, name=STD_NAME)
965 testWin.panel = wx.PrePanel()
966 res.LoadOnObject(testWin.panel, testWin, STD_NAME, 'wxPanel')
967 testWin.SetClientSize(testWin.GetBestSize())
968 testWin.Show(True)
969 elif xxx.__class__ == xxxMenuBar:
970 testWin = g.testWin = wx.Frame(g.frame, -1, 'MenuBar: ' + name,
971 pos=pos, name=STD_NAME)
972 testWin.panel = None
973 # Set status bar to display help
974 testWin.CreateStatusBar()
975 testWin.menuBar = res.LoadMenuBar(STD_NAME)
976 testWin.SetMenuBar(testWin.menuBar)
977 testWin.Show(True)
978 elif xxx.__class__ == xxxToolBar:
979 testWin = g.testWin = wx.Frame(g.frame, -1, 'ToolBar: ' + name,
980 pos=pos, name=STD_NAME)
981 testWin.panel = None
982 # Set status bar to display help
983 testWin.CreateStatusBar()
984 testWin.toolBar = res.LoadToolBar(testWin, STD_NAME)
985 testWin.SetToolBar(testWin.toolBar)
986 testWin.Show(True)
987 # Catch some events, set highlight
988 if testWin:
989 testWin.item = item
990 wx.EVT_CLOSE(testWin, self.OnCloseTestWin)
991 wx.EVT_SIZE(testWin, self.OnSizeTestWin)
992 testWin.highLight = None
993 if highLight and not self.pendingHighLight:
994 self.HighLight(highLight)
995 except:
996 if g.testWin:
997 self.SetItemBold(item, False)
998 g.testWinPos = g.testWin.GetPosition()
999 g.testWin.Destroy()
1000 g.testWin = None
1001 inf = sys.exc_info()
1002 wx.LogError(traceback.format_exception(inf[0], inf[1], None)[-1])
1003 wx.LogError('Error loading resource')
1004 wx.MemoryFSHandler.RemoveFile('xxx.xrc')
1005
1006 def CloseTestWindow(self):
1007 if not g.testWin: return
1008 self.SetItemBold(g.testWin.item, False)
1009 g.frame.tb.ToggleTool(g.frame.ID_TOOL_LOCATE, False)
1010 g.testWinPos = g.testWin.GetPosition()
1011 g.testWin.Destroy()
1012 g.testWin = None
1013
1014 def OnCloseTestWin(self, evt):
1015 self.CloseTestWindow()
1016
1017 def OnSizeTestWin(self, evt):
1018 if g.testWin.highLight:
1019 self.HighLight(g.testWin.highLight.item)
1020 evt.Skip()
1021
1022 # Return index in parent, for real window children
1023 def WindowIndex(self, item):
1024 n = 0 # index of sibling
1025 prev = self.GetPrevSibling(item)
1026 while prev.IsOk():
1027 # MenuBar is not a child
1028 if not isinstance(self.GetPyData(prev), xxxMenuBar):
1029 n += 1
1030 prev = self.GetPrevSibling(prev)
1031 return n
1032
1033 # Return item index in parent
1034 def ItemIndex(self, item):
1035 n = 0 # index of sibling
1036 prev = self.GetPrevSibling(item)
1037 while prev.IsOk():
1038 prev = self.GetPrevSibling(prev)
1039 n += 1
1040 return n
1041
1042 # Full tree index of an item - list of positions
1043 def ItemFullIndex(self, item):
1044 if not item.IsOk(): return None
1045 l = []
1046 while item != self.root:
1047 l.insert(0, self.ItemIndex(item))
1048 item = self.GetItemParent(item)
1049 return l
1050 # Get item position from full index
1051 def ItemAtFullIndex(self, index):
1052 if index is None: return wx.TreeItemId()
1053 item = self.root
1054 for i in index:
1055 item = self.GetFirstChild(item)[0]
1056 for k in range(i): item = self.GetNextSibling(item)
1057 return item
1058
1059 # True if next item should be inserted after current (vs. appended to it)
1060 def NeedInsert(self, item):
1061 xxx = self.GetPyData(item)
1062 if item == self.root: return False # root item
1063 if xxx.hasChildren and not self.GetChildrenCount(item, False):
1064 return False
1065 return not (self.IsExpanded(item) and self.GetChildrenCount(item, False))
1066
1067 # Override to use like single-selection tree
1068 def GetSelection(self):
1069 return self.selection
1070 def SelectItem(self, item):
1071 self.UnselectAll()
1072 self.ChangeSelection(item)
1073 wx.TreeCtrl.SelectItem(self, item)
1074
1075 # Pull-down
1076 def OnRightDown(self, evt):
1077 pullDownMenu = g.pullDownMenu
1078 # select this item
1079 pt = evt.GetPosition();
1080 item, flags = self.HitTest(pt)
1081 if item.Ok() and flags & wx.TREE_HITTEST_ONITEM:
1082 self.SelectItem(item)
1083
1084 # Setup menu
1085 menu = wx.Menu()
1086
1087 item = self.selection
1088 if not item:
1089 menu.Append(g.pullDownMenu.ID_EXPAND, 'Expand', 'Expand tree')
1090 menu.Append(g.pullDownMenu.ID_COLLAPSE, 'Collapse', 'Collapse tree')
1091 else:
1092 # self.ctrl = evt.ControlDown() # save Ctrl state
1093 # self.shift = evt.ShiftDown() # and Shift too
1094 m = wx.Menu() # create menu
1095 if self.ctrl:
1096 needInsert = True
1097 else:
1098 needInsert = self.NeedInsert(item)
1099 if item == self.root or needInsert and self.GetItemParent(item) == self.root:
1100 SetMenu(m, pullDownMenu.topLevel)
1101 m.AppendSeparator()
1102 m.Append(ID_NEW.REF, 'reference...', 'Create object_ref node')
1103 m.Append(ID_NEW.COMMENT, 'comment', 'Create comment node')
1104 else:
1105 xxx = self.GetPyData(item).treeObject()
1106 # Check parent for possible child nodes if inserting sibling
1107 if needInsert: xxx = xxx.parent
1108 if xxx.__class__ == xxxMenuBar:
1109 m.Append(ID_NEW.MENU, 'Menu', 'Create menu')
1110 elif xxx.__class__ in [xxxToolBar, xxxTool] or \
1111 xxx.__class__ == xxxSeparator and xxx.parent.__class__ == xxxToolBar:
1112 SetMenu(m, pullDownMenu.toolBarControls)
1113 elif xxx.__class__ in [xxxMenu, xxxMenuItem]:
1114 SetMenu(m, pullDownMenu.menuControls)
1115 elif xxx.__class__ == xxxStdDialogButtonSizer:
1116 SetMenu(m, pullDownMenu.stdButtons)
1117 else:
1118 SetMenu(m, pullDownMenu.controls)
1119 if xxx.__class__ in [xxxNotebook, xxxChoicebook, xxxListbook]:
1120 m.Enable(m.FindItem('sizer'), False)
1121 elif not (xxx.isSizer or xxx.parent and xxx.parent.isSizer):
1122 m.Enable(ID_NEW.SPACER, False)
1123 if xxx.__class__ is not xxxFrame:
1124 m.Enable(ID_NEW.MENU_BAR, False)
1125 m.AppendSeparator()
1126 m.Append(ID_NEW.REF, 'reference...', 'Create object_ref node')
1127 m.Append(ID_NEW.COMMENT, 'comment', 'Create comment node')
1128 # Select correct label for create menu
1129 if not needInsert:
1130 if self.shift:
1131 menu.AppendMenu(wx.NewId(), 'Insert Child', m,
1132 'Create child object as the first child')
1133 else:
1134 menu.AppendMenu(wx.NewId(), 'Append Child', m,
1135 'Create child object as the last child')
1136 else:
1137 if self.shift:
1138 menu.AppendMenu(wx.NewId(), 'Create Sibling', m,
1139 'Create sibling before selected object')
1140 else:
1141 menu.AppendMenu(wx.NewId(), 'Create Sibling', m,
1142 'Create sibling after selected object')
1143 # Build replace menu
1144 if item != self.root:
1145 xxx = self.GetPyData(item).treeObject()
1146 m = wx.Menu() # create replace menu
1147 if xxx.__class__ == xxxMenuBar:
1148 m.Append(1000 + ID_NEW.MENU, 'Menu', 'Create menu')
1149 elif xxx.__class__ in [xxxMenu, xxxMenuItem]:
1150 SetMenu(m, pullDownMenu.menuControls, shift=True)
1151 elif xxx.__class__ == xxxToolBar and \
1152 self.GetItemParent(item) == self.root:
1153 SetMenu(m, [], shift=True)
1154 elif xxx.__class__ in [xxxFrame, xxxDialog, xxxPanel]:
1155 SetMenu(m, [
1156 (ID_NEW.PANEL, 'Panel', 'Create panel'),
1157 (ID_NEW.DIALOG, 'Dialog', 'Create dialog'),
1158 (ID_NEW.FRAME, 'Frame', 'Create frame')], shift=True)
1159 elif xxx.isSizer and self.ItemHasChildren(item):
1160 SetMenu(m, pullDownMenu.sizers, shift=True)
1161 else:
1162 SetMenu(m, pullDownMenu.controls, shift=True)
1163 if xxx.isElement:
1164 id = wx.NewId()
1165 menu.AppendMenu(id, 'Replace With', m)
1166 if not m.GetMenuItemCount(): menu.Enable(id, False)
1167 menu.Append(pullDownMenu.ID_SUBCLASS, 'Subclass...',
1168 'Set "subclass" property')
1169 menu.AppendSeparator()
1170 # Not using standart IDs because we don't want to show shortcuts
1171 menu.Append(wx.ID_CUT, 'Cut', 'Cut to the clipboard')
1172 menu.Append(wx.ID_COPY, 'Copy', 'Copy to the clipboard')
1173 if self.ctrl and item != self.root:
1174 menu.Append(pullDownMenu.ID_PASTE_SIBLING, 'Paste Sibling',
1175 'Paste from the clipboard as a sibling')
1176 else:
1177 menu.Append(wx.ID_PASTE, 'Paste', 'Paste from the clipboard')
1178 menu.Append(pullDownMenu.ID_DELETE,
1179 'Delete', 'Delete object')
1180 if self.ItemHasChildren(item):
1181 menu.AppendSeparator()
1182 menu.Append(pullDownMenu.ID_EXPAND, 'Expand', 'Expand subtree')
1183 menu.Append(pullDownMenu.ID_COLLAPSE, 'Collapse', 'Collapse subtree')
1184 self.PopupMenu(menu, evt.GetPosition())
1185 menu.Destroy()
1186
1187 # Redefine to force the update of font dimentions on wxGTK
1188 if wx.Platform == '__WXGTK__':
1189 def SetItemBold(self, item, state=True):
1190 wx.TreeCtrl.SetItemBold(self, item, state)
1191 self.SetIndent(self.GetIndent())
1192
1193 # Apply changes
1194 def Apply(self, xxx, item):
1195 g.panel.Apply()
1196 # Update tree view
1197 xxx = xxx.treeObject()
1198 if xxx.hasName and self.GetItemText(item) != xxx.name:
1199 self.SetItemText(item, xxx.treeName())
1200 # Item width may have changed
1201 # !!! Tric to update tree width (wxGTK, ??)
1202 self.SetIndent(self.GetIndent())
1203 elif xxx.className == 'comment':
1204 self.SetItemText(item, xxx.treeName())
1205 # Change tree icon for sizers
1206 if isinstance(xxx, xxxBoxSizer):
1207 self.SetItemImage(item, xxx.treeImage())
1208 # Set global modified state
1209 g.frame.SetModified()
1210
1211 def OnBeginLabelEdit(self, evt):
1212 xxx = self.GetPyData(evt.GetItem())
1213 if xxx.isElement:
1214 evt.Veto()
1215 else:
1216 evt.Skip()
1217
1218 def OnEndLabelEdit(self, evt):
1219 xxx = self.GetPyData(evt.GetItem())
1220 node = xxx.node
1221 if not xxx.isElement:
1222 node.data = evt.GetLabel()
1223 g.panel.SetData(xxx)
1224 evt.Skip()