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
)
222 # Hide some icons on Mac to reduce the toolbar size,
223 # and comply more with the Apple LnF, besides
224 # wxMac icons are ugly
225 if wx
.Platform
!= '__WXMAC__':
226 tb
.SetToolBitmapSize((24,24))
227 new_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_NORMAL_FILE
, wx
.ART_TOOLBAR
)
228 open_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_OPEN
, wx
.ART_TOOLBAR
)
229 save_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_SAVE
, wx
.ART_TOOLBAR
)
230 undo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_UNDO
, wx
.ART_TOOLBAR
)
231 redo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_REDO
, wx
.ART_TOOLBAR
)
232 cut_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_CUT
, wx
.ART_TOOLBAR
)
233 copy_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_COPY
, wx
.ART_TOOLBAR
)
234 paste_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_PASTE
, wx
.ART_TOOLBAR
)
235 tb
.AddSimpleTool(wx
.ID_NEW
, new_bmp
, 'New', 'New file')
236 tb
.AddSimpleTool(wx
.ID_OPEN
, open_bmp
, 'Open', 'Open file')
237 tb
.AddSimpleTool(wx
.ID_SAVE
, save_bmp
, 'Save', 'Save file')
238 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
239 tb
.AddSimpleTool(wx
.ID_UNDO
, undo_bmp
, 'Undo', 'Undo')
240 tb
.AddSimpleTool(wx
.ID_REDO
, redo_bmp
, 'Redo', 'Redo')
241 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
242 tb
.AddSimpleTool(wx
.ID_CUT
, cut_bmp
, 'Cut', 'Cut')
243 tb
.AddSimpleTool(wx
.ID_COPY
, copy_bmp
, 'Copy', 'Copy')
244 tb
.AddSimpleTool(self
.ID_TOOL_PASTE
, paste_bmp
, 'Paste', 'Paste')
245 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
246 tb
.AddSimpleTool(self
.ID_TOOL_LOCATE
,
247 images
.getLocateBitmap(), #images.getLocateArmedBitmap(),
248 'Locate', 'Locate control in test window and select it', True)
249 # tb.AddControl(wx.StaticLine(tb, -1, size=(-1,23), style=wx.LI_VERTICAL))
250 tb
.AddSimpleTool(self
.ID_TEST
, images
.getTestBitmap(), 'Test', 'Test window')
251 tb
.AddSimpleTool(self
.ID_REFRESH
, images
.getRefreshBitmap(),
252 'Refresh', 'Refresh view')
253 tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, images
.getAutoRefreshBitmap(),
254 'Auto-refresh', 'Toggle auto-refresh mode', True)
255 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
))
256 tb
.AddSimpleTool(self
.ID_MOVEUP
, images
.getToolMoveUpBitmap(),
257 'Up', 'Move before previous sibling')
258 tb
.AddSimpleTool(self
.ID_MOVEDOWN
, images
.getToolMoveDownBitmap(),
259 'Down', 'Move after next sibling')
260 tb
.AddSimpleTool(self
.ID_MOVELEFT
, images
.getToolMoveLeftBitmap(),
261 'Make Sibling', 'Make sibling of parent')
262 tb
.AddSimpleTool(self
.ID_MOVERIGHT
, images
.getToolMoveRightBitmap(),
263 'Make Child', 'Make child of previous sibling')
264 # if wx.Platform == '__WXGTK__':
265 # tb.AddSeparator() # otherwise auto-refresh sticks in status line
266 tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
270 self
.minWidth
= tb
.GetSize()[0] # minimal width is the size of toolbar
273 wx
.EVT_MENU(self
, wx
.ID_NEW
, self
.OnNew
)
274 wx
.EVT_MENU(self
, wx
.ID_OPEN
, self
.OnOpen
)
275 wx
.EVT_MENU(self
, wx
.ID_SAVE
, self
.OnSaveOrSaveAs
)
276 wx
.EVT_MENU(self
, wx
.ID_SAVEAS
, self
.OnSaveOrSaveAs
)
277 wx
.EVT_MENU(self
, self
.ID_GENERATE_PYTHON
, self
.OnGeneratePython
)
278 wx
.EVT_MENU(self
, self
.ID_PREFS
, self
.OnPrefs
)
279 wx
.EVT_MENU(self
, wx
.ID_EXIT
, self
.OnExit
)
281 wx
.EVT_MENU(self
, wx
.ID_UNDO
, self
.OnUndo
)
282 wx
.EVT_MENU(self
, wx
.ID_REDO
, self
.OnRedo
)
283 wx
.EVT_MENU(self
, wx
.ID_CUT
, self
.OnCutDelete
)
284 wx
.EVT_MENU(self
, wx
.ID_COPY
, self
.OnCopy
)
285 wx
.EVT_MENU(self
, wx
.ID_PASTE
, self
.OnPaste
)
286 wx
.EVT_MENU(self
, self
.ID_TOOL_PASTE
, self
.OnPaste
)
287 wx
.EVT_MENU(self
, self
.ID_DELETE
, self
.OnCutDelete
)
288 wx
.EVT_MENU(self
, self
.ID_LOCATE
, self
.OnLocate
)
289 wx
.EVT_MENU(self
, self
.ID_TOOL_LOCATE
, self
.OnLocate
)
291 wx
.EVT_MENU(self
, self
.ID_EMBED_PANEL
, self
.OnEmbedPanel
)
292 wx
.EVT_MENU(self
, self
.ID_SHOW_TOOLS
, self
.OnShowTools
)
293 wx
.EVT_MENU(self
, self
.ID_TEST
, self
.OnTest
)
294 wx
.EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
)
295 wx
.EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
)
296 wx
.EVT_MENU(self
, self
.ID_TEST_HIDE
, self
.OnTestHide
)
298 wx
.EVT_MENU(self
, self
.ID_MOVEUP
, self
.OnMoveUp
)
299 wx
.EVT_MENU(self
, self
.ID_MOVEDOWN
, self
.OnMoveDown
)
300 wx
.EVT_MENU(self
, self
.ID_MOVELEFT
, self
.OnMoveLeft
)
301 wx
.EVT_MENU(self
, self
.ID_MOVERIGHT
, self
.OnMoveRight
)
303 wx
.EVT_MENU(self
, wx
.ID_ABOUT
, self
.OnAbout
)
304 wx
.EVT_MENU(self
, self
.ID_README
, self
.OnReadme
)
307 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVE
, self
.OnUpdateUI
)
308 wx
.EVT_UPDATE_UI(self
, wx
.ID_CUT
, self
.OnUpdateUI
)
309 wx
.EVT_UPDATE_UI(self
, wx
.ID_COPY
, self
.OnUpdateUI
)
310 wx
.EVT_UPDATE_UI(self
, wx
.ID_PASTE
, self
.OnUpdateUI
)
311 wx
.EVT_UPDATE_UI(self
, self
.ID_LOCATE
, self
.OnUpdateUI
)
312 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_LOCATE
, self
.OnUpdateUI
)
313 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_PASTE
, self
.OnUpdateUI
)
314 wx
.EVT_UPDATE_UI(self
, wx
.ID_UNDO
, self
.OnUpdateUI
)
315 wx
.EVT_UPDATE_UI(self
, wx
.ID_REDO
, self
.OnUpdateUI
)
316 wx
.EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
)
317 wx
.EVT_UPDATE_UI(self
, self
.ID_TEST
, self
.OnUpdateUI
)
318 wx
.EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
)
321 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
322 #sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND)
323 # Horizontal sizer for toolbar and splitter
324 self
.toolsSizer
= sizer1
= wx
.BoxSizer()
325 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.SP_3DSASH
)
326 self
.splitter
= splitter
327 splitter
.SetMinimumPaneSize(100)
330 g
.tree
= tree
= XML_Tree(splitter
, -1)
332 # Init pull-down menu data
334 g
.pullDownMenu
= pullDownMenu
= PullDownMenu(self
)
336 # Vertical toolbar for GUI buttons
337 g
.tools
= tools
= Tools(self
)
338 tools
.Show(conf
.showTools
)
339 if conf
.showTools
: sizer1
.Add(tools
, 0, wx
.EXPAND
)
341 tree
.RegisterKeyEvents()
343 # Miniframe for split mode
344 miniFrame
= wx
.MiniFrame(self
, -1, 'Properties & Style',
345 (conf
.panelX
, conf
.panelY
),
346 (conf
.panelWidth
, conf
.panelHeight
))
347 self
.miniFrame
= miniFrame
348 sizer2
= wx
.BoxSizer()
349 miniFrame
.SetSizer(sizer2
)
350 # Create panel for parameters
353 panel
= Panel(splitter
)
354 # Set plitter windows
355 splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
357 panel
= Panel(miniFrame
)
358 sizer2
.Add(panel
, 1, wx
.EXPAND
)
360 splitter
.Initialize(tree
)
361 if wx
.Platform
== '__WXMAC__':
362 sizer1
.Add(splitter
, 1, wx
.EXPAND|wx
.RIGHT
, 5)
364 sizer1
.Add(splitter
, 1, wx
.EXPAND
)
365 sizer
.Add(sizer1
, 1, wx
.EXPAND
)
366 self
.SetAutoLayout(True)
370 wx
.EVT_IDLE(self
, self
.OnIdle
)
371 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
372 wx
.EVT_KEY_DOWN(self
, tools
.OnKeyDown
)
373 wx
.EVT_KEY_UP(self
, tools
.OnKeyUp
)
374 wx
.EVT_ICONIZE(self
, self
.OnIconize
)
376 def OnRecentFile(self
,evt
):
377 # open recently used file
378 if not self
.AskSave(): return
381 # get the pathname based on the menu ID
382 fileNum
= evt
.GetId() - wx
.ID_FILE1
383 path
= g
.fileHistory
.GetHistoryFile(fileNum
)
386 self
.SetStatusText('Data loaded')
387 # add it back to the history so it will be moved up the list
388 self
.SaveRecent(path
)
390 self
.SetStatusText('Failed')
394 def OnNew(self
, evt
):
395 if not self
.AskSave(): return
398 def OnOpen(self
, evt
):
399 if not self
.AskSave(): return
400 dlg
= wx
.FileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
401 '', '*.xrc', wx
.OPEN | wx
.CHANGE_DIR
)
402 if dlg
.ShowModal() == wx
.ID_OK
:
404 self
.SetStatusText('Loading...')
408 self
.SetStatusText('Data loaded')
409 self
.SaveRecent(path
)
411 self
.SetStatusText('Failed')
416 def OnSaveOrSaveAs(self
, evt
):
417 if evt
.GetId() == wx
.ID_SAVEAS
or not self
.dataFile
:
418 if self
.dataFile
: name
= ''
419 else: name
= defaultName
420 dirname
= os
.path
.abspath(os
.path
.dirname(self
.dataFile
))
421 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.xrc',
422 wx
.SAVE | wx
.OVERWRITE_PROMPT | wx
.CHANGE_DIR
)
423 if dlg
.ShowModal() == wx
.ID_OK
:
425 if isinstance(path
, unicode):
426 path
= path
.encode(sys
.getfilesystemencoding())
433 # if we already have a localconf then it needs to be
434 # copied to a new config with the new name
436 nc
= self
.CreateLocalConf(path
)
437 flag
, key
, idx
= lc
.GetFirstEntry()
439 nc
.Write(key
, lc
.Read(key
))
440 flag
, key
, idx
= lc
.GetNextEntry(idx
)
443 # otherwise create a new one
444 conf
.localconf
= self
.CreateLocalConf(path
)
447 self
.SetStatusText('Saving...')
451 tmpFile
,tmpName
= tempfile
.mkstemp(prefix
='xrced-')
453 self
.Save(tmpName
) # save temporary file first
454 shutil
.move(tmpName
, path
)
456 self
.SetModified(False)
457 if conf
.localconf
.ReadBool("autogenerate", False):
458 pypath
= conf
.localconf
.Read("filename")
459 embed
= conf
.localconf
.ReadBool("embedResource", False)
460 genGettext
= conf
.localconf
.ReadBool("genGettext", False)
461 self
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
463 self
.SetStatusText('Data saved')
464 self
.SaveRecent(path
)
466 self
.SetStatusText('Failed')
470 def SaveRecent(self
,path
):
471 # append to recently used files
472 g
.fileHistory
.AddFileToHistory(path
)
474 def GeneratePython(self
, dataFile
, pypath
, embed
, genGettext
):
476 import wx
.tools
.pywxrc
477 rescomp
= wx
.tools
.pywxrc
.XmlResourceCompiler()
478 rescomp
.MakePythonModule([dataFile
], pypath
, embed
, genGettext
)
481 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
482 wx
.LogError('Error generating python code : %s' % pypath
)
486 def OnGeneratePython(self
, evt
):
487 if self
.modified
or not conf
.localconf
:
488 wx
.MessageBox("Save the XRC file first!", "Error")
491 dlg
= PythonOptions(self
, conf
.localconf
, self
.dataFile
)
495 def OnPrefs(self
, evt
):
496 dlg
= PrefsDialog(self
)
497 if dlg
.ShowModal() == wx
.ID_OK
:
498 # Fetch new preferences
499 for id,cdp
in dlg
.checkControls
.items():
501 if dlg
.FindWindowById(id).IsChecked():
502 d
[p
] = str(c
.GetValue())
503 elif p
in d
: del d
[p
]
504 g
.conf
.allowExec
= ('ask', 'yes', 'no')[dlg
.radio_allow_exec
.GetSelection()]
507 def OnExit(self
, evt
):
510 def OnUndo(self
, evt
):
511 # Extra check to not mess with idle updating
512 if undoMan
.CanUndo():
514 g
.panel
.SetModified(False)
515 if not undoMan
.CanUndo():
516 self
.SetModified(False)
518 def OnRedo(self
, evt
):
519 if undoMan
.CanRedo():
521 self
.SetModified(True)
523 def OnCopy(self
, evt
):
524 selected
= tree
.selection
525 if not selected
: return # key pressed event
526 xxx
= tree
.GetPyData(selected
)
527 if wx
.TheClipboard
.Open():
529 data
= wx
.CustomDataObject('XRCED')
530 # Set encoding in header
532 s
= xxx
.node
.toxml(encoding
=expat
.native_encoding
)
534 data
= wx
.CustomDataObject('XRCED_node')
536 data
.SetData(cPickle
.dumps(s
))
537 wx
.TheClipboard
.SetData(data
)
538 wx
.TheClipboard
.Close()
539 self
.SetStatusText('Copied')
541 wx
.MessageBox("Unable to open the clipboard", "Error")
543 def OnPaste(self
, evt
):
544 selected
= tree
.selection
545 if not selected
: return # key pressed event
546 # For pasting with Ctrl pressed
548 if evt
.GetId() == pullDownMenu
.ID_PASTE_SIBLING
: appendChild
= False
549 elif evt
.GetId() == self
.ID_TOOL_PASTE
:
550 if g
.tree
.ctrl
: appendChild
= False
551 else: appendChild
= not tree
.NeedInsert(selected
)
552 else: appendChild
= not tree
.NeedInsert(selected
)
553 xxx
= tree
.GetPyData(selected
)
555 # If has next item, insert, else append to parent
556 nextItem
= tree
.GetNextSibling(selected
)
557 parentLeaf
= tree
.GetItemParent(selected
)
558 # Expanded container (must have children)
559 elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, False):
560 # Insert as first child
561 nextItem
= tree
.GetFirstChild(selected
)[0]
562 parentLeaf
= selected
564 # No children or unexpanded item - appendChild stays True
565 nextItem
= wx
.TreeItemId() # no next item
566 parentLeaf
= selected
567 parent
= tree
.GetPyData(parentLeaf
).treeObject()
569 # Create a copy of clipboard pickled element
570 success
= success_node
= False
571 if wx
.TheClipboard
.Open():
573 data
= wx
.CustomDataObject('XRCED')
574 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
576 success
= wx
.TheClipboard
.GetData(data
)
578 # there is a problem if XRCED_node is in clipboard
579 # but previous SetData was for XRCED
581 if not success
: # try other format
582 data
= wx
.CustomDataObject('XRCED_node')
583 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
584 success_node
= wx
.TheClipboard
.GetData(data
)
586 wx
.TheClipboard
.Close()
588 if not success
and not success_node
:
590 "There is no data in the clipboard in the required format",
594 xml
= cPickle
.loads(data
.GetData()) # xml representation of element
596 elem
= minidom
.parseString(xml
).childNodes
[0]
598 elem
= g
.tree
.dom
.createComment(xml
)
600 # Tempopary xxx object to test things
601 xxx
= MakeXXXFromDOM(parent
, elem
)
603 # Check compatibility
604 if not self
.ItemsAreCompatible(parent
, xxx
.treeObject()): return
606 # Check parent and child relationships.
607 # If parent is sizer or notebook, child is of wrong class or
608 # parent is normal window, child is child container then detach child.
609 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
610 parentIsBook
= parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]
611 if isChildContainer
and \
612 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
613 (parentIsBook
and not isinstance(xxx
, xxxPage
)) or \
614 not (parent
.isSizer
or parentIsBook
)):
615 elem
.removeChild(xxx
.child
.node
) # detach child
616 elem
.unlink() # delete child container
617 elem
= xxx
.child
.node
# replace
618 # This may help garbage collection
619 xxx
.child
.parent
= None
620 isChildContainer
= False
621 # Parent is sizer or notebook, child is not child container
622 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
623 # Create sizer item element
624 sizerItemElem
= MakeEmptyDOM(parent
.itemTag
)
625 sizerItemElem
.appendChild(elem
)
627 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
628 pageElem
= MakeEmptyDOM('notebookpage')
629 pageElem
.appendChild(elem
)
631 elif isinstance(parent
, xxxChoicebook
) and not isChildContainer
:
632 pageElem
= MakeEmptyDOM('choicebookpage')
633 pageElem
.appendChild(elem
)
635 elif isinstance(parent
, xxxListbook
) and not isChildContainer
:
636 pageElem
= MakeEmptyDOM('listbookpage')
637 pageElem
.appendChild(elem
)
639 # Insert new node, register undo
640 newItem
= tree
.InsertNode(parentLeaf
, parent
, elem
, nextItem
)
641 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
642 # Scroll to show new item (!!! redundant?)
643 tree
.EnsureVisible(newItem
)
644 tree
.SelectItem(newItem
)
645 if not tree
.IsVisible(newItem
):
646 tree
.ScrollTo(newItem
)
649 if g
.testWin
and tree
.IsHighlatable(newItem
):
651 tree
.needUpdate
= True
652 tree
.pendingHighLight
= newItem
654 tree
.pendingHighLight
= None
656 self
.SetStatusText('Pasted')
659 def ItemsAreCompatible(self
, parent
, child
):
660 # Check compatibility
662 # Comments are always compatible
663 if child
.__class
__ == xxxComment
:
666 if child
.__class
__ in [xxxDialog
, xxxFrame
, xxxWizard
]:
668 if parent
.__class
__ != xxxMainNode
: error
= True
669 elif child
.__class
__ == xxxMenuBar
:
670 # Menubar can be put in frame or dialog
671 if parent
.__class
__ not in [xxxMainNode
, xxxFrame
, xxxDialog
]: error
= True
672 elif child
.__class
__ == xxxToolBar
:
673 # Toolbar can be top-level of child of panel or frame
674 if parent
.__class
__ not in [xxxMainNode
, xxxPanel
, xxxFrame
] and \
675 not parent
.isSizer
: error
= True
676 elif child
.__class
__ == xxxPanel
and parent
.__class
__ == xxxMainNode
:
678 elif child
.__class
__ == xxxSpacer
:
679 if not parent
.isSizer
: error
= True
680 elif child
.__class
__ == xxxSeparator
:
681 if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error
= True
682 elif child
.__class
__ == xxxTool
:
683 if parent
.__class
__ != xxxToolBar
: error
= True
684 elif child
.__class
__ == xxxMenu
:
685 if not parent
.__class
__ in [xxxMainNode
, xxxMenuBar
, xxxMenu
]: error
= True
686 elif child
.__class
__ == xxxMenuItem
:
687 if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
688 elif child
.isSizer
and parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]:
690 else: # normal controls can be almost anywhere
691 if parent
.__class
__ == xxxMainNode
or \
692 parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
694 if parent
.__class
__ == xxxMainNode
: parentClass
= 'root'
695 else: parentClass
= parent
.className
696 wx
.LogError('Incompatible parent/child: parent is %s, child is %s!' %
697 (parentClass
, child
.className
))
701 def OnMoveUp(self
, evt
):
702 selected
= tree
.selection
703 if not selected
: return
705 index
= tree
.ItemIndex(selected
)
706 if index
== 0: return # No previous sibling found
708 # Remove highlight, update testWin
709 if g
.testWin
and g
.testWin
.highLight
:
710 g
.testWin
.highLight
.Remove()
711 tree
.needUpdate
= True
714 self
.lastOp
= 'MOVEUP'
715 status
= 'Moved before previous sibling'
721 parent
= tree
.GetItemParent(selected
)
722 elem
= tree
.RemoveLeaf(selected
)
723 nextItem
= tree
.GetFirstChild(parent
)[0]
724 for i
in range(index
- 1): nextItem
= tree
.GetNextSibling(nextItem
)
725 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
726 newIndex
= tree
.ItemIndex(selected
)
727 tree
.SelectItem(selected
)
729 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
732 self
.SetStatusText(status
)
736 def OnMoveDown(self
, evt
):
737 selected
= tree
.selection
738 if not selected
: return
740 index
= tree
.ItemIndex(selected
)
741 next
= tree
.GetNextSibling(selected
)
744 # Remove highlight, update testWin
745 if g
.testWin
and g
.testWin
.highLight
:
746 g
.testWin
.highLight
.Remove()
747 tree
.needUpdate
= True
750 self
.lastOp
= 'MOVEDOWN'
751 status
= 'Moved after next sibling'
757 parent
= tree
.GetItemParent(selected
)
758 elem
= tree
.RemoveLeaf(selected
)
759 nextItem
= tree
.GetFirstChild(parent
)[0]
760 for i
in range(index
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
761 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
762 newIndex
= tree
.ItemIndex(selected
)
763 tree
.SelectItem(selected
)
765 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
768 self
.SetStatusText(status
)
772 def OnMoveLeft(self
, evt
):
773 selected
= tree
.selection
774 if not selected
: return
776 oldParent
= tree
.GetItemParent(selected
)
777 if not oldParent
: return
778 pparent
= tree
.GetItemParent(oldParent
)
779 if not pparent
: return
781 # Check compatibility
782 if not self
.ItemsAreCompatible(tree
.GetPyData(pparent
).treeObject(), tree
.GetPyData(selected
).treeObject()): return
784 if g
.testWin
and g
.testWin
.highLight
:
785 g
.testWin
.highLight
.Remove()
786 tree
.needUpdate
= True
789 self
.lastOp
= 'MOVELEFT'
790 status
= 'Made next sibling of parent'
792 oldIndex
= tree
.ItemIndex(selected
)
793 elem
= tree
.RemoveLeaf(selected
)
794 nextItem
= tree
.GetFirstChild(pparent
)[0]
795 parentIndex
= tree
.ItemIndex(oldParent
)
796 for i
in range(parentIndex
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
798 # Check parent and child relationships.
799 # If parent is sizer or notebook, child is of wrong class or
800 # parent is normal window, child is child container then detach child.
801 parent
= tree
.GetPyData(pparent
).treeObject()
802 xxx
= MakeXXXFromDOM(parent
, elem
)
803 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
804 if isChildContainer
and \
805 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
806 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
807 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
808 elem
.removeChild(xxx
.child
.node
) # detach child
809 elem
.unlink() # delete child container
810 elem
= xxx
.child
.node
# replace
811 # This may help garbage collection
812 xxx
.child
.parent
= None
813 isChildContainer
= False
814 # Parent is sizer or notebook, child is not child container
815 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
816 # Create sizer item element
817 sizerItemElem
= MakeEmptyDOM('sizeritem')
818 sizerItemElem
.appendChild(elem
)
820 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
821 pageElem
= MakeEmptyDOM('notebookpage')
822 pageElem
.appendChild(elem
)
825 selected
= tree
.InsertNode(pparent
, tree
.GetPyData(pparent
).treeObject(), elem
, nextItem
)
826 newIndex
= tree
.ItemIndex(selected
)
827 tree
.SelectItem(selected
)
829 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, pparent
, newIndex
))
832 self
.SetStatusText(status
)
834 def OnMoveRight(self
, evt
):
835 selected
= tree
.selection
836 if not selected
: return
838 oldParent
= tree
.GetItemParent(selected
)
839 if not oldParent
: return
841 newParent
= tree
.GetPrevSibling(selected
)
842 if not newParent
: return
844 parent
= tree
.GetPyData(newParent
).treeObject()
846 # Check compatibility
847 if not self
.ItemsAreCompatible(parent
, tree
.GetPyData(selected
).treeObject()): return
849 # Remove highlight, update testWin
850 if g
.testWin
and g
.testWin
.highLight
:
851 g
.testWin
.highLight
.Remove()
852 tree
.needUpdate
= True
855 self
.lastOp
= 'MOVERIGHT'
856 status
= 'Made last child of previous sibling'
858 oldIndex
= tree
.ItemIndex(selected
)
859 elem
= tree
.RemoveLeaf(selected
)
861 # Check parent and child relationships.
862 # If parent is sizer or notebook, child is of wrong class or
863 # parent is normal window, child is child container then detach child.
864 xxx
= MakeXXXFromDOM(parent
, elem
)
865 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
866 if isChildContainer
and \
867 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
868 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
869 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
870 elem
.removeChild(xxx
.child
.node
) # detach child
871 elem
.unlink() # delete child container
872 elem
= xxx
.child
.node
# replace
873 # This may help garbage collection
874 xxx
.child
.parent
= None
875 isChildContainer
= False
876 # Parent is sizer or notebook, child is not child container
877 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
878 # Create sizer item element
879 sizerItemElem
= MakeEmptyDOM('sizeritem')
880 sizerItemElem
.appendChild(elem
)
882 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
883 pageElem
= MakeEmptyDOM('notebookpage')
884 pageElem
.appendChild(elem
)
887 selected
= tree
.InsertNode(newParent
, tree
.GetPyData(newParent
).treeObject(), elem
, wx
.TreeItemId())
889 newIndex
= tree
.ItemIndex(selected
)
890 tree
.SelectItem(selected
)
892 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, newParent
, newIndex
))
895 self
.SetStatusText(status
)
897 def OnCutDelete(self
, evt
):
898 selected
= tree
.selection
899 if not selected
: return # key pressed event
901 if evt
.GetId() == wx
.ID_CUT
:
903 status
= 'Removed to clipboard'
905 self
.lastOp
= 'DELETE'
909 # If deleting top-level item, delete testWin
910 if selected
== g
.testWin
.item
:
914 # Remove highlight, update testWin
915 if g
.testWin
.highLight
:
916 g
.testWin
.highLight
.Remove()
917 tree
.needUpdate
= True
920 index
= tree
.ItemFullIndex(selected
)
921 xxx
= tree
.GetPyData(selected
)
922 parent
= tree
.GetPyData(tree
.GetItemParent(selected
)).treeObject()
924 elem
= tree
.RemoveLeaf(selected
)
925 undoMan
.RegisterUndo(UndoCutDelete(index
, parent
, elem
))
926 if evt
.GetId() == wx
.ID_CUT
:
927 if wx
.TheClipboard
.Open():
929 data
= wx
.CustomDataObject('XRCED')
931 s
= elem
.toxml(encoding
=expat
.native_encoding
)
933 data
= wx
.CustomDataObject('XRCED_node')
935 data
.SetData(cPickle
.dumps(s
))
936 wx
.TheClipboard
.SetData(data
)
937 wx
.TheClipboard
.Close()
939 wx
.MessageBox("Unable to open the clipboard", "Error")
940 tree
.pendingHighLight
= None
944 self
.SetStatusText(status
)
946 def OnSubclass(self
, evt
):
947 selected
= tree
.selection
948 xxx
= tree
.GetPyData(selected
).treeObject()
950 subclass
= xxx
.subclass
951 dlg
= wx
.TextEntryDialog(self
, 'Subclass:', defaultValue
=subclass
)
952 if dlg
.ShowModal() == wx
.ID_OK
:
953 subclass
= dlg
.GetValue()
955 elem
.setAttribute('subclass', subclass
)
956 elif elem
.hasAttribute('subclass'):
957 elem
.removeAttribute('subclass')
959 xxx
.subclass
= elem
.getAttribute('subclass')
960 tree
.SetItemText(selected
, xxx
.treeName())
961 panel
.pages
[0].box
.SetLabel(xxx
.panelName())
964 def OnEmbedPanel(self
, evt
):
965 conf
.embedPanel
= evt
.IsChecked()
967 # Remember last dimentions
968 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
969 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
970 size
= self
.GetSize()
971 pos
= self
.GetPosition()
972 sizePanel
= panel
.GetSize()
973 panel
.Reparent(self
.splitter
)
974 self
.miniFrame
.GetSizer().Remove(panel
)
976 self
.SetDimensions(pos
.x
, pos
.y
, size
.width
+ sizePanel
.width
, size
.height
)
977 self
.splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
978 self
.miniFrame
.Show(False)
980 conf
.sashPos
= self
.splitter
.GetSashPosition()
981 pos
= self
.GetPosition()
982 size
= self
.GetSize()
983 sizePanel
= panel
.GetSize()
984 self
.splitter
.Unsplit(panel
)
985 sizer
= self
.miniFrame
.GetSizer()
986 panel
.Reparent(self
.miniFrame
)
988 sizer
.Add(panel
, 1, wx
.EXPAND
)
989 self
.miniFrame
.Show(True)
990 self
.miniFrame
.SetDimensions(conf
.panelX
, conf
.panelY
,
991 conf
.panelWidth
, conf
.panelHeight
)
992 self
.miniFrame
.Layout()
994 self
.SetDimensions(pos
.x
, pos
.y
,
995 max(size
.width
- sizePanel
.width
, self
.minWidth
), size
.height
)
997 def OnShowTools(self
, evt
):
998 conf
.showTools
= evt
.IsChecked()
999 g
.tools
.Show(conf
.showTools
)
1001 self
.toolsSizer
.Prepend(g
.tools
, 0, wx
.EXPAND
)
1003 self
.toolsSizer
.Remove(g
.tools
)
1004 self
.toolsSizer
.Layout()
1006 def OnTest(self
, evt
):
1007 if not tree
.selection
: return # key pressed event
1008 tree
.ShowTestWindow(tree
.selection
)
1010 def OnTestHide(self
, evt
):
1011 tree
.CloseTestWindow()
1013 # Find object by relative position
1014 def FindObject(self
, item
, obj
):
1015 # We simply perform depth-first traversal, sinse it's too much
1016 # hassle to deal with all sizer/window combinations
1017 w
= tree
.FindNodeObject(item
)
1018 if w
== obj
or isinstance(w
, wx
.GBSizerItem
) and w
.GetWindow() == obj
:
1020 if tree
.ItemHasChildren(item
):
1021 child
= tree
.GetFirstChild(item
)[0]
1023 found
= self
.FindObject(child
, obj
)
1024 if found
: return found
1025 child
= tree
.GetNextSibling(child
)
1028 # Click event after locate activated
1029 def OnTestWinLeftDown(self
, evt
):
1030 # Restore normal event processing
1031 self
.SetHandler(g
.testWin
)
1032 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1033 item
= self
.FindObject(g
.testWin
.item
, evt
.GetEventObject())
1035 tree
.EnsureVisible(item
)
1036 tree
.SelectItem(item
)
1037 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, False)
1039 self
.SetStatusText('Selected %s' % tree
.GetItemText(item
))
1041 self
.SetStatusText('Locate failed!')
1043 def SetHandler(self
, w
, h
=None):
1045 w
.SetEventHandler(h
)
1046 w
.SetCursor(wx
.CROSS_CURSOR
)
1048 w
.SetEventHandler(w
)
1049 w
.SetCursor(wx
.NullCursor
)
1050 for ch
in w
.GetChildren():
1051 self
.SetHandler(ch
, h
)
1053 def OnLocate(self
, evt
):
1055 if evt
.GetId() == self
.ID_LOCATE
or \
1056 evt
.GetId() == self
.ID_TOOL_LOCATE
and evt
.IsChecked():
1057 self
.SetHandler(g
.testWin
, g
.testWin
)
1058 g
.testWin
.Connect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
, self
.OnTestWinLeftDown
)
1059 if evt
.GetId() == self
.ID_LOCATE
:
1060 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, True)
1061 elif evt
.GetId() == self
.ID_TOOL_LOCATE
and not evt
.IsChecked():
1062 self
.SetHandler(g
.testWin
, None)
1063 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1064 self
.SetStatusText('Click somewhere in your test window now')
1066 def OnRefresh(self
, evt
):
1067 # If modified, apply first
1068 selection
= tree
.selection
1070 xxx
= tree
.GetPyData(selection
)
1071 if xxx
and panel
.IsModified():
1072 tree
.Apply(xxx
, selection
)
1075 tree
.CreateTestWin(g
.testWin
.item
)
1076 panel
.modified
= False
1077 tree
.needUpdate
= False
1079 def OnAutoRefresh(self
, evt
):
1080 conf
.autoRefresh
= evt
.IsChecked()
1081 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1082 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1084 def OnAbout(self
, evt
):
1088 (c) Roman Rolinsky <rollrom@users.sourceforge.net>
1089 Homepage: http://xrced.sourceforge.net\
1091 dlg
= wx
.MessageDialog(self
, str, 'About XRCed', wx
.OK | wx
.CENTRE
)
1095 def OnReadme(self
, evt
):
1096 text
= open(os
.path
.join(basePath
, 'README.txt'), 'r').read()
1097 dlg
= ScrolledMessageDialog(self
, text
, "XRCed README")
1101 # Simple emulation of python command line
1102 def OnDebugCMD(self
, evt
):
1105 exec raw_input('C:\> ')
1110 (etype
, value
, tb
) =sys
.exc_info()
1111 tblist
=traceback
.extract_tb(tb
)[1:]
1112 msg
=' '.join(traceback
.format_exception_only(etype
, value
)
1113 +traceback
.format_list(tblist
))
1116 def OnCreate(self
, evt
):
1117 # Ignore fake events generated while dragging
1119 g
.tools
.drag
= False
1121 selected
= tree
.selection
1122 if tree
.ctrl
: appendChild
= False
1123 else: appendChild
= not tree
.NeedInsert(selected
)
1124 xxx
= tree
.GetPyData(selected
)
1128 # If has previous item, insert after it, else append to parent
1130 parentLeaf
= tree
.GetItemParent(selected
)
1132 # If has next item, insert, else append to parent
1133 nextItem
= tree
.GetNextSibling(selected
)
1134 parentLeaf
= tree
.GetItemParent(selected
)
1135 # Expanded container (must have children)
1136 elif tree
.shift
and tree
.IsExpanded(selected
) \
1137 and tree
.GetChildrenCount(selected
, False):
1138 nextItem
= tree
.GetFirstChild(selected
)[0]
1139 parentLeaf
= selected
1141 nextItem
= wx
.TreeItemId()
1142 parentLeaf
= selected
1143 parent
= tree
.GetPyData(parentLeaf
)
1144 if parent
.hasChild
: parent
= parent
.child
1146 self
.CreateXXX(parent
, parentLeaf
, nextItem
, evt
.GetId())
1148 # Actual method to create object and add to XML and wx trees
1149 def CreateXXX(self
, parent
, parentLeaf
, nextItem
, id):
1150 selected
= tree
.selection
1151 # Create object_ref?
1152 if id == ID_NEW
.REF
:
1153 ref
= wx
.GetTextFromUser('Create reference to:', 'Create reference')
1155 xxx
= MakeEmptyRefXXX(parent
, ref
)
1156 elif id == ID_NEW
.COMMENT
:
1157 xxx
= MakeEmptyCommentXXX(parent
)
1159 # Create empty element
1160 if id >= ID_NEW
.CUSTOM
:
1161 className
= pullDownMenu
.customMap
[id]
1163 className
= pullDownMenu
.createMap
[id]
1164 xxx
= MakeEmptyXXX(parent
, className
)
1166 # Insert new node, register undo
1167 if xxx
.isElement
: # true object
1168 # Set default name for top-level windows
1169 if parent
.__class
__ == xxxMainNode
:
1170 cl
= xxx
.treeObject().__class
__
1171 frame
.maxIDs
[cl
] += 1
1172 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1173 # And for some other standard controls
1174 elif parent
.__class
__ == xxxStdDialogButtonSizer
:
1175 # ... we can even set automatically tree name
1176 xxx
.setTreeName(pullDownMenu
.stdButtonIDs
[id][0])
1177 obj
= xxx
.treeObject()
1179 elem
= g
.tree
.dom
.createElement('label')
1180 elem
.appendChild(g
.tree
.dom
.createTextNode(pullDownMenu
.stdButtonIDs
[id][1]))
1181 obj
.params
['label'] = xxxParam(elem
)
1182 xxx
.treeObject().node
.appendChild(elem
)
1183 # Else, set label if exists to class name
1184 elif 'label' in xxx
.treeObject().allParams
:
1186 if label
[:2] == 'wx': label
= label
[2:]
1187 xxx
.treeObject().set('label', label
.upper())
1188 # For comment nodes, simply add node
1189 newItem
= tree
.InsertNode(parentLeaf
, parent
, xxx
.node
, nextItem
)
1190 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
1191 tree
.EnsureVisible(newItem
)
1192 tree
.SelectItem(newItem
)
1193 if not tree
.IsVisible(newItem
):
1194 tree
.ScrollTo(newItem
)
1197 if xxx
.isElement
and g
.testWin
and tree
.IsHighlatable(newItem
):
1198 if conf
.autoRefresh
:
1199 tree
.needUpdate
= True
1200 tree
.pendingHighLight
= newItem
1202 tree
.pendingHighLight
= None
1204 if not xxx
.isElement
:
1205 tree
.EditLabel(newItem
)
1209 # Replace one object with another
1210 def OnReplace(self
, evt
):
1211 selected
= tree
.selection
1212 xxx
= tree
.GetPyData(selected
).treeObject()
1214 parent
= elem
.parentNode
1215 undoMan
.RegisterUndo(UndoReplace(selected
))
1217 className
= pullDownMenu
.createMap
[evt
.GetId() - 1000]
1219 # Create temporary empty node (with default values)
1220 dummy
= MakeEmptyDOM(className
)
1221 if className
== 'spacer' and xxx
.className
!= 'spacer':
1223 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1224 klass
= xxxSizerItem
1226 klass
= xxxDict
[className
]
1227 # Remove non-compatible children
1228 if tree
.ItemHasChildren(selected
) and not klass
.hasChildren
:
1229 tree
.DeleteChildren(selected
)
1230 nodes
= elem
.childNodes
[:]
1233 if node
.nodeType
!= minidom
.Node
.ELEMENT_NODE
: continue
1237 if not klass
.hasChildren
: remove
= True
1238 elif tag
not in klass
.allParams
and \
1239 (not klass
.hasStyle
or tag
not in klass
.styles
):
1244 elem
.removeChild(node
)
1247 # Remove sizeritem child if spacer
1248 if className
== 'spacer' and xxx
.className
!= 'spacer':
1249 sizeritem
= elem
.parentNode
1250 assert sizeritem
.getAttribute('class') == 'sizeritem'
1251 sizeritem
.removeChild(elem
)
1254 tree
.GetPyData(selected
).hasChild
= False
1255 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1256 # Create sizeritem element
1257 assert xxx
.parent
.isSizer
1258 elem
.setAttribute('class', 'sizeritem')
1259 node
= MakeEmptyDOM(className
)
1260 elem
.appendChild(node
)
1261 # Replace to point to new object
1262 xxx
= xxxSizerItem(xxx
.parent
, elem
)
1264 tree
.SetPyData(selected
, xxx
)
1267 # Copy parameters present in dummy but not in elem
1268 for node
in dummy
.childNodes
:
1269 if node
.tagName
not in tags
: elem
.appendChild(node
.cloneNode(True))
1273 elem
.setAttribute('class', className
)
1274 if elem
.hasAttribute('subclass'):
1275 elem
.removeAttribute('subclass') # clear subclassing
1276 # Re-create xxx element
1277 xxx
= MakeXXXFromDOM(xxx
.parent
, elem
)
1278 # Remove incompatible style flags
1279 if 'style' in xxx
.params
:
1280 styles
= map(string
.strip
, xxx
.params
['style'].value().split('|'))
1281 newStyles
= [s
for s
in styles
if s
in klass
.winStyles
or s
in genericStyles
]
1282 if newStyles
!= styles
:
1284 value
= reduce(lambda a
,b
: a
+'|'+b
, newStyles
)
1287 xxx
.params
['style'].update(value
)
1289 # Update parent in child objects
1290 if tree
.ItemHasChildren(selected
):
1291 i
, cookie
= tree
.GetFirstChild(selected
)
1293 x
= tree
.GetPyData(i
)
1295 if x
.hasChild
: x
.child
.parent
= xxx
1296 i
, cookie
= tree
.GetNextChild(selected
, cookie
)
1299 if tree
.GetPyData(selected
).hasChild
: # child container
1300 container
= tree
.GetPyData(selected
)
1301 container
.resetChild(xxx
)
1304 tree
.SetPyData(selected
, xxx
)
1305 tree
.SetItemText(selected
, xxx
.treeName())
1306 tree
.SetItemImage(selected
, xxx
.treeImage())
1308 # Set default name for top-level windows
1309 if parent
.__class
__ == xxxMainNode
:
1310 cl
= xxx
.treeObject().__class
__
1311 frame
.maxIDs
[cl
] += 1
1312 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1315 g
.panel
.SetData(xxx
)
1319 #undoMan.RegisterUndo(UndoPasteCreate(parentLeaf, parent, newItem, selected))
1321 if g
.testWin
and tree
.IsHighlatable(selected
):
1322 if conf
.autoRefresh
:
1323 tree
.needUpdate
= True
1324 tree
.pendingHighLight
= selected
1326 tree
.pendingHighLight
= None
1330 # Expand/collapse subtree
1331 def OnExpand(self
, evt
):
1332 if tree
.selection
: tree
.ExpandAll(tree
.selection
)
1333 else: tree
.ExpandAll(tree
.root
)
1334 def OnCollapse(self
, evt
):
1335 if tree
.selection
: tree
.CollapseAll(tree
.selection
)
1336 else: tree
.CollapseAll(tree
.root
)
1338 def OnPullDownHighlight(self
, evt
):
1339 menuId
= evt
.GetMenuId()
1341 menu
= evt
.GetEventObject()
1343 help = menu
.GetHelpString(menuId
)
1344 self
.SetStatusText(help)
1346 self
.SetStatusText('')
1348 self
.SetStatusText('')
1350 def OnUpdateUI(self
, evt
):
1351 if evt
.GetId() in [wx
.ID_CUT
, wx
.ID_COPY
, self
.ID_DELETE
]:
1352 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1353 elif evt
.GetId() == wx
.ID_SAVE
:
1354 evt
.Enable(self
.modified
)
1355 elif evt
.GetId() in [wx
.ID_PASTE
, self
.ID_TOOL_PASTE
]:
1356 evt
.Enable(tree
.selection
is not None)
1357 elif evt
.GetId() == self
.ID_TEST
:
1358 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1359 elif evt
.GetId() in [self
.ID_LOCATE
, self
.ID_TOOL_LOCATE
]:
1360 evt
.Enable(g
.testWin
is not None)
1361 elif evt
.GetId() == wx
.ID_UNDO
: evt
.Enable(undoMan
.CanUndo())
1362 elif evt
.GetId() == wx
.ID_REDO
: evt
.Enable(undoMan
.CanRedo())
1364 def OnIdle(self
, evt
):
1365 if self
.inIdle
: return # Recursive call protection
1367 #print 'onidle',tree.needUpdate,tree.pendingHighLight
1370 if conf
.autoRefresh
:
1372 #self.SetStatusText('Refreshing test window...')
1374 tree
.CreateTestWin(g
.testWin
.item
)
1375 #self.SetStatusText('')
1376 tree
.needUpdate
= False
1377 elif tree
.pendingHighLight
:
1379 tree
.HighLight(tree
.pendingHighLight
)
1381 # Remove highlight if any problem
1382 if g
.testWin
and g
.testWin
.highLight
:
1383 g
.testWin
.highLight
.Remove()
1384 tree
.pendingHighLight
= None
1391 def OnIconize(self
, evt
):
1393 conf
.x
, conf
.y
= self
.GetPosition()
1394 conf
.width
, conf
.height
= self
.GetSize()
1396 conf
.sashPos
= self
.splitter
.GetSashPosition()
1398 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1399 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1400 self
.miniFrame
.Show(False)
1402 if not conf
.embedPanel
:
1403 self
.miniFrame
.Show(True)
1406 def OnCloseWindow(self
, evt
):
1407 if not self
.AskSave(): return
1408 if g
.testWin
: g
.testWin
.Destroy()
1409 if not panel
.GetPageCount() == 2:
1410 panel
.page2
.Destroy()
1412 # If we don't do this, page does not get destroyed (a bug?)
1414 if not self
.IsIconized():
1415 conf
.x
, conf
.y
= self
.GetPosition()
1416 if wx
.Platform
== '__WXMAC__':
1417 conf
.width
, conf
.height
= self
.GetClientSize()
1419 conf
.width
, conf
.height
= self
.GetSize()
1421 conf
.sashPos
= self
.splitter
.GetSashPosition()
1423 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1424 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1427 def CreateLocalConf(self
, path
):
1428 name
= os
.path
.splitext(path
)[0]
1430 return wx
.FileConfig(localFilename
=name
)
1434 conf
.localconf
= None
1436 self
.SetModified(False)
1442 # Numbers for new controls
1444 for cl
in [xxxPanel
, xxxDialog
, xxxFrame
,
1445 xxxMenuBar
, xxxMenu
, xxxToolBar
,
1446 xxxWizard
, xxxBitmap
, xxxIcon
]:
1448 # Restore handlers, menu, etc. to initial
1449 setHandlers(self
.handlers
[:])
1450 g
.pullDownMenu
.custom
= self
.custom
[:]
1451 # Remove modules imported from comment directives
1452 map(sys
.modules
.pop
, [m
for m
in sys
.modules
if m
not in self
.modules
])
1453 xxxParamComment
.locals = {} # clear local namespace
1454 xxxParamComment
.allow
= None # clear execution state
1456 def SetModified(self
, state
=True):
1457 self
.modified
= state
1458 name
= os
.path
.basename(self
.dataFile
)
1459 if not name
: name
= defaultName
1461 self
.SetTitle(progname
+ ': ' + name
+ ' *')
1463 self
.SetTitle(progname
+ ': ' + name
)
1465 def Open(self
, path
):
1466 if not os
.path
.exists(path
):
1467 wx
.LogError('File does not exists: %s' % path
)
1469 # Try to read the file
1473 dom
= minidom
.parse(f
)
1475 # Set encoding global variable and default encoding
1477 g
.currentEncoding
= dom
.encoding
1478 wx
.SetDefaultPyEncoding(g
.currentEncoding
.encode())
1480 g
.currentEncoding
= ''
1482 self
.dataFile
= path
= os
.path
.abspath(path
)
1483 dir = os
.path
.dirname(path
)
1484 if dir: os
.chdir(dir)
1485 # Allow importing modules from the same directory
1486 sys
.path
= sys_path
+ [dir]
1488 self
.SetTitle(progname
+ ': ' + os
.path
.basename(path
))
1489 conf
.localconf
= self
.CreateLocalConf(self
.dataFile
)
1491 # Nice exception printing
1492 inf
= sys
.exc_info()
1493 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1494 wx
.LogError('Error reading file: %s' % path
)
1499 def Indent(self
, node
, indent
= 0):
1500 if node
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1501 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1502 node
.parentNode
.insertBefore(text
, node
)
1503 return # no children
1504 # Copy child list because it will change soon
1505 children
= node
.childNodes
[:]
1506 # Main node doesn't need to be indented
1508 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1509 node
.parentNode
.insertBefore(text
, node
)
1511 # Append newline after last child, except for text nodes
1512 if children
[-1].nodeType
== minidom
.Node
.ELEMENT_NODE
:
1513 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1514 node
.appendChild(text
)
1515 # Indent children which are elements
1517 if n
.nodeType
== minidom
.Node
.ELEMENT_NODE
or \
1518 n
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1519 self
.Indent(n
, indent
+ 2)
1521 def Save(self
, path
):
1525 if tree
.selection
and panel
.IsModified():
1526 self
.OnRefresh(wx
.CommandEvent())
1527 if g
.currentEncoding
:
1528 f
= codecs
.open(path
, 'wt', g
.currentEncoding
)
1530 f
= codecs
.open(path
, 'wt')
1531 # Make temporary copy for formatting it
1532 # !!! We can't clone dom node, it works only once
1533 #self.domCopy = tree.dom.cloneNode(True)
1534 self
.domCopy
= MyDocument()
1535 mainNode
= self
.domCopy
.appendChild(tree
.mainNode
.cloneNode(True))
1536 # Remove first child (test element)
1537 testElem
= mainNode
.firstChild
1538 mainNode
.removeChild(testElem
)
1540 self
.Indent(mainNode
)
1541 self
.domCopy
.writexml(f
, encoding
= g
.currentEncoding
)
1543 self
.domCopy
.unlink()
1545 self
.SetModified(False)
1546 panel
.SetModified(False)
1547 conf
.localconf
.Flush()
1549 inf
= sys
.exc_info()
1550 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1551 wx
.LogError('Error writing file: %s' % path
)
1555 if not (self
.modified
or panel
.IsModified()): return True
1556 flags
= wx
.ICON_EXCLAMATION | wx
.YES_NO | wx
.CANCEL | wx
.CENTRE
1557 dlg
= wx
.MessageDialog( self
, 'File is modified. Save before exit?',
1558 'Save before too late?', flags
)
1559 say
= dlg
.ShowModal()
1562 if say
== wx
.ID_YES
:
1563 self
.OnSaveOrSaveAs(wx
.CommandEvent(wx
.ID_SAVE
))
1564 # If save was successful, modified flag is unset
1565 if not self
.modified
: return True
1566 elif say
== wx
.ID_NO
:
1567 self
.SetModified(False)
1568 panel
.SetModified(False)
1572 ################################################################################
1574 class PythonOptions(wx
.Dialog
):
1576 def __init__(self
, parent
, cfg
, dataFile
):
1577 pre
= wx
.PreDialog()
1578 g
.frame
.res
.LoadOnDialog(pre
, parent
, "PYTHON_OPTIONS")
1579 self
.PostCreate(pre
)
1582 self
.dataFile
= dataFile
1584 self
.AutoGenerateCB
= xrc
.XRCCTRL(self
, "AutoGenerateCB")
1585 self
.EmbedCB
= xrc
.XRCCTRL(self
, "EmbedCB")
1586 self
.GettextCB
= xrc
.XRCCTRL(self
, "GettextCB")
1587 self
.MakeXRSFileCB
= xrc
.XRCCTRL(self
, "MakeXRSFileCB")
1588 self
.FileNameTC
= xrc
.XRCCTRL(self
, "FileNameTC")
1589 self
.BrowseBtn
= xrc
.XRCCTRL(self
, "BrowseBtn")
1590 self
.GenerateBtn
= xrc
.XRCCTRL(self
, "GenerateBtn")
1591 self
.SaveOptsBtn
= xrc
.XRCCTRL(self
, "SaveOptsBtn")
1593 self
.Bind(wx
.EVT_BUTTON
, self
.OnBrowse
, self
.BrowseBtn
)
1594 self
.Bind(wx
.EVT_BUTTON
, self
.OnGenerate
, self
.GenerateBtn
)
1595 self
.Bind(wx
.EVT_BUTTON
, self
.OnSaveOpts
, self
.SaveOptsBtn
)
1597 if self
.cfg
.Read("filename", "") != "":
1598 self
.FileNameTC
.SetValue(self
.cfg
.Read("filename"))
1600 name
= os
.path
.splitext(os
.path
.split(dataFile
)[1])[0]
1602 self
.FileNameTC
.SetValue(name
)
1603 self
.AutoGenerateCB
.SetValue(self
.cfg
.ReadBool("autogenerate", False))
1604 self
.EmbedCB
.SetValue(self
.cfg
.ReadBool("embedResource", False))
1605 self
.MakeXRSFileCB
.SetValue(self
.cfg
.ReadBool("makeXRS", False))
1606 self
.GettextCB
.SetValue(self
.cfg
.ReadBool("genGettext", False))
1609 def OnBrowse(self
, evt
):
1610 path
= self
.FileNameTC
.GetValue()
1611 dirname
= os
.path
.abspath(os
.path
.dirname(path
))
1612 name
= os
.path
.split(path
)[1]
1613 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.py',
1614 wx
.SAVE | wx
.OVERWRITE_PROMPT
)
1615 if dlg
.ShowModal() == wx
.ID_OK
:
1616 path
= dlg
.GetPath()
1617 self
.FileNameTC
.SetValue(path
)
1621 def OnGenerate(self
, evt
):
1622 pypath
= self
.FileNameTC
.GetValue()
1623 embed
= self
.EmbedCB
.GetValue()
1624 genGettext
= self
.GettextCB
.GetValue()
1625 frame
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
1629 def OnSaveOpts(self
, evt
=None):
1630 self
.cfg
.Write("filename", self
.FileNameTC
.GetValue())
1631 self
.cfg
.WriteBool("autogenerate", self
.AutoGenerateCB
.GetValue())
1632 self
.cfg
.WriteBool("embedResource", self
.EmbedCB
.GetValue())
1633 self
.cfg
.WriteBool("makeXRS", self
.MakeXRSFileCB
.GetValue())
1634 self
.cfg
.WriteBool("genGettext", self
.GettextCB
.GetValue())
1636 self
.EndModal(wx
.ID_OK
)
1638 ################################################################################
1640 class PrefsDialog(wx
.Dialog
):
1642 def __init__(self
, parent
):
1643 pre
= wx
.PreDialog()
1644 g
.frame
.res
.LoadOnDialog(pre
, parent
, "DIALOG_PREFS")
1645 self
.PostCreate(pre
)
1646 self
.checkControls
= {} # map of check IDs to (control,dict,param)
1648 ##xxx = sys.modules['xxx']
1650 d
= xxx
.xxxSizerItem
.defaults_panel
1652 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_panel')
1653 id = self
.check_proportion_panel
.GetId()
1654 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1655 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_panel'),
1658 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_panel')
1659 id = self
.check_flag_panel
.GetId()
1660 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1661 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_panel'),
1664 d
= xxx
.xxxSizerItem
.defaults_control
1666 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_control')
1667 id = self
.check_proportion_panel
.GetId()
1668 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1669 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_control'),
1672 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_control')
1673 id = self
.check_flag_panel
.GetId()
1674 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1675 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_control'),
1678 for id,cdp
in self
.checkControls
.items():
1681 if isinstance(c
, wx
.SpinCtrl
):
1682 c
.SetValue(int(d
[p
]))
1685 self
.FindWindowById(id).SetValue(True)
1689 self
.radio_allow_exec
= xrc
.XRCCTRL(self
, 'radio_allow_exec')
1691 radio
= {'ask': 0, 'yes':1, 'no':2}
[g
.conf
.allowExec
]
1694 self
.radio_allow_exec
.SetSelection(radio
)
1696 def OnCheck(self
, evt
):
1697 self
.checkControls
[evt
.GetId()][0].Enable(evt
.IsChecked())
1700 ################################################################################
1702 # Parse string in form var1=val1[,var2=val2]* as dictionary
1703 def ReadDictFromString(s
):
1705 for vv
in s
.split(','):
1706 var
,val
= vv
.split(':')
1707 d
[var
.strip()] = val
1710 # Transform dictionary with strings into one string
1711 def DictToString(d
):
1712 return ','.join(map(':'.join
, d
.items()))
1715 print >> sys
.stderr
, 'usage: xrced [-dhiv] [file]'
1720 if wx
.VERSION
[:3] < MinWxVersion
:
1722 This version of XRCed may not work correctly on your version of wxWidgets. \
1723 Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion
)
1725 # Process comand-line
1728 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'dhiv')
1736 print 'XRCed version', version
1739 except getopt
.GetoptError
:
1740 if wx
.Platform
!= '__WXMAC__': # macs have some extra parameters
1741 print >> sys
.stderr
, 'Unknown option'
1745 self
.SetAppName('xrced')
1748 conf
= g
.conf
= wx
.Config(style
= wx
.CONFIG_USE_LOCAL_FILE
)
1749 conf
.localconf
= None
1750 conf
.autoRefresh
= conf
.ReadInt('autorefresh', True)
1751 pos
= conf
.ReadInt('x', -1), conf
.ReadInt('y', -1)
1752 size
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600)
1753 conf
.embedPanel
= conf
.ReadInt('embedPanel', True)
1754 conf
.showTools
= conf
.ReadInt('showTools', True)
1755 conf
.sashPos
= conf
.ReadInt('sashPos', 200)
1757 # read recently used files
1758 g
.fileHistory
= wx
.FileHistory()
1759 g
.fileHistory
.Load(conf
)
1761 if not conf
.embedPanel
:
1762 conf
.panelX
= conf
.ReadInt('panelX', -1)
1763 conf
.panelY
= conf
.ReadInt('panelY', -1)
1765 conf
.panelX
= conf
.panelY
= -1
1766 conf
.panelWidth
= conf
.ReadInt('panelWidth', 200)
1767 conf
.panelHeight
= conf
.ReadInt('panelHeight', 200)
1768 conf
.panic
= not conf
.HasEntry('nopanic')
1770 conf
.allowExec
= conf
.Read('Prefs/allowExec', 'ask')
1771 p
= 'Prefs/sizeritem_defaults_panel'
1773 if conf
.HasEntry(p
):
1774 ##sys.modules['xxx'].xxxSizerItem.defaults_panel = ReadDictFromString(conf.Read(p))
1775 xxx
.xxxSizerItem
.defaults_panel
= ReadDictFromString(conf
.Read(p
))
1776 p
= 'Prefs/sizeritem_defaults_control'
1777 if conf
.HasEntry(p
):
1778 ##sys.modules['xxx'].xxxSizerItem.defaults_control = ReadDictFromString(conf.Read(p))
1779 xxx
.xxxSizerItem
.defaults_control
= ReadDictFromString(conf
.Read(p
))
1782 wx
.FileSystem
.AddHandler(wx
.MemoryFSHandler())
1784 frame
= Frame(pos
, size
)
1785 # Mac does not set the correct size
1786 if wx
.Platform
== '__WXMAC__':
1787 frame
.SetClientSize(size
)
1791 plugins
= os
.getenv('XRCEDPATH')
1795 for dir in plugins
.split(':'):
1796 if os
.path
.isdir(dir) and \
1797 os
.path
.isfile(os
.path
.join(dir, '__init__.py')):
1799 dir = os
.path
.abspath(os
.path
.normpath(dir))
1800 sys
.path
= sys_path
+ [os
.path
.dirname(dir)]
1803 __import__(os
.path
.basename(dir), globals(), locals(), ['*'])
1805 print traceback
.print_exc()
1808 # Store important data
1809 frame
.handlers
= getHandlers()[:]
1810 frame
.custom
= g
.pullDownMenu
.custom
[:]
1811 frame
.modules
= sys
.modules
.copy()
1816 # Load file after showing
1819 frame
.open = frame
.Open(args
[0])
1827 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1828 wc
.WriteInt('x', conf
.x
)
1829 wc
.WriteInt('y', conf
.y
)
1830 wc
.WriteInt('width', conf
.width
)
1831 wc
.WriteInt('height', conf
.height
)
1832 wc
.WriteInt('embedPanel', conf
.embedPanel
)
1833 wc
.WriteInt('showTools', conf
.showTools
)
1834 if not conf
.embedPanel
:
1835 wc
.WriteInt('panelX', conf
.panelX
)
1836 wc
.WriteInt('panelY', conf
.panelY
)
1837 wc
.WriteInt('sashPos', conf
.sashPos
)
1838 wc
.WriteInt('panelWidth', conf
.panelWidth
)
1839 wc
.WriteInt('panelHeight', conf
.panelHeight
)
1840 wc
.WriteInt('nopanic', 1)
1841 g
.fileHistory
.Save(wc
)
1843 wc
.DeleteGroup('Prefs')
1844 wc
.Write('Prefs/allowExec', conf
.allowExec
)
1846 ##v = sys.modules['xxx'].xxxSizerItem.defaults_panel
1847 v
= xxx
.xxxSizerItem
.defaults_panel
1848 if v
: wc
.Write('Prefs/sizeritem_defaults_panel', DictToString(v
))
1849 ###v = sys.modules['xxx'].xxxSizerItem.defaults_control
1850 v
= xxx
.xxxSizerItem
.defaults_control
1851 if v
: wc
.Write('Prefs/sizeritem_defaults_control', DictToString(v
))
1856 app
= App(0, useBestVisual
=False)
1857 #app.SetAssertMode(wx.PYAPP_ASSERT_LOG)
1863 if __name__
== '__main__':