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 TaskBarIcon(wx
.TaskBarIcon
):
96 def __init__(self
, frame
):
97 wx
.TaskBarIcon
.__init
__(self
)
100 self
.SetIcon(images
.getIconIcon(), "XRCed")
102 class Frame(wx
.Frame
):
103 def __init__(self
, pos
, size
):
105 # pre.SetExtraStyle(wx.FRAME_EX_METAL)
106 pre
.Create(None, -1, '', pos
, size
)
108 #wx.Frame.__init__(self, None, -1, '', pos, size)
110 frame
= g
.frame
= self
111 bar
= self
.CreateStatusBar(2)
112 bar
.SetStatusWidths([-1, 40])
113 self
.SetIcon(images
.getIconIcon())
115 self
.tbicon
= TaskBarIcon(self
)
122 # Load our own resources
123 self
.res
= xrc
.EmptyXmlResource()
124 # !!! Blocking of assert failure occurring in older unicode builds
126 quietlog
= wx
.LogNull()
127 self
.res
.Load(os
.path
.join(basePath
, 'xrced.xrc'))
128 except wx
._core
.PyAssertionError
:
129 print 'PyAssertionError was ignored'
132 menuBar
= wx
.MenuBar()
135 menu
.Append(wx
.ID_NEW
, '&New\tCtrl-N', 'New file')
136 menu
.AppendSeparator()
137 menu
.Append(wx
.ID_OPEN
, '&Open...\tCtrl-O', 'Open XRC file')
139 self
.recentMenu
= wx
.Menu()
140 g
.fileHistory
.UseMenu(self
.recentMenu
)
141 g
.fileHistory
.AddFilesToMenu()
142 self
.Bind(wx
.EVT_MENU
, self
.OnRecentFile
, id=wx
.ID_FILE1
, id2
=wx
.ID_FILE9
)
143 menu
.AppendMenu(-1, 'Open &Recent', self
.recentMenu
, 'Open a recent file')
145 menu
.AppendSeparator()
146 menu
.Append(wx
.ID_SAVE
, '&Save\tCtrl-S', 'Save XRC file')
147 menu
.Append(wx
.ID_SAVEAS
, 'Save &As...', 'Save XRC file under different name')
148 self
.ID_GENERATE_PYTHON
= wx
.NewId()
149 menu
.Append(self
.ID_GENERATE_PYTHON
, '&Generate Python...',
150 'Generate a Python module that uses this XRC')
151 menu
.AppendSeparator()
152 self
.ID_PREFS
= wx
.NewId()
153 menu
.Append(self
.ID_PREFS
, 'Preferences...', 'Change XRCed settings')
154 menu
.AppendSeparator()
155 menu
.Append(wx
.ID_EXIT
, '&Quit\tCtrl-Q', 'Exit application')
157 menuBar
.Append(menu
, '&File')
160 menu
.Append(wx
.ID_UNDO
, '&Undo\tCtrl-Z', 'Undo')
161 menu
.Append(wx
.ID_REDO
, '&Redo\tCtrl-Y', 'Redo')
162 menu
.AppendSeparator()
163 menu
.Append(wx
.ID_CUT
, 'Cut\tCtrl-X', 'Cut to the clipboard')
164 menu
.Append(wx
.ID_COPY
, '&Copy\tCtrl-C', 'Copy to the clipboard')
165 menu
.Append(wx
.ID_PASTE
, '&Paste\tCtrl-V', 'Paste from the clipboard')
166 self
.ID_DELETE
= wx
.NewId()
167 menu
.Append(self
.ID_DELETE
, '&Delete\tCtrl-D', 'Delete object')
168 menu
.AppendSeparator()
169 self
.ID_LOCATE
= wx
.NewId()
170 self
.ID_TOOL_LOCATE
= wx
.NewId()
171 self
.ID_TOOL_PASTE
= wx
.NewId()
172 menu
.Append(self
.ID_LOCATE
, '&Locate\tCtrl-L', 'Locate control in test window and select it')
173 menuBar
.Append(menu
, '&Edit')
175 self
.ID_EMBED_PANEL
= wx
.NewId()
176 menu
.Append(self
.ID_EMBED_PANEL
, '&Embed Panel',
177 'Toggle embedding properties panel in the main window', True)
178 menu
.Check(self
.ID_EMBED_PANEL
, conf
.embedPanel
)
179 self
.ID_SHOW_TOOLS
= wx
.NewId()
180 menu
.Append(self
.ID_SHOW_TOOLS
, 'Show &Tools', 'Toggle tools', True)
181 menu
.Check(self
.ID_SHOW_TOOLS
, conf
.showTools
)
182 menu
.AppendSeparator()
183 self
.ID_TEST
= wx
.NewId()
184 menu
.Append(self
.ID_TEST
, '&Test\tF5', 'Show test window')
185 self
.ID_REFRESH
= wx
.NewId()
186 menu
.Append(self
.ID_REFRESH
, '&Refresh\tCtrl-R', 'Refresh test window')
187 self
.ID_AUTO_REFRESH
= wx
.NewId()
188 menu
.Append(self
.ID_AUTO_REFRESH
, '&Auto-refresh\tAlt-A',
189 'Toggle auto-refresh mode', True)
190 menu
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
191 self
.ID_TEST_HIDE
= wx
.NewId()
192 menu
.Append(self
.ID_TEST_HIDE
, '&Hide\tF6', 'Close test window')
193 menuBar
.Append(menu
, '&View')
196 self
.ID_MOVEUP
= wx
.NewId()
197 menu
.Append(self
.ID_MOVEUP
, '&Up', 'Move before previous sibling')
198 self
.ID_MOVEDOWN
= wx
.NewId()
199 menu
.Append(self
.ID_MOVEDOWN
, '&Down', 'Move after next sibling')
200 self
.ID_MOVELEFT
= wx
.NewId()
201 menu
.Append(self
.ID_MOVELEFT
, '&Make sibling', 'Make sibling of parent')
202 self
.ID_MOVERIGHT
= wx
.NewId()
203 menu
.Append(self
.ID_MOVERIGHT
, '&Make child', 'Make child of previous sibling')
204 menuBar
.Append(menu
, '&Move')
207 menu
.Append(wx
.ID_ABOUT
, '&About...', 'About XCRed')
208 self
.ID_README
= wx
.NewId()
209 menu
.Append(self
.ID_README
, '&Readme...\tF1', 'View the README file')
211 self
.ID_DEBUG_CMD
= wx
.NewId()
212 menu
.Append(self
.ID_DEBUG_CMD
, 'CMD', 'Python command line')
213 wx
.EVT_MENU(self
, self
.ID_DEBUG_CMD
, self
.OnDebugCMD
)
214 menuBar
.Append(menu
, '&Help')
216 self
.menuBar
= menuBar
217 self
.SetMenuBar(menuBar
)
220 tb
= self
.CreateToolBar(wx
.TB_HORIZONTAL | wx
.NO_BORDER | wx
.TB_FLAT
)
221 if wx
.Platform
!= '__WXMAC__':
222 # Redefine AddSeparator on wxGTK and wxMSW to add vertical line
224 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23),
225 style
=wx
.LI_VERTICAL
))
226 tb
.AddSeparator
= _AddSeparator
228 # Use tango icons and slightly wider bitmap size on Mac
229 if wx
.Platform
== '__WXMAC__':
230 tb
.SetToolBitmapSize((26,26))
231 new_bmp
= images
.getNewBitmap()
232 open_bmp
= images
.getOpenBitmap()
233 save_bmp
= images
.getSaveBitmap()
234 undo_bmp
= images
.getUndoBitmap()
235 redo_bmp
= images
.getRedoBitmap()
236 cut_bmp
= images
.getCutBitmap()
237 copy_bmp
= images
.getCopyBitmap()
238 paste_bmp
= images
.getPasteBitmap()
240 tb
.SetToolBitmapSize((24,24))
241 new_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_NORMAL_FILE
, wx
.ART_TOOLBAR
)
242 open_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_OPEN
, wx
.ART_TOOLBAR
)
243 save_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_SAVE
, wx
.ART_TOOLBAR
)
244 undo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_UNDO
, wx
.ART_TOOLBAR
)
245 redo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_REDO
, wx
.ART_TOOLBAR
)
246 cut_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_CUT
, wx
.ART_TOOLBAR
)
247 copy_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_COPY
, wx
.ART_TOOLBAR
)
248 paste_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_PASTE
, wx
.ART_TOOLBAR
)
249 tb
.AddSimpleTool(wx
.ID_NEW
, new_bmp
, 'New', 'New file')
250 tb
.AddSimpleTool(wx
.ID_OPEN
, open_bmp
, 'Open', 'Open file')
251 tb
.AddSimpleTool(wx
.ID_SAVE
, save_bmp
, 'Save', 'Save file')
253 tb
.AddSimpleTool(wx
.ID_UNDO
, undo_bmp
, 'Undo', 'Undo')
254 tb
.AddSimpleTool(wx
.ID_REDO
, redo_bmp
, 'Redo', 'Redo')
256 tb
.AddSimpleTool(wx
.ID_CUT
, cut_bmp
, 'Cut', 'Cut')
257 tb
.AddSimpleTool(wx
.ID_COPY
, copy_bmp
, 'Copy', 'Copy')
258 tb
.AddSimpleTool(self
.ID_TOOL_PASTE
, paste_bmp
, 'Paste', 'Paste')
260 tb
.AddSimpleTool(self
.ID_TOOL_LOCATE
,
261 images
.getLocateBitmap(), #images.getLocateArmedBitmap(),
262 'Locate', 'Locate control in test window and select it', True)
263 tb
.AddSimpleTool(self
.ID_TEST
, images
.getTestBitmap(), 'Test', 'Test window')
264 tb
.AddSimpleTool(self
.ID_REFRESH
, images
.getRefreshBitmap(),
265 'Refresh', 'Refresh view')
266 tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, images
.getAutoRefreshBitmap(),
267 'Auto-refresh', 'Toggle auto-refresh mode', True)
269 tb
.AddSimpleTool(self
.ID_MOVEUP
, images
.getToolMoveUpBitmap(),
270 'Up', 'Move before previous sibling')
271 tb
.AddSimpleTool(self
.ID_MOVEDOWN
, images
.getToolMoveDownBitmap(),
272 'Down', 'Move after next sibling')
273 tb
.AddSimpleTool(self
.ID_MOVELEFT
, images
.getToolMoveLeftBitmap(),
274 'Make Sibling', 'Make sibling of parent')
275 tb
.AddSimpleTool(self
.ID_MOVERIGHT
, images
.getToolMoveRightBitmap(),
276 'Make Child', 'Make child of previous sibling')
277 tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
281 self
.minWidth
= tb
.GetSize()[0] # minimal width is the size of toolbar
284 wx
.EVT_MENU(self
, wx
.ID_NEW
, self
.OnNew
)
285 wx
.EVT_MENU(self
, wx
.ID_OPEN
, self
.OnOpen
)
286 wx
.EVT_MENU(self
, wx
.ID_SAVE
, self
.OnSaveOrSaveAs
)
287 wx
.EVT_MENU(self
, wx
.ID_SAVEAS
, self
.OnSaveOrSaveAs
)
288 wx
.EVT_MENU(self
, self
.ID_GENERATE_PYTHON
, self
.OnGeneratePython
)
289 wx
.EVT_MENU(self
, self
.ID_PREFS
, self
.OnPrefs
)
290 wx
.EVT_MENU(self
, wx
.ID_EXIT
, self
.OnExit
)
292 wx
.EVT_MENU(self
, wx
.ID_UNDO
, self
.OnUndo
)
293 wx
.EVT_MENU(self
, wx
.ID_REDO
, self
.OnRedo
)
294 wx
.EVT_MENU(self
, wx
.ID_CUT
, self
.OnCutDelete
)
295 wx
.EVT_MENU(self
, wx
.ID_COPY
, self
.OnCopy
)
296 wx
.EVT_MENU(self
, wx
.ID_PASTE
, self
.OnPaste
)
297 wx
.EVT_MENU(self
, self
.ID_TOOL_PASTE
, self
.OnPaste
)
298 wx
.EVT_MENU(self
, self
.ID_DELETE
, self
.OnCutDelete
)
299 wx
.EVT_MENU(self
, self
.ID_LOCATE
, self
.OnLocate
)
300 wx
.EVT_MENU(self
, self
.ID_TOOL_LOCATE
, self
.OnLocate
)
302 wx
.EVT_MENU(self
, self
.ID_EMBED_PANEL
, self
.OnEmbedPanel
)
303 wx
.EVT_MENU(self
, self
.ID_SHOW_TOOLS
, self
.OnShowTools
)
304 wx
.EVT_MENU(self
, self
.ID_TEST
, self
.OnTest
)
305 wx
.EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
)
306 wx
.EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
)
307 wx
.EVT_MENU(self
, self
.ID_TEST_HIDE
, self
.OnTestHide
)
309 wx
.EVT_MENU(self
, self
.ID_MOVEUP
, self
.OnMoveUp
)
310 wx
.EVT_MENU(self
, self
.ID_MOVEDOWN
, self
.OnMoveDown
)
311 wx
.EVT_MENU(self
, self
.ID_MOVELEFT
, self
.OnMoveLeft
)
312 wx
.EVT_MENU(self
, self
.ID_MOVERIGHT
, self
.OnMoveRight
)
314 wx
.EVT_MENU(self
, wx
.ID_ABOUT
, self
.OnAbout
)
315 wx
.EVT_MENU(self
, self
.ID_README
, self
.OnReadme
)
318 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVE
, self
.OnUpdateUI
)
319 wx
.EVT_UPDATE_UI(self
, wx
.ID_CUT
, self
.OnUpdateUI
)
320 wx
.EVT_UPDATE_UI(self
, wx
.ID_COPY
, self
.OnUpdateUI
)
321 wx
.EVT_UPDATE_UI(self
, wx
.ID_PASTE
, self
.OnUpdateUI
)
322 wx
.EVT_UPDATE_UI(self
, self
.ID_LOCATE
, self
.OnUpdateUI
)
323 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_LOCATE
, self
.OnUpdateUI
)
324 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_PASTE
, self
.OnUpdateUI
)
325 wx
.EVT_UPDATE_UI(self
, wx
.ID_UNDO
, self
.OnUpdateUI
)
326 wx
.EVT_UPDATE_UI(self
, wx
.ID_REDO
, self
.OnUpdateUI
)
327 wx
.EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
)
328 wx
.EVT_UPDATE_UI(self
, self
.ID_TEST
, self
.OnUpdateUI
)
329 wx
.EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
)
332 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
333 #sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND)
334 # Horizontal sizer for toolbar and splitter
335 self
.toolsSizer
= sizer1
= wx
.BoxSizer()
336 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.SP_3DSASH
)
337 self
.splitter
= splitter
338 splitter
.SetMinimumPaneSize(100)
341 g
.tree
= tree
= XML_Tree(splitter
, -1)
343 # Init pull-down menu data
345 g
.pullDownMenu
= pullDownMenu
= PullDownMenu(self
)
347 # Vertical toolbar for GUI buttons
348 g
.tools
= tools
= Tools(self
)
349 tools
.Show(conf
.showTools
)
350 if conf
.showTools
: sizer1
.Add(tools
, 0, wx
.EXPAND
)
352 tree
.RegisterKeyEvents()
354 # Miniframe for split mode
355 miniFrame
= wx
.MiniFrame(self
, -1, 'Properties & Style',
356 (conf
.panelX
, conf
.panelY
),
357 (conf
.panelWidth
, conf
.panelHeight
))
358 self
.miniFrame
= miniFrame
359 sizer2
= wx
.BoxSizer()
360 miniFrame
.SetSizer(sizer2
)
361 # Create panel for parameters
364 panel
= Panel(splitter
)
365 # Set plitter windows
366 splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
368 panel
= Panel(miniFrame
)
369 sizer2
.Add(panel
, 1, wx
.EXPAND
)
371 splitter
.Initialize(tree
)
372 if wx
.Platform
== '__WXMAC__':
373 sizer1
.Add(splitter
, 1, wx
.EXPAND|wx
.RIGHT
, 5)
375 sizer1
.Add(splitter
, 1, wx
.EXPAND
)
376 sizer
.Add(sizer1
, 1, wx
.EXPAND
)
377 self
.SetAutoLayout(True)
381 wx
.EVT_IDLE(self
, self
.OnIdle
)
382 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
383 wx
.EVT_KEY_DOWN(self
, tools
.OnKeyDown
)
384 wx
.EVT_KEY_UP(self
, tools
.OnKeyUp
)
385 wx
.EVT_ICONIZE(self
, self
.OnIconize
)
387 def OnRecentFile(self
,evt
):
388 # open recently used file
389 if not self
.AskSave(): return
392 # get the pathname based on the menu ID
393 fileNum
= evt
.GetId() - wx
.ID_FILE1
394 path
= g
.fileHistory
.GetHistoryFile(fileNum
)
397 self
.SetStatusText('Data loaded')
398 # add it back to the history so it will be moved up the list
399 self
.SaveRecent(path
)
401 self
.SetStatusText('Failed')
405 def OnNew(self
, evt
):
406 if not self
.AskSave(): return
409 def OnOpen(self
, evt
):
410 if not self
.AskSave(): return
411 dlg
= wx
.FileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
412 '', '*.xrc', wx
.OPEN | wx
.CHANGE_DIR
)
413 if dlg
.ShowModal() == wx
.ID_OK
:
415 self
.SetStatusText('Loading...')
419 self
.SetStatusText('Data loaded')
420 self
.SaveRecent(path
)
422 self
.SetStatusText('Failed')
427 def OnSaveOrSaveAs(self
, evt
):
428 if evt
.GetId() == wx
.ID_SAVEAS
or not self
.dataFile
:
429 if self
.dataFile
: name
= ''
430 else: name
= defaultName
431 dirname
= os
.path
.abspath(os
.path
.dirname(self
.dataFile
))
432 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.xrc',
433 wx
.SAVE | wx
.OVERWRITE_PROMPT | wx
.CHANGE_DIR
)
434 if dlg
.ShowModal() == wx
.ID_OK
:
436 if isinstance(path
, unicode):
437 path
= path
.encode(sys
.getfilesystemencoding())
444 # if we already have a localconf then it needs to be
445 # copied to a new config with the new name
447 nc
= self
.CreateLocalConf(path
)
448 flag
, key
, idx
= lc
.GetFirstEntry()
450 nc
.Write(key
, lc
.Read(key
))
451 flag
, key
, idx
= lc
.GetNextEntry(idx
)
454 # otherwise create a new one
455 conf
.localconf
= self
.CreateLocalConf(path
)
458 self
.SetStatusText('Saving...')
462 tmpFile
,tmpName
= tempfile
.mkstemp(prefix
='xrced-')
464 self
.Save(tmpName
) # save temporary file first
465 shutil
.move(tmpName
, path
)
467 self
.SetModified(False)
468 if conf
.localconf
.ReadBool("autogenerate", False):
469 pypath
= conf
.localconf
.Read("filename")
470 embed
= conf
.localconf
.ReadBool("embedResource", False)
471 genGettext
= conf
.localconf
.ReadBool("genGettext", False)
472 self
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
474 self
.SetStatusText('Data saved')
475 self
.SaveRecent(path
)
477 self
.SetStatusText('Failed')
481 def SaveRecent(self
,path
):
482 # append to recently used files
483 g
.fileHistory
.AddFileToHistory(path
)
485 def GeneratePython(self
, dataFile
, pypath
, embed
, genGettext
):
487 import wx
.tools
.pywxrc
488 rescomp
= wx
.tools
.pywxrc
.XmlResourceCompiler()
489 rescomp
.MakePythonModule([dataFile
], pypath
, embed
, genGettext
)
492 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
493 wx
.LogError('Error generating python code : %s' % pypath
)
497 def OnGeneratePython(self
, evt
):
498 if self
.modified
or not conf
.localconf
:
499 wx
.MessageBox("Save the XRC file first!", "Error")
502 dlg
= PythonOptions(self
, conf
.localconf
, self
.dataFile
)
506 def OnPrefs(self
, evt
):
507 dlg
= PrefsDialog(self
)
508 if dlg
.ShowModal() == wx
.ID_OK
:
509 # Fetch new preferences
510 for id,cdp
in dlg
.checkControls
.items():
512 if dlg
.FindWindowById(id).IsChecked():
513 d
[p
] = str(c
.GetValue())
514 elif p
in d
: del d
[p
]
515 g
.conf
.allowExec
= ('ask', 'yes', 'no')[dlg
.radio_allow_exec
.GetSelection()]
518 def OnExit(self
, evt
):
521 def OnUndo(self
, evt
):
522 # Extra check to not mess with idle updating
523 if undoMan
.CanUndo():
525 g
.panel
.SetModified(False)
526 if not undoMan
.CanUndo():
527 self
.SetModified(False)
529 def OnRedo(self
, evt
):
530 if undoMan
.CanRedo():
532 self
.SetModified(True)
534 def OnCopy(self
, evt
):
535 selected
= tree
.selection
536 if not selected
: return # key pressed event
537 xxx
= tree
.GetPyData(selected
)
538 if wx
.TheClipboard
.Open():
540 data
= wx
.CustomDataObject('XRCED')
541 # Set encoding in header
543 s
= xxx
.node
.toxml(encoding
=expat
.native_encoding
)
545 data
= wx
.CustomDataObject('XRCED_node')
547 data
.SetData(cPickle
.dumps(s
))
548 wx
.TheClipboard
.SetData(data
)
549 wx
.TheClipboard
.Close()
550 self
.SetStatusText('Copied')
552 wx
.MessageBox("Unable to open the clipboard", "Error")
554 def OnPaste(self
, evt
):
555 selected
= tree
.selection
556 if not selected
: return # key pressed event
557 # For pasting with Ctrl pressed
559 if evt
.GetId() == pullDownMenu
.ID_PASTE_SIBLING
: appendChild
= False
560 elif evt
.GetId() == self
.ID_TOOL_PASTE
:
561 if g
.tree
.ctrl
: appendChild
= False
562 else: appendChild
= not tree
.NeedInsert(selected
)
563 else: appendChild
= not tree
.NeedInsert(selected
)
564 xxx
= tree
.GetPyData(selected
)
566 # If has next item, insert, else append to parent
567 nextItem
= tree
.GetNextSibling(selected
)
568 parentLeaf
= tree
.GetItemParent(selected
)
569 # Expanded container (must have children)
570 elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, False):
571 # Insert as first child
572 nextItem
= tree
.GetFirstChild(selected
)[0]
573 parentLeaf
= selected
575 # No children or unexpanded item - appendChild stays True
576 nextItem
= wx
.TreeItemId() # no next item
577 parentLeaf
= selected
578 parent
= tree
.GetPyData(parentLeaf
).treeObject()
580 # Create a copy of clipboard pickled element
581 success
= success_node
= False
582 if wx
.TheClipboard
.Open():
584 data
= wx
.CustomDataObject('XRCED')
585 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
587 success
= wx
.TheClipboard
.GetData(data
)
589 # there is a problem if XRCED_node is in clipboard
590 # but previous SetData was for XRCED
592 if not success
: # try other format
593 data
= wx
.CustomDataObject('XRCED_node')
594 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
595 success_node
= wx
.TheClipboard
.GetData(data
)
597 wx
.TheClipboard
.Close()
599 if not success
and not success_node
:
601 "There is no data in the clipboard in the required format",
605 xml
= cPickle
.loads(data
.GetData()) # xml representation of element
607 elem
= minidom
.parseString(xml
).childNodes
[0]
609 elem
= g
.tree
.dom
.createComment(xml
)
611 # Tempopary xxx object to test things
612 xxx
= MakeXXXFromDOM(parent
, elem
)
614 # Check compatibility
615 if not self
.ItemsAreCompatible(parent
, xxx
.treeObject()): return
617 # Check parent and child relationships.
618 # If parent is sizer or notebook, child is of wrong class or
619 # parent is normal window, child is child container then detach child.
620 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
621 parentIsBook
= parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]
622 if isChildContainer
and \
623 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
624 (parentIsBook
and not isinstance(xxx
, xxxPage
)) or \
625 not (parent
.isSizer
or parentIsBook
)):
626 elem
.removeChild(xxx
.child
.node
) # detach child
627 elem
.unlink() # delete child container
628 elem
= xxx
.child
.node
# replace
629 # This may help garbage collection
630 xxx
.child
.parent
= None
631 isChildContainer
= False
632 # Parent is sizer or notebook, child is not child container
633 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
634 # Create sizer item element
635 sizerItemElem
= MakeEmptyDOM(parent
.itemTag
)
636 sizerItemElem
.appendChild(elem
)
638 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
639 pageElem
= MakeEmptyDOM('notebookpage')
640 pageElem
.appendChild(elem
)
642 elif isinstance(parent
, xxxChoicebook
) and not isChildContainer
:
643 pageElem
= MakeEmptyDOM('choicebookpage')
644 pageElem
.appendChild(elem
)
646 elif isinstance(parent
, xxxListbook
) and not isChildContainer
:
647 pageElem
= MakeEmptyDOM('listbookpage')
648 pageElem
.appendChild(elem
)
650 # Insert new node, register undo
651 newItem
= tree
.InsertNode(parentLeaf
, parent
, elem
, nextItem
)
652 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
653 # Scroll to show new item (!!! redundant?)
654 tree
.EnsureVisible(newItem
)
655 tree
.SelectItem(newItem
)
656 if not tree
.IsVisible(newItem
):
657 tree
.ScrollTo(newItem
)
660 if g
.testWin
and tree
.IsHighlatable(newItem
):
662 tree
.needUpdate
= True
663 tree
.pendingHighLight
= newItem
665 tree
.pendingHighLight
= None
667 self
.SetStatusText('Pasted')
670 def ItemsAreCompatible(self
, parent
, child
):
671 # Check compatibility
673 # Comments are always compatible
674 if child
.__class
__ == xxxComment
:
677 if child
.__class
__ in [xxxDialog
, xxxFrame
, xxxWizard
]:
679 if parent
.__class
__ != xxxMainNode
: error
= True
680 elif child
.__class
__ == xxxMenuBar
:
681 # Menubar can be put in frame or dialog
682 if parent
.__class
__ not in [xxxMainNode
, xxxFrame
, xxxDialog
]: error
= True
683 elif child
.__class
__ == xxxToolBar
:
684 # Toolbar can be top-level of child of panel or frame
685 if parent
.__class
__ not in [xxxMainNode
, xxxPanel
, xxxFrame
] and \
686 not parent
.isSizer
: error
= True
687 elif child
.__class
__ == xxxPanel
and parent
.__class
__ == xxxMainNode
:
689 elif child
.__class
__ == xxxSpacer
:
690 if not parent
.isSizer
: error
= True
691 elif child
.__class
__ == xxxSeparator
:
692 if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error
= True
693 elif child
.__class
__ == xxxTool
:
694 if parent
.__class
__ != xxxToolBar
: error
= True
695 elif child
.__class
__ == xxxMenu
:
696 if not parent
.__class
__ in [xxxMainNode
, xxxMenuBar
, xxxMenu
]: error
= True
697 elif child
.__class
__ == xxxMenuItem
:
698 if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
699 elif child
.isSizer
and parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]:
701 else: # normal controls can be almost anywhere
702 if parent
.__class
__ == xxxMainNode
or \
703 parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
705 if parent
.__class
__ == xxxMainNode
: parentClass
= 'root'
706 else: parentClass
= parent
.className
707 wx
.LogError('Incompatible parent/child: parent is %s, child is %s!' %
708 (parentClass
, child
.className
))
712 def OnMoveUp(self
, evt
):
713 selected
= tree
.selection
714 if not selected
: return
716 index
= tree
.ItemIndex(selected
)
717 if index
== 0: return # No previous sibling found
719 # Remove highlight, update testWin
720 if g
.testWin
and g
.testWin
.highLight
:
721 g
.testWin
.highLight
.Remove()
722 tree
.needUpdate
= True
725 self
.lastOp
= 'MOVEUP'
726 status
= 'Moved before previous sibling'
732 parent
= tree
.GetItemParent(selected
)
733 elem
= tree
.RemoveLeaf(selected
)
734 nextItem
= tree
.GetFirstChild(parent
)[0]
735 for i
in range(index
- 1): nextItem
= tree
.GetNextSibling(nextItem
)
736 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
737 newIndex
= tree
.ItemIndex(selected
)
738 tree
.SelectItem(selected
)
740 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
743 self
.SetStatusText(status
)
747 def OnMoveDown(self
, evt
):
748 selected
= tree
.selection
749 if not selected
: return
751 index
= tree
.ItemIndex(selected
)
752 next
= tree
.GetNextSibling(selected
)
755 # Remove highlight, update testWin
756 if g
.testWin
and g
.testWin
.highLight
:
757 g
.testWin
.highLight
.Remove()
758 tree
.needUpdate
= True
761 self
.lastOp
= 'MOVEDOWN'
762 status
= 'Moved after next sibling'
768 parent
= tree
.GetItemParent(selected
)
769 elem
= tree
.RemoveLeaf(selected
)
770 nextItem
= tree
.GetFirstChild(parent
)[0]
771 for i
in range(index
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
772 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
773 newIndex
= tree
.ItemIndex(selected
)
774 tree
.SelectItem(selected
)
776 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
779 self
.SetStatusText(status
)
783 def OnMoveLeft(self
, evt
):
784 selected
= tree
.selection
785 if not selected
: return
787 oldParent
= tree
.GetItemParent(selected
)
788 if not oldParent
: return
789 pparent
= tree
.GetItemParent(oldParent
)
790 if not pparent
: return
792 # Check compatibility
793 if not self
.ItemsAreCompatible(tree
.GetPyData(pparent
).treeObject(), tree
.GetPyData(selected
).treeObject()): return
795 if g
.testWin
and g
.testWin
.highLight
:
796 g
.testWin
.highLight
.Remove()
797 tree
.needUpdate
= True
800 self
.lastOp
= 'MOVELEFT'
801 status
= 'Made next sibling of parent'
803 oldIndex
= tree
.ItemIndex(selected
)
804 elem
= tree
.RemoveLeaf(selected
)
805 nextItem
= tree
.GetFirstChild(pparent
)[0]
806 parentIndex
= tree
.ItemIndex(oldParent
)
807 for i
in range(parentIndex
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
809 # Check parent and child relationships.
810 # If parent is sizer or notebook, child is of wrong class or
811 # parent is normal window, child is child container then detach child.
812 parent
= tree
.GetPyData(pparent
).treeObject()
813 xxx
= MakeXXXFromDOM(parent
, elem
)
814 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
815 if isChildContainer
and \
816 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
817 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
818 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
819 elem
.removeChild(xxx
.child
.node
) # detach child
820 elem
.unlink() # delete child container
821 elem
= xxx
.child
.node
# replace
822 # This may help garbage collection
823 xxx
.child
.parent
= None
824 isChildContainer
= False
825 # Parent is sizer or notebook, child is not child container
826 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
827 # Create sizer item element
828 sizerItemElem
= MakeEmptyDOM('sizeritem')
829 sizerItemElem
.appendChild(elem
)
831 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
832 pageElem
= MakeEmptyDOM('notebookpage')
833 pageElem
.appendChild(elem
)
836 selected
= tree
.InsertNode(pparent
, tree
.GetPyData(pparent
).treeObject(), elem
, nextItem
)
837 newIndex
= tree
.ItemIndex(selected
)
838 tree
.SelectItem(selected
)
840 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, pparent
, newIndex
))
843 self
.SetStatusText(status
)
845 def OnMoveRight(self
, evt
):
846 selected
= tree
.selection
847 if not selected
: return
849 oldParent
= tree
.GetItemParent(selected
)
850 if not oldParent
: return
852 newParent
= tree
.GetPrevSibling(selected
)
853 if not newParent
: return
855 parent
= tree
.GetPyData(newParent
).treeObject()
857 # Check compatibility
858 if not self
.ItemsAreCompatible(parent
, tree
.GetPyData(selected
).treeObject()): return
860 # Remove highlight, update testWin
861 if g
.testWin
and g
.testWin
.highLight
:
862 g
.testWin
.highLight
.Remove()
863 tree
.needUpdate
= True
866 self
.lastOp
= 'MOVERIGHT'
867 status
= 'Made last child of previous sibling'
869 oldIndex
= tree
.ItemIndex(selected
)
870 elem
= tree
.RemoveLeaf(selected
)
872 # Check parent and child relationships.
873 # If parent is sizer or notebook, child is of wrong class or
874 # parent is normal window, child is child container then detach child.
875 xxx
= MakeXXXFromDOM(parent
, elem
)
876 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
877 if isChildContainer
and \
878 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
879 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
880 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
881 elem
.removeChild(xxx
.child
.node
) # detach child
882 elem
.unlink() # delete child container
883 elem
= xxx
.child
.node
# replace
884 # This may help garbage collection
885 xxx
.child
.parent
= None
886 isChildContainer
= False
887 # Parent is sizer or notebook, child is not child container
888 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
889 # Create sizer item element
890 sizerItemElem
= MakeEmptyDOM('sizeritem')
891 sizerItemElem
.appendChild(elem
)
893 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
894 pageElem
= MakeEmptyDOM('notebookpage')
895 pageElem
.appendChild(elem
)
898 selected
= tree
.InsertNode(newParent
, tree
.GetPyData(newParent
).treeObject(), elem
, wx
.TreeItemId())
900 newIndex
= tree
.ItemIndex(selected
)
901 tree
.SelectItem(selected
)
903 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, newParent
, newIndex
))
906 self
.SetStatusText(status
)
908 def OnCutDelete(self
, evt
):
909 selected
= tree
.selection
910 if not selected
: return # key pressed event
912 if evt
.GetId() == wx
.ID_CUT
:
914 status
= 'Removed to clipboard'
916 self
.lastOp
= 'DELETE'
920 # If deleting top-level item, delete testWin
921 if selected
== g
.testWin
.item
:
925 # Remove highlight, update testWin
926 if g
.testWin
.highLight
:
927 g
.testWin
.highLight
.Remove()
928 tree
.needUpdate
= True
931 index
= tree
.ItemFullIndex(selected
)
932 xxx
= tree
.GetPyData(selected
)
933 parent
= tree
.GetPyData(tree
.GetItemParent(selected
)).treeObject()
935 elem
= tree
.RemoveLeaf(selected
)
936 undoMan
.RegisterUndo(UndoCutDelete(index
, parent
, elem
))
937 if evt
.GetId() == wx
.ID_CUT
:
938 if wx
.TheClipboard
.Open():
940 data
= wx
.CustomDataObject('XRCED')
942 s
= elem
.toxml(encoding
=expat
.native_encoding
)
944 data
= wx
.CustomDataObject('XRCED_node')
946 data
.SetData(cPickle
.dumps(s
))
947 wx
.TheClipboard
.SetData(data
)
948 wx
.TheClipboard
.Close()
950 wx
.MessageBox("Unable to open the clipboard", "Error")
951 tree
.pendingHighLight
= None
955 self
.SetStatusText(status
)
957 def OnSubclass(self
, evt
):
958 selected
= tree
.selection
959 xxx
= tree
.GetPyData(selected
).treeObject()
961 subclass
= xxx
.subclass
962 dlg
= wx
.TextEntryDialog(self
, 'Subclass:', defaultValue
=subclass
)
963 if dlg
.ShowModal() == wx
.ID_OK
:
964 subclass
= dlg
.GetValue()
966 elem
.setAttribute('subclass', subclass
)
967 elif elem
.hasAttribute('subclass'):
968 elem
.removeAttribute('subclass')
970 xxx
.subclass
= elem
.getAttribute('subclass')
971 tree
.SetItemText(selected
, xxx
.treeName())
972 panel
.pages
[0].box
.SetLabel(xxx
.panelName())
975 def OnEmbedPanel(self
, evt
):
976 conf
.embedPanel
= evt
.IsChecked()
978 # Remember last dimentions
979 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
980 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
981 size
= self
.GetSize()
982 pos
= self
.GetPosition()
983 sizePanel
= panel
.GetSize()
984 panel
.Reparent(self
.splitter
)
985 self
.miniFrame
.GetSizer().Remove(panel
)
987 self
.SetDimensions(pos
.x
, pos
.y
, size
.width
+ sizePanel
.width
, size
.height
)
988 self
.splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
989 self
.miniFrame
.Show(False)
991 conf
.sashPos
= self
.splitter
.GetSashPosition()
992 pos
= self
.GetPosition()
993 size
= self
.GetSize()
994 sizePanel
= panel
.GetSize()
995 self
.splitter
.Unsplit(panel
)
996 sizer
= self
.miniFrame
.GetSizer()
997 panel
.Reparent(self
.miniFrame
)
999 sizer
.Add(panel
, 1, wx
.EXPAND
)
1000 self
.miniFrame
.Show(True)
1001 self
.miniFrame
.SetDimensions(conf
.panelX
, conf
.panelY
,
1002 conf
.panelWidth
, conf
.panelHeight
)
1003 self
.miniFrame
.Layout()
1005 self
.SetDimensions(pos
.x
, pos
.y
,
1006 max(size
.width
- sizePanel
.width
, self
.minWidth
), size
.height
)
1008 def OnShowTools(self
, evt
):
1009 conf
.showTools
= evt
.IsChecked()
1010 g
.tools
.Show(conf
.showTools
)
1012 self
.toolsSizer
.Prepend(g
.tools
, 0, wx
.EXPAND
)
1014 self
.toolsSizer
.Remove(g
.tools
)
1015 self
.toolsSizer
.Layout()
1017 def OnTest(self
, evt
):
1018 if not tree
.selection
: return # key pressed event
1019 tree
.ShowTestWindow(tree
.selection
)
1021 def OnTestHide(self
, evt
):
1022 tree
.CloseTestWindow()
1024 # Find object by relative position
1025 def FindObject(self
, item
, obj
):
1026 # We simply perform depth-first traversal, sinse it's too much
1027 # hassle to deal with all sizer/window combinations
1028 w
= tree
.FindNodeObject(item
)
1029 if w
== obj
or isinstance(w
, wx
.GBSizerItem
) and w
.GetWindow() == obj
:
1031 if tree
.ItemHasChildren(item
):
1032 child
= tree
.GetFirstChild(item
)[0]
1034 found
= self
.FindObject(child
, obj
)
1035 if found
: return found
1036 child
= tree
.GetNextSibling(child
)
1039 # Click event after locate activated
1040 def OnTestWinLeftDown(self
, evt
):
1041 # Restore normal event processing
1042 self
.SetHandler(g
.testWin
)
1043 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1044 item
= self
.FindObject(g
.testWin
.item
, evt
.GetEventObject())
1046 tree
.EnsureVisible(item
)
1047 tree
.SelectItem(item
)
1048 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, False)
1050 self
.SetStatusText('Selected %s' % tree
.GetItemText(item
))
1052 self
.SetStatusText('Locate failed!')
1054 def SetHandler(self
, w
, h
=None):
1056 w
.SetEventHandler(h
)
1057 w
.SetCursor(wx
.CROSS_CURSOR
)
1059 w
.SetEventHandler(w
)
1060 w
.SetCursor(wx
.NullCursor
)
1061 for ch
in w
.GetChildren():
1062 self
.SetHandler(ch
, h
)
1064 def OnLocate(self
, evt
):
1066 if evt
.GetId() == self
.ID_LOCATE
or \
1067 evt
.GetId() == self
.ID_TOOL_LOCATE
and evt
.IsChecked():
1068 self
.SetHandler(g
.testWin
, g
.testWin
)
1069 g
.testWin
.Connect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
, self
.OnTestWinLeftDown
)
1070 if evt
.GetId() == self
.ID_LOCATE
:
1071 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, True)
1072 elif evt
.GetId() == self
.ID_TOOL_LOCATE
and not evt
.IsChecked():
1073 self
.SetHandler(g
.testWin
, None)
1074 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1075 self
.SetStatusText('Click somewhere in your test window now')
1077 def OnRefresh(self
, evt
):
1078 # If modified, apply first
1079 selection
= tree
.selection
1081 xxx
= tree
.GetPyData(selection
)
1082 if xxx
and panel
.IsModified():
1083 tree
.Apply(xxx
, selection
)
1086 tree
.CreateTestWin(g
.testWin
.item
)
1087 panel
.modified
= False
1088 tree
.needUpdate
= False
1090 def OnAutoRefresh(self
, evt
):
1091 conf
.autoRefresh
= evt
.IsChecked()
1092 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1093 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1095 def OnAbout(self
, evt
):
1099 (c) Roman Rolinsky <rollrom@users.sourceforge.net>
1100 Homepage: http://xrced.sourceforge.net\
1102 dlg
= wx
.MessageDialog(self
, str, 'About XRCed', wx
.OK | wx
.CENTRE
)
1106 def OnReadme(self
, evt
):
1107 text
= open(os
.path
.join(basePath
, 'README.txt'), 'r').read()
1108 dlg
= ScrolledMessageDialog(self
, text
, "XRCed README")
1112 # Simple emulation of python command line
1113 def OnDebugCMD(self
, evt
):
1116 exec raw_input('C:\> ')
1121 (etype
, value
, tb
) =sys
.exc_info()
1122 tblist
=traceback
.extract_tb(tb
)[1:]
1123 msg
=' '.join(traceback
.format_exception_only(etype
, value
)
1124 +traceback
.format_list(tblist
))
1127 def OnCreate(self
, evt
):
1128 # Ignore fake events generated while dragging
1130 g
.tools
.drag
= False
1132 selected
= tree
.selection
1133 if tree
.ctrl
: appendChild
= False
1134 else: appendChild
= not tree
.NeedInsert(selected
)
1135 xxx
= tree
.GetPyData(selected
)
1139 # If has previous item, insert after it, else append to parent
1141 parentLeaf
= tree
.GetItemParent(selected
)
1143 # If has next item, insert, else append to parent
1144 nextItem
= tree
.GetNextSibling(selected
)
1145 parentLeaf
= tree
.GetItemParent(selected
)
1146 # Expanded container (must have children)
1147 elif tree
.shift
and tree
.IsExpanded(selected
) \
1148 and tree
.GetChildrenCount(selected
, False):
1149 nextItem
= tree
.GetFirstChild(selected
)[0]
1150 parentLeaf
= selected
1152 nextItem
= wx
.TreeItemId()
1153 parentLeaf
= selected
1154 parent
= tree
.GetPyData(parentLeaf
)
1155 if parent
.hasChild
: parent
= parent
.child
1157 self
.CreateXXX(parent
, parentLeaf
, nextItem
, evt
.GetId())
1159 # Actual method to create object and add to XML and wx trees
1160 def CreateXXX(self
, parent
, parentLeaf
, nextItem
, id):
1161 selected
= tree
.selection
1162 # Create object_ref?
1163 if id == ID_NEW
.REF
:
1164 ref
= wx
.GetTextFromUser('Create reference to:', 'Create reference')
1166 xxx
= MakeEmptyRefXXX(parent
, ref
)
1167 elif id == ID_NEW
.COMMENT
:
1168 xxx
= MakeEmptyCommentXXX(parent
)
1170 # Create empty element
1171 if id >= ID_NEW
.CUSTOM
:
1172 className
= pullDownMenu
.customMap
[id]
1174 className
= pullDownMenu
.createMap
[id]
1175 xxx
= MakeEmptyXXX(parent
, className
)
1177 # Insert new node, register undo
1178 if xxx
.isElement
: # true object
1179 # Set default name for top-level windows
1180 if parent
.__class
__ == xxxMainNode
:
1181 cl
= xxx
.treeObject().__class
__
1182 frame
.maxIDs
[cl
] += 1
1183 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1184 # And for some other standard controls
1185 elif parent
.__class
__ == xxxStdDialogButtonSizer
:
1186 # ... we can even set automatically tree name
1187 xxx
.setTreeName(pullDownMenu
.stdButtonIDs
[id][0])
1188 obj
= xxx
.treeObject()
1190 elem
= g
.tree
.dom
.createElement('label')
1191 elem
.appendChild(g
.tree
.dom
.createTextNode(pullDownMenu
.stdButtonIDs
[id][1]))
1192 obj
.params
['label'] = xxxParam(elem
)
1193 xxx
.treeObject().node
.appendChild(elem
)
1194 # Else, set label if exists to class name
1195 elif 'label' in xxx
.treeObject().allParams
:
1197 if label
[:2] == 'wx': label
= label
[2:]
1198 xxx
.treeObject().set('label', label
.upper())
1199 # For comment nodes, simply add node
1200 newItem
= tree
.InsertNode(parentLeaf
, parent
, xxx
.node
, nextItem
)
1201 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
1202 tree
.EnsureVisible(newItem
)
1203 tree
.SelectItem(newItem
)
1204 if not tree
.IsVisible(newItem
):
1205 tree
.ScrollTo(newItem
)
1208 if xxx
.isElement
and g
.testWin
and tree
.IsHighlatable(newItem
):
1209 if conf
.autoRefresh
:
1210 tree
.needUpdate
= True
1211 tree
.pendingHighLight
= newItem
1213 tree
.pendingHighLight
= None
1215 if not xxx
.isElement
:
1216 tree
.EditLabel(newItem
)
1220 # Replace one object with another
1221 def OnReplace(self
, evt
):
1222 selected
= tree
.selection
1223 xxx
= tree
.GetPyData(selected
).treeObject()
1225 parent
= elem
.parentNode
1226 undoMan
.RegisterUndo(UndoReplace(selected
))
1228 className
= pullDownMenu
.createMap
[evt
.GetId() - 1000]
1230 # Create temporary empty node (with default values)
1231 dummy
= MakeEmptyDOM(className
)
1232 if className
== 'spacer' and xxx
.className
!= 'spacer':
1234 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1235 klass
= xxxSizerItem
1237 klass
= xxxDict
[className
]
1238 # Remove non-compatible children
1239 if tree
.ItemHasChildren(selected
) and not klass
.hasChildren
:
1240 tree
.DeleteChildren(selected
)
1241 nodes
= elem
.childNodes
[:]
1244 if node
.nodeType
!= minidom
.Node
.ELEMENT_NODE
: continue
1248 if not klass
.hasChildren
: remove
= True
1249 elif tag
not in klass
.allParams
and \
1250 (not klass
.hasStyle
or tag
not in klass
.styles
):
1255 elem
.removeChild(node
)
1258 # Remove sizeritem child if spacer
1259 if className
== 'spacer' and xxx
.className
!= 'spacer':
1260 sizeritem
= elem
.parentNode
1261 assert sizeritem
.getAttribute('class') == 'sizeritem'
1262 sizeritem
.removeChild(elem
)
1265 tree
.GetPyData(selected
).hasChild
= False
1266 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1267 # Create sizeritem element
1268 assert xxx
.parent
.isSizer
1269 elem
.setAttribute('class', 'sizeritem')
1270 node
= MakeEmptyDOM(className
)
1271 elem
.appendChild(node
)
1272 # Replace to point to new object
1273 xxx
= xxxSizerItem(xxx
.parent
, elem
)
1275 tree
.SetPyData(selected
, xxx
)
1278 # Copy parameters present in dummy but not in elem
1279 for node
in dummy
.childNodes
:
1280 if node
.tagName
not in tags
: elem
.appendChild(node
.cloneNode(True))
1284 elem
.setAttribute('class', className
)
1285 if elem
.hasAttribute('subclass'):
1286 elem
.removeAttribute('subclass') # clear subclassing
1287 # Re-create xxx element
1288 xxx
= MakeXXXFromDOM(xxx
.parent
, elem
)
1289 # Remove incompatible style flags
1290 if 'style' in xxx
.params
:
1291 styles
= map(string
.strip
, xxx
.params
['style'].value().split('|'))
1292 newStyles
= [s
for s
in styles
if s
in klass
.winStyles
or s
in genericStyles
]
1293 if newStyles
!= styles
:
1295 value
= reduce(lambda a
,b
: a
+'|'+b
, newStyles
)
1298 xxx
.params
['style'].update(value
)
1300 # Update parent in child objects
1301 if tree
.ItemHasChildren(selected
):
1302 i
, cookie
= tree
.GetFirstChild(selected
)
1304 x
= tree
.GetPyData(i
)
1306 if x
.hasChild
: x
.child
.parent
= xxx
1307 i
, cookie
= tree
.GetNextChild(selected
, cookie
)
1310 if tree
.GetPyData(selected
).hasChild
: # child container
1311 container
= tree
.GetPyData(selected
)
1312 container
.resetChild(xxx
)
1315 tree
.SetPyData(selected
, xxx
)
1316 tree
.SetItemText(selected
, xxx
.treeName())
1317 tree
.SetItemImage(selected
, xxx
.treeImage())
1319 # Set default name for top-level windows
1320 if parent
.__class
__ == xxxMainNode
:
1321 cl
= xxx
.treeObject().__class
__
1322 frame
.maxIDs
[cl
] += 1
1323 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1326 g
.panel
.SetData(xxx
)
1330 #undoMan.RegisterUndo(UndoPasteCreate(parentLeaf, parent, newItem, selected))
1332 if g
.testWin
and tree
.IsHighlatable(selected
):
1333 if conf
.autoRefresh
:
1334 tree
.needUpdate
= True
1335 tree
.pendingHighLight
= selected
1337 tree
.pendingHighLight
= None
1341 # Expand/collapse subtree
1342 def OnExpand(self
, evt
):
1343 if tree
.selection
: tree
.ExpandAll(tree
.selection
)
1344 else: tree
.ExpandAll(tree
.root
)
1345 def OnCollapse(self
, evt
):
1346 if tree
.selection
: tree
.CollapseAll(tree
.selection
)
1347 else: tree
.CollapseAll(tree
.root
)
1349 def OnPullDownHighlight(self
, evt
):
1350 menuId
= evt
.GetMenuId()
1352 menu
= evt
.GetEventObject()
1354 help = menu
.GetHelpString(menuId
)
1355 self
.SetStatusText(help)
1357 self
.SetStatusText('')
1359 self
.SetStatusText('')
1361 def OnUpdateUI(self
, evt
):
1362 if evt
.GetId() in [wx
.ID_CUT
, wx
.ID_COPY
, self
.ID_DELETE
]:
1363 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1364 elif evt
.GetId() == wx
.ID_SAVE
:
1365 evt
.Enable(self
.modified
)
1366 elif evt
.GetId() in [wx
.ID_PASTE
, self
.ID_TOOL_PASTE
]:
1367 evt
.Enable(tree
.selection
is not None)
1368 elif evt
.GetId() == self
.ID_TEST
:
1369 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1370 elif evt
.GetId() in [self
.ID_LOCATE
, self
.ID_TOOL_LOCATE
]:
1371 evt
.Enable(g
.testWin
is not None)
1372 elif evt
.GetId() == wx
.ID_UNDO
: evt
.Enable(undoMan
.CanUndo())
1373 elif evt
.GetId() == wx
.ID_REDO
: evt
.Enable(undoMan
.CanRedo())
1375 def OnIdle(self
, evt
):
1376 if self
.inIdle
: return # Recursive call protection
1378 #print 'onidle',tree.needUpdate,tree.pendingHighLight
1381 if conf
.autoRefresh
:
1383 #self.SetStatusText('Refreshing test window...')
1385 tree
.CreateTestWin(g
.testWin
.item
)
1386 #self.SetStatusText('')
1387 tree
.needUpdate
= False
1388 elif tree
.pendingHighLight
:
1390 tree
.HighLight(tree
.pendingHighLight
)
1392 # Remove highlight if any problem
1393 if g
.testWin
and g
.testWin
.highLight
:
1394 g
.testWin
.highLight
.Remove()
1395 tree
.pendingHighLight
= None
1402 def OnIconize(self
, evt
):
1404 conf
.x
, conf
.y
= self
.GetPosition()
1405 conf
.width
, conf
.height
= self
.GetSize()
1407 conf
.sashPos
= self
.splitter
.GetSashPosition()
1409 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1410 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1411 self
.miniFrame
.Show(False)
1413 if not conf
.embedPanel
:
1414 self
.miniFrame
.Show(True)
1417 def OnCloseWindow(self
, evt
):
1418 if not self
.AskSave(): return
1419 if g
.testWin
: g
.testWin
.Destroy()
1420 if not panel
.GetPageCount() == 2:
1421 panel
.page2
.Destroy()
1423 # If we don't do this, page does not get destroyed (a bug?)
1425 if not self
.IsIconized():
1426 conf
.x
, conf
.y
= self
.GetPosition()
1427 if wx
.Platform
== '__WXMAC__':
1428 conf
.width
, conf
.height
= self
.GetClientSize()
1430 conf
.width
, conf
.height
= self
.GetSize()
1432 conf
.sashPos
= self
.splitter
.GetSashPosition()
1434 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1435 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1438 def CreateLocalConf(self
, path
):
1439 name
= os
.path
.splitext(path
)[0]
1441 return wx
.FileConfig(localFilename
=name
)
1445 conf
.localconf
= None
1447 self
.SetModified(False)
1453 # Numbers for new controls
1455 for cl
in [xxxPanel
, xxxDialog
, xxxFrame
,
1456 xxxMenuBar
, xxxMenu
, xxxToolBar
,
1457 xxxWizard
, xxxBitmap
, xxxIcon
]:
1459 # Restore handlers, menu, etc. to initial
1460 setHandlers(self
.handlers
[:])
1461 g
.pullDownMenu
.custom
= self
.custom
[:]
1462 # Remove modules imported from comment directives
1463 map(sys
.modules
.pop
, [m
for m
in sys
.modules
if m
not in self
.modules
])
1464 xxxParamComment
.locals = {} # clear local namespace
1465 xxxParamComment
.allow
= None # clear execution state
1467 def SetModified(self
, state
=True):
1468 self
.modified
= state
1469 name
= os
.path
.basename(self
.dataFile
)
1470 if not name
: name
= defaultName
1472 self
.SetTitle(progname
+ ': ' + name
+ ' *')
1474 self
.SetTitle(progname
+ ': ' + name
)
1476 def Open(self
, path
):
1477 if not os
.path
.exists(path
):
1478 wx
.LogError('File does not exists: %s' % path
)
1480 # Try to read the file
1484 dom
= minidom
.parse(f
)
1486 # Set encoding global variable and default encoding
1488 g
.currentEncoding
= dom
.encoding
1489 wx
.SetDefaultPyEncoding(g
.currentEncoding
.encode())
1491 g
.currentEncoding
= ''
1493 self
.dataFile
= path
= os
.path
.abspath(path
)
1494 dir = os
.path
.dirname(path
)
1495 if dir: os
.chdir(dir)
1496 # Allow importing modules from the same directory
1497 sys
.path
= sys_path
+ [dir]
1499 self
.SetTitle(progname
+ ': ' + os
.path
.basename(path
))
1500 conf
.localconf
= self
.CreateLocalConf(self
.dataFile
)
1502 # Nice exception printing
1503 inf
= sys
.exc_info()
1504 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1505 wx
.LogError('Error reading file: %s' % path
)
1510 def Indent(self
, node
, indent
= 0):
1511 if node
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1512 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1513 node
.parentNode
.insertBefore(text
, node
)
1514 return # no children
1515 # Copy child list because it will change soon
1516 children
= node
.childNodes
[:]
1517 # Main node doesn't need to be indented
1519 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1520 node
.parentNode
.insertBefore(text
, node
)
1522 # Append newline after last child, except for text nodes
1523 if children
[-1].nodeType
== minidom
.Node
.ELEMENT_NODE
:
1524 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1525 node
.appendChild(text
)
1526 # Indent children which are elements
1528 if n
.nodeType
== minidom
.Node
.ELEMENT_NODE
or \
1529 n
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1530 self
.Indent(n
, indent
+ 2)
1532 def Save(self
, path
):
1536 if tree
.selection
and panel
.IsModified():
1537 self
.OnRefresh(wx
.CommandEvent())
1538 if g
.currentEncoding
:
1539 f
= codecs
.open(path
, 'wt', g
.currentEncoding
)
1541 f
= codecs
.open(path
, 'wt')
1542 # Make temporary copy for formatting it
1543 # !!! We can't clone dom node, it works only once
1544 #self.domCopy = tree.dom.cloneNode(True)
1545 self
.domCopy
= MyDocument()
1546 mainNode
= self
.domCopy
.appendChild(tree
.mainNode
.cloneNode(True))
1547 # Remove first child (test element)
1548 testElem
= mainNode
.firstChild
1549 mainNode
.removeChild(testElem
)
1551 self
.Indent(mainNode
)
1552 self
.domCopy
.writexml(f
, encoding
= g
.currentEncoding
)
1554 self
.domCopy
.unlink()
1556 self
.SetModified(False)
1557 panel
.SetModified(False)
1558 conf
.localconf
.Flush()
1560 inf
= sys
.exc_info()
1561 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1562 wx
.LogError('Error writing file: %s' % path
)
1566 if not (self
.modified
or panel
.IsModified()): return True
1567 flags
= wx
.ICON_EXCLAMATION | wx
.YES_NO | wx
.CANCEL | wx
.CENTRE
1568 dlg
= wx
.MessageDialog( self
, 'File is modified. Save before exit?',
1569 'Save before too late?', flags
)
1570 say
= dlg
.ShowModal()
1573 if say
== wx
.ID_YES
:
1574 self
.OnSaveOrSaveAs(wx
.CommandEvent(wx
.ID_SAVE
))
1575 # If save was successful, modified flag is unset
1576 if not self
.modified
: return True
1577 elif say
== wx
.ID_NO
:
1578 self
.SetModified(False)
1579 panel
.SetModified(False)
1583 ################################################################################
1585 class PythonOptions(wx
.Dialog
):
1587 def __init__(self
, parent
, cfg
, dataFile
):
1588 pre
= wx
.PreDialog()
1589 g
.frame
.res
.LoadOnDialog(pre
, parent
, "PYTHON_OPTIONS")
1590 self
.PostCreate(pre
)
1593 self
.dataFile
= dataFile
1595 self
.AutoGenerateCB
= xrc
.XRCCTRL(self
, "AutoGenerateCB")
1596 self
.EmbedCB
= xrc
.XRCCTRL(self
, "EmbedCB")
1597 self
.GettextCB
= xrc
.XRCCTRL(self
, "GettextCB")
1598 self
.MakeXRSFileCB
= xrc
.XRCCTRL(self
, "MakeXRSFileCB")
1599 self
.FileNameTC
= xrc
.XRCCTRL(self
, "FileNameTC")
1600 self
.BrowseBtn
= xrc
.XRCCTRL(self
, "BrowseBtn")
1601 self
.GenerateBtn
= xrc
.XRCCTRL(self
, "GenerateBtn")
1602 self
.SaveOptsBtn
= xrc
.XRCCTRL(self
, "SaveOptsBtn")
1604 self
.Bind(wx
.EVT_BUTTON
, self
.OnBrowse
, self
.BrowseBtn
)
1605 self
.Bind(wx
.EVT_BUTTON
, self
.OnGenerate
, self
.GenerateBtn
)
1606 self
.Bind(wx
.EVT_BUTTON
, self
.OnSaveOpts
, self
.SaveOptsBtn
)
1608 if self
.cfg
.Read("filename", "") != "":
1609 self
.FileNameTC
.SetValue(self
.cfg
.Read("filename"))
1611 name
= os
.path
.splitext(os
.path
.split(dataFile
)[1])[0]
1613 self
.FileNameTC
.SetValue(name
)
1614 self
.AutoGenerateCB
.SetValue(self
.cfg
.ReadBool("autogenerate", False))
1615 self
.EmbedCB
.SetValue(self
.cfg
.ReadBool("embedResource", False))
1616 self
.MakeXRSFileCB
.SetValue(self
.cfg
.ReadBool("makeXRS", False))
1617 self
.GettextCB
.SetValue(self
.cfg
.ReadBool("genGettext", False))
1620 def OnBrowse(self
, evt
):
1621 path
= self
.FileNameTC
.GetValue()
1622 dirname
= os
.path
.abspath(os
.path
.dirname(path
))
1623 name
= os
.path
.split(path
)[1]
1624 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.py',
1625 wx
.SAVE | wx
.OVERWRITE_PROMPT
)
1626 if dlg
.ShowModal() == wx
.ID_OK
:
1627 path
= dlg
.GetPath()
1628 self
.FileNameTC
.SetValue(path
)
1632 def OnGenerate(self
, evt
):
1633 pypath
= self
.FileNameTC
.GetValue()
1634 embed
= self
.EmbedCB
.GetValue()
1635 genGettext
= self
.GettextCB
.GetValue()
1636 frame
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
1640 def OnSaveOpts(self
, evt
=None):
1641 self
.cfg
.Write("filename", self
.FileNameTC
.GetValue())
1642 self
.cfg
.WriteBool("autogenerate", self
.AutoGenerateCB
.GetValue())
1643 self
.cfg
.WriteBool("embedResource", self
.EmbedCB
.GetValue())
1644 self
.cfg
.WriteBool("makeXRS", self
.MakeXRSFileCB
.GetValue())
1645 self
.cfg
.WriteBool("genGettext", self
.GettextCB
.GetValue())
1647 self
.EndModal(wx
.ID_OK
)
1649 ################################################################################
1651 class PrefsDialog(wx
.Dialog
):
1653 def __init__(self
, parent
):
1654 pre
= wx
.PreDialog()
1655 g
.frame
.res
.LoadOnDialog(pre
, parent
, "DIALOG_PREFS")
1656 self
.PostCreate(pre
)
1657 self
.checkControls
= {} # map of check IDs to (control,dict,param)
1659 ##xxx = sys.modules['xxx']
1661 d
= xxx
.xxxSizerItem
.defaults_panel
1663 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_panel')
1664 id = self
.check_proportion_panel
.GetId()
1665 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1666 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_panel'),
1669 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_panel')
1670 id = self
.check_flag_panel
.GetId()
1671 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1672 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_panel'),
1675 d
= xxx
.xxxSizerItem
.defaults_control
1677 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_control')
1678 id = self
.check_proportion_panel
.GetId()
1679 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1680 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_control'),
1683 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_control')
1684 id = self
.check_flag_panel
.GetId()
1685 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1686 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_control'),
1689 for id,cdp
in self
.checkControls
.items():
1692 if isinstance(c
, wx
.SpinCtrl
):
1693 c
.SetValue(int(d
[p
]))
1696 self
.FindWindowById(id).SetValue(True)
1700 self
.radio_allow_exec
= xrc
.XRCCTRL(self
, 'radio_allow_exec')
1702 radio
= {'ask': 0, 'yes':1, 'no':2}
[g
.conf
.allowExec
]
1705 self
.radio_allow_exec
.SetSelection(radio
)
1707 def OnCheck(self
, evt
):
1708 self
.checkControls
[evt
.GetId()][0].Enable(evt
.IsChecked())
1711 ################################################################################
1713 # Parse string in form var1=val1[,var2=val2]* as dictionary
1714 def ReadDictFromString(s
):
1716 for vv
in s
.split(','):
1717 var
,val
= vv
.split(':')
1718 d
[var
.strip()] = val
1721 # Transform dictionary with strings into one string
1722 def DictToString(d
):
1723 return ','.join(map(':'.join
, d
.items()))
1726 print >> sys
.stderr
, 'usage: xrced [-dhiv] [file]'
1731 if wx
.VERSION
[:3] < MinWxVersion
:
1733 This version of XRCed may not work correctly on your version of wxWidgets. \
1734 Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion
)
1736 # Process comand-line
1739 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'dhiv')
1747 print 'XRCed version', version
1750 except getopt
.GetoptError
:
1751 if wx
.Platform
!= '__WXMAC__': # macs have some extra parameters
1752 print >> sys
.stderr
, 'Unknown option'
1756 self
.SetAppName('xrced')
1759 conf
= g
.conf
= wx
.Config(style
= wx
.CONFIG_USE_LOCAL_FILE
)
1760 conf
.localconf
= None
1761 conf
.autoRefresh
= conf
.ReadInt('autorefresh', True)
1762 pos
= conf
.ReadInt('x', -1), conf
.ReadInt('y', -1)
1763 size
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600)
1764 conf
.embedPanel
= conf
.ReadInt('embedPanel', True)
1765 conf
.showTools
= conf
.ReadInt('showTools', True)
1766 conf
.sashPos
= conf
.ReadInt('sashPos', 200)
1768 # read recently used files
1769 g
.fileHistory
= wx
.FileHistory()
1770 g
.fileHistory
.Load(conf
)
1772 if not conf
.embedPanel
:
1773 conf
.panelX
= conf
.ReadInt('panelX', -1)
1774 conf
.panelY
= conf
.ReadInt('panelY', -1)
1776 conf
.panelX
= conf
.panelY
= -1
1777 conf
.panelWidth
= conf
.ReadInt('panelWidth', 200)
1778 conf
.panelHeight
= conf
.ReadInt('panelHeight', 200)
1779 conf
.panic
= not conf
.HasEntry('nopanic')
1781 conf
.allowExec
= conf
.Read('Prefs/allowExec', 'ask')
1782 p
= 'Prefs/sizeritem_defaults_panel'
1784 if conf
.HasEntry(p
):
1785 ##sys.modules['xxx'].xxxSizerItem.defaults_panel = ReadDictFromString(conf.Read(p))
1786 xxx
.xxxSizerItem
.defaults_panel
= ReadDictFromString(conf
.Read(p
))
1787 p
= 'Prefs/sizeritem_defaults_control'
1788 if conf
.HasEntry(p
):
1789 ##sys.modules['xxx'].xxxSizerItem.defaults_control = ReadDictFromString(conf.Read(p))
1790 xxx
.xxxSizerItem
.defaults_control
= ReadDictFromString(conf
.Read(p
))
1793 wx
.FileSystem
.AddHandler(wx
.MemoryFSHandler())
1795 frame
= Frame(pos
, size
)
1796 # Mac does not set the correct size
1797 if wx
.Platform
== '__WXMAC__':
1798 frame
.SetClientSize(size
)
1802 plugins
= os
.getenv('XRCEDPATH')
1806 for dir in plugins
.split(':'):
1807 if os
.path
.isdir(dir) and \
1808 os
.path
.isfile(os
.path
.join(dir, '__init__.py')):
1810 dir = os
.path
.abspath(os
.path
.normpath(dir))
1811 sys
.path
= sys_path
+ [os
.path
.dirname(dir)]
1814 __import__(os
.path
.basename(dir), globals(), locals(), ['*'])
1816 print traceback
.print_exc()
1819 # Store important data
1820 frame
.handlers
= getHandlers()[:]
1821 frame
.custom
= g
.pullDownMenu
.custom
[:]
1822 frame
.modules
= sys
.modules
.copy()
1827 # Load file after showing
1830 frame
.open = frame
.Open(args
[0])
1838 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1839 wc
.WriteInt('x', conf
.x
)
1840 wc
.WriteInt('y', conf
.y
)
1841 wc
.WriteInt('width', conf
.width
)
1842 wc
.WriteInt('height', conf
.height
)
1843 wc
.WriteInt('embedPanel', conf
.embedPanel
)
1844 wc
.WriteInt('showTools', conf
.showTools
)
1845 if not conf
.embedPanel
:
1846 wc
.WriteInt('panelX', conf
.panelX
)
1847 wc
.WriteInt('panelY', conf
.panelY
)
1848 wc
.WriteInt('sashPos', conf
.sashPos
)
1849 wc
.WriteInt('panelWidth', conf
.panelWidth
)
1850 wc
.WriteInt('panelHeight', conf
.panelHeight
)
1851 wc
.WriteInt('nopanic', 1)
1852 g
.fileHistory
.Save(wc
)
1854 wc
.DeleteGroup('Prefs')
1855 wc
.Write('Prefs/allowExec', conf
.allowExec
)
1857 ##v = sys.modules['xxx'].xxxSizerItem.defaults_panel
1858 v
= xxx
.xxxSizerItem
.defaults_panel
1859 if v
: wc
.Write('Prefs/sizeritem_defaults_panel', DictToString(v
))
1860 ###v = sys.modules['xxx'].xxxSizerItem.defaults_control
1861 v
= xxx
.xxxSizerItem
.defaults_control
1862 if v
: wc
.Write('Prefs/sizeritem_defaults_control', DictToString(v
))
1867 app
= App(0, useBestVisual
=False)
1868 #app.SetAssertMode(wx.PYAPP_ASSERT_LOG)
1874 if __name__
== '__main__':