2 # Purpose: XRC editor, main module
3 # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
6 from wxPython
.wx
import *
7 from wxPython
.xrc
import *
8 from wxPython
.html
import *
9 import wxPython
.lib
.wxpTag
10 from xml
.dom
import minidom
17 htmlHeader
= '<html><body bgcolor="#b0c4de">\n'
18 htmlFooter
= '</body></html>\n'
27 testWinPos
= wxDefaultPosition
29 # 1 adds CMD command to Help menu
36 # Set menu to list items.
37 # Each menu command is a tuple (id, label, help)
38 # submenus are lists [id, label, help, submenu]
39 # and separators are any other type
42 if type(l
) == types
.TupleType
:
44 elif type(l
) == types
.ListType
:
46 SetMenu(subMenu
, l
[2:])
47 m
.AppendMenu(wxNewId(), l
[0], subMenu
, l
[1])
52 class Panel(wxHtmlWindow
):
53 def __init__(self
, parent
, id):
54 wxHtmlWindow
.__init
__(self
, parent
, id)
56 self
.SetFonts('', '', [8, 10, 12, 14, 16, 19, 24])
57 EVT_CHECKBOX(self
, xxxObject
.ID_CHECK_PARAMS
, self
.OnCheckParams
)
58 EVT_CHECKBOX(self
, xxxChildContainer
.ID_CHECK_PARAMS
, self
.OnCheckParams
)
62 self
.SetPage(htmlHeader
+ 'select a tree item on the left' + htmlFooter
)
64 def OnCheckParams(self
, evt
):
65 selected
= tree
.GetSelection()
66 xxx
= tree
.GetPyData(selected
)
67 if xxx
.hasChild
and evt
.GetId() != xxxChildContainer
.ID_CHECK_PARAMS
:
70 param
= evt
.GetEventObject().GetName()[6:]
72 w
= GetRegistered('_'+param
)
74 w
= GetRegistered(param
)
77 # Ad new text node in order of allParams
79 textElem
= tree
.dom
.createElement(param
)
80 textNode
= tree
.dom
.createTextNode('')
81 textElem
.appendChild(textNode
)
82 # Find place to put new element: first present element after param
84 for p
in xxx
.allParams
[xxx
.allParams
.index(param
) + 1:]:
85 # Content params don't have same type
86 if xxx
.params
.has_key(p
) and p
!= 'content':
90 nextTextElem
= xxx
.params
[p
].parentNode
91 elem
.insertBefore(textElem
, nextTextElem
)
93 elem
.appendChild(textElem
)
94 xxx
.params
[param
] = textNode
96 # Remove parameter element and following text node
97 textElem
= xxx
.params
[param
].parentNode
98 newline
= textElem
.nextSibling
99 if newline
and newline
.nodeType
== minidom
.Node
.TEXT_NODE
:
100 elem
.removeChild(newline
)
101 elem
.removeChild(textElem
)
102 del xxx
.params
[param
]
104 w
.Enable(evt
.IsChecked())
106 self
.SetModified(true
)
108 # If some parameter was changed
109 def IsModified(self
):
111 def SetModified(self
, value
):
112 self
.modified
= value
115 def __init__(self
, pos
, size
):
117 l1
= wxWindow(w
, -1, pos
, wxSize(size
.x
, 2))
118 l1
.SetBackgroundColour(wxRED
)
119 l2
= wxWindow(w
, -1, pos
, wxSize(2, size
.y
))
120 l2
.SetBackgroundColour(wxRED
)
121 l3
= wxWindow(w
, -1, wxPoint(pos
.x
+ size
.x
- 2, pos
.y
), wxSize(2, size
.y
))
122 l3
.SetBackgroundColour(wxRED
)
123 l4
= wxWindow(w
, -1, wxPoint(pos
.x
, pos
.y
+ size
.y
- 2), wxSize(size
.x
, 2))
124 l4
.SetBackgroundColour(wxRED
)
125 self
.lines
= [l1
, l2
, l3
, l4
]
126 # Move highlight to a new position
127 def Replace(self
, pos
, size
):
128 self
.lines
[0].SetDimensions(pos
.x
, pos
.y
, size
.x
, 2, wxSIZE_ALLOW_MINUS_ONE
)
129 self
.lines
[1].SetDimensions(pos
.x
, pos
.y
, 2, size
.y
, wxSIZE_ALLOW_MINUS_ONE
)
130 self
.lines
[2].SetDimensions(pos
.x
+ size
.x
- 2, pos
.y
, 2, size
.y
,
131 wxSIZE_ALLOW_MINUS_ONE
)
132 self
.lines
[3].SetDimensions(pos
.x
, pos
.y
+ size
.y
- 2, size
.x
, 2,
133 wxSIZE_ALLOW_MINUS_ONE
)
136 map(wxWindow
.Destroy
, self
.lines
)
137 testWin
.highLight
= None
140 def __init__(self
, name
):
143 def write(self
, data
):
144 self
.buffer = self
.buffer + data
.encode()
146 f
= open(self
.name
, 'w')
149 # !!! memory FS will work someday
150 #self.file = wxMemoryFSHandler_AddFile(self.name, self.buffer)
152 class XML_Tree(wxTreeCtrl
):
153 def __init__(self
, parent
, id):
154 wxTreeCtrl
.__init
__(self
, parent
, id)
155 self
.SetBackgroundColour(wxColour(224, 248, 224))
156 EVT_TREE_SEL_CHANGED(self
, self
.GetId(), self
.OnSelChanged
)
157 EVT_TREE_ITEM_ACTIVATED(self
, self
.GetId(), self
.OnItemActivated
)
158 EVT_RIGHT_DOWN(self
, self
.OnRightDown
)
159 self
.needUpdate
= false
160 self
.pendingHighLight
= None
164 il
= wxImageList(16, 16, true
)
165 xxxPanel
.image
= il
.AddIcon( wxIconFromXPMData(images
.getTreePanelData()) )
166 xxxDialog
.image
= il
.AddIcon( wxIconFromXPMData(images
.getTreeDialogData()) )
167 xxxFrame
.image
= il
.AddIcon( wxIconFromXPMData(images
.getTreeFrameData()) )
168 xxxMenuBar
.image
= il
.AddIcon( wxIconFromXPMData(images
.getTreeMenuBarData()) )
169 xxxMenu
.image
= il
.AddIcon( wxIconFromXPMData(images
.getTreeMenuData()) )
170 xxxSizer
.imageH
= il
.AddIcon( wxIconFromXPMData(images
.getTreeSizerHData()) )
171 xxxSizer
.imageV
= il
.AddIcon( wxIconFromXPMData(images
.getTreeSizerVData()) )
172 xxxStaticBoxSizer
.imageH
= il
.AddIcon( wxIconFromXPMData(images
.getTreeStaticBoxSizerHData()) )
173 xxxStaticBoxSizer
.imageV
= il
.AddIcon( wxIconFromXPMData(images
.getTreeStaticBoxSizerVData()) )
174 xxxGridSizer
.image
= il
.AddIcon( wxIconFromXPMData(images
.getTreeSizerGridData()) )
175 xxxFlexGridSizer
.image
= il
.AddIcon( wxIconFromXPMData(images
.getTreeSizerFlexGridData()) )
177 self
.SetImageList(il
)
179 # !!! temporary solution for GetOldItem problem
181 self
.selection
= wxTreeItemId()
182 wxTreeCtrl
.Unselect(self
)
183 def GetSelection(self
):
184 return self
.selection
186 def ExpandAll(self
, item
):
187 if self
.ItemHasChildren(item
):
189 i
, cookie
= self
.GetFirstChild(item
, 0)
193 i
, cookie
= self
.GetNextChild(item
, cookie
)
197 def SetData(self
, dom
):
199 # Find 'resource' child, add it's children
200 self
.mainNode
= dom
.getElementsByTagName('resource')[0]
201 nodes
= self
.mainNode
.childNodes
[:]
204 self
.AddNode(self
.GetRootItem(), None, node
)
206 self
.mainNode
.removeChild(node
)
210 # Add tree item for given parent item if node is DOM element node with
211 # 'object' tag. xxxParent is parent xxx object
212 def AddNode(self
, itemParent
, xxxParent
, node
):
213 # Set item data to current node
214 xxx
= MakeXXXFromDOM(xxxParent
, node
)
215 treeObj
= xxx
.treeObject()
217 item
= self
.AppendItem(itemParent
, treeObj
.treeName(),
218 image
=treeObj
.treeImage(),
219 data
=wxTreeItemData(xxx
))
220 # Try to find children objects
221 if treeObj
.hasChildren
:
222 nodes
= treeObj
.element
.childNodes
[:]
225 self
.AddNode(item
, treeObj
, n
)
226 elif n
.nodeType
!= minidom
.Node
.ELEMENT_NODE
:
227 treeObj
.element
.removeChild(n
)
231 # Remove leaf of tree, return it's data object
232 def RemoveLeaf(self
, leaf
):
233 xxx
= self
.GetPyData(leaf
)
235 parent
= node
.parentNode
236 parent
.removeChild(node
)
239 #if testWin and self.GetItemAncestor(leaf) == testWin.item:
240 # if testWin.highLight:
241 # testWin.highLight.Remove()
242 # self.needUpdate = true
245 # Find position relative to the top-level window
246 def FindNodePos(self
, item
):
247 itemParent
= self
.GetItemParent(item
)
248 if itemParent
== self
.GetRootItem(): return wxPoint(0, 0)
249 obj
= self
.FindNodeObject(item
)
250 # Find first ancestor which is a wxWindow (not a sizer)
251 winParent
= itemParent
252 while self
.GetPyData(winParent
).isSizer
:
253 winParent
= self
.GetItemParent(winParent
)
254 parentPos
= self
.FindNodePos(winParent
)
255 return parentPos
+ obj
.GetPosition()
257 # Find window (or sizer) corresponding to a tree item.
258 def FindNodeObject(self
, item
):
259 itemParent
= self
.GetItemParent(item
)
260 # If top-level, return testWin (or panel if wxFrame)
261 if itemParent
== self
.GetRootItem(): return testWin
.panel
262 xxx
= self
.GetPyData(item
).treeObject()
263 parentWin
= self
.FindNodeObject(itemParent
)
264 # Top-level sizer? return window's sizer
265 if xxx
.isSizer
and isinstance(parentWin
, wxWindowPtr
):
266 return parentWin
.GetSizer()
267 # Otherwise get parent's object and it's child
268 n
= 0 # index of sibling
269 prev
= self
.GetPrevSibling(item
)
271 prev
= self
.GetPrevSibling(prev
)
273 child
= parentWin
.GetChildren()[n
]
274 # Return window or sizer for sizer items
275 if child
.GetClassName() == 'wxSizerItem':
276 if child
.IsWindow(): child
= child
.GetWindow()
277 elif child
.IsSizer():
278 child
= child
.GetSizer()
279 # Test for notebook sizers
280 if isinstance(child
, wxNotebookSizerPtr
):
281 child
= child
.GetNotebook()
284 def OnSelChanged(self
, evt
):
286 # !!! problem with wxGTK
287 #oldItem = evt.GetOldItem()
288 oldItem
= self
.selection
290 xxx
= self
.GetPyData(oldItem
)
291 # If some data was modified, apply changes
293 if panel
.IsModified():
294 self
.Apply(xxx
, oldItem
)
295 #if conf.autoRefresh:
296 if testWin
and testWin
.highLight
:
297 testWin
.highLight
.Remove()
298 self
.needUpdate
= true
301 self
.selection
= item
# !!! fix
302 xxx
= self
.GetPyData(item
)
304 # List of parameters tuples (parameter, isDefined)
305 if not xxx
: # root item
306 html
+= 'this item has no properties' + htmlFooter
308 if testWin
and testWin
.highLight
:
309 testWin
.highLight
.Remove()
312 ClearRegister() # empty register
313 html
+= xxx
.generateHtml()
316 # Set values, checkboxes to false, disable defaults
317 if xxx
.hasChild
: prefix
= '_'
319 for param
in xxx
.allParams
:
320 if xxx
.params
.has_key(param
):
321 if param
== 'content':
323 for text
in xxx
.params
[param
]:
324 value
.append(str(text
.data
)) # convert from unicode
326 value
= xxx
.params
[param
].data
327 GetRegistered(prefix
+ param
).SetValue(value
)
328 if not param
in xxx
.required
:
329 panel
.FindWindowByName('check_' + param
).SetValue(true
)
331 GetRegistered(prefix
+ param
).Enable(false
)
332 # Same for the child of sizeritem
335 for param
in xxx
.allParams
:
336 if xxx
.params
.has_key(param
):
337 if param
== 'content':
339 for text
in xxx
.params
[param
]:
340 value
.append(str(text
.data
)) # convert from unicode
342 value
= xxx
.params
[param
].data
343 GetRegistered(param
).SetValue(value
)
344 if not param
in xxx
.required
:
345 panel
.FindWindowByName('check_' + param
).SetValue(true
)
347 GetRegistered(param
).Enable(false
)
349 panel
.SetModified(false
)
350 # Hightlighting is done in OnIdle
351 tree
.pendingHighLight
= item
353 # Find top-level parent
354 def GetItemAncestor(self
, item
):
355 while self
.GetItemParent(item
) != self
.GetRootItem():
356 item
= self
.GetItemParent(item
)
359 # Highlight selected item
360 def HighLight(self
, item
):
361 self
.pendingHighLight
= None
362 if not testWin
or self
.GetPyData(testWin
.item
).className \
363 not in ['wxDialog', 'wxPanel', 'wxFrame']:
365 # Top-level does not have highlight
366 if item
== testWin
.item
:
367 if testWin
.highLight
: testWin
.highLight
.Remove()
369 # If a control from another window is selected, remove highlight
370 if self
.GetItemAncestor(item
) != testWin
.item
and testWin
.highLight
:
371 testWin
.highLight
.Remove()
373 # Get window/sizer object
374 obj
, pos
= self
.FindNodeObject(item
), self
.FindNodePos(item
)
376 # For notebook, select item's page.
377 # For children of page, nothing happens (too much work)
378 if isinstance(self
.GetPyData(item
).parent
, xxxNotebook
):
379 notebook
= self
.FindNodeObject(self
.GetItemParent(item
))
382 prev
= self
.GetPrevSibling(item
)
385 prev
= self
.GetPrevSibling(prev
)
386 notebook
.SetSelection(n
)
388 try: # finally I use exceptions
389 testWin
.highLight
.Replace(pos
, size
)
390 except AttributeError:
391 testWin
.highLight
= HightLightBox(pos
, size
)
392 testWin
.highLight
.item
= item
395 def OnItemActivated(self
, evt
):
397 xxx
= self
.GetPyData(item
)
398 if not xxx
: return # if root selected, do nothing
399 if panel
.IsModified():
400 self
.Apply(xxx
, item
) # apply changes
401 self
.CreateTestWin(item
)
403 # (re)create test window
404 def CreateTestWin(self
, node
):
406 # Create a window with this resource
407 xxx
= self
.GetPyData(node
).treeObject()
408 if not xxx
: return # if root selected, do nothing
409 # If noname element, display error
410 if not xxx
.hasName
or not xxx
.name
:
411 wxLogError("Can't display a noname element")
413 # Close old window, remember where it was
416 pos
= testWin
.GetPosition()
417 if node
== testWin
.item
:
418 # Remember highlight if same top-level window
419 if testWin
.highLight
:
420 highLight
= testWin
.highLight
.item
421 # !!! if 0 is removed, refresh is broken (notebook not deleted?)
422 if 0 and xxx
.className
== 'wxPanel':
423 if testWin
.highLight
:
424 testWin
.pendingHighLight
= highLight
425 testWin
.highLight
.Remove()
426 testWin
.panel
.Destroy()
436 # Save in temporary file before activating
437 memFile
= MemoryFile(tempfile
.mktemp('xrc'))
438 #memFile = MemoryFile('core.xrc') # to write debug file
439 # Create partial XML file - faster for big files
441 dom
= minidom
.Document()
442 mainNode
= dom
.createElement('resource')
443 dom
.appendChild(mainNode
)
445 # Remove temporarily from old parent
447 parent
= elem
.parentNode
448 next
= elem
.nextSibling
449 parent
.replaceChild(self
.dummyNode
, elem
)
450 # Append to new DOM, write it
451 mainNode
.appendChild(elem
)
452 dom
.writexml(memFile
)
454 mainNode
.removeChild(elem
)
456 parent
.replaceChild(elem
, self
.dummyNode
)
458 memFile
.close() # write to wxMemoryFS
459 res
= wxXmlResource('')
460 res
.Load(memFile
.name
)
461 if xxx
.className
== 'wxFrame':
463 testWin
= wxPreFrame()
464 res
.LoadFrame(testWin
, frame
, xxx
.name
)
465 testWin
.panel
= testWin
466 testWin
.SetPosition(pos
)
468 elif xxx
.className
== 'wxPanel':
471 testWin
= wxFrame(frame
, -1, 'Panel: ' + xxx
.name
, pos
=pos
)
472 testWin
.panel
= res
.LoadPanel(testWin
, xxx
.name
)
473 testWin
.SetSize(testWin
.panel
.GetSize())
475 elif xxx
.className
== 'wxDialog':
477 testWin
= res
.LoadDialog(None, xxx
.name
)
478 testWin
.panel
= testWin
479 testWin
.SetPosition(pos
)
481 elif xxx
.className
== 'wxMenuBar':
482 testWin
= wxFrame(frame
, -1, 'MenuBar: ' + xxx
.name
, pos
=pos
)
483 # Set status bar to display help
484 testWin
.CreateStatusBar()
485 testWin
.menuBar
= res
.LoadMenuBar(xxx
.name
)
486 testWin
.SetMenuBar(testWin
.menuBar
)
489 wxLogMessage('No view for this element yet')
491 os
.unlink(memFile
.name
) # remove tmp file
493 testWin
.Connect(testWin
.GetId(), -1, wxEVT_CLOSE_WINDOW
, self
.OnCloseTestWin
)
494 testWin
.highLight
= None
495 if highLight
and not tree
.pendingHighLight
:
496 self
.HighLight(highLight
)
498 def OnCloseTestWin(self
, evt
):
499 global testWin
, testWinPos
500 testWinPos
= testWin
.GetPosition()
505 # True if next item should be inserted after current (vs. appended to it)
506 def NeedInsert(self
, item
):
507 xxx
= self
.GetPyData(item
)
508 if not xxx
: return false
# root item
509 if self
.ctrl
: return true
# if Ctrl pressed, always insert
510 if xxx
.hasChildren
and not self
.ItemHasChildren(item
):
512 return not (self
.IsExpanded(item
) and self
.ItemHasChildren(item
))
515 def OnRightDown(self
, evt
):
517 pullDownMenu
.menu
= wxMenu()
518 item
= self
.GetSelection()
520 pullDownMenu
.menu
.Append(pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand tree')
522 self
.ctrl
= evt
.ControlDown() # save Ctrl state
523 m
= wxMenu() # create menu
524 if item
!= self
.GetRootItem(): needInsert
= self
.NeedInsert(item
)
525 if item
== self
.GetRootItem() or \
526 self
.GetItemParent(item
) == self
.GetRootItem() and needInsert
:
527 m
.Append(pullDownMenu
.ID_NEW_PANEL
, 'Panel', 'Create panel')
528 m
.Append(pullDownMenu
.ID_NEW_DIALOG
, 'Dialog', 'Create dialog')
529 m
.Append(pullDownMenu
.ID_NEW_FRAME
, 'Frame', 'Create frame')
531 m
.Append(pullDownMenu
.ID_NEW_MENU_BAR
, 'MenuBar', 'Create menu bar')
532 m
.Append(pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu')
534 xxx
= self
.GetPyData(item
)
535 if xxx
.__class
__ == xxxMenuBar
:
536 m
.Append(pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu')
537 elif xxx
.__class
__ in [xxxMenu
, xxxMenuItem
]:
538 SetMenu(m
, pullDownMenu
.menuControls
)
540 SetMenu(m
, pullDownMenu
.controls
)
541 if not (xxx
.isSizer
or \
542 xxx
.parent
and xxx
.parent
.isSizer
):
543 m
.Enable(pullDownMenu
.ID_NEW_SPACER
, false
)
544 # Select correct label for create menu
545 if item
== self
.GetRootItem():
546 pullDownMenu
.menu
.AppendMenu(wxNewId(), 'Create', m
, 'Create top-level object')
549 pullDownMenu
.menu
.AppendMenu(wxNewId(), 'Create child', m
,
550 'Create child object')
552 pullDownMenu
.menu
.AppendMenu(wxNewId(), 'Create Sibling', m
,
553 'Create sibling of selected object')
554 pullDownMenu
.menu
.AppendSeparator()
555 pullDownMenu
.menu
.Append(wxID_CUT
, 'Cut', 'Cut to the clipboard')
556 pullDownMenu
.menu
.Append(wxID_COPY
, 'Copy', 'Copy to the clipboard')
557 pullDownMenu
.menu
.Append(wxID_PASTE
, 'Paste', 'Paste from the clipboard')
558 pullDownMenu
.menu
.Append(pullDownMenu
.ID_DELETE
,
559 'Delete', 'Delete object')
560 if item
.IsOk() and self
.ItemHasChildren(item
):
561 pullDownMenu
.menu
.AppendSeparator()
562 pullDownMenu
.menu
.Append(pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand subtree')
563 self
.PopupMenu(pullDownMenu
.menu
, evt
.GetPosition())
564 pullDownMenu
.menu
.Destroy()
565 pullDownMenu
.menu
= None
570 self
.DeleteAllItems()
571 # Add minimal structure
572 root
= self
.AddRoot('XML tree')
574 if self
.dom
: self
.dom
.unlink()
575 self
.dom
= minidom
.Document()
576 self
.dummyNode
= self
.dom
.createComment('dummy node')
578 self
.mainNode
= self
.dom
.createElement('resource')
579 self
.dom
.appendChild(self
.mainNode
)
582 def Apply(self
, xxx
, item
):
585 if xxx
.undo
: xxx
.undo
.unlink()
586 xxx
.undo
= xxx
.element
.cloneNode(false
)
588 name
= GetRegistered('name').GetValue()
591 xxx
.element
.setAttribute('name', name
)
592 self
.SetItemText(item
, xxx
.treeName())
593 if xxx
.hasChild
: prefix
= '_'
595 for param
, data
in xxx
.params
.items():
596 value
= GetRegistered(prefix
+ param
).GetValue()
597 if param
== 'content':
598 # If number if items is not the same, recreate children
599 if len(value
) != len(data
):
600 elem
= xxx
.element
.getElementsByTagName('content')[0]
601 for n
in elem
.childNodes
:
605 itemElem
= tree
.dom
.createElement('item')
606 itemText
= tree
.dom
.createTextNode(str)
607 itemElem
.appendChild(itemText
)
608 elem
.appendChild(itemElem
)
609 data
.append(itemText
)
610 xxx
.params
[param
] = data
612 for i
in range(len(value
)):
613 data
[i
].data
= value
[i
]
617 self
.Apply(xxx
.child
, item
)
619 # Change tree icon for sizers
620 if isinstance(xxx
, xxxBoxSizer
):
621 self
.SetItemImage(item
, xxx
.treeImage())
622 # Set global modified state
623 frame
.modified
= true
625 class Frame(wxFrame
):
626 def __init__(self
, size
):
627 wxFrame
.__init
__(self
, None, -1, '', size
=size
)
628 self
.CreateStatusBar()
631 menuBar
= wxMenuBar()
634 menu
.Append(wxID_NEW
, '&New\tCtrl-N', 'New file')
635 menu
.Append(wxID_OPEN
, '&Open...\tCtrl-O', 'Open XRC file')
636 menu
.Append(wxID_SAVE
, '&Save\tCtrl-S', 'Save XRC file')
637 menu
.Append(wxID_SAVEAS
, 'Save &As...', 'Save XRC file under different name')
638 menu
.AppendSeparator()
639 menu
.Append(wxID_EXIT
, '&Quit\tCtrl-Q', 'Exit application')
640 menuBar
.Append(menu
, '&File')
643 menu
.Append(wxID_UNDO
, '&Undo\tCtrl-Z', 'Undo')
644 menu
.Append(wxID_REDO
, '&Redo\tCtrl-R', 'Redo')
645 menu
.AppendSeparator()
646 menu
.Append(wxID_CUT
, 'Cut\tCtrl-X', 'Cut to the clipboard')
647 menu
.Append(wxID_COPY
, '&Copy\tCtrl-C', 'Copy to the clipboard')
648 menu
.Append(wxID_PASTE
, '&Paste\tCtrl-V', 'Paste from the clipboard')
649 self
.ID_DELETE
= wxNewId()
650 menu
.Append(self
.ID_DELETE
, '&Delete\tCtrl-D', 'Delete object')
651 menuBar
.Append(menu
, '&Edit')
654 self
.ID_REFRESH
= wxNewId()
655 menu
.Append(self
.ID_REFRESH
, '&Refresh\tCtrl-R', 'Refresh view')
656 self
.ID_AUTO_REFRESH
= wxNewId()
657 menu
.Append(self
.ID_AUTO_REFRESH
, '&Auto-refresh\tCtrl-A',
658 'Toggle auto-refresh mode', true
)
659 menu
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
660 menuBar
.Append(menu
, '&View')
663 menu
.Append(wxID_ABOUT
, 'About...', 'About XCRed')
665 self
.ID_DEBUG_CMD
= wxNewId()
666 menu
.Append(self
.ID_DEBUG_CMD
, 'CMD', 'Python command line')
667 EVT_MENU(self
, self
.ID_DEBUG_CMD
, self
.OnDebugCMD
)
668 menuBar
.Append(menu
, '&Help')
670 self
.menuBar
= menuBar
671 self
.SetMenuBar(menuBar
)
674 tb
= self
.CreateToolBar()#wxTB_DOCKABLE | wxTB_FLAT)
675 tb
.SetToolBitmapSize((24,23))
676 tb
.AddSimpleTool(wxID_NEW
, images
.getNewBitmap(), 'New', 'New file')
677 tb
.AddSimpleTool(wxID_OPEN
, images
.getOpenBitmap(), 'Open', 'Open file')
678 tb
.AddSimpleTool(wxID_SAVE
, images
.getSaveBitmap(), 'Save', 'Save file')
680 tb
.AddSimpleTool(wxID_CUT
, images
.getCutBitmap(), 'Cut', 'Cut')
681 tb
.AddSimpleTool(wxID_COPY
, images
.getCopyBitmap(), 'Copy', 'Copy')
682 tb
.AddSimpleTool(wxID_PASTE
, images
.getPasteBitmap(), 'Paste', 'Paste')
684 tb
.AddSimpleTool(self
.ID_REFRESH
, images
.getRefreshBitmap(),
685 'Refresh', 'Refresh view')
686 tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, images
.getAutoRefreshBitmap(),
687 'Auto-refresh', 'Toggle auto-refresh mode', true
)
688 tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
693 EVT_MENU(self
, wxID_NEW
, self
.OnNew
)
694 EVT_MENU(self
, wxID_OPEN
, self
.OnOpen
)
695 EVT_MENU(self
, wxID_SAVE
, self
.OnSaveOrSaveAs
)
696 EVT_MENU(self
, wxID_SAVEAS
, self
.OnSaveOrSaveAs
)
697 EVT_MENU(self
, wxID_EXIT
, self
.OnExit
)
699 EVT_MENU(self
, wxID_UNDO
, self
.OnUndo
)
700 EVT_MENU(self
, wxID_REDO
, self
.OnRedo
)
701 EVT_MENU(self
, wxID_CUT
, self
.OnCut
)
702 EVT_MENU(self
, wxID_COPY
, self
.OnCopy
)
703 EVT_MENU(self
, wxID_PASTE
, self
.OnPaste
)
704 EVT_MENU(self
, self
.ID_DELETE
, self
.OnDelete
)
706 EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
)
707 EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
)
709 EVT_MENU(self
, wxID_ABOUT
, self
.OnAbout
)
712 EVT_UPDATE_UI(self
, wxID_CUT
, self
.OnUpdateUI
)
713 EVT_UPDATE_UI(self
, wxID_COPY
, self
.OnUpdateUI
)
714 EVT_UPDATE_UI(self
, wxID_PASTE
, self
.OnUpdateUI
)
715 EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
)
718 splitter
= wxSplitterWindow(self
, -1)
721 tree
= XML_Tree(splitter
, -1)
722 sys
.modules
['xxx'].tree
= tree
723 # Create panel for parameters
725 #panel = wxPanel(self, -1)
726 # Sizer for static box
727 #sizer = wxBoxSizer()
728 panel
= Panel(splitter
, -1)
729 sys
.modules
['params'].panel
= panel
730 #sizer.Add(panel, 1, wxEXPAND)
731 #box = wxStaticBox(panel, -1, 'Parameters')
732 #boxSizer = wxStaticBoxSizer(box)
733 #boxSizer.Add(wxButton(panel, -1, 'BUTT ON'))
734 #sizer.Add(boxSizer, 1, wxEXPAND | wxALL, 10)
735 #panel.SetAutoLayout(true)
736 #panel.SetSizer(sizer)
737 # Set plitter windows
738 splitter
.SplitVertically(tree
, panel
, 200)
739 #topSizer = wxBoxSizer()
740 #topSizer.Add(splitter, 1, wxEXPAND)
741 #self.SetAutoLayout(true)
742 #self.SetSizer(topSizer)
744 # Init pull-down menu data
747 pullDownMenu
= MenuData()
748 pullDownMenu
.menu
= None
749 pullDownMenu
.ID_NEW_PANEL
= wxNewId()
750 pullDownMenu
.ID_NEW_DIALOG
= wxNewId()
751 pullDownMenu
.ID_NEW_FRAME
= wxNewId()
752 pullDownMenu
.ID_NEW_MENU_BAR
= wxNewId()
753 pullDownMenu
.ID_NEW_MENU
= wxNewId()
755 pullDownMenu
.ID_NEW_STATIC_TEXT
= wxNewId()
756 pullDownMenu
.ID_NEW_TEXT_CTRL
= wxNewId()
758 pullDownMenu
.ID_NEW_BUTTON
= wxNewId()
759 pullDownMenu
.ID_NEW_BITMAP_BUTTON
= wxNewId()
760 pullDownMenu
.ID_NEW_RADIO_BUTTON
= wxNewId()
761 pullDownMenu
.ID_NEW_SPIN_BUTTON
= wxNewId()
763 pullDownMenu
.ID_NEW_STATIC_BOX
= wxNewId()
764 pullDownMenu
.ID_NEW_CHECK_BOX
= wxNewId()
765 pullDownMenu
.ID_NEW_RADIO_BOX
= wxNewId()
766 pullDownMenu
.ID_NEW_COMBO_BOX
= wxNewId()
767 pullDownMenu
.ID_NEW_LIST_BOX
= wxNewId()
769 pullDownMenu
.ID_NEW_STATIC_LINE
= wxNewId()
770 pullDownMenu
.ID_NEW_CHOICE
= wxNewId()
771 pullDownMenu
.ID_NEW_SLIDER
= wxNewId()
772 pullDownMenu
.ID_NEW_GAUGE
= wxNewId()
773 pullDownMenu
.ID_NEW_SCROLL_BAR
= wxNewId()
774 pullDownMenu
.ID_NEW_TREE_CTRL
= wxNewId()
775 pullDownMenu
.ID_NEW_LIST_CTRL
= wxNewId()
776 pullDownMenu
.ID_NEW_CHECK_LIST
= wxNewId()
777 pullDownMenu
.ID_NEW_NOTEBOOK
= wxNewId()
778 pullDownMenu
.ID_NEW_HTML_WINDOW
= wxNewId()
779 pullDownMenu
.ID_NEW_CALENDAR
= wxNewId()
781 pullDownMenu
.ID_NEW_BOX_SIZER
= wxNewId()
782 pullDownMenu
.ID_NEW_STATIC_BOX_SIZER
= wxNewId()
783 pullDownMenu
.ID_NEW_GRID_SIZER
= wxNewId()
784 pullDownMenu
.ID_NEW_FLEX_GRID_SIZER
= wxNewId()
785 pullDownMenu
.ID_NEW_SPACER
= wxNewId()
786 pullDownMenu
.ID_NEW_MENU
= wxNewId()
787 pullDownMenu
.ID_NEW_MENU_ITEM
= wxNewId()
788 pullDownMenu
.ID_NEW_SEPARATOR
= wxNewId()
789 pullDownMenu
.ID_NEW_LAST
= wxNewId()
790 pullDownMenu
.ID_DELETE
= self
.ID_DELETE
791 pullDownMenu
.ID_EXPAND
= wxNewId()
792 EVT_MENU_RANGE(self
, pullDownMenu
.ID_NEW_PANEL
,
793 pullDownMenu
.ID_NEW_LAST
, self
.OnCreate
)
794 EVT_MENU(self
, pullDownMenu
.ID_EXPAND
, self
.OnExpand
)
795 # We connect to tree, but process in frame
796 EVT_MENU_HIGHLIGHT_ALL(tree
, self
.OnPullDownHighlight
)
797 # Mapping from IDs to element names
799 pullDownMenu
.ID_NEW_PANEL
: 'wxPanel',
800 pullDownMenu
.ID_NEW_DIALOG
: 'wxDialog',
801 pullDownMenu
.ID_NEW_FRAME
: 'wxFrame',
802 pullDownMenu
.ID_NEW_MENU_BAR
: 'wxMenuBar',
803 pullDownMenu
.ID_NEW_MENU
: 'wxMenu',
805 pullDownMenu
.ID_NEW_STATIC_TEXT
: 'wxStaticText',
806 pullDownMenu
.ID_NEW_TEXT_CTRL
: 'wxTextCtrl',
808 pullDownMenu
.ID_NEW_BUTTON
: 'wxButton',
809 pullDownMenu
.ID_NEW_BITMAP_BUTTON
: 'wxBitmapButton',
810 pullDownMenu
.ID_NEW_RADIO_BUTTON
: 'wxRadioButton',
811 pullDownMenu
.ID_NEW_SPIN_BUTTON
: 'wxSpinButton',
813 pullDownMenu
.ID_NEW_STATIC_BOX
: 'wxStaticBox',
814 pullDownMenu
.ID_NEW_CHECK_BOX
: 'wxCheckBox',
815 pullDownMenu
.ID_NEW_RADIO_BOX
: 'wxRadioBox',
816 pullDownMenu
.ID_NEW_COMBO_BOX
: 'wxComboBox',
817 pullDownMenu
.ID_NEW_LIST_BOX
: 'wxListBox',
819 pullDownMenu
.ID_NEW_STATIC_LINE
: 'wxStaticLine',
820 pullDownMenu
.ID_NEW_CHOICE
: 'wxChoice',
821 pullDownMenu
.ID_NEW_SLIDER
: 'wxSlider',
822 pullDownMenu
.ID_NEW_GAUGE
: 'wxGauge',
823 pullDownMenu
.ID_NEW_SCROLL_BAR
: 'wxScrollBar',
824 pullDownMenu
.ID_NEW_TREE_CTRL
: 'wxTreeCtrl',
825 pullDownMenu
.ID_NEW_LIST_CTRL
: 'wxListCtrl',
826 pullDownMenu
.ID_NEW_CHECK_LIST
: 'wxCheckList',
827 pullDownMenu
.ID_NEW_NOTEBOOK
: 'wxNotebook',
828 pullDownMenu
.ID_NEW_HTML_WINDOW
: 'wxHtmlWindow',
829 pullDownMenu
.ID_NEW_CALENDAR
: 'wxCalendar',
831 pullDownMenu
.ID_NEW_BOX_SIZER
: 'wxBoxSizer',
832 pullDownMenu
.ID_NEW_STATIC_BOX_SIZER
: 'wxStaticBoxSizer',
833 pullDownMenu
.ID_NEW_GRID_SIZER
: 'wxGridSizer',
834 pullDownMenu
.ID_NEW_FLEX_GRID_SIZER
: 'wxFlexGridSizer',
835 pullDownMenu
.ID_NEW_SPACER
: 'spacer',
836 pullDownMenu
.ID_NEW_MENU
: 'wxMenu',
837 pullDownMenu
.ID_NEW_MENU_ITEM
: 'wxMenuItem',
838 pullDownMenu
.ID_NEW_SEPARATOR
: 'separator',
840 pullDownMenu
.controls
= [
841 ['control', 'Various controls',
842 (pullDownMenu
.ID_NEW_STATIC_TEXT
, 'Label', 'Create static label'),
843 (pullDownMenu
.ID_NEW_STATIC_LINE
, 'Line', 'Create static line'),
844 (pullDownMenu
.ID_NEW_TEXT_CTRL
, 'TextBox', 'Create text box control'),
845 (pullDownMenu
.ID_NEW_CHOICE
, 'Choice', 'Create choice control'),
846 (pullDownMenu
.ID_NEW_SLIDER
, 'Slider', 'Create slider control'),
847 (pullDownMenu
.ID_NEW_GAUGE
, 'Gauge', 'Create gauge control'),
848 (pullDownMenu
.ID_NEW_SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'),
849 (pullDownMenu
.ID_NEW_TREE_CTRL
, 'TreeCtrl', 'Create tree control'),
850 (pullDownMenu
.ID_NEW_LIST_CTRL
, 'ListCtrl', 'Create list control'),
851 (pullDownMenu
.ID_NEW_CHECK_LIST
, 'CheckList', 'Create check list control'),
852 (pullDownMenu
.ID_NEW_HTML_WINDOW
, 'HtmlWindow', 'Create HTML window'),
853 (pullDownMenu
.ID_NEW_CALENDAR
, 'Calendar', 'Create calendar control'),
854 (pullDownMenu
.ID_NEW_PANEL
, 'Panel', 'Create panel'),
855 (pullDownMenu
.ID_NEW_NOTEBOOK
, 'Notebook', 'Create notebook control'),
857 ['button', 'Buttons',
858 (pullDownMenu
.ID_NEW_BUTTON
, 'Button', 'Create button'),
859 (pullDownMenu
.ID_NEW_BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'),
860 (pullDownMenu
.ID_NEW_RADIO_BUTTON
, 'RadioButton', 'Create radio button'),
861 (pullDownMenu
.ID_NEW_SPIN_BUTTON
, 'SpinButton', 'Create spin button'),
864 (pullDownMenu
.ID_NEW_STATIC_BOX
, 'StaticBox', 'Create static box'),
865 (pullDownMenu
.ID_NEW_CHECK_BOX
, 'CheckBox', 'Create check box'),
866 (pullDownMenu
.ID_NEW_RADIO_BOX
, 'RadioBox', 'Create radio box'),
867 (pullDownMenu
.ID_NEW_COMBO_BOX
, 'ComboBox', 'Create combo box'),
868 (pullDownMenu
.ID_NEW_LIST_BOX
, 'ListBox', 'Create list box'),
871 (pullDownMenu
.ID_NEW_BOX_SIZER
, 'BoxSizer', 'Create box sizer'),
872 (pullDownMenu
.ID_NEW_STATIC_BOX_SIZER
, 'StaticBoxSizer',
873 'Create static box sizer'),
874 (pullDownMenu
.ID_NEW_GRID_SIZER
, 'GridSizer', 'Create grid sizer'),
875 (pullDownMenu
.ID_NEW_FLEX_GRID_SIZER
, 'FlexGridSizer',
876 'Create flexgrid sizer'),
877 (pullDownMenu
.ID_NEW_SPACER
, 'Spacer', 'Create spacer'),
880 pullDownMenu
.menuControls
= [
881 (pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu'),
882 (pullDownMenu
.ID_NEW_MENU_ITEM
, 'MenuItem', 'Create menu item'),
883 (pullDownMenu
.ID_NEW_SEPARATOR
, 'Separator', 'Create separator'),
890 EVT_IDLE(self
, self
.OnIdle
)
891 EVT_CLOSE(self
, self
.OnCloseWindow
)
893 def OnNew(self
, evt
):
896 def OnOpen(self
, evt
):
897 if not self
.AskSave(): return
898 dlg
= wxFileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
899 '', '*.xrc', wxOPEN | wxCHANGE_DIR
)
900 if dlg
.ShowModal() == wxID_OK
:
902 self
.SetStatusText('Loading...')
907 self
.SetStatusText('Ready')
910 def OnSaveOrSaveAs(self
, evt
):
911 if evt
.GetId() == wxID_SAVEAS
or not self
.dataFile
:
912 if self
.dataFile
: defaultName
= ''
913 else: defaultName
= 'UNTITLED.xrc'
914 dlg
= wxFileDialog(self
, 'Save As', os
.path
.dirname(self
.dataFile
),
915 defaultName
, '*.xrc',
916 wxSAVE | wxOVERWRITE_PROMPT | wxCHANGE_DIR
)
917 if dlg
.ShowModal() == wxID_CANCEL
: return
922 self
.SetStatusText('Saving...')
928 self
.SetStatusText('Ready')
930 def OnExit(self
, evt
):
933 def OnUndo(self
, evt
):
934 print '*** being implemented'
935 print self
.lastOp
, self
.undo
936 if self
.lastOp
== 'DELETE':
937 parent
, prev
, elem
= self
.undo
939 xxx
= MakeXXXFromDOM(tree
.GetPyData(parent
).treeObject(), elem
)
940 item
= tree
.InsertItem( parent
, prev
, xxx
.treeObject().className
,
941 data
=wxTreeItemData(xxx
) )
943 def OnRedo(self
, evt
):
944 print '*** being implemented'
946 def OnCut(self
, evt
):
947 selected
= tree
.GetSelection()
950 self
.undo
= [tree
.GetItemParent(selected
), tree
.GetPrevSibling(selected
)]
954 # If deleting top-level item, delete testWin
955 if selected
== testWin
.item
:
959 # Remove highlight, update testWin
960 if tree
.GetItemAncestor(selected
) == testWin
.item
:
961 if testWin
.highLight
: testWin
.highLight
.Remove()
962 tree
.needUpdate
= true
963 self
.clipboard
= tree
.RemoveLeaf(selected
)
964 tree
.pendingHighLight
= None
969 def OnCopy(self
, evt
):
970 selected
= tree
.GetSelection()
971 xxx
= tree
.GetPyData(selected
)
972 self
.clipboard
= xxx
.element
.cloneNode(true
)
974 def OnPaste(self
, evt
):
975 selected
= tree
.GetSelection()
976 appendChild
= not tree
.NeedInsert(selected
)
977 xxx
= tree
.GetPyData(selected
)
979 # If has next item, insert, else append to parent
980 nextItem
= tree
.GetNextSibling(selected
)
982 # Insert before nextItem
983 parentLeaf
= tree
.GetItemParent(selected
)
984 else: # last child: change selected to parent
986 selected
= tree
.GetItemParent(selected
)
987 # Expanded container (must have children)
988 elif tree
.IsExpanded(selected
) and tree
.ItemHasChildren(selected
):
990 nextItem
= tree
.GetFirstChild(selected
, 0)[0]
991 parentLeaf
= selected
992 # Parent should be tree element or None
994 parent
= tree
.GetPyData(selected
)
996 parent
= tree
.GetPyData(parentLeaf
)
997 if parent
and parent
.hasChild
: parent
= parent
.child
999 # Create a copy of clipboard element
1000 elem
= self
.clipboard
.cloneNode(true
)
1001 # Tempopary xxx object to test things
1002 xxx
= MakeXXXFromDOM(parent
, elem
)
1003 className
= xxx
.treeObject().className
1004 # Check parent and child relationships
1005 # Parent is sizer or notebook, child is of wrong class or
1006 # parent is normal window, child is child container: detach child
1007 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
1008 if not parent
and isChildContainer
or \
1009 (parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
1010 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
1011 (not parent
.isSizer
and not isinstance(parent
, xxxNotebook
) and \
1013 if isChildContainer
:
1014 elem
.removeChild(xxx
.child
.element
) # detach child
1015 elem
.unlink() # delete child container
1016 elem
= xxx
.child
.element
# replace
1017 # This should help garbage collection (!!! maybe not needed?)
1018 xxx
.child
.parent
= None
1021 # Parent is sizer or notebook, child is not child container
1022 if parent
.isSizer
and not isChildContainer
and \
1023 not isinstance(xxx
, xxxSpacer
):
1024 # Create sizer item element
1025 sizerItemElem
= MakeEmptyDOM('sizeritem')
1026 sizerItemElem
.appendChild(elem
)
1027 elem
= sizerItemElem
1028 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
1029 pageElem
= MakeEmptyDOM('notebookpage')
1030 pageElem
.appendChild(elem
)
1032 xxx
= MakeXXXFromDOM(parent
, elem
)
1033 # Figure out if we must append a new child or sibling
1035 if parent
: node
= parent
.element
1036 else: node
= tree
.mainNode
1037 node
.appendChild(elem
)
1038 newItem
= tree
.AppendItem(selected
, xxx
.treeName(), image
=xxx
.treeImage(),
1039 data
=wxTreeItemData(xxx
))
1041 node
= tree
.GetPyData(nextItem
).element
1043 elemParent
= parent
.element
1045 elemParent
= tree
.mainNode
1046 elemParent
.insertBefore(elem
, node
)
1047 # Inserting before is difficult, se we insert after or first child
1048 newItem
= tree
.InsertItem(parentLeaf
, selected
, xxx
.treeName(),
1049 image
=xxx
.treeImage(), data
=wxTreeItemData(xxx
))
1050 # Add children items
1052 treeObj
= xxx
.treeObject()
1053 for n
in treeObj
.element
.childNodes
:
1055 tree
.AddNode(newItem
, treeObj
, n
)
1056 # Scroll to show new item
1057 tree
.EnsureVisible(newItem
)
1058 tree
.SelectItem(newItem
)
1059 if not tree
.IsVisible(newItem
):
1060 tree
.ScrollTo(newItem
)
1063 if testWin
and tree
.GetItemAncestor(newItem
) == testWin
.item
:
1064 if conf
.autoRefresh
:
1065 tree
.needUpdate
= true
1066 tree
.pendingHighLight
= newItem
1068 tree
.pendingHighLight
= None
1069 self
.modified
= true
1071 def OnDelete(self
, evt
):
1072 selected
= tree
.GetSelection()
1074 self
.lastOp
= 'DELETE'
1075 self
.undo
= [tree
.GetItemParent(selected
), tree
.GetPrevSibling(selected
)]
1079 # If deleting top-level item, delete testWin
1080 if selected
== testWin
.item
:
1084 # Remove highlight, update testWin
1085 if tree
.GetItemAncestor(selected
) == testWin
.item
:
1086 if testWin
.highLight
: testWin
.highLight
.Remove()
1087 tree
.needUpdate
= true
1088 xnode
= tree
.RemoveLeaf(selected
)
1089 self
.undo
.append(xnode
.cloneNode(true
))
1091 tree
.pendingHighLight
= None
1094 self
.modified
= true
1096 def OnRefresh(self
, evt
):
1097 # If modified, apply first
1098 selection
= tree
.GetSelection()
1099 if selection
.IsOk():
1100 xxx
= tree
.GetPyData(selection
)
1101 if xxx
and panel
.IsModified():
1102 tree
.Apply(xxx
, selection
)
1105 tree
.CreateTestWin(testWin
.item
)
1106 tree
.needUpdate
= false
1108 def OnAutoRefresh(self
, evt
):
1109 conf
.autoRefresh
= evt
.IsChecked()
1110 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1111 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1113 def OnAbout(self
, evt
):
1114 dlg
= wxMessageDialog(self
, '%s %s\n\nRoman Rolinsky <rolinsky@mema.ucl.ac.be>' % \
1115 (progname
, version
),
1116 'About %s' % progname
, wxOK | wxCENTRE
)
1120 # Simple emulation of python command line
1121 def OnDebugCMD(self
, evt
):
1124 exec raw_input('C:\> ')
1129 (etype
, value
, tb
) =sys
.exc_info()
1130 tblist
=traceback
.extract_tb(tb
)[1:]
1131 msg
=string
.join(traceback
.format_exception_only(etype
, value
)
1132 +traceback
.format_list(tblist
))
1135 def OnCreate(self
, evt
):
1136 selected
= tree
.GetSelection()
1137 appendChild
= not tree
.NeedInsert(selected
)
1138 xxx
= tree
.GetPyData(selected
)
1140 # If has next item, insert, else append to parent
1141 nextItem
= tree
.GetNextSibling(selected
)
1143 # Insert before nextItem
1144 parentLeaf
= tree
.GetItemParent(selected
)
1145 else: # last child: change selected to parent
1147 selected
= tree
.GetItemParent(selected
)
1148 # Expanded container (must have children)
1149 elif tree
.IsExpanded(selected
) and tree
.ItemHasChildren(selected
):
1151 nextItem
= tree
.GetFirstChild(selected
, 0)[0]
1152 parentLeaf
= selected
1153 # Parent should be tree element or None
1155 parent
= tree
.GetPyData(selected
)
1157 parent
= tree
.GetPyData(parentLeaf
)
1158 if parent
and parent
.hasChild
: parent
= parent
.child
1161 className
= self
.createMap
[evt
.GetId()]
1162 xxx
= MakeEmptyXXX(parent
, className
)
1163 # Figure out if we must append a new child or sibling
1166 if parent
: node
= parent
.element
1167 else: node
= tree
.mainNode
1168 # Insert newline for debug purposes
1169 node
.appendChild(tree
.dom
.createTextNode('\n'))
1170 node
.appendChild(elem
)
1171 newItem
= tree
.AppendItem(selected
, xxx
.treeName(), image
=xxx
.treeImage(),
1172 data
=wxTreeItemData(xxx
))
1174 node
= tree
.GetPyData(nextItem
).element
1176 elemParent
= parent
.element
1178 elemParent
= tree
.mainNode
1179 elemParent
.insertBefore(tree
.dom
.createTextNode('\n'), node
)
1180 elemParent
.insertBefore(elem
, node
)
1181 # Inserting before is difficult, se we insert after or first child
1182 newItem
= tree
.InsertItem(parentLeaf
, selected
,
1183 xxx
.treeName(), image
=xxx
.treeImage(),
1184 data
=wxTreeItemData(xxx
))
1185 tree
.EnsureVisible(newItem
)
1186 tree
.SelectItem(newItem
)
1187 if not tree
.IsVisible(newItem
):
1188 tree
.ScrollTo(newItem
)
1191 if testWin
and tree
.GetItemAncestor(newItem
) == testWin
.item
:
1192 if conf
.autoRefresh
:
1193 tree
.needUpdate
= true
1194 tree
.pendingHighLight
= newItem
1196 tree
.pendingHighLight
= None
1198 def OnExpand(self
, evt
):
1199 if tree
.GetSelection().IsOk():
1200 tree
.ExpandAll(tree
.GetSelection())
1202 tree
.ExpandAll(tree
.GetRootItem())
1204 def OnPullDownHighlight(self
, evt
):
1205 menuId
= evt
.GetMenuId()
1207 if menuId
!= -1: help = pullDownMenu
.GetHelpString(menuId
)
1208 self
.SetStatusText(help)
1210 def OnUpdateUI(self
, evt
):
1211 if evt
.GetId() in [wxID_CUT
, wxID_COPY
, self
.ID_DELETE
]:
1212 enable
= tree
.GetSelection().IsOk() and \
1213 tree
.GetSelection() != tree
.GetRootItem()
1215 elif evt
.GetId() == wxID_PASTE
:
1216 enable
= self
.clipboard
!= None
1219 def OnIdle(self
, evt
):
1221 if conf
.autoRefresh
:
1224 tree
.CreateTestWin(testWin
.item
)
1225 tree
.needUpdate
= false
1226 elif tree
.pendingHighLight
:
1227 tree
.HighLight(tree
.pendingHighLight
)
1230 def OnCloseWindow(self
, evt
):
1231 if not self
.AskSave(): return
1232 if testWin
: testWin
.Destroy()
1233 conf
.width
, conf
.height
= self
.GetSize()
1238 self
.clipboard
= None
1239 self
.modified
= false
1240 panel
.SetModified(false
)
1247 self
.SetTitle(progname
)
1249 def Open(self
, path
):
1250 # Try to read the file
1255 dom
= minidom
.parse(path
)
1257 self
.dataFile
= path
1258 self
.SetTitle(progname
+ ': ' + os
.path
.basename(path
))
1260 wxLogError('Error reading file: ' + path
)
1262 def Save(self
, path
):
1264 memFile
= MemoryFile(path
)
1265 tree
.dom
.writexml(memFile
)
1267 self
.modified
= false
1268 panel
.SetModified(false
)
1270 wxLogError('Error writing file: ' + path
)
1273 if not (self
.modified
or panel
.IsModified()): return true
1274 flags
= wxICON_EXCLAMATION | wxYES_NO | wxCANCEL | wxCENTRE
1275 dlg
= wxMessageDialog( self
, 'File is modified. Save before exit?',
1276 'Save before too late?', flags
)
1277 say
= dlg
.ShowModal()
1280 self
.OnSaveOrSaveAs(wxCommandEvent(wxID_SAVE
))
1281 # If save was successful, modified flag is unset
1282 if not self
.modified
: return true
1283 elif say
== wxID_NO
:
1284 self
.modified
= false
1285 panel
.SetModified(false
)
1291 self
.SetAppName("xrced")
1294 # !!! wxConfigBase_Get doesn't seem to work
1295 conf
= wxConfig(style
=wxCONFIG_USE_LOCAL_FILE
)
1296 conf
.autoRefresh
= conf
.ReadInt('autorefresh', true
)
1297 size
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600)
1299 wxFileSystem_AddHandler(wxMemoryFSHandler())
1300 wxInitAllImageHandlers()
1303 frame
= self
.frame
= Frame(size
)
1304 self
.frame
.Show(true
)
1305 # Load resources from XRC file (!!! should be transformed to .py later)
1306 sys
.modules
['params'].frame
= frame
1307 frame
.res
= wxXmlResource('')
1308 frame
.res
.Load(os
.path
.join(sys
.path
[0], 'xrced.xrc'))
1313 wc
= wxConfigBase_Get()
1314 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1315 wc
.WriteInt('width', conf
.width
)
1316 wc
.WriteInt('height', conf
.height
)
1324 if __name__
== '__main__':