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
79 # List of child windows
81 # Create scrolled windows for pages
82 self
.page1
= wxScrolledWindow(self
, -1)
84 sizer
.Add(wxBoxSizer()) # dummy sizer
85 self
.page1
.SetAutoLayout(true
)
86 self
.page1
.SetSizer(sizer
)
87 self
.AddPage(self
.page1
, 'Properties')
89 self
.page2
= wxScrolledWindow(self
, -1)
91 sizer
.Add(wxBoxSizer()) # dummy sizer
92 self
.page2
.SetAutoLayout(true
)
93 self
.page2
.SetSizer(sizer
)
94 # Cache for already used panels
95 self
.pageCache
= {} # cached property panels
96 self
.stylePageCache
= {} # cached style panels
97 # Dummy parent window for cache pages
98 self
.cacheParent
= wxFrame(None, -1, 'non visible')
99 # Delete child windows and recreate page sizer
100 def ResetPage(self
, page
):
101 topSizer
= page
.GetSizer()
102 sizer
= topSizer
.GetChildren()[0].GetSizer()
103 for w
in page
.GetChildren():
104 sizer
.RemoveWindow(w
)
105 if isinstance(w
, ParamPage
):
106 # With SetParent, we wouldn't need this
107 w
.Reparent(self
.cacheParent
)
110 topSizer
.RemoveSizer(sizer
)
112 sizer
= wxBoxSizer(wxVERTICAL
)
113 # Special case - resize html window
115 topSizer
.Add(sizer
, 1, wxEXPAND
)
117 topSizer
.Add(sizer
, 0, wxALL
, 5)
119 def SetData(self
, xxx
):
122 # Set cached or new page
123 # Remove current objects and sizer
124 sizer
= self
.ResetPage(self
.page1
)
125 if not xxx
or (not xxx
.allParams
and not xxx
.hasName
):
127 sizer
.Add(wxStaticText(self
.page1
, -1, 'This item has no properties.'))
128 else: # nothing selected
129 # If first time, show some help
131 html
= wxHtmlWindow(self
.page1
, -1, wxDefaultPosition
,
132 wxDefaultSize
, wxSUNKEN_BORDER
)
133 html
.SetPage(helpText
)
134 sizer
.Add(html
, 1, wxEXPAND
)
137 sizer
.Add(wxStaticText(self
.page1
, -1, 'Select a tree item.'))
139 SetCurrentXXX(xxx
.treeObject())
141 page
= self
.pageCache
[xxx
.__class
__]
142 page
.Reparent(self
.page1
)
144 page
= PropPage(self
.page1
, xxx
.className
, xxx
)
145 self
.pageCache
[xxx
.__class
__] = page
147 self
.pages
.append(page
)
148 sizer
.Add(page
, 1, wxEXPAND
)
150 # Special label for child objects - they may have different GUI
151 cacheID
= (xxx
.child
.__class
__, xxx
.__class
__)
153 page
= self
.pageCache
[cacheID
]
154 page
.Reparent(self
.page1
)
156 page
= PropPage(self
.page1
, xxx
.child
.className
, xxx
.child
)
157 self
.pageCache
[cacheID
] = page
158 page
.SetValues(xxx
.child
)
159 self
.pages
.append(page
)
160 sizer
.Add(page
, 0, wxEXPAND | wxTOP
, 5)
162 size
= self
.page1
.GetSizer().GetMinSize()
163 self
.page1
.SetScrollbars(1, 1, size
.x
, size
.y
, 0, 0, true
)
166 # Create if does not exist
167 if xxx
and xxx
.treeObject().hasStyle
:
168 xxx
= xxx
.treeObject()
169 # Simplest case: set data if class is the same
170 sizer
= self
.ResetPage(self
.page2
)
172 page
= self
.stylePageCache
[xxx
.__class
__]
173 page
.Reparent(self
.page2
)
175 page
= StylePage(self
.page2
, xxx
.className
+ ' style', xxx
)
176 self
.stylePageCache
[xxx
.__class
__] = page
178 self
.pages
.append(page
)
179 sizer
.Add(page
, 0, wxEXPAND
)
180 # Add page if not exists
181 if not self
.GetPageCount() == 2:
182 self
.AddPage(self
.page2
, 'Style')
184 size
= self
.page2
.GetSizer().GetMinSize()
185 self
.page2
.SetScrollbars(1, 1, size
.x
, size
.y
, 0, 0, true
)
187 # Remove page if exists
188 if self
.GetPageCount() == 2:
194 # Check if some parameter on some page has changed
195 def IsModified(self
):
197 if p
.IsModified(): return true
199 # Reset changed state
200 def SetModified(self
, value
):
201 for p
in self
.pages
: p
.SetModified(value
)
203 for p
in self
.pages
: p
.Apply()
205 ################################################################################
207 # General class for notebook pages
208 class ParamPage(wxPanel
):
209 def __init__(self
, parent
, xxx
):
210 wxPanel
.__init
__(self
, parent
, -1)
212 # Register event handlers
213 for id in paramIDs
.values():
214 EVT_CHECKBOX(self
, id, self
.OnCheckParams
)
215 self
.modified
= false
217 self
.controls
= {} # save python objects
218 self
.controlName
= None
219 def OnCheckParams(self
, evt
):
221 param
= evt
.GetEventObject().GetName()
222 w
= self
.controls
[param
]
223 objElem
= xxx
.element
225 # Ad new text node in order of allParams
226 w
.SetValue('') # set empty (default) value
227 w
.SetModified() # mark as changed
228 elem
= tree
.dom
.createElement(param
)
229 # Some classes are special
231 xxx
.params
[param
] = xxxParamFont(xxx
.element
, elem
)
233 xxx
.params
[param
] = xxxParam(elem
)
234 # Find place to put new element: first present element after param
236 paramStyles
= xxx
.allParams
+ xxx
.styles
237 for p
in paramStyles
[paramStyles
.index(param
) + 1:]:
238 # Content params don't have same type
239 if xxx
.params
.has_key(p
) and p
!= 'content':
243 nextTextElem
= xxx
.params
[p
].node
244 objElem
.insertBefore(elem
, nextTextElem
)
246 objElem
.appendChild(elem
)
249 xxx
.params
[param
].remove()
250 del xxx
.params
[param
]
252 w
.modified
= false
# mark as not changed
254 self
.SetModified(true
)
255 w
.Enable(evt
.IsChecked())
256 # If some parameter has changed
257 def IsModified(self
):
259 def SetModified(self
, value
):
260 self
.modified
= value
264 # if xxx.undo: xxx.undo.unlink()
265 # xxx.undo = xxx.element.cloneNode(false)
267 name
= self
.controlName
.GetValue()
270 xxx
.element
.setAttribute('name', name
)
271 for param
, w
in self
.controls
.items():
273 paramObj
= xxx
.params
[param
]
275 if param
in xxx
.specials
:
276 xxx
.setSpecial(param
, value
)
278 paramObj
.update(value
)
280 ################################################################################
282 # Panel for displaying properties
283 class PropPage(ParamPage
):
284 def __init__(self
, parent
, label
, xxx
):
285 ParamPage
.__init
__(self
, parent
, xxx
)
286 box
= wxStaticBox(self
, -1, label
)
287 box
.SetFont(labelFont
)
288 topSizer
= wxStaticBoxSizer(box
, wxVERTICAL
)
289 sizer
= wxFlexGridSizer(len(xxx
.allParams
), 2, 1, 1)
291 label
= wxStaticText(self
, -1, 'XML ID:', size
=(100,-1))
292 control
= ParamText(self
, name
='XML_name')
293 sizer
.AddMany([ (label
, 0, wxALIGN_CENTER_VERTICAL
),
294 (control
, 0, wxALIGN_CENTER_VERTICAL
) ])
295 self
.controlName
= control
296 for param
in xxx
.allParams
:
297 present
= param
in xxx
.params
298 if param
in xxx
.required
:
299 label
= wxStaticText(self
, paramIDs
[param
], param
+ ':',
300 size
= (100,-1), name
= param
)
302 # Notebook has one very loooooong parameter
303 if param
== 'usenotebooksizer': sParam
= 'usesizer:'
304 else: sParam
= param
+ ':'
305 label
= wxCheckBox(self
, paramIDs
[param
], sParam
,
306 size
= (100,-1), name
= param
)
307 self
.checks
[param
] = label
309 typeClass
= xxx
.paramDict
[param
]
313 typeClass
= paramDict
[param
]
316 typeClass
= ParamText
317 control
= typeClass(self
, param
)
318 control
.Enable(present
)
319 sizer
.AddMany([ (label
, 0, wxALIGN_CENTER_VERTICAL
),
320 (control
, 0, wxALIGN_CENTER_VERTICAL
) ])
321 self
.controls
[param
] = control
322 topSizer
.Add(sizer
, 1, wxALL | wxEXPAND
, 3)
323 self
.SetAutoLayout(true
)
324 self
.SetSizer(topSizer
)
326 def SetValues(self
, xxx
):
328 # Set values, checkboxes to false, disable defaults
330 self
.controlName
.SetValue(xxx
.name
)
331 for param
in xxx
.allParams
:
332 w
= self
.controls
[param
]
335 value
= xxx
.params
[param
].value()
338 if not param
in xxx
.required
:
339 self
.checks
[param
].SetValue(true
)
341 self
.checks
[param
].SetValue(false
)
344 self
.SetModified(false
)
346 ################################################################################
348 # Style notebook page
349 class StylePage(ParamPage
):
350 def __init__(self
, parent
, label
, xxx
):
351 ParamPage
.__init
__(self
, parent
, xxx
)
352 box
= wxStaticBox(self
, -1, label
)
353 box
.SetFont(labelFont
)
354 topSizer
= wxStaticBoxSizer(box
, wxVERTICAL
)
355 sizer
= wxFlexGridSizer(len(xxx
.styles
), 2, 1, 1)
356 for param
in xxx
.styles
:
357 present
= param
in xxx
.params
.keys()
358 check
= wxCheckBox(self
, paramIDs
[param
],
359 param
+ ':', size
= (100,-1), name
= param
)
360 check
.SetValue(present
)
361 control
= paramDict
[param
](self
, name
= param
)
362 control
.Enable(present
)
363 sizer
.AddMany([ (check
, 0, wxALIGN_CENTER_VERTICAL
),
364 (control
, 0, wxALIGN_CENTER_VERTICAL
) ])
365 self
.checks
[param
] = check
366 self
.controls
[param
] = control
367 topSizer
.Add(sizer
, 1, wxALL | wxEXPAND
, 3)
368 self
.SetAutoLayout(true
)
369 self
.SetSizer(topSizer
)
371 # Set data for a cahced page
372 def SetValues(self
, xxx
):
374 for param
in xxx
.styles
:
375 present
= param
in xxx
.params
.keys()
376 check
= self
.checks
[param
]
377 check
.SetValue(present
)
378 w
= self
.controls
[param
]
381 w
.SetValue(xxx
.params
[param
].value())
385 self
.SetModified(false
)
387 ################################################################################
390 def __init__(self
, pos
, size
):
392 l1
= wxWindow(w
, -1, pos
, wxSize(size
.x
, 2))
393 l1
.SetBackgroundColour(wxRED
)
394 l2
= wxWindow(w
, -1, pos
, wxSize(2, size
.y
))
395 l2
.SetBackgroundColour(wxRED
)
396 l3
= wxWindow(w
, -1, wxPoint(pos
.x
+ size
.x
- 2, pos
.y
), wxSize(2, size
.y
))
397 l3
.SetBackgroundColour(wxRED
)
398 l4
= wxWindow(w
, -1, wxPoint(pos
.x
, pos
.y
+ size
.y
- 2), wxSize(size
.x
, 2))
399 l4
.SetBackgroundColour(wxRED
)
400 self
.lines
= [l1
, l2
, l3
, l4
]
401 # Move highlight to a new position
402 def Replace(self
, pos
, size
):
403 self
.lines
[0].SetDimensions(pos
.x
, pos
.y
, size
.x
, 2, wxSIZE_ALLOW_MINUS_ONE
)
404 self
.lines
[1].SetDimensions(pos
.x
, pos
.y
, 2, size
.y
, wxSIZE_ALLOW_MINUS_ONE
)
405 self
.lines
[2].SetDimensions(pos
.x
+ size
.x
- 2, pos
.y
, 2, size
.y
,
406 wxSIZE_ALLOW_MINUS_ONE
)
407 self
.lines
[3].SetDimensions(pos
.x
, pos
.y
+ size
.y
- 2, size
.x
, 2,
408 wxSIZE_ALLOW_MINUS_ONE
)
411 map(wxWindow
.Destroy
, self
.lines
)
412 testWin
.highLight
= None
414 ################################################################################
417 def __init__(self
, name
):
420 def write(self
, data
):
421 self
.buffer += data
.encode()
423 wxMemoryFSHandler_AddFile(self
.name
, self
.buffer)
425 class XML_Tree(wxTreeCtrl
):
426 def __init__(self
, parent
, id):
427 wxTreeCtrl
.__init
__(self
, parent
, id, style
= wxTR_HAS_BUTTONS
)
428 self
.SetBackgroundColour(wxColour(224, 248, 224))
429 EVT_TREE_SEL_CHANGED(self
, self
.GetId(), self
.OnSelChanged
)
430 # One works on Linux, another on Windows
431 if wxGetOsVersion()[0] == wxGTK
:
432 EVT_TREE_ITEM_ACTIVATED(self
, self
.GetId(), self
.OnItemActivated
)
434 EVT_LEFT_DCLICK(self
, self
.OnDClick
)
435 EVT_RIGHT_DOWN(self
, self
.OnRightDown
)
437 self
.needUpdate
= false
438 self
.pendingHighLight
= None
439 self
.ctrl
= self
.shift
= false
442 il
= wxImageList(16, 16, true
)
443 self
.rootImage
= il
.AddIcon(wxIconFromXPMData(images
.getTreeRootData()))
444 xxxObject
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeDefaultData()))
445 xxxPanel
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreePanelData()))
446 xxxDialog
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeDialogData()))
447 xxxFrame
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeFrameData()))
448 xxxMenuBar
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeMenuBarData()))
449 xxxToolBar
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeToolBarData()))
450 xxxMenu
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeMenuData()))
451 xxxSizer
.imageH
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerHData()))
452 xxxSizer
.imageV
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerVData()))
453 xxxStaticBoxSizer
.imageH
= il
.AddIcon(wxIconFromXPMData(images
.getTreeStaticBoxSizerHData()))
454 xxxStaticBoxSizer
.imageV
= il
.AddIcon(wxIconFromXPMData(images
.getTreeStaticBoxSizerVData()))
455 xxxGridSizer
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerGridData()))
456 xxxFlexGridSizer
.image
= il
.AddIcon(wxIconFromXPMData(images
.getTreeSizerFlexGridData()))
458 self
.SetImageList(il
)
461 self
.selection
= None
462 wxTreeCtrl
.Unselect(self
)
464 def ExpandAll(self
, item
):
465 if self
.ItemHasChildren(item
):
467 i
, cookie
= self
.GetFirstChild(item
, 0)
471 i
, cookie
= self
.GetNextChild(item
, cookie
)
474 def CollapseAll(self
, item
):
475 if self
.ItemHasChildren(item
):
476 i
, cookie
= self
.GetFirstChild(item
, 0)
480 i
, cookie
= self
.GetNextChild(item
, cookie
)
487 self
.DeleteAllItems()
488 # Add minimal structure
489 if self
.dom
: self
.dom
.unlink()
490 self
.dom
= minidom
.Document()
491 self
.dummyNode
= self
.dom
.createComment('dummy node')
493 self
.mainNode
= self
.dom
.createElement('resource')
494 self
.dom
.appendChild(self
.mainNode
)
495 xxx
= xxxMainNode(None, self
.mainNode
)
496 self
.root
= self
.AddRoot('XML tree', self
.rootImage
, data
=wxTreeItemData(xxx
))
497 self
.SetItemHasChildren(self
.root
)
498 self
.Expand(self
.root
)
501 # Clear old data and set new
502 def SetData(self
, dom
):
503 self
.DeleteAllItems()
504 # Add minimal structure
505 if self
.dom
: self
.dom
.unlink()
507 self
.dummyNode
= self
.dom
.createComment('dummy node')
508 # Find 'resource' child, add it's children
509 self
.mainNode
= dom
.getElementsByTagName('resource')[0]
510 xxx
= xxxMainNode(None, self
.mainNode
)
511 self
.root
= self
.AddRoot('XML tree', self
.rootImage
, data
=wxTreeItemData(xxx
))
512 self
.SetItemHasChildren(self
.root
)
513 nodes
= self
.mainNode
.childNodes
[:]
516 self
.AddNode(self
.root
, None, node
)
518 self
.mainNode
.removeChild(node
)
520 self
.Expand(self
.root
)
523 # Add tree item for given parent item if node is DOM element node with
524 # 'object' tag. xxxParent is parent xxx object
525 def AddNode(self
, itemParent
, xxxParent
, node
):
526 # Set item data to current node
528 xxx
= MakeXXXFromDOM(xxxParent
, node
)
530 print 'ERROR: MakeXXXFromDom(%s, %s)' % (xxxParent
, node
)
532 treeObj
= xxx
.treeObject()
534 item
= self
.AppendItem(itemParent
, treeObj
.treeName(),
535 image
=treeObj
.treeImage(),
536 data
=wxTreeItemData(xxx
))
537 # Try to find children objects
538 if treeObj
.hasChildren
:
539 nodes
= treeObj
.element
.childNodes
[:]
542 self
.AddNode(item
, treeObj
, n
)
543 elif n
.nodeType
!= minidom
.Node
.ELEMENT_NODE
:
544 treeObj
.element
.removeChild(n
)
546 # Remove leaf of tree, return it's data object
547 def RemoveLeaf(self
, leaf
):
548 xxx
= self
.GetPyData(leaf
)
550 parent
= node
.parentNode
551 parent
.removeChild(node
)
553 # Reset selection object
554 self
.selection
= None
556 # Find position relative to the top-level window
557 def FindNodePos(self
, item
):
559 if item
== testWin
.item
: return wxPoint(0, 0)
560 itemParent
= self
.GetItemParent(item
)
562 obj
= self
.FindNodeObject(item
)
563 if self
.GetPyData(itemParent
).treeObject().__class
__ == xxxNotebook
:
564 notebook
= self
.FindNodeObject(itemParent
)
566 for i
in range(notebook
.GetPageCount()):
567 if notebook
.GetPage(i
) == obj
:
568 if notebook
.GetSelection() != i
: notebook
.SetSelection(i
)
570 # Find first ancestor which is a wxWindow (not a sizer)
571 winParent
= itemParent
572 while self
.GetPyData(winParent
).isSizer
:
573 winParent
= self
.GetItemParent(winParent
)
574 parentPos
= self
.FindNodePos(winParent
)
575 # Position (-1,-1) is really (0,0)
576 pos
= obj
.GetPosition()
577 if pos
== (-1,-1): pos
= (0,0)
578 return parentPos
+ pos
579 # Find window (or sizer) corresponding to a tree item.
580 def FindNodeObject(self
, item
):
581 if item
== testWin
.item
: return testWin
.panel
582 itemParent
= self
.GetItemParent(item
)
583 # If top-level, return testWin (or panel if wxFrame)
584 xxx
= self
.GetPyData(item
).treeObject()
585 parentWin
= self
.FindNodeObject(itemParent
)
586 # Top-level sizer? return window's sizer
587 if xxx
.isSizer
and isinstance(parentWin
, wxWindowPtr
):
588 return parentWin
.GetSizer()
589 # Otherwise get parent's object and it's child
590 n
= 0 # index of sibling
591 prev
= self
.GetPrevSibling(item
)
593 prev
= self
.GetPrevSibling(prev
)
595 child
= parentWin
.GetChildren()[n
]
596 # Return window or sizer for sizer items
597 if child
.GetClassName() == 'wxSizerItem':
598 if child
.IsWindow(): child
= child
.GetWindow()
599 elif child
.IsSizer():
600 child
= child
.GetSizer()
601 # Test for notebook sizers
602 if isinstance(child
, wxNotebookSizerPtr
):
603 child
= child
.GetNotebook()
605 def OnSelChanged(self
, evt
):
607 # !!! problem with wxGTK - GetOldItem is Ok if nothing selected
608 #oldItem = evt.GetOldItem()
610 oldItem
= self
.selection
612 xxx
= self
.GetPyData(oldItem
)
613 # If some data was modified, apply changes
614 if panel
.IsModified():
615 self
.Apply(xxx
, oldItem
)
616 #if conf.autoRefresh:
618 if testWin
.highLight
and not tree
.IsHighlatable(oldItem
):
619 testWin
.highLight
.Remove()
620 self
.needUpdate
= true
621 status
= 'Changes were applied'
622 frame
.SetStatusText(status
)
624 self
.selection
= evt
.GetItem()
625 if not self
.selection
.IsOk():
626 self
.selection
= None
628 xxx
= self
.GetPyData(self
.selection
)
632 panel
.SetModified(false
)
633 # Hightlighting is done in OnIdle
634 tree
.pendingHighLight
= self
.selection
635 # Check if item is in testWin subtree
636 def IsHighlatable(self
, item
):
637 if item
== testWin
.item
: return false
638 while item
!= self
.root
:
639 item
= self
.GetItemParent(item
)
640 if item
== testWin
.item
: return true
642 # Highlight selected item
643 def HighLight(self
, item
):
644 self
.pendingHighLight
= None
645 if not testWin
or self
.GetPyData(testWin
.item
).className \
646 not in ['wxDialog', 'wxPanel', 'wxFrame']:
648 # Top-level does not have highlight
649 if item
== testWin
.item
or item
== tree
.root
:
650 if testWin
.highLight
: testWin
.highLight
.Remove()
652 # If a control from another window is selected, remove highlight
653 if not self
.IsHighlatable(item
):
654 if testWin
.highLight
: testWin
.highLight
.Remove()
656 # Get window/sizer object
657 obj
, pos
= self
.FindNodeObject(item
), self
.FindNodePos(item
)
660 # Nagative positions are not working wuite well
661 if testWin
.highLight
:
662 testWin
.highLight
.Replace(pos
, size
)
664 testWin
.highLight
= HightLightBox(pos
, size
)
665 testWin
.highLight
.item
= item
666 def ShowTestWindow(self
, item
):
668 xxx
= self
.GetPyData(item
)
669 if panel
.IsModified():
670 self
.Apply(xxx
, item
) # apply changes
671 treeObj
= xxx
.treeObject()
672 if treeObj
.className
not in ['wxFrame', 'wxPanel', 'wxDialog',
673 'wxMenuBar', 'wxToolBar']:
674 wxLogMessage('No view for this element (yet)')
677 wxLogError("Can't display a noname element!")
681 self
.SetItemBold(testWin
.item
, false
)
682 self
.SetItemBold(item
)
683 self
.CreateTestWin(item
)
684 # Double-click on Linux
685 def OnItemActivated(self
, evt
):
686 if evt
.GetItem() != self
.root
:
687 self
.ShowTestWindow(evt
.GetItem())
688 # Double-click on Windows
689 def OnDClick(self
, evt
):
690 item
, flags
= self
.HitTest(evt
.GetPosition())
691 if flags
in [wxTREE_HITTEST_ONITEMBUTTON
, wxTREE_HITTEST_ONITEMLABEL
]:
692 if item
!= self
.root
: self
.ShowTestWindow(item
)
695 # (re)create test window
696 def CreateTestWin(self
, item
):
699 # Create a window with this resource
700 xxx
= self
.GetPyData(item
).treeObject()
701 # Close old window, remember where it was
704 pos
= testWin
.GetPosition()
705 if item
== testWin
.item
:
706 # Remember highlight if same top-level window
707 if testWin
.highLight
:
708 highLight
= testWin
.highLight
.item
709 # !!! if 0 is removed, refresh is broken (notebook not deleted?)
710 if xxx
.className
== 'wxPanel':
711 if testWin
.highLight
:
712 testWin
.pendingHighLight
= highLight
713 testWin
.highLight
.Remove()
714 testWin
.panel
.Destroy()
725 memFile
= MemoryFile('xxx.xrc')
726 # Create partial XML file - faster for big files
728 dom
= minidom
.Document()
729 mainNode
= dom
.createElement('resource')
730 dom
.appendChild(mainNode
)
732 # Remove temporarily from old parent
734 parent
= elem
.parentNode
735 next
= elem
.nextSibling
736 parent
.replaceChild(self
.dummyNode
, elem
)
737 # Append to new DOM, write it
738 mainNode
.appendChild(elem
)
739 dom
.writexml(memFile
)
741 mainNode
.removeChild(elem
)
743 parent
.replaceChild(elem
, self
.dummyNode
)
744 memFile
.close() # write to wxMemoryFS
745 res
= wxXmlResource('')
746 res
.Load('memory:xxx.xrc')
747 if xxx
.className
== 'wxFrame':
749 testWin
= wxPreFrame()
750 res
.LoadOnFrame(testWin
, frame
, xxx
.name
)
752 testWin
.CreateStatusBar()
753 testWin
.panel
= testWin
754 testWin
.SetPosition(pos
)
756 elif xxx
.className
== 'wxPanel':
759 testWin
= wxFrame(frame
, -1, 'Panel: ' + xxx
.name
, pos
=pos
)
760 testWin
.panel
= res
.LoadPanel(testWin
, xxx
.name
)
761 testWin
.SetClientSize(testWin
.panel
.GetSize())
763 elif xxx
.className
== 'wxDialog':
765 testWin
= res
.LoadDialog(None, xxx
.name
)
766 testWin
.panel
= testWin
768 testWin
.SetPosition(pos
)
770 elif xxx
.className
== 'wxMenuBar':
771 testWin
= wxFrame(frame
, -1, 'MenuBar: ' + xxx
.name
, pos
=pos
)
773 # Set status bar to display help
774 testWin
.CreateStatusBar()
775 testWin
.menuBar
= res
.LoadMenuBar(xxx
.name
)
776 testWin
.SetMenuBar(testWin
.menuBar
)
778 elif xxx
.className
== 'wxToolBar':
779 testWin
= wxFrame(frame
, -1, 'ToolBar: ' + xxx
.name
, pos
=pos
)
781 # Set status bar to display help
782 testWin
.CreateStatusBar()
783 testWin
.toolBar
= res
.LoadToolBar(testWin
, xxx
.name
)
784 testWin
.SetToolBar(testWin
.toolBar
)
786 wxMemoryFSHandler_RemoveFile('xxx.xrc')
788 EVT_CLOSE(testWin
, self
.OnCloseTestWin
)
789 EVT_BUTTON(testWin
, wxID_OK
, self
.OnCloseTestWin
)
790 EVT_BUTTON(testWin
, wxID_CANCEL
, self
.OnCloseTestWin
)
791 testWin
.highLight
= None
792 if highLight
and not tree
.pendingHighLight
:
793 self
.HighLight(highLight
)
796 def OnCloseTestWin(self
, evt
):
797 global testWin
, testWinPos
798 self
.SetItemBold(testWin
.item
, false
)
799 testWinPos
= testWin
.GetPosition()
803 # Return item index in parent
804 def ItemIndex(self
, parent
, item
):
806 it
, cookie
= self
.GetFirstChild(parent
, 0)
809 it
, cookie
= self
.GetNextChild(parent
, cookie
)
812 # True if next item should be inserted after current (vs. appended to it)
813 def NeedInsert(self
, item
):
814 xxx
= self
.GetPyData(item
)
815 if item
== self
.root
: return false
# root item
816 if xxx
.hasChildren
and not self
.GetChildrenCount(item
, false
):
818 return not (self
.IsExpanded(item
) and self
.GetChildrenCount(item
, false
))
821 def OnRightDown(self
, evt
):
823 pt
= evt
.GetPosition();
824 item
, flags
= self
.HitTest(pt
)
825 if item
.Ok() and flags
& wxTREE_HITTEST_ONITEM
:
826 self
.SelectItem(item
)
831 item
= self
.selection
833 menu
.Append(pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand tree')
834 menu
.Append(pullDownMenu
.ID_COLLAPSE
, 'Collapse', 'Collapse tree')
836 self
.ctrl
= evt
.ControlDown() # save Ctrl state
837 self
.shift
= evt
.ShiftDown() # and Shift too
838 m
= wxMenu() # create menu
842 needInsert
= self
.NeedInsert(item
)
843 if item
== self
.root
or needInsert
and self
.GetItemParent(item
) == self
.root
:
844 m
.Append(pullDownMenu
.ID_NEW_PANEL
, 'Panel', 'Create panel')
845 m
.Append(pullDownMenu
.ID_NEW_DIALOG
, 'Dialog', 'Create dialog')
846 m
.Append(pullDownMenu
.ID_NEW_FRAME
, 'Frame', 'Create frame')
848 m
.Append(pullDownMenu
.ID_NEW_TOOL_BAR
, 'ToolBar', 'Create toolbar')
849 m
.Append(pullDownMenu
.ID_NEW_MENU_BAR
, 'MenuBar', 'Create menubar')
850 m
.Append(pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu')
852 xxx
= self
.GetPyData(item
).treeObject()
853 # Check parent for possible child nodes if inserting sibling
854 if needInsert
: xxx
= xxx
.parent
855 if xxx
.__class
__ == xxxMenuBar
:
856 m
.Append(pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu')
857 elif xxx
.__class
__ in [xxxToolBar
, xxxTool
] or \
858 xxx
.__class
__ == xxxSeparator
and xxx
.parent
.__class
__ == xxxToolBar
:
859 SetMenu(m
, pullDownMenu
.toolBarControls
)
860 elif xxx
.__class
__ in [xxxMenu
, xxxMenuItem
]:
861 SetMenu(m
, pullDownMenu
.menuControls
)
863 SetMenu(m
, pullDownMenu
.controls
)
864 if xxx
.__class
__ == xxxNotebook
:
865 m
.Enable(m
.FindItem('sizer'), false
)
866 elif not (xxx
.isSizer
or xxx
.parent
and xxx
.parent
.isSizer
):
867 m
.Enable(pullDownMenu
.ID_NEW_SPACER
, false
)
868 # Select correct label for create menu
871 menu
.AppendMenu(wxNewId(), 'Insert Child', m
,
872 'Create child object as the first child')
874 menu
.AppendMenu(wxNewId(), 'Append Child', m
,
875 'Create child object as the last child')
878 menu
.AppendMenu(wxNewId(), 'Create Sibling', m
,
879 'Create sibling before selected object')
881 menu
.AppendMenu(wxNewId(), 'Create Sibling', m
,
882 'Create sibling after selected object')
883 menu
.AppendSeparator()
884 # Not using standart IDs because we don't want to show shortcuts
885 menu
.Append(wxID_CUT
, 'Cut', 'Cut to the clipboard')
886 menu
.Append(wxID_COPY
, 'Copy', 'Copy to the clipboard')
887 if self
.ctrl
and item
!= tree
.root
:
888 menu
.Append(pullDownMenu
.ID_PASTE_SIBLING
, 'Paste Sibling',
889 'Paste from the clipboard as a sibling')
891 menu
.Append(wxID_PASTE
, 'Paste', 'Paste from the clipboard')
892 menu
.Append(pullDownMenu
.ID_DELETE
,
893 'Delete', 'Delete object')
894 if self
.ItemHasChildren(item
):
895 menu
.AppendSeparator()
896 menu
.Append(pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand subtree')
897 menu
.Append(pullDownMenu
.ID_COLLAPSE
, 'Collapse', 'Collapse subtree')
898 self
.PopupMenu(menu
, evt
.GetPosition())
902 def Apply(self
, xxx
, item
):
905 xxx
= xxx
.treeObject()
906 if xxx
.hasName
and self
.GetItemText(item
) != xxx
.name
:
907 self
.SetItemText(item
, xxx
.treeName())
908 # Change tree icon for sizers
909 if isinstance(xxx
, xxxBoxSizer
):
910 self
.SetItemImage(item
, xxx
.treeImage())
911 # Set global modified state
912 frame
.modified
= true
915 ID_NEW_PANEL
= wxNewId()
916 ID_NEW_DIALOG
= wxNewId()
917 ID_NEW_FRAME
= wxNewId()
918 ID_NEW_TOOL_BAR
= wxNewId()
919 ID_NEW_TOOL
= wxNewId()
920 ID_NEW_MENU_BAR
= wxNewId()
921 ID_NEW_MENU
= wxNewId()
923 ID_NEW_STATIC_TEXT
= wxNewId()
924 ID_NEW_TEXT_CTRL
= wxNewId()
926 ID_NEW_BUTTON
= wxNewId()
927 ID_NEW_BITMAP_BUTTON
= wxNewId()
928 ID_NEW_RADIO_BUTTON
= wxNewId()
929 ID_NEW_SPIN_BUTTON
= wxNewId()
931 ID_NEW_STATIC_BOX
= wxNewId()
932 ID_NEW_CHECK_BOX
= wxNewId()
933 ID_NEW_RADIO_BOX
= wxNewId()
934 ID_NEW_COMBO_BOX
= wxNewId()
935 ID_NEW_LIST_BOX
= wxNewId()
937 ID_NEW_STATIC_LINE
= wxNewId()
938 ID_NEW_STATIC_BITMAP
= wxNewId()
939 ID_NEW_CHOICE
= wxNewId()
940 ID_NEW_SLIDER
= wxNewId()
941 ID_NEW_GAUGE
= wxNewId()
942 ID_NEW_SCROLL_BAR
= wxNewId()
943 ID_NEW_TREE_CTRL
= wxNewId()
944 ID_NEW_LIST_CTRL
= wxNewId()
945 ID_NEW_CHECK_LIST
= wxNewId()
946 ID_NEW_NOTEBOOK
= wxNewId()
947 ID_NEW_HTML_WINDOW
= wxNewId()
948 ID_NEW_CALENDAR
= wxNewId()
950 ID_NEW_BOX_SIZER
= wxNewId()
951 ID_NEW_STATIC_BOX_SIZER
= wxNewId()
952 ID_NEW_GRID_SIZER
= wxNewId()
953 ID_NEW_FLEX_GRID_SIZER
= wxNewId()
954 ID_NEW_SPACER
= wxNewId()
955 ID_NEW_TOOL_BAR
= wxNewId()
956 ID_NEW_TOOL
= wxNewId()
957 ID_NEW_MENU
= wxNewId()
958 ID_NEW_MENU_ITEM
= wxNewId()
959 ID_NEW_SEPARATOR
= wxNewId()
960 ID_NEW_LAST
= wxNewId()
961 ID_EXPAND
= wxNewId()
962 ID_COLLAPSE
= wxNewId()
963 ID_PASTE_SIBLING
= wxNewId()
965 def __init__(self
, parent
):
966 self
.ID_DELETE
= parent
.ID_DELETE
967 EVT_MENU_RANGE(parent
, self
.ID_NEW_PANEL
,
968 self
.ID_NEW_LAST
, parent
.OnCreate
)
969 EVT_MENU(parent
, self
.ID_COLLAPSE
, parent
.OnCollapse
)
970 EVT_MENU(parent
, self
.ID_EXPAND
, parent
.OnExpand
)
971 EVT_MENU(parent
, self
.ID_PASTE_SIBLING
, parent
.OnPaste
)
972 # We connect to tree, but process in frame
973 EVT_MENU_HIGHLIGHT_ALL(tree
, parent
.OnPullDownHighlight
)
975 ################################################################################
977 # ScrolledMessageDialog - modified from wxPython lib to set fixed-width font
978 class ScrolledMessageDialog(wxDialog
):
979 def __init__(self
, parent
, msg
, caption
, pos
= wxDefaultPosition
, size
= (500,300)):
980 from wxPython
.lib
.layoutf
import Layoutf
981 wxDialog
.__init
__(self
, parent
, -1, caption
, pos
, size
)
982 text
= wxTextCtrl(self
, -1, msg
, wxDefaultPosition
,
983 wxDefaultSize
, wxTE_MULTILINE | wxTE_READONLY
)
984 text
.SetFont(modernFont
)
985 dc
= wxWindowDC(text
)
986 w
, h
= dc
.GetTextExtent(' ')
987 ok
= wxButton(self
, wxID_OK
, "OK")
988 text
.SetConstraints(Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self
,ok
)))
989 text
.SetSize((w
* 80 + 30, h
* 40))
990 ok
.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!25', (self
,)))
991 self
.SetAutoLayout(TRUE
)
993 self
.CenterOnScreen(wxBOTH
)
995 ################################################################################
997 class Frame(wxFrame
):
998 def __init__(self
, pos
, size
):
1001 wxFrame
.__init
__(self
, None, -1, '', pos
, size
)
1002 self
.CreateStatusBar()
1003 #progpath = os.path.split(__file__)[0]
1004 #icon = wxIcon(os.path.join(progpath, 'xrced.ico'), wxBITMAP_TYPE_ICO)
1005 icon
= wxEmptyIcon()
1006 icon
.CopyFromBitmap(images
.getIconBitmap())
1013 menuBar
= wxMenuBar()
1016 menu
.Append(wxID_NEW
, '&New\tCtrl-N', 'New file')
1017 menu
.Append(wxID_OPEN
, '&Open...\tCtrl-O', 'Open XRC file')
1018 menu
.Append(wxID_SAVE
, '&Save\tCtrl-S', 'Save XRC file')
1019 menu
.Append(wxID_SAVEAS
, 'Save &As...', 'Save XRC file under different name')
1020 menu
.AppendSeparator()
1021 menu
.Append(wxID_EXIT
, '&Quit\tCtrl-Q', 'Exit application')
1022 menuBar
.Append(menu
, '&File')
1025 menu
.Append(wxID_UNDO
, '&Undo\tCtrl-Z', 'Undo')
1026 menu
.Append(wxID_REDO
, '&Redo\tCtrl-Y', 'Redo')
1027 menu
.AppendSeparator()
1028 menu
.Append(wxID_CUT
, 'Cut\tCtrl-X', 'Cut to the clipboard')
1029 menu
.Append(wxID_COPY
, '&Copy\tCtrl-C', 'Copy to the clipboard')
1030 menu
.Append(wxID_PASTE
, '&Paste\tCtrl-V', 'Paste from the clipboard')
1031 self
.ID_DELETE
= wxNewId()
1032 menu
.Append(self
.ID_DELETE
, '&Delete\tCtrl-D', 'Delete object')
1033 menuBar
.Append(menu
, '&Edit')
1036 self
.ID_EMBED_PANEL
= wxNewId()
1037 menu
.Append(self
.ID_EMBED_PANEL
, '&Embed Panel',
1038 'Toggle embedding properties panel in the main window', true
)
1039 menu
.Check(self
.ID_EMBED_PANEL
, conf
.embedPanel
)
1040 menu
.AppendSeparator()
1041 self
.ID_TEST
= wxNewId()
1042 menu
.Append(self
.ID_TEST
, '&Test\tF5', 'Test window')
1043 self
.ID_REFRESH
= wxNewId()
1044 menu
.Append(self
.ID_REFRESH
, '&Refresh\tCtrl-R', 'Refresh test window')
1045 self
.ID_AUTO_REFRESH
= wxNewId()
1046 menu
.Append(self
.ID_AUTO_REFRESH
, '&Auto-refresh\tCtrl-A',
1047 'Toggle auto-refresh mode', true
)
1048 menu
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1049 menuBar
.Append(menu
, '&View')
1052 menu
.Append(wxID_ABOUT
, '&About...', 'About XCRed')
1053 self
.ID_README
= wxNewId()
1054 menu
.Append(self
.ID_README
, '&Readme...', 'View the README file')
1056 self
.ID_DEBUG_CMD
= wxNewId()
1057 menu
.Append(self
.ID_DEBUG_CMD
, 'CMD', 'Python command line')
1058 EVT_MENU(self
, self
.ID_DEBUG_CMD
, self
.OnDebugCMD
)
1059 menuBar
.Append(menu
, '&Help')
1061 self
.menuBar
= menuBar
1062 self
.SetMenuBar(menuBar
)
1065 tb
= self
.CreateToolBar(wxTB_HORIZONTAL | wxNO_BORDER | wxTB_FLAT
)
1066 tb
.SetToolBitmapSize((24, 23))
1067 tb
.AddSimpleTool(wxID_NEW
, images
.getNewBitmap(), 'New', 'New file')
1068 tb
.AddSimpleTool(wxID_OPEN
, images
.getOpenBitmap(), 'Open', 'Open file')
1069 tb
.AddSimpleTool(wxID_SAVE
, images
.getSaveBitmap(), 'Save', 'Save file')
1070 tb
.AddControl(wxStaticLine(tb
, -1, size
=(-1,23), style
=wxLI_VERTICAL
))
1071 tb
.AddSimpleTool(wxID_CUT
, images
.getCutBitmap(), 'Cut', 'Cut')
1072 tb
.AddSimpleTool(wxID_COPY
, images
.getCopyBitmap(), 'Copy', 'Copy')
1073 tb
.AddSimpleTool(wxID_PASTE
, images
.getPasteBitmap(), 'Paste', 'Paste')
1074 tb
.AddControl(wxStaticLine(tb
, -1, size
=(-1,23), style
=wxLI_VERTICAL
))
1075 tb
.AddSimpleTool(self
.ID_TEST
, images
.getTestBitmap(), 'Test', 'Test window')
1076 tb
.AddSimpleTool(self
.ID_REFRESH
, images
.getRefreshBitmap(),
1077 'Refresh', 'Refresh view')
1078 tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, images
.getAutoRefreshBitmap(),
1079 'Auto-refresh', 'Toggle auto-refresh mode', true
)
1080 if wxGetOsVersion()[0] == wxGTK
:
1081 tb
.AddSeparator() # otherwise auto-refresh sticks in status line
1082 tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1085 self
.minWidth
= tb
.GetSize()[0] # minimal width is the size of toolbar
1088 EVT_MENU(self
, wxID_NEW
, self
.OnNew
)
1089 EVT_MENU(self
, wxID_OPEN
, self
.OnOpen
)
1090 EVT_MENU(self
, wxID_SAVE
, self
.OnSaveOrSaveAs
)
1091 EVT_MENU(self
, wxID_SAVEAS
, self
.OnSaveOrSaveAs
)
1092 EVT_MENU(self
, wxID_EXIT
, self
.OnExit
)
1094 EVT_MENU(self
, wxID_UNDO
, self
.OnUndo
)
1095 EVT_MENU(self
, wxID_REDO
, self
.OnRedo
)
1096 EVT_MENU(self
, wxID_CUT
, self
.OnCut
)
1097 EVT_MENU(self
, wxID_COPY
, self
.OnCopy
)
1098 EVT_MENU(self
, wxID_PASTE
, self
.OnPaste
)
1099 EVT_MENU(self
, self
.ID_DELETE
, self
.OnDelete
)
1101 EVT_MENU(self
, self
.ID_EMBED_PANEL
, self
.OnEmbedPanel
)
1102 EVT_MENU(self
, self
.ID_TEST
, self
.OnTest
)
1103 EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
)
1104 EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
)
1106 EVT_MENU(self
, wxID_ABOUT
, self
.OnAbout
)
1107 EVT_MENU(self
, self
.ID_README
, self
.OnReadme
)
1110 EVT_UPDATE_UI(self
, wxID_CUT
, self
.OnUpdateUI
)
1111 EVT_UPDATE_UI(self
, wxID_COPY
, self
.OnUpdateUI
)
1112 EVT_UPDATE_UI(self
, wxID_PASTE
, self
.OnUpdateUI
)
1113 EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
)
1114 EVT_UPDATE_UI(self
, self
.ID_TEST
, self
.OnUpdateUI
)
1115 EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
)
1118 sizer
= wxBoxSizer(wxVERTICAL
)
1119 sizer
.Add(wxStaticLine(self
, -1), 0, wxEXPAND
)
1120 splitter
= wxSplitterWindow(self
, -1, style
=wxSP_3DSASH
)
1121 self
.splitter
= splitter
1122 splitter
.SetMinimumPaneSize(100)
1126 tree
= XML_Tree(splitter
, -1)
1127 ##sys.modules['xxx'].tree = tree
1131 # !!! frame styles are broken
1132 # Miniframe for not embedded mode
1133 miniFrame
= wxFrame(self
, -1, 'Properties Panel',
1134 (conf
.panelX
, conf
.panelY
),
1135 (conf
.panelWidth
, conf
.panelHeight
))
1136 self
.miniFrame
= miniFrame
1137 sizer2
= wxBoxSizer()
1138 miniFrame
.SetAutoLayout(true
)
1139 miniFrame
.SetSizer(sizer2
)
1140 EVT_CLOSE(self
.miniFrame
, self
.OnCloseMiniFrame
)
1141 # Create panel for parameters
1144 panel
= Panel(splitter
)
1145 # Set plitter windows
1146 splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
1148 panel
= Panel(miniFrame
)
1149 sizer2
.Add(panel
, 1, wxEXPAND
)
1150 miniFrame
.Show(true
)
1151 splitter
.Initialize(tree
)
1152 sizer
.Add(splitter
, 1, wxEXPAND
)
1153 self
.SetAutoLayout(true
)
1154 self
.SetSizer(sizer
)
1156 # Init pull-down menu data
1158 pullDownMenu
= PullDownMenu(self
)
1159 # Mapping from IDs to element names
1161 pullDownMenu
.ID_NEW_PANEL
: 'wxPanel',
1162 pullDownMenu
.ID_NEW_DIALOG
: 'wxDialog',
1163 pullDownMenu
.ID_NEW_FRAME
: 'wxFrame',
1164 pullDownMenu
.ID_NEW_TOOL_BAR
: 'wxToolBar',
1165 pullDownMenu
.ID_NEW_TOOL
: 'tool',
1166 pullDownMenu
.ID_NEW_MENU_BAR
: 'wxMenuBar',
1167 pullDownMenu
.ID_NEW_MENU
: 'wxMenu',
1168 pullDownMenu
.ID_NEW_MENU_ITEM
: 'wxMenuItem',
1169 pullDownMenu
.ID_NEW_SEPARATOR
: 'separator',
1171 pullDownMenu
.ID_NEW_STATIC_TEXT
: 'wxStaticText',
1172 pullDownMenu
.ID_NEW_TEXT_CTRL
: 'wxTextCtrl',
1174 pullDownMenu
.ID_NEW_BUTTON
: 'wxButton',
1175 pullDownMenu
.ID_NEW_BITMAP_BUTTON
: 'wxBitmapButton',
1176 pullDownMenu
.ID_NEW_RADIO_BUTTON
: 'wxRadioButton',
1177 pullDownMenu
.ID_NEW_SPIN_BUTTON
: 'wxSpinButton',
1179 pullDownMenu
.ID_NEW_STATIC_BOX
: 'wxStaticBox',
1180 pullDownMenu
.ID_NEW_CHECK_BOX
: 'wxCheckBox',
1181 pullDownMenu
.ID_NEW_RADIO_BOX
: 'wxRadioBox',
1182 pullDownMenu
.ID_NEW_COMBO_BOX
: 'wxComboBox',
1183 pullDownMenu
.ID_NEW_LIST_BOX
: 'wxListBox',
1185 pullDownMenu
.ID_NEW_STATIC_LINE
: 'wxStaticLine',
1186 pullDownMenu
.ID_NEW_STATIC_BITMAP
: 'wxStaticBitmap',
1187 pullDownMenu
.ID_NEW_CHOICE
: 'wxChoice',
1188 pullDownMenu
.ID_NEW_SLIDER
: 'wxSlider',
1189 pullDownMenu
.ID_NEW_GAUGE
: 'wxGauge',
1190 pullDownMenu
.ID_NEW_SCROLL_BAR
: 'wxScrollBar',
1191 pullDownMenu
.ID_NEW_TREE_CTRL
: 'wxTreeCtrl',
1192 pullDownMenu
.ID_NEW_LIST_CTRL
: 'wxListCtrl',
1193 pullDownMenu
.ID_NEW_CHECK_LIST
: 'wxCheckList',
1194 pullDownMenu
.ID_NEW_NOTEBOOK
: 'wxNotebook',
1195 pullDownMenu
.ID_NEW_HTML_WINDOW
: 'wxHtmlWindow',
1196 pullDownMenu
.ID_NEW_CALENDAR
: 'wxCalendar',
1198 pullDownMenu
.ID_NEW_BOX_SIZER
: 'wxBoxSizer',
1199 pullDownMenu
.ID_NEW_STATIC_BOX_SIZER
: 'wxStaticBoxSizer',
1200 pullDownMenu
.ID_NEW_GRID_SIZER
: 'wxGridSizer',
1201 pullDownMenu
.ID_NEW_FLEX_GRID_SIZER
: 'wxFlexGridSizer',
1202 pullDownMenu
.ID_NEW_SPACER
: 'spacer',
1204 pullDownMenu
.controls
= [
1205 ['control', 'Various controls',
1206 (pullDownMenu
.ID_NEW_STATIC_TEXT
, 'Label', 'Create static label'),
1207 (pullDownMenu
.ID_NEW_STATIC_LINE
, 'Line', 'Create static line'),
1208 (pullDownMenu
.ID_NEW_TEXT_CTRL
, 'TextBox', 'Create text box control'),
1209 (pullDownMenu
.ID_NEW_CHOICE
, 'Choice', 'Create choice control'),
1210 (pullDownMenu
.ID_NEW_SLIDER
, 'Slider', 'Create slider control'),
1211 (pullDownMenu
.ID_NEW_GAUGE
, 'Gauge', 'Create gauge control'),
1212 (pullDownMenu
.ID_NEW_SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'),
1213 (pullDownMenu
.ID_NEW_TREE_CTRL
, 'TreeCtrl', 'Create tree control'),
1214 (pullDownMenu
.ID_NEW_LIST_CTRL
, 'ListCtrl', 'Create list control'),
1215 (pullDownMenu
.ID_NEW_HTML_WINDOW
, 'HtmlWindow', 'Create HTML window'),
1216 (pullDownMenu
.ID_NEW_CALENDAR
, 'Calendar', 'Create calendar control'),
1217 (pullDownMenu
.ID_NEW_PANEL
, 'Panel', 'Create panel'),
1218 (pullDownMenu
.ID_NEW_NOTEBOOK
, 'Notebook', 'Create notebook control'),
1220 ['button', 'Buttons',
1221 (pullDownMenu
.ID_NEW_BUTTON
, 'Button', 'Create button'),
1222 (pullDownMenu
.ID_NEW_BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'),
1223 (pullDownMenu
.ID_NEW_RADIO_BUTTON
, 'RadioButton', 'Create radio button'),
1224 (pullDownMenu
.ID_NEW_SPIN_BUTTON
, 'SpinButton', 'Create spin button'),
1227 (pullDownMenu
.ID_NEW_STATIC_BOX
, 'StaticBox', 'Create static box'),
1228 (pullDownMenu
.ID_NEW_CHECK_BOX
, 'CheckBox', 'Create check box'),
1229 (pullDownMenu
.ID_NEW_RADIO_BOX
, 'RadioBox', 'Create radio box'),
1230 (pullDownMenu
.ID_NEW_COMBO_BOX
, 'ComboBox', 'Create combo box'),
1231 (pullDownMenu
.ID_NEW_LIST_BOX
, 'ListBox', 'Create list box'),
1232 (pullDownMenu
.ID_NEW_CHECK_LIST
, 'CheckListBox',
1233 'Create check list control'),
1236 (pullDownMenu
.ID_NEW_BOX_SIZER
, 'BoxSizer', 'Create box sizer'),
1237 (pullDownMenu
.ID_NEW_STATIC_BOX_SIZER
, 'StaticBoxSizer',
1238 'Create static box sizer'),
1239 (pullDownMenu
.ID_NEW_GRID_SIZER
, 'GridSizer', 'Create grid sizer'),
1240 (pullDownMenu
.ID_NEW_FLEX_GRID_SIZER
, 'FlexGridSizer',
1241 'Create flexgrid sizer'),
1242 (pullDownMenu
.ID_NEW_SPACER
, 'Spacer', 'Create spacer'),
1245 pullDownMenu
.menuControls
= [
1246 (pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu'),
1247 (pullDownMenu
.ID_NEW_MENU_ITEM
, 'MenuItem', 'Create menu item'),
1248 (pullDownMenu
.ID_NEW_SEPARATOR
, 'Separator', 'Create separator'),
1250 pullDownMenu
.toolBarControls
= [
1251 (pullDownMenu
.ID_NEW_TOOL
, 'Tool', 'Create tool'),
1252 (pullDownMenu
.ID_NEW_SEPARATOR
, 'Separator', 'Create separator'),
1253 ['control', 'Various controls',
1254 (pullDownMenu
.ID_NEW_STATIC_TEXT
, 'Label', 'Create static label'),
1255 (pullDownMenu
.ID_NEW_STATIC_LINE
, 'Line', 'Create static line'),
1256 (pullDownMenu
.ID_NEW_TEXT_CTRL
, 'TextBox', 'Create text box control'),
1257 (pullDownMenu
.ID_NEW_CHOICE
, 'Choice', 'Create choice control'),
1258 (pullDownMenu
.ID_NEW_SLIDER
, 'Slider', 'Create slider control'),
1259 (pullDownMenu
.ID_NEW_GAUGE
, 'Gauge', 'Create gauge control'),
1260 (pullDownMenu
.ID_NEW_SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'),
1261 (pullDownMenu
.ID_NEW_LIST_CTRL
, 'ListCtrl', 'Create list control'),
1263 ['button', 'Buttons',
1264 (pullDownMenu
.ID_NEW_BUTTON
, 'Button', 'Create button'),
1265 (pullDownMenu
.ID_NEW_BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'),
1266 (pullDownMenu
.ID_NEW_RADIO_BUTTON
, 'RadioButton', 'Create radio button'),
1267 (pullDownMenu
.ID_NEW_SPIN_BUTTON
, 'SpinButton', 'Create spin button'),
1270 (pullDownMenu
.ID_NEW_STATIC_BOX
, 'StaticBox', 'Create static box'),
1271 (pullDownMenu
.ID_NEW_CHECK_BOX
, 'CheckBox', 'Create check box'),
1272 (pullDownMenu
.ID_NEW_RADIO_BOX
, 'RadioBox', 'Create radio box'),
1273 (pullDownMenu
.ID_NEW_COMBO_BOX
, 'ComboBox', 'Create combo box'),
1274 (pullDownMenu
.ID_NEW_LIST_BOX
, 'ListBox', 'Create list box'),
1275 (pullDownMenu
.ID_NEW_CHECK_LIST
, 'CheckListBox',
1276 'Create check list control'),
1284 EVT_IDLE(self
, self
.OnIdle
)
1285 EVT_CLOSE(self
, self
.OnCloseWindow
)
1287 def OnNew(self
, evt
):
1290 def OnOpen(self
, evt
):
1291 if not self
.AskSave(): return
1292 dlg
= wxFileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
1293 '', '*.xrc', wxOPEN | wxCHANGE_DIR
)
1294 if dlg
.ShowModal() == wxID_OK
:
1295 path
= dlg
.GetPath()
1296 self
.SetStatusText('Loading...')
1301 self
.SetStatusText('Data loaded')
1303 self
.SetStatusText('Failed')
1308 def OnSaveOrSaveAs(self
, evt
):
1309 if evt
.GetId() == wxID_SAVEAS
or not self
.dataFile
:
1310 if self
.dataFile
: defaultName
= ''
1311 else: defaultName
= 'UNTITLED.xrc'
1312 dlg
= wxFileDialog(self
, 'Save As', os
.path
.dirname(self
.dataFile
),
1313 defaultName
, '*.xrc',
1314 wxSAVE | wxOVERWRITE_PROMPT | wxCHANGE_DIR
)
1315 if dlg
.ShowModal() == wxID_OK
:
1316 path
= dlg
.GetPath()
1322 path
= self
.dataFile
1323 self
.SetStatusText('Saving...')
1328 self
.dataFile
= path
1329 self
.SetStatusText('Data saved')
1331 self
.SetStatusText('Failed')
1334 def OnExit(self
, evt
):
1337 def OnUndo(self
, evt
):
1338 print '*** being implemented'
1340 print self
.lastOp
, self
.undo
1341 if self
.lastOp
== 'DELETE':
1342 parent
, prev
, elem
= self
.undo
1344 xxx
= MakeXXXFromDOM(tree
.GetPyData(parent
).treeObject(), elem
)
1345 item
= tree
.InsertItem( parent
, prev
, xxx
.treeObject().className
,
1346 data
=wxTreeItemData(xxx
) )
1348 def OnRedo(self
, evt
):
1349 print '*** being implemented'
1351 def OnCut(self
, evt
):
1352 selected
= tree
.selection
1353 if not selected
: return # key pressed event
1356 self
.undo
= [tree
.GetItemParent(selected
), tree
.GetPrevSibling(selected
)]
1360 # If deleting top-level item, delete testWin
1361 if selected
== testWin
.item
:
1365 # Remove highlight, update testWin
1366 if not tree
.IsHighlatable(selected
):
1367 if testWin
.highLight
: testWin
.highLight
.Remove()
1368 tree
.needUpdate
= true
1369 self
.clipboard
= tree
.RemoveLeaf(selected
)
1370 tree
.pendingHighLight
= None
1373 self
.modified
= true
1374 self
.SetStatusText('Removed to clipboard')
1376 def OnCopy(self
, evt
):
1377 selected
= tree
.selection
1378 if not selected
: return # key pressed event
1379 xxx
= tree
.GetPyData(selected
)
1380 self
.clipboard
= xxx
.element
.cloneNode(true
)
1381 self
.SetStatusText('Copied')
1383 def OnPaste(self
, evt
):
1384 selected
= tree
.selection
1385 if not selected
: return # key pressed event
1386 # For pasting with Ctrl pressed
1387 if evt
.GetId() == pullDownMenu
.ID_PASTE_SIBLING
: appendChild
= false
1388 else: appendChild
= not tree
.NeedInsert(selected
)
1389 xxx
= tree
.GetPyData(selected
)
1391 # If has next item, insert, else append to parent
1392 nextItem
= tree
.GetNextSibling(selected
)
1394 # Insert before nextItem
1395 parentLeaf
= tree
.GetItemParent(selected
)
1396 else: # last child: change selected to parent
1398 selected
= tree
.GetItemParent(selected
)
1399 # Expanded container (must have children)
1400 elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, false
):
1402 nextItem
= tree
.GetFirstChild(selected
, 0)[0]
1403 parentLeaf
= selected
1404 # Parent should be tree element or None
1406 parent
= tree
.GetPyData(selected
)
1408 parent
= tree
.GetPyData(parentLeaf
)
1409 if parent
.hasChild
: parent
= parent
.child
1411 # Create a copy of clipboard element
1412 elem
= self
.clipboard
.cloneNode(true
)
1413 # Tempopary xxx object to test things
1414 xxx
= MakeXXXFromDOM(parent
, elem
)
1416 # Check compatibility
1419 x
= xxx
.treeObject()
1420 if x
.__class
__ in [xxxDialog
, xxxFrame
, xxxMenuBar
, xxxToolBar
]:
1421 if parent
.__class
__ != xxxMainNode
: error
= true
1422 elif x
.__class
__ == xxxPanel
and parent
.__class
__ == xxxMainNode
:
1424 elif x
.__class
__ == xxxSpacer
:
1425 if not parent
.isSizer
: error
= true
1426 elif x
.__class
__ == xxxSeparator
:
1427 if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error
= true
1428 elif x
.__class
__ == xxxTool
:
1429 if parent
.__class
__ != xxxToolBar
: error
= true
1430 elif x
.__class
__ == xxxMenuItem
:
1431 if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= true
1432 elif x
.isSizer
and parent
.__class
__ == xxxNotebook
: error
= true
1433 else: # normal controls can be almost anywhere
1434 if parent
.__class
__ == xxxMainNode
or \
1435 parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= true
1437 if parent
.__class
__ == xxxMainNode
: parentClass
= 'root'
1438 else: parentClass
= parent
.className
1439 wxLogError('Incompatible parent/child: parent is %s, child is %s!' %
1440 (parentClass
, x
.className
))
1443 # Check parent and child relationships.
1444 # If parent is sizer or notebook, child is of wrong class or
1445 # parent is normal window, child is child container then detach child.
1446 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
1447 if isChildContainer
and \
1448 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
1449 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
1450 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
1451 elem
.removeChild(xxx
.child
.element
) # detach child
1452 elem
.unlink() # delete child container
1453 elem
= xxx
.child
.element
# replace
1454 # This may help garbage collection
1455 xxx
.child
.parent
= None
1456 isChildContainer
= false
1457 # Parent is sizer or notebook, child is not child container
1458 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
1459 # Create sizer item element
1460 sizerItemElem
= MakeEmptyDOM('sizeritem')
1461 sizerItemElem
.appendChild(elem
)
1462 elem
= sizerItemElem
1463 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
1464 pageElem
= MakeEmptyDOM('notebookpage')
1465 pageElem
.appendChild(elem
)
1467 xxx
= MakeXXXFromDOM(parent
, elem
)
1468 # Figure out if we must append a new child or sibling
1470 parent
.element
.appendChild(elem
)
1471 newItem
= tree
.AppendItem(selected
, xxx
.treeName(), image
=xxx
.treeImage(),
1472 data
=wxTreeItemData(xxx
))
1474 node
= tree
.GetPyData(nextItem
).element
1475 parent
.element
.insertBefore(elem
, node
)
1476 # Inserting before is difficult, se we insert after or first child
1477 index
= tree
.ItemIndex(parentLeaf
, nextItem
)
1478 newItem
= tree
.InsertItemBefore(parentLeaf
, index
,
1479 xxx
.treeName(), image
=xxx
.treeImage())
1480 tree
.SetPyData(newItem
, xxx
)
1481 # newItem = tree.InsertItem(parentLeaf, selected, xxx.treeName(),
1482 # image=xxx.treeImage(), data=wxTreeItemData(xxx))
1483 # Add children items
1485 treeObj
= xxx
.treeObject()
1486 for n
in treeObj
.element
.childNodes
:
1488 tree
.AddNode(newItem
, treeObj
, n
)
1489 # Scroll to show new item
1490 tree
.EnsureVisible(newItem
)
1491 tree
.SelectItem(newItem
)
1492 if not tree
.IsVisible(newItem
):
1493 tree
.ScrollTo(newItem
)
1496 if testWin
and tree
.IsHighlatable(newItem
):
1497 if conf
.autoRefresh
:
1498 tree
.needUpdate
= true
1499 tree
.pendingHighLight
= newItem
1501 tree
.pendingHighLight
= None
1502 self
.modified
= true
1503 self
.SetStatusText('Pasted')
1505 def OnDelete(self
, evt
):
1506 selected
= tree
.selection
1507 if not selected
: return # key pressed event
1509 self
.lastOp
= 'DELETE'
1510 self
.undo
= [tree
.GetItemParent(selected
), tree
.GetPrevSibling(selected
)]
1514 # If deleting top-level item, delete testWin
1515 if selected
== testWin
.item
:
1519 # Remove highlight, update testWin
1520 if not tree
.IsHighlatable(selected
):
1521 if testWin
.highLight
: testWin
.highLight
.Remove()
1522 tree
.needUpdate
= true
1523 xnode
= tree
.RemoveLeaf(selected
)
1524 # !!! cloneNode is broken, or something is wrong
1525 # self.undo.append(xnode.cloneNode(true))
1527 tree
.pendingHighLight
= None
1530 self
.modified
= true
1531 self
.SetStatusText('Deleted')
1533 def OnEmbedPanel(self
, evt
):
1534 conf
.embedPanel
= evt
.IsChecked()
1536 # Remember last dimentions
1537 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1538 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1539 size
= self
.GetSize()
1540 pos
= self
.GetPosition()
1541 sizePanel
= panel
.GetSize()
1542 panel
.Reparent(self
.splitter
)
1543 self
.miniFrame
.GetSizer().RemoveWindow(panel
)
1546 self
.SetDimensions(pos
.x
, pos
.y
, size
.x
+ sizePanel
.x
, size
.y
)
1547 self
.splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
1548 self
.miniFrame
.Show(false
)
1550 conf
.sashPos
= self
.splitter
.GetSashPosition()
1551 pos
= self
.GetPosition()
1552 size
= self
.GetSize()
1553 sizePanel
= panel
.GetSize()
1554 self
.splitter
.Unsplit(panel
)
1555 sizer
= self
.miniFrame
.GetSizer()
1556 panel
.Reparent(self
.miniFrame
)
1558 sizer
.Add(panel
, 1, wxEXPAND
)
1559 self
.miniFrame
.Show(true
)
1560 self
.miniFrame
.SetDimensions(conf
.panelX
, conf
.panelY
,
1561 conf
.panelWidth
, conf
.panelHeight
)
1564 self
.SetDimensions(pos
.x
, pos
.y
,
1565 max(size
.x
- sizePanel
.x
, self
.minWidth
), size
.y
)
1567 def OnTest(self
, evt
):
1568 if not tree
.selection
: return # key pressed event
1569 tree
.ShowTestWindow(tree
.selection
)
1571 def OnRefresh(self
, evt
):
1572 # If modified, apply first
1573 selection
= tree
.selection
1575 xxx
= tree
.GetPyData(selection
)
1576 if xxx
and panel
.IsModified():
1577 tree
.Apply(xxx
, selection
)
1580 tree
.CreateTestWin(testWin
.item
)
1581 tree
.needUpdate
= false
1583 def OnAutoRefresh(self
, evt
):
1584 conf
.autoRefresh
= evt
.IsChecked()
1585 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1586 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1588 def OnAbout(self
, evt
):
1589 str = '%s %s\n\nRoman Rolinsky <rolinsky@mema.ucl.ac.be>' % \
1591 dlg
= wxMessageDialog(self
, str, 'About ' + progname
, wxOK | wxCENTRE
)
1595 def OnReadme(self
, evt
):
1596 text
= open(os
.path
.join(sys
.path
[0], 'README'), 'r').read()
1597 dlg
= ScrolledMessageDialog(self
, text
, "XRCed README")
1602 # Simple emulation of python command line
1603 def OnDebugCMD(self
, evt
):
1607 exec raw_input('C:\> ')
1612 (etype
, value
, tb
) =sys
.exc_info()
1613 tblist
=traceback
.extract_tb(tb
)[1:]
1614 msg
=string
.join(traceback
.format_exception_only(etype
, value
)
1615 +traceback
.format_list(tblist
))
1618 def OnCreate(self
, evt
):
1619 selected
= tree
.selection
1620 if tree
.ctrl
: appendChild
= false
1621 else: appendChild
= not tree
.NeedInsert(selected
)
1622 xxx
= tree
.GetPyData(selected
)
1626 # If has previous item, insert after it, else append to parent
1628 parentLeaf
= tree
.GetItemParent(selected
)
1630 # If has next item, insert, else append to parent
1631 nextItem
= tree
.GetNextSibling(selected
)
1633 # Insert before nextItem
1634 parentLeaf
= tree
.GetItemParent(selected
)
1635 else: # last child: change selected to parent
1637 selected
= tree
.GetItemParent(selected
)
1638 # Expanded container (must have children)
1639 elif tree
.shift
and tree
.IsExpanded(selected
) \
1640 and tree
.GetChildrenCount(selected
, false
):
1642 nextItem
= tree
.GetFirstChild(selected
, 0)[0]
1643 parentLeaf
= selected
1644 # Parent should be tree element or None
1646 parent
= tree
.GetPyData(selected
)
1648 parent
= tree
.GetPyData(parentLeaf
)
1649 if parent
.hasChild
: parent
= parent
.child
1652 className
= self
.createMap
[evt
.GetId()]
1653 xxx
= MakeEmptyXXX(parent
, className
)
1655 # Set default name for top-level windows
1656 if parent
.__class
__ == xxxMainNode
:
1657 cl
= xxx
.treeObject().__class
__
1658 frame
.maxIDs
[cl
] += 1
1659 xxx
.treeObject().name
= '%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
])
1660 xxx
.treeObject().element
.setAttribute('name', xxx
.treeObject().name
)
1662 # Figure out if we must append a new child or sibling
1665 # Insert newline for debug purposes
1666 parent
.element
.appendChild(elem
)
1667 newItem
= tree
.AppendItem(selected
, xxx
.treeName(), image
=xxx
.treeImage(),
1668 data
=wxTreeItemData(xxx
))
1670 node
= tree
.GetPyData(nextItem
).element
1671 parent
.element
.insertBefore(elem
, node
)
1672 # !!! There is a different behavious on Win and GTK
1673 # !!! On Win InsertItem(parent, parent, ...) inserts at the end.
1674 index
= tree
.ItemIndex(parentLeaf
, nextItem
)
1675 newItem
= tree
.InsertItemBefore(parentLeaf
, index
,
1676 xxx
.treeName(), image
=xxx
.treeImage())
1677 # data=wxTreeItemData(xxx)) # does not work
1678 tree
.SetPyData(newItem
, xxx
)
1679 # newItem = tree.InsertItem(parentLeaf, selected,
1680 # xxx.treeName(), image=xxx.treeImage(),
1681 # data=wxTreeItemData(xxx))
1682 tree
.EnsureVisible(newItem
)
1683 tree
.SelectItem(newItem
)
1684 if not tree
.IsVisible(newItem
):
1685 tree
.ScrollTo(newItem
)
1688 if testWin
and tree
.IsHighlatable(newItem
):
1689 if conf
.autoRefresh
:
1690 tree
.needUpdate
= true
1691 tree
.pendingHighLight
= newItem
1693 tree
.pendingHighLight
= None
1695 # Expand/collapse subtree
1696 def OnExpand(self
, evt
):
1697 if tree
.selection
: tree
.ExpandAll(tree
.selection
)
1698 else: tree
.ExpandAll(tree
.root
)
1699 def OnCollapse(self
, evt
):
1700 if tree
.selection
: tree
.CollapseAll(tree
.selection
)
1701 else: tree
.CollapseAll(tree
.root
)
1703 def OnPullDownHighlight(self
, evt
):
1704 menuId
= evt
.GetMenuId()
1706 menu
= evt
.GetEventObject()
1707 help = menu
.GetHelpString(menuId
)
1708 self
.SetStatusText(help)
1710 self
.SetStatusText('')
1712 def OnUpdateUI(self
, evt
):
1713 if evt
.GetId() in [wxID_CUT
, wxID_COPY
, self
.ID_DELETE
]:
1714 evt
.Enable(tree
.selection
!= tree
.root
)
1715 elif evt
.GetId() == wxID_PASTE
:
1716 evt
.Enable((self
.clipboard
and tree
.selection
) != None)
1717 elif evt
.GetId() == self
.ID_TEST
:
1718 evt
.Enable(tree
.selection
!= tree
.root
)
1720 def OnIdle(self
, evt
):
1721 if self
.inIdle
: return # Recursive call protection
1724 if conf
.autoRefresh
:
1726 self
.SetStatusText('Refreshing test window...')
1728 tree
.CreateTestWin(testWin
.item
)
1730 self
.SetStatusText('')
1731 tree
.needUpdate
= false
1732 elif tree
.pendingHighLight
:
1733 tree
.HighLight(tree
.pendingHighLight
)
1738 # We don't let close panel window
1739 def OnCloseMiniFrame(self
, evt
):
1742 def OnCloseWindow(self
, evt
):
1743 if not self
.AskSave(): return
1744 if testWin
: testWin
.Destroy()
1745 # Destroy cached windows
1746 panel
.cacheParent
.Destroy()
1747 if not panel
.GetPageCount() == 2:
1748 panel
.page2
.Destroy()
1749 conf
.x
, conf
.y
= self
.GetPosition()
1750 conf
.width
, conf
.height
= self
.GetSize()
1752 conf
.sashPos
= self
.splitter
.GetSashPosition()
1754 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1755 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1760 self
.clipboard
= None
1761 self
.modified
= false
1762 panel
.SetModified(false
)
1769 self
.SetTitle(progname
)
1770 # Numbers for new controls
1772 self
.maxIDs
[xxxPanel
] = self
.maxIDs
[xxxDialog
] = self
.maxIDs
[xxxFrame
] = \
1773 self
.maxIDs
[xxxMenuBar
] = self
.maxIDs
[xxxMenu
] = self
.maxIDs
[xxxToolBar
] = 0
1775 def Open(self
, path
):
1776 # Try to read the file
1781 dom
= minidom
.parse(path
)
1783 self
.dataFile
= path
1784 self
.SetTitle(progname
+ ': ' + os
.path
.basename(path
))
1786 wxLogError('Error reading file: %s' % path
)
1789 def Indent(self
, node
, indent
= 0):
1790 # Copy child list because it will change soon
1791 children
= node
.childNodes
[:]
1792 # Main node doesn't need to be indented
1794 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1795 node
.parentNode
.insertBefore(text
, node
)
1797 # Append newline after last child, except for text nodes
1798 if children
[-1].nodeType
== minidom
.Node
.ELEMENT_NODE
:
1799 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1800 node
.appendChild(text
)
1801 # Indent children which are elements
1803 if n
.nodeType
== minidom
.Node
.ELEMENT_NODE
:
1804 self
.Indent(n
, indent
+ 2)
1806 def Save(self
, path
):
1809 self
.OnRefresh(wxCommandEvent())
1811 # Make temporary copy
1812 # !!! We can't clone dom node, it works only once
1813 #self.domCopy = tree.dom.cloneNode(true)
1814 self
.domCopy
= minidom
.Document()
1815 mainNode
= self
.domCopy
.appendChild(tree
.mainNode
.cloneNode(true
))
1816 self
.Indent(mainNode
)
1817 self
.domCopy
.writexml(f
)
1819 self
.domCopy
.unlink()
1821 self
.modified
= false
1822 panel
.SetModified(false
)
1824 wxLogError('Error writing file: %s' % path
)
1828 if not (self
.modified
or panel
.IsModified()): return true
1829 flags
= wxICON_EXCLAMATION | wxYES_NO | wxCANCEL | wxCENTRE
1830 dlg
= wxMessageDialog( self
, 'File is modified. Save before exit?',
1831 'Save before too late?', flags
)
1832 say
= dlg
.ShowModal()
1835 self
.OnSaveOrSaveAs(wxCommandEvent(wxID_SAVE
))
1836 # If save was successful, modified flag is unset
1837 if not self
.modified
: return true
1838 elif say
== wxID_NO
:
1839 self
.modified
= false
1840 panel
.SetModified(false
)
1844 ################################################################################
1847 print >> sys
.stderr
, 'usage: xrced [-dvh] [file]'
1851 global debug
, verbose
1852 # Process comand-line
1854 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'dvh')
1855 except getopt
.GetoptError
:
1856 print >> sys
.stderr
, 'Unknown option'
1866 print 'XRCed version', version
1869 self
.SetAppName('xrced')
1872 conf
= wxConfig(style
= wxCONFIG_USE_LOCAL_FILE
)
1873 conf
.autoRefresh
= conf
.ReadInt('autorefresh', true
)
1874 pos
= conf
.ReadInt('x', -1), conf
.ReadInt('y', -1)
1875 size
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600)
1876 conf
.embedPanel
= conf
.ReadInt('embedPanel', true
)
1877 conf
.sashPos
= conf
.ReadInt('sashPos', 200)
1878 if not conf
.embedPanel
:
1879 conf
.panelX
= conf
.ReadInt('panelX', -1)
1880 conf
.panelY
= conf
.ReadInt('panelY', -1)
1882 conf
.panelX
= conf
.panelY
= -1
1883 conf
.panelWidth
= conf
.ReadInt('panelWidth', 200)
1884 conf
.panelHeight
= conf
.ReadInt('panelHeight', 200)
1885 conf
.panic
= not conf
.HasEntry('nopanic')
1887 wxFileSystem_AddHandler(wxMemoryFSHandler())
1888 wxInitAllImageHandlers()
1890 frame
= Frame(pos
, size
)
1892 # Load resources from XRC file (!!! should be transformed to .py later?)
1893 ##sys.modules['params'].frame = frame
1895 params
.frame
= frame
1896 frame
.res
= wxXmlResource('')
1897 frame
.res
.Load(os
.path
.join(sys
.path
[0], 'xrced.xrc'))
1899 # Load file after showing
1902 frame
.open = frame
.Open(args
[0])
1909 wc
= wxConfigBase_Get()
1910 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1911 wc
.WriteInt('x', conf
.x
)
1912 wc
.WriteInt('y', conf
.y
)
1913 wc
.WriteInt('width', conf
.width
)
1914 wc
.WriteInt('height', conf
.height
)
1915 wc
.WriteInt('embedPanel', conf
.embedPanel
)
1916 if not conf
.embedPanel
:
1917 wc
.WriteInt('panelX', conf
.panelX
)
1918 wc
.WriteInt('panelY', conf
.panelY
)
1919 wc
.WriteInt('sashPos', conf
.sashPos
)
1920 wc
.WriteInt('panelWidth', conf
.panelWidth
)
1921 wc
.WriteInt('panelHeight', conf
.panelHeight
)
1922 wc
.WriteInt('nopanic', 1)
1931 if __name__
== '__main__':