2 # Purpose: XRC editor, main module
3 # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
7 from wxPython
.wx
import *
8 from wxPython
.xrc
import *
9 from wxPython
.html
import *
10 from xml
.dom
import minidom
20 if wxGetOsVersion()[1] == 1:
21 labelFont
= wxFont(12, wxDEFAULT
, wxNORMAL
, wxBOLD
)
23 labelFont
= wxFont(10, wxDEFAULT
, wxNORMAL
, wxBOLD
)
33 testWinPos
= wxDefaultPosition
35 # 1 adds CMD command to Help menu
39 <HTML><H2>Welcome to XRCed!</H2><H3><font color="green">DON'T PANIC :)</font></H3>
40 To start select tree root, then popup menu with your right mouse button,
41 select "Append Child", and then any command.<P>
42 Enter XML ID, change properties, create children.<P>
43 To test your interface select Test command (View menu).<P>
44 Consult README file for the details.</HTML>
47 defaultIDs
= {xxxPanel
:'PANEL', xxxDialog
:'DIALOG', xxxFrame
:'FRAME',
48 xxxMenuBar
:'MENUBAR', xxxMenu
:'MENU', xxxToolBar
:'TOOLBAR'}
50 # Set menu to list items.
51 # Each menu command is a tuple (id, label, help)
52 # submenus are lists [id, label, help, submenu]
53 # and separators are any other type
56 if type(l
) == types
.TupleType
:
58 elif type(l
) == types
.ListType
:
60 SetMenu(subMenu
, l
[2:])
61 m
.AppendMenu(wxNewId(), l
[0], subMenu
, l
[1])
65 ################################################################################
67 # Properties panel containing notebook
68 class Panel(wxNotebook
):
69 def __init__(self
, parent
, id = -1):
70 wxNotebook
.__init
__(self
, parent
, id, style
=wxNB_BOTTOM
)
71 sys
.modules
['params'].panel
= self
72 # List of child windows
74 # Create scrolled windows for pages
75 self
.page1
= wxScrolledWindow(self
, -1)
77 sizer
.Add(wxBoxSizer()) # dummy sizer
78 self
.page1
.SetAutoLayout(true
)
79 self
.page1
.SetSizer(sizer
)
80 self
.AddPage(self
.page1
, 'Properties')
82 self
.page2
= wxScrolledWindow(self
, -1)
84 sizer
.Add(wxBoxSizer()) # dummy sizer
85 self
.page2
.SetAutoLayout(true
)
86 self
.page2
.SetSizer(sizer
)
87 # Cache for already used panels
88 self
.pageCache
= {} # cached property panels
89 self
.stylePageCache
= {} # cached style panels
90 # Dummy parent window for cache pages
91 self
.cacheParent
= wxFrame(None, -1, 'non visible')
92 # Delete child windows and recreate page sizer
93 def ResetPage(self
, page
):
94 topSizer
= page
.GetSizer()
95 sizer
= topSizer
.GetChildren()[0].GetSizer()
96 for w
in page
.GetChildren():
98 if isinstance(w
, ParamPage
):
99 # With SetParent, we wouldn't need this
100 w
.Reparent(self
.cacheParent
)
103 topSizer
.RemoveSizer(sizer
)
105 sizer
= wxBoxSizer(wxVERTICAL
)
106 # Special case - resize html window
108 topSizer
.Add(sizer
, 1, wxEXPAND
)
110 topSizer
.Add(sizer
, 0, wxALL
, 5)
112 def SetData(self
, xxx
):
115 # Set cached or new page
116 # Remove current objects and sizer
117 sizer
= self
.ResetPage(self
.page1
)
118 if not xxx
or (not xxx
.allParams
and not xxx
.hasName
):
120 sizer
.Add(wxStaticText(self
.page1
, -1, 'This item has no properties.'))
121 else: # nothing selected
122 # If first time, show some help
124 html
= wxHtmlWindow(self
.page1
, -1, wxDefaultPosition
,
125 wxDefaultSize
, wxSUNKEN_BORDER
)
126 html
.SetPage(helpText
)
127 sizer
.Add(html
, 1, wxEXPAND
)
130 sizer
.Add(wxStaticText(self
.page1
, -1, 'Select a tree item.'))
132 SetCurrentXXX(xxx
.treeObject())
134 page
= self
.pageCache
[xxx
.__class
__]
135 page
.Reparent(self
.page1
)
137 page
= PropPage(self
.page1
, xxx
.className
, xxx
)
138 self
.pageCache
[xxx
.__class
__] = page
140 self
.pages
.append(page
)
141 sizer
.Add(page
, 1, wxEXPAND
)
143 # Special label for child objects - they may have different GUI
144 cacheID
= (xxx
.child
.__class
__, xxx
.__class
__)
146 page
= self
.pageCache
[cacheID
]
147 page
.Reparent(self
.page1
)
149 page
= PropPage(self
.page1
, xxx
.child
.className
, xxx
.child
)
150 self
.pageCache
[cacheID
] = page
151 page
.SetValues(xxx
.child
)
152 self
.pages
.append(page
)
153 sizer
.Add(page
, 0, wxEXPAND | wxTOP
, 5)
155 size
= self
.page1
.GetSizer().GetMinSize()
156 self
.page1
.SetScrollbars(1, 1, size
.x
, size
.y
, 0, 0, true
)
159 # Create if does not exist
160 if xxx
and xxx
.treeObject().hasStyle
:
161 xxx
= xxx
.treeObject()
162 # Simplest case: set data if class is the same
163 sizer
= self
.ResetPage(self
.page2
)
165 page
= self
.stylePageCache
[xxx
.__class
__]
166 page
.Reparent(self
.page2
)
168 page
= StylePage(self
.page2
, xxx
.className
+ ' style', xxx
)
169 self
.stylePageCache
[xxx
.__class
__] = page
171 self
.pages
.append(page
)
172 sizer
.Add(page
, 0, wxEXPAND
)
173 # Add page if not exists
174 if not self
.GetPageCount() == 2:
175 self
.AddPage(self
.page2
, 'Style')
177 size
= self
.page2
.GetSizer().GetMinSize()
178 self
.page2
.SetScrollbars(1, 1, size
.x
, size
.y
, 0, 0, true
)
180 # Remove page if exists
181 if self
.GetPageCount() == 2:
185 # Check if some parameter on some page has changed
186 def IsModified(self
):
188 if p
.IsModified(): return true
190 # Reset changed state
191 def SetModified(self
, value
):
192 for p
in self
.pages
: p
.SetModified(value
)
194 for p
in self
.pages
: p
.Apply()
196 ################################################################################
198 # General class for notebook pages
199 class ParamPage(wxPanel
):
200 def __init__(self
, parent
, xxx
):
201 wxPanel
.__init
__(self
, parent
, -1)
203 # Register event handlers
204 for id in paramIDs
.values():
205 EVT_CHECKBOX(self
, id, self
.OnCheckParams
)
206 self
.modified
= false
208 self
.controls
= {} # save python objects
209 self
.controlName
= None
210 def OnCheckParams(self
, evt
):
212 param
= evt
.GetEventObject().GetName()
213 w
= self
.controls
[param
]
214 objElem
= xxx
.element
216 # Ad new text node in order of allParams
217 w
.SetValue('') # set empty (default) value
218 w
.SetModified() # mark as changed
219 elem
= tree
.dom
.createElement(param
)
220 xxx
.params
[param
] = xxxParam(elem
)
221 # Find place to put new element: first present element after param
223 paramStyles
= xxx
.allParams
+ xxx
.styles
224 for p
in paramStyles
[paramStyles
.index(param
) + 1:]:
225 # Content params don't have same type
226 if xxx
.params
.has_key(p
) and p
!= 'content':
230 nextTextElem
= xxx
.params
[p
].node
231 objElem
.insertBefore(elem
, nextTextElem
)
233 objElem
.appendChild(elem
)
236 xxx
.params
[param
].remove()
237 del xxx
.params
[param
]
239 w
.modified
= false
# mark as not changed
241 self
.SetModified(true
)
242 w
.Enable(evt
.IsChecked())
243 # If some parameter has changed
244 def IsModified(self
):
246 def SetModified(self
, value
):
247 self
.modified
= value
251 # if xxx.undo: xxx.undo.unlink()
252 # xxx.undo = xxx.element.cloneNode(false)
254 name
= self
.controlName
.GetValue()
257 xxx
.element
.setAttribute('name', name
)
258 for param
, w
in self
.controls
.items():
260 paramObj
= xxx
.params
[param
]
262 if param
in xxx
.specials
:
263 xxx
.setSpecial(param
, value
)
265 paramObj
.update(value
)
267 ################################################################################
269 # Panel for displaying properties
270 class PropPage(ParamPage
):
271 def __init__(self
, parent
, label
, xxx
):
272 ParamPage
.__init
__(self
, parent
, xxx
)
273 box
= wxStaticBox(self
, -1, label
)
274 box
.SetFont(labelFont
)
275 topSizer
= wxStaticBoxSizer(box
, wxVERTICAL
)
276 sizer
= wxFlexGridSizer(len(xxx
.allParams
), 2, 1, 1)
278 label
= wxStaticText(self
, -1, 'XML ID:', size
=(80,-1))
279 control
= ParamText(self
, name
='XML_name')
280 sizer
.AddMany([ (label
, 0, wxALIGN_CENTER_VERTICAL
),
281 (control
, 0, wxALIGN_CENTER_VERTICAL
) ])
282 self
.controlName
= control
283 for param
in xxx
.allParams
:
284 present
= param
in xxx
.params
285 if param
in xxx
.required
:
286 label
= wxStaticText(self
, paramIDs
[param
], param
+ ':',
287 size
= (80,-1), name
= param
)
289 # Notebook has one very loooooong parameter
290 if param
== 'usenotebooksizer': sParam
= 'usesizer:'
291 else: sParam
= param
+ ':'
292 label
= wxCheckBox(self
, paramIDs
[param
], sParam
,
293 size
= (80,-1), name
= param
)
294 self
.checks
[param
] = label
296 typeClass
= xxx
.paramDict
[param
]
300 typeClass
= paramDict
[param
]
303 typeClass
= ParamText
304 control
= typeClass(self
, param
)
305 control
.Enable(present
)
306 sizer
.AddMany([ (label
, 0, wxALIGN_CENTER_VERTICAL
),
307 (control
, 0, wxALIGN_CENTER_VERTICAL
) ])
308 self
.controls
[param
] = control
309 topSizer
.Add(sizer
, 1, wxALL | wxEXPAND
, 5)
310 self
.SetAutoLayout(true
)
311 self
.SetSizer(topSizer
)
313 def SetValues(self
, xxx
):
315 # Set values, checkboxes to false, disable defaults
317 self
.controlName
.SetValue(xxx
.name
)
318 for param
in xxx
.allParams
:
319 w
= self
.controls
[param
]
322 value
= xxx
.params
[param
].value()
325 if not param
in xxx
.required
:
326 self
.checks
[param
].SetValue(true
)
328 self
.checks
[param
].SetValue(false
)
331 self
.SetModified(false
)
333 ################################################################################
335 # Style notebook page
336 class StylePage(ParamPage
):
337 def __init__(self
, parent
, label
, xxx
):
338 ParamPage
.__init
__(self
, parent
, xxx
)
339 box
= wxStaticBox(self
, -1, label
)
340 box
.SetFont(labelFont
)
341 topSizer
= wxStaticBoxSizer(box
, wxVERTICAL
)
342 sizer
= wxFlexGridSizer(len(xxx
.styles
), 2, 1, 1)
343 for param
in xxx
.styles
:
344 present
= param
in xxx
.params
.keys()
345 check
= wxCheckBox(self
, paramIDs
[param
],
346 param
+ ':', size
= (80,-1), name
= param
)
347 check
.SetValue(present
)
348 control
= paramDict
[param
](self
, name
= param
)
349 control
.Enable(present
)
350 sizer
.AddMany([ (check
, 0, wxALIGN_CENTER_VERTICAL
),
351 (control
, 0, wxALIGN_CENTER_VERTICAL
) ])
352 self
.checks
[param
] = check
353 self
.controls
[param
] = control
354 topSizer
.Add(sizer
, 1, wxALL | wxEXPAND
, 5)
355 self
.SetAutoLayout(true
)
356 self
.SetSizer(topSizer
)
358 # Set data for a cahced page
359 def SetValues(self
, xxx
):
361 for param
in xxx
.styles
:
362 present
= param
in xxx
.params
.keys()
363 check
= self
.checks
[param
]
364 check
.SetValue(present
)
365 control
= self
.controls
[param
]
367 control
.SetValue(xxx
.params
[param
].value())
370 control
.Enable(present
)
371 self
.SetModified(false
)
373 ################################################################################
376 def __init__(self
, pos
, size
):
378 l1
= wxWindow(w
, -1, pos
, wxSize(size
.x
, 2))
379 l1
.SetBackgroundColour(wxRED
)
380 l2
= wxWindow(w
, -1, pos
, wxSize(2, size
.y
))
381 l2
.SetBackgroundColour(wxRED
)
382 l3
= wxWindow(w
, -1, wxPoint(pos
.x
+ size
.x
- 2, pos
.y
), wxSize(2, size
.y
))
383 l3
.SetBackgroundColour(wxRED
)
384 l4
= wxWindow(w
, -1, wxPoint(pos
.x
, pos
.y
+ size
.y
- 2), wxSize(size
.x
, 2))
385 l4
.SetBackgroundColour(wxRED
)
386 self
.lines
= [l1
, l2
, l3
, l4
]
387 # Move highlight to a new position
388 def Replace(self
, pos
, size
):
389 self
.lines
[0].SetDimensions(pos
.x
, pos
.y
, size
.x
, 2, wxSIZE_ALLOW_MINUS_ONE
)
390 self
.lines
[1].SetDimensions(pos
.x
, pos
.y
, 2, size
.y
, wxSIZE_ALLOW_MINUS_ONE
)
391 self
.lines
[2].SetDimensions(pos
.x
+ size
.x
- 2, pos
.y
, 2, size
.y
,
392 wxSIZE_ALLOW_MINUS_ONE
)
393 self
.lines
[3].SetDimensions(pos
.x
, pos
.y
+ size
.y
- 2, size
.x
, 2,
394 wxSIZE_ALLOW_MINUS_ONE
)
397 map(wxWindow
.Destroy
, self
.lines
)
398 testWin
.highLight
= None
400 ################################################################################
403 def __init__(self
, name
):
406 def write(self
, data
):
407 self
.buffer += data
.encode()
409 wxMemoryFSHandler_AddFile(self
.name
, self
.buffer)
411 class XML_Tree(wxTreeCtrl
):
412 def __init__(self
, parent
, id):
413 wxTreeCtrl
.__init
__(self
, parent
, id, style
= wxTR_HAS_BUTTONS
)
414 self
.SetBackgroundColour(wxColour(224, 248, 224))
415 EVT_TREE_SEL_CHANGED(self
, self
.GetId(), self
.OnSelChanged
)
416 # One works on Linux, another on Windows
417 if wxGetOsVersion()[1] == 1:
418 EVT_TREE_ITEM_ACTIVATED(self
, self
.GetId(), self
.OnItemActivated
)
420 EVT_LEFT_DCLICK(self
, self
.OnDClick
)
421 EVT_RIGHT_DOWN(self
, self
.OnRightDown
)
423 self
.needUpdate
= false
424 self
.pendingHighLight
= None
428 il
= wxImageList(16, 16, true
)
429 self
.rootImage
= il
.AddIcon(wxIconFromXPMData(images
.getTreeRootData()))
430 xxxObject
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeDefaultData()))
431 xxxPanel
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreePanelData()))
432 xxxDialog
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeDialogData()))
433 xxxFrame
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeFrameData()))
434 xxxMenuBar
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeMenuBarData()))
435 xxxToolBar
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeToolBarData()))
436 xxxMenu
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeMenuData()))
437 xxxSizer
.imageH
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerHData()))
438 xxxSizer
.imageV
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerVData()))
439 xxxStaticBoxSizer
.imageH
= il
.AddIcon(wxIconFromXPMData(images
.getTreeStaticBoxSizerHData()))
440 xxxStaticBoxSizer
.imageV
= il
.AddIcon(wxIconFromXPMData(images
.getTreeStaticBoxSizerVData()))
441 xxxGridSizer
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerGridData()))
442 xxxFlexGridSizer
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerFlexGridData()))
444 self
.SetImageList(il
)
447 self
.selection
= None
448 wxTreeCtrl
.Unselect(self
)
450 def ExpandAll(self
, item
):
451 if self
.ItemHasChildren(item
):
453 i
, cookie
= self
.GetFirstChild(item
, 0)
457 i
, cookie
= self
.GetNextChild(item
, cookie
)
460 def CollapseAll(self
, item
):
461 if self
.ItemHasChildren(item
):
462 i
, cookie
= self
.GetFirstChild(item
, 0)
466 i
, cookie
= self
.GetNextChild(item
, cookie
)
473 self
.DeleteAllItems()
474 # Add minimal structure
475 if self
.dom
: self
.dom
.unlink()
476 self
.dom
= minidom
.Document()
477 self
.dummyNode
= self
.dom
.createComment('dummy node')
479 self
.mainNode
= self
.dom
.createElement('resource')
480 self
.dom
.appendChild(self
.mainNode
)
481 xxx
= xxxMainNode(None, self
.mainNode
)
482 self
.root
= self
.AddRoot('XML tree', self
.rootImage
, data
=wxTreeItemData(xxx
))
483 self
.SetItemHasChildren(self
.root
)
484 self
.Expand(self
.root
)
487 # Clear old data and set new
488 def SetData(self
, dom
):
489 self
.DeleteAllItems()
490 # Add minimal structure
491 if self
.dom
: self
.dom
.unlink()
493 self
.dummyNode
= self
.dom
.createComment('dummy node')
494 # Find 'resource' child, add it's children
495 self
.mainNode
= dom
.getElementsByTagName('resource')[0]
496 xxx
= xxxMainNode(None, self
.mainNode
)
497 self
.root
= self
.AddRoot('XML tree', self
.rootImage
, data
=wxTreeItemData(xxx
))
498 self
.SetItemHasChildren(self
.root
)
499 nodes
= self
.mainNode
.childNodes
[:]
502 self
.AddNode(self
.root
, None, node
)
504 self
.mainNode
.removeChild(node
)
506 self
.Expand(self
.root
)
509 # Add tree item for given parent item if node is DOM element node with
510 # 'object' tag. xxxParent is parent xxx object
511 def AddNode(self
, itemParent
, xxxParent
, node
):
512 # Set item data to current node
514 xxx
= MakeXXXFromDOM(xxxParent
, node
)
516 print 'ERROR: MakeXXXFromDom(%s, %s)' % (xxxParent
, node
)
519 treeObj
= xxx
.treeObject()
521 item
= self
.AppendItem(itemParent
, treeObj
.treeName(),
522 image
=treeObj
.treeImage(),
523 data
=wxTreeItemData(xxx
))
524 # Try to find children objects
525 if treeObj
.hasChildren
:
526 nodes
= treeObj
.element
.childNodes
[:]
529 self
.AddNode(item
, treeObj
, n
)
530 elif n
.nodeType
!= minidom
.Node
.ELEMENT_NODE
:
531 treeObj
.element
.removeChild(n
)
533 # Remove leaf of tree, return it's data object
534 def RemoveLeaf(self
, leaf
):
535 xxx
= self
.GetPyData(leaf
)
537 parent
= node
.parentNode
538 parent
.removeChild(node
)
540 # Reset selection object
541 self
.selection
= None
543 # Find position relative to the top-level window
544 def FindNodePos(self
, item
):
545 itemParent
= self
.GetItemParent(item
)
547 obj
= self
.FindNodeObject(item
)
548 if self
.GetPyData(itemParent
).treeObject().__class
__ == xxxNotebook
:
549 notebook
= self
.FindNodeObject(itemParent
)
551 for i
in range(notebook
.GetPageCount()):
552 if notebook
.GetPage(i
) == obj
:
553 if notebook
.GetSelection() != i
: notebook
.SetSelection(i
)
556 if itemParent
== self
.root
: return wxPoint(0, 0)
557 # Find first ancestor which is a wxWindow (not a sizer)
558 winParent
= itemParent
559 while self
.GetPyData(winParent
).isSizer
:
560 winParent
= self
.GetItemParent(winParent
)
561 parentPos
= self
.FindNodePos(winParent
)
562 # Position (-1,-1) is really (0,0)
563 pos
= obj
.GetPosition()
564 if pos
== (-1,-1): pos
= (0,0)
565 return parentPos
+ pos
566 # Find window (or sizer) corresponding to a tree item.
567 def FindNodeObject(self
, item
):
568 itemParent
= self
.GetItemParent(item
)
569 # If top-level, return testWin (or panel if wxFrame)
570 if itemParent
== self
.root
: return testWin
.panel
571 xxx
= self
.GetPyData(item
).treeObject()
572 parentWin
= self
.FindNodeObject(itemParent
)
573 # Top-level sizer? return window's sizer
574 if xxx
.isSizer
and isinstance(parentWin
, wxWindowPtr
):
575 return parentWin
.GetSizer()
576 # Otherwise get parent's object and it's child
577 n
= 0 # index of sibling
578 prev
= self
.GetPrevSibling(item
)
580 prev
= self
.GetPrevSibling(prev
)
582 child
= parentWin
.GetChildren()[n
]
583 # Return window or sizer for sizer items
584 if child
.GetClassName() == 'wxSizerItem':
585 if child
.IsWindow(): child
= child
.GetWindow()
586 elif child
.IsSizer():
587 child
= child
.GetSizer()
588 # Test for notebook sizers
589 if isinstance(child
, wxNotebookSizerPtr
):
590 child
= child
.GetNotebook()
592 def OnSelChanged(self
, evt
):
594 # !!! problem with wxGTK - GetOldItem is Ok if nothing selected
595 #oldItem = evt.GetOldItem()
597 oldItem
= self
.selection
599 xxx
= self
.GetPyData(oldItem
)
600 # If some data was modified, apply changes
601 if panel
.IsModified():
602 self
.Apply(xxx
, oldItem
)
603 #if conf.autoRefresh:
604 if testWin
and tree
.GetItemAncestor(oldItem
) == testWin
.item
:
605 if testWin
.highLight
:
606 testWin
.highLight
.Remove()
607 self
.needUpdate
= true
608 status
= 'Changes were applied'
609 frame
.SetStatusText(status
)
611 self
.selection
= evt
.GetItem()
612 if not self
.selection
.IsOk():
613 self
.selection
= None
615 xxx
= self
.GetPyData(self
.selection
)
619 panel
.SetModified(false
)
620 # Hightlighting is done in OnIdle
621 tree
.pendingHighLight
= self
.selection
622 # Find top-level parent
623 def GetItemAncestor(self
, item
):
624 while self
.GetItemParent(item
) != self
.root
:
625 item
= self
.GetItemParent(item
)
627 # Highlight selected item
628 def HighLight(self
, item
):
629 self
.pendingHighLight
= None
630 if not testWin
or self
.GetPyData(testWin
.item
).className \
631 not in ['wxDialog', 'wxPanel', 'wxFrame']:
633 # Top-level does not have highlight
634 if item
== testWin
.item
or item
== tree
.root
:
635 if testWin
.highLight
: testWin
.highLight
.Remove()
637 # If a control from another window is selected, remove highlight
638 if self
.GetItemAncestor(item
) != testWin
.item
:
639 if testWin
.highLight
: testWin
.highLight
.Remove()
641 # Get window/sizer object
642 obj
, pos
= self
.FindNodeObject(item
), self
.FindNodePos(item
)
645 # Nagative positions are not working wuite well
646 if testWin
.highLight
:
647 testWin
.highLight
.Replace(pos
, size
)
649 testWin
.highLight
= HightLightBox(pos
, size
)
650 testWin
.highLight
.item
= item
651 def ShowTestWindow(self
, item
):
653 xxx
= self
.GetPyData(item
)
654 if panel
.IsModified():
655 self
.Apply(xxx
, item
) # apply changes
656 treeObj
= xxx
.treeObject()
657 if treeObj
.className
not in ['wxFrame', 'wxPanel', 'wxDialog',
658 'wxMenuBar', 'wxToolBar']:
659 wxLogMessage('No view for this element (yet)')
662 wxLogError("Can't display a noname element!")
666 self
.SetItemBold(testWin
.item
, false
)
667 self
.SetItemBold(item
)
668 self
.CreateTestWin(item
)
669 # Double-click on Linux
670 def OnItemActivated(self
, evt
):
671 if evt
.GetItem() != self
.root
:
672 self
.ShowTestWindow(evt
.GetItem())
673 # Double-click on Windows
674 def OnDClick(self
, evt
):
675 item
, flags
= self
.HitTest(evt
.GetPosition())
676 if flags
in [wxTREE_HITTEST_ONITEMBUTTON
, wxTREE_HITTEST_ONITEMLABEL
]:
677 if item
!= self
.root
: self
.ShowTestWindow(item
)
680 # (re)create test window
681 def CreateTestWin(self
, item
):
683 # Create a window with this resource
684 xxx
= self
.GetPyData(item
).treeObject()
685 # Close old window, remember where it was
688 pos
= testWin
.GetPosition()
689 if item
== testWin
.item
:
690 # Remember highlight if same top-level window
691 if testWin
.highLight
:
692 highLight
= testWin
.highLight
.item
693 # !!! if 0 is removed, refresh is broken (notebook not deleted?)
694 if 0 and xxx
.className
== 'wxPanel':
695 if testWin
.highLight
:
696 testWin
.pendingHighLight
= highLight
697 testWin
.highLight
.Remove()
698 testWin
.panel
.Destroy()
709 memFile
= MemoryFile('xxx.xrc')
710 # Create partial XML file - faster for big files
712 dom
= minidom
.Document()
713 mainNode
= dom
.createElement('resource')
714 dom
.appendChild(mainNode
)
716 # Remove temporarily from old parent
718 parent
= elem
.parentNode
719 next
= elem
.nextSibling
720 parent
.replaceChild(self
.dummyNode
, elem
)
721 # Append to new DOM, write it
722 mainNode
.appendChild(elem
)
723 dom
.writexml(memFile
)
725 mainNode
.removeChild(elem
)
727 parent
.replaceChild(elem
, self
.dummyNode
)
728 memFile
.close() # write to wxMemoryFS
729 res
= wxXmlResource('')
730 res
.Load('memory:xxx.xrc')
731 if xxx
.className
== 'wxFrame':
733 testWin
= wxPreFrame()
734 res
.LoadFrame(testWin
, frame
, xxx
.name
)
735 testWin
.panel
= testWin
736 testWin
.SetPosition(pos
)
738 elif xxx
.className
== 'wxPanel':
741 testWin
= wxFrame(frame
, -1, 'Panel: ' + xxx
.name
, pos
=pos
)
742 testWin
.panel
= res
.LoadPanel(testWin
, xxx
.name
)
743 testWin
.SetClientSize(testWin
.panel
.GetSize())
745 elif xxx
.className
== 'wxDialog':
747 testWin
= res
.LoadDialog(None, xxx
.name
)
748 testWin
.panel
= testWin
750 testWin
.SetPosition(pos
)
752 elif xxx
.className
== 'wxMenuBar':
753 testWin
= wxFrame(frame
, -1, 'MenuBar: ' + xxx
.name
, pos
=pos
)
754 # Set status bar to display help
755 testWin
.CreateStatusBar()
756 testWin
.menuBar
= res
.LoadMenuBar(xxx
.name
)
757 testWin
.SetMenuBar(testWin
.menuBar
)
759 elif xxx
.className
== 'wxToolBar':
760 testWin
= wxFrame(frame
, -1, 'ToolBar: ' + xxx
.name
, pos
=pos
)
761 # Set status bar to display help
762 testWin
.CreateStatusBar()
763 testWin
.toolBar
= res
.LoadToolBar(testWin
, xxx
.name
)
764 testWin
.SetToolBar(testWin
.toolBar
)
766 wxMemoryFSHandler_RemoveFile('xxx.xrc')
768 testWin
.Connect(testWin
.GetId(), -1, wxEVT_CLOSE_WINDOW
, self
.OnCloseTestWin
)
769 testWin
.highLight
= None
770 if highLight
and not tree
.pendingHighLight
:
771 self
.HighLight(highLight
)
773 def OnCloseTestWin(self
, evt
):
774 global testWin
, testWinPos
775 self
.SetItemBold(testWin
.item
, false
)
776 testWinPos
= testWin
.GetPosition()
781 # True if next item should be inserted after current (vs. appended to it)
782 def NeedInsert(self
, item
):
783 xxx
= self
.GetPyData(item
)
784 if item
== self
.root
: return false
# root item
785 if self
.ctrl
: return true
# if Ctrl pressed, always insert
786 if xxx
.hasChildren
and not self
.GetChildrenCount(item
, false
):
788 return not (self
.IsExpanded(item
) and self
.GetChildrenCount(item
, false
))
791 def OnRightDown(self
, evt
):
793 pt
= evt
.GetPosition();
794 item
, flags
= self
.HitTest(pt
)
795 if item
.Ok() and flags
& wxTREE_HITTEST_ONITEM
:
796 self
.SelectItem(item
)
801 item
= self
.selection
803 menu
.Append(pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand tree')
804 menu
.Append(pullDownMenu
.ID_COLLAPSE
, 'Collapse', 'Collapse tree')
806 self
.ctrl
= evt
.ControlDown() # save Ctrl state
807 self
.shift
= evt
.ShiftDown() # and Shift too
808 m
= wxMenu() # create menu
810 if item
!= self
.root
: needInsert
= self
.NeedInsert(item
)
811 if item
== self
.root
or \
812 self
.GetItemParent(item
) == self
.root
and needInsert
:
813 m
.Append(pullDownMenu
.ID_NEW_PANEL
, 'Panel', 'Create panel')
814 m
.Append(pullDownMenu
.ID_NEW_DIALOG
, 'Dialog', 'Create dialog')
815 m
.Append(pullDownMenu
.ID_NEW_FRAME
, 'Frame', 'Create frame')
817 m
.Append(pullDownMenu
.ID_NEW_TOOL_BAR
, 'ToolBar', 'Create toolbar')
818 m
.Append(pullDownMenu
.ID_NEW_MENU_BAR
, 'MenuBar', 'Create menubar')
819 m
.Append(pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu')
821 xxx
= self
.GetPyData(item
).treeObject()
822 # Check parent for possible child nodes if inserting sibling
823 if needInsert
: xxx
= xxx
.parent
824 if xxx
.__class
__ == xxxMenuBar
:
825 m
.Append(pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu')
826 elif xxx
.__class
__ in [xxxToolBar
, xxxTool
] or \
827 xxx
.__class
__ == xxxSeparator
and xxx
.parent
.__class
__ == xxxToolBar
:
828 SetMenu(m
, pullDownMenu
.toolBarControls
)
829 elif xxx
.__class
__ in [xxxMenu
, xxxMenuItem
]:
830 SetMenu(m
, pullDownMenu
.menuControls
)
832 SetMenu(m
, pullDownMenu
.controls
)
833 if xxx
.__class
__ == xxxNotebook
:
834 m
.Enable(m
.FindItem('sizer'), false
)
835 elif not (xxx
.isSizer
or xxx
.parent
and xxx
.parent
.isSizer
):
836 m
.Enable(pullDownMenu
.ID_NEW_SPACER
, false
)
837 # Select correct label for create menu
840 menu
.AppendMenu(wxNewId(), 'Insert Child', m
,
841 'Create child object as the first child')
843 menu
.AppendMenu(wxNewId(), 'Append Child', m
,
844 'Create child object as the last child')
847 menu
.AppendMenu(wxNewId(), 'Create Sibling', m
,
848 'Create sibling before selected object')
850 menu
.AppendMenu(wxNewId(), 'Create Sibling', m
,
851 'Create sibling after selected object')
852 menu
.AppendSeparator()
853 # Not using standart IDs because we don't want to show shortcuts
854 menu
.Append(wxID_CUT
, 'Cut', 'Cut to the clipboard')
855 menu
.Append(wxID_COPY
, 'Copy', 'Copy to the clipboard')
856 if self
.ctrl
and item
!= tree
.root
:
857 menu
.Append(wxID_PASTE
, 'Paste Sibling',
858 'Paste from the clipboard as a sibling')
860 menu
.Append(wxID_PASTE
, 'Paste', 'Paste from the clipboard')
861 menu
.Append(pullDownMenu
.ID_DELETE
,
862 'Delete', 'Delete object')
863 if self
.ItemHasChildren(item
):
864 menu
.AppendSeparator()
865 menu
.Append(pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand subtree')
866 menu
.Append(pullDownMenu
.ID_COLLAPSE
, 'Collapse', 'Collapse subtree')
867 self
.PopupMenu(menu
, evt
.GetPosition())
871 def Apply(self
, xxx
, item
):
874 xxx
= xxx
.treeObject()
875 if xxx
.hasName
and self
.GetItemText(item
) != xxx
.name
:
876 self
.SetItemText(item
, xxx
.treeName())
877 # Change tree icon for sizers
878 if isinstance(xxx
, xxxBoxSizer
):
879 self
.SetItemImage(item
, xxx
.treeImage())
880 # Set global modified state
881 frame
.modified
= true
884 ID_NEW_PANEL
= wxNewId()
885 ID_NEW_DIALOG
= wxNewId()
886 ID_NEW_FRAME
= wxNewId()
887 ID_NEW_TOOL_BAR
= wxNewId()
888 ID_NEW_TOOL
= wxNewId()
889 ID_NEW_MENU_BAR
= wxNewId()
890 ID_NEW_MENU
= wxNewId()
892 ID_NEW_STATIC_TEXT
= wxNewId()
893 ID_NEW_TEXT_CTRL
= wxNewId()
895 ID_NEW_BUTTON
= wxNewId()
896 ID_NEW_BITMAP_BUTTON
= wxNewId()
897 ID_NEW_RADIO_BUTTON
= wxNewId()
898 ID_NEW_SPIN_BUTTON
= wxNewId()
900 ID_NEW_STATIC_BOX
= wxNewId()
901 ID_NEW_CHECK_BOX
= wxNewId()
902 ID_NEW_RADIO_BOX
= wxNewId()
903 ID_NEW_COMBO_BOX
= wxNewId()
904 ID_NEW_LIST_BOX
= wxNewId()
906 ID_NEW_STATIC_LINE
= wxNewId()
907 ID_NEW_STATIC_BITMAP
= wxNewId()
908 ID_NEW_CHOICE
= wxNewId()
909 ID_NEW_SLIDER
= wxNewId()
910 ID_NEW_GAUGE
= wxNewId()
911 ID_NEW_SCROLL_BAR
= wxNewId()
912 ID_NEW_TREE_CTRL
= wxNewId()
913 ID_NEW_LIST_CTRL
= wxNewId()
914 ID_NEW_CHECK_LIST
= wxNewId()
915 ID_NEW_NOTEBOOK
= wxNewId()
916 ID_NEW_HTML_WINDOW
= wxNewId()
917 ID_NEW_CALENDAR
= wxNewId()
919 ID_NEW_BOX_SIZER
= wxNewId()
920 ID_NEW_STATIC_BOX_SIZER
= wxNewId()
921 ID_NEW_GRID_SIZER
= wxNewId()
922 ID_NEW_FLEX_GRID_SIZER
= wxNewId()
923 ID_NEW_SPACER
= wxNewId()
924 ID_NEW_TOOL_BAR
= wxNewId()
925 ID_NEW_TOOL
= wxNewId()
926 ID_NEW_MENU
= wxNewId()
927 ID_NEW_MENU_ITEM
= wxNewId()
928 ID_NEW_SEPARATOR
= wxNewId()
929 ID_NEW_LAST
= wxNewId()
930 ID_EXPAND
= wxNewId()
931 ID_COLLAPSE
= wxNewId()
933 def __init__(self
, parent
):
934 self
.ID_DELETE
= parent
.ID_DELETE
935 EVT_MENU_RANGE(parent
, self
.ID_NEW_PANEL
,
936 self
.ID_NEW_LAST
, parent
.OnCreate
)
937 EVT_MENU(parent
, self
.ID_COLLAPSE
, parent
.OnCollapse
)
938 EVT_MENU(parent
, self
.ID_EXPAND
, parent
.OnExpand
)
939 # We connect to tree, but process in frame
940 EVT_MENU_HIGHLIGHT_ALL(tree
, parent
.OnPullDownHighlight
)
942 ################################################################################
944 class Frame(wxFrame
):
945 def __init__(self
, pos
, size
):
948 wxFrame
.__init
__(self
, None, -1, '', pos
, size
)
949 self
.CreateStatusBar()
950 #self.SetIcon(wxIconFromXPMData(images.getIconData()))
951 #icon = wxIconFromXPMData(images.getIconData())
952 icon
= wxIcon(os
.path
.join(sys
.path
[0], 'xrced.ico'), wxBITMAP_TYPE_ICO
)
957 self
.panelX
= self
.panelY
= -1
958 self
.panelWidth
= 300
959 self
.panelHeight
= 200
962 menuBar
= wxMenuBar()
965 menu
.Append(wxID_NEW
, '&New\tCtrl-N', 'New file')
966 menu
.Append(wxID_OPEN
, '&Open...\tCtrl-O', 'Open XRC file')
967 menu
.Append(wxID_SAVE
, '&Save\tCtrl-S', 'Save XRC file')
968 menu
.Append(wxID_SAVEAS
, 'Save &As...', 'Save XRC file under different name')
969 menu
.AppendSeparator()
970 menu
.Append(wxID_EXIT
, '&Quit\tCtrl-Q', 'Exit application')
971 menuBar
.Append(menu
, '&File')
974 menu
.Append(wxID_UNDO
, '&Undo\tCtrl-Z', 'Undo')
975 menu
.Append(wxID_REDO
, '&Redo\tCtrl-Y', 'Redo')
976 menu
.AppendSeparator()
977 menu
.Append(wxID_CUT
, 'Cut\tCtrl-X', 'Cut to the clipboard')
978 menu
.Append(wxID_COPY
, '&Copy\tCtrl-C', 'Copy to the clipboard')
979 menu
.Append(wxID_PASTE
, '&Paste\tCtrl-V', 'Paste from the clipboard')
980 self
.ID_DELETE
= wxNewId()
981 menu
.Append(self
.ID_DELETE
, '&Delete\tCtrl-D', 'Delete object')
982 menuBar
.Append(menu
, '&Edit')
985 self
.ID_EMBED_PANEL
= wxNewId()
986 menu
.Append(self
.ID_EMBED_PANEL
, '&Embed Panel',
987 'Toggle embedding properties panel in the main window', true
)
988 menu
.Check(self
.ID_EMBED_PANEL
, conf
.embedPanel
)
989 menu
.AppendSeparator()
990 self
.ID_TEST
= wxNewId()
991 menu
.Append(self
.ID_TEST
, '&Test\tF5', 'Test window')
992 self
.ID_REFRESH
= wxNewId()
993 menu
.Append(self
.ID_REFRESH
, '&Refresh\tCtrl-R', 'Refresh test window')
994 self
.ID_AUTO_REFRESH
= wxNewId()
995 menu
.Append(self
.ID_AUTO_REFRESH
, '&Auto-refresh\tCtrl-A',
996 'Toggle auto-refresh mode', true
)
997 menu
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
998 menuBar
.Append(menu
, '&View')
1001 menu
.Append(wxID_ABOUT
, '&About...', 'About XCRed')
1002 self
.ID_README
= wxNewId()
1003 menu
.Append(self
.ID_README
, '&Readme...', 'View the README file')
1005 self
.ID_DEBUG_CMD
= wxNewId()
1006 menu
.Append(self
.ID_DEBUG_CMD
, 'CMD', 'Python command line')
1007 EVT_MENU(self
, self
.ID_DEBUG_CMD
, self
.OnDebugCMD
)
1008 menuBar
.Append(menu
, '&Help')
1010 self
.menuBar
= menuBar
1011 self
.SetMenuBar(menuBar
)
1014 tb
= self
.CreateToolBar(wxTB_HORIZONTAL | wxNO_BORDER | wxTB_FLAT
)
1015 tb
.SetToolBitmapSize((24, 23))
1016 tb
.AddSimpleTool(wxID_NEW
, images
.getNewBitmap(), 'New', 'New file')
1017 tb
.AddSimpleTool(wxID_OPEN
, images
.getOpenBitmap(), 'Open', 'Open file')
1018 tb
.AddSimpleTool(wxID_SAVE
, images
.getSaveBitmap(), 'Save', 'Save file')
1019 tb
.AddControl(wxStaticLine(tb
, -1, size
=(-1,23), style
=wxLI_VERTICAL
))
1020 tb
.AddSimpleTool(wxID_CUT
, images
.getCutBitmap(), 'Cut', 'Cut')
1021 tb
.AddSimpleTool(wxID_COPY
, images
.getCopyBitmap(), 'Copy', 'Copy')
1022 tb
.AddSimpleTool(wxID_PASTE
, images
.getPasteBitmap(), 'Paste', 'Paste')
1023 tb
.AddControl(wxStaticLine(tb
, -1, size
=(-1,23), style
=wxLI_VERTICAL
))
1024 tb
.AddSimpleTool(self
.ID_TEST
, images
.getTestBitmap(), 'Test', 'Test window')
1025 tb
.AddSimpleTool(self
.ID_REFRESH
, images
.getRefreshBitmap(),
1026 'Refresh', 'Refresh view')
1027 tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, images
.getAutoRefreshBitmap(),
1028 'Auto-refresh', 'Toggle auto-refresh mode', true
)
1029 if wxGetOsVersion()[1] == 1:
1030 tb
.AddSeparator() # otherwise auto-refresh sticks in status line
1031 tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1036 EVT_MENU(self
, wxID_NEW
, self
.OnNew
)
1037 EVT_MENU(self
, wxID_OPEN
, self
.OnOpen
)
1038 EVT_MENU(self
, wxID_SAVE
, self
.OnSaveOrSaveAs
)
1039 EVT_MENU(self
, wxID_SAVEAS
, self
.OnSaveOrSaveAs
)
1040 EVT_MENU(self
, wxID_EXIT
, self
.OnExit
)
1042 EVT_MENU(self
, wxID_UNDO
, self
.OnUndo
)
1043 EVT_MENU(self
, wxID_REDO
, self
.OnRedo
)
1044 EVT_MENU(self
, wxID_CUT
, self
.OnCut
)
1045 EVT_MENU(self
, wxID_COPY
, self
.OnCopy
)
1046 EVT_MENU(self
, wxID_PASTE
, self
.OnPaste
)
1047 EVT_MENU(self
, self
.ID_DELETE
, self
.OnDelete
)
1049 EVT_MENU(self
, self
.ID_EMBED_PANEL
, self
.OnEmbedPanel
)
1050 EVT_MENU(self
, self
.ID_TEST
, self
.OnTest
)
1051 EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
)
1052 EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
)
1054 EVT_MENU(self
, wxID_ABOUT
, self
.OnAbout
)
1055 EVT_MENU(self
, self
.ID_README
, self
.OnReadme
)
1058 EVT_UPDATE_UI(self
, wxID_CUT
, self
.OnUpdateUI
)
1059 EVT_UPDATE_UI(self
, wxID_COPY
, self
.OnUpdateUI
)
1060 EVT_UPDATE_UI(self
, wxID_PASTE
, self
.OnUpdateUI
)
1061 EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
)
1062 EVT_UPDATE_UI(self
, self
.ID_TEST
, self
.OnUpdateUI
)
1063 EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
)
1066 sizer
= wxBoxSizer(wxVERTICAL
)
1067 sizer
.Add(wxStaticLine(self
, -1), 0, wxEXPAND
)
1068 splitter
= wxSplitterWindow(self
, -1, style
=wxSP_3DSASH
)
1069 self
.splitter
= splitter
1070 splitter
.SetMinimumPaneSize(100)
1073 tree
= XML_Tree(splitter
, -1)
1074 sys
.modules
['xxx'].tree
= tree
1075 # !!! frame styles are broken
1076 # Miniframe for not embedded mode
1077 miniFrame
= wxFrame(self
, -1, 'Properties Panel',
1078 (conf
.panelX
, conf
.panelY
),
1079 (conf
.panelWidth
, conf
.panelHeight
))
1080 self
.miniFrame
= miniFrame
1081 sizer2
= wxBoxSizer()
1082 miniFrame
.SetAutoLayout(true
)
1083 miniFrame
.SetSizer(sizer2
)
1084 EVT_CLOSE(self
.miniFrame
, self
.OnCloseMiniFrame
)
1085 # Create panel for parameters
1088 panel
= Panel(splitter
)
1089 # Set plitter windows
1090 splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
1092 panel
= Panel(miniFrame
)
1093 sizer2
.Add(panel
, 1, wxEXPAND
)
1094 miniFrame
.Show(true
)
1095 splitter
.Initialize(tree
)
1096 sizer
.Add(splitter
, 1, wxEXPAND
)
1097 self
.SetAutoLayout(true
)
1098 self
.SetSizer(sizer
)
1100 # Init pull-down menu data
1102 pullDownMenu
= PullDownMenu(self
)
1103 # Mapping from IDs to element names
1105 pullDownMenu
.ID_NEW_PANEL
: 'wxPanel',
1106 pullDownMenu
.ID_NEW_DIALOG
: 'wxDialog',
1107 pullDownMenu
.ID_NEW_FRAME
: 'wxFrame',
1108 pullDownMenu
.ID_NEW_TOOL_BAR
: 'wxToolBar',
1109 pullDownMenu
.ID_NEW_TOOL
: 'tool',
1110 pullDownMenu
.ID_NEW_MENU_BAR
: 'wxMenuBar',
1111 pullDownMenu
.ID_NEW_MENU
: 'wxMenu',
1112 pullDownMenu
.ID_NEW_MENU_ITEM
: 'wxMenuItem',
1113 pullDownMenu
.ID_NEW_SEPARATOR
: 'separator',
1115 pullDownMenu
.ID_NEW_STATIC_TEXT
: 'wxStaticText',
1116 pullDownMenu
.ID_NEW_TEXT_CTRL
: 'wxTextCtrl',
1118 pullDownMenu
.ID_NEW_BUTTON
: 'wxButton',
1119 pullDownMenu
.ID_NEW_BITMAP_BUTTON
: 'wxBitmapButton',
1120 pullDownMenu
.ID_NEW_RADIO_BUTTON
: 'wxRadioButton',
1121 pullDownMenu
.ID_NEW_SPIN_BUTTON
: 'wxSpinButton',
1123 pullDownMenu
.ID_NEW_STATIC_BOX
: 'wxStaticBox',
1124 pullDownMenu
.ID_NEW_CHECK_BOX
: 'wxCheckBox',
1125 pullDownMenu
.ID_NEW_RADIO_BOX
: 'wxRadioBox',
1126 pullDownMenu
.ID_NEW_COMBO_BOX
: 'wxComboBox',
1127 pullDownMenu
.ID_NEW_LIST_BOX
: 'wxListBox',
1129 pullDownMenu
.ID_NEW_STATIC_LINE
: 'wxStaticLine',
1130 pullDownMenu
.ID_NEW_STATIC_BITMAP
: 'wxStaticBitmap',
1131 pullDownMenu
.ID_NEW_CHOICE
: 'wxChoice',
1132 pullDownMenu
.ID_NEW_SLIDER
: 'wxSlider',
1133 pullDownMenu
.ID_NEW_GAUGE
: 'wxGauge',
1134 pullDownMenu
.ID_NEW_SCROLL_BAR
: 'wxScrollBar',
1135 pullDownMenu
.ID_NEW_TREE_CTRL
: 'wxTreeCtrl',
1136 pullDownMenu
.ID_NEW_LIST_CTRL
: 'wxListCtrl',
1137 pullDownMenu
.ID_NEW_CHECK_LIST
: 'wxCheckList',
1138 pullDownMenu
.ID_NEW_NOTEBOOK
: 'wxNotebook',
1139 pullDownMenu
.ID_NEW_HTML_WINDOW
: 'wxHtmlWindow',
1140 pullDownMenu
.ID_NEW_CALENDAR
: 'wxCalendar',
1142 pullDownMenu
.ID_NEW_BOX_SIZER
: 'wxBoxSizer',
1143 pullDownMenu
.ID_NEW_STATIC_BOX_SIZER
: 'wxStaticBoxSizer',
1144 pullDownMenu
.ID_NEW_GRID_SIZER
: 'wxGridSizer',
1145 pullDownMenu
.ID_NEW_FLEX_GRID_SIZER
: 'wxFlexGridSizer',
1146 pullDownMenu
.ID_NEW_SPACER
: 'spacer',
1148 pullDownMenu
.controls
= [
1149 ['control', 'Various controls',
1150 (pullDownMenu
.ID_NEW_STATIC_TEXT
, 'Label', 'Create static label'),
1151 (pullDownMenu
.ID_NEW_STATIC_LINE
, 'Line', 'Create static line'),
1152 (pullDownMenu
.ID_NEW_TEXT_CTRL
, 'TextBox', 'Create text box control'),
1153 (pullDownMenu
.ID_NEW_CHOICE
, 'Choice', 'Create choice control'),
1154 (pullDownMenu
.ID_NEW_SLIDER
, 'Slider', 'Create slider control'),
1155 (pullDownMenu
.ID_NEW_GAUGE
, 'Gauge', 'Create gauge control'),
1156 (pullDownMenu
.ID_NEW_SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'),
1157 (pullDownMenu
.ID_NEW_TREE_CTRL
, 'TreeCtrl', 'Create tree control'),
1158 (pullDownMenu
.ID_NEW_LIST_CTRL
, 'ListCtrl', 'Create list control'),
1159 (pullDownMenu
.ID_NEW_HTML_WINDOW
, 'HtmlWindow', 'Create HTML window'),
1160 (pullDownMenu
.ID_NEW_CALENDAR
, 'Calendar', 'Create calendar control'),
1161 (pullDownMenu
.ID_NEW_PANEL
, 'Panel', 'Create panel'),
1162 (pullDownMenu
.ID_NEW_NOTEBOOK
, 'Notebook', 'Create notebook control'),
1164 ['button', 'Buttons',
1165 (pullDownMenu
.ID_NEW_BUTTON
, 'Button', 'Create button'),
1166 (pullDownMenu
.ID_NEW_BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'),
1167 (pullDownMenu
.ID_NEW_RADIO_BUTTON
, 'RadioButton', 'Create radio button'),
1168 (pullDownMenu
.ID_NEW_SPIN_BUTTON
, 'SpinButton', 'Create spin button'),
1171 (pullDownMenu
.ID_NEW_STATIC_BOX
, 'StaticBox', 'Create static box'),
1172 (pullDownMenu
.ID_NEW_CHECK_BOX
, 'CheckBox', 'Create check box'),
1173 (pullDownMenu
.ID_NEW_RADIO_BOX
, 'RadioBox', 'Create radio box'),
1174 (pullDownMenu
.ID_NEW_COMBO_BOX
, 'ComboBox', 'Create combo box'),
1175 (pullDownMenu
.ID_NEW_LIST_BOX
, 'ListBox', 'Create list box'),
1176 (pullDownMenu
.ID_NEW_CHECK_LIST
, 'CheckListBox',
1177 'Create check list control'),
1180 (pullDownMenu
.ID_NEW_BOX_SIZER
, 'BoxSizer', 'Create box sizer'),
1181 (pullDownMenu
.ID_NEW_STATIC_BOX_SIZER
, 'StaticBoxSizer',
1182 'Create static box sizer'),
1183 (pullDownMenu
.ID_NEW_GRID_SIZER
, 'GridSizer', 'Create grid sizer'),
1184 (pullDownMenu
.ID_NEW_FLEX_GRID_SIZER
, 'FlexGridSizer',
1185 'Create flexgrid sizer'),
1186 (pullDownMenu
.ID_NEW_SPACER
, 'Spacer', 'Create spacer'),
1189 pullDownMenu
.menuControls
= [
1190 (pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu'),
1191 (pullDownMenu
.ID_NEW_MENU_ITEM
, 'MenuItem', 'Create menu item'),
1192 (pullDownMenu
.ID_NEW_SEPARATOR
, 'Separator', 'Create separator'),
1194 pullDownMenu
.toolBarControls
= [
1195 (pullDownMenu
.ID_NEW_TOOL
, 'Tool', 'Create tool'),
1196 (pullDownMenu
.ID_NEW_SEPARATOR
, 'Separator', 'Create separator'),
1197 ['control', 'Various controls',
1198 (pullDownMenu
.ID_NEW_STATIC_TEXT
, 'Label', 'Create static label'),
1199 (pullDownMenu
.ID_NEW_STATIC_LINE
, 'Line', 'Create static line'),
1200 (pullDownMenu
.ID_NEW_TEXT_CTRL
, 'TextBox', 'Create text box control'),
1201 (pullDownMenu
.ID_NEW_CHOICE
, 'Choice', 'Create choice control'),
1202 (pullDownMenu
.ID_NEW_SLIDER
, 'Slider', 'Create slider control'),
1203 (pullDownMenu
.ID_NEW_GAUGE
, 'Gauge', 'Create gauge control'),
1204 (pullDownMenu
.ID_NEW_SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'),
1205 (pullDownMenu
.ID_NEW_LIST_CTRL
, 'ListCtrl', 'Create list control'),
1207 ['button', 'Buttons',
1208 (pullDownMenu
.ID_NEW_BUTTON
, 'Button', 'Create button'),
1209 (pullDownMenu
.ID_NEW_BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'),
1210 (pullDownMenu
.ID_NEW_RADIO_BUTTON
, 'RadioButton', 'Create radio button'),
1211 (pullDownMenu
.ID_NEW_SPIN_BUTTON
, 'SpinButton', 'Create spin button'),
1214 (pullDownMenu
.ID_NEW_STATIC_BOX
, 'StaticBox', 'Create static box'),
1215 (pullDownMenu
.ID_NEW_CHECK_BOX
, 'CheckBox', 'Create check box'),
1216 (pullDownMenu
.ID_NEW_RADIO_BOX
, 'RadioBox', 'Create radio box'),
1217 (pullDownMenu
.ID_NEW_COMBO_BOX
, 'ComboBox', 'Create combo box'),
1218 (pullDownMenu
.ID_NEW_LIST_BOX
, 'ListBox', 'Create list box'),
1219 (pullDownMenu
.ID_NEW_CHECK_LIST
, 'CheckListBox',
1220 'Create check list control'),
1228 EVT_IDLE(self
, self
.OnIdle
)
1229 EVT_CLOSE(self
, self
.OnCloseWindow
)
1231 def OnNew(self
, evt
):
1234 def OnOpen(self
, evt
):
1235 if not self
.AskSave(): return
1236 dlg
= wxFileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
1237 '', '*.xrc', wxOPEN | wxCHANGE_DIR
)
1238 if dlg
.ShowModal() == wxID_OK
:
1239 path
= dlg
.GetPath()
1240 self
.SetStatusText('Loading...')
1245 self
.SetStatusText('Data loaded')
1247 self
.SetStatusText('Failed')
1252 def OnSaveOrSaveAs(self
, evt
):
1253 if evt
.GetId() == wxID_SAVEAS
or not self
.dataFile
:
1254 if self
.dataFile
: defaultName
= ''
1255 else: defaultName
= 'UNTITLED.xrc'
1256 dlg
= wxFileDialog(self
, 'Save As', os
.path
.dirname(self
.dataFile
),
1257 defaultName
, '*.xrc',
1258 wxSAVE | wxOVERWRITE_PROMPT | wxCHANGE_DIR
)
1259 if dlg
.ShowModal() == wxID_OK
:
1260 path
= dlg
.GetPath()
1266 path
= self
.dataFile
1267 self
.SetStatusText('Saving...')
1272 self
.dataFile
= path
1273 self
.SetStatusText('Data saved')
1275 self
.SetStatusText('Failed')
1278 def OnExit(self
, evt
):
1281 def OnUndo(self
, evt
):
1282 print '*** being implemented'
1284 print self
.lastOp
, self
.undo
1285 if self
.lastOp
== 'DELETE':
1286 parent
, prev
, elem
= self
.undo
1288 xxx
= MakeXXXFromDOM(tree
.GetPyData(parent
).treeObject(), elem
)
1289 item
= tree
.InsertItem( parent
, prev
, xxx
.treeObject().className
,
1290 data
=wxTreeItemData(xxx
) )
1292 def OnRedo(self
, evt
):
1293 print '*** being implemented'
1295 def OnCut(self
, evt
):
1296 selected
= tree
.selection
1299 self
.undo
= [tree
.GetItemParent(selected
), tree
.GetPrevSibling(selected
)]
1303 # If deleting top-level item, delete testWin
1304 if selected
== testWin
.item
:
1308 # Remove highlight, update testWin
1309 if tree
.GetItemAncestor(selected
) == testWin
.item
:
1310 if testWin
.highLight
: testWin
.highLight
.Remove()
1311 tree
.needUpdate
= true
1312 self
.clipboard
= tree
.RemoveLeaf(selected
)
1313 tree
.pendingHighLight
= None
1316 self
.modified
= true
1317 self
.SetStatusText('Removed to clipboard')
1319 def OnCopy(self
, evt
):
1320 selected
= tree
.selection
1321 xxx
= tree
.GetPyData(selected
)
1322 self
.clipboard
= xxx
.element
.cloneNode(true
)
1323 self
.SetStatusText('Copied')
1325 def OnPaste(self
, evt
):
1326 selected
= tree
.selection
1327 appendChild
= not tree
.NeedInsert(selected
)
1328 xxx
= tree
.GetPyData(selected
)
1330 # If has next item, insert, else append to parent
1331 nextItem
= tree
.GetNextSibling(selected
)
1333 # Insert before nextItem
1334 parentLeaf
= tree
.GetItemParent(selected
)
1335 else: # last child: change selected to parent
1337 selected
= tree
.GetItemParent(selected
)
1338 # Expanded container (must have children)
1339 elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, false
):
1341 nextItem
= tree
.GetFirstChild(selected
, 0)[0]
1342 parentLeaf
= selected
1343 # Parent should be tree element or None
1345 parent
= tree
.GetPyData(selected
)
1347 parent
= tree
.GetPyData(parentLeaf
)
1348 if parent
.hasChild
: parent
= parent
.child
1350 # Create a copy of clipboard element
1351 elem
= self
.clipboard
.cloneNode(true
)
1352 # Tempopary xxx object to test things
1353 xxx
= MakeXXXFromDOM(parent
, elem
)
1355 # Check compatibility
1358 x
= xxx
.treeObject()
1359 if x
.__class
__ in [xxxDialog
, xxxFrame
, xxxMenuBar
, xxxToolBar
]:
1360 if parent
.__class
__ != xxxMainNode
: error
= true
1361 elif x
.__class
__ == xxxSpacer
:
1362 if not parent
.isSizer
: error
= true
1363 elif x
.__class
__ == xxxSeparator
:
1364 if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error
= true
1365 elif x
.__class
__ == xxxTool
:
1366 if parent
.__class
__ != xxxToolBar
: error
= true
1367 elif x
.__class
__ == xxxMenuItem
:
1368 if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= true
1369 elif x
.isSizer
and parent
.__class
__ == xxxNotebook
: error
= true
1370 else: # normal controls can be almost anywhere
1371 if parent
.__class
__ == xxxMainNode
or \
1372 parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= true
1374 if parent
.__class
__ == xxxMainNode
: parentClass
= 'root'
1375 else: parentClass
= parent
.className
1376 wxLogError('Incompatible parent/child: parent is %s, child is %s!' %
1377 (parentClass
, x
.className
))
1380 # Check parent and child relationships.
1381 # If parent is sizer or notebook, child is of wrong class or
1382 # parent is normal window, child is child container then detach child.
1383 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
1384 if isChildContainer
and \
1385 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
1386 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
1387 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
1388 elem
.removeChild(xxx
.child
.element
) # detach child
1389 elem
.unlink() # delete child container
1390 elem
= xxx
.child
.element
# replace
1391 # This may help garbage collection
1392 xxx
.child
.parent
= None
1393 isChildContainer
= false
1394 # Parent is sizer or notebook, child is not child container
1395 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
1396 # Create sizer item element
1397 sizerItemElem
= MakeEmptyDOM('sizeritem')
1398 sizerItemElem
.appendChild(elem
)
1399 elem
= sizerItemElem
1400 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
1401 pageElem
= MakeEmptyDOM('notebookpage')
1402 pageElem
.appendChild(elem
)
1404 xxx
= MakeXXXFromDOM(parent
, elem
)
1405 # Figure out if we must append a new child or sibling
1407 parent
.element
.appendChild(elem
)
1408 newItem
= tree
.AppendItem(selected
, xxx
.treeName(), image
=xxx
.treeImage(),
1409 data
=wxTreeItemData(xxx
))
1411 node
= tree
.GetPyData(nextItem
).element
1412 parent
.element
.insertBefore(elem
, node
)
1413 # Inserting before is difficult, se we insert after or first child
1414 newItem
= tree
.InsertItem(parentLeaf
, selected
, xxx
.treeName(),
1415 image
=xxx
.treeImage(), data
=wxTreeItemData(xxx
))
1416 # Add children items
1418 treeObj
= xxx
.treeObject()
1419 for n
in treeObj
.element
.childNodes
:
1421 tree
.AddNode(newItem
, treeObj
, n
)
1422 # Scroll to show new item
1423 tree
.EnsureVisible(newItem
)
1424 tree
.SelectItem(newItem
)
1425 if not tree
.IsVisible(newItem
):
1426 tree
.ScrollTo(newItem
)
1429 if testWin
and tree
.GetItemAncestor(newItem
) == testWin
.item
:
1430 if conf
.autoRefresh
:
1431 tree
.needUpdate
= true
1432 tree
.pendingHighLight
= newItem
1434 tree
.pendingHighLight
= None
1435 self
.modified
= true
1436 self
.SetStatusText('Pasted')
1438 def OnDelete(self
, evt
):
1439 selected
= tree
.selection
1441 self
.lastOp
= 'DELETE'
1442 self
.undo
= [tree
.GetItemParent(selected
), tree
.GetPrevSibling(selected
)]
1446 # If deleting top-level item, delete testWin
1447 if selected
== testWin
.item
:
1451 # Remove highlight, update testWin
1452 if tree
.GetItemAncestor(selected
) == testWin
.item
:
1453 if testWin
.highLight
: testWin
.highLight
.Remove()
1454 tree
.needUpdate
= true
1455 xnode
= tree
.RemoveLeaf(selected
)
1456 # !!! cloneNode is broken, or something is wrong
1457 # self.undo.append(xnode.cloneNode(true))
1459 tree
.pendingHighLight
= None
1462 self
.modified
= true
1463 self
.SetStatusText('Deleted')
1465 def OnEmbedPanel(self
, evt
):
1466 conf
.embedPanel
= evt
.IsChecked()
1468 # Remember last dimentions
1469 self
.panelWidth
, self
.panelHeight
= panel
.GetSize()
1470 panel
.Reparent(self
.splitter
)
1471 self
.miniFrame
.GetSizer().RemoveWindow(panel
)
1472 self
.splitter
.SplitVertically(tree
, panel
, self
.sashPos
)
1473 self
.miniFrame
.Show(false
)
1475 self
.sashPos
= self
.splitter
.GetSashPosition()
1476 self
.splitter
.Unsplit(panel
)
1477 sizer
= self
.miniFrame
.GetSizer()
1478 panel
.Reparent(self
.miniFrame
)
1480 sizer
.Add(panel
, 1, wxEXPAND
)
1481 self
.miniFrame
.Show(true
)
1482 self
.miniFrame
.SetSize((self
.panelWidth
, self
.panelHeight
))
1484 def OnTest(self
, evt
):
1485 tree
.ShowTestWindow(tree
.selection
)
1487 def OnRefresh(self
, evt
):
1488 # If modified, apply first
1489 selection
= tree
.selection
1491 xxx
= tree
.GetPyData(selection
)
1492 if xxx
and panel
.IsModified():
1493 tree
.Apply(xxx
, selection
)
1496 tree
.CreateTestWin(testWin
.item
)
1497 tree
.needUpdate
= false
1499 def OnAutoRefresh(self
, evt
):
1500 conf
.autoRefresh
= evt
.IsChecked()
1501 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1502 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1504 def OnAbout(self
, evt
):
1505 str = '%s %s\n\nRoman Rolinsky <rolinsky@mema.ucl.ac.be>' % \
1507 dlg
= wxMessageDialog(self
, str, 'About ' + progname
, wxOK | wxCENTRE
)
1511 def OnReadme(self
, evt
):
1512 from wxPython
.lib
.dialogs
import wxScrolledMessageDialog
1513 text
= open(os
.path
.join(sys
.path
[0], 'README'), 'r').read()
1514 dlg
= wxScrolledMessageDialog(self
, text
, "XRCed README")
1519 # Simple emulation of python command line
1520 def OnDebugCMD(self
, evt
):
1524 exec raw_input('C:\> ')
1529 (etype
, value
, tb
) =sys
.exc_info()
1530 tblist
=traceback
.extract_tb(tb
)[1:]
1531 msg
=string
.join(traceback
.format_exception_only(etype
, value
)
1532 +traceback
.format_list(tblist
))
1535 def OnCreate(self
, evt
):
1536 selected
= tree
.selection
1537 appendChild
= not tree
.NeedInsert(selected
)
1538 xxx
= tree
.GetPyData(selected
)
1542 # If has previous item, insert after it, else append to parent
1544 selected
= tree
.GetPrevSibling(selected
)
1546 # Insert before nextItem
1547 parentLeaf
= tree
.GetItemParent(selected
)
1548 else: # last child: change selected to parent
1549 parentLeaf
= selected
= tree
.GetItemParent(nextItem
)
1551 # If has next item, insert, else append to parent
1552 nextItem
= tree
.GetNextSibling(selected
)
1554 # Insert before nextItem
1555 parentLeaf
= tree
.GetItemParent(selected
)
1556 else: # last child: change selected to parent
1558 selected
= tree
.GetItemParent(selected
)
1559 # Expanded container (must have children)
1561 # Can't use HasChildren because root always has
1562 if tree
.shift
and tree
.IsExpanded(selected
) \
1563 and tree
.GetChildrenCount(selected
, false
):
1565 nextItem
= tree
.GetFirstChild(selected
, 0)[0]
1566 parentLeaf
= selected
1567 # Parent should be tree element or None
1569 parent
= tree
.GetPyData(selected
)
1571 parent
= tree
.GetPyData(parentLeaf
)
1572 if parent
.hasChild
: parent
= parent
.child
1575 className
= self
.createMap
[evt
.GetId()]
1576 xxx
= MakeEmptyXXX(parent
, className
)
1578 # Set default name for top-level windows
1579 if parent
.__class
__ == xxxMainNode
:
1580 cl
= xxx
.treeObject().__class
__
1581 frame
.maxIDs
[cl
] += 1
1582 xxx
.treeObject().name
= '%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
])
1583 xxx
.treeObject().element
.setAttribute('name', xxx
.treeObject().name
)
1585 # Figure out if we must append a new child or sibling
1588 # Insert newline for debug purposes
1589 parent
.element
.appendChild(elem
)
1590 newItem
= tree
.AppendItem(selected
, xxx
.treeName(), image
=xxx
.treeImage(),
1591 data
=wxTreeItemData(xxx
))
1593 node
= tree
.GetPyData(nextItem
).element
1594 parent
.element
.insertBefore(elem
, node
)
1595 newItem
= tree
.InsertItem(parentLeaf
, selected
,
1596 xxx
.treeName(), image
=xxx
.treeImage(),
1597 data
=wxTreeItemData(xxx
))
1598 tree
.EnsureVisible(newItem
)
1599 tree
.SelectItem(newItem
)
1600 if not tree
.IsVisible(newItem
):
1601 tree
.ScrollTo(newItem
)
1604 if testWin
and tree
.GetItemAncestor(newItem
) == testWin
.item
:
1605 if conf
.autoRefresh
:
1606 tree
.needUpdate
= true
1607 tree
.pendingHighLight
= newItem
1609 tree
.pendingHighLight
= None
1611 # Expand/collapse subtree
1612 def OnExpand(self
, evt
):
1613 if tree
.selection
: tree
.ExpandAll(tree
.selection
)
1614 else: tree
.ExpandAll(tree
.root
)
1615 def OnCollapse(self
, evt
):
1616 if tree
.selection
: tree
.CollapseAll(tree
.selection
)
1617 else: tree
.CollapseAll(tree
.root
)
1619 def OnPullDownHighlight(self
, evt
):
1620 menuId
= evt
.GetMenuId()
1622 menu
= evt
.GetEventObject()
1623 help = menu
.GetHelpString(menuId
)
1624 self
.SetStatusText(help)
1626 self
.SetStatusText('')
1628 def OnUpdateUI(self
, evt
):
1629 if evt
.GetId() in [wxID_CUT
, wxID_COPY
, self
.ID_DELETE
]:
1630 evt
.Enable(tree
.selection
!= tree
.root
)
1631 elif evt
.GetId() == wxID_PASTE
:
1632 evt
.Enable((self
.clipboard
and tree
.selection
) != None)
1633 elif evt
.GetId() == self
.ID_TEST
:
1634 evt
.Enable(tree
.selection
!= tree
.root
)
1635 elif evt
.GetId() == self
.ID_REFRESH
:
1636 evt
.Enable(testWin
!= None)
1638 def OnIdle(self
, evt
):
1640 if conf
.autoRefresh
:
1643 tree
.CreateTestWin(testWin
.item
)
1644 tree
.needUpdate
= false
1645 elif tree
.pendingHighLight
:
1646 tree
.HighLight(tree
.pendingHighLight
)
1650 # We don't let close panel window
1651 def OnCloseMiniFrame(self
, evt
):
1654 def OnCloseWindow(self
, evt
):
1655 if not self
.AskSave(): return
1656 if testWin
: testWin
.Destroy()
1657 # Destroy cached windows
1658 panel
.cacheParent
.Destroy()
1659 # for w in panel.styleCache.values(): w.Destroy()
1660 if not panel
.GetPageCount() == 2:
1661 panel
.page2
.Destroy()
1662 conf
.x
, conf
.y
= self
.GetPosition()
1663 conf
.width
, conf
.height
= self
.GetSize()
1665 conf
.sashPos
= self
.splitter
.GetSashPosition()
1666 conf
.panelWidth
, conf
.panelHeight
= self
.panelWidth
, self
.panelHeight
1668 conf
.sashPos
= self
.sashPos
1669 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1670 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1675 self
.clipboard
= None
1676 self
.modified
= false
1677 panel
.SetModified(false
)
1684 self
.SetTitle(progname
)
1685 # Numbers for new controls
1687 self
.maxIDs
[xxxPanel
] = self
.maxIDs
[xxxDialog
] = self
.maxIDs
[xxxFrame
] = \
1688 self
.maxIDs
[xxxMenuBar
] = self
.maxIDs
[xxxMenu
] = self
.maxIDs
[xxxToolBar
] = 0
1690 def Open(self
, path
):
1691 # Try to read the file
1696 dom
= minidom
.parse(path
)
1698 self
.dataFile
= path
1699 self
.SetTitle(progname
+ ': ' + os
.path
.basename(path
))
1701 wxLogError('Error reading file: %s' % path
)
1704 def Indent(self
, node
, indent
= 0):
1705 # Copy child list because it will change soon
1706 children
= node
.childNodes
[:]
1707 # Main node doesn't need to be indented
1709 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1710 node
.parentNode
.insertBefore(text
, node
)
1712 # Append newline after last child, except for text nodes
1713 if children
[-1].nodeType
== minidom
.Node
.ELEMENT_NODE
:
1714 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1715 node
.appendChild(text
)
1716 # Indent children which are elements
1718 if n
.nodeType
== minidom
.Node
.ELEMENT_NODE
:
1719 self
.Indent(n
, indent
+ 2)
1721 def Save(self
, path
):
1724 self
.OnRefresh(wxCommandEvent())
1726 # Make temporary copy
1727 self
.domCopy
= domCopy
= tree
.dom
.cloneNode(true
)
1728 self
.Indent(domCopy
.getElementsByTagName('resource')[0])
1733 self
.modified
= false
1734 panel
.SetModified(false
)
1736 wxLogError('Error writing file: %s' % path
)
1740 if not (self
.modified
or panel
.IsModified()): return true
1741 flags
= wxICON_EXCLAMATION | wxYES_NO | wxCANCEL | wxCENTRE
1742 dlg
= wxMessageDialog( self
, 'File is modified. Save before exit?',
1743 'Save before too late?', flags
)
1744 say
= dlg
.ShowModal()
1747 self
.OnSaveOrSaveAs(wxCommandEvent(wxID_SAVE
))
1748 # If save was successful, modified flag is unset
1749 if not self
.modified
: return true
1750 elif say
== wxID_NO
:
1751 self
.modified
= false
1752 panel
.SetModified(false
)
1756 ################################################################################
1759 print >> sys
.stderr
, 'usage: xrced [-dvh] [file]'
1763 global debug
, verbose
1764 # Process comand-line
1766 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'dvh')
1767 except getopt
.GetoptError
:
1768 print >> sys
.stderr
, 'Unknown option'
1778 print 'XRCed version', version
1781 self
.SetAppName('xrced')
1784 conf
= wxConfig(style
= wxCONFIG_USE_LOCAL_FILE
)
1785 conf
.autoRefresh
= conf
.ReadInt('autorefresh', true
)
1786 pos
= conf
.ReadInt('x', -1), conf
.ReadInt('y', -1)
1787 size
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600)
1788 conf
.embedPanel
= conf
.ReadInt('embedPanel', true
)
1789 conf
.sashPos
= conf
.ReadInt('sashPos', 200)
1790 if not conf
.embedPanel
:
1791 conf
.panelX
= conf
.ReadInt('panelX', -1)
1792 conf
.panelY
= conf
.ReadInt('panelY', -1)
1794 conf
.panelX
= conf
.panelY
= -1
1795 conf
.panelWidth
= conf
.ReadInt('panelWidth', 200)
1796 conf
.panelHeight
= conf
.ReadInt('panelHeight', 200)
1797 conf
.panic
= not conf
.HasEntry('nopanic')
1799 wxFileSystem_AddHandler(wxMemoryFSHandler())
1800 wxInitAllImageHandlers()
1802 frame
= Frame(pos
, size
)
1804 # Load resources from XRC file (!!! should be transformed to .py later?)
1805 sys
.modules
['params'].frame
= frame
1806 frame
.res
= wxXmlResource('')
1807 frame
.res
.Load(os
.path
.join(sys
.path
[0], 'xrced.xrc'))
1809 # Load file after showing
1812 frame
.open = frame
.Open(args
[0])
1818 wc
= wxConfigBase_Get()
1819 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1820 wc
.WriteInt('x', conf
.x
)
1821 wc
.WriteInt('y', conf
.y
)
1822 wc
.WriteInt('width', conf
.width
)
1823 wc
.WriteInt('height', conf
.height
)
1824 wc
.WriteInt('embedPanel', conf
.embedPanel
)
1825 if not conf
.embedPanel
:
1826 wc
.WriteInt('panelX', conf
.panelX
)
1827 wc
.WriteInt('panelY', conf
.panelY
)
1828 wc
.WriteInt('sashPos', conf
.sashPos
)
1829 wc
.WriteInt('panelWidth', conf
.panelWidth
)
1830 wc
.WriteInt('panelHeight', conf
.panelHeight
)
1831 wc
.WriteInt('nopanic', 1)
1839 if __name__
== '__main__':