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
.LoadFrame(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
)
1011 menuBar
= wxMenuBar()
1014 menu
.Append(wxID_NEW
, '&New\tCtrl-N', 'New file')
1015 menu
.Append(wxID_OPEN
, '&Open...\tCtrl-O', 'Open XRC file')
1016 menu
.Append(wxID_SAVE
, '&Save\tCtrl-S', 'Save XRC file')
1017 menu
.Append(wxID_SAVEAS
, 'Save &As...', 'Save XRC file under different name')
1018 menu
.AppendSeparator()
1019 menu
.Append(wxID_EXIT
, '&Quit\tCtrl-Q', 'Exit application')
1020 menuBar
.Append(menu
, '&File')
1023 menu
.Append(wxID_UNDO
, '&Undo\tCtrl-Z', 'Undo')
1024 menu
.Append(wxID_REDO
, '&Redo\tCtrl-Y', 'Redo')
1025 menu
.AppendSeparator()
1026 menu
.Append(wxID_CUT
, 'Cut\tCtrl-X', 'Cut to the clipboard')
1027 menu
.Append(wxID_COPY
, '&Copy\tCtrl-C', 'Copy to the clipboard')
1028 menu
.Append(wxID_PASTE
, '&Paste\tCtrl-V', 'Paste from the clipboard')
1029 self
.ID_DELETE
= wxNewId()
1030 menu
.Append(self
.ID_DELETE
, '&Delete\tCtrl-D', 'Delete object')
1031 menuBar
.Append(menu
, '&Edit')
1034 self
.ID_EMBED_PANEL
= wxNewId()
1035 menu
.Append(self
.ID_EMBED_PANEL
, '&Embed Panel',
1036 'Toggle embedding properties panel in the main window', true
)
1037 menu
.Check(self
.ID_EMBED_PANEL
, conf
.embedPanel
)
1038 menu
.AppendSeparator()
1039 self
.ID_TEST
= wxNewId()
1040 menu
.Append(self
.ID_TEST
, '&Test\tF5', 'Test window')
1041 self
.ID_REFRESH
= wxNewId()
1042 menu
.Append(self
.ID_REFRESH
, '&Refresh\tCtrl-R', 'Refresh test window')
1043 self
.ID_AUTO_REFRESH
= wxNewId()
1044 menu
.Append(self
.ID_AUTO_REFRESH
, '&Auto-refresh\tCtrl-A',
1045 'Toggle auto-refresh mode', true
)
1046 menu
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1047 menuBar
.Append(menu
, '&View')
1050 menu
.Append(wxID_ABOUT
, '&About...', 'About XCRed')
1051 self
.ID_README
= wxNewId()
1052 menu
.Append(self
.ID_README
, '&Readme...', 'View the README file')
1054 self
.ID_DEBUG_CMD
= wxNewId()
1055 menu
.Append(self
.ID_DEBUG_CMD
, 'CMD', 'Python command line')
1056 EVT_MENU(self
, self
.ID_DEBUG_CMD
, self
.OnDebugCMD
)
1057 menuBar
.Append(menu
, '&Help')
1059 self
.menuBar
= menuBar
1060 self
.SetMenuBar(menuBar
)
1063 tb
= self
.CreateToolBar(wxTB_HORIZONTAL | wxNO_BORDER | wxTB_FLAT
)
1064 tb
.SetToolBitmapSize((24, 23))
1065 tb
.AddSimpleTool(wxID_NEW
, images
.getNewBitmap(), 'New', 'New file')
1066 tb
.AddSimpleTool(wxID_OPEN
, images
.getOpenBitmap(), 'Open', 'Open file')
1067 tb
.AddSimpleTool(wxID_SAVE
, images
.getSaveBitmap(), 'Save', 'Save file')
1068 tb
.AddControl(wxStaticLine(tb
, -1, size
=(-1,23), style
=wxLI_VERTICAL
))
1069 tb
.AddSimpleTool(wxID_CUT
, images
.getCutBitmap(), 'Cut', 'Cut')
1070 tb
.AddSimpleTool(wxID_COPY
, images
.getCopyBitmap(), 'Copy', 'Copy')
1071 tb
.AddSimpleTool(wxID_PASTE
, images
.getPasteBitmap(), 'Paste', 'Paste')
1072 tb
.AddControl(wxStaticLine(tb
, -1, size
=(-1,23), style
=wxLI_VERTICAL
))
1073 tb
.AddSimpleTool(self
.ID_TEST
, images
.getTestBitmap(), 'Test', 'Test window')
1074 tb
.AddSimpleTool(self
.ID_REFRESH
, images
.getRefreshBitmap(),
1075 'Refresh', 'Refresh view')
1076 tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, images
.getAutoRefreshBitmap(),
1077 'Auto-refresh', 'Toggle auto-refresh mode', true
)
1078 if wxGetOsVersion()[0] == wxGTK
:
1079 tb
.AddSeparator() # otherwise auto-refresh sticks in status line
1080 tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1083 self
.minWidth
= tb
.GetSize()[0] # minimal width is the size of toolbar
1086 EVT_MENU(self
, wxID_NEW
, self
.OnNew
)
1087 EVT_MENU(self
, wxID_OPEN
, self
.OnOpen
)
1088 EVT_MENU(self
, wxID_SAVE
, self
.OnSaveOrSaveAs
)
1089 EVT_MENU(self
, wxID_SAVEAS
, self
.OnSaveOrSaveAs
)
1090 EVT_MENU(self
, wxID_EXIT
, self
.OnExit
)
1092 EVT_MENU(self
, wxID_UNDO
, self
.OnUndo
)
1093 EVT_MENU(self
, wxID_REDO
, self
.OnRedo
)
1094 EVT_MENU(self
, wxID_CUT
, self
.OnCut
)
1095 EVT_MENU(self
, wxID_COPY
, self
.OnCopy
)
1096 EVT_MENU(self
, wxID_PASTE
, self
.OnPaste
)
1097 EVT_MENU(self
, self
.ID_DELETE
, self
.OnDelete
)
1099 EVT_MENU(self
, self
.ID_EMBED_PANEL
, self
.OnEmbedPanel
)
1100 EVT_MENU(self
, self
.ID_TEST
, self
.OnTest
)
1101 EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
)
1102 EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
)
1104 EVT_MENU(self
, wxID_ABOUT
, self
.OnAbout
)
1105 EVT_MENU(self
, self
.ID_README
, self
.OnReadme
)
1108 EVT_UPDATE_UI(self
, wxID_CUT
, self
.OnUpdateUI
)
1109 EVT_UPDATE_UI(self
, wxID_COPY
, self
.OnUpdateUI
)
1110 EVT_UPDATE_UI(self
, wxID_PASTE
, self
.OnUpdateUI
)
1111 EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
)
1112 EVT_UPDATE_UI(self
, self
.ID_TEST
, self
.OnUpdateUI
)
1113 EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
)
1116 sizer
= wxBoxSizer(wxVERTICAL
)
1117 sizer
.Add(wxStaticLine(self
, -1), 0, wxEXPAND
)
1118 splitter
= wxSplitterWindow(self
, -1, style
=wxSP_3DSASH
)
1119 self
.splitter
= splitter
1120 splitter
.SetMinimumPaneSize(100)
1124 tree
= XML_Tree(splitter
, -1)
1125 ##sys.modules['xxx'].tree = tree
1129 # !!! frame styles are broken
1130 # Miniframe for not embedded mode
1131 miniFrame
= wxFrame(self
, -1, 'Properties Panel',
1132 (conf
.panelX
, conf
.panelY
),
1133 (conf
.panelWidth
, conf
.panelHeight
))
1134 self
.miniFrame
= miniFrame
1135 sizer2
= wxBoxSizer()
1136 miniFrame
.SetAutoLayout(true
)
1137 miniFrame
.SetSizer(sizer2
)
1138 EVT_CLOSE(self
.miniFrame
, self
.OnCloseMiniFrame
)
1139 # Create panel for parameters
1142 panel
= Panel(splitter
)
1143 # Set plitter windows
1144 splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
1146 panel
= Panel(miniFrame
)
1147 sizer2
.Add(panel
, 1, wxEXPAND
)
1148 miniFrame
.Show(true
)
1149 splitter
.Initialize(tree
)
1150 sizer
.Add(splitter
, 1, wxEXPAND
)
1151 self
.SetAutoLayout(true
)
1152 self
.SetSizer(sizer
)
1154 # Init pull-down menu data
1156 pullDownMenu
= PullDownMenu(self
)
1157 # Mapping from IDs to element names
1159 pullDownMenu
.ID_NEW_PANEL
: 'wxPanel',
1160 pullDownMenu
.ID_NEW_DIALOG
: 'wxDialog',
1161 pullDownMenu
.ID_NEW_FRAME
: 'wxFrame',
1162 pullDownMenu
.ID_NEW_TOOL_BAR
: 'wxToolBar',
1163 pullDownMenu
.ID_NEW_TOOL
: 'tool',
1164 pullDownMenu
.ID_NEW_MENU_BAR
: 'wxMenuBar',
1165 pullDownMenu
.ID_NEW_MENU
: 'wxMenu',
1166 pullDownMenu
.ID_NEW_MENU_ITEM
: 'wxMenuItem',
1167 pullDownMenu
.ID_NEW_SEPARATOR
: 'separator',
1169 pullDownMenu
.ID_NEW_STATIC_TEXT
: 'wxStaticText',
1170 pullDownMenu
.ID_NEW_TEXT_CTRL
: 'wxTextCtrl',
1172 pullDownMenu
.ID_NEW_BUTTON
: 'wxButton',
1173 pullDownMenu
.ID_NEW_BITMAP_BUTTON
: 'wxBitmapButton',
1174 pullDownMenu
.ID_NEW_RADIO_BUTTON
: 'wxRadioButton',
1175 pullDownMenu
.ID_NEW_SPIN_BUTTON
: 'wxSpinButton',
1177 pullDownMenu
.ID_NEW_STATIC_BOX
: 'wxStaticBox',
1178 pullDownMenu
.ID_NEW_CHECK_BOX
: 'wxCheckBox',
1179 pullDownMenu
.ID_NEW_RADIO_BOX
: 'wxRadioBox',
1180 pullDownMenu
.ID_NEW_COMBO_BOX
: 'wxComboBox',
1181 pullDownMenu
.ID_NEW_LIST_BOX
: 'wxListBox',
1183 pullDownMenu
.ID_NEW_STATIC_LINE
: 'wxStaticLine',
1184 pullDownMenu
.ID_NEW_STATIC_BITMAP
: 'wxStaticBitmap',
1185 pullDownMenu
.ID_NEW_CHOICE
: 'wxChoice',
1186 pullDownMenu
.ID_NEW_SLIDER
: 'wxSlider',
1187 pullDownMenu
.ID_NEW_GAUGE
: 'wxGauge',
1188 pullDownMenu
.ID_NEW_SCROLL_BAR
: 'wxScrollBar',
1189 pullDownMenu
.ID_NEW_TREE_CTRL
: 'wxTreeCtrl',
1190 pullDownMenu
.ID_NEW_LIST_CTRL
: 'wxListCtrl',
1191 pullDownMenu
.ID_NEW_CHECK_LIST
: 'wxCheckList',
1192 pullDownMenu
.ID_NEW_NOTEBOOK
: 'wxNotebook',
1193 pullDownMenu
.ID_NEW_HTML_WINDOW
: 'wxHtmlWindow',
1194 pullDownMenu
.ID_NEW_CALENDAR
: 'wxCalendar',
1196 pullDownMenu
.ID_NEW_BOX_SIZER
: 'wxBoxSizer',
1197 pullDownMenu
.ID_NEW_STATIC_BOX_SIZER
: 'wxStaticBoxSizer',
1198 pullDownMenu
.ID_NEW_GRID_SIZER
: 'wxGridSizer',
1199 pullDownMenu
.ID_NEW_FLEX_GRID_SIZER
: 'wxFlexGridSizer',
1200 pullDownMenu
.ID_NEW_SPACER
: 'spacer',
1202 pullDownMenu
.controls
= [
1203 ['control', 'Various controls',
1204 (pullDownMenu
.ID_NEW_STATIC_TEXT
, 'Label', 'Create static label'),
1205 (pullDownMenu
.ID_NEW_STATIC_LINE
, 'Line', 'Create static line'),
1206 (pullDownMenu
.ID_NEW_TEXT_CTRL
, 'TextBox', 'Create text box control'),
1207 (pullDownMenu
.ID_NEW_CHOICE
, 'Choice', 'Create choice control'),
1208 (pullDownMenu
.ID_NEW_SLIDER
, 'Slider', 'Create slider control'),
1209 (pullDownMenu
.ID_NEW_GAUGE
, 'Gauge', 'Create gauge control'),
1210 (pullDownMenu
.ID_NEW_SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'),
1211 (pullDownMenu
.ID_NEW_TREE_CTRL
, 'TreeCtrl', 'Create tree control'),
1212 (pullDownMenu
.ID_NEW_LIST_CTRL
, 'ListCtrl', 'Create list control'),
1213 (pullDownMenu
.ID_NEW_HTML_WINDOW
, 'HtmlWindow', 'Create HTML window'),
1214 (pullDownMenu
.ID_NEW_CALENDAR
, 'Calendar', 'Create calendar control'),
1215 (pullDownMenu
.ID_NEW_PANEL
, 'Panel', 'Create panel'),
1216 (pullDownMenu
.ID_NEW_NOTEBOOK
, 'Notebook', 'Create notebook control'),
1218 ['button', 'Buttons',
1219 (pullDownMenu
.ID_NEW_BUTTON
, 'Button', 'Create button'),
1220 (pullDownMenu
.ID_NEW_BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'),
1221 (pullDownMenu
.ID_NEW_RADIO_BUTTON
, 'RadioButton', 'Create radio button'),
1222 (pullDownMenu
.ID_NEW_SPIN_BUTTON
, 'SpinButton', 'Create spin button'),
1225 (pullDownMenu
.ID_NEW_STATIC_BOX
, 'StaticBox', 'Create static box'),
1226 (pullDownMenu
.ID_NEW_CHECK_BOX
, 'CheckBox', 'Create check box'),
1227 (pullDownMenu
.ID_NEW_RADIO_BOX
, 'RadioBox', 'Create radio box'),
1228 (pullDownMenu
.ID_NEW_COMBO_BOX
, 'ComboBox', 'Create combo box'),
1229 (pullDownMenu
.ID_NEW_LIST_BOX
, 'ListBox', 'Create list box'),
1230 (pullDownMenu
.ID_NEW_CHECK_LIST
, 'CheckListBox',
1231 'Create check list control'),
1234 (pullDownMenu
.ID_NEW_BOX_SIZER
, 'BoxSizer', 'Create box sizer'),
1235 (pullDownMenu
.ID_NEW_STATIC_BOX_SIZER
, 'StaticBoxSizer',
1236 'Create static box sizer'),
1237 (pullDownMenu
.ID_NEW_GRID_SIZER
, 'GridSizer', 'Create grid sizer'),
1238 (pullDownMenu
.ID_NEW_FLEX_GRID_SIZER
, 'FlexGridSizer',
1239 'Create flexgrid sizer'),
1240 (pullDownMenu
.ID_NEW_SPACER
, 'Spacer', 'Create spacer'),
1243 pullDownMenu
.menuControls
= [
1244 (pullDownMenu
.ID_NEW_MENU
, 'Menu', 'Create menu'),
1245 (pullDownMenu
.ID_NEW_MENU_ITEM
, 'MenuItem', 'Create menu item'),
1246 (pullDownMenu
.ID_NEW_SEPARATOR
, 'Separator', 'Create separator'),
1248 pullDownMenu
.toolBarControls
= [
1249 (pullDownMenu
.ID_NEW_TOOL
, 'Tool', 'Create tool'),
1250 (pullDownMenu
.ID_NEW_SEPARATOR
, 'Separator', 'Create separator'),
1251 ['control', 'Various controls',
1252 (pullDownMenu
.ID_NEW_STATIC_TEXT
, 'Label', 'Create static label'),
1253 (pullDownMenu
.ID_NEW_STATIC_LINE
, 'Line', 'Create static line'),
1254 (pullDownMenu
.ID_NEW_TEXT_CTRL
, 'TextBox', 'Create text box control'),
1255 (pullDownMenu
.ID_NEW_CHOICE
, 'Choice', 'Create choice control'),
1256 (pullDownMenu
.ID_NEW_SLIDER
, 'Slider', 'Create slider control'),
1257 (pullDownMenu
.ID_NEW_GAUGE
, 'Gauge', 'Create gauge control'),
1258 (pullDownMenu
.ID_NEW_SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'),
1259 (pullDownMenu
.ID_NEW_LIST_CTRL
, 'ListCtrl', 'Create list control'),
1261 ['button', 'Buttons',
1262 (pullDownMenu
.ID_NEW_BUTTON
, 'Button', 'Create button'),
1263 (pullDownMenu
.ID_NEW_BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'),
1264 (pullDownMenu
.ID_NEW_RADIO_BUTTON
, 'RadioButton', 'Create radio button'),
1265 (pullDownMenu
.ID_NEW_SPIN_BUTTON
, 'SpinButton', 'Create spin button'),
1268 (pullDownMenu
.ID_NEW_STATIC_BOX
, 'StaticBox', 'Create static box'),
1269 (pullDownMenu
.ID_NEW_CHECK_BOX
, 'CheckBox', 'Create check box'),
1270 (pullDownMenu
.ID_NEW_RADIO_BOX
, 'RadioBox', 'Create radio box'),
1271 (pullDownMenu
.ID_NEW_COMBO_BOX
, 'ComboBox', 'Create combo box'),
1272 (pullDownMenu
.ID_NEW_LIST_BOX
, 'ListBox', 'Create list box'),
1273 (pullDownMenu
.ID_NEW_CHECK_LIST
, 'CheckListBox',
1274 'Create check list control'),
1282 EVT_IDLE(self
, self
.OnIdle
)
1283 EVT_CLOSE(self
, self
.OnCloseWindow
)
1285 def OnNew(self
, evt
):
1288 def OnOpen(self
, evt
):
1289 if not self
.AskSave(): return
1290 dlg
= wxFileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
1291 '', '*.xrc', wxOPEN | wxCHANGE_DIR
)
1292 if dlg
.ShowModal() == wxID_OK
:
1293 path
= dlg
.GetPath()
1294 self
.SetStatusText('Loading...')
1299 self
.SetStatusText('Data loaded')
1301 self
.SetStatusText('Failed')
1306 def OnSaveOrSaveAs(self
, evt
):
1307 if evt
.GetId() == wxID_SAVEAS
or not self
.dataFile
:
1308 if self
.dataFile
: defaultName
= ''
1309 else: defaultName
= 'UNTITLED.xrc'
1310 dlg
= wxFileDialog(self
, 'Save As', os
.path
.dirname(self
.dataFile
),
1311 defaultName
, '*.xrc',
1312 wxSAVE | wxOVERWRITE_PROMPT | wxCHANGE_DIR
)
1313 if dlg
.ShowModal() == wxID_OK
:
1314 path
= dlg
.GetPath()
1320 path
= self
.dataFile
1321 self
.SetStatusText('Saving...')
1326 self
.dataFile
= path
1327 self
.SetStatusText('Data saved')
1329 self
.SetStatusText('Failed')
1332 def OnExit(self
, evt
):
1335 def OnUndo(self
, evt
):
1336 print '*** being implemented'
1338 print self
.lastOp
, self
.undo
1339 if self
.lastOp
== 'DELETE':
1340 parent
, prev
, elem
= self
.undo
1342 xxx
= MakeXXXFromDOM(tree
.GetPyData(parent
).treeObject(), elem
)
1343 item
= tree
.InsertItem( parent
, prev
, xxx
.treeObject().className
,
1344 data
=wxTreeItemData(xxx
) )
1346 def OnRedo(self
, evt
):
1347 print '*** being implemented'
1349 def OnCut(self
, evt
):
1350 selected
= tree
.selection
1351 if not selected
: return # key pressed event
1354 self
.undo
= [tree
.GetItemParent(selected
), tree
.GetPrevSibling(selected
)]
1358 # If deleting top-level item, delete testWin
1359 if selected
== testWin
.item
:
1363 # Remove highlight, update testWin
1364 if not tree
.IsHighlatable(selected
):
1365 if testWin
.highLight
: testWin
.highLight
.Remove()
1366 tree
.needUpdate
= true
1367 self
.clipboard
= tree
.RemoveLeaf(selected
)
1368 tree
.pendingHighLight
= None
1371 self
.modified
= true
1372 self
.SetStatusText('Removed to clipboard')
1374 def OnCopy(self
, evt
):
1375 selected
= tree
.selection
1376 if not selected
: return # key pressed event
1377 xxx
= tree
.GetPyData(selected
)
1378 self
.clipboard
= xxx
.element
.cloneNode(true
)
1379 self
.SetStatusText('Copied')
1381 def OnPaste(self
, evt
):
1382 selected
= tree
.selection
1383 if not selected
: return # key pressed event
1384 # For pasting with Ctrl pressed
1385 if evt
.GetId() == pullDownMenu
.ID_PASTE_SIBLING
: appendChild
= false
1386 else: appendChild
= not tree
.NeedInsert(selected
)
1387 xxx
= tree
.GetPyData(selected
)
1389 # If has next item, insert, else append to parent
1390 nextItem
= tree
.GetNextSibling(selected
)
1392 # Insert before nextItem
1393 parentLeaf
= tree
.GetItemParent(selected
)
1394 else: # last child: change selected to parent
1396 selected
= tree
.GetItemParent(selected
)
1397 # Expanded container (must have children)
1398 elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, false
):
1400 nextItem
= tree
.GetFirstChild(selected
, 0)[0]
1401 parentLeaf
= selected
1402 # Parent should be tree element or None
1404 parent
= tree
.GetPyData(selected
)
1406 parent
= tree
.GetPyData(parentLeaf
)
1407 if parent
.hasChild
: parent
= parent
.child
1409 # Create a copy of clipboard element
1410 elem
= self
.clipboard
.cloneNode(true
)
1411 # Tempopary xxx object to test things
1412 xxx
= MakeXXXFromDOM(parent
, elem
)
1414 # Check compatibility
1417 x
= xxx
.treeObject()
1418 if x
.__class
__ in [xxxDialog
, xxxFrame
, xxxMenuBar
, xxxToolBar
]:
1419 if parent
.__class
__ != xxxMainNode
: error
= true
1420 elif x
.__class
__ == xxxPanel
and parent
.__class
__ == xxxMainNode
:
1422 elif x
.__class
__ == xxxSpacer
:
1423 if not parent
.isSizer
: error
= true
1424 elif x
.__class
__ == xxxSeparator
:
1425 if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error
= true
1426 elif x
.__class
__ == xxxTool
:
1427 if parent
.__class
__ != xxxToolBar
: error
= true
1428 elif x
.__class
__ == xxxMenuItem
:
1429 if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= true
1430 elif x
.isSizer
and parent
.__class
__ == xxxNotebook
: error
= true
1431 else: # normal controls can be almost anywhere
1432 if parent
.__class
__ == xxxMainNode
or \
1433 parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= true
1435 if parent
.__class
__ == xxxMainNode
: parentClass
= 'root'
1436 else: parentClass
= parent
.className
1437 wxLogError('Incompatible parent/child: parent is %s, child is %s!' %
1438 (parentClass
, x
.className
))
1441 # Check parent and child relationships.
1442 # If parent is sizer or notebook, child is of wrong class or
1443 # parent is normal window, child is child container then detach child.
1444 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
1445 if isChildContainer
and \
1446 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
1447 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
1448 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
1449 elem
.removeChild(xxx
.child
.element
) # detach child
1450 elem
.unlink() # delete child container
1451 elem
= xxx
.child
.element
# replace
1452 # This may help garbage collection
1453 xxx
.child
.parent
= None
1454 isChildContainer
= false
1455 # Parent is sizer or notebook, child is not child container
1456 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
1457 # Create sizer item element
1458 sizerItemElem
= MakeEmptyDOM('sizeritem')
1459 sizerItemElem
.appendChild(elem
)
1460 elem
= sizerItemElem
1461 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
1462 pageElem
= MakeEmptyDOM('notebookpage')
1463 pageElem
.appendChild(elem
)
1465 xxx
= MakeXXXFromDOM(parent
, elem
)
1466 # Figure out if we must append a new child or sibling
1468 parent
.element
.appendChild(elem
)
1469 newItem
= tree
.AppendItem(selected
, xxx
.treeName(), image
=xxx
.treeImage(),
1470 data
=wxTreeItemData(xxx
))
1472 node
= tree
.GetPyData(nextItem
).element
1473 parent
.element
.insertBefore(elem
, node
)
1474 # Inserting before is difficult, se we insert after or first child
1475 index
= tree
.ItemIndex(parentLeaf
, nextItem
)
1476 newItem
= tree
.InsertItemBefore(parentLeaf
, index
,
1477 xxx
.treeName(), image
=xxx
.treeImage())
1478 tree
.SetPyData(newItem
, xxx
)
1479 # newItem = tree.InsertItem(parentLeaf, selected, xxx.treeName(),
1480 # image=xxx.treeImage(), data=wxTreeItemData(xxx))
1481 # Add children items
1483 treeObj
= xxx
.treeObject()
1484 for n
in treeObj
.element
.childNodes
:
1486 tree
.AddNode(newItem
, treeObj
, n
)
1487 # Scroll to show new item
1488 tree
.EnsureVisible(newItem
)
1489 tree
.SelectItem(newItem
)
1490 if not tree
.IsVisible(newItem
):
1491 tree
.ScrollTo(newItem
)
1494 if testWin
and tree
.IsHighlatable(newItem
):
1495 if conf
.autoRefresh
:
1496 tree
.needUpdate
= true
1497 tree
.pendingHighLight
= newItem
1499 tree
.pendingHighLight
= None
1500 self
.modified
= true
1501 self
.SetStatusText('Pasted')
1503 def OnDelete(self
, evt
):
1504 selected
= tree
.selection
1505 if not selected
: return # key pressed event
1507 self
.lastOp
= 'DELETE'
1508 self
.undo
= [tree
.GetItemParent(selected
), tree
.GetPrevSibling(selected
)]
1512 # If deleting top-level item, delete testWin
1513 if selected
== testWin
.item
:
1517 # Remove highlight, update testWin
1518 if not tree
.IsHighlatable(selected
):
1519 if testWin
.highLight
: testWin
.highLight
.Remove()
1520 tree
.needUpdate
= true
1521 xnode
= tree
.RemoveLeaf(selected
)
1522 # !!! cloneNode is broken, or something is wrong
1523 # self.undo.append(xnode.cloneNode(true))
1525 tree
.pendingHighLight
= None
1528 self
.modified
= true
1529 self
.SetStatusText('Deleted')
1531 def OnEmbedPanel(self
, evt
):
1532 conf
.embedPanel
= evt
.IsChecked()
1534 # Remember last dimentions
1535 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1536 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1537 size
= self
.GetSize()
1538 pos
= self
.GetPosition()
1539 sizePanel
= panel
.GetSize()
1540 panel
.Reparent(self
.splitter
)
1541 self
.miniFrame
.GetSizer().RemoveWindow(panel
)
1544 self
.SetDimensions(pos
.x
, pos
.y
, size
.x
+ sizePanel
.x
, size
.y
)
1545 self
.splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
1546 self
.miniFrame
.Show(false
)
1548 conf
.sashPos
= self
.splitter
.GetSashPosition()
1549 pos
= self
.GetPosition()
1550 size
= self
.GetSize()
1551 sizePanel
= panel
.GetSize()
1552 self
.splitter
.Unsplit(panel
)
1553 sizer
= self
.miniFrame
.GetSizer()
1554 panel
.Reparent(self
.miniFrame
)
1556 sizer
.Add(panel
, 1, wxEXPAND
)
1557 self
.miniFrame
.Show(true
)
1558 self
.miniFrame
.SetDimensions(conf
.panelX
, conf
.panelY
,
1559 conf
.panelWidth
, conf
.panelHeight
)
1562 self
.SetDimensions(pos
.x
, pos
.y
,
1563 max(size
.x
- sizePanel
.x
, self
.minWidth
), size
.y
)
1565 def OnTest(self
, evt
):
1566 if not tree
.selection
: return # key pressed event
1567 tree
.ShowTestWindow(tree
.selection
)
1569 def OnRefresh(self
, evt
):
1570 # If modified, apply first
1571 selection
= tree
.selection
1573 xxx
= tree
.GetPyData(selection
)
1574 if xxx
and panel
.IsModified():
1575 tree
.Apply(xxx
, selection
)
1578 tree
.CreateTestWin(testWin
.item
)
1579 tree
.needUpdate
= false
1581 def OnAutoRefresh(self
, evt
):
1582 conf
.autoRefresh
= evt
.IsChecked()
1583 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1584 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1586 def OnAbout(self
, evt
):
1587 str = '%s %s\n\nRoman Rolinsky <rolinsky@mema.ucl.ac.be>' % \
1589 dlg
= wxMessageDialog(self
, str, 'About ' + progname
, wxOK | wxCENTRE
)
1593 def OnReadme(self
, evt
):
1594 text
= open(os
.path
.join(sys
.path
[0], 'README'), 'r').read()
1595 dlg
= ScrolledMessageDialog(self
, text
, "XRCed README")
1600 # Simple emulation of python command line
1601 def OnDebugCMD(self
, evt
):
1605 exec raw_input('C:\> ')
1610 (etype
, value
, tb
) =sys
.exc_info()
1611 tblist
=traceback
.extract_tb(tb
)[1:]
1612 msg
=string
.join(traceback
.format_exception_only(etype
, value
)
1613 +traceback
.format_list(tblist
))
1616 def OnCreate(self
, evt
):
1617 selected
= tree
.selection
1618 if tree
.ctrl
: appendChild
= false
1619 else: appendChild
= not tree
.NeedInsert(selected
)
1620 xxx
= tree
.GetPyData(selected
)
1624 # If has previous item, insert after it, else append to parent
1626 parentLeaf
= tree
.GetItemParent(selected
)
1628 # If has next item, insert, else append to parent
1629 nextItem
= tree
.GetNextSibling(selected
)
1631 # Insert before nextItem
1632 parentLeaf
= tree
.GetItemParent(selected
)
1633 else: # last child: change selected to parent
1635 selected
= tree
.GetItemParent(selected
)
1636 # Expanded container (must have children)
1637 elif tree
.shift
and tree
.IsExpanded(selected
) \
1638 and tree
.GetChildrenCount(selected
, false
):
1640 nextItem
= tree
.GetFirstChild(selected
, 0)[0]
1641 parentLeaf
= selected
1642 # Parent should be tree element or None
1644 parent
= tree
.GetPyData(selected
)
1646 parent
= tree
.GetPyData(parentLeaf
)
1647 if parent
.hasChild
: parent
= parent
.child
1650 className
= self
.createMap
[evt
.GetId()]
1651 xxx
= MakeEmptyXXX(parent
, className
)
1653 # Set default name for top-level windows
1654 if parent
.__class
__ == xxxMainNode
:
1655 cl
= xxx
.treeObject().__class
__
1656 frame
.maxIDs
[cl
] += 1
1657 xxx
.treeObject().name
= '%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
])
1658 xxx
.treeObject().element
.setAttribute('name', xxx
.treeObject().name
)
1660 # Figure out if we must append a new child or sibling
1663 # Insert newline for debug purposes
1664 parent
.element
.appendChild(elem
)
1665 newItem
= tree
.AppendItem(selected
, xxx
.treeName(), image
=xxx
.treeImage(),
1666 data
=wxTreeItemData(xxx
))
1668 node
= tree
.GetPyData(nextItem
).element
1669 parent
.element
.insertBefore(elem
, node
)
1670 # !!! There is a different behavious on Win and GTK
1671 # !!! On Win InsertItem(parent, parent, ...) inserts at the end.
1672 index
= tree
.ItemIndex(parentLeaf
, nextItem
)
1673 newItem
= tree
.InsertItemBefore(parentLeaf
, index
,
1674 xxx
.treeName(), image
=xxx
.treeImage())
1675 # data=wxTreeItemData(xxx)) # does not work
1676 tree
.SetPyData(newItem
, xxx
)
1677 # newItem = tree.InsertItem(parentLeaf, selected,
1678 # xxx.treeName(), image=xxx.treeImage(),
1679 # data=wxTreeItemData(xxx))
1680 tree
.EnsureVisible(newItem
)
1681 tree
.SelectItem(newItem
)
1682 if not tree
.IsVisible(newItem
):
1683 tree
.ScrollTo(newItem
)
1686 if testWin
and tree
.IsHighlatable(newItem
):
1687 if conf
.autoRefresh
:
1688 tree
.needUpdate
= true
1689 tree
.pendingHighLight
= newItem
1691 tree
.pendingHighLight
= None
1693 # Expand/collapse subtree
1694 def OnExpand(self
, evt
):
1695 if tree
.selection
: tree
.ExpandAll(tree
.selection
)
1696 else: tree
.ExpandAll(tree
.root
)
1697 def OnCollapse(self
, evt
):
1698 if tree
.selection
: tree
.CollapseAll(tree
.selection
)
1699 else: tree
.CollapseAll(tree
.root
)
1701 def OnPullDownHighlight(self
, evt
):
1702 menuId
= evt
.GetMenuId()
1704 menu
= evt
.GetEventObject()
1705 help = menu
.GetHelpString(menuId
)
1706 self
.SetStatusText(help)
1708 self
.SetStatusText('')
1710 def OnUpdateUI(self
, evt
):
1711 if evt
.GetId() in [wxID_CUT
, wxID_COPY
, self
.ID_DELETE
]:
1712 evt
.Enable(tree
.selection
!= tree
.root
)
1713 elif evt
.GetId() == wxID_PASTE
:
1714 evt
.Enable((self
.clipboard
and tree
.selection
) != None)
1715 elif evt
.GetId() == self
.ID_TEST
:
1716 evt
.Enable(tree
.selection
!= tree
.root
)
1718 def OnIdle(self
, evt
):
1719 if self
.inIdle
: return # Recursive call protection
1722 if conf
.autoRefresh
:
1724 self
.SetStatusText('Refreshing test window...')
1726 tree
.CreateTestWin(testWin
.item
)
1728 self
.SetStatusText('')
1729 tree
.needUpdate
= false
1730 elif tree
.pendingHighLight
:
1731 tree
.HighLight(tree
.pendingHighLight
)
1736 # We don't let close panel window
1737 def OnCloseMiniFrame(self
, evt
):
1740 def OnCloseWindow(self
, evt
):
1741 if not self
.AskSave(): return
1742 if testWin
: testWin
.Destroy()
1743 # Destroy cached windows
1744 panel
.cacheParent
.Destroy()
1745 if not panel
.GetPageCount() == 2:
1746 panel
.page2
.Destroy()
1747 conf
.x
, conf
.y
= self
.GetPosition()
1748 conf
.width
, conf
.height
= self
.GetSize()
1750 conf
.sashPos
= self
.splitter
.GetSashPosition()
1752 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1753 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1758 self
.clipboard
= None
1759 self
.modified
= false
1760 panel
.SetModified(false
)
1767 self
.SetTitle(progname
)
1768 # Numbers for new controls
1770 self
.maxIDs
[xxxPanel
] = self
.maxIDs
[xxxDialog
] = self
.maxIDs
[xxxFrame
] = \
1771 self
.maxIDs
[xxxMenuBar
] = self
.maxIDs
[xxxMenu
] = self
.maxIDs
[xxxToolBar
] = 0
1773 def Open(self
, path
):
1774 # Try to read the file
1779 dom
= minidom
.parse(path
)
1781 self
.dataFile
= path
1782 self
.SetTitle(progname
+ ': ' + os
.path
.basename(path
))
1784 wxLogError('Error reading file: %s' % path
)
1787 def Indent(self
, node
, indent
= 0):
1788 # Copy child list because it will change soon
1789 children
= node
.childNodes
[:]
1790 # Main node doesn't need to be indented
1792 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1793 node
.parentNode
.insertBefore(text
, node
)
1795 # Append newline after last child, except for text nodes
1796 if children
[-1].nodeType
== minidom
.Node
.ELEMENT_NODE
:
1797 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1798 node
.appendChild(text
)
1799 # Indent children which are elements
1801 if n
.nodeType
== minidom
.Node
.ELEMENT_NODE
:
1802 self
.Indent(n
, indent
+ 2)
1804 def Save(self
, path
):
1807 self
.OnRefresh(wxCommandEvent())
1809 # Make temporary copy
1810 # !!! We can't clone dom node, it works only once
1811 #self.domCopy = tree.dom.cloneNode(true)
1812 self
.domCopy
= minidom
.Document()
1813 mainNode
= self
.domCopy
.appendChild(tree
.mainNode
.cloneNode(true
))
1814 self
.Indent(mainNode
)
1815 self
.domCopy
.writexml(f
)
1817 self
.domCopy
.unlink()
1819 self
.modified
= false
1820 panel
.SetModified(false
)
1822 wxLogError('Error writing file: %s' % path
)
1826 if not (self
.modified
or panel
.IsModified()): return true
1827 flags
= wxICON_EXCLAMATION | wxYES_NO | wxCANCEL | wxCENTRE
1828 dlg
= wxMessageDialog( self
, 'File is modified. Save before exit?',
1829 'Save before too late?', flags
)
1830 say
= dlg
.ShowModal()
1833 self
.OnSaveOrSaveAs(wxCommandEvent(wxID_SAVE
))
1834 # If save was successful, modified flag is unset
1835 if not self
.modified
: return true
1836 elif say
== wxID_NO
:
1837 self
.modified
= false
1838 panel
.SetModified(false
)
1842 ################################################################################
1845 print >> sys
.stderr
, 'usage: xrced [-dvh] [file]'
1849 global debug
, verbose
1850 # Process comand-line
1852 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'dvh')
1853 except getopt
.GetoptError
:
1854 print >> sys
.stderr
, 'Unknown option'
1864 print 'XRCed version', version
1867 self
.SetAppName('xrced')
1870 conf
= wxConfig(style
= wxCONFIG_USE_LOCAL_FILE
)
1871 conf
.autoRefresh
= conf
.ReadInt('autorefresh', true
)
1872 pos
= conf
.ReadInt('x', -1), conf
.ReadInt('y', -1)
1873 size
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600)
1874 conf
.embedPanel
= conf
.ReadInt('embedPanel', true
)
1875 conf
.sashPos
= conf
.ReadInt('sashPos', 200)
1876 if not conf
.embedPanel
:
1877 conf
.panelX
= conf
.ReadInt('panelX', -1)
1878 conf
.panelY
= conf
.ReadInt('panelY', -1)
1880 conf
.panelX
= conf
.panelY
= -1
1881 conf
.panelWidth
= conf
.ReadInt('panelWidth', 200)
1882 conf
.panelHeight
= conf
.ReadInt('panelHeight', 200)
1883 conf
.panic
= not conf
.HasEntry('nopanic')
1885 wxFileSystem_AddHandler(wxMemoryFSHandler())
1886 wxInitAllImageHandlers()
1888 frame
= Frame(pos
, size
)
1890 # Load resources from XRC file (!!! should be transformed to .py later?)
1891 ##sys.modules['params'].frame = frame
1893 params
.frame
= frame
1894 frame
.res
= wxXmlResource('')
1895 frame
.res
.Load(os
.path
.join(sys
.path
[0], 'xrced.xrc'))
1897 # Load file after showing
1900 frame
.open = frame
.Open(args
[0])
1907 wc
= wxConfigBase_Get()
1908 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1909 wc
.WriteInt('x', conf
.x
)
1910 wc
.WriteInt('y', conf
.y
)
1911 wc
.WriteInt('width', conf
.width
)
1912 wc
.WriteInt('height', conf
.height
)
1913 wc
.WriteInt('embedPanel', conf
.embedPanel
)
1914 if not conf
.embedPanel
:
1915 wc
.WriteInt('panelX', conf
.panelX
)
1916 wc
.WriteInt('panelY', conf
.panelY
)
1917 wc
.WriteInt('sashPos', conf
.sashPos
)
1918 wc
.WriteInt('panelWidth', conf
.panelWidth
)
1919 wc
.WriteInt('panelHeight', conf
.panelHeight
)
1920 wc
.WriteInt('nopanic', 1)
1929 if __name__
== '__main__':