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
in ['__WXMAC__', '__WXMSW__']:
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
.getMoveUpBitmap(),
270 'Up', 'Move before previous sibling')
271 tb
.AddSimpleTool(self
.ID_MOVEDOWN
, images
.getMoveDownBitmap(),
272 'Down', 'Move after next sibling')
273 tb
.AddSimpleTool(self
.ID_MOVELEFT
, images
.getMoveLeftBitmap(),
274 'Make Sibling', 'Make sibling of parent')
275 tb
.AddSimpleTool(self
.ID_MOVERIGHT
, images
.getMoveRightBitmap(),
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_MOVEUP
, self
.OnUpdateUI
)
330 wx
.EVT_UPDATE_UI(self
, self
.ID_MOVEDOWN
, self
.OnUpdateUI
)
331 wx
.EVT_UPDATE_UI(self
, self
.ID_MOVELEFT
, self
.OnUpdateUI
)
332 wx
.EVT_UPDATE_UI(self
, self
.ID_MOVERIGHT
, self
.OnUpdateUI
)
333 wx
.EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
)
336 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
337 #sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND)
338 # Horizontal sizer for toolbar and splitter
339 self
.toolsSizer
= sizer1
= wx
.BoxSizer()
340 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.SP_3DSASH
)
341 self
.splitter
= splitter
342 splitter
.SetMinimumPaneSize(100)
345 g
.tree
= tree
= XML_Tree(splitter
, -1)
347 # Init pull-down menu data
349 g
.pullDownMenu
= pullDownMenu
= PullDownMenu(self
)
351 # Vertical toolbar for GUI buttons
352 g
.tools
= tools
= Tools(self
)
353 tools
.Show(conf
.showTools
)
354 if conf
.showTools
: sizer1
.Add(tools
, 0, wx
.EXPAND
)
356 tree
.RegisterKeyEvents()
358 # Miniframe for split mode
359 miniFrame
= wx
.MiniFrame(self
, -1, 'Properties & Style',
360 (conf
.panelX
, conf
.panelY
),
361 (conf
.panelWidth
, conf
.panelHeight
))
362 self
.miniFrame
= miniFrame
363 sizer2
= wx
.BoxSizer()
364 miniFrame
.SetSizer(sizer2
)
365 # Create panel for parameters
368 panel
= Panel(splitter
)
369 # Set plitter windows
370 splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
372 panel
= Panel(miniFrame
)
373 sizer2
.Add(panel
, 1, wx
.EXPAND
)
375 splitter
.Initialize(tree
)
376 if wx
.Platform
== '__WXMAC__':
377 sizer1
.Add(splitter
, 1, wx
.EXPAND|wx
.RIGHT
, 5)
379 sizer1
.Add(splitter
, 1, wx
.EXPAND
)
380 sizer
.Add(sizer1
, 1, wx
.EXPAND
)
381 self
.SetAutoLayout(True)
385 wx
.EVT_IDLE(self
, self
.OnIdle
)
386 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
387 wx
.EVT_KEY_DOWN(self
, tools
.OnKeyDown
)
388 wx
.EVT_KEY_UP(self
, tools
.OnKeyUp
)
389 wx
.EVT_ICONIZE(self
, self
.OnIconize
)
391 def OnRecentFile(self
,evt
):
392 # open recently used file
393 if not self
.AskSave(): return
396 # get the pathname based on the menu ID
397 fileNum
= evt
.GetId() - wx
.ID_FILE1
398 path
= g
.fileHistory
.GetHistoryFile(fileNum
)
401 self
.SetStatusText('Data loaded')
402 # add it back to the history so it will be moved up the list
403 self
.SaveRecent(path
)
405 self
.SetStatusText('Failed')
409 def OnNew(self
, evt
):
410 if not self
.AskSave(): return
413 def OnOpen(self
, evt
):
414 if not self
.AskSave(): return
415 dlg
= wx
.FileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
416 '', '*.xrc', wx
.OPEN | wx
.CHANGE_DIR
)
417 if dlg
.ShowModal() == wx
.ID_OK
:
419 self
.SetStatusText('Loading...')
423 self
.SetStatusText('Data loaded')
424 self
.SaveRecent(path
)
426 self
.SetStatusText('Failed')
431 def OnSaveOrSaveAs(self
, evt
):
432 if evt
.GetId() == wx
.ID_SAVEAS
or not self
.dataFile
:
433 if self
.dataFile
: name
= ''
434 else: name
= defaultName
435 dirname
= os
.path
.abspath(os
.path
.dirname(self
.dataFile
))
436 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.xrc',
437 wx
.SAVE | wx
.OVERWRITE_PROMPT | wx
.CHANGE_DIR
)
438 if dlg
.ShowModal() == wx
.ID_OK
:
440 if isinstance(path
, unicode):
441 path
= path
.encode(sys
.getfilesystemencoding())
448 # if we already have a localconf then it needs to be
449 # copied to a new config with the new name
451 nc
= self
.CreateLocalConf(path
)
452 flag
, key
, idx
= lc
.GetFirstEntry()
454 nc
.Write(key
, lc
.Read(key
))
455 flag
, key
, idx
= lc
.GetNextEntry(idx
)
458 # otherwise create a new one
459 conf
.localconf
= self
.CreateLocalConf(path
)
462 self
.SetStatusText('Saving...')
466 tmpFile
,tmpName
= tempfile
.mkstemp(prefix
='xrced-')
468 self
.Save(tmpName
) # save temporary file first
469 shutil
.move(tmpName
, path
)
471 self
.SetModified(False)
472 if conf
.localconf
.ReadBool("autogenerate", False):
473 pypath
= conf
.localconf
.Read("filename")
474 embed
= conf
.localconf
.ReadBool("embedResource", False)
475 genGettext
= conf
.localconf
.ReadBool("genGettext", False)
476 self
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
478 self
.SetStatusText('Data saved')
479 self
.SaveRecent(path
)
481 self
.SetStatusText('Failed')
485 def SaveRecent(self
,path
):
486 # append to recently used files
487 g
.fileHistory
.AddFileToHistory(path
)
489 def GeneratePython(self
, dataFile
, pypath
, embed
, genGettext
):
491 import wx
.tools
.pywxrc
492 rescomp
= wx
.tools
.pywxrc
.XmlResourceCompiler()
493 rescomp
.MakePythonModule([dataFile
], pypath
, embed
, genGettext
)
496 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
497 wx
.LogError('Error generating python code : %s' % pypath
)
501 def OnGeneratePython(self
, evt
):
502 if self
.modified
or not conf
.localconf
:
503 wx
.MessageBox("Save the XRC file first!", "Error")
506 dlg
= PythonOptions(self
, conf
.localconf
, self
.dataFile
)
510 def OnPrefs(self
, evt
):
511 dlg
= PrefsDialog(self
)
512 if dlg
.ShowModal() == wx
.ID_OK
:
513 # Fetch new preferences
514 for id,cdp
in dlg
.checkControls
.items():
516 if dlg
.FindWindowById(id).IsChecked():
517 d
[p
] = str(c
.GetValue())
518 elif p
in d
: del d
[p
]
519 g
.conf
.allowExec
= ('ask', 'yes', 'no')[dlg
.radio_allow_exec
.GetSelection()]
522 def OnExit(self
, evt
):
525 def OnUndo(self
, evt
):
526 # Extra check to not mess with idle updating
527 if undoMan
.CanUndo():
529 g
.panel
.SetModified(False)
530 if not undoMan
.CanUndo():
531 self
.SetModified(False)
533 def OnRedo(self
, evt
):
534 if undoMan
.CanRedo():
536 self
.SetModified(True)
538 def OnCopy(self
, evt
):
539 selected
= tree
.selection
540 if not selected
: return # key pressed event
541 xxx
= tree
.GetPyData(selected
)
542 if wx
.TheClipboard
.Open():
544 data
= wx
.CustomDataObject('XRCED')
545 # Set encoding in header
547 s
= xxx
.node
.toxml(encoding
=expat
.native_encoding
)
549 data
= wx
.CustomDataObject('XRCED_node')
551 data
.SetData(cPickle
.dumps(s
))
552 wx
.TheClipboard
.SetData(data
)
553 wx
.TheClipboard
.Close()
554 self
.SetStatusText('Copied')
556 wx
.MessageBox("Unable to open the clipboard", "Error")
558 def OnPaste(self
, evt
):
559 selected
= tree
.selection
560 if not selected
: return # key pressed event
561 # For pasting with Ctrl pressed
563 if evt
.GetId() == pullDownMenu
.ID_PASTE_SIBLING
: appendChild
= False
564 elif evt
.GetId() == self
.ID_TOOL_PASTE
:
565 if g
.tree
.ctrl
: appendChild
= False
566 else: appendChild
= not tree
.NeedInsert(selected
)
567 else: appendChild
= not tree
.NeedInsert(selected
)
568 xxx
= tree
.GetPyData(selected
)
570 # If has next item, insert, else append to parent
571 nextItem
= tree
.GetNextSibling(selected
)
572 parentLeaf
= tree
.GetItemParent(selected
)
573 # Expanded container (must have children)
574 elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, False):
575 # Insert as first child
576 nextItem
= tree
.GetFirstChild(selected
)[0]
577 parentLeaf
= selected
579 # No children or unexpanded item - appendChild stays True
580 nextItem
= wx
.TreeItemId() # no next item
581 parentLeaf
= selected
582 parent
= tree
.GetPyData(parentLeaf
).treeObject()
584 # Create a copy of clipboard pickled element
585 success
= success_node
= False
586 if wx
.TheClipboard
.Open():
588 data
= wx
.CustomDataObject('XRCED')
589 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
591 success
= wx
.TheClipboard
.GetData(data
)
593 # there is a problem if XRCED_node is in clipboard
594 # but previous SetData was for XRCED
596 if not success
: # try other format
597 data
= wx
.CustomDataObject('XRCED_node')
598 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
599 success_node
= wx
.TheClipboard
.GetData(data
)
601 wx
.TheClipboard
.Close()
603 if not success
and not success_node
:
605 "There is no data in the clipboard in the required format",
609 xml
= cPickle
.loads(data
.GetData()) # xml representation of element
611 elem
= minidom
.parseString(xml
).childNodes
[0]
613 elem
= g
.tree
.dom
.createComment(xml
)
615 # Tempopary xxx object to test things
616 xxx
= MakeXXXFromDOM(parent
, elem
)
618 # Check compatibility
619 if not self
.ItemsAreCompatible(parent
, xxx
.treeObject()): return
621 # Check parent and child relationships.
622 # If parent is sizer or notebook, child is of wrong class or
623 # parent is normal window, child is child container then detach child.
624 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
625 parentIsBook
= parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]
626 if isChildContainer
and \
627 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
628 (parentIsBook
and not isinstance(xxx
, xxxPage
)) or \
629 not (parent
.isSizer
or parentIsBook
)):
630 elem
.removeChild(xxx
.child
.node
) # detach child
631 elem
.unlink() # delete child container
632 elem
= xxx
.child
.node
# replace
633 # This may help garbage collection
634 xxx
.child
.parent
= None
635 isChildContainer
= False
636 # Parent is sizer or notebook, child is not child container
637 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
638 # Create sizer item element
639 sizerItemElem
= MakeEmptyDOM(parent
.itemTag
)
640 sizerItemElem
.appendChild(elem
)
642 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
643 pageElem
= MakeEmptyDOM('notebookpage')
644 pageElem
.appendChild(elem
)
646 elif isinstance(parent
, xxxChoicebook
) and not isChildContainer
:
647 pageElem
= MakeEmptyDOM('choicebookpage')
648 pageElem
.appendChild(elem
)
650 elif isinstance(parent
, xxxListbook
) and not isChildContainer
:
651 pageElem
= MakeEmptyDOM('listbookpage')
652 pageElem
.appendChild(elem
)
654 # Insert new node, register undo
655 newItem
= tree
.InsertNode(parentLeaf
, parent
, elem
, nextItem
)
656 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
657 # Scroll to show new item (!!! redundant?)
658 tree
.EnsureVisible(newItem
)
659 tree
.SelectItem(newItem
)
660 if not tree
.IsVisible(newItem
):
661 tree
.ScrollTo(newItem
)
664 if g
.testWin
and tree
.IsHighlatable(newItem
):
666 tree
.needUpdate
= True
667 tree
.pendingHighLight
= newItem
669 tree
.pendingHighLight
= None
671 self
.SetStatusText('Pasted')
674 def ItemsAreCompatible(self
, parent
, child
):
675 # Check compatibility
677 # Comments are always compatible
678 if child
.__class
__ == xxxComment
:
681 if child
.__class
__ in [xxxDialog
, xxxFrame
, xxxWizard
]:
683 if parent
.__class
__ != xxxMainNode
: error
= True
684 elif child
.__class
__ == xxxMenuBar
:
685 # Menubar can be put in frame or dialog
686 if parent
.__class
__ not in [xxxMainNode
, xxxFrame
, xxxDialog
]: error
= True
687 elif child
.__class
__ == xxxToolBar
:
688 # Toolbar can be top-level of child of panel or frame
689 if parent
.__class
__ not in [xxxMainNode
, xxxPanel
, xxxFrame
] and \
690 not parent
.isSizer
: error
= True
691 elif child
.__class
__ == xxxPanel
and parent
.__class
__ == xxxMainNode
:
693 elif child
.__class
__ == xxxSpacer
:
694 if not parent
.isSizer
: error
= True
695 elif child
.__class
__ == xxxSeparator
:
696 if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error
= True
697 elif child
.__class
__ == xxxTool
:
698 if parent
.__class
__ != xxxToolBar
: error
= True
699 elif child
.__class
__ == xxxMenu
:
700 if not parent
.__class
__ in [xxxMainNode
, xxxMenuBar
, xxxMenu
]: error
= True
701 elif child
.__class
__ == xxxMenuItem
:
702 if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
703 elif child
.isSizer
and parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]:
705 else: # normal controls can be almost anywhere
706 if parent
.__class
__ == xxxMainNode
or \
707 parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
709 if parent
.__class
__ == xxxMainNode
: parentClass
= 'root'
710 else: parentClass
= parent
.className
711 wx
.LogError('Incompatible parent/child: parent is %s, child is %s!' %
712 (parentClass
, child
.className
))
716 def OnMoveUp(self
, evt
):
717 selected
= tree
.selection
718 if not selected
: return
720 index
= tree
.ItemIndex(selected
)
721 if index
== 0: return # No previous sibling found
723 # Remove highlight, update testWin
724 if g
.testWin
and g
.testWin
.highLight
:
725 g
.testWin
.highLight
.Remove()
726 tree
.needUpdate
= True
729 self
.lastOp
= 'MOVEUP'
730 status
= 'Moved before previous sibling'
736 parent
= tree
.GetItemParent(selected
)
737 elem
= tree
.RemoveLeaf(selected
)
738 nextItem
= tree
.GetFirstChild(parent
)[0]
739 for i
in range(index
- 1): nextItem
= tree
.GetNextSibling(nextItem
)
740 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
741 newIndex
= tree
.ItemIndex(selected
)
742 tree
.SelectItem(selected
)
744 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
747 self
.SetStatusText(status
)
751 def OnMoveDown(self
, evt
):
752 selected
= tree
.selection
753 if not selected
: return
755 index
= tree
.ItemIndex(selected
)
756 next
= tree
.GetNextSibling(selected
)
759 # Remove highlight, update testWin
760 if g
.testWin
and g
.testWin
.highLight
:
761 g
.testWin
.highLight
.Remove()
762 tree
.needUpdate
= True
765 self
.lastOp
= 'MOVEDOWN'
766 status
= 'Moved after next sibling'
772 parent
= tree
.GetItemParent(selected
)
773 elem
= tree
.RemoveLeaf(selected
)
774 nextItem
= tree
.GetFirstChild(parent
)[0]
775 for i
in range(index
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
776 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
777 newIndex
= tree
.ItemIndex(selected
)
778 tree
.SelectItem(selected
)
780 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
783 self
.SetStatusText(status
)
787 def OnMoveLeft(self
, evt
):
788 selected
= tree
.selection
789 if not selected
: return
791 oldParent
= tree
.GetItemParent(selected
)
792 if not oldParent
: return
793 pparent
= tree
.GetItemParent(oldParent
)
794 if not pparent
: return
796 # Check compatibility
797 if not self
.ItemsAreCompatible(tree
.GetPyData(pparent
).treeObject(), tree
.GetPyData(selected
).treeObject()): return
799 if g
.testWin
and g
.testWin
.highLight
:
800 g
.testWin
.highLight
.Remove()
801 tree
.needUpdate
= True
804 self
.lastOp
= 'MOVELEFT'
805 status
= 'Made next sibling of parent'
807 oldIndex
= tree
.ItemIndex(selected
)
808 elem
= tree
.RemoveLeaf(selected
)
809 nextItem
= tree
.GetFirstChild(pparent
)[0]
810 parentIndex
= tree
.ItemIndex(oldParent
)
811 for i
in range(parentIndex
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
813 # Check parent and child relationships.
814 # If parent is sizer or notebook, child is of wrong class or
815 # parent is normal window, child is child container then detach child.
816 parent
= tree
.GetPyData(pparent
).treeObject()
817 xxx
= MakeXXXFromDOM(parent
, elem
)
818 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
819 if isChildContainer
and \
820 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
821 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
822 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
823 elem
.removeChild(xxx
.child
.node
) # detach child
824 elem
.unlink() # delete child container
825 elem
= xxx
.child
.node
# replace
826 # This may help garbage collection
827 xxx
.child
.parent
= None
828 isChildContainer
= False
829 # Parent is sizer or notebook, child is not child container
830 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
831 # Create sizer item element
832 sizerItemElem
= MakeEmptyDOM('sizeritem')
833 sizerItemElem
.appendChild(elem
)
835 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
836 pageElem
= MakeEmptyDOM('notebookpage')
837 pageElem
.appendChild(elem
)
840 selected
= tree
.InsertNode(pparent
, tree
.GetPyData(pparent
).treeObject(), elem
, nextItem
)
841 newIndex
= tree
.ItemIndex(selected
)
842 tree
.SelectItem(selected
)
844 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, pparent
, newIndex
))
847 self
.SetStatusText(status
)
849 def OnMoveRight(self
, evt
):
850 selected
= tree
.selection
851 if not selected
: return
853 oldParent
= tree
.GetItemParent(selected
)
854 if not oldParent
: return
856 newParent
= tree
.GetPrevSibling(selected
)
857 if not newParent
: return
859 parent
= tree
.GetPyData(newParent
).treeObject()
861 # Check compatibility
862 if not self
.ItemsAreCompatible(parent
, tree
.GetPyData(selected
).treeObject()): return
864 # Remove highlight, update testWin
865 if g
.testWin
and g
.testWin
.highLight
:
866 g
.testWin
.highLight
.Remove()
867 tree
.needUpdate
= True
870 self
.lastOp
= 'MOVERIGHT'
871 status
= 'Made last child of previous sibling'
873 oldIndex
= tree
.ItemIndex(selected
)
874 elem
= tree
.RemoveLeaf(selected
)
876 # Check parent and child relationships.
877 # If parent is sizer or notebook, child is of wrong class or
878 # parent is normal window, child is child container then detach child.
879 xxx
= MakeXXXFromDOM(parent
, elem
)
880 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
881 if isChildContainer
and \
882 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
883 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
884 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
885 elem
.removeChild(xxx
.child
.node
) # detach child
886 elem
.unlink() # delete child container
887 elem
= xxx
.child
.node
# replace
888 # This may help garbage collection
889 xxx
.child
.parent
= None
890 isChildContainer
= False
891 # Parent is sizer or notebook, child is not child container
892 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
893 # Create sizer item element
894 sizerItemElem
= MakeEmptyDOM('sizeritem')
895 sizerItemElem
.appendChild(elem
)
897 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
898 pageElem
= MakeEmptyDOM('notebookpage')
899 pageElem
.appendChild(elem
)
902 selected
= tree
.InsertNode(newParent
, tree
.GetPyData(newParent
).treeObject(), elem
, wx
.TreeItemId())
904 newIndex
= tree
.ItemIndex(selected
)
905 tree
.SelectItem(selected
)
907 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, newParent
, newIndex
))
910 self
.SetStatusText(status
)
912 def OnCutDelete(self
, evt
):
913 selected
= tree
.selection
914 if not selected
: return # key pressed event
916 if evt
.GetId() == wx
.ID_CUT
:
918 status
= 'Removed to clipboard'
920 self
.lastOp
= 'DELETE'
924 # If deleting top-level item, delete testWin
925 if selected
== g
.testWin
.item
:
929 # Remove highlight, update testWin
930 if g
.testWin
.highLight
:
931 g
.testWin
.highLight
.Remove()
932 tree
.needUpdate
= True
935 index
= tree
.ItemFullIndex(selected
)
936 xxx
= tree
.GetPyData(selected
)
937 parent
= tree
.GetPyData(tree
.GetItemParent(selected
)).treeObject()
939 elem
= tree
.RemoveLeaf(selected
)
940 undoMan
.RegisterUndo(UndoCutDelete(index
, parent
, elem
))
941 if evt
.GetId() == wx
.ID_CUT
:
942 if wx
.TheClipboard
.Open():
944 data
= wx
.CustomDataObject('XRCED')
946 s
= elem
.toxml(encoding
=expat
.native_encoding
)
948 data
= wx
.CustomDataObject('XRCED_node')
950 data
.SetData(cPickle
.dumps(s
))
951 wx
.TheClipboard
.SetData(data
)
952 wx
.TheClipboard
.Close()
954 wx
.MessageBox("Unable to open the clipboard", "Error")
955 tree
.pendingHighLight
= None
959 self
.SetStatusText(status
)
961 def OnSubclass(self
, evt
):
962 selected
= tree
.selection
963 xxx
= tree
.GetPyData(selected
).treeObject()
965 subclass
= xxx
.subclass
966 dlg
= wx
.TextEntryDialog(self
, 'Subclass:', defaultValue
=subclass
)
967 if dlg
.ShowModal() == wx
.ID_OK
:
968 subclass
= dlg
.GetValue()
970 elem
.setAttribute('subclass', subclass
)
971 elif elem
.hasAttribute('subclass'):
972 elem
.removeAttribute('subclass')
974 xxx
.subclass
= elem
.getAttribute('subclass')
975 tree
.SetItemText(selected
, xxx
.treeName())
976 panel
.pages
[0].box
.SetLabel(xxx
.panelName())
979 def OnEmbedPanel(self
, evt
):
980 conf
.embedPanel
= evt
.IsChecked()
982 # Remember last dimentions
983 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
984 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
985 size
= self
.GetSize()
986 pos
= self
.GetPosition()
987 sizePanel
= panel
.GetSize()
988 panel
.Reparent(self
.splitter
)
989 self
.miniFrame
.GetSizer().Remove(panel
)
991 self
.SetDimensions(pos
.x
, pos
.y
, size
.width
+ sizePanel
.width
, size
.height
)
992 self
.splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
993 self
.miniFrame
.Show(False)
995 conf
.sashPos
= self
.splitter
.GetSashPosition()
996 pos
= self
.GetPosition()
997 size
= self
.GetSize()
998 sizePanel
= panel
.GetSize()
999 self
.splitter
.Unsplit(panel
)
1000 sizer
= self
.miniFrame
.GetSizer()
1001 panel
.Reparent(self
.miniFrame
)
1003 sizer
.Add(panel
, 1, wx
.EXPAND
)
1004 self
.miniFrame
.Show(True)
1005 self
.miniFrame
.SetDimensions(conf
.panelX
, conf
.panelY
,
1006 conf
.panelWidth
, conf
.panelHeight
)
1007 self
.miniFrame
.Layout()
1009 self
.SetDimensions(pos
.x
, pos
.y
,
1010 max(size
.width
- sizePanel
.width
, self
.minWidth
), size
.height
)
1012 def OnShowTools(self
, evt
):
1013 conf
.showTools
= evt
.IsChecked()
1014 g
.tools
.Show(conf
.showTools
)
1016 self
.toolsSizer
.Prepend(g
.tools
, 0, wx
.EXPAND
)
1018 self
.toolsSizer
.Remove(g
.tools
)
1019 self
.toolsSizer
.Layout()
1021 def OnTest(self
, evt
):
1022 if not tree
.selection
: return # key pressed event
1023 tree
.ShowTestWindow(tree
.selection
)
1025 def OnTestHide(self
, evt
):
1026 tree
.CloseTestWindow()
1028 # Find object by relative position
1029 def FindObject(self
, item
, obj
):
1030 # We simply perform depth-first traversal, sinse it's too much
1031 # hassle to deal with all sizer/window combinations
1032 w
= tree
.FindNodeObject(item
)
1033 if w
== obj
or isinstance(w
, wx
.GBSizerItem
) and w
.GetWindow() == obj
:
1035 if tree
.ItemHasChildren(item
):
1036 child
= tree
.GetFirstChild(item
)[0]
1038 found
= self
.FindObject(child
, obj
)
1039 if found
: return found
1040 child
= tree
.GetNextSibling(child
)
1043 # Click event after locate activated
1044 def OnTestWinLeftDown(self
, evt
):
1045 # Restore normal event processing
1046 self
.SetHandler(g
.testWin
)
1047 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1048 item
= self
.FindObject(g
.testWin
.item
, evt
.GetEventObject())
1050 tree
.EnsureVisible(item
)
1051 tree
.SelectItem(item
)
1052 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, False)
1054 self
.SetStatusText('Selected %s' % tree
.GetItemText(item
))
1056 self
.SetStatusText('Locate failed!')
1058 def SetHandler(self
, w
, h
=None):
1060 w
.SetEventHandler(h
)
1061 w
.SetCursor(wx
.CROSS_CURSOR
)
1063 w
.SetEventHandler(w
)
1064 w
.SetCursor(wx
.NullCursor
)
1065 for ch
in w
.GetChildren():
1066 self
.SetHandler(ch
, h
)
1068 def OnLocate(self
, evt
):
1070 if evt
.GetId() == self
.ID_LOCATE
or \
1071 evt
.GetId() == self
.ID_TOOL_LOCATE
and evt
.IsChecked():
1072 self
.SetHandler(g
.testWin
, g
.testWin
)
1073 g
.testWin
.Connect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
, self
.OnTestWinLeftDown
)
1074 if evt
.GetId() == self
.ID_LOCATE
:
1075 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, True)
1076 elif evt
.GetId() == self
.ID_TOOL_LOCATE
and not evt
.IsChecked():
1077 self
.SetHandler(g
.testWin
, None)
1078 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1079 self
.SetStatusText('Click somewhere in your test window now')
1081 def OnRefresh(self
, evt
):
1082 # If modified, apply first
1083 selection
= tree
.selection
1085 xxx
= tree
.GetPyData(selection
)
1086 if xxx
and panel
.IsModified():
1087 tree
.Apply(xxx
, selection
)
1090 tree
.CreateTestWin(g
.testWin
.item
)
1091 panel
.modified
= False
1092 tree
.needUpdate
= False
1094 def OnAutoRefresh(self
, evt
):
1095 conf
.autoRefresh
= evt
.IsChecked()
1096 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1097 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1099 def OnAbout(self
, evt
):
1103 (c) Roman Rolinsky <rollrom@users.sourceforge.net>
1104 Homepage: http://xrced.sourceforge.net\
1106 dlg
= wx
.MessageDialog(self
, str, 'About XRCed', wx
.OK | wx
.CENTRE
)
1110 def OnReadme(self
, evt
):
1111 text
= open(os
.path
.join(basePath
, 'README.txt'), 'r').read()
1112 dlg
= ScrolledMessageDialog(self
, text
, "XRCed README")
1116 # Simple emulation of python command line
1117 def OnDebugCMD(self
, evt
):
1120 exec raw_input('C:\> ')
1125 (etype
, value
, tb
) =sys
.exc_info()
1126 tblist
=traceback
.extract_tb(tb
)[1:]
1127 msg
=' '.join(traceback
.format_exception_only(etype
, value
)
1128 +traceback
.format_list(tblist
))
1131 def OnCreate(self
, evt
):
1132 # Ignore fake events generated while dragging
1134 g
.tools
.drag
= False
1136 selected
= tree
.selection
1137 if tree
.ctrl
: appendChild
= False
1138 else: appendChild
= not tree
.NeedInsert(selected
)
1139 xxx
= tree
.GetPyData(selected
)
1143 # If has previous item, insert after it, else append to parent
1145 parentLeaf
= tree
.GetItemParent(selected
)
1147 # If has next item, insert, else append to parent
1148 nextItem
= tree
.GetNextSibling(selected
)
1149 parentLeaf
= tree
.GetItemParent(selected
)
1150 # Expanded container (must have children)
1151 elif tree
.shift
and tree
.IsExpanded(selected
) \
1152 and tree
.GetChildrenCount(selected
, False):
1153 nextItem
= tree
.GetFirstChild(selected
)[0]
1154 parentLeaf
= selected
1156 nextItem
= wx
.TreeItemId()
1157 parentLeaf
= selected
1158 parent
= tree
.GetPyData(parentLeaf
)
1159 if parent
.hasChild
: parent
= parent
.child
1161 self
.CreateXXX(parent
, parentLeaf
, nextItem
, evt
.GetId())
1163 # Actual method to create object and add to XML and wx trees
1164 def CreateXXX(self
, parent
, parentLeaf
, nextItem
, id):
1165 selected
= tree
.selection
1166 # Create object_ref?
1167 if id == ID_NEW
.REF
:
1168 ref
= wx
.GetTextFromUser('Create reference to:', 'Create reference')
1170 xxx
= MakeEmptyRefXXX(parent
, ref
)
1171 elif id == ID_NEW
.COMMENT
:
1172 xxx
= MakeEmptyCommentXXX(parent
)
1174 # Create empty element
1175 if id >= ID_NEW
.CUSTOM
:
1176 className
= pullDownMenu
.customMap
[id]
1178 className
= pullDownMenu
.createMap
[id]
1179 xxx
= MakeEmptyXXX(parent
, className
)
1181 # Insert new node, register undo
1182 if xxx
.isElement
: # true object
1183 # Set default name for top-level windows
1184 if parent
.__class
__ == xxxMainNode
:
1185 cl
= xxx
.treeObject().__class
__
1186 frame
.maxIDs
[cl
] += 1
1187 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1188 # And for some other standard controls
1189 elif parent
.__class
__ == xxxStdDialogButtonSizer
:
1190 # ... we can even set automatically tree name
1191 xxx
.setTreeName(pullDownMenu
.stdButtonIDs
[id][0])
1192 obj
= xxx
.treeObject()
1194 elem
= g
.tree
.dom
.createElement('label')
1195 elem
.appendChild(g
.tree
.dom
.createTextNode(pullDownMenu
.stdButtonIDs
[id][1]))
1196 obj
.params
['label'] = xxxParam(elem
)
1197 xxx
.treeObject().node
.appendChild(elem
)
1198 # Else, set label if exists to class name
1199 elif 'label' in xxx
.treeObject().allParams
:
1201 if label
[:2] == 'wx': label
= label
[2:]
1202 xxx
.treeObject().set('label', label
.upper())
1203 # For comment nodes, simply add node
1204 newItem
= tree
.InsertNode(parentLeaf
, parent
, xxx
.node
, nextItem
)
1205 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
1206 tree
.EnsureVisible(newItem
)
1207 tree
.SelectItem(newItem
)
1208 if not tree
.IsVisible(newItem
):
1209 tree
.ScrollTo(newItem
)
1212 if xxx
.isElement
and g
.testWin
and tree
.IsHighlatable(newItem
):
1213 if conf
.autoRefresh
:
1214 tree
.needUpdate
= True
1215 tree
.pendingHighLight
= newItem
1217 tree
.pendingHighLight
= None
1219 if not xxx
.isElement
:
1220 tree
.EditLabel(newItem
)
1224 # Replace one object with another
1225 def OnReplace(self
, evt
):
1226 selected
= tree
.selection
1227 xxx
= tree
.GetPyData(selected
).treeObject()
1229 parent
= elem
.parentNode
1230 undoMan
.RegisterUndo(UndoReplace(selected
))
1232 className
= pullDownMenu
.createMap
[evt
.GetId() - 1000]
1234 # Create temporary empty node (with default values)
1235 dummy
= MakeEmptyDOM(className
)
1236 if className
== 'spacer' and xxx
.className
!= 'spacer':
1238 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1239 klass
= xxxSizerItem
1241 klass
= xxxDict
[className
]
1242 # Remove non-compatible children
1243 if tree
.ItemHasChildren(selected
) and not klass
.hasChildren
:
1244 tree
.DeleteChildren(selected
)
1245 nodes
= elem
.childNodes
[:]
1248 if node
.nodeType
!= minidom
.Node
.ELEMENT_NODE
: continue
1252 if not klass
.hasChildren
: remove
= True
1253 elif tag
not in klass
.allParams
and \
1254 (not klass
.hasStyle
or tag
not in klass
.styles
):
1259 elem
.removeChild(node
)
1262 # Remove sizeritem child if spacer
1263 if className
== 'spacer' and xxx
.className
!= 'spacer':
1264 sizeritem
= elem
.parentNode
1265 assert sizeritem
.getAttribute('class') == 'sizeritem'
1266 sizeritem
.removeChild(elem
)
1269 tree
.GetPyData(selected
).hasChild
= False
1270 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1271 # Create sizeritem element
1272 assert xxx
.parent
.isSizer
1273 elem
.setAttribute('class', 'sizeritem')
1274 node
= MakeEmptyDOM(className
)
1275 elem
.appendChild(node
)
1276 # Replace to point to new object
1277 xxx
= xxxSizerItem(xxx
.parent
, elem
)
1279 tree
.SetPyData(selected
, xxx
)
1282 # Copy parameters present in dummy but not in elem
1283 for node
in dummy
.childNodes
:
1284 if node
.tagName
not in tags
: elem
.appendChild(node
.cloneNode(True))
1288 elem
.setAttribute('class', className
)
1289 if elem
.hasAttribute('subclass'):
1290 elem
.removeAttribute('subclass') # clear subclassing
1291 # Re-create xxx element
1292 xxx
= MakeXXXFromDOM(xxx
.parent
, elem
)
1293 # Remove incompatible style flags
1294 if 'style' in xxx
.params
:
1295 styles
= map(string
.strip
, xxx
.params
['style'].value().split('|'))
1296 newStyles
= [s
for s
in styles
if s
in klass
.winStyles
or s
in genericStyles
]
1297 if newStyles
!= styles
:
1299 value
= reduce(lambda a
,b
: a
+'|'+b
, newStyles
)
1302 xxx
.params
['style'].update(value
)
1304 # Update parent in child objects
1305 if tree
.ItemHasChildren(selected
):
1306 i
, cookie
= tree
.GetFirstChild(selected
)
1308 x
= tree
.GetPyData(i
)
1310 if x
.hasChild
: x
.child
.parent
= xxx
1311 i
, cookie
= tree
.GetNextChild(selected
, cookie
)
1314 if tree
.GetPyData(selected
).hasChild
: # child container
1315 container
= tree
.GetPyData(selected
)
1316 container
.resetChild(xxx
)
1319 tree
.SetPyData(selected
, xxx
)
1320 tree
.SetItemText(selected
, xxx
.treeName())
1321 tree
.SetItemImage(selected
, xxx
.treeImage())
1323 # Set default name for top-level windows
1324 if parent
.__class
__ == xxxMainNode
:
1325 cl
= xxx
.treeObject().__class
__
1326 frame
.maxIDs
[cl
] += 1
1327 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1330 g
.panel
.SetData(xxx
)
1334 #undoMan.RegisterUndo(UndoPasteCreate(parentLeaf, parent, newItem, selected))
1336 if g
.testWin
and tree
.IsHighlatable(selected
):
1337 if conf
.autoRefresh
:
1338 tree
.needUpdate
= True
1339 tree
.pendingHighLight
= selected
1341 tree
.pendingHighLight
= None
1345 # Expand/collapse subtree
1346 def OnExpand(self
, evt
):
1347 if tree
.selection
: tree
.ExpandAll(tree
.selection
)
1348 else: tree
.ExpandAll(tree
.root
)
1349 def OnCollapse(self
, evt
):
1350 if tree
.selection
: tree
.CollapseAll(tree
.selection
)
1351 else: tree
.CollapseAll(tree
.root
)
1353 def OnPullDownHighlight(self
, evt
):
1354 menuId
= evt
.GetMenuId()
1356 menu
= evt
.GetEventObject()
1358 help = menu
.GetHelpString(menuId
)
1359 self
.SetStatusText(help)
1361 self
.SetStatusText('')
1363 self
.SetStatusText('')
1365 def OnUpdateUI(self
, evt
):
1366 if evt
.GetId() in [wx
.ID_CUT
, wx
.ID_COPY
, self
.ID_DELETE
]:
1367 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1368 elif evt
.GetId() == wx
.ID_SAVE
:
1369 evt
.Enable(self
.modified
)
1370 elif evt
.GetId() in [wx
.ID_PASTE
, self
.ID_TOOL_PASTE
]:
1371 evt
.Enable(tree
.selection
is not None)
1372 elif evt
.GetId() in [self
.ID_TEST
,
1373 self
.ID_MOVEUP
, self
.ID_MOVEDOWN
,
1374 self
.ID_MOVELEFT
, self
.ID_MOVERIGHT
]:
1375 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1376 elif evt
.GetId() in [self
.ID_LOCATE
, self
.ID_TOOL_LOCATE
,
1378 evt
.Enable(g
.testWin
is not None)
1379 elif evt
.GetId() == wx
.ID_UNDO
: evt
.Enable(undoMan
.CanUndo())
1380 elif evt
.GetId() == wx
.ID_REDO
: evt
.Enable(undoMan
.CanRedo())
1382 def OnIdle(self
, evt
):
1383 if self
.inIdle
: return # Recursive call protection
1385 #print 'onidle',tree.needUpdate,tree.pendingHighLight
1388 if conf
.autoRefresh
:
1390 #self.SetStatusText('Refreshing test window...')
1392 tree
.CreateTestWin(g
.testWin
.item
)
1393 #self.SetStatusText('')
1394 tree
.needUpdate
= False
1395 elif tree
.pendingHighLight
:
1397 tree
.HighLight(tree
.pendingHighLight
)
1399 # Remove highlight if any problem
1400 if g
.testWin
and g
.testWin
.highLight
:
1401 g
.testWin
.highLight
.Remove()
1402 tree
.pendingHighLight
= None
1409 def OnIconize(self
, evt
):
1411 conf
.x
, conf
.y
= self
.GetPosition()
1412 conf
.width
, conf
.height
= self
.GetSize()
1414 conf
.sashPos
= self
.splitter
.GetSashPosition()
1416 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1417 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1418 self
.miniFrame
.Show(False)
1420 if not conf
.embedPanel
:
1421 self
.miniFrame
.Show(True)
1424 def OnCloseWindow(self
, evt
):
1425 if not self
.AskSave(): return
1426 if g
.testWin
: g
.testWin
.Destroy()
1427 if not panel
.GetPageCount() == 2:
1428 panel
.page2
.Destroy()
1430 # If we don't do this, page does not get destroyed (a bug?)
1432 if not self
.IsIconized():
1433 conf
.x
, conf
.y
= self
.GetPosition()
1434 if wx
.Platform
== '__WXMAC__':
1435 conf
.width
, conf
.height
= self
.GetClientSize()
1437 conf
.width
, conf
.height
= self
.GetSize()
1439 conf
.sashPos
= self
.splitter
.GetSashPosition()
1441 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1442 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1445 def CreateLocalConf(self
, path
):
1446 name
= os
.path
.splitext(path
)[0]
1448 return wx
.FileConfig(localFilename
=name
)
1452 conf
.localconf
= None
1454 self
.SetModified(False)
1460 # Numbers for new controls
1462 for cl
in [xxxPanel
, xxxDialog
, xxxFrame
,
1463 xxxMenuBar
, xxxMenu
, xxxToolBar
,
1464 xxxWizard
, xxxBitmap
, xxxIcon
]:
1466 # Restore handlers, menu, etc. to initial
1467 setHandlers(self
.handlers
[:])
1468 g
.pullDownMenu
.custom
= self
.custom
[:]
1469 # Remove modules imported from comment directives
1470 map(sys
.modules
.pop
, [m
for m
in sys
.modules
if m
not in self
.modules
])
1471 xxxParamComment
.locals = {} # clear local namespace
1472 xxxParamComment
.allow
= None # clear execution state
1474 def SetModified(self
, state
=True):
1475 self
.modified
= state
1476 name
= os
.path
.basename(self
.dataFile
)
1477 if not name
: name
= defaultName
1479 self
.SetTitle(progname
+ ': ' + name
+ ' *')
1481 self
.SetTitle(progname
+ ': ' + name
)
1483 def Open(self
, path
):
1484 if not os
.path
.exists(path
):
1485 wx
.LogError('File does not exists: %s' % path
)
1487 # Try to read the file
1491 dom
= minidom
.parse(f
)
1493 # Set encoding global variable and default encoding
1495 g
.currentEncoding
= dom
.encoding
1496 wx
.SetDefaultPyEncoding(g
.currentEncoding
.encode())
1498 g
.currentEncoding
= ''
1500 self
.dataFile
= path
= os
.path
.abspath(path
)
1501 dir = os
.path
.dirname(path
)
1502 if dir: os
.chdir(dir)
1503 # Allow importing modules from the same directory
1504 sys
.path
= sys_path
+ [dir]
1506 self
.SetTitle(progname
+ ': ' + os
.path
.basename(path
))
1507 conf
.localconf
= self
.CreateLocalConf(self
.dataFile
)
1509 # Nice exception printing
1510 inf
= sys
.exc_info()
1511 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1512 wx
.LogError('Error reading file: %s' % path
)
1517 def Indent(self
, node
, indent
= 0):
1518 if node
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1519 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1520 node
.parentNode
.insertBefore(text
, node
)
1521 return # no children
1522 # Copy child list because it will change soon
1523 children
= node
.childNodes
[:]
1524 # Main node doesn't need to be indented
1526 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1527 node
.parentNode
.insertBefore(text
, node
)
1529 # Append newline after last child, except for text nodes
1530 if children
[-1].nodeType
== minidom
.Node
.ELEMENT_NODE
:
1531 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1532 node
.appendChild(text
)
1533 # Indent children which are elements
1535 if n
.nodeType
== minidom
.Node
.ELEMENT_NODE
or \
1536 n
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1537 self
.Indent(n
, indent
+ 2)
1539 def Save(self
, path
):
1543 if tree
.selection
and panel
.IsModified():
1544 self
.OnRefresh(wx
.CommandEvent())
1545 if g
.currentEncoding
:
1546 f
= codecs
.open(path
, 'wt', g
.currentEncoding
)
1548 f
= codecs
.open(path
, 'wt')
1549 # Make temporary copy for formatting it
1550 # !!! We can't clone dom node, it works only once
1551 #self.domCopy = tree.dom.cloneNode(True)
1552 self
.domCopy
= MyDocument()
1553 mainNode
= self
.domCopy
.appendChild(tree
.mainNode
.cloneNode(True))
1554 # Remove first child (test element)
1555 testElem
= mainNode
.firstChild
1556 mainNode
.removeChild(testElem
)
1558 self
.Indent(mainNode
)
1559 self
.domCopy
.writexml(f
, encoding
= g
.currentEncoding
)
1561 self
.domCopy
.unlink()
1563 self
.SetModified(False)
1564 panel
.SetModified(False)
1565 conf
.localconf
.Flush()
1567 inf
= sys
.exc_info()
1568 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1569 wx
.LogError('Error writing file: %s' % path
)
1573 if not (self
.modified
or panel
.IsModified()): return True
1574 flags
= wx
.ICON_EXCLAMATION | wx
.YES_NO | wx
.CANCEL | wx
.CENTRE
1575 dlg
= wx
.MessageDialog( self
, 'File is modified. Save before exit?',
1576 'Save before too late?', flags
)
1577 say
= dlg
.ShowModal()
1580 if say
== wx
.ID_YES
:
1581 self
.OnSaveOrSaveAs(wx
.CommandEvent(wx
.ID_SAVE
))
1582 # If save was successful, modified flag is unset
1583 if not self
.modified
: return True
1584 elif say
== wx
.ID_NO
:
1585 self
.SetModified(False)
1586 panel
.SetModified(False)
1590 ################################################################################
1592 class PythonOptions(wx
.Dialog
):
1594 def __init__(self
, parent
, cfg
, dataFile
):
1595 pre
= wx
.PreDialog()
1596 g
.frame
.res
.LoadOnDialog(pre
, parent
, "PYTHON_OPTIONS")
1597 self
.PostCreate(pre
)
1600 self
.dataFile
= dataFile
1602 self
.AutoGenerateCB
= xrc
.XRCCTRL(self
, "AutoGenerateCB")
1603 self
.EmbedCB
= xrc
.XRCCTRL(self
, "EmbedCB")
1604 self
.GettextCB
= xrc
.XRCCTRL(self
, "GettextCB")
1605 self
.MakeXRSFileCB
= xrc
.XRCCTRL(self
, "MakeXRSFileCB")
1606 self
.FileNameTC
= xrc
.XRCCTRL(self
, "FileNameTC")
1607 self
.BrowseBtn
= xrc
.XRCCTRL(self
, "BrowseBtn")
1608 self
.GenerateBtn
= xrc
.XRCCTRL(self
, "GenerateBtn")
1609 self
.SaveOptsBtn
= xrc
.XRCCTRL(self
, "SaveOptsBtn")
1611 self
.Bind(wx
.EVT_BUTTON
, self
.OnBrowse
, self
.BrowseBtn
)
1612 self
.Bind(wx
.EVT_BUTTON
, self
.OnGenerate
, self
.GenerateBtn
)
1613 self
.Bind(wx
.EVT_BUTTON
, self
.OnSaveOpts
, self
.SaveOptsBtn
)
1615 if self
.cfg
.Read("filename", "") != "":
1616 self
.FileNameTC
.SetValue(self
.cfg
.Read("filename"))
1618 name
= os
.path
.splitext(os
.path
.split(dataFile
)[1])[0]
1620 self
.FileNameTC
.SetValue(name
)
1621 self
.AutoGenerateCB
.SetValue(self
.cfg
.ReadBool("autogenerate", False))
1622 self
.EmbedCB
.SetValue(self
.cfg
.ReadBool("embedResource", False))
1623 self
.MakeXRSFileCB
.SetValue(self
.cfg
.ReadBool("makeXRS", False))
1624 self
.GettextCB
.SetValue(self
.cfg
.ReadBool("genGettext", False))
1627 def OnBrowse(self
, evt
):
1628 path
= self
.FileNameTC
.GetValue()
1629 dirname
= os
.path
.abspath(os
.path
.dirname(path
))
1630 name
= os
.path
.split(path
)[1]
1631 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.py',
1632 wx
.SAVE | wx
.OVERWRITE_PROMPT
)
1633 if dlg
.ShowModal() == wx
.ID_OK
:
1634 path
= dlg
.GetPath()
1635 self
.FileNameTC
.SetValue(path
)
1639 def OnGenerate(self
, evt
):
1640 pypath
= self
.FileNameTC
.GetValue()
1641 embed
= self
.EmbedCB
.GetValue()
1642 genGettext
= self
.GettextCB
.GetValue()
1643 frame
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
1647 def OnSaveOpts(self
, evt
=None):
1648 self
.cfg
.Write("filename", self
.FileNameTC
.GetValue())
1649 self
.cfg
.WriteBool("autogenerate", self
.AutoGenerateCB
.GetValue())
1650 self
.cfg
.WriteBool("embedResource", self
.EmbedCB
.GetValue())
1651 self
.cfg
.WriteBool("makeXRS", self
.MakeXRSFileCB
.GetValue())
1652 self
.cfg
.WriteBool("genGettext", self
.GettextCB
.GetValue())
1654 self
.EndModal(wx
.ID_OK
)
1656 ################################################################################
1658 class PrefsDialog(wx
.Dialog
):
1660 def __init__(self
, parent
):
1661 pre
= wx
.PreDialog()
1662 g
.frame
.res
.LoadOnDialog(pre
, parent
, "DIALOG_PREFS")
1663 self
.PostCreate(pre
)
1664 self
.checkControls
= {} # map of check IDs to (control,dict,param)
1666 ##xxx = sys.modules['xxx']
1668 d
= xxx
.xxxSizerItem
.defaults_panel
1670 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_panel')
1671 id = self
.check_proportion_panel
.GetId()
1672 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1673 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_panel'),
1676 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_panel')
1677 id = self
.check_flag_panel
.GetId()
1678 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1679 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_panel'),
1682 d
= xxx
.xxxSizerItem
.defaults_control
1684 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_control')
1685 id = self
.check_proportion_panel
.GetId()
1686 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1687 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_control'),
1690 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_control')
1691 id = self
.check_flag_panel
.GetId()
1692 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1693 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_control'),
1696 for id,cdp
in self
.checkControls
.items():
1699 if isinstance(c
, wx
.SpinCtrl
):
1700 c
.SetValue(int(d
[p
]))
1703 self
.FindWindowById(id).SetValue(True)
1707 self
.radio_allow_exec
= xrc
.XRCCTRL(self
, 'radio_allow_exec')
1709 radio
= {'ask': 0, 'yes':1, 'no':2}
[g
.conf
.allowExec
]
1712 self
.radio_allow_exec
.SetSelection(radio
)
1714 def OnCheck(self
, evt
):
1715 self
.checkControls
[evt
.GetId()][0].Enable(evt
.IsChecked())
1718 ################################################################################
1720 # Parse string in form var1=val1[,var2=val2]* as dictionary
1721 def ReadDictFromString(s
):
1723 for vv
in s
.split(','):
1724 var
,val
= vv
.split(':')
1725 d
[var
.strip()] = val
1728 # Transform dictionary with strings into one string
1729 def DictToString(d
):
1730 return ','.join(map(':'.join
, d
.items()))
1733 print >> sys
.stderr
, 'usage: xrced [-dhiv] [file]'
1738 if wx
.VERSION
[:3] < MinWxVersion
:
1740 This version of XRCed may not work correctly on your version of wxWidgets. \
1741 Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion
)
1743 # Process comand-line
1746 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'dhiv')
1754 print 'XRCed version', version
1757 except getopt
.GetoptError
:
1758 if wx
.Platform
!= '__WXMAC__': # macs have some extra parameters
1759 print >> sys
.stderr
, 'Unknown option'
1763 self
.SetAppName('xrced')
1766 conf
= g
.conf
= wx
.Config(style
= wx
.CONFIG_USE_LOCAL_FILE
)
1767 conf
.localconf
= None
1768 conf
.autoRefresh
= conf
.ReadInt('autorefresh', True)
1769 pos
= conf
.ReadInt('x', -1), conf
.ReadInt('y', -1)
1770 size
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600)
1771 conf
.embedPanel
= conf
.ReadInt('embedPanel', True)
1772 conf
.showTools
= conf
.ReadInt('showTools', True)
1773 conf
.sashPos
= conf
.ReadInt('sashPos', 200)
1775 # read recently used files
1776 g
.fileHistory
= wx
.FileHistory()
1777 g
.fileHistory
.Load(conf
)
1779 if not conf
.embedPanel
:
1780 conf
.panelX
= conf
.ReadInt('panelX', -1)
1781 conf
.panelY
= conf
.ReadInt('panelY', -1)
1783 conf
.panelX
= conf
.panelY
= -1
1784 conf
.panelWidth
= conf
.ReadInt('panelWidth', 200)
1785 conf
.panelHeight
= conf
.ReadInt('panelHeight', 200)
1786 conf
.panic
= not conf
.HasEntry('nopanic')
1788 conf
.allowExec
= conf
.Read('Prefs/allowExec', 'ask')
1789 p
= 'Prefs/sizeritem_defaults_panel'
1791 if conf
.HasEntry(p
):
1792 ##sys.modules['xxx'].xxxSizerItem.defaults_panel = ReadDictFromString(conf.Read(p))
1793 xxx
.xxxSizerItem
.defaults_panel
= ReadDictFromString(conf
.Read(p
))
1794 p
= 'Prefs/sizeritem_defaults_control'
1795 if conf
.HasEntry(p
):
1796 ##sys.modules['xxx'].xxxSizerItem.defaults_control = ReadDictFromString(conf.Read(p))
1797 xxx
.xxxSizerItem
.defaults_control
= ReadDictFromString(conf
.Read(p
))
1800 wx
.FileSystem
.AddHandler(wx
.MemoryFSHandler())
1802 frame
= Frame(pos
, size
)
1803 # Mac does not set the correct size
1804 if wx
.Platform
== '__WXMAC__':
1805 frame
.SetClientSize(size
)
1809 plugins
= os
.getenv('XRCEDPATH')
1813 for dir in plugins
.split(':'):
1814 if os
.path
.isdir(dir) and \
1815 os
.path
.isfile(os
.path
.join(dir, '__init__.py')):
1817 dir = os
.path
.abspath(os
.path
.normpath(dir))
1818 sys
.path
= sys_path
+ [os
.path
.dirname(dir)]
1821 __import__(os
.path
.basename(dir), globals(), locals(), ['*'])
1823 print traceback
.print_exc()
1826 # Store important data
1827 frame
.handlers
= getHandlers()[:]
1828 frame
.custom
= g
.pullDownMenu
.custom
[:]
1829 frame
.modules
= sys
.modules
.copy()
1834 # Load file after showing
1837 frame
.open = frame
.Open(args
[0])
1845 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1846 wc
.WriteInt('x', conf
.x
)
1847 wc
.WriteInt('y', conf
.y
)
1848 wc
.WriteInt('width', conf
.width
)
1849 wc
.WriteInt('height', conf
.height
)
1850 wc
.WriteInt('embedPanel', conf
.embedPanel
)
1851 wc
.WriteInt('showTools', conf
.showTools
)
1852 if not conf
.embedPanel
:
1853 wc
.WriteInt('panelX', conf
.panelX
)
1854 wc
.WriteInt('panelY', conf
.panelY
)
1855 wc
.WriteInt('sashPos', conf
.sashPos
)
1856 wc
.WriteInt('panelWidth', conf
.panelWidth
)
1857 wc
.WriteInt('panelHeight', conf
.panelHeight
)
1858 wc
.WriteInt('nopanic', 1)
1859 g
.fileHistory
.Save(wc
)
1861 wc
.DeleteGroup('Prefs')
1862 wc
.Write('Prefs/allowExec', conf
.allowExec
)
1864 ##v = sys.modules['xxx'].xxxSizerItem.defaults_panel
1865 v
= xxx
.xxxSizerItem
.defaults_panel
1866 if v
: wc
.Write('Prefs/sizeritem_defaults_panel', DictToString(v
))
1867 ###v = sys.modules['xxx'].xxxSizerItem.defaults_control
1868 v
= xxx
.xxxSizerItem
.defaults_control
1869 if v
: wc
.Write('Prefs/sizeritem_defaults_control', DictToString(v
))
1874 app
= App(0, useBestVisual
=False)
1875 #app.SetAssertMode(wx.PYAPP_ASSERT_LOG)
1881 if __name__
== '__main__':