2 # Purpose: XRC editor, main module
3 # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
9 xrced -- Simple resource editor for XRC format used by wxWidgets/wxPython
14 xrced [ -h ] [ -v ] [ XRC-file ]
18 -h output short usage info and exit
20 -v output version info and exit
24 import os
, sys
, getopt
, re
, traceback
, tempfile
, shutil
, cPickle
25 from xml
.parsers
import expat
28 from tree
import * # imports xxx which imports params
31 from params
import genericStyles
32 # Cleanup recursive import sideeffects, otherwise we can't create undoMan
34 undo
.ParamPage
= ParamPage
35 undoMan
= g
.undoMan
= UndoManager()
37 # Set application path for loading resources
38 if __name__
== '__main__':
39 basePath
= os
.path
.dirname(sys
.argv
[0])
41 basePath
= os
.path
.dirname(__file__
)
43 # Remember system path
46 # 1 adds CMD command to Help menu
50 <HTML><H2>Welcome to XRC<font color="blue">ed</font></H2><H3><font color="green">DON'T PANIC :)</font></H3>
51 Read this note before clicking on anything!<P>
52 To start select tree root, then popup menu with your right mouse button,
53 select "Append Child", and then any command.<P>
54 Or just press one of the buttons on the tools palette.<P>
55 Enter XML ID, change properties, create children.<P>
56 To test your interface select Test command (View menu).<P>
57 Consult README.txt file for the details.</HTML>
60 defaultIDs
= {xxxPanel
:'PANEL', xxxDialog
:'DIALOG', xxxFrame
:'FRAME',
61 xxxMenuBar
:'MENUBAR', xxxMenu
:'MENU', xxxToolBar
:'TOOLBAR',
62 xxxWizard
:'WIZARD', xxxBitmap
:'BITMAP', xxxIcon
:'ICON'}
64 defaultName
= 'UNTITLED.xrc'
66 ################################################################################
68 # ScrolledMessageDialog - modified from wxPython lib to set fixed-width font
69 class ScrolledMessageDialog(wx
.Dialog
):
70 def __init__(self
, parent
, msg
, caption
, pos
= wx
.DefaultPosition
, size
= (500,300)):
71 from wx
.lib
.layoutf
import Layoutf
72 wx
.Dialog
.__init
__(self
, parent
, -1, caption
, pos
, size
)
73 text
= wx
.TextCtrl(self
, -1, msg
, wx
.DefaultPosition
,
74 wx
.DefaultSize
, wx
.TE_MULTILINE | wx
.TE_READONLY
)
75 text
.SetFont(g
.modernFont())
76 dc
= wx
.WindowDC(text
)
77 w
, h
= dc
.GetFullTextExtent(' ', g
.modernFont())[:2]
78 ok
= wx
.Button(self
, wx
.ID_OK
, "OK")
80 text
.SetConstraints(Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self
,ok
)))
81 text
.SetSize((w
* 80 + 30, h
* 40))
82 text
.ShowPosition(1) # scroll to the first line
83 ok
.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!35', (self
,)))
84 self
.SetAutoLayout(True)
86 self
.CenterOnScreen(wx
.BOTH
)
88 ################################################################################
90 # Event handler for using during location
91 class Locator(wx
.EvtHandler
):
92 def ProcessEvent(self
, evt
):
95 class Frame(wx
.Frame
):
96 def __init__(self
, pos
, size
):
97 wx
.Frame
.__init
__(self
, None, -1, '', pos
, size
)
99 frame
= g
.frame
= self
100 bar
= self
.CreateStatusBar(2)
101 bar
.SetStatusWidths([-1, 40])
102 self
.SetIcon(images
.getIconIcon())
107 # Load our own resources
108 self
.res
= xrc
.XmlResource('')
109 # !!! Blocking of assert failure occurring in older unicode builds
111 quietlog
= wx
.LogNull()
112 self
.res
.Load(os
.path
.join(basePath
, 'xrced.xrc'))
113 except wx
._core
.PyAssertionError
:
114 print 'PyAssertionError was ignored'
117 menuBar
= wx
.MenuBar()
120 menu
.Append(wx
.ID_NEW
, '&New\tCtrl-N', 'New file')
121 menu
.AppendSeparator()
122 menu
.Append(wx
.ID_OPEN
, '&Open...\tCtrl-O', 'Open XRC file')
123 self
.recentMenu
= wx
.Menu()
124 self
.AppendRecent(self
.recentMenu
)
125 menu
.AppendMenu(-1, 'Open Recent', self
.recentMenu
, 'Open a recent file')
126 menu
.AppendSeparator()
127 menu
.Append(wx
.ID_SAVE
, '&Save\tCtrl-S', 'Save XRC file')
128 menu
.Append(wx
.ID_SAVEAS
, 'Save &As...', 'Save XRC file under different name')
129 self
.ID_GENERATE_PYTHON
= wx
.NewId()
130 menu
.Append(self
.ID_GENERATE_PYTHON
, '&Generate Python...',
131 'Generate a Python module that uses this XRC')
132 menu
.AppendSeparator()
133 self
.ID_PREFS
= wx
.NewId()
134 menu
.Append(self
.ID_PREFS
, 'Preferences...', 'Change XRCed settings')
135 menu
.AppendSeparator()
136 menu
.Append(wx
.ID_EXIT
, '&Quit\tCtrl-Q', 'Exit application')
138 menuBar
.Append(menu
, '&File')
141 menu
.Append(wx
.ID_UNDO
, '&Undo\tCtrl-Z', 'Undo')
142 menu
.Append(wx
.ID_REDO
, '&Redo\tCtrl-Y', 'Redo')
143 menu
.AppendSeparator()
144 menu
.Append(wx
.ID_CUT
, 'Cut\tCtrl-X', 'Cut to the clipboard')
145 menu
.Append(wx
.ID_COPY
, '&Copy\tCtrl-C', 'Copy to the clipboard')
146 menu
.Append(wx
.ID_PASTE
, '&Paste\tCtrl-V', 'Paste from the clipboard')
147 self
.ID_DELETE
= wx
.NewId()
148 menu
.Append(self
.ID_DELETE
, '&Delete\tCtrl-D', 'Delete object')
149 menu
.AppendSeparator()
150 self
.ID_LOCATE
= wx
.NewId()
151 self
.ID_TOOL_LOCATE
= wx
.NewId()
152 self
.ID_TOOL_PASTE
= wx
.NewId()
153 menu
.Append(self
.ID_LOCATE
, '&Locate\tCtrl-L', 'Locate control in test window and select it')
154 menuBar
.Append(menu
, '&Edit')
157 self
.ID_EMBED_PANEL
= wx
.NewId()
158 menu
.Append(self
.ID_EMBED_PANEL
, '&Embed Panel',
159 'Toggle embedding properties panel in the main window', True)
160 menu
.Check(self
.ID_EMBED_PANEL
, conf
.embedPanel
)
161 self
.ID_SHOW_TOOLS
= wx
.NewId()
162 menu
.Append(self
.ID_SHOW_TOOLS
, 'Show &Tools', 'Toggle tools', True)
163 menu
.Check(self
.ID_SHOW_TOOLS
, conf
.showTools
)
164 menu
.AppendSeparator()
165 self
.ID_TEST
= wx
.NewId()
166 menu
.Append(self
.ID_TEST
, '&Test\tF5', 'Show test window')
167 self
.ID_REFRESH
= wx
.NewId()
168 menu
.Append(self
.ID_REFRESH
, '&Refresh\tCtrl-R', 'Refresh test window')
169 self
.ID_AUTO_REFRESH
= wx
.NewId()
170 menu
.Append(self
.ID_AUTO_REFRESH
, '&Auto-refresh\tAlt-A',
171 'Toggle auto-refresh mode', True)
172 menu
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
173 self
.ID_TEST_HIDE
= wx
.NewId()
174 menu
.Append(self
.ID_TEST_HIDE
, '&Hide\tF6', 'Close test window')
175 menuBar
.Append(menu
, '&View')
178 self
.ID_MOVEUP
= wx
.NewId()
179 menu
.Append(self
.ID_MOVEUP
, '&Up', 'Move before previous sibling')
180 self
.ID_MOVEDOWN
= wx
.NewId()
181 menu
.Append(self
.ID_MOVEDOWN
, '&Down', 'Move after next sibling')
182 self
.ID_MOVELEFT
= wx
.NewId()
183 menu
.Append(self
.ID_MOVELEFT
, '&Make sibling', 'Make sibling of parent')
184 self
.ID_MOVERIGHT
= wx
.NewId()
185 menu
.Append(self
.ID_MOVERIGHT
, '&Make child', 'Make child of previous sibling')
186 menuBar
.Append(menu
, '&Move')
189 menu
.Append(wx
.ID_ABOUT
, '&About...', 'About XCRed')
190 self
.ID_README
= wx
.NewId()
191 menu
.Append(self
.ID_README
, '&Readme...\tF1', 'View the README file')
193 self
.ID_DEBUG_CMD
= wx
.NewId()
194 menu
.Append(self
.ID_DEBUG_CMD
, 'CMD', 'Python command line')
195 wx
.EVT_MENU(self
, self
.ID_DEBUG_CMD
, self
.OnDebugCMD
)
196 menuBar
.Append(menu
, '&Help')
198 self
.menuBar
= menuBar
199 self
.SetMenuBar(menuBar
)
202 tb
= self
.CreateToolBar(wx
.TB_HORIZONTAL | wx
.NO_BORDER | wx
.TB_FLAT
)
203 tb
.SetToolBitmapSize((24,24))
204 new_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_NORMAL_FILE
, wx
.ART_TOOLBAR
)
205 open_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_OPEN
, wx
.ART_TOOLBAR
)
206 save_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_SAVE
, wx
.ART_TOOLBAR
)
207 undo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_UNDO
, wx
.ART_TOOLBAR
)
208 redo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_REDO
, wx
.ART_TOOLBAR
)
209 cut_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_CUT
, wx
.ART_TOOLBAR
)
210 copy_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_COPY
, wx
.ART_TOOLBAR
)
211 paste_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_PASTE
, wx
.ART_TOOLBAR
)
213 tb
.AddSimpleTool(wx
.ID_NEW
, new_bmp
, 'New', 'New file')
214 tb
.AddSimpleTool(wx
.ID_OPEN
, open_bmp
, 'Open', 'Open file')
215 tb
.AddSimpleTool(wx
.ID_SAVE
, save_bmp
, 'Save', 'Save file')
216 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
217 tb
.AddSimpleTool(wx
.ID_UNDO
, undo_bmp
, 'Undo', 'Undo')
218 tb
.AddSimpleTool(wx
.ID_REDO
, redo_bmp
, 'Redo', 'Redo')
219 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
220 tb
.AddSimpleTool(wx
.ID_CUT
, cut_bmp
, 'Cut', 'Cut')
221 tb
.AddSimpleTool(wx
.ID_COPY
, copy_bmp
, 'Copy', 'Copy')
222 tb
.AddSimpleTool(self
.ID_TOOL_PASTE
, paste_bmp
, 'Paste', 'Paste')
223 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
224 tb
.AddSimpleTool(self
.ID_TOOL_LOCATE
,
225 images
.getLocateBitmap(), #images.getLocateArmedBitmap(),
226 'Locate', 'Locate control in test window and select it', True)
227 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
228 tb
.AddSimpleTool(self
.ID_TEST
, images
.getTestBitmap(), 'Test', 'Test window')
229 tb
.AddSimpleTool(self
.ID_REFRESH
, images
.getRefreshBitmap(),
230 'Refresh', 'Refresh view')
231 tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, images
.getAutoRefreshBitmap(),
232 'Auto-refresh', 'Toggle auto-refresh mode', True)
233 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
234 tb
.AddSimpleTool(self
.ID_MOVEUP
, images
.getToolMoveUpBitmap(),
235 'Up', 'Move before previous sibling')
236 tb
.AddSimpleTool(self
.ID_MOVEDOWN
, images
.getToolMoveDownBitmap(),
237 'Down', 'Move after next sibling')
238 tb
.AddSimpleTool(self
.ID_MOVELEFT
, images
.getToolMoveLeftBitmap(),
239 'Make Sibling', 'Make sibling of parent')
240 tb
.AddSimpleTool(self
.ID_MOVERIGHT
, images
.getToolMoveRightBitmap(),
241 'Make Child', 'Make child of previous sibling')
242 # if wx.Platform == '__WXGTK__':
243 # tb.AddSeparator() # otherwise auto-refresh sticks in status line
244 tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
248 self
.minWidth
= tb
.GetSize()[0] # minimal width is the size of toolbar
251 wx
.EVT_MENU(self
, wx
.ID_NEW
, self
.OnNew
)
252 wx
.EVT_MENU(self
, wx
.ID_OPEN
, self
.OnOpen
)
253 wx
.EVT_MENU(self
, wx
.ID_SAVE
, self
.OnSaveOrSaveAs
)
254 wx
.EVT_MENU(self
, wx
.ID_SAVEAS
, self
.OnSaveOrSaveAs
)
255 wx
.EVT_MENU(self
, self
.ID_GENERATE_PYTHON
, self
.OnGeneratePython
)
256 wx
.EVT_MENU(self
, self
.ID_PREFS
, self
.OnPrefs
)
257 wx
.EVT_MENU(self
, wx
.ID_EXIT
, self
.OnExit
)
259 wx
.EVT_MENU(self
, wx
.ID_UNDO
, self
.OnUndo
)
260 wx
.EVT_MENU(self
, wx
.ID_REDO
, self
.OnRedo
)
261 wx
.EVT_MENU(self
, wx
.ID_CUT
, self
.OnCutDelete
)
262 wx
.EVT_MENU(self
, wx
.ID_COPY
, self
.OnCopy
)
263 wx
.EVT_MENU(self
, wx
.ID_PASTE
, self
.OnPaste
)
264 wx
.EVT_MENU(self
, self
.ID_TOOL_PASTE
, self
.OnPaste
)
265 wx
.EVT_MENU(self
, self
.ID_DELETE
, self
.OnCutDelete
)
266 wx
.EVT_MENU(self
, self
.ID_LOCATE
, self
.OnLocate
)
267 wx
.EVT_MENU(self
, self
.ID_TOOL_LOCATE
, self
.OnLocate
)
269 wx
.EVT_MENU(self
, self
.ID_EMBED_PANEL
, self
.OnEmbedPanel
)
270 wx
.EVT_MENU(self
, self
.ID_SHOW_TOOLS
, self
.OnShowTools
)
271 wx
.EVT_MENU(self
, self
.ID_TEST
, self
.OnTest
)
272 wx
.EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
)
273 wx
.EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
)
274 wx
.EVT_MENU(self
, self
.ID_TEST_HIDE
, self
.OnTestHide
)
276 wx
.EVT_MENU(self
, self
.ID_MOVEUP
, self
.OnMoveUp
)
277 wx
.EVT_MENU(self
, self
.ID_MOVEDOWN
, self
.OnMoveDown
)
278 wx
.EVT_MENU(self
, self
.ID_MOVELEFT
, self
.OnMoveLeft
)
279 wx
.EVT_MENU(self
, self
.ID_MOVERIGHT
, self
.OnMoveRight
)
281 wx
.EVT_MENU(self
, wx
.ID_ABOUT
, self
.OnAbout
)
282 wx
.EVT_MENU(self
, self
.ID_README
, self
.OnReadme
)
285 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVE
, self
.OnUpdateUI
)
286 wx
.EVT_UPDATE_UI(self
, wx
.ID_CUT
, self
.OnUpdateUI
)
287 wx
.EVT_UPDATE_UI(self
, wx
.ID_COPY
, self
.OnUpdateUI
)
288 wx
.EVT_UPDATE_UI(self
, wx
.ID_PASTE
, self
.OnUpdateUI
)
289 wx
.EVT_UPDATE_UI(self
, self
.ID_LOCATE
, self
.OnUpdateUI
)
290 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_LOCATE
, self
.OnUpdateUI
)
291 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_PASTE
, self
.OnUpdateUI
)
292 wx
.EVT_UPDATE_UI(self
, wx
.ID_UNDO
, self
.OnUpdateUI
)
293 wx
.EVT_UPDATE_UI(self
, wx
.ID_REDO
, self
.OnUpdateUI
)
294 wx
.EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
)
295 wx
.EVT_UPDATE_UI(self
, self
.ID_TEST
, self
.OnUpdateUI
)
296 wx
.EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
)
299 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
300 sizer
.Add(wx
.StaticLine(self
, -1), 0, wx
.EXPAND
)
301 # Horizontal sizer for toolbar and splitter
302 self
.toolsSizer
= sizer1
= wx
.BoxSizer()
303 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.SP_3DSASH
)
304 self
.splitter
= splitter
305 splitter
.SetMinimumPaneSize(100)
308 g
.tree
= tree
= XML_Tree(splitter
, -1)
310 # Init pull-down menu data
312 g
.pullDownMenu
= pullDownMenu
= PullDownMenu(self
)
314 # Vertical toolbar for GUI buttons
315 g
.tools
= tools
= Tools(self
)
316 tools
.Show(conf
.showTools
)
317 if conf
.showTools
: sizer1
.Add(tools
, 0, wx
.EXPAND
)
319 tree
.RegisterKeyEvents()
321 # Miniframe for split mode
322 miniFrame
= wx
.MiniFrame(self
, -1, 'Properties & Style',
323 (conf
.panelX
, conf
.panelY
),
324 (conf
.panelWidth
, conf
.panelHeight
))
325 self
.miniFrame
= miniFrame
326 sizer2
= wx
.BoxSizer()
327 miniFrame
.SetAutoLayout(True)
328 miniFrame
.SetSizer(sizer2
)
329 wx
.EVT_CLOSE(self
.miniFrame
, self
.OnCloseMiniFrame
)
330 # Create panel for parameters
333 panel
= Panel(splitter
)
334 # Set plitter windows
335 splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
337 panel
= Panel(miniFrame
)
338 sizer2
.Add(panel
, 1, wx
.EXPAND
)
340 splitter
.Initialize(tree
)
341 sizer1
.Add(splitter
, 1, wx
.EXPAND
)
342 sizer
.Add(sizer1
, 1, wx
.EXPAND
)
343 self
.SetAutoLayout(True)
347 wx
.EVT_IDLE(self
, self
.OnIdle
)
348 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
349 wx
.EVT_KEY_DOWN(self
, tools
.OnKeyDown
)
350 wx
.EVT_KEY_UP(self
, tools
.OnKeyUp
)
351 wx
.EVT_ICONIZE(self
, self
.OnIconize
)
353 def AppendRecent(self
, menu
):
354 # add recently used files to the menu
355 for id,name
in conf
.recentfiles
.iteritems():
357 wx
.EVT_MENU(self
,id,self
.OnRecentFile
)
360 def OnRecentFile(self
,evt
):
361 # open recently used file
362 if not self
.AskSave(): return
365 path
=conf
.recentfiles
[evt
.GetId()]
367 self
.SetStatusText('Data loaded')
369 self
.SetStatusText('Failed')
371 self
.SetStatusText('No such file')
374 def OnNew(self
, evt
):
375 if not self
.AskSave(): return
378 def OnOpen(self
, evt
):
379 if not self
.AskSave(): return
380 dlg
= wx
.FileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
381 '', '*.xrc', wx
.OPEN | wx
.CHANGE_DIR
)
382 if dlg
.ShowModal() == wx
.ID_OK
:
384 self
.SetStatusText('Loading...')
388 self
.SetStatusText('Data loaded')
390 self
.SetStatusText('Failed')
391 self
.SaveRecent(path
)
396 def OnSaveOrSaveAs(self
, evt
):
397 if evt
.GetId() == wx
.ID_SAVEAS
or not self
.dataFile
:
398 if self
.dataFile
: name
= ''
399 else: name
= defaultName
400 dirname
= os
.path
.abspath(os
.path
.dirname(self
.dataFile
))
401 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.xrc',
402 wx
.SAVE | wx
.OVERWRITE_PROMPT | wx
.CHANGE_DIR
)
403 if dlg
.ShowModal() == wx
.ID_OK
:
405 if isinstance(path
, unicode):
406 path
= path
.encode(sys
.getfilesystemencoding())
413 # if we already have a localconf then it needs to be
414 # copied to a new config with the new name
416 nc
= self
.CreateLocalConf(path
)
417 flag
, key
, idx
= lc
.GetFirstEntry()
419 nc
.Write(key
, lc
.Read(key
))
420 flag
, key
, idx
= lc
.GetNextEntry(idx
)
423 # otherwise create a new one
424 conf
.localconf
= self
.CreateLocalConf(path
)
427 self
.SetStatusText('Saving...')
431 tmpFile
,tmpName
= tempfile
.mkstemp(prefix
='xrced-')
433 self
.Save(tmpName
) # save temporary file first
434 shutil
.move(tmpName
, path
)
436 if conf
.localconf
.ReadBool("autogenerate", False):
437 pypath
= conf
.localconf
.Read("filename")
438 embed
= conf
.localconf
.ReadBool("embedResource", False)
439 genGettext
= conf
.localconf
.ReadBool("genGettext", False)
440 self
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
442 self
.SetStatusText('Data saved')
443 self
.SaveRecent(path
)
445 self
.SetStatusText('Failed')
449 def SaveRecent(self
,path
):
450 # append to recently used files
451 if path
not in conf
.recentfiles
.values():
453 self
.recentMenu
.Append(newid
, path
)
454 wx
.EVT_MENU(self
, newid
, self
.OnRecentFile
)
455 conf
.recentfiles
[newid
] = path
457 def GeneratePython(self
, dataFile
, pypath
, embed
, genGettext
):
459 import wx
.tools
.pywxrc
460 rescomp
= wx
.tools
.pywxrc
.XmlResourceCompiler()
461 rescomp
.MakePythonModule([dataFile
], pypath
, embed
, genGettext
)
464 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
465 wx
.LogError('Error generating python code : %s' % pypath
)
469 def OnGeneratePython(self
, evt
):
470 if self
.modified
or not conf
.localconf
:
471 wx
.MessageBox("Save the XRC file first!", "Error")
474 dlg
= PythonOptions(self
, conf
.localconf
, self
.dataFile
)
478 def OnPrefs(self
, evt
):
479 dlg
= PrefsDialog(self
)
480 if dlg
.ShowModal() == wx
.ID_OK
:
481 # Fetch new preferences
482 for id,cdp
in dlg
.checkControls
.items():
484 if dlg
.FindWindowById(id).IsChecked():
485 d
[p
] = str(c
.GetValue())
486 elif p
in d
: del d
[p
]
487 g
.conf
.allowExec
= ('ask', 'yes', 'no')[dlg
.radio_allow_exec
.GetSelection()]
490 def OnExit(self
, evt
):
493 def OnUndo(self
, evt
):
494 # Extra check to not mess with idle updating
495 if undoMan
.CanUndo():
497 g
.panel
.SetModified(False)
498 if not undoMan
.CanUndo():
499 self
.SetModified(False)
501 def OnRedo(self
, evt
):
502 if undoMan
.CanRedo():
504 self
.SetModified(True)
506 def OnCopy(self
, evt
):
507 selected
= tree
.selection
508 if not selected
: return # key pressed event
509 xxx
= tree
.GetPyData(selected
)
510 if wx
.TheClipboard
.Open():
512 data
= wx
.CustomDataObject('XRCED')
513 # Set encoding in header
515 s
= xxx
.node
.toxml(encoding
=expat
.native_encoding
)
517 data
= wx
.CustomDataObject('XRCED_node')
519 data
.SetData(cPickle
.dumps(s
))
520 wx
.TheClipboard
.SetData(data
)
521 wx
.TheClipboard
.Close()
522 self
.SetStatusText('Copied')
524 wx
.MessageBox("Unable to open the clipboard", "Error")
526 def OnPaste(self
, evt
):
527 selected
= tree
.selection
528 if not selected
: return # key pressed event
529 # For pasting with Ctrl pressed
531 if evt
.GetId() == pullDownMenu
.ID_PASTE_SIBLING
: appendChild
= False
532 elif evt
.GetId() == self
.ID_TOOL_PASTE
:
533 if g
.tree
.ctrl
: appendChild
= False
534 else: appendChild
= not tree
.NeedInsert(selected
)
535 else: appendChild
= not tree
.NeedInsert(selected
)
536 xxx
= tree
.GetPyData(selected
)
538 # If has next item, insert, else append to parent
539 nextItem
= tree
.GetNextSibling(selected
)
540 parentLeaf
= tree
.GetItemParent(selected
)
541 # Expanded container (must have children)
542 elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, False):
543 # Insert as first child
544 nextItem
= tree
.GetFirstChild(selected
)[0]
545 parentLeaf
= selected
547 # No children or unexpanded item - appendChild stays True
548 nextItem
= wx
.TreeItemId() # no next item
549 parentLeaf
= selected
550 parent
= tree
.GetPyData(parentLeaf
).treeObject()
552 # Create a copy of clipboard pickled element
553 success
= success_node
= False
554 if wx
.TheClipboard
.Open():
556 data
= wx
.CustomDataObject('XRCED')
557 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
559 success
= wx
.TheClipboard
.GetData(data
)
561 # there is a problem if XRCED_node is in clipboard
562 # but previous SetData was for XRCED
564 if not success
: # try other format
565 data
= wx
.CustomDataObject('XRCED_node')
566 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
567 success_node
= wx
.TheClipboard
.GetData(data
)
569 wx
.TheClipboard
.Close()
571 if not success
and not success_node
:
573 "There is no data in the clipboard in the required format",
577 xml
= cPickle
.loads(data
.GetData()) # xml representation of element
579 elem
= minidom
.parseString(xml
).childNodes
[0]
581 elem
= g
.tree
.dom
.createComment(xml
)
583 # Tempopary xxx object to test things
584 xxx
= MakeXXXFromDOM(parent
, elem
)
586 # Check compatibility
587 if not self
.ItemsAreCompatible(parent
, xxx
.treeObject()): return
589 # Check parent and child relationships.
590 # If parent is sizer or notebook, child is of wrong class or
591 # parent is normal window, child is child container then detach child.
592 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
593 parentIsBook
= parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]
594 if isChildContainer
and \
595 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
596 (parentIsBook
and not isinstance(xxx
, xxxPage
)) or \
597 not (parent
.isSizer
or parentIsBook
)):
598 elem
.removeChild(xxx
.child
.node
) # detach child
599 elem
.unlink() # delete child container
600 elem
= xxx
.child
.node
# replace
601 # This may help garbage collection
602 xxx
.child
.parent
= None
603 isChildContainer
= False
604 # Parent is sizer or notebook, child is not child container
605 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
606 # Create sizer item element
607 sizerItemElem
= MakeEmptyDOM(parent
.itemTag
)
608 sizerItemElem
.appendChild(elem
)
610 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
611 pageElem
= MakeEmptyDOM('notebookpage')
612 pageElem
.appendChild(elem
)
614 elif isinstance(parent
, xxxChoicebook
) and not isChildContainer
:
615 pageElem
= MakeEmptyDOM('choicebookpage')
616 pageElem
.appendChild(elem
)
618 elif isinstance(parent
, xxxListbook
) and not isChildContainer
:
619 pageElem
= MakeEmptyDOM('listbookpage')
620 pageElem
.appendChild(elem
)
622 # Insert new node, register undo
623 newItem
= tree
.InsertNode(parentLeaf
, parent
, elem
, nextItem
)
624 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
625 # Scroll to show new item (!!! redundant?)
626 tree
.EnsureVisible(newItem
)
627 tree
.SelectItem(newItem
)
628 if not tree
.IsVisible(newItem
):
629 tree
.ScrollTo(newItem
)
632 if g
.testWin
and tree
.IsHighlatable(newItem
):
634 tree
.needUpdate
= True
635 tree
.pendingHighLight
= newItem
637 tree
.pendingHighLight
= None
639 self
.SetStatusText('Pasted')
642 def ItemsAreCompatible(self
, parent
, child
):
643 # Check compatibility
645 # Comments are always compatible
646 if child
.__class
__ == xxxComment
:
649 if child
.__class
__ in [xxxDialog
, xxxFrame
, xxxWizard
]:
651 if parent
.__class
__ != xxxMainNode
: error
= True
652 elif child
.__class
__ == xxxMenuBar
:
653 # Menubar can be put in frame or dialog
654 if parent
.__class
__ not in [xxxMainNode
, xxxFrame
, xxxDialog
]: error
= True
655 elif child
.__class
__ == xxxToolBar
:
656 # Toolbar can be top-level of child of panel or frame
657 if parent
.__class
__ not in [xxxMainNode
, xxxPanel
, xxxFrame
] and \
658 not parent
.isSizer
: error
= True
659 elif child
.__class
__ == xxxPanel
and parent
.__class
__ == xxxMainNode
:
661 elif child
.__class
__ == xxxSpacer
:
662 if not parent
.isSizer
: error
= True
663 elif child
.__class
__ == xxxSeparator
:
664 if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error
= True
665 elif child
.__class
__ == xxxTool
:
666 if parent
.__class
__ != xxxToolBar
: error
= True
667 elif child
.__class
__ == xxxMenu
:
668 if not parent
.__class
__ in [xxxMainNode
, xxxMenuBar
, xxxMenu
]: error
= True
669 elif child
.__class
__ == xxxMenuItem
:
670 if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
671 elif child
.isSizer
and parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]:
673 else: # normal controls can be almost anywhere
674 if parent
.__class
__ == xxxMainNode
or \
675 parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
677 if parent
.__class
__ == xxxMainNode
: parentClass
= 'root'
678 else: parentClass
= parent
.className
679 wx
.LogError('Incompatible parent/child: parent is %s, child is %s!' %
680 (parentClass
, child
.className
))
684 def OnMoveUp(self
, evt
):
685 selected
= tree
.selection
686 if not selected
: return
688 index
= tree
.ItemIndex(selected
)
689 if index
== 0: return # No previous sibling found
692 self
.lastOp
= 'MOVEUP'
693 status
= 'Moved before previous sibling'
698 parent
= tree
.GetItemParent(selected
)
699 elem
= tree
.RemoveLeaf(selected
)
700 nextItem
= tree
.GetFirstChild(parent
)[0]
701 for i
in range(index
- 1): nextItem
= tree
.GetNextSibling(nextItem
)
702 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
703 newIndex
= tree
.ItemIndex(selected
)
704 tree
.SelectItem(selected
)
706 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
709 self
.SetStatusText(status
)
713 def OnMoveDown(self
, evt
):
714 selected
= tree
.selection
715 if not selected
: return
717 index
= tree
.ItemIndex(selected
)
718 next
= tree
.GetNextSibling(selected
)
722 self
.lastOp
= 'MOVEDOWN'
723 status
= 'Moved after next sibling'
728 parent
= tree
.GetItemParent(selected
)
729 elem
= tree
.RemoveLeaf(selected
)
730 nextItem
= tree
.GetFirstChild(parent
)[0]
731 for i
in range(index
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
732 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
733 newIndex
= tree
.ItemIndex(selected
)
734 tree
.SelectItem(selected
)
736 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
739 self
.SetStatusText(status
)
743 def OnMoveLeft(self
, evt
):
744 selected
= tree
.selection
745 if not selected
: return
747 oldParent
= tree
.GetItemParent(selected
)
748 if not oldParent
: return
749 pparent
= tree
.GetItemParent(oldParent
)
750 if not pparent
: return
752 # Check compatibility
753 if not self
.ItemsAreCompatible(tree
.GetPyData(pparent
).treeObject(), tree
.GetPyData(selected
).treeObject()): return
756 self
.lastOp
= 'MOVELEFT'
757 status
= 'Made next sibling of parent'
759 oldIndex
= tree
.ItemIndex(selected
)
760 elem
= tree
.RemoveLeaf(selected
)
761 nextItem
= tree
.GetFirstChild(pparent
)[0]
762 parentIndex
= tree
.ItemIndex(oldParent
)
763 for i
in range(parentIndex
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
765 # Check parent and child relationships.
766 # If parent is sizer or notebook, child is of wrong class or
767 # parent is normal window, child is child container then detach child.
768 parent
= tree
.GetPyData(pparent
).treeObject()
769 xxx
= MakeXXXFromDOM(parent
, elem
)
770 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
771 if isChildContainer
and \
772 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
773 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
774 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
775 elem
.removeChild(xxx
.child
.node
) # detach child
776 elem
.unlink() # delete child container
777 elem
= xxx
.child
.node
# replace
778 # This may help garbage collection
779 xxx
.child
.parent
= None
780 isChildContainer
= False
781 # Parent is sizer or notebook, child is not child container
782 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
783 # Create sizer item element
784 sizerItemElem
= MakeEmptyDOM('sizeritem')
785 sizerItemElem
.appendChild(elem
)
787 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
788 pageElem
= MakeEmptyDOM('notebookpage')
789 pageElem
.appendChild(elem
)
792 selected
= tree
.InsertNode(pparent
, tree
.GetPyData(pparent
).treeObject(), elem
, nextItem
)
793 newIndex
= tree
.ItemIndex(selected
)
794 tree
.SelectItem(selected
)
796 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, pparent
, newIndex
))
799 self
.SetStatusText(status
)
801 def OnMoveRight(self
, evt
):
802 selected
= tree
.selection
803 if not selected
: return
805 oldParent
= tree
.GetItemParent(selected
)
806 if not oldParent
: return
808 newParent
= tree
.GetPrevSibling(selected
)
809 if not newParent
: return
811 parent
= tree
.GetPyData(newParent
).treeObject()
813 # Check compatibility
814 if not self
.ItemsAreCompatible(parent
, tree
.GetPyData(selected
).treeObject()): return
817 self
.lastOp
= 'MOVERIGHT'
818 status
= 'Made last child of previous sibling'
820 oldIndex
= tree
.ItemIndex(selected
)
821 elem
= tree
.RemoveLeaf(selected
)
823 # Check parent and child relationships.
824 # If parent is sizer or notebook, child is of wrong class or
825 # parent is normal window, child is child container then detach child.
826 xxx
= MakeXXXFromDOM(parent
, elem
)
827 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
828 if isChildContainer
and \
829 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
830 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
831 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
832 elem
.removeChild(xxx
.child
.node
) # detach child
833 elem
.unlink() # delete child container
834 elem
= xxx
.child
.node
# replace
835 # This may help garbage collection
836 xxx
.child
.parent
= None
837 isChildContainer
= False
838 # Parent is sizer or notebook, child is not child container
839 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
840 # Create sizer item element
841 sizerItemElem
= MakeEmptyDOM('sizeritem')
842 sizerItemElem
.appendChild(elem
)
844 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
845 pageElem
= MakeEmptyDOM('notebookpage')
846 pageElem
.appendChild(elem
)
849 selected
= tree
.InsertNode(newParent
, tree
.GetPyData(newParent
).treeObject(), elem
, wx
.TreeItemId())
851 newIndex
= tree
.ItemIndex(selected
)
852 tree
.SelectItem(selected
)
854 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, newParent
, newIndex
))
857 self
.SetStatusText(status
)
860 def OnCutDelete(self
, evt
):
861 selected
= tree
.selection
862 if not selected
: return # key pressed event
864 if evt
.GetId() == wx
.ID_CUT
:
866 status
= 'Removed to clipboard'
868 self
.lastOp
= 'DELETE'
872 # If deleting top-level item, delete testWin
873 if selected
== g
.testWin
.item
:
877 # Remove highlight, update testWin
878 if g
.testWin
.highLight
:
879 g
.testWin
.highLight
.Remove()
880 tree
.needUpdate
= True
883 index
= tree
.ItemFullIndex(selected
)
884 xxx
= tree
.GetPyData(selected
)
885 parent
= tree
.GetPyData(tree
.GetItemParent(selected
)).treeObject()
886 elem
= tree
.RemoveLeaf(selected
)
887 undoMan
.RegisterUndo(UndoCutDelete(index
, parent
, elem
))
888 if evt
.GetId() == wx
.ID_CUT
:
889 if wx
.TheClipboard
.Open():
891 data
= wx
.CustomDataObject('XRCED')
893 s
= elem
.toxml(encoding
=expat
.native_encoding
)
895 data
= wx
.CustomDataObject('XRCED_node')
897 data
.SetData(cPickle
.dumps(s
))
898 wx
.TheClipboard
.SetData(data
)
899 wx
.TheClipboard
.Close()
901 wx
.MessageBox("Unable to open the clipboard", "Error")
902 tree
.pendingHighLight
= None
904 tree
.selection
= None
909 self
.SetStatusText(status
)
911 def OnSubclass(self
, evt
):
912 selected
= tree
.selection
913 xxx
= tree
.GetPyData(selected
).treeObject()
915 subclass
= xxx
.subclass
916 dlg
= wx
.TextEntryDialog(self
, 'Subclass:', defaultValue
=subclass
)
917 if dlg
.ShowModal() == wx
.ID_OK
:
918 subclass
= dlg
.GetValue()
920 elem
.setAttribute('subclass', subclass
)
921 elif elem
.hasAttribute('subclass'):
922 elem
.removeAttribute('subclass')
924 xxx
.subclass
= elem
.getAttribute('subclass')
925 tree
.SetItemText(selected
, xxx
.treeName())
926 panel
.pages
[0].box
.SetLabel(xxx
.panelName())
929 def OnEmbedPanel(self
, evt
):
930 conf
.embedPanel
= evt
.IsChecked()
932 # Remember last dimentions
933 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
934 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
935 size
= self
.GetSize()
936 pos
= self
.GetPosition()
937 sizePanel
= panel
.GetSize()
938 panel
.Reparent(self
.splitter
)
939 self
.miniFrame
.GetSizer().Remove(panel
)
941 self
.SetDimensions(pos
.x
, pos
.y
, size
.width
+ sizePanel
.width
, size
.height
)
942 self
.splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
943 self
.miniFrame
.Show(False)
945 conf
.sashPos
= self
.splitter
.GetSashPosition()
946 pos
= self
.GetPosition()
947 size
= self
.GetSize()
948 sizePanel
= panel
.GetSize()
949 self
.splitter
.Unsplit(panel
)
950 sizer
= self
.miniFrame
.GetSizer()
951 panel
.Reparent(self
.miniFrame
)
953 sizer
.Add(panel
, 1, wx
.EXPAND
)
954 self
.miniFrame
.Show(True)
955 self
.miniFrame
.SetDimensions(conf
.panelX
, conf
.panelY
,
956 conf
.panelWidth
, conf
.panelHeight
)
957 self
.miniFrame
.Layout()
959 self
.SetDimensions(pos
.x
, pos
.y
,
960 max(size
.width
- sizePanel
.width
, self
.minWidth
), size
.height
)
962 def OnShowTools(self
, evt
):
963 conf
.showTools
= evt
.IsChecked()
964 g
.tools
.Show(conf
.showTools
)
966 self
.toolsSizer
.Prepend(g
.tools
, 0, wx
.EXPAND
)
968 self
.toolsSizer
.Remove(g
.tools
)
969 self
.toolsSizer
.Layout()
971 def OnTest(self
, evt
):
972 if not tree
.selection
: return # key pressed event
973 tree
.ShowTestWindow(tree
.selection
)
975 def OnTestHide(self
, evt
):
976 tree
.CloseTestWindow()
978 # Find object by relative position
979 def FindObject(self
, item
, obj
):
980 # We simply perform depth-first traversal, sinse it's too much
981 # hassle to deal with all sizer/window combinations
982 w
= tree
.FindNodeObject(item
)
983 if w
== obj
or isinstance(w
, wx
.GBSizerItem
) and w
.GetWindow() == obj
:
985 if tree
.ItemHasChildren(item
):
986 child
= tree
.GetFirstChild(item
)[0]
988 found
= self
.FindObject(child
, obj
)
989 if found
: return found
990 child
= tree
.GetNextSibling(child
)
993 def OnTestWinLeftDown(self
, evt
):
994 pos
= evt
.GetPosition()
995 self
.SetHandler(g
.testWin
)
996 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
997 item
= self
.FindObject(g
.testWin
.item
, evt
.GetEventObject())
999 tree
.EnsureVisible(item
)
1000 tree
.SelectItem(item
)
1001 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, False)
1003 self
.SetStatusText('Selected %s' % tree
.GetItemText(item
))
1005 self
.SetStatusText('Locate failed!')
1007 def SetHandler(self
, w
, h
=None):
1009 w
.SetEventHandler(h
)
1010 w
.SetCursor(wx
.CROSS_CURSOR
)
1012 w
.SetEventHandler(w
)
1013 w
.SetCursor(wx
.NullCursor
)
1014 for ch
in w
.GetChildren():
1015 self
.SetHandler(ch
, h
)
1017 def OnLocate(self
, evt
):
1019 if evt
.GetId() == self
.ID_LOCATE
or \
1020 evt
.GetId() == self
.ID_TOOL_LOCATE
and evt
.IsChecked():
1021 self
.SetHandler(g
.testWin
, g
.testWin
)
1022 g
.testWin
.Connect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
, self
.OnTestWinLeftDown
)
1023 if evt
.GetId() == self
.ID_LOCATE
:
1024 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, True)
1025 elif evt
.GetId() == self
.ID_TOOL_LOCATE
and not evt
.IsChecked():
1026 self
.SetHandler(g
.testWin
, None)
1027 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1028 self
.SetStatusText('Click somewhere in your test window now')
1030 def OnRefresh(self
, evt
):
1031 # If modified, apply first
1032 selection
= tree
.selection
1034 xxx
= tree
.GetPyData(selection
)
1035 if xxx
and panel
.IsModified():
1036 tree
.Apply(xxx
, selection
)
1039 tree
.CreateTestWin(g
.testWin
.item
)
1040 panel
.modified
= False
1041 tree
.needUpdate
= False
1043 def OnAutoRefresh(self
, evt
):
1044 conf
.autoRefresh
= evt
.IsChecked()
1045 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1046 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1048 def OnAbout(self
, evt
):
1052 (c) Roman Rolinsky <rollrom@users.sourceforge.net>
1053 Homepage: http://xrced.sourceforge.net\
1055 dlg
= wx
.MessageDialog(self
, str, 'About XRCed', wx
.OK | wx
.CENTRE
)
1059 def OnReadme(self
, evt
):
1060 text
= open(os
.path
.join(basePath
, 'README.txt'), 'r').read()
1061 dlg
= ScrolledMessageDialog(self
, text
, "XRCed README")
1065 # Simple emulation of python command line
1066 def OnDebugCMD(self
, evt
):
1069 exec raw_input('C:\> ')
1074 (etype
, value
, tb
) =sys
.exc_info()
1075 tblist
=traceback
.extract_tb(tb
)[1:]
1076 msg
=' '.join(traceback
.format_exception_only(etype
, value
)
1077 +traceback
.format_list(tblist
))
1080 def OnCreate(self
, evt
):
1081 selected
= tree
.selection
1082 if tree
.ctrl
: appendChild
= False
1083 else: appendChild
= not tree
.NeedInsert(selected
)
1084 xxx
= tree
.GetPyData(selected
)
1088 # If has previous item, insert after it, else append to parent
1090 parentLeaf
= tree
.GetItemParent(selected
)
1092 # If has next item, insert, else append to parent
1093 nextItem
= tree
.GetNextSibling(selected
)
1094 parentLeaf
= tree
.GetItemParent(selected
)
1095 # Expanded container (must have children)
1096 elif tree
.shift
and tree
.IsExpanded(selected
) \
1097 and tree
.GetChildrenCount(selected
, False):
1098 nextItem
= tree
.GetFirstChild(selected
)[0]
1099 parentLeaf
= selected
1101 nextItem
= wx
.TreeItemId()
1102 parentLeaf
= selected
1103 parent
= tree
.GetPyData(parentLeaf
)
1104 if parent
.hasChild
: parent
= parent
.child
1106 # Create object_ref?
1107 if evt
.GetId() == ID_NEW
.REF
:
1108 ref
= wx
.GetTextFromUser('Create reference to:', 'Create reference')
1110 xxx
= MakeEmptyRefXXX(parent
, ref
)
1111 elif evt
.GetId() == ID_NEW
.COMMENT
:
1112 xxx
= MakeEmptyCommentXXX(parent
)
1114 # Create empty element
1115 if evt
.GetId() >= ID_NEW
.CUSTOM
:
1116 className
= pullDownMenu
.customMap
[evt
.GetId()]
1118 className
= pullDownMenu
.createMap
[evt
.GetId()]
1119 xxx
= MakeEmptyXXX(parent
, className
)
1121 # Insert new node, register undo
1122 if xxx
.isElement
: # true object
1123 # Set default name for top-level windows
1124 if parent
.__class
__ == xxxMainNode
:
1125 cl
= xxx
.treeObject().__class
__
1126 frame
.maxIDs
[cl
] += 1
1127 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1128 # And for some other standard controls
1129 elif parent
.__class
__ == xxxStdDialogButtonSizer
:
1130 xxx
.setTreeName(pullDownMenu
.stdButtonIDs
[evt
.GetId()][0])
1131 # We can even set label
1132 obj
= xxx
.treeObject()
1133 elem
= g
.tree
.dom
.createElement('label')
1134 elem
.appendChild(g
.tree
.dom
.createTextNode(pullDownMenu
.stdButtonIDs
[evt
.GetId()][1]))
1135 obj
.params
['label'] = xxxParam(elem
)
1136 xxx
.treeObject().node
.appendChild(elem
)
1138 newItem
= tree
.InsertNode(parentLeaf
, parent
, xxx
.node
, nextItem
)
1139 else: # comment node
1140 newItem
= tree
.InsertNode(parentLeaf
, parent
, xxx
.node
, nextItem
)
1141 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
1142 tree
.EnsureVisible(newItem
)
1143 tree
.SelectItem(newItem
)
1144 if not tree
.IsVisible(newItem
):
1145 tree
.ScrollTo(newItem
)
1148 if xxx
.isElement
and g
.testWin
and tree
.IsHighlatable(newItem
):
1149 if conf
.autoRefresh
:
1150 tree
.needUpdate
= True
1151 tree
.pendingHighLight
= newItem
1153 tree
.pendingHighLight
= None
1155 if not xxx
.isElement
:
1156 tree
.EditLabel(newItem
)
1159 # Replace one object with another
1160 def OnReplace(self
, evt
):
1161 selected
= tree
.selection
1162 xxx
= tree
.GetPyData(selected
).treeObject()
1164 parent
= elem
.parentNode
1165 undoMan
.RegisterUndo(UndoReplace(selected
))
1167 className
= pullDownMenu
.createMap
[evt
.GetId() - 1000]
1169 # Create temporary empty node (with default values)
1170 dummy
= MakeEmptyDOM(className
)
1171 if className
== 'spacer' and xxx
.className
!= 'spacer':
1173 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1174 klass
= xxxSizerItem
1176 klass
= xxxDict
[className
]
1177 # Remove non-compatible children
1178 if tree
.ItemHasChildren(selected
) and not klass
.hasChildren
:
1179 tree
.DeleteChildren(selected
)
1180 nodes
= elem
.childNodes
[:]
1183 if node
.nodeType
!= minidom
.Node
.ELEMENT_NODE
: continue
1187 if not klass
.hasChildren
: remove
= True
1188 elif tag
not in klass
.allParams
and \
1189 (not klass
.hasStyle
or tag
not in klass
.styles
):
1194 elem
.removeChild(node
)
1197 # Remove sizeritem child if spacer
1198 if className
== 'spacer' and xxx
.className
!= 'spacer':
1199 sizeritem
= elem
.parentNode
1200 assert sizeritem
.getAttribute('class') == 'sizeritem'
1201 sizeritem
.removeChild(elem
)
1204 tree
.GetPyData(selected
).hasChild
= False
1205 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1206 # Create sizeritem element
1207 assert xxx
.parent
.isSizer
1208 elem
.setAttribute('class', 'sizeritem')
1209 node
= MakeEmptyDOM(className
)
1210 elem
.appendChild(node
)
1211 # Replace to point to new object
1212 xxx
= xxxSizerItem(xxx
.parent
, elem
)
1214 tree
.SetPyData(selected
, xxx
)
1217 # Copy parameters present in dummy but not in elem
1218 for node
in dummy
.childNodes
:
1219 if node
.tagName
not in tags
: elem
.appendChild(node
.cloneNode(True))
1223 elem
.setAttribute('class', className
)
1224 if elem
.hasAttribute('subclass'):
1225 elem
.removeAttribute('subclass') # clear subclassing
1226 # Re-create xxx element
1227 xxx
= MakeXXXFromDOM(xxx
.parent
, elem
)
1228 # Remove incompatible style flags
1229 if 'style' in xxx
.params
:
1230 styles
= map(string
.strip
, xxx
.params
['style'].value().split('|'))
1231 newStyles
= [s
for s
in styles
if s
in klass
.winStyles
or s
in genericStyles
]
1232 if newStyles
!= styles
:
1234 value
= reduce(lambda a
,b
: a
+'|'+b
, newStyles
)
1237 xxx
.params
['style'].update(value
)
1239 # Update parent in child objects
1240 if tree
.ItemHasChildren(selected
):
1241 i
, cookie
= tree
.GetFirstChild(selected
)
1243 x
= tree
.GetPyData(i
)
1245 if x
.hasChild
: x
.child
.parent
= xxx
1246 i
, cookie
= tree
.GetNextChild(selected
, cookie
)
1249 if tree
.GetPyData(selected
).hasChild
: # child container
1250 container
= tree
.GetPyData(selected
)
1251 container
.resetChild(xxx
)
1254 tree
.SetPyData(selected
, xxx
)
1255 tree
.SetItemText(selected
, xxx
.treeName())
1256 tree
.SetItemImage(selected
, xxx
.treeImage())
1258 # Set default name for top-level windows
1259 if parent
.__class
__ == xxxMainNode
:
1260 cl
= xxx
.treeObject().__class
__
1261 frame
.maxIDs
[cl
] += 1
1262 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1265 g
.panel
.SetData(xxx
)
1269 #undoMan.RegisterUndo(UndoPasteCreate(parentLeaf, parent, newItem, selected))
1271 if g
.testWin
and tree
.IsHighlatable(selected
):
1272 if conf
.autoRefresh
:
1273 tree
.needUpdate
= True
1274 tree
.pendingHighLight
= selected
1276 tree
.pendingHighLight
= None
1280 # Expand/collapse subtree
1281 def OnExpand(self
, evt
):
1282 if tree
.selection
: tree
.ExpandAll(tree
.selection
)
1283 else: tree
.ExpandAll(tree
.root
)
1284 def OnCollapse(self
, evt
):
1285 if tree
.selection
: tree
.CollapseAll(tree
.selection
)
1286 else: tree
.CollapseAll(tree
.root
)
1288 def OnPullDownHighlight(self
, evt
):
1289 menuId
= evt
.GetMenuId()
1291 menu
= evt
.GetEventObject()
1292 help = menu
.GetHelpString(menuId
)
1293 self
.SetStatusText(help)
1295 self
.SetStatusText('')
1297 def OnUpdateUI(self
, evt
):
1298 if evt
.GetId() in [wx
.ID_CUT
, wx
.ID_COPY
, self
.ID_DELETE
]:
1299 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1300 elif evt
.GetId() == wx
.ID_SAVE
:
1301 evt
.Enable(self
.modified
)
1302 elif evt
.GetId() in [wx
.ID_PASTE
, self
.ID_TOOL_PASTE
]:
1303 evt
.Enable(tree
.selection
is not None)
1304 elif evt
.GetId() == self
.ID_TEST
:
1305 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1306 elif evt
.GetId() in [self
.ID_LOCATE
, self
.ID_TOOL_LOCATE
]:
1307 evt
.Enable(g
.testWin
is not None)
1308 elif evt
.GetId() == wx
.ID_UNDO
: evt
.Enable(undoMan
.CanUndo())
1309 elif evt
.GetId() == wx
.ID_REDO
: evt
.Enable(undoMan
.CanRedo())
1311 def OnIdle(self
, evt
):
1312 if self
.inIdle
: return # Recursive call protection
1316 if conf
.autoRefresh
:
1318 self
.SetStatusText('Refreshing test window...')
1320 tree
.CreateTestWin(g
.testWin
.item
)
1321 self
.SetStatusText('')
1322 tree
.needUpdate
= False
1323 elif tree
.pendingHighLight
:
1325 tree
.HighLight(tree
.pendingHighLight
)
1327 # Remove highlight if any problem
1328 if g
.testWin
.highLight
:
1329 g
.testWin
.highLight
.Remove()
1330 tree
.pendingHighLight
= None
1337 # We don't let close panel window
1338 def OnCloseMiniFrame(self
, evt
):
1341 def OnIconize(self
, evt
):
1343 conf
.x
, conf
.y
= self
.GetPosition()
1344 conf
.width
, conf
.height
= self
.GetSize()
1346 conf
.sashPos
= self
.splitter
.GetSashPosition()
1348 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1349 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1350 self
.miniFrame
.Iconize()
1352 if not conf
.embedPanel
:
1353 self
.miniFrame
.Iconize(False)
1356 def OnCloseWindow(self
, evt
):
1357 if not self
.AskSave(): return
1358 if g
.testWin
: g
.testWin
.Destroy()
1359 if not panel
.GetPageCount() == 2:
1360 panel
.page2
.Destroy()
1362 # If we don't do this, page does not get destroyed (a bug?)
1364 if not self
.IsIconized():
1365 conf
.x
, conf
.y
= self
.GetPosition()
1366 conf
.width
, conf
.height
= self
.GetSize()
1368 conf
.sashPos
= self
.splitter
.GetSashPosition()
1370 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1371 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1374 def CreateLocalConf(self
, path
):
1375 name
= os
.path
.splitext(path
)[0]
1377 return wx
.FileConfig(localFilename
=name
)
1381 conf
.localconf
= None
1383 self
.SetModified(False)
1389 # Numbers for new controls
1391 for cl
in [xxxPanel
, xxxDialog
, xxxFrame
,
1392 xxxMenuBar
, xxxMenu
, xxxToolBar
,
1393 xxxWizard
, xxxBitmap
, xxxIcon
]:
1395 # Restore handlers, menu, etc. to initial
1396 setHandlers(self
.handlers
[:])
1397 g
.pullDownMenu
.custom
= self
.custom
[:]
1398 # Remove modules imported from comment directives
1399 map(sys
.modules
.pop
, [m
for m
in sys
.modules
if m
not in self
.modules
])
1400 xxxParamComment
.locals = {} # clear local namespace
1401 xxxParamComment
.allow
= None # clear execution state
1403 def SetModified(self
, state
=True):
1404 self
.modified
= state
1405 name
= os
.path
.basename(self
.dataFile
)
1406 if not name
: name
= defaultName
1408 self
.SetTitle(progname
+ ': ' + name
+ ' *')
1410 self
.SetTitle(progname
+ ': ' + name
)
1412 def Open(self
, path
):
1413 if not os
.path
.exists(path
):
1414 wx
.LogError('File does not exists: %s' % path
)
1416 # Try to read the file
1420 dom
= minidom
.parse(f
)
1422 # Set encoding global variable and default encoding
1424 g
.currentEncoding
= dom
.encoding
1425 wx
.SetDefaultPyEncoding(g
.currentEncoding
.encode())
1427 g
.currentEncoding
= ''
1429 self
.dataFile
= path
= os
.path
.abspath(path
)
1430 dir = os
.path
.dirname(path
)
1431 if dir: os
.chdir(dir)
1432 # Allow importing modules from the same directory
1433 sys
.path
= sys_path
+ [dir]
1435 self
.SetTitle(progname
+ ': ' + os
.path
.basename(path
))
1436 conf
.localconf
= self
.CreateLocalConf(self
.dataFile
)
1438 # Nice exception printing
1439 inf
= sys
.exc_info()
1440 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1441 wx
.LogError('Error reading file: %s' % path
)
1446 def Indent(self
, node
, indent
= 0):
1447 if node
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1448 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1449 node
.parentNode
.insertBefore(text
, node
)
1450 return # no children
1451 # Copy child list because it will change soon
1452 children
= node
.childNodes
[:]
1453 # Main node doesn't need to be indented
1455 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1456 node
.parentNode
.insertBefore(text
, node
)
1458 # Append newline after last child, except for text nodes
1459 if children
[-1].nodeType
== minidom
.Node
.ELEMENT_NODE
:
1460 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1461 node
.appendChild(text
)
1462 # Indent children which are elements
1464 if n
.nodeType
== minidom
.Node
.ELEMENT_NODE
or \
1465 n
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1466 self
.Indent(n
, indent
+ 2)
1468 def Save(self
, path
):
1472 if tree
.selection
and panel
.IsModified():
1473 self
.OnRefresh(wx
.CommandEvent())
1474 if g
.currentEncoding
:
1475 f
= codecs
.open(path
, 'wt', g
.currentEncoding
)
1477 f
= codecs
.open(path
, 'wt')
1478 # Make temporary copy for formatting it
1479 # !!! We can't clone dom node, it works only once
1480 #self.domCopy = tree.dom.cloneNode(True)
1481 self
.domCopy
= MyDocument()
1482 mainNode
= self
.domCopy
.appendChild(tree
.mainNode
.cloneNode(True))
1483 # Remove first child (test element)
1484 testElem
= mainNode
.firstChild
1485 mainNode
.removeChild(testElem
)
1487 self
.Indent(mainNode
)
1488 self
.domCopy
.writexml(f
, encoding
= g
.currentEncoding
)
1490 self
.domCopy
.unlink()
1492 self
.SetModified(False)
1493 panel
.SetModified(False)
1494 conf
.localconf
.Flush()
1496 inf
= sys
.exc_info()
1497 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1498 wx
.LogError('Error writing file: %s' % path
)
1502 if not (self
.modified
or panel
.IsModified()): return True
1503 flags
= wx
.ICON_EXCLAMATION | wx
.YES_NO | wx
.CANCEL | wx
.CENTRE
1504 dlg
= wx
.MessageDialog( self
, 'File is modified. Save before exit?',
1505 'Save before too late?', flags
)
1506 say
= dlg
.ShowModal()
1509 if say
== wx
.ID_YES
:
1510 self
.OnSaveOrSaveAs(wx
.CommandEvent(wx
.ID_SAVE
))
1511 # If save was successful, modified flag is unset
1512 if not self
.modified
: return True
1513 elif say
== wx
.ID_NO
:
1514 self
.SetModified(False)
1515 panel
.SetModified(False)
1519 ################################################################################
1521 class PythonOptions(wx
.Dialog
):
1523 def __init__(self
, parent
, cfg
, dataFile
):
1524 pre
= wx
.PreDialog()
1525 g
.frame
.res
.LoadOnDialog(pre
, parent
, "PYTHON_OPTIONS")
1526 self
.PostCreate(pre
)
1529 self
.dataFile
= dataFile
1531 self
.AutoGenerateCB
= xrc
.XRCCTRL(self
, "AutoGenerateCB")
1532 self
.EmbedCB
= xrc
.XRCCTRL(self
, "EmbedCB")
1533 self
.GettextCB
= xrc
.XRCCTRL(self
, "GettextCB")
1534 self
.MakeXRSFileCB
= xrc
.XRCCTRL(self
, "MakeXRSFileCB")
1535 self
.FileNameTC
= xrc
.XRCCTRL(self
, "FileNameTC")
1536 self
.BrowseBtn
= xrc
.XRCCTRL(self
, "BrowseBtn")
1537 self
.GenerateBtn
= xrc
.XRCCTRL(self
, "GenerateBtn")
1538 self
.SaveOptsBtn
= xrc
.XRCCTRL(self
, "SaveOptsBtn")
1540 self
.Bind(wx
.EVT_BUTTON
, self
.OnBrowse
, self
.BrowseBtn
)
1541 self
.Bind(wx
.EVT_BUTTON
, self
.OnGenerate
, self
.GenerateBtn
)
1542 self
.Bind(wx
.EVT_BUTTON
, self
.OnSaveOpts
, self
.SaveOptsBtn
)
1544 if self
.cfg
.Read("filename", "") != "":
1545 self
.FileNameTC
.SetValue(self
.cfg
.Read("filename"))
1547 name
= os
.path
.splitext(os
.path
.split(dataFile
)[1])[0]
1549 self
.FileNameTC
.SetValue(name
)
1550 self
.AutoGenerateCB
.SetValue(self
.cfg
.ReadBool("autogenerate", False))
1551 self
.EmbedCB
.SetValue(self
.cfg
.ReadBool("embedResource", False))
1552 self
.MakeXRSFileCB
.SetValue(self
.cfg
.ReadBool("makeXRS", False))
1553 self
.GettextCB
.SetValue(self
.cfg
.ReadBool("genGettext", False))
1556 def OnBrowse(self
, evt
):
1557 path
= self
.FileNameTC
.GetValue()
1558 dirname
= os
.path
.abspath(os
.path
.dirname(path
))
1559 name
= os
.path
.split(path
)[1]
1560 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.py',
1561 wx
.SAVE | wx
.OVERWRITE_PROMPT
)
1562 if dlg
.ShowModal() == wx
.ID_OK
:
1563 path
= dlg
.GetPath()
1564 self
.FileNameTC
.SetValue(path
)
1568 def OnGenerate(self
, evt
):
1569 pypath
= self
.FileNameTC
.GetValue()
1570 embed
= self
.EmbedCB
.GetValue()
1571 genGettext
= self
.GettextCB
.GetValue()
1572 frame
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
1576 def OnSaveOpts(self
, evt
=None):
1577 self
.cfg
.Write("filename", self
.FileNameTC
.GetValue())
1578 self
.cfg
.WriteBool("autogenerate", self
.AutoGenerateCB
.GetValue())
1579 self
.cfg
.WriteBool("embedResource", self
.EmbedCB
.GetValue())
1580 self
.cfg
.WriteBool("makeXRS", self
.MakeXRSFileCB
.GetValue())
1581 self
.cfg
.WriteBool("genGettext", self
.GettextCB
.GetValue())
1583 self
.EndModal(wx
.ID_OK
)
1585 ################################################################################
1587 class PrefsDialog(wx
.Dialog
):
1589 def __init__(self
, parent
):
1590 pre
= wx
.PreDialog()
1591 g
.frame
.res
.LoadOnDialog(pre
, parent
, "DIALOG_PREFS")
1592 self
.PostCreate(pre
)
1593 self
.checkControls
= {} # map of check IDs to (control,dict,param)
1595 xxx
= sys
.modules
['xxx']
1596 d
= xxx
.xxxSizerItem
.defaults_panel
1598 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_panel')
1599 id = self
.check_proportion_panel
.GetId()
1600 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1601 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_panel'),
1604 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_panel')
1605 id = self
.check_flag_panel
.GetId()
1606 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1607 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_panel'),
1610 d
= xxx
.xxxSizerItem
.defaults_control
1612 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_control')
1613 id = self
.check_proportion_panel
.GetId()
1614 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1615 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_control'),
1618 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_control')
1619 id = self
.check_flag_panel
.GetId()
1620 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1621 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_control'),
1624 for id,cdp
in self
.checkControls
.items():
1627 if isinstance(c
, wx
.SpinCtrl
):
1628 c
.SetValue(int(d
[p
]))
1631 self
.FindWindowById(id).SetValue(True)
1635 self
.radio_allow_exec
= xrc
.XRCCTRL(self
, 'radio_allow_exec')
1637 radio
= {'ask': 0, 'yes':1, 'no':2}
[g
.conf
.allowExec
]
1640 self
.radio_allow_exec
.SetSelection(radio
)
1642 def OnCheck(self
, evt
):
1643 self
.checkControls
[evt
.GetId()][0].Enable(evt
.IsChecked())
1646 ################################################################################
1648 # Parse string in form var1=val1[,var2=val2]* as dictionary
1649 def ReadDictFromString(s
):
1651 for vv
in s
.split(','):
1652 var
,val
= vv
.split(':')
1653 d
[var
.strip()] = val
1656 # Transform dictionary with strings into one string
1657 def DictToString(d
):
1658 return ','.join(map(':'.join
, d
.items()))
1661 print >> sys
.stderr
, 'usage: xrced [-dhiv] [file]'
1666 if wx
.VERSION
[:3] < MinWxVersion
:
1668 This version of XRCed may not work correctly on your version of wxWidgets. \
1669 Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion
)
1671 # Process comand-line
1674 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'dhiv')
1682 print 'XRCed version', version
1685 except getopt
.GetoptError
:
1686 if wx
.Platform
!= '__WXMAC__': # macs have some extra parameters
1687 print >> sys
.stderr
, 'Unknown option'
1691 self
.SetAppName('xrced')
1694 conf
= g
.conf
= wx
.Config(style
= wx
.CONFIG_USE_LOCAL_FILE
)
1695 conf
.localconf
= None
1696 conf
.autoRefresh
= conf
.ReadInt('autorefresh', True)
1697 pos
= conf
.ReadInt('x', -1), conf
.ReadInt('y', -1)
1698 size
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600)
1699 conf
.embedPanel
= conf
.ReadInt('embedPanel', True)
1700 conf
.showTools
= conf
.ReadInt('showTools', True)
1701 conf
.sashPos
= conf
.ReadInt('sashPos', 200)
1702 # read recently used files
1703 recentfiles
=conf
.Read('recentFiles','')
1706 for fil
in recentfiles
.split('|'):
1707 conf
.recentfiles
[wx
.NewId()]=fil
1708 if not conf
.embedPanel
:
1709 conf
.panelX
= conf
.ReadInt('panelX', -1)
1710 conf
.panelY
= conf
.ReadInt('panelY', -1)
1712 conf
.panelX
= conf
.panelY
= -1
1713 conf
.panelWidth
= conf
.ReadInt('panelWidth', 200)
1714 conf
.panelHeight
= conf
.ReadInt('panelHeight', 200)
1715 conf
.panic
= not conf
.HasEntry('nopanic')
1717 conf
.allowExec
= conf
.Read('Prefs/allowExec', 'ask')
1718 p
= 'Prefs/sizeritem_defaults_panel'
1719 if conf
.HasEntry(p
):
1720 sys
.modules
['xxx'].xxxSizerItem
.defaults_panel
= ReadDictFromString(conf
.Read(p
))
1721 p
= 'Prefs/sizeritem_defaults_control'
1722 if conf
.HasEntry(p
):
1723 sys
.modules
['xxx'].xxxSizerItem
.defaults_control
= ReadDictFromString(conf
.Read(p
))
1726 wx
.FileSystem
.AddHandler(wx
.MemoryFSHandler())
1728 frame
= Frame(pos
, size
)
1732 plugins
= os
.getenv('XRCEDPATH')
1736 for dir in plugins
.split(':'):
1737 if os
.path
.isdir(dir) and \
1738 os
.path
.isfile(os
.path
.join(dir, '__init__.py')):
1740 dir = os
.path
.abspath(os
.path
.normpath(dir))
1741 sys
.path
= sys_path
+ [os
.path
.dirname(dir)]
1744 __import__(os
.path
.basename(dir), globals(), locals(), ['*'])
1746 print traceback
.print_exc()
1749 # Store important data
1750 frame
.handlers
= getHandlers()[:]
1751 frame
.custom
= g
.pullDownMenu
.custom
[:]
1752 frame
.modules
= set(sys
.modules
.keys())
1757 # Load file after showing
1760 frame
.open = frame
.Open(args
[0])
1768 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1769 wc
.WriteInt('x', conf
.x
)
1770 wc
.WriteInt('y', conf
.y
)
1771 wc
.WriteInt('width', conf
.width
)
1772 wc
.WriteInt('height', conf
.height
)
1773 wc
.WriteInt('embedPanel', conf
.embedPanel
)
1774 wc
.WriteInt('showTools', conf
.showTools
)
1775 if not conf
.embedPanel
:
1776 wc
.WriteInt('panelX', conf
.panelX
)
1777 wc
.WriteInt('panelY', conf
.panelY
)
1778 wc
.WriteInt('sashPos', conf
.sashPos
)
1779 wc
.WriteInt('panelWidth', conf
.panelWidth
)
1780 wc
.WriteInt('panelHeight', conf
.panelHeight
)
1781 wc
.WriteInt('nopanic', 1)
1782 wc
.Write('recentFiles', '|'.join(conf
.recentfiles
.values()[-5:]))
1784 wc
.DeleteGroup('Prefs')
1785 wc
.Write('Prefs/allowExec', conf
.allowExec
)
1786 v
= sys
.modules
['xxx'].xxxSizerItem
.defaults_panel
1787 if v
: wc
.Write('Prefs/sizeritem_defaults_panel', DictToString(v
))
1788 v
= sys
.modules
['xxx'].xxxSizerItem
.defaults_control
1789 if v
: wc
.Write('Prefs/sizeritem_defaults_control', DictToString(v
))
1794 app
= App(0, useBestVisual
=False)
1795 #app.SetAssertMode(wx.PYAPP_ASSERT_LOG)
1801 if __name__
== '__main__':