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 wxHtmlWindow
10 from xml
.dom
import minidom
19 # Return code from wxGetOsVersion
22 if wxGetOsVersion()[0] == wxGTK
:
23 labelFont
= wxFont(12, wxDEFAULT
, wxNORMAL
, wxBOLD
)
24 modernFont
= wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
)
26 labelFont
= wxFont(10, wxDEFAULT
, wxNORMAL
, wxBOLD
)
27 modernFont
= wxFont(10, wxMODERN
, wxNORMAL
, wxNORMAL
)
37 testWinPos
= wxDefaultPosition
39 # 1 adds CMD command to Help menu
43 <HTML><H2>Welcome to XRCed!</H2><H3><font color="green">DON'T PANIC :)</font></H3>
44 To start select tree root, then popup menu with your right mouse button,
45 select "Append Child", and then any command.<P>
46 Enter XML ID, change properties, create children.<P>
47 To test your interface select Test command (View menu).<P>
48 Consult README file for the details.</HTML>
51 defaultIDs
= {xxxPanel
:'PANEL', xxxDialog
:'DIALOG', xxxFrame
:'FRAME',
52 xxxMenuBar
:'MENUBAR', xxxMenu
:'MENU', xxxToolBar
:'TOOLBAR'}
54 # Set menu to list items.
55 # Each menu command is a tuple (id, label, help)
56 # submenus are lists [id, label, help, submenu]
57 # and separators are any other type
60 if type(l
) == types
.TupleType
:
62 elif type(l
) == types
.ListType
:
64 SetMenu(subMenu
, l
[2:])
65 m
.AppendMenu(wxNewId(), l
[0], subMenu
, l
[1])
69 ################################################################################
71 # Properties panel containing notebook
72 class Panel(wxNotebook
):
73 def __init__(self
, parent
, id = -1):
74 wxNotebook
.__init
__(self
, parent
, id, style
=wxNB_BOTTOM
)
75 sys
.modules
['params'].panel
= self
76 # List of child windows
78 # Create scrolled windows for pages
79 self
.page1
= wxScrolledWindow(self
, -1)
81 sizer
.Add(wxBoxSizer()) # dummy sizer
82 self
.page1
.SetAutoLayout(true
)
83 self
.page1
.SetSizer(sizer
)
84 self
.AddPage(self
.page1
, 'Properties')
86 self
.page2
= wxScrolledWindow(self
, -1)
88 sizer
.Add(wxBoxSizer()) # dummy sizer
89 self
.page2
.SetAutoLayout(true
)
90 self
.page2
.SetSizer(sizer
)
91 # Cache for already used panels
92 self
.pageCache
= {} # cached property panels
93 self
.stylePageCache
= {} # cached style panels
94 # Dummy parent window for cache pages
95 self
.cacheParent
= wxFrame(None, -1, 'non visible')
96 # Delete child windows and recreate page sizer
97 def ResetPage(self
, page
):
98 topSizer
= page
.GetSizer()
99 sizer
= topSizer
.GetChildren()[0].GetSizer()
100 for w
in page
.GetChildren():
101 sizer
.RemoveWindow(w
)
102 if isinstance(w
, ParamPage
):
103 # With SetParent, we wouldn't need this
104 w
.Reparent(self
.cacheParent
)
107 topSizer
.RemoveSizer(sizer
)
109 sizer
= wxBoxSizer(wxVERTICAL
)
110 # Special case - resize html window
112 topSizer
.Add(sizer
, 1, wxEXPAND
)
114 topSizer
.Add(sizer
, 0, wxALL
, 5)
116 def SetData(self
, xxx
):
119 # Set cached or new page
120 # Remove current objects and sizer
121 sizer
= self
.ResetPage(self
.page1
)
122 if not xxx
or (not xxx
.allParams
and not xxx
.hasName
):
124 sizer
.Add(wxStaticText(self
.page1
, -1, 'This item has no properties.'))
125 else: # nothing selected
126 # If first time, show some help
128 html
= wxHtmlWindow(self
.page1
, -1, wxDefaultPosition
,
129 wxDefaultSize
, wxSUNKEN_BORDER
)
130 html
.SetPage(helpText
)
131 sizer
.Add(html
, 1, wxEXPAND
)
134 sizer
.Add(wxStaticText(self
.page1
, -1, 'Select a tree item.'))
136 SetCurrentXXX(xxx
.treeObject())
138 page
= self
.pageCache
[xxx
.__class
__]
139 page
.Reparent(self
.page1
)
141 page
= PropPage(self
.page1
, xxx
.className
, xxx
)
142 self
.pageCache
[xxx
.__class
__] = page
144 self
.pages
.append(page
)
145 sizer
.Add(page
, 1, wxEXPAND
)
147 # Special label for child objects - they may have different GUI
148 cacheID
= (xxx
.child
.__class
__, xxx
.__class
__)
150 page
= self
.pageCache
[cacheID
]
151 page
.Reparent(self
.page1
)
153 page
= PropPage(self
.page1
, xxx
.child
.className
, xxx
.child
)
154 self
.pageCache
[cacheID
] = page
155 page
.SetValues(xxx
.child
)
156 self
.pages
.append(page
)
157 sizer
.Add(page
, 0, wxEXPAND | wxTOP
, 5)
159 size
= self
.page1
.GetSizer().GetMinSize()
160 self
.page1
.SetScrollbars(1, 1, size
.x
, size
.y
, 0, 0, true
)
163 # Create if does not exist
164 if xxx
and xxx
.treeObject().hasStyle
:
165 xxx
= xxx
.treeObject()
166 # Simplest case: set data if class is the same
167 sizer
= self
.ResetPage(self
.page2
)
169 page
= self
.stylePageCache
[xxx
.__class
__]
170 page
.Reparent(self
.page2
)
172 page
= StylePage(self
.page2
, xxx
.className
+ ' style', xxx
)
173 self
.stylePageCache
[xxx
.__class
__] = page
175 self
.pages
.append(page
)
176 sizer
.Add(page
, 0, wxEXPAND
)
177 # Add page if not exists
178 if not self
.GetPageCount() == 2:
179 self
.AddPage(self
.page2
, 'Style')
181 size
= self
.page2
.GetSizer().GetMinSize()
182 self
.page2
.SetScrollbars(1, 1, size
.x
, size
.y
, 0, 0, true
)
184 # Remove page if exists
185 if self
.GetPageCount() == 2:
191 # Check if some parameter on some page has changed
192 def IsModified(self
):
194 if p
.IsModified(): return true
196 # Reset changed state
197 def SetModified(self
, value
):
198 for p
in self
.pages
: p
.SetModified(value
)
200 for p
in self
.pages
: p
.Apply()
202 ################################################################################
204 # General class for notebook pages
205 class ParamPage(wxPanel
):
206 def __init__(self
, parent
, xxx
):
207 wxPanel
.__init
__(self
, parent
, -1)
209 # Register event handlers
210 for id in paramIDs
.values():
211 EVT_CHECKBOX(self
, id, self
.OnCheckParams
)
212 self
.modified
= false
214 self
.controls
= {} # save python objects
215 self
.controlName
= None
216 def OnCheckParams(self
, evt
):
218 param
= evt
.GetEventObject().GetName()
219 w
= self
.controls
[param
]
220 objElem
= xxx
.element
222 # Ad new text node in order of allParams
223 w
.SetValue('') # set empty (default) value
224 w
.SetModified() # mark as changed
225 elem
= tree
.dom
.createElement(param
)
226 # Some classes are special
228 xxx
.params
[param
] = xxxParamFont(xxx
.element
, elem
)
230 xxx
.params
[param
] = xxxParam(elem
)
231 # Find place to put new element: first present element after param
233 paramStyles
= xxx
.allParams
+ xxx
.styles
234 for p
in paramStyles
[paramStyles
.index(param
) + 1:]:
235 # Content params don't have same type
236 if xxx
.params
.has_key(p
) and p
!= 'content':
240 nextTextElem
= xxx
.params
[p
].node
241 objElem
.insertBefore(elem
, nextTextElem
)
243 objElem
.appendChild(elem
)
246 xxx
.params
[param
].remove()
247 del xxx
.params
[param
]
249 w
.modified
= false
# mark as not changed
251 self
.SetModified(true
)
252 w
.Enable(evt
.IsChecked())
253 # If some parameter has changed
254 def IsModified(self
):
256 def SetModified(self
, value
):
257 self
.modified
= value
261 # if xxx.undo: xxx.undo.unlink()
262 # xxx.undo = xxx.element.cloneNode(false)
264 name
= self
.controlName
.GetValue()
267 xxx
.element
.setAttribute('name', name
)
268 for param
, w
in self
.controls
.items():
270 paramObj
= xxx
.params
[param
]
272 if param
in xxx
.specials
:
273 xxx
.setSpecial(param
, value
)
275 paramObj
.update(value
)
277 ################################################################################
279 # Panel for displaying properties
280 class PropPage(ParamPage
):
281 def __init__(self
, parent
, label
, xxx
):
282 ParamPage
.__init
__(self
, parent
, xxx
)
283 box
= wxStaticBox(self
, -1, label
)
284 box
.SetFont(labelFont
)
285 topSizer
= wxStaticBoxSizer(box
, wxVERTICAL
)
286 sizer
= wxFlexGridSizer(len(xxx
.allParams
), 2, 1, 1)
288 label
= wxStaticText(self
, -1, 'XML ID:', size
=(100,-1))
289 control
= ParamText(self
, name
='XML_name')
290 sizer
.AddMany([ (label
, 0, wxALIGN_CENTER_VERTICAL
),
291 (control
, 0, wxALIGN_CENTER_VERTICAL
) ])
292 self
.controlName
= control
293 for param
in xxx
.allParams
:
294 present
= param
in xxx
.params
295 if param
in xxx
.required
:
296 label
= wxStaticText(self
, paramIDs
[param
], param
+ ':',
297 size
= (100,-1), name
= param
)
299 # Notebook has one very loooooong parameter
300 if param
== 'usenotebooksizer': sParam
= 'usesizer:'
301 else: sParam
= param
+ ':'
302 label
= wxCheckBox(self
, paramIDs
[param
], sParam
,
303 size
= (100,-1), name
= param
)
304 self
.checks
[param
] = label
306 typeClass
= xxx
.paramDict
[param
]
310 typeClass
= paramDict
[param
]
313 typeClass
= ParamText
314 control
= typeClass(self
, param
)
315 control
.Enable(present
)
316 sizer
.AddMany([ (label
, 0, wxALIGN_CENTER_VERTICAL
),
317 (control
, 0, wxALIGN_CENTER_VERTICAL
) ])
318 self
.controls
[param
] = control
319 topSizer
.Add(sizer
, 1, wxALL | wxEXPAND
, 3)
320 self
.SetAutoLayout(true
)
321 self
.SetSizer(topSizer
)
323 def SetValues(self
, xxx
):
325 # Set values, checkboxes to false, disable defaults
327 self
.controlName
.SetValue(xxx
.name
)
328 for param
in xxx
.allParams
:
329 w
= self
.controls
[param
]
332 value
= xxx
.params
[param
].value()
335 if not param
in xxx
.required
:
336 self
.checks
[param
].SetValue(true
)
338 self
.checks
[param
].SetValue(false
)
341 self
.SetModified(false
)
343 ################################################################################
345 # Style notebook page
346 class StylePage(ParamPage
):
347 def __init__(self
, parent
, label
, xxx
):
348 ParamPage
.__init
__(self
, parent
, xxx
)
349 box
= wxStaticBox(self
, -1, label
)
350 box
.SetFont(labelFont
)
351 topSizer
= wxStaticBoxSizer(box
, wxVERTICAL
)
352 sizer
= wxFlexGridSizer(len(xxx
.styles
), 2, 1, 1)
353 for param
in xxx
.styles
:
354 present
= param
in xxx
.params
.keys()
355 check
= wxCheckBox(self
, paramIDs
[param
],
356 param
+ ':', size
= (100,-1), name
= param
)
357 check
.SetValue(present
)
358 control
= paramDict
[param
](self
, name
= param
)
359 control
.Enable(present
)
360 sizer
.AddMany([ (check
, 0, wxALIGN_CENTER_VERTICAL
),
361 (control
, 0, wxALIGN_CENTER_VERTICAL
) ])
362 self
.checks
[param
] = check
363 self
.controls
[param
] = control
364 topSizer
.Add(sizer
, 1, wxALL | wxEXPAND
, 3)
365 self
.SetAutoLayout(true
)
366 self
.SetSizer(topSizer
)
368 # Set data for a cahced page
369 def SetValues(self
, xxx
):
371 for param
in xxx
.styles
:
372 present
= param
in xxx
.params
.keys()
373 check
= self
.checks
[param
]
374 check
.SetValue(present
)
375 w
= self
.controls
[param
]
378 w
.SetValue(xxx
.params
[param
].value())
382 self
.SetModified(false
)
384 ################################################################################
387 def __init__(self
, pos
, size
):
389 l1
= wxWindow(w
, -1, pos
, wxSize(size
.x
, 2))
390 l1
.SetBackgroundColour(wxRED
)
391 l2
= wxWindow(w
, -1, pos
, wxSize(2, size
.y
))
392 l2
.SetBackgroundColour(wxRED
)
393 l3
= wxWindow(w
, -1, wxPoint(pos
.x
+ size
.x
- 2, pos
.y
), wxSize(2, size
.y
))
394 l3
.SetBackgroundColour(wxRED
)
395 l4
= wxWindow(w
, -1, wxPoint(pos
.x
, pos
.y
+ size
.y
- 2), wxSize(size
.x
, 2))
396 l4
.SetBackgroundColour(wxRED
)
397 self
.lines
= [l1
, l2
, l3
, l4
]
398 # Move highlight to a new position
399 def Replace(self
, pos
, size
):
400 self
.lines
[0].SetDimensions(pos
.x
, pos
.y
, size
.x
, 2, wxSIZE_ALLOW_MINUS_ONE
)
401 self
.lines
[1].SetDimensions(pos
.x
, pos
.y
, 2, size
.y
, wxSIZE_ALLOW_MINUS_ONE
)
402 self
.lines
[2].SetDimensions(pos
.x
+ size
.x
- 2, pos
.y
, 2, size
.y
,
403 wxSIZE_ALLOW_MINUS_ONE
)
404 self
.lines
[3].SetDimensions(pos
.x
, pos
.y
+ size
.y
- 2, size
.x
, 2,
405 wxSIZE_ALLOW_MINUS_ONE
)
408 map(wxWindow
.Destroy
, self
.lines
)
409 testWin
.highLight
= None
411 ################################################################################
414 def __init__(self
, name
):
417 def write(self
, data
):
418 self
.buffer += data
.encode()
420 wxMemoryFSHandler_AddFile(self
.name
, self
.buffer)
422 class XML_Tree(wxTreeCtrl
):
423 def __init__(self
, parent
, id):
424 wxTreeCtrl
.__init
__(self
, parent
, id, style
= wxTR_HAS_BUTTONS
)
425 self
.SetBackgroundColour(wxColour(224, 248, 224))
426 EVT_TREE_SEL_CHANGED(self
, self
.GetId(), self
.OnSelChanged
)
427 # One works on Linux, another on Windows
428 if wxGetOsVersion()[0] == wxGTK
:
429 EVT_TREE_ITEM_ACTIVATED(self
, self
.GetId(), self
.OnItemActivated
)
431 EVT_LEFT_DCLICK(self
, self
.OnDClick
)
432 EVT_RIGHT_DOWN(self
, self
.OnRightDown
)
434 self
.needUpdate
= false
435 self
.pendingHighLight
= None
436 self
.ctrl
= self
.shift
= false
439 il
= wxImageList(16, 16, true
)
440 self
.rootImage
= il
.AddIcon(wxIconFromXPMData(images
.getTreeRootData()))
441 xxxObject
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeDefaultData()))
442 xxxPanel
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreePanelData()))
443 xxxDialog
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeDialogData()))
444 xxxFrame
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeFrameData()))
445 xxxMenuBar
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeMenuBarData()))
446 xxxToolBar
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeToolBarData()))
447 xxxMenu
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeMenuData()))
448 xxxSizer
.imageH
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerHData()))
449 xxxSizer
.imageV
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerVData()))
450 xxxStaticBoxSizer
.imageH
= il
.AddIcon(wxIconFromXPMData(images
.getTreeStaticBoxSizerHData()))
451 xxxStaticBoxSizer
.imageV
= il
.AddIcon(wxIconFromXPMData(images
.getTreeStaticBoxSizerVData()))
452 xxxGridSizer
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerGridData()))
453 xxxFlexGridSizer
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerFlexGridData()))
455 self
.SetImageList(il
)
458 self
.selection
= None
459 wxTreeCtrl
.Unselect(self
)
461 def ExpandAll(self
, item
):
462 if self
.ItemHasChildren(item
):
464 i
, cookie
= self
.GetFirstChild(item
, 0)
468 i
, cookie
= self
.GetNextChild(item
, cookie
)
471 def CollapseAll(self
, item
):
472 if self
.ItemHasChildren(item
):
473 i
, cookie
= self
.GetFirstChild(item
, 0)
477 i
, cookie
= self
.GetNextChild(item
, cookie
)
484 self
.DeleteAllItems()
485 # Add minimal structure
486 if self
.dom
: self
.dom
.unlink()
487 self
.dom
= minidom
.Document()
488 self
.dummyNode
= self
.dom
.createComment('dummy node')
490 self
.mainNode
= self
.dom
.createElement('resource')
491 self
.dom
.appendChild(self
.mainNode
)
492 xxx
= xxxMainNode(None, self
.mainNode
)
493 self
.root
= self
.AddRoot('XML tree', self
.rootImage
, data
=wxTreeItemData(xxx
))
494 self
.SetItemHasChildren(self
.root
)
495 self
.Expand(self
.root
)
498 # Clear old data and set new
499 def SetData(self
, dom
):
500 self
.DeleteAllItems()
501 # Add minimal structure
502 if self
.dom
: self
.dom
.unlink()
504 self
.dummyNode
= self
.dom
.createComment('dummy node')
505 # Find 'resource' child, add it's children
506 self
.mainNode
= dom
.getElementsByTagName('resource')[0]
507 xxx
= xxxMainNode(None, self
.mainNode
)
508 self
.root
= self
.AddRoot('XML tree', self
.rootImage
, data
=wxTreeItemData(xxx
))
509 self
.SetItemHasChildren(self
.root
)
510 nodes
= self
.mainNode
.childNodes
[:]
513 self
.AddNode(self
.root
, None, node
)
515 self
.mainNode
.removeChild(node
)
517 self
.Expand(self
.root
)
520 # Add tree item for given parent item if node is DOM element node with
521 # 'object' tag. xxxParent is parent xxx object
522 def AddNode(self
, itemParent
, xxxParent
, node
):
523 # Set item data to current node
525 xxx
= MakeXXXFromDOM(xxxParent
, node
)
527 print 'ERROR: MakeXXXFromDom(%s, %s)' % (xxxParent
, node
)
529 treeObj
= xxx
.treeObject()
531 item
= self
.AppendItem(itemParent
, treeObj
.treeName(),
532 image
=treeObj
.treeImage(),
533 data
=wxTreeItemData(xxx
))
534 # Try to find children objects
535 if treeObj
.hasChildren
:
536 nodes
= treeObj
.element
.childNodes
[:]
539 self
.AddNode(item
, treeObj
, n
)
540 elif n
.nodeType
!= minidom
.Node
.ELEMENT_NODE
:
541 treeObj
.element
.removeChild(n
)
543 # Remove leaf of tree, return it's data object
544 def RemoveLeaf(self
, leaf
):
545 xxx
= self
.GetPyData(leaf
)
547 parent
= node
.parentNode
548 parent
.removeChild(node
)
550 # Reset selection object
551 self
.selection
= None
553 # Find position relative to the top-level window
554 def FindNodePos(self
, item
):
556 if item
== testWin
.item
: return wxPoint(0, 0)
557 itemParent
= self
.GetItemParent(item
)
559 obj
= self
.FindNodeObject(item
)
560 if self
.GetPyData(itemParent
).treeObject().__class
__ == xxxNotebook
:
561 notebook
= self
.FindNodeObject(itemParent
)
563 for i
in range(notebook
.GetPageCount()):
564 if notebook
.GetPage(i
) == obj
:
565 if notebook
.GetSelection() != i
: notebook
.SetSelection(i
)
567 # Find first ancestor which is a wxWindow (not a sizer)
568 winParent
= itemParent
569 while self
.GetPyData(winParent
).isSizer
:
570 winParent
= self
.GetItemParent(winParent
)
571 parentPos
= self
.FindNodePos(winParent
)
572 # Position (-1,-1) is really (0,0)
573 pos
= obj
.GetPosition()
574 if pos
== (-1,-1): pos
= (0,0)
575 return parentPos
+ pos
576 # Find window (or sizer) corresponding to a tree item.
577 def FindNodeObject(self
, item
):
578 if item
== testWin
.item
: return testWin
.panel
579 itemParent
= self
.GetItemParent(item
)
580 # If top-level, return testWin (or panel if wxFrame)
581 xxx
= self
.GetPyData(item
).treeObject()
582 parentWin
= self
.FindNodeObject(itemParent
)
583 # Top-level sizer? return window's sizer
584 if xxx
.isSizer
and isinstance(parentWin
, wxWindowPtr
):
585 return parentWin
.GetSizer()
586 # Otherwise get parent's object and it's child
587 n
= 0 # index of sibling
588 prev
= self
.GetPrevSibling(item
)
590 prev
= self
.GetPrevSibling(prev
)
592 child
= parentWin
.GetChildren()[n
]
593 # Return window or sizer for sizer items
594 if child
.GetClassName() == 'wxSizerItem':
595 if child
.IsWindow(): child
= child
.GetWindow()
596 elif child
.IsSizer():
597 child
= child
.GetSizer()
598 # Test for notebook sizers
599 if isinstance(child
, wxNotebookSizerPtr
):
600 child
= child
.GetNotebook()
602 def OnSelChanged(self
, evt
):
604 # !!! problem with wxGTK - GetOldItem is Ok if nothing selected
605 #oldItem = evt.GetOldItem()
607 oldItem
= self
.selection
609 xxx
= self
.GetPyData(oldItem
)
610 # If some data was modified, apply changes
611 if panel
.IsModified():
612 self
.Apply(xxx
, oldItem
)
613 #if conf.autoRefresh:
615 if testWin
.highLight
and not tree
.IsHighlatable(oldItem
):
616 testWin
.highLight
.Remove()
617 self
.needUpdate
= true
618 status
= 'Changes were applied'
619 frame
.SetStatusText(status
)
621 self
.selection
= evt
.GetItem()
622 if not self
.selection
.IsOk():
623 self
.selection
= None
625 xxx
= self
.GetPyData(self
.selection
)
629 panel
.SetModified(false
)
630 # Hightlighting is done in OnIdle
631 tree
.pendingHighLight
= self
.selection
632 # Check if item is in testWin subtree
633 def IsHighlatable(self
, item
):
634 if item
== testWin
.item
: return false
635 while item
!= self
.root
:
636 item
= self
.GetItemParent(item
)
637 if item
== testWin
.item
: return true
639 # Highlight selected item
640 def HighLight(self
, item
):
641 self
.pendingHighLight
= None
642 if not testWin
or self
.GetPyData(testWin
.item
).className \
643 not in ['wxDialog', 'wxPanel', 'wxFrame']:
645 # Top-level does not have highlight
646 if item
== testWin
.item
or item
== tree
.root
:
647 if testWin
.highLight
: testWin
.highLight
.Remove()
649 # If a control from another window is selected, remove highlight
650 if not self
.IsHighlatable(item
):
651 if testWin
.highLight
: testWin
.highLight
.Remove()
653 # Get window/sizer object
654 obj
, pos
= self
.FindNodeObject(item
), self
.FindNodePos(item
)
657 # Nagative positions are not working wuite well
658 if testWin
.highLight
:
659 testWin
.highLight
.Replace(pos
, size
)
661 testWin
.highLight
= HightLightBox(pos
, size
)
662 testWin
.highLight
.item
= item
663 def ShowTestWindow(self
, item
):
665 xxx
= self
.GetPyData(item
)
666 if panel
.IsModified():
667 self
.Apply(xxx
, item
) # apply changes
668 treeObj
= xxx
.treeObject()
669 if treeObj
.className
not in ['wxFrame', 'wxPanel', 'wxDialog',
670 'wxMenuBar', 'wxToolBar']:
671 wxLogMessage('No view for this element (yet)')
674 wxLogError("Can't display a noname element!")
678 self
.SetItemBold(testWin
.item
, false
)
679 self
.SetItemBold(item
)
680 self
.CreateTestWin(item
)
681 # Double-click on Linux
682 def OnItemActivated(self
, evt
):
683 if evt
.GetItem() != self
.root
:
684 self
.ShowTestWindow(evt
.GetItem())
685 # Double-click on Windows
686 def OnDClick(self
, evt
):
687 item
, flags
= self
.HitTest(evt
.GetPosition())
688 if flags
in [wxTREE_HITTEST_ONITEMBUTTON
, wxTREE_HITTEST_ONITEMLABEL
]:
689 if item
!= self
.root
: self
.ShowTestWindow(item
)
692 # (re)create test window
693 def CreateTestWin(self
, item
):
696 # Create a window with this resource
697 xxx
= self
.GetPyData(item
).treeObject()
698 # Close old window, remember where it was
701 pos
= testWin
.GetPosition()
702 if item
== testWin
.item
:
703 # Remember highlight if same top-level window
704 if testWin
.highLight
:
705 highLight
= testWin
.highLight
.item
706 # !!! if 0 is removed, refresh is broken (notebook not deleted?)
707 if xxx
.className
== 'wxPanel':
708 if testWin
.highLight
:
709 testWin
.pendingHighLight
= highLight
710 testWin
.highLight
.Remove()
711 testWin
.panel
.Destroy()
722 memFile
= MemoryFile('xxx.xrc')
723 # Create partial XML file - faster for big files
725 dom
= minidom
.Document()
726 mainNode
= dom
.createElement('resource')
727 dom
.appendChild(mainNode
)
729 # Remove temporarily from old parent
731 parent
= elem
.parentNode
732 next
= elem
.nextSibling
733 parent
.replaceChild(self
.dummyNode
, elem
)
734 # Append to new DOM, write it
735 mainNode
.appendChild(elem
)
736 dom
.writexml(memFile
)
738 mainNode
.removeChild(elem
)
740 parent
.replaceChild(elem
, self
.dummyNode
)
741 memFile
.close() # write to wxMemoryFS
742 res
= wxXmlResource('')
743 res
.Load('memory:xxx.xrc')
744 if xxx
.className
== 'wxFrame':
746 testWin
= wxPreFrame()
747 res
.LoadFrame(testWin
, frame
, xxx
.name
)
749 testWin
.CreateStatusBar()
750 testWin
.panel
= testWin
751 testWin
.SetPosition(pos
)
753 elif xxx
.className
== 'wxPanel':
756 testWin
= wxFrame(frame
, -1, 'Panel: ' + xxx
.name
, pos
=pos
)
757 testWin
.panel
= res
.LoadPanel(testWin
, xxx
.name
)
758 testWin
.SetClientSize(testWin
.panel
.GetSize())
760 elif xxx
.className
== 'wxDialog':
762 testWin
= res
.LoadDialog(None, xxx
.name
)
763 testWin
.panel
= testWin
765 testWin
.SetPosition(pos
)
767 elif xxx
.className
== 'wxMenuBar':
768 testWin
= wxFrame(frame
, -1, 'MenuBar: ' + xxx
.name
, pos
=pos
)
770 # Set status bar to display help
771 testWin
.CreateStatusBar()
772 testWin
.menuBar
= res
.LoadMenuBar(xxx
.name
)
773 testWin
.SetMenuBar(testWin
.menuBar
)
775 elif xxx
.className
== 'wxToolBar':
776 testWin
= wxFrame(frame
, -1, 'ToolBar: ' + xxx
.name
, pos
=pos
)
778 # Set status bar to display help
779 testWin
.CreateStatusBar()
780 testWin
.toolBar
= res
.LoadToolBar(testWin
, xxx
.name
)
781 testWin
.SetToolBar(testWin
.toolBar
)
783 wxMemoryFSHandler_RemoveFile('xxx.xrc')
785 EVT_CLOSE(testWin
, self
.OnCloseTestWin
)
786 EVT_BUTTON(testWin
, wxID_OK
, self
.OnCloseTestWin
)
787 EVT_BUTTON(testWin
, wxID_CANCEL
, self
.OnCloseTestWin
)
788 testWin
.highLight
= None
789 if highLight
and not tree
.pendingHighLight
:
790 self
.HighLight(highLight
)
793 def OnCloseTestWin(self
, evt
):
794 global testWin
, testWinPos
795 self
.SetItemBold(testWin
.item
, false
)
796 testWinPos
= testWin
.GetPosition()
800 # Return item index in parent
801 def ItemIndex(self
, parent
, item
):
803 it
, cookie
= self
.GetFirstChild(parent
, 0)
806 it
, cookie
= self
.GetNextChild(parent
, cookie
)
809 # True if next item should be inserted after current (vs. appended to it)
810 def NeedInsert(self
, item
):
811 xxx
= self
.GetPyData(item
)
812 if item
== self
.root
: return false
# root item
813 if xxx
.hasChildren
and not self
.GetChildrenCount(item
, false
):
815 return not (self
.IsExpanded(item
) and self
.GetChildrenCount(item
, false
))
818 def OnRightDown(self
, evt
):
820 pt
= evt
.GetPosition();
821 item
, flags
= self
.HitTest(pt
)
822 if item
.Ok() and flags
& wxTREE_HITTEST_ONITEM
:
823 self
.SelectItem(item
)
828 item
= self
.selection
830 menu
.Append(pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand tree')
831 menu
.Append(pullDownMenu
.ID_COLLAPSE
, 'Collapse', 'Collapse tree')
833 self
.ctrl
= evt
.ControlDown() # save Ctrl state
834 self
.shift
= evt
.ShiftDown() # and Shift too
835 m
= wxMenu() # create menu
839 needInsert
= self
.NeedInsert(item
)
840 if item
== self
.root
or needInsert
and self
.GetItemParent(item
) == self
.root
:
841 m
.Append(pullDownMenu
.ID_NEW_PANEL
, 'Panel', 'Create panel')
842 m
.Append(pullDownMenu
.ID_NEW_DIALOG
, 'Dialog', 'Create dialog')
843 m
.Append(pullDownMenu
.ID_NEW_FRAME
, 'Frame', 'Create frame')
845 m
.Append(pullDownMenu
.ID_NEW_TOOL_BAR
, 'ToolBar', 'Create toolbar')
846 m
.Append(pullDownMenu
.ID_NEW_MENU_BAR
, 'MenuBar', 'Create menubar')
847 m
.Append(pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu')
849 xxx
= self
.GetPyData(item
).treeObject()
850 # Check parent for possible child nodes if inserting sibling
851 if needInsert
: xxx
= xxx
.parent
852 if xxx
.__class
__ == xxxMenuBar
:
853 m
.Append(pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu')
854 elif xxx
.__class
__ in [xxxToolBar
, xxxTool
] or \
855 xxx
.__class
__ == xxxSeparator
and xxx
.parent
.__class
__ == xxxToolBar
:
856 SetMenu(m
, pullDownMenu
.toolBarControls
)
857 elif xxx
.__class
__ in [xxxMenu
, xxxMenuItem
]:
858 SetMenu(m
, pullDownMenu
.menuControls
)
860 SetMenu(m
, pullDownMenu
.controls
)
861 if xxx
.__class
__ == xxxNotebook
:
862 m
.Enable(m
.FindItem('sizer'), false
)
863 elif not (xxx
.isSizer
or xxx
.parent
and xxx
.parent
.isSizer
):
864 m
.Enable(pullDownMenu
.ID_NEW_SPACER
, false
)
865 # Select correct label for create menu
868 menu
.AppendMenu(wxNewId(), 'Insert Child', m
,
869 'Create child object as the first child')
871 menu
.AppendMenu(wxNewId(), 'Append Child', m
,
872 'Create child object as the last child')
875 menu
.AppendMenu(wxNewId(), 'Create Sibling', m
,
876 'Create sibling before selected object')
878 menu
.AppendMenu(wxNewId(), 'Create Sibling', m
,
879 'Create sibling after selected object')
880 menu
.AppendSeparator()
881 # Not using standart IDs because we don't want to show shortcuts
882 menu
.Append(wxID_CUT
, 'Cut', 'Cut to the clipboard')
883 menu
.Append(wxID_COPY
, 'Copy', 'Copy to the clipboard')
884 if self
.ctrl
and item
!= tree
.root
:
885 menu
.Append(pullDownMenu
.ID_PASTE_SIBLING
, 'Paste Sibling',
886 'Paste from the clipboard as a sibling')
888 menu
.Append(wxID_PASTE
, 'Paste', 'Paste from the clipboard')
889 menu
.Append(pullDownMenu
.ID_DELETE
,
890 'Delete', 'Delete object')
891 if self
.ItemHasChildren(item
):
892 menu
.AppendSeparator()
893 menu
.Append(pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand subtree')
894 menu
.Append(pullDownMenu
.ID_COLLAPSE
, 'Collapse', 'Collapse subtree')
895 self
.PopupMenu(menu
, evt
.GetPosition())
899 def Apply(self
, xxx
, item
):
902 xxx
= xxx
.treeObject()
903 if xxx
.hasName
and self
.GetItemText(item
) != xxx
.name
:
904 self
.SetItemText(item
, xxx
.treeName())
905 # Change tree icon for sizers
906 if isinstance(xxx
, xxxBoxSizer
):
907 self
.SetItemImage(item
, xxx
.treeImage())
908 # Set global modified state
909 frame
.modified
= true
912 ID_NEW_PANEL
= wxNewId()
913 ID_NEW_DIALOG
= wxNewId()
914 ID_NEW_FRAME
= wxNewId()
915 ID_NEW_TOOL_BAR
= wxNewId()
916 ID_NEW_TOOL
= wxNewId()
917 ID_NEW_MENU_BAR
= wxNewId()
918 ID_NEW_MENU
= wxNewId()
920 ID_NEW_STATIC_TEXT
= wxNewId()
921 ID_NEW_TEXT_CTRL
= wxNewId()
923 ID_NEW_BUTTON
= wxNewId()
924 ID_NEW_BITMAP_BUTTON
= wxNewId()
925 ID_NEW_RADIO_BUTTON
= wxNewId()
926 ID_NEW_SPIN_BUTTON
= wxNewId()
928 ID_NEW_STATIC_BOX
= wxNewId()
929 ID_NEW_CHECK_BOX
= wxNewId()
930 ID_NEW_RADIO_BOX
= wxNewId()
931 ID_NEW_COMBO_BOX
= wxNewId()
932 ID_NEW_LIST_BOX
= wxNewId()
934 ID_NEW_STATIC_LINE
= wxNewId()
935 ID_NEW_STATIC_BITMAP
= wxNewId()
936 ID_NEW_CHOICE
= wxNewId()
937 ID_NEW_SLIDER
= wxNewId()
938 ID_NEW_GAUGE
= wxNewId()
939 ID_NEW_SCROLL_BAR
= wxNewId()
940 ID_NEW_TREE_CTRL
= wxNewId()
941 ID_NEW_LIST_CTRL
= wxNewId()
942 ID_NEW_CHECK_LIST
= wxNewId()
943 ID_NEW_NOTEBOOK
= wxNewId()
944 ID_NEW_HTML_WINDOW
= wxNewId()
945 ID_NEW_CALENDAR
= wxNewId()
947 ID_NEW_BOX_SIZER
= wxNewId()
948 ID_NEW_STATIC_BOX_SIZER
= wxNewId()
949 ID_NEW_GRID_SIZER
= wxNewId()
950 ID_NEW_FLEX_GRID_SIZER
= wxNewId()
951 ID_NEW_SPACER
= wxNewId()
952 ID_NEW_TOOL_BAR
= wxNewId()
953 ID_NEW_TOOL
= wxNewId()
954 ID_NEW_MENU
= wxNewId()
955 ID_NEW_MENU_ITEM
= wxNewId()
956 ID_NEW_SEPARATOR
= wxNewId()
957 ID_NEW_LAST
= wxNewId()
958 ID_EXPAND
= wxNewId()
959 ID_COLLAPSE
= wxNewId()
960 ID_PASTE_SIBLING
= wxNewId()
962 def __init__(self
, parent
):
963 self
.ID_DELETE
= parent
.ID_DELETE
964 EVT_MENU_RANGE(parent
, self
.ID_NEW_PANEL
,
965 self
.ID_NEW_LAST
, parent
.OnCreate
)
966 EVT_MENU(parent
, self
.ID_COLLAPSE
, parent
.OnCollapse
)
967 EVT_MENU(parent
, self
.ID_EXPAND
, parent
.OnExpand
)
968 EVT_MENU(parent
, self
.ID_PASTE_SIBLING
, parent
.OnPaste
)
969 # We connect to tree, but process in frame
970 EVT_MENU_HIGHLIGHT_ALL(tree
, parent
.OnPullDownHighlight
)
972 ################################################################################
974 # ScrolledMessageDialog - modified from wxPython lib to set fixed-width font
975 class ScrolledMessageDialog(wxDialog
):
976 def __init__(self
, parent
, msg
, caption
, pos
= wxDefaultPosition
, size
= (500,300)):
977 from wxPython
.lib
.layoutf
import Layoutf
978 wxDialog
.__init
__(self
, parent
, -1, caption
, pos
, size
)
979 text
= wxTextCtrl(self
, -1, msg
, wxDefaultPosition
,
980 wxDefaultSize
, wxTE_MULTILINE | wxTE_READONLY
)
981 text
.SetFont(modernFont
)
982 dc
= wxWindowDC(text
)
983 w
, h
= dc
.GetTextExtent(' ')
984 ok
= wxButton(self
, wxID_OK
, "OK")
985 text
.SetConstraints(Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self
,ok
)))
986 text
.SetSize((w
* 80 + 30, h
* 40))
987 ok
.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!25', (self
,)))
988 self
.SetAutoLayout(TRUE
)
990 self
.CenterOnScreen(wxBOTH
)
992 ################################################################################
994 class Frame(wxFrame
):
995 def __init__(self
, pos
, size
):
998 wxFrame
.__init
__(self
, None, -1, '', pos
, size
)
999 self
.CreateStatusBar()
1000 icon
= wxIcon(os
.path
.join(sys
.path
[0], 'xrced.ico'), wxBITMAP_TYPE_ICO
)
1007 menuBar
= wxMenuBar()
1010 menu
.Append(wxID_NEW
, '&New\tCtrl-N', 'New file')
1011 menu
.Append(wxID_OPEN
, '&Open...\tCtrl-O', 'Open XRC file')
1012 menu
.Append(wxID_SAVE
, '&Save\tCtrl-S', 'Save XRC file')
1013 menu
.Append(wxID_SAVEAS
, 'Save &As...', 'Save XRC file under different name')
1014 menu
.AppendSeparator()
1015 menu
.Append(wxID_EXIT
, '&Quit\tCtrl-Q', 'Exit application')
1016 menuBar
.Append(menu
, '&File')
1019 menu
.Append(wxID_UNDO
, '&Undo\tCtrl-Z', 'Undo')
1020 menu
.Append(wxID_REDO
, '&Redo\tCtrl-Y', 'Redo')
1021 menu
.AppendSeparator()
1022 menu
.Append(wxID_CUT
, 'Cut\tCtrl-X', 'Cut to the clipboard')
1023 menu
.Append(wxID_COPY
, '&Copy\tCtrl-C', 'Copy to the clipboard')
1024 menu
.Append(wxID_PASTE
, '&Paste\tCtrl-V', 'Paste from the clipboard')
1025 self
.ID_DELETE
= wxNewId()
1026 menu
.Append(self
.ID_DELETE
, '&Delete\tCtrl-D', 'Delete object')
1027 menuBar
.Append(menu
, '&Edit')
1030 self
.ID_EMBED_PANEL
= wxNewId()
1031 menu
.Append(self
.ID_EMBED_PANEL
, '&Embed Panel',
1032 'Toggle embedding properties panel in the main window', true
)
1033 menu
.Check(self
.ID_EMBED_PANEL
, conf
.embedPanel
)
1034 menu
.AppendSeparator()
1035 self
.ID_TEST
= wxNewId()
1036 menu
.Append(self
.ID_TEST
, '&Test\tF5', 'Test window')
1037 self
.ID_REFRESH
= wxNewId()
1038 menu
.Append(self
.ID_REFRESH
, '&Refresh\tCtrl-R', 'Refresh test window')
1039 self
.ID_AUTO_REFRESH
= wxNewId()
1040 menu
.Append(self
.ID_AUTO_REFRESH
, '&Auto-refresh\tCtrl-A',
1041 'Toggle auto-refresh mode', true
)
1042 menu
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1043 menuBar
.Append(menu
, '&View')
1046 menu
.Append(wxID_ABOUT
, '&About...', 'About XCRed')
1047 self
.ID_README
= wxNewId()
1048 menu
.Append(self
.ID_README
, '&Readme...', 'View the README file')
1050 self
.ID_DEBUG_CMD
= wxNewId()
1051 menu
.Append(self
.ID_DEBUG_CMD
, 'CMD', 'Python command line')
1052 EVT_MENU(self
, self
.ID_DEBUG_CMD
, self
.OnDebugCMD
)
1053 menuBar
.Append(menu
, '&Help')
1055 self
.menuBar
= menuBar
1056 self
.SetMenuBar(menuBar
)
1059 tb
= self
.CreateToolBar(wxTB_HORIZONTAL | wxNO_BORDER | wxTB_FLAT
)
1060 tb
.SetToolBitmapSize((24, 23))
1061 tb
.AddSimpleTool(wxID_NEW
, '', images
.getNewBitmap(), 'New', 'New file')
1062 tb
.AddSimpleTool(wxID_OPEN
, '', images
.getOpenBitmap(), 'Open', 'Open file')
1063 tb
.AddSimpleTool(wxID_SAVE
, '', images
.getSaveBitmap(), 'Save', 'Save file')
1064 tb
.AddControl(wxStaticLine(tb
, -1, size
=(-1,23), style
=wxLI_VERTICAL
))
1065 tb
.AddSimpleTool(wxID_CUT
, '', images
.getCutBitmap(), 'Cut', 'Cut')
1066 tb
.AddSimpleTool(wxID_COPY
, '', images
.getCopyBitmap(), 'Copy', 'Copy')
1067 tb
.AddSimpleTool(wxID_PASTE
, '', images
.getPasteBitmap(), 'Paste', 'Paste')
1068 tb
.AddControl(wxStaticLine(tb
, -1, size
=(-1,23), style
=wxLI_VERTICAL
))
1069 tb
.AddSimpleTool(self
.ID_TEST
, '', images
.getTestBitmap(), 'Test', 'Test window')
1070 tb
.AddSimpleTool(self
.ID_REFRESH
, '', images
.getRefreshBitmap(),
1071 'Refresh', 'Refresh view')
1072 tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, '', images
.getAutoRefreshBitmap(),
1073 'Auto-refresh', 'Toggle auto-refresh mode', true
)
1074 if wxGetOsVersion()[0] == wxGTK
:
1075 tb
.AddSeparator() # otherwise auto-refresh sticks in status line
1076 tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1079 self
.minWidth
= tb
.GetSize()[0] # minimal width is the size of toolbar
1082 EVT_MENU(self
, wxID_NEW
, self
.OnNew
)
1083 EVT_MENU(self
, wxID_OPEN
, self
.OnOpen
)
1084 EVT_MENU(self
, wxID_SAVE
, self
.OnSaveOrSaveAs
)
1085 EVT_MENU(self
, wxID_SAVEAS
, self
.OnSaveOrSaveAs
)
1086 EVT_MENU(self
, wxID_EXIT
, self
.OnExit
)
1088 EVT_MENU(self
, wxID_UNDO
, self
.OnUndo
)
1089 EVT_MENU(self
, wxID_REDO
, self
.OnRedo
)
1090 EVT_MENU(self
, wxID_CUT
, self
.OnCut
)
1091 EVT_MENU(self
, wxID_COPY
, self
.OnCopy
)
1092 EVT_MENU(self
, wxID_PASTE
, self
.OnPaste
)
1093 EVT_MENU(self
, self
.ID_DELETE
, self
.OnDelete
)
1095 EVT_MENU(self
, self
.ID_EMBED_PANEL
, self
.OnEmbedPanel
)
1096 EVT_MENU(self
, self
.ID_TEST
, self
.OnTest
)
1097 EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
)
1098 EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
)
1100 EVT_MENU(self
, wxID_ABOUT
, self
.OnAbout
)
1101 EVT_MENU(self
, self
.ID_README
, self
.OnReadme
)
1104 EVT_UPDATE_UI(self
, wxID_CUT
, self
.OnUpdateUI
)
1105 EVT_UPDATE_UI(self
, wxID_COPY
, self
.OnUpdateUI
)
1106 EVT_UPDATE_UI(self
, wxID_PASTE
, self
.OnUpdateUI
)
1107 EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
)
1108 EVT_UPDATE_UI(self
, self
.ID_TEST
, self
.OnUpdateUI
)
1109 EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
)
1112 sizer
= wxBoxSizer(wxVERTICAL
)
1113 sizer
.Add(wxStaticLine(self
, -1), 0, wxEXPAND
)
1114 splitter
= wxSplitterWindow(self
, -1, style
=wxSP_3DSASH
)
1115 self
.splitter
= splitter
1116 splitter
.SetMinimumPaneSize(100)
1119 tree
= XML_Tree(splitter
, -1)
1120 sys
.modules
['xxx'].tree
= tree
1121 # !!! frame styles are broken
1122 # Miniframe for not embedded mode
1123 miniFrame
= wxFrame(self
, -1, 'Properties Panel',
1124 (conf
.panelX
, conf
.panelY
),
1125 (conf
.panelWidth
, conf
.panelHeight
))
1126 self
.miniFrame
= miniFrame
1127 sizer2
= wxBoxSizer()
1128 miniFrame
.SetAutoLayout(true
)
1129 miniFrame
.SetSizer(sizer2
)
1130 EVT_CLOSE(self
.miniFrame
, self
.OnCloseMiniFrame
)
1131 # Create panel for parameters
1134 panel
= Panel(splitter
)
1135 # Set plitter windows
1136 splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
1138 panel
= Panel(miniFrame
)
1139 sizer2
.Add(panel
, 1, wxEXPAND
)
1140 miniFrame
.Show(true
)
1141 splitter
.Initialize(tree
)
1142 sizer
.Add(splitter
, 1, wxEXPAND
)
1143 self
.SetAutoLayout(true
)
1144 self
.SetSizer(sizer
)
1146 # Init pull-down menu data
1148 pullDownMenu
= PullDownMenu(self
)
1149 # Mapping from IDs to element names
1151 pullDownMenu
.ID_NEW_PANEL
: 'wxPanel',
1152 pullDownMenu
.ID_NEW_DIALOG
: 'wxDialog',
1153 pullDownMenu
.ID_NEW_FRAME
: 'wxFrame',
1154 pullDownMenu
.ID_NEW_TOOL_BAR
: 'wxToolBar',
1155 pullDownMenu
.ID_NEW_TOOL
: 'tool',
1156 pullDownMenu
.ID_NEW_MENU_BAR
: 'wxMenuBar',
1157 pullDownMenu
.ID_NEW_MENU
: 'wxMenu',
1158 pullDownMenu
.ID_NEW_MENU_ITEM
: 'wxMenuItem',
1159 pullDownMenu
.ID_NEW_SEPARATOR
: 'separator',
1161 pullDownMenu
.ID_NEW_STATIC_TEXT
: 'wxStaticText',
1162 pullDownMenu
.ID_NEW_TEXT_CTRL
: 'wxTextCtrl',
1164 pullDownMenu
.ID_NEW_BUTTON
: 'wxButton',
1165 pullDownMenu
.ID_NEW_BITMAP_BUTTON
: 'wxBitmapButton',
1166 pullDownMenu
.ID_NEW_RADIO_BUTTON
: 'wxRadioButton',
1167 pullDownMenu
.ID_NEW_SPIN_BUTTON
: 'wxSpinButton',
1169 pullDownMenu
.ID_NEW_STATIC_BOX
: 'wxStaticBox',
1170 pullDownMenu
.ID_NEW_CHECK_BOX
: 'wxCheckBox',
1171 pullDownMenu
.ID_NEW_RADIO_BOX
: 'wxRadioBox',
1172 pullDownMenu
.ID_NEW_COMBO_BOX
: 'wxComboBox',
1173 pullDownMenu
.ID_NEW_LIST_BOX
: 'wxListBox',
1175 pullDownMenu
.ID_NEW_STATIC_LINE
: 'wxStaticLine',
1176 pullDownMenu
.ID_NEW_STATIC_BITMAP
: 'wxStaticBitmap',
1177 pullDownMenu
.ID_NEW_CHOICE
: 'wxChoice',
1178 pullDownMenu
.ID_NEW_SLIDER
: 'wxSlider',
1179 pullDownMenu
.ID_NEW_GAUGE
: 'wxGauge',
1180 pullDownMenu
.ID_NEW_SCROLL_BAR
: 'wxScrollBar',
1181 pullDownMenu
.ID_NEW_TREE_CTRL
: 'wxTreeCtrl',
1182 pullDownMenu
.ID_NEW_LIST_CTRL
: 'wxListCtrl',
1183 pullDownMenu
.ID_NEW_CHECK_LIST
: 'wxCheckList',
1184 pullDownMenu
.ID_NEW_NOTEBOOK
: 'wxNotebook',
1185 pullDownMenu
.ID_NEW_HTML_WINDOW
: 'wxHtmlWindow',
1186 pullDownMenu
.ID_NEW_CALENDAR
: 'wxCalendar',
1188 pullDownMenu
.ID_NEW_BOX_SIZER
: 'wxBoxSizer',
1189 pullDownMenu
.ID_NEW_STATIC_BOX_SIZER
: 'wxStaticBoxSizer',
1190 pullDownMenu
.ID_NEW_GRID_SIZER
: 'wxGridSizer',
1191 pullDownMenu
.ID_NEW_FLEX_GRID_SIZER
: 'wxFlexGridSizer',
1192 pullDownMenu
.ID_NEW_SPACER
: 'spacer',
1194 pullDownMenu
.controls
= [
1195 ['control', 'Various controls',
1196 (pullDownMenu
.ID_NEW_STATIC_TEXT
, 'Label', 'Create static label'),
1197 (pullDownMenu
.ID_NEW_STATIC_LINE
, 'Line', 'Create static line'),
1198 (pullDownMenu
.ID_NEW_TEXT_CTRL
, 'TextBox', 'Create text box control'),
1199 (pullDownMenu
.ID_NEW_CHOICE
, 'Choice', 'Create choice control'),
1200 (pullDownMenu
.ID_NEW_SLIDER
, 'Slider', 'Create slider control'),
1201 (pullDownMenu
.ID_NEW_GAUGE
, 'Gauge', 'Create gauge control'),
1202 (pullDownMenu
.ID_NEW_SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'),
1203 (pullDownMenu
.ID_NEW_TREE_CTRL
, 'TreeCtrl', 'Create tree control'),
1204 (pullDownMenu
.ID_NEW_LIST_CTRL
, 'ListCtrl', 'Create list control'),
1205 (pullDownMenu
.ID_NEW_HTML_WINDOW
, 'HtmlWindow', 'Create HTML window'),
1206 (pullDownMenu
.ID_NEW_CALENDAR
, 'Calendar', 'Create calendar control'),
1207 (pullDownMenu
.ID_NEW_PANEL
, 'Panel', 'Create panel'),
1208 (pullDownMenu
.ID_NEW_NOTEBOOK
, 'Notebook', 'Create notebook control'),
1210 ['button', 'Buttons',
1211 (pullDownMenu
.ID_NEW_BUTTON
, 'Button', 'Create button'),
1212 (pullDownMenu
.ID_NEW_BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'),
1213 (pullDownMenu
.ID_NEW_RADIO_BUTTON
, 'RadioButton', 'Create radio button'),
1214 (pullDownMenu
.ID_NEW_SPIN_BUTTON
, 'SpinButton', 'Create spin button'),
1217 (pullDownMenu
.ID_NEW_STATIC_BOX
, 'StaticBox', 'Create static box'),
1218 (pullDownMenu
.ID_NEW_CHECK_BOX
, 'CheckBox', 'Create check box'),
1219 (pullDownMenu
.ID_NEW_RADIO_BOX
, 'RadioBox', 'Create radio box'),
1220 (pullDownMenu
.ID_NEW_COMBO_BOX
, 'ComboBox', 'Create combo box'),
1221 (pullDownMenu
.ID_NEW_LIST_BOX
, 'ListBox', 'Create list box'),
1222 (pullDownMenu
.ID_NEW_CHECK_LIST
, 'CheckListBox',
1223 'Create check list control'),
1226 (pullDownMenu
.ID_NEW_BOX_SIZER
, 'BoxSizer', 'Create box sizer'),
1227 (pullDownMenu
.ID_NEW_STATIC_BOX_SIZER
, 'StaticBoxSizer',
1228 'Create static box sizer'),
1229 (pullDownMenu
.ID_NEW_GRID_SIZER
, 'GridSizer', 'Create grid sizer'),
1230 (pullDownMenu
.ID_NEW_FLEX_GRID_SIZER
, 'FlexGridSizer',
1231 'Create flexgrid sizer'),
1232 (pullDownMenu
.ID_NEW_SPACER
, 'Spacer', 'Create spacer'),
1235 pullDownMenu
.menuControls
= [
1236 (pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu'),
1237 (pullDownMenu
.ID_NEW_MENU_ITEM
, 'MenuItem', 'Create menu item'),
1238 (pullDownMenu
.ID_NEW_SEPARATOR
, 'Separator', 'Create separator'),
1240 pullDownMenu
.toolBarControls
= [
1241 (pullDownMenu
.ID_NEW_TOOL
, 'Tool', 'Create tool'),
1242 (pullDownMenu
.ID_NEW_SEPARATOR
, 'Separator', 'Create separator'),
1243 ['control', 'Various controls',
1244 (pullDownMenu
.ID_NEW_STATIC_TEXT
, 'Label', 'Create static label'),
1245 (pullDownMenu
.ID_NEW_STATIC_LINE
, 'Line', 'Create static line'),
1246 (pullDownMenu
.ID_NEW_TEXT_CTRL
, 'TextBox', 'Create text box control'),
1247 (pullDownMenu
.ID_NEW_CHOICE
, 'Choice', 'Create choice control'),
1248 (pullDownMenu
.ID_NEW_SLIDER
, 'Slider', 'Create slider control'),
1249 (pullDownMenu
.ID_NEW_GAUGE
, 'Gauge', 'Create gauge control'),
1250 (pullDownMenu
.ID_NEW_SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'),
1251 (pullDownMenu
.ID_NEW_LIST_CTRL
, 'ListCtrl', 'Create list control'),
1253 ['button', 'Buttons',
1254 (pullDownMenu
.ID_NEW_BUTTON
, 'Button', 'Create button'),
1255 (pullDownMenu
.ID_NEW_BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'),
1256 (pullDownMenu
.ID_NEW_RADIO_BUTTON
, 'RadioButton', 'Create radio button'),
1257 (pullDownMenu
.ID_NEW_SPIN_BUTTON
, 'SpinButton', 'Create spin button'),
1260 (pullDownMenu
.ID_NEW_STATIC_BOX
, 'StaticBox', 'Create static box'),
1261 (pullDownMenu
.ID_NEW_CHECK_BOX
, 'CheckBox', 'Create check box'),
1262 (pullDownMenu
.ID_NEW_RADIO_BOX
, 'RadioBox', 'Create radio box'),
1263 (pullDownMenu
.ID_NEW_COMBO_BOX
, 'ComboBox', 'Create combo box'),
1264 (pullDownMenu
.ID_NEW_LIST_BOX
, 'ListBox', 'Create list box'),
1265 (pullDownMenu
.ID_NEW_CHECK_LIST
, 'CheckListBox',
1266 'Create check list control'),
1274 EVT_IDLE(self
, self
.OnIdle
)
1275 EVT_CLOSE(self
, self
.OnCloseWindow
)
1277 def OnNew(self
, evt
):
1280 def OnOpen(self
, evt
):
1281 if not self
.AskSave(): return
1282 dlg
= wxFileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
1283 '', '*.xrc', wxOPEN | wxCHANGE_DIR
)
1284 if dlg
.ShowModal() == wxID_OK
:
1285 path
= dlg
.GetPath()
1286 self
.SetStatusText('Loading...')
1291 self
.SetStatusText('Data loaded')
1293 self
.SetStatusText('Failed')
1298 def OnSaveOrSaveAs(self
, evt
):
1299 if evt
.GetId() == wxID_SAVEAS
or not self
.dataFile
:
1300 if self
.dataFile
: defaultName
= ''
1301 else: defaultName
= 'UNTITLED.xrc'
1302 dlg
= wxFileDialog(self
, 'Save As', os
.path
.dirname(self
.dataFile
),
1303 defaultName
, '*.xrc',
1304 wxSAVE | wxOVERWRITE_PROMPT | wxCHANGE_DIR
)
1305 if dlg
.ShowModal() == wxID_OK
:
1306 path
= dlg
.GetPath()
1312 path
= self
.dataFile
1313 self
.SetStatusText('Saving...')
1318 self
.dataFile
= path
1319 self
.SetStatusText('Data saved')
1321 self
.SetStatusText('Failed')
1324 def OnExit(self
, evt
):
1327 def OnUndo(self
, evt
):
1328 print '*** being implemented'
1330 print self
.lastOp
, self
.undo
1331 if self
.lastOp
== 'DELETE':
1332 parent
, prev
, elem
= self
.undo
1334 xxx
= MakeXXXFromDOM(tree
.GetPyData(parent
).treeObject(), elem
)
1335 item
= tree
.InsertItem( parent
, prev
, xxx
.treeObject().className
,
1336 data
=wxTreeItemData(xxx
) )
1338 def OnRedo(self
, evt
):
1339 print '*** being implemented'
1341 def OnCut(self
, evt
):
1342 selected
= tree
.selection
1343 if not selected
: return # key pressed event
1346 self
.undo
= [tree
.GetItemParent(selected
), tree
.GetPrevSibling(selected
)]
1350 # If deleting top-level item, delete testWin
1351 if selected
== testWin
.item
:
1355 # Remove highlight, update testWin
1356 if not tree
.IsHighlatable(selected
):
1357 if testWin
.highLight
: testWin
.highLight
.Remove()
1358 tree
.needUpdate
= true
1359 self
.clipboard
= tree
.RemoveLeaf(selected
)
1360 tree
.pendingHighLight
= None
1363 self
.modified
= true
1364 self
.SetStatusText('Removed to clipboard')
1366 def OnCopy(self
, evt
):
1367 selected
= tree
.selection
1368 if not selected
: return # key pressed event
1369 xxx
= tree
.GetPyData(selected
)
1370 self
.clipboard
= xxx
.element
.cloneNode(true
)
1371 self
.SetStatusText('Copied')
1373 def OnPaste(self
, evt
):
1374 selected
= tree
.selection
1375 if not selected
: return # key pressed event
1376 # For pasting with Ctrl pressed
1377 if evt
.GetId() == pullDownMenu
.ID_PASTE_SIBLING
: appendChild
= false
1378 else: appendChild
= not tree
.NeedInsert(selected
)
1379 xxx
= tree
.GetPyData(selected
)
1381 # If has next item, insert, else append to parent
1382 nextItem
= tree
.GetNextSibling(selected
)
1384 # Insert before nextItem
1385 parentLeaf
= tree
.GetItemParent(selected
)
1386 else: # last child: change selected to parent
1388 selected
= tree
.GetItemParent(selected
)
1389 # Expanded container (must have children)
1390 elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, false
):
1392 nextItem
= tree
.GetFirstChild(selected
, 0)[0]
1393 parentLeaf
= selected
1394 # Parent should be tree element or None
1396 parent
= tree
.GetPyData(selected
)
1398 parent
= tree
.GetPyData(parentLeaf
)
1399 if parent
.hasChild
: parent
= parent
.child
1401 # Create a copy of clipboard element
1402 elem
= self
.clipboard
.cloneNode(true
)
1403 # Tempopary xxx object to test things
1404 xxx
= MakeXXXFromDOM(parent
, elem
)
1406 # Check compatibility
1409 x
= xxx
.treeObject()
1410 if x
.__class
__ in [xxxDialog
, xxxFrame
, xxxMenuBar
, xxxToolBar
]:
1411 if parent
.__class
__ != xxxMainNode
: error
= true
1412 elif x
.__class
__ == xxxPanel
and parent
.__class
__ == xxxMainNode
:
1414 elif x
.__class
__ == xxxSpacer
:
1415 if not parent
.isSizer
: error
= true
1416 elif x
.__class
__ == xxxSeparator
:
1417 if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error
= true
1418 elif x
.__class
__ == xxxTool
:
1419 if parent
.__class
__ != xxxToolBar
: error
= true
1420 elif x
.__class
__ == xxxMenuItem
:
1421 if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= true
1422 elif x
.isSizer
and parent
.__class
__ == xxxNotebook
: error
= true
1423 else: # normal controls can be almost anywhere
1424 if parent
.__class
__ == xxxMainNode
or \
1425 parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= true
1427 if parent
.__class
__ == xxxMainNode
: parentClass
= 'root'
1428 else: parentClass
= parent
.className
1429 wxLogError('Incompatible parent/child: parent is %s, child is %s!' %
1430 (parentClass
, x
.className
))
1433 # Check parent and child relationships.
1434 # If parent is sizer or notebook, child is of wrong class or
1435 # parent is normal window, child is child container then detach child.
1436 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
1437 if isChildContainer
and \
1438 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
1439 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
1440 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
1441 elem
.removeChild(xxx
.child
.element
) # detach child
1442 elem
.unlink() # delete child container
1443 elem
= xxx
.child
.element
# replace
1444 # This may help garbage collection
1445 xxx
.child
.parent
= None
1446 isChildContainer
= false
1447 # Parent is sizer or notebook, child is not child container
1448 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
1449 # Create sizer item element
1450 sizerItemElem
= MakeEmptyDOM('sizeritem')
1451 sizerItemElem
.appendChild(elem
)
1452 elem
= sizerItemElem
1453 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
1454 pageElem
= MakeEmptyDOM('notebookpage')
1455 pageElem
.appendChild(elem
)
1457 xxx
= MakeXXXFromDOM(parent
, elem
)
1458 # Figure out if we must append a new child or sibling
1460 parent
.element
.appendChild(elem
)
1461 newItem
= tree
.AppendItem(selected
, xxx
.treeName(), image
=xxx
.treeImage(),
1462 data
=wxTreeItemData(xxx
))
1464 node
= tree
.GetPyData(nextItem
).element
1465 parent
.element
.insertBefore(elem
, node
)
1466 # Inserting before is difficult, se we insert after or first child
1467 index
= tree
.ItemIndex(parentLeaf
, nextItem
)
1468 newItem
= tree
.InsertItemBefore(parentLeaf
, index
,
1469 xxx
.treeName(), image
=xxx
.treeImage())
1470 tree
.SetPyData(newItem
, xxx
)
1471 # newItem = tree.InsertItem(parentLeaf, selected, xxx.treeName(),
1472 # image=xxx.treeImage(), data=wxTreeItemData(xxx))
1473 # Add children items
1475 treeObj
= xxx
.treeObject()
1476 for n
in treeObj
.element
.childNodes
:
1478 tree
.AddNode(newItem
, treeObj
, n
)
1479 # Scroll to show new item
1480 tree
.EnsureVisible(newItem
)
1481 tree
.SelectItem(newItem
)
1482 if not tree
.IsVisible(newItem
):
1483 tree
.ScrollTo(newItem
)
1486 if testWin
and tree
.IsHighlatable(newItem
):
1487 if conf
.autoRefresh
:
1488 tree
.needUpdate
= true
1489 tree
.pendingHighLight
= newItem
1491 tree
.pendingHighLight
= None
1492 self
.modified
= true
1493 self
.SetStatusText('Pasted')
1495 def OnDelete(self
, evt
):
1496 selected
= tree
.selection
1497 if not selected
: return # key pressed event
1499 self
.lastOp
= 'DELETE'
1500 self
.undo
= [tree
.GetItemParent(selected
), tree
.GetPrevSibling(selected
)]
1504 # If deleting top-level item, delete testWin
1505 if selected
== testWin
.item
:
1509 # Remove highlight, update testWin
1510 if not tree
.IsHighlatable(selected
):
1511 if testWin
.highLight
: testWin
.highLight
.Remove()
1512 tree
.needUpdate
= true
1513 xnode
= tree
.RemoveLeaf(selected
)
1514 # !!! cloneNode is broken, or something is wrong
1515 # self.undo.append(xnode.cloneNode(true))
1517 tree
.pendingHighLight
= None
1520 self
.modified
= true
1521 self
.SetStatusText('Deleted')
1523 def OnEmbedPanel(self
, evt
):
1524 conf
.embedPanel
= evt
.IsChecked()
1526 # Remember last dimentions
1527 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1528 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1529 size
= self
.GetSize()
1530 pos
= self
.GetPosition()
1531 sizePanel
= panel
.GetSize()
1532 panel
.Reparent(self
.splitter
)
1533 self
.miniFrame
.GetSizer().RemoveWindow(panel
)
1536 self
.SetDimensions(pos
.x
, pos
.y
, size
.x
+ sizePanel
.x
, size
.y
)
1537 self
.splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
1538 self
.miniFrame
.Show(false
)
1540 conf
.sashPos
= self
.splitter
.GetSashPosition()
1541 pos
= self
.GetPosition()
1542 size
= self
.GetSize()
1543 sizePanel
= panel
.GetSize()
1544 self
.splitter
.Unsplit(panel
)
1545 sizer
= self
.miniFrame
.GetSizer()
1546 panel
.Reparent(self
.miniFrame
)
1548 sizer
.Add(panel
, 1, wxEXPAND
)
1549 self
.miniFrame
.Show(true
)
1550 self
.miniFrame
.SetDimensions(conf
.panelX
, conf
.panelY
,
1551 conf
.panelWidth
, conf
.panelHeight
)
1554 self
.SetDimensions(pos
.x
, pos
.y
,
1555 max(size
.x
- sizePanel
.x
, self
.minWidth
), size
.y
)
1557 def OnTest(self
, evt
):
1558 if not tree
.selection
: return # key pressed event
1559 tree
.ShowTestWindow(tree
.selection
)
1561 def OnRefresh(self
, evt
):
1562 # If modified, apply first
1563 selection
= tree
.selection
1565 xxx
= tree
.GetPyData(selection
)
1566 if xxx
and panel
.IsModified():
1567 tree
.Apply(xxx
, selection
)
1570 tree
.CreateTestWin(testWin
.item
)
1571 tree
.needUpdate
= false
1573 def OnAutoRefresh(self
, evt
):
1574 conf
.autoRefresh
= evt
.IsChecked()
1575 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1576 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1578 def OnAbout(self
, evt
):
1579 str = '%s %s\n\nRoman Rolinsky <rolinsky@mema.ucl.ac.be>' % \
1581 dlg
= wxMessageDialog(self
, str, 'About ' + progname
, wxOK | wxCENTRE
)
1585 def OnReadme(self
, evt
):
1586 text
= open(os
.path
.join(sys
.path
[0], 'README'), 'r').read()
1587 dlg
= ScrolledMessageDialog(self
, text
, "XRCed README")
1592 # Simple emulation of python command line
1593 def OnDebugCMD(self
, evt
):
1597 exec raw_input('C:\> ')
1602 (etype
, value
, tb
) =sys
.exc_info()
1603 tblist
=traceback
.extract_tb(tb
)[1:]
1604 msg
=string
.join(traceback
.format_exception_only(etype
, value
)
1605 +traceback
.format_list(tblist
))
1608 def OnCreate(self
, evt
):
1609 selected
= tree
.selection
1610 if tree
.ctrl
: appendChild
= false
1611 else: appendChild
= not tree
.NeedInsert(selected
)
1612 xxx
= tree
.GetPyData(selected
)
1616 # If has previous item, insert after it, else append to parent
1618 parentLeaf
= tree
.GetItemParent(selected
)
1620 # If has next item, insert, else append to parent
1621 nextItem
= tree
.GetNextSibling(selected
)
1623 # Insert before nextItem
1624 parentLeaf
= tree
.GetItemParent(selected
)
1625 else: # last child: change selected to parent
1627 selected
= tree
.GetItemParent(selected
)
1628 # Expanded container (must have children)
1629 elif tree
.shift
and tree
.IsExpanded(selected
) \
1630 and tree
.GetChildrenCount(selected
, false
):
1632 nextItem
= tree
.GetFirstChild(selected
, 0)[0]
1633 parentLeaf
= selected
1634 # Parent should be tree element or None
1636 parent
= tree
.GetPyData(selected
)
1638 parent
= tree
.GetPyData(parentLeaf
)
1639 if parent
.hasChild
: parent
= parent
.child
1642 className
= self
.createMap
[evt
.GetId()]
1643 xxx
= MakeEmptyXXX(parent
, className
)
1645 # Set default name for top-level windows
1646 if parent
.__class
__ == xxxMainNode
:
1647 cl
= xxx
.treeObject().__class
__
1648 frame
.maxIDs
[cl
] += 1
1649 xxx
.treeObject().name
= '%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
])
1650 xxx
.treeObject().element
.setAttribute('name', xxx
.treeObject().name
)
1652 # Figure out if we must append a new child or sibling
1655 # Insert newline for debug purposes
1656 parent
.element
.appendChild(elem
)
1657 newItem
= tree
.AppendItem(selected
, xxx
.treeName(), image
=xxx
.treeImage(),
1658 data
=wxTreeItemData(xxx
))
1660 node
= tree
.GetPyData(nextItem
).element
1661 parent
.element
.insertBefore(elem
, node
)
1662 # !!! There is a different behavious on Win and GTK
1663 # !!! On Win InsertItem(parent, parent, ...) inserts at the end.
1664 index
= tree
.ItemIndex(parentLeaf
, nextItem
)
1665 newItem
= tree
.InsertItemBefore(parentLeaf
, index
,
1666 xxx
.treeName(), image
=xxx
.treeImage())
1667 # data=wxTreeItemData(xxx)) # does not work
1668 tree
.SetPyData(newItem
, xxx
)
1669 # newItem = tree.InsertItem(parentLeaf, selected,
1670 # xxx.treeName(), image=xxx.treeImage(),
1671 # data=wxTreeItemData(xxx))
1672 tree
.EnsureVisible(newItem
)
1673 tree
.SelectItem(newItem
)
1674 if not tree
.IsVisible(newItem
):
1675 tree
.ScrollTo(newItem
)
1678 if testWin
and tree
.IsHighlatable(newItem
):
1679 if conf
.autoRefresh
:
1680 tree
.needUpdate
= true
1681 tree
.pendingHighLight
= newItem
1683 tree
.pendingHighLight
= None
1685 # Expand/collapse subtree
1686 def OnExpand(self
, evt
):
1687 if tree
.selection
: tree
.ExpandAll(tree
.selection
)
1688 else: tree
.ExpandAll(tree
.root
)
1689 def OnCollapse(self
, evt
):
1690 if tree
.selection
: tree
.CollapseAll(tree
.selection
)
1691 else: tree
.CollapseAll(tree
.root
)
1693 def OnPullDownHighlight(self
, evt
):
1694 menuId
= evt
.GetMenuId()
1696 menu
= evt
.GetEventObject()
1697 help = menu
.GetHelpString(menuId
)
1698 self
.SetStatusText(help)
1700 self
.SetStatusText('')
1702 def OnUpdateUI(self
, evt
):
1703 if evt
.GetId() in [wxID_CUT
, wxID_COPY
, self
.ID_DELETE
]:
1704 evt
.Enable(tree
.selection
!= tree
.root
)
1705 elif evt
.GetId() == wxID_PASTE
:
1706 evt
.Enable((self
.clipboard
and tree
.selection
) != None)
1707 elif evt
.GetId() == self
.ID_TEST
:
1708 evt
.Enable(tree
.selection
!= tree
.root
)
1710 def OnIdle(self
, evt
):
1711 if self
.inIdle
: return # Recursive call protection
1714 if conf
.autoRefresh
:
1716 self
.SetStatusText('Refreshing test window...')
1718 tree
.CreateTestWin(testWin
.item
)
1720 self
.SetStatusText('')
1721 tree
.needUpdate
= false
1722 elif tree
.pendingHighLight
:
1723 tree
.HighLight(tree
.pendingHighLight
)
1728 # We don't let close panel window
1729 def OnCloseMiniFrame(self
, evt
):
1732 def OnCloseWindow(self
, evt
):
1733 if not self
.AskSave(): return
1734 if testWin
: testWin
.Destroy()
1735 # Destroy cached windows
1736 panel
.cacheParent
.Destroy()
1737 if not panel
.GetPageCount() == 2:
1738 panel
.page2
.Destroy()
1739 conf
.x
, conf
.y
= self
.GetPosition()
1740 conf
.width
, conf
.height
= self
.GetSize()
1742 conf
.sashPos
= self
.splitter
.GetSashPosition()
1744 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1745 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1750 self
.clipboard
= None
1751 self
.modified
= false
1752 panel
.SetModified(false
)
1759 self
.SetTitle(progname
)
1760 # Numbers for new controls
1762 self
.maxIDs
[xxxPanel
] = self
.maxIDs
[xxxDialog
] = self
.maxIDs
[xxxFrame
] = \
1763 self
.maxIDs
[xxxMenuBar
] = self
.maxIDs
[xxxMenu
] = self
.maxIDs
[xxxToolBar
] = 0
1765 def Open(self
, path
):
1766 # Try to read the file
1771 dom
= minidom
.parse(path
)
1773 self
.dataFile
= path
1774 self
.SetTitle(progname
+ ': ' + os
.path
.basename(path
))
1776 wxLogError('Error reading file: %s' % path
)
1779 def Indent(self
, node
, indent
= 0):
1780 # Copy child list because it will change soon
1781 children
= node
.childNodes
[:]
1782 # Main node doesn't need to be indented
1784 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1785 node
.parentNode
.insertBefore(text
, node
)
1787 # Append newline after last child, except for text nodes
1788 if children
[-1].nodeType
== minidom
.Node
.ELEMENT_NODE
:
1789 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1790 node
.appendChild(text
)
1791 # Indent children which are elements
1793 if n
.nodeType
== minidom
.Node
.ELEMENT_NODE
:
1794 self
.Indent(n
, indent
+ 2)
1796 def Save(self
, path
):
1799 self
.OnRefresh(wxCommandEvent())
1801 # Make temporary copy
1802 # !!! We can't clone dom node, it works only once
1803 #self.domCopy = tree.dom.cloneNode(true)
1804 self
.domCopy
= minidom
.Document()
1805 mainNode
= self
.domCopy
.appendChild(tree
.mainNode
.cloneNode(true
))
1806 self
.Indent(mainNode
)
1807 self
.domCopy
.writexml(f
)
1809 self
.domCopy
.unlink()
1811 self
.modified
= false
1812 panel
.SetModified(false
)
1814 wxLogError('Error writing file: %s' % path
)
1818 if not (self
.modified
or panel
.IsModified()): return true
1819 flags
= wxICON_EXCLAMATION | wxYES_NO | wxCANCEL | wxCENTRE
1820 dlg
= wxMessageDialog( self
, 'File is modified. Save before exit?',
1821 'Save before too late?', flags
)
1822 say
= dlg
.ShowModal()
1825 self
.OnSaveOrSaveAs(wxCommandEvent(wxID_SAVE
))
1826 # If save was successful, modified flag is unset
1827 if not self
.modified
: return true
1828 elif say
== wxID_NO
:
1829 self
.modified
= false
1830 panel
.SetModified(false
)
1834 ################################################################################
1837 print >> sys
.stderr
, 'usage: xrced [-dvh] [file]'
1841 global debug
, verbose
1842 # Process comand-line
1844 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'dvh')
1845 except getopt
.GetoptError
:
1846 print >> sys
.stderr
, 'Unknown option'
1856 print 'XRCed version', version
1859 self
.SetAppName('xrced')
1862 conf
= wxConfig(style
= wxCONFIG_USE_LOCAL_FILE
)
1863 conf
.autoRefresh
= conf
.ReadInt('autorefresh', true
)
1864 pos
= conf
.ReadInt('x', -1), conf
.ReadInt('y', -1)
1865 size
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600)
1866 conf
.embedPanel
= conf
.ReadInt('embedPanel', true
)
1867 conf
.sashPos
= conf
.ReadInt('sashPos', 200)
1868 if not conf
.embedPanel
:
1869 conf
.panelX
= conf
.ReadInt('panelX', -1)
1870 conf
.panelY
= conf
.ReadInt('panelY', -1)
1872 conf
.panelX
= conf
.panelY
= -1
1873 conf
.panelWidth
= conf
.ReadInt('panelWidth', 200)
1874 conf
.panelHeight
= conf
.ReadInt('panelHeight', 200)
1875 conf
.panic
= not conf
.HasEntry('nopanic')
1877 wxFileSystem_AddHandler(wxMemoryFSHandler())
1878 wxInitAllImageHandlers()
1880 frame
= Frame(pos
, size
)
1882 # Load resources from XRC file (!!! should be transformed to .py later?)
1883 sys
.modules
['params'].frame
= frame
1884 frame
.res
= wxXmlResource('')
1885 frame
.res
.Load(os
.path
.join(sys
.path
[0], 'xrced.xrc'))
1887 # Load file after showing
1890 frame
.open = frame
.Open(args
[0])
1896 wc
= wxConfigBase_Get()
1897 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1898 wc
.WriteInt('x', conf
.x
)
1899 wc
.WriteInt('y', conf
.y
)
1900 wc
.WriteInt('width', conf
.width
)
1901 wc
.WriteInt('height', conf
.height
)
1902 wc
.WriteInt('embedPanel', conf
.embedPanel
)
1903 if not conf
.embedPanel
:
1904 wc
.WriteInt('panelX', conf
.panelX
)
1905 wc
.WriteInt('panelY', conf
.panelY
)
1906 wc
.WriteInt('sashPos', conf
.sashPos
)
1907 wc
.WriteInt('panelWidth', conf
.panelWidth
)
1908 wc
.WriteInt('panelHeight', conf
.panelHeight
)
1909 wc
.WriteInt('nopanic', 1)
1917 if __name__
== '__main__':