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 # ArtProvider for toolbar icons
103 class ToolArtProvider(wx
.ArtProvider
):
105 wx
.ArtProvider
.__init
__(self
)
107 'ART_LOCATE': images
.getLocateImage(),
108 'ART_TEST': images
.getTestImage(),
109 'ART_REFRESH': images
.getRefreshImage(),
110 'ART_AUTO_REFRESH': images
.getAutoRefreshImage(),
111 'ART_MOVEUP': images
.getMoveUpImage(),
112 'ART_MOVEDOWN': images
.getMoveDownImage(),
113 'ART_MOVELEFT': images
.getMoveLeftImage(),
114 'ART_MOVERIGHT': images
.getMoveRightImage()
116 if wx
.Platform
in ['__WXMAC__', '__WXMSW__']:
118 wx
.ART_NORMAL_FILE
: images
.getNewImage(),
119 wx
.ART_FILE_OPEN
: images
.getOpenImage(),
120 wx
.ART_FILE_SAVE
: images
.getSaveImage(),
121 wx
.ART_UNDO
: images
.getUndoImage(),
122 wx
.ART_REDO
: images
.getRedoImage(),
123 wx
.ART_CUT
: images
.getCutImage(),
124 wx
.ART_COPY
: images
.getCopyImage(),
125 wx
.ART_PASTE
: images
.getPasteImage()
127 def CreateBitmap(self
, id, client
, size
):
129 if id in self
.images
:
130 img
= self
.images
[id]
131 # Alpha not implemented completely there
132 if wx
.Platform
in ['__WXMAC__', '__WXMSW__']:
133 img
.ConvertAlphaToMask()
134 bmp
= wx
.BitmapFromImage(img
)
137 class Frame(wx
.Frame
):
138 def __init__(self
, pos
, size
):
139 wx
.Frame
.__init
__(self
, None, -1, '', pos
, size
)
141 frame
= g
.frame
= self
142 bar
= self
.CreateStatusBar(2)
143 bar
.SetStatusWidths([-1, 40])
144 self
.SetIcon(images
.getIconIcon())
146 self
.tbicon
= TaskBarIcon(self
)
153 # Load our own resources
154 self
.res
= xrc
.EmptyXmlResource()
155 # !!! Blocking of assert failure occurring in older unicode builds
157 quietlog
= wx
.LogNull()
158 self
.res
.Load(os
.path
.join(basePath
, 'xrced.xrc'))
159 except wx
._core
.PyAssertionError
:
160 print 'PyAssertionError was ignored'
163 menuBar
= wx
.MenuBar()
166 menu
.Append(wx
.ID_NEW
, '&New\tCtrl-N', 'New file')
167 menu
.AppendSeparator()
168 menu
.Append(wx
.ID_OPEN
, '&Open...\tCtrl-O', 'Open XRC file')
170 self
.recentMenu
= wx
.Menu()
171 g
.fileHistory
.UseMenu(self
.recentMenu
)
172 g
.fileHistory
.AddFilesToMenu()
173 self
.Bind(wx
.EVT_MENU
, self
.OnRecentFile
, id=wx
.ID_FILE1
, id2
=wx
.ID_FILE9
)
174 menu
.AppendMenu(-1, 'Open &Recent', self
.recentMenu
, 'Open a recent file')
176 menu
.AppendSeparator()
177 menu
.Append(wx
.ID_SAVE
, '&Save\tCtrl-S', 'Save XRC file')
178 menu
.Append(wx
.ID_SAVEAS
, 'Save &As...', 'Save XRC file under different name')
179 self
.ID_GENERATE_PYTHON
= wx
.NewId()
180 menu
.Append(self
.ID_GENERATE_PYTHON
, '&Generate Python...',
181 'Generate a Python module that uses this XRC')
182 menu
.AppendSeparator()
183 self
.ID_PREFS
= wx
.NewId()
184 menu
.Append(self
.ID_PREFS
, 'Preferences...', 'Change XRCed settings')
185 menu
.AppendSeparator()
186 menu
.Append(wx
.ID_EXIT
, '&Quit\tCtrl-Q', 'Exit application')
188 menuBar
.Append(menu
, '&File')
191 menu
.Append(wx
.ID_UNDO
, '&Undo\tCtrl-Z', 'Undo')
192 menu
.Append(wx
.ID_REDO
, '&Redo\tCtrl-Y', 'Redo')
193 menu
.AppendSeparator()
194 menu
.Append(wx
.ID_CUT
, 'Cut\tCtrl-X', 'Cut to the clipboard')
195 menu
.Append(wx
.ID_COPY
, '&Copy\tCtrl-C', 'Copy to the clipboard')
196 menu
.Append(wx
.ID_PASTE
, '&Paste\tCtrl-V', 'Paste from the clipboard')
197 self
.ID_DELETE
= wx
.NewId()
198 menu
.Append(self
.ID_DELETE
, '&Delete\tCtrl-D', 'Delete object')
199 menu
.AppendSeparator()
200 self
.ID_LOCATE
= wx
.NewId()
201 self
.ID_TOOL_LOCATE
= wx
.NewId()
202 self
.ART_LOCATE
= 'ART_LOCATE'
203 self
.ID_TOOL_PASTE
= wx
.NewId()
204 menu
.Append(self
.ID_LOCATE
, '&Locate\tCtrl-L', 'Locate control in test window and select it')
205 menuBar
.Append(menu
, '&Edit')
207 self
.ID_EMBED_PANEL
= wx
.NewId()
208 menu
.Append(self
.ID_EMBED_PANEL
, '&Embed Panel',
209 'Toggle embedding properties panel in the main window', True)
210 menu
.Check(self
.ID_EMBED_PANEL
, conf
.embedPanel
)
211 self
.ID_SHOW_TOOLS
= wx
.NewId()
212 menu
.Append(self
.ID_SHOW_TOOLS
, 'Show &Tools', 'Toggle tools', True)
213 menu
.Check(self
.ID_SHOW_TOOLS
, conf
.showTools
)
214 menu
.AppendSeparator()
215 self
.ID_TEST
= wx
.NewId()
216 self
.ART_TEST
= 'ART_TEST'
217 menu
.Append(self
.ID_TEST
, '&Test\tF5', 'Show test window')
218 self
.ID_REFRESH
= wx
.NewId()
219 self
.ART_REFRESH
= 'ART_REFRESH'
220 menu
.Append(self
.ID_REFRESH
, '&Refresh\tCtrl-R', 'Refresh test window')
221 self
.ID_AUTO_REFRESH
= wx
.NewId()
222 self
.ART_AUTO_REFRESH
= 'ART_AUTO_REFRESH'
223 menu
.Append(self
.ID_AUTO_REFRESH
, '&Auto-refresh\tAlt-A',
224 'Toggle auto-refresh mode', True)
225 menu
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
226 self
.ID_TEST_HIDE
= wx
.NewId()
227 menu
.Append(self
.ID_TEST_HIDE
, '&Hide\tF6', 'Close test window')
228 menuBar
.Append(menu
, '&View')
231 self
.ID_MOVEUP
= wx
.NewId()
232 self
.ART_MOVEUP
= 'ART_MOVEUP'
233 menu
.Append(self
.ID_MOVEUP
, '&Up', 'Move before previous sibling')
234 self
.ID_MOVEDOWN
= wx
.NewId()
235 self
.ART_MOVEDOWN
= 'ART_MOVEDOWN'
236 menu
.Append(self
.ID_MOVEDOWN
, '&Down', 'Move after next sibling')
237 self
.ID_MOVELEFT
= wx
.NewId()
238 self
.ART_MOVELEFT
= 'ART_MOVELEFT'
239 menu
.Append(self
.ID_MOVELEFT
, '&Make sibling', 'Make sibling of parent')
240 self
.ID_MOVERIGHT
= wx
.NewId()
241 self
.ART_MOVERIGHT
= 'ART_MOVERIGHT'
242 menu
.Append(self
.ID_MOVERIGHT
, '&Make child', 'Make child of previous sibling')
243 menuBar
.Append(menu
, '&Move')
246 menu
.Append(wx
.ID_ABOUT
, '&About...', 'About XCRed')
247 self
.ID_README
= wx
.NewId()
248 menu
.Append(self
.ID_README
, '&Readme...\tF1', 'View the README file')
250 self
.ID_DEBUG_CMD
= wx
.NewId()
251 menu
.Append(self
.ID_DEBUG_CMD
, 'CMD', 'Python command line')
252 wx
.EVT_MENU(self
, self
.ID_DEBUG_CMD
, self
.OnDebugCMD
)
253 menuBar
.Append(menu
, '&Help')
255 self
.menuBar
= menuBar
256 self
.SetMenuBar(menuBar
)
259 tb
= self
.CreateToolBar(wx
.TB_HORIZONTAL | wx
.NO_BORDER | wx
.TB_FLAT
)
260 if wx
.Platform
!= '__WXMAC__':
261 # Redefine AddSeparator on wxGTK and wxMSW to add vertical line
263 tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23),
264 style
=wx
.LI_VERTICAL
))
265 tb
.AddSeparator
= _AddSeparator
267 # Use tango icons and slightly wider bitmap size on Mac
268 if wx
.Platform
in ['__WXMAC__', '__WXMSW__']:
269 tb
.SetToolBitmapSize((26,26))
271 tb
.SetToolBitmapSize((24,24))
272 new_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_NORMAL_FILE
, wx
.ART_TOOLBAR
)
273 open_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_OPEN
, wx
.ART_TOOLBAR
)
274 save_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_SAVE
, wx
.ART_TOOLBAR
)
275 undo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_UNDO
, wx
.ART_TOOLBAR
)
276 redo_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_REDO
, wx
.ART_TOOLBAR
)
277 cut_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_CUT
, wx
.ART_TOOLBAR
)
278 copy_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_COPY
, wx
.ART_TOOLBAR
)
279 paste_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_PASTE
, wx
.ART_TOOLBAR
)
280 tb
.AddSimpleTool(wx
.ID_NEW
, new_bmp
, 'New', 'New file')
281 tb
.AddSimpleTool(wx
.ID_OPEN
, open_bmp
, 'Open', 'Open file')
282 tb
.AddSimpleTool(wx
.ID_SAVE
, save_bmp
, 'Save', 'Save file')
284 tb
.AddSimpleTool(wx
.ID_UNDO
, undo_bmp
, 'Undo', 'Undo')
285 tb
.AddSimpleTool(wx
.ID_REDO
, redo_bmp
, 'Redo', 'Redo')
287 tb
.AddSimpleTool(wx
.ID_CUT
, cut_bmp
, 'Cut', 'Cut')
288 tb
.AddSimpleTool(wx
.ID_COPY
, copy_bmp
, 'Copy', 'Copy')
289 tb
.AddSimpleTool(self
.ID_TOOL_PASTE
, paste_bmp
, 'Paste', 'Paste')
291 bmp
= wx
.ArtProvider
.GetBitmap(self
.ART_LOCATE
, wx
.ART_TOOLBAR
)
292 tb
.AddSimpleTool(self
.ID_TOOL_LOCATE
, bmp
,
293 'Locate', 'Locate control in test window and select it', True)
294 bmp
= wx
.ArtProvider
.GetBitmap(self
.ART_TEST
, wx
.ART_TOOLBAR
)
295 tb
.AddSimpleTool(self
.ID_TEST
, bmp
, 'Test', 'Test window')
296 bmp
= wx
.ArtProvider
.GetBitmap(self
.ART_REFRESH
, wx
.ART_TOOLBAR
)
297 tb
.AddSimpleTool(self
.ID_REFRESH
, bmp
, 'Refresh', 'Refresh view')
298 bmp
= wx
.ArtProvider
.GetBitmap(self
.ART_AUTO_REFRESH
, wx
.ART_TOOLBAR
)
299 tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, bmp
,
300 'Auto-refresh', 'Toggle auto-refresh mode', True)
302 bmp
= wx
.ArtProvider
.GetBitmap(self
.ART_MOVEUP
, wx
.ART_TOOLBAR
)
303 tb
.AddSimpleTool(self
.ID_MOVEUP
, bmp
,
304 'Up', 'Move before previous sibling')
305 bmp
= wx
.ArtProvider
.GetBitmap(self
.ART_MOVEDOWN
, wx
.ART_TOOLBAR
)
306 tb
.AddSimpleTool(self
.ID_MOVEDOWN
, bmp
,
307 'Down', 'Move after next sibling')
308 bmp
= wx
.ArtProvider
.GetBitmap(self
.ART_MOVELEFT
, wx
.ART_TOOLBAR
)
309 tb
.AddSimpleTool(self
.ID_MOVELEFT
, bmp
,
310 'Make Sibling', 'Make sibling of parent')
311 bmp
= wx
.ArtProvider
.GetBitmap(self
.ART_MOVERIGHT
, wx
.ART_TOOLBAR
)
312 tb
.AddSimpleTool(self
.ID_MOVERIGHT
, bmp
,
313 'Make Child', 'Make child of previous sibling')
314 tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
318 self
.minWidth
= tb
.GetSize()[0] # minimal width is the size of toolbar
321 wx
.EVT_MENU(self
, wx
.ID_NEW
, self
.OnNew
)
322 wx
.EVT_MENU(self
, wx
.ID_OPEN
, self
.OnOpen
)
323 wx
.EVT_MENU(self
, wx
.ID_SAVE
, self
.OnSaveOrSaveAs
)
324 wx
.EVT_MENU(self
, wx
.ID_SAVEAS
, self
.OnSaveOrSaveAs
)
325 wx
.EVT_MENU(self
, self
.ID_GENERATE_PYTHON
, self
.OnGeneratePython
)
326 wx
.EVT_MENU(self
, self
.ID_PREFS
, self
.OnPrefs
)
327 wx
.EVT_MENU(self
, wx
.ID_EXIT
, self
.OnExit
)
329 wx
.EVT_MENU(self
, wx
.ID_UNDO
, self
.OnUndo
)
330 wx
.EVT_MENU(self
, wx
.ID_REDO
, self
.OnRedo
)
331 wx
.EVT_MENU(self
, wx
.ID_CUT
, self
.OnCutDelete
)
332 wx
.EVT_MENU(self
, wx
.ID_COPY
, self
.OnCopy
)
333 wx
.EVT_MENU(self
, wx
.ID_PASTE
, self
.OnPaste
)
334 wx
.EVT_MENU(self
, self
.ID_TOOL_PASTE
, self
.OnPaste
)
335 wx
.EVT_MENU(self
, self
.ID_DELETE
, self
.OnCutDelete
)
336 wx
.EVT_MENU(self
, self
.ID_LOCATE
, self
.OnLocate
)
337 wx
.EVT_MENU(self
, self
.ID_TOOL_LOCATE
, self
.OnLocate
)
339 wx
.EVT_MENU(self
, self
.ID_EMBED_PANEL
, self
.OnEmbedPanel
)
340 wx
.EVT_MENU(self
, self
.ID_SHOW_TOOLS
, self
.OnShowTools
)
341 wx
.EVT_MENU(self
, self
.ID_TEST
, self
.OnTest
)
342 wx
.EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
)
343 wx
.EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
)
344 wx
.EVT_MENU(self
, self
.ID_TEST_HIDE
, self
.OnTestHide
)
346 wx
.EVT_MENU(self
, self
.ID_MOVEUP
, self
.OnMoveUp
)
347 wx
.EVT_MENU(self
, self
.ID_MOVEDOWN
, self
.OnMoveDown
)
348 wx
.EVT_MENU(self
, self
.ID_MOVELEFT
, self
.OnMoveLeft
)
349 wx
.EVT_MENU(self
, self
.ID_MOVERIGHT
, self
.OnMoveRight
)
351 wx
.EVT_MENU(self
, wx
.ID_ABOUT
, self
.OnAbout
)
352 wx
.EVT_MENU(self
, self
.ID_README
, self
.OnReadme
)
355 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVE
, self
.OnUpdateUI
)
356 wx
.EVT_UPDATE_UI(self
, wx
.ID_CUT
, self
.OnUpdateUI
)
357 wx
.EVT_UPDATE_UI(self
, wx
.ID_COPY
, self
.OnUpdateUI
)
358 wx
.EVT_UPDATE_UI(self
, wx
.ID_PASTE
, self
.OnUpdateUI
)
359 wx
.EVT_UPDATE_UI(self
, self
.ID_LOCATE
, self
.OnUpdateUI
)
360 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_LOCATE
, self
.OnUpdateUI
)
361 wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_PASTE
, self
.OnUpdateUI
)
362 wx
.EVT_UPDATE_UI(self
, wx
.ID_UNDO
, self
.OnUpdateUI
)
363 wx
.EVT_UPDATE_UI(self
, wx
.ID_REDO
, self
.OnUpdateUI
)
364 wx
.EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
)
365 wx
.EVT_UPDATE_UI(self
, self
.ID_TEST
, self
.OnUpdateUI
)
366 wx
.EVT_UPDATE_UI(self
, self
.ID_MOVEUP
, self
.OnUpdateUI
)
367 wx
.EVT_UPDATE_UI(self
, self
.ID_MOVEDOWN
, self
.OnUpdateUI
)
368 wx
.EVT_UPDATE_UI(self
, self
.ID_MOVELEFT
, self
.OnUpdateUI
)
369 wx
.EVT_UPDATE_UI(self
, self
.ID_MOVERIGHT
, self
.OnUpdateUI
)
370 wx
.EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
)
373 sizer
= wx
.BoxSizer(wx
.VERTICAL
)
374 #sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND)
375 # Horizontal sizer for toolbar and splitter
376 self
.toolsSizer
= sizer1
= wx
.BoxSizer()
377 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.SP_3DSASH
)
378 self
.splitter
= splitter
379 splitter
.SetMinimumPaneSize(100)
382 g
.tree
= tree
= XML_Tree(splitter
, -1)
384 # Init pull-down menu data
386 g
.pullDownMenu
= pullDownMenu
= PullDownMenu(self
)
388 # Vertical toolbar for GUI buttons
389 g
.tools
= tools
= Tools(self
)
390 tools
.Show(conf
.showTools
)
391 if conf
.showTools
: sizer1
.Add(tools
, 0, wx
.EXPAND
)
393 tree
.RegisterKeyEvents()
395 # Miniframe for split mode
396 miniFrame
= wx
.MiniFrame(self
, -1, 'Properties & Style',
397 (conf
.panelX
, conf
.panelY
),
398 (conf
.panelWidth
, conf
.panelHeight
))
399 self
.miniFrame
= miniFrame
400 sizer2
= wx
.BoxSizer()
401 miniFrame
.SetSizer(sizer2
)
402 # Create panel for parameters
405 panel
= Panel(splitter
)
406 # Set plitter windows
407 splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
409 panel
= Panel(miniFrame
)
410 sizer2
.Add(panel
, 1, wx
.EXPAND
)
412 splitter
.Initialize(tree
)
413 if wx
.Platform
== '__WXMAC__':
414 sizer1
.Add(splitter
, 1, wx
.EXPAND|wx
.RIGHT
, 5)
416 sizer1
.Add(splitter
, 1, wx
.EXPAND
)
417 sizer
.Add(sizer1
, 1, wx
.EXPAND
)
418 self
.SetAutoLayout(True)
422 wx
.EVT_IDLE(self
, self
.OnIdle
)
423 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
424 wx
.EVT_KEY_DOWN(self
, tools
.OnKeyDown
)
425 wx
.EVT_KEY_UP(self
, tools
.OnKeyUp
)
426 wx
.EVT_ICONIZE(self
, self
.OnIconize
)
428 def OnRecentFile(self
,evt
):
429 # open recently used file
430 if not self
.AskSave(): return
433 # get the pathname based on the menu ID
434 fileNum
= evt
.GetId() - wx
.ID_FILE1
435 path
= g
.fileHistory
.GetHistoryFile(fileNum
)
438 self
.SetStatusText('Data loaded')
439 # add it back to the history so it will be moved up the list
440 self
.SaveRecent(path
)
442 self
.SetStatusText('Failed')
446 def OnNew(self
, evt
):
447 if not self
.AskSave(): return
450 def OnOpen(self
, evt
):
451 if not self
.AskSave(): return
452 dlg
= wx
.FileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
),
453 '', '*.xrc', wx
.OPEN | wx
.CHANGE_DIR
)
454 if dlg
.ShowModal() == wx
.ID_OK
:
456 self
.SetStatusText('Loading...')
460 self
.SetStatusText('Data loaded')
461 self
.SaveRecent(path
)
463 self
.SetStatusText('Failed')
468 def OnSaveOrSaveAs(self
, evt
):
469 if evt
.GetId() == wx
.ID_SAVEAS
or not self
.dataFile
:
470 if self
.dataFile
: name
= ''
471 else: name
= defaultName
472 dirname
= os
.path
.abspath(os
.path
.dirname(self
.dataFile
))
473 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.xrc',
474 wx
.SAVE | wx
.OVERWRITE_PROMPT | wx
.CHANGE_DIR
)
475 if dlg
.ShowModal() == wx
.ID_OK
:
477 if isinstance(path
, unicode):
478 path
= path
.encode(sys
.getfilesystemencoding())
485 # if we already have a localconf then it needs to be
486 # copied to a new config with the new name
488 nc
= self
.CreateLocalConf(path
)
489 flag
, key
, idx
= lc
.GetFirstEntry()
491 nc
.Write(key
, lc
.Read(key
))
492 flag
, key
, idx
= lc
.GetNextEntry(idx
)
495 # otherwise create a new one
496 conf
.localconf
= self
.CreateLocalConf(path
)
499 self
.SetStatusText('Saving...')
503 tmpFile
,tmpName
= tempfile
.mkstemp(prefix
='xrced-')
505 self
.Save(tmpName
) # save temporary file first
506 shutil
.move(tmpName
, path
)
508 self
.SetModified(False)
509 if conf
.localconf
.ReadBool("autogenerate", False):
510 pypath
= conf
.localconf
.Read("filename")
511 embed
= conf
.localconf
.ReadBool("embedResource", False)
512 genGettext
= conf
.localconf
.ReadBool("genGettext", False)
513 self
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
515 self
.SetStatusText('Data saved')
516 self
.SaveRecent(path
)
518 self
.SetStatusText('Failed')
522 def SaveRecent(self
,path
):
523 # append to recently used files
524 g
.fileHistory
.AddFileToHistory(path
)
526 def GeneratePython(self
, dataFile
, pypath
, embed
, genGettext
):
528 import wx
.tools
.pywxrc
529 rescomp
= wx
.tools
.pywxrc
.XmlResourceCompiler()
530 rescomp
.MakePythonModule([dataFile
], pypath
, embed
, genGettext
)
533 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
534 wx
.LogError('Error generating python code : %s' % pypath
)
538 def OnGeneratePython(self
, evt
):
539 if self
.modified
or not conf
.localconf
:
540 wx
.MessageBox("Save the XRC file first!", "Error")
543 dlg
= PythonOptions(self
, conf
.localconf
, self
.dataFile
)
547 def OnPrefs(self
, evt
):
548 dlg
= PrefsDialog(self
)
549 if dlg
.ShowModal() == wx
.ID_OK
:
550 # Fetch new preferences
551 for id,cdp
in dlg
.checkControls
.items():
553 if dlg
.FindWindowById(id).IsChecked():
554 d
[p
] = str(c
.GetValue())
555 elif p
in d
: del d
[p
]
556 g
.conf
.allowExec
= ('ask', 'yes', 'no')[dlg
.radio_allow_exec
.GetSelection()]
559 def OnExit(self
, evt
):
562 def OnUndo(self
, evt
):
563 # Extra check to not mess with idle updating
564 if undoMan
.CanUndo():
566 g
.panel
.SetModified(False)
567 if not undoMan
.CanUndo():
568 self
.SetModified(False)
570 def OnRedo(self
, evt
):
571 if undoMan
.CanRedo():
573 self
.SetModified(True)
575 def OnCopy(self
, evt
):
576 selected
= tree
.selection
577 if not selected
: return # key pressed event
578 xxx
= tree
.GetPyData(selected
)
579 if wx
.TheClipboard
.Open():
581 data
= wx
.CustomDataObject('XRCED')
582 # Set encoding in header
584 s
= xxx
.node
.toxml(encoding
=expat
.native_encoding
)
586 data
= wx
.CustomDataObject('XRCED_node')
588 data
.SetData(cPickle
.dumps(s
))
589 wx
.TheClipboard
.SetData(data
)
590 wx
.TheClipboard
.Close()
591 self
.SetStatusText('Copied')
593 wx
.MessageBox("Unable to open the clipboard", "Error")
595 def OnPaste(self
, evt
):
596 selected
= tree
.selection
597 if not selected
: return # key pressed event
598 # For pasting with Ctrl pressed
600 if evt
.GetId() == pullDownMenu
.ID_PASTE_SIBLING
: appendChild
= False
601 elif evt
.GetId() == self
.ID_TOOL_PASTE
:
602 if g
.tree
.ctrl
: appendChild
= False
603 else: appendChild
= not tree
.NeedInsert(selected
)
604 else: appendChild
= not tree
.NeedInsert(selected
)
605 xxx
= tree
.GetPyData(selected
)
607 # If has next item, insert, else append to parent
608 nextItem
= tree
.GetNextSibling(selected
)
609 parentLeaf
= tree
.GetItemParent(selected
)
610 # Expanded container (must have children)
611 elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, False):
612 # Insert as first child
613 nextItem
= tree
.GetFirstChild(selected
)[0]
614 parentLeaf
= selected
616 # No children or unexpanded item - appendChild stays True
617 nextItem
= wx
.TreeItemId() # no next item
618 parentLeaf
= selected
619 parent
= tree
.GetPyData(parentLeaf
).treeObject()
621 # Create a copy of clipboard pickled element
622 success
= success_node
= False
623 if wx
.TheClipboard
.Open():
625 data
= wx
.CustomDataObject('XRCED')
626 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
628 success
= wx
.TheClipboard
.GetData(data
)
630 # there is a problem if XRCED_node is in clipboard
631 # but previous SetData was for XRCED
633 if not success
: # try other format
634 data
= wx
.CustomDataObject('XRCED_node')
635 if wx
.TheClipboard
.IsSupported(data
.GetFormat()):
636 success_node
= wx
.TheClipboard
.GetData(data
)
638 wx
.TheClipboard
.Close()
640 if not success
and not success_node
:
642 "There is no data in the clipboard in the required format",
646 xml
= cPickle
.loads(data
.GetData()) # xml representation of element
648 elem
= minidom
.parseString(xml
).childNodes
[0]
650 elem
= g
.tree
.dom
.createComment(xml
)
652 # Tempopary xxx object to test things
653 xxx
= MakeXXXFromDOM(parent
, elem
)
655 # Check compatibility
656 if not self
.ItemsAreCompatible(parent
, xxx
.treeObject()): return
658 # Check parent and child relationships.
659 # If parent is sizer or notebook, child is of wrong class or
660 # parent is normal window, child is child container then detach child.
661 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
662 parentIsBook
= parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]
663 if isChildContainer
and \
664 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
665 (parentIsBook
and not isinstance(xxx
, xxxPage
)) or \
666 not (parent
.isSizer
or parentIsBook
)):
667 elem
.removeChild(xxx
.child
.node
) # detach child
668 elem
.unlink() # delete child container
669 elem
= xxx
.child
.node
# replace
670 # This may help garbage collection
671 xxx
.child
.parent
= None
672 isChildContainer
= False
673 # Parent is sizer or notebook, child is not child container
674 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
675 # Create sizer item element
676 sizerItemElem
= MakeEmptyDOM(parent
.itemTag
)
677 sizerItemElem
.appendChild(elem
)
679 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
680 pageElem
= MakeEmptyDOM('notebookpage')
681 pageElem
.appendChild(elem
)
683 elif isinstance(parent
, xxxChoicebook
) and not isChildContainer
:
684 pageElem
= MakeEmptyDOM('choicebookpage')
685 pageElem
.appendChild(elem
)
687 elif isinstance(parent
, xxxListbook
) and not isChildContainer
:
688 pageElem
= MakeEmptyDOM('listbookpage')
689 pageElem
.appendChild(elem
)
691 # Insert new node, register undo
692 newItem
= tree
.InsertNode(parentLeaf
, parent
, elem
, nextItem
)
693 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
694 # Scroll to show new item (!!! redundant?)
695 tree
.EnsureVisible(newItem
)
696 tree
.SelectItem(newItem
)
697 if not tree
.IsVisible(newItem
):
698 tree
.ScrollTo(newItem
)
701 if g
.testWin
and tree
.IsHighlatable(newItem
):
703 tree
.needUpdate
= True
704 tree
.pendingHighLight
= newItem
706 tree
.pendingHighLight
= None
708 self
.SetStatusText('Pasted')
711 def ItemsAreCompatible(self
, parent
, child
):
712 # Check compatibility
714 # Comments are always compatible
715 if child
.__class
__ == xxxComment
:
718 if child
.__class
__ in [xxxDialog
, xxxFrame
, xxxWizard
]:
720 if parent
.__class
__ != xxxMainNode
: error
= True
721 elif child
.__class
__ == xxxMenuBar
:
722 # Menubar can be put in frame or dialog
723 if parent
.__class
__ not in [xxxMainNode
, xxxFrame
, xxxDialog
]: error
= True
724 elif child
.__class
__ == xxxToolBar
:
725 # Toolbar can be top-level of child of panel or frame
726 if parent
.__class
__ not in [xxxMainNode
, xxxPanel
, xxxFrame
] and \
727 not parent
.isSizer
: error
= True
728 elif child
.__class
__ == xxxPanel
and parent
.__class
__ == xxxMainNode
:
730 elif child
.__class
__ == xxxSpacer
:
731 if not parent
.isSizer
: error
= True
732 elif child
.__class
__ == xxxSeparator
:
733 if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error
= True
734 elif child
.__class
__ == xxxTool
:
735 if parent
.__class
__ != xxxToolBar
: error
= True
736 elif child
.__class
__ == xxxMenu
:
737 if not parent
.__class
__ in [xxxMainNode
, xxxMenuBar
, xxxMenu
]: error
= True
738 elif child
.__class
__ == xxxMenuItem
:
739 if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
740 elif child
.isSizer
and parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]:
742 else: # normal controls can be almost anywhere
743 if parent
.__class
__ == xxxMainNode
or \
744 parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error
= True
746 if parent
.__class
__ == xxxMainNode
: parentClass
= 'root'
747 else: parentClass
= parent
.className
748 wx
.LogError('Incompatible parent/child: parent is %s, child is %s!' %
749 (parentClass
, child
.className
))
753 def OnMoveUp(self
, evt
):
754 selected
= tree
.selection
755 if not selected
: return
757 index
= tree
.ItemIndex(selected
)
758 if index
== 0: return # No previous sibling found
760 # Remove highlight, update testWin
761 if g
.testWin
and g
.testWin
.highLight
:
762 g
.testWin
.highLight
.Remove()
763 tree
.needUpdate
= True
766 self
.lastOp
= 'MOVEUP'
767 status
= 'Moved before previous sibling'
773 parent
= tree
.GetItemParent(selected
)
774 elem
= tree
.RemoveLeaf(selected
)
775 nextItem
= tree
.GetFirstChild(parent
)[0]
776 for i
in range(index
- 1): nextItem
= tree
.GetNextSibling(nextItem
)
777 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
778 newIndex
= tree
.ItemIndex(selected
)
779 tree
.SelectItem(selected
)
781 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
784 self
.SetStatusText(status
)
788 def OnMoveDown(self
, evt
):
789 selected
= tree
.selection
790 if not selected
: return
792 index
= tree
.ItemIndex(selected
)
793 next
= tree
.GetNextSibling(selected
)
796 # Remove highlight, update testWin
797 if g
.testWin
and g
.testWin
.highLight
:
798 g
.testWin
.highLight
.Remove()
799 tree
.needUpdate
= True
802 self
.lastOp
= 'MOVEDOWN'
803 status
= 'Moved after next sibling'
809 parent
= tree
.GetItemParent(selected
)
810 elem
= tree
.RemoveLeaf(selected
)
811 nextItem
= tree
.GetFirstChild(parent
)[0]
812 for i
in range(index
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
813 selected
= tree
.InsertNode(parent
, tree
.GetPyData(parent
).treeObject(), elem
, nextItem
)
814 newIndex
= tree
.ItemIndex(selected
)
815 tree
.SelectItem(selected
)
817 undoMan
.RegisterUndo(UndoMove(parent
, index
, parent
, newIndex
))
820 self
.SetStatusText(status
)
824 def OnMoveLeft(self
, evt
):
825 selected
= tree
.selection
826 if not selected
: return
828 oldParent
= tree
.GetItemParent(selected
)
829 if not oldParent
: return
830 pparent
= tree
.GetItemParent(oldParent
)
831 if not pparent
: return
833 # Check compatibility
834 if not self
.ItemsAreCompatible(tree
.GetPyData(pparent
).treeObject(), tree
.GetPyData(selected
).treeObject()): return
836 if g
.testWin
and g
.testWin
.highLight
:
837 g
.testWin
.highLight
.Remove()
838 tree
.needUpdate
= True
841 self
.lastOp
= 'MOVELEFT'
842 status
= 'Made next sibling of parent'
844 oldIndex
= tree
.ItemIndex(selected
)
845 elem
= tree
.RemoveLeaf(selected
)
846 nextItem
= tree
.GetFirstChild(pparent
)[0]
847 parentIndex
= tree
.ItemIndex(oldParent
)
848 for i
in range(parentIndex
+ 1): nextItem
= tree
.GetNextSibling(nextItem
)
850 # Check parent and child relationships.
851 # If parent is sizer or notebook, child is of wrong class or
852 # parent is normal window, child is child container then detach child.
853 parent
= tree
.GetPyData(pparent
).treeObject()
854 xxx
= MakeXXXFromDOM(parent
, elem
)
855 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
856 if isChildContainer
and \
857 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
858 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
859 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
860 elem
.removeChild(xxx
.child
.node
) # detach child
861 elem
.unlink() # delete child container
862 elem
= xxx
.child
.node
# replace
863 # This may help garbage collection
864 xxx
.child
.parent
= None
865 isChildContainer
= False
866 # Parent is sizer or notebook, child is not child container
867 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
868 # Create sizer item element
869 sizerItemElem
= MakeEmptyDOM('sizeritem')
870 sizerItemElem
.appendChild(elem
)
872 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
873 pageElem
= MakeEmptyDOM('notebookpage')
874 pageElem
.appendChild(elem
)
877 selected
= tree
.InsertNode(pparent
, tree
.GetPyData(pparent
).treeObject(), elem
, nextItem
)
878 newIndex
= tree
.ItemIndex(selected
)
879 tree
.SelectItem(selected
)
881 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, pparent
, newIndex
))
884 self
.SetStatusText(status
)
886 def OnMoveRight(self
, evt
):
887 selected
= tree
.selection
888 if not selected
: return
890 oldParent
= tree
.GetItemParent(selected
)
891 if not oldParent
: return
893 newParent
= tree
.GetPrevSibling(selected
)
894 if not newParent
: return
896 parent
= tree
.GetPyData(newParent
).treeObject()
898 # Check compatibility
899 if not self
.ItemsAreCompatible(parent
, tree
.GetPyData(selected
).treeObject()): return
901 # Remove highlight, update testWin
902 if g
.testWin
and g
.testWin
.highLight
:
903 g
.testWin
.highLight
.Remove()
904 tree
.needUpdate
= True
907 self
.lastOp
= 'MOVERIGHT'
908 status
= 'Made last child of previous sibling'
910 oldIndex
= tree
.ItemIndex(selected
)
911 elem
= tree
.RemoveLeaf(selected
)
913 # Check parent and child relationships.
914 # If parent is sizer or notebook, child is of wrong class or
915 # parent is normal window, child is child container then detach child.
916 xxx
= MakeXXXFromDOM(parent
, elem
)
917 isChildContainer
= isinstance(xxx
, xxxChildContainer
)
918 if isChildContainer
and \
919 ((parent
.isSizer
and not isinstance(xxx
, xxxSizerItem
)) or \
920 (isinstance(parent
, xxxNotebook
) and not isinstance(xxx
, xxxNotebookPage
)) or \
921 not (parent
.isSizer
or isinstance(parent
, xxxNotebook
))):
922 elem
.removeChild(xxx
.child
.node
) # detach child
923 elem
.unlink() # delete child container
924 elem
= xxx
.child
.node
# replace
925 # This may help garbage collection
926 xxx
.child
.parent
= None
927 isChildContainer
= False
928 # Parent is sizer or notebook, child is not child container
929 if parent
.isSizer
and not isChildContainer
and not isinstance(xxx
, xxxSpacer
):
930 # Create sizer item element
931 sizerItemElem
= MakeEmptyDOM('sizeritem')
932 sizerItemElem
.appendChild(elem
)
934 elif isinstance(parent
, xxxNotebook
) and not isChildContainer
:
935 pageElem
= MakeEmptyDOM('notebookpage')
936 pageElem
.appendChild(elem
)
939 selected
= tree
.InsertNode(newParent
, tree
.GetPyData(newParent
).treeObject(), elem
, wx
.TreeItemId())
941 newIndex
= tree
.ItemIndex(selected
)
942 tree
.SelectItem(selected
)
944 undoMan
.RegisterUndo(UndoMove(oldParent
, oldIndex
, newParent
, newIndex
))
947 self
.SetStatusText(status
)
949 def OnCutDelete(self
, evt
):
950 selected
= tree
.selection
951 if not selected
: return # key pressed event
953 if evt
.GetId() == wx
.ID_CUT
:
955 status
= 'Removed to clipboard'
957 self
.lastOp
= 'DELETE'
961 # If deleting top-level item, delete testWin
962 if selected
== g
.testWin
.item
:
966 # Remove highlight, update testWin
967 if g
.testWin
.highLight
:
968 g
.testWin
.highLight
.Remove()
969 tree
.needUpdate
= True
972 index
= tree
.ItemFullIndex(selected
)
973 xxx
= tree
.GetPyData(selected
)
974 parent
= tree
.GetPyData(tree
.GetItemParent(selected
)).treeObject()
976 elem
= tree
.RemoveLeaf(selected
)
977 undoMan
.RegisterUndo(UndoCutDelete(index
, parent
, elem
))
978 if evt
.GetId() == wx
.ID_CUT
:
979 if wx
.TheClipboard
.Open():
981 data
= wx
.CustomDataObject('XRCED')
983 s
= elem
.toxml(encoding
=expat
.native_encoding
)
985 data
= wx
.CustomDataObject('XRCED_node')
987 data
.SetData(cPickle
.dumps(s
))
988 wx
.TheClipboard
.SetData(data
)
989 wx
.TheClipboard
.Close()
991 wx
.MessageBox("Unable to open the clipboard", "Error")
992 tree
.pendingHighLight
= None
996 self
.SetStatusText(status
)
998 def OnSubclass(self
, evt
):
999 selected
= tree
.selection
1000 xxx
= tree
.GetPyData(selected
).treeObject()
1002 subclass
= xxx
.subclass
1003 dlg
= wx
.TextEntryDialog(self
, 'Subclass:', defaultValue
=subclass
)
1004 if dlg
.ShowModal() == wx
.ID_OK
:
1005 subclass
= dlg
.GetValue()
1007 elem
.setAttribute('subclass', subclass
)
1008 elif elem
.hasAttribute('subclass'):
1009 elem
.removeAttribute('subclass')
1011 xxx
.subclass
= elem
.getAttribute('subclass')
1012 tree
.SetItemText(selected
, xxx
.treeName())
1013 panel
.pages
[0].box
.SetLabel(xxx
.panelName())
1016 def OnEmbedPanel(self
, evt
):
1017 conf
.embedPanel
= evt
.IsChecked()
1019 # Remember last dimentions
1020 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1021 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1022 size
= self
.GetSize()
1023 pos
= self
.GetPosition()
1024 sizePanel
= panel
.GetSize()
1025 panel
.Reparent(self
.splitter
)
1026 self
.miniFrame
.GetSizer().Remove(panel
)
1028 self
.SetDimensions(pos
.x
, pos
.y
, size
.width
+ sizePanel
.width
, size
.height
)
1029 self
.splitter
.SplitVertically(tree
, panel
, conf
.sashPos
)
1030 self
.miniFrame
.Show(False)
1032 conf
.sashPos
= self
.splitter
.GetSashPosition()
1033 pos
= self
.GetPosition()
1034 size
= self
.GetSize()
1035 sizePanel
= panel
.GetSize()
1036 self
.splitter
.Unsplit(panel
)
1037 sizer
= self
.miniFrame
.GetSizer()
1038 panel
.Reparent(self
.miniFrame
)
1040 sizer
.Add(panel
, 1, wx
.EXPAND
)
1041 self
.miniFrame
.Show(True)
1042 self
.miniFrame
.SetDimensions(conf
.panelX
, conf
.panelY
,
1043 conf
.panelWidth
, conf
.panelHeight
)
1044 self
.miniFrame
.Layout()
1046 self
.SetDimensions(pos
.x
, pos
.y
,
1047 max(size
.width
- sizePanel
.width
, self
.minWidth
), size
.height
)
1049 def OnShowTools(self
, evt
):
1050 conf
.showTools
= evt
.IsChecked()
1051 g
.tools
.Show(conf
.showTools
)
1053 self
.toolsSizer
.Prepend(g
.tools
, 0, wx
.EXPAND
)
1055 self
.toolsSizer
.Remove(g
.tools
)
1056 self
.toolsSizer
.Layout()
1058 def OnTest(self
, evt
):
1059 if not tree
.selection
: return # key pressed event
1060 tree
.ShowTestWindow(tree
.selection
)
1062 def OnTestHide(self
, evt
):
1063 tree
.CloseTestWindow()
1065 # Find object by relative position
1066 def FindObject(self
, item
, obj
):
1067 # We simply perform depth-first traversal, sinse it's too much
1068 # hassle to deal with all sizer/window combinations
1069 w
= tree
.FindNodeObject(item
)
1070 if w
== obj
or isinstance(w
, wx
.GBSizerItem
) and w
.GetWindow() == obj
:
1072 if tree
.ItemHasChildren(item
):
1073 child
= tree
.GetFirstChild(item
)[0]
1075 found
= self
.FindObject(child
, obj
)
1076 if found
: return found
1077 child
= tree
.GetNextSibling(child
)
1080 # Click event after locate activated
1081 def OnTestWinLeftDown(self
, evt
):
1082 # Restore normal event processing
1083 self
.SetHandler(g
.testWin
)
1084 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1085 item
= self
.FindObject(g
.testWin
.item
, evt
.GetEventObject())
1087 tree
.EnsureVisible(item
)
1088 tree
.SelectItem(item
)
1089 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, False)
1091 self
.SetStatusText('Selected %s' % tree
.GetItemText(item
))
1093 self
.SetStatusText('Locate failed!')
1095 def SetHandler(self
, w
, h
=None):
1097 w
.SetEventHandler(h
)
1098 w
.SetCursor(wx
.CROSS_CURSOR
)
1100 w
.SetEventHandler(w
)
1101 w
.SetCursor(wx
.NullCursor
)
1102 for ch
in w
.GetChildren():
1103 self
.SetHandler(ch
, h
)
1105 def OnLocate(self
, evt
):
1107 if evt
.GetId() == self
.ID_LOCATE
or \
1108 evt
.GetId() == self
.ID_TOOL_LOCATE
and evt
.IsChecked():
1109 self
.SetHandler(g
.testWin
, g
.testWin
)
1110 g
.testWin
.Connect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
, self
.OnTestWinLeftDown
)
1111 if evt
.GetId() == self
.ID_LOCATE
:
1112 self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, True)
1113 elif evt
.GetId() == self
.ID_TOOL_LOCATE
and not evt
.IsChecked():
1114 self
.SetHandler(g
.testWin
, None)
1115 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
)
1116 self
.SetStatusText('Click somewhere in your test window now')
1118 def OnRefresh(self
, evt
):
1119 # If modified, apply first
1120 selection
= tree
.selection
1122 xxx
= tree
.GetPyData(selection
)
1123 if xxx
and panel
.IsModified():
1124 tree
.Apply(xxx
, selection
)
1127 tree
.CreateTestWin(g
.testWin
.item
)
1128 panel
.modified
= False
1129 tree
.needUpdate
= False
1131 def OnAutoRefresh(self
, evt
):
1132 conf
.autoRefresh
= evt
.IsChecked()
1133 self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1134 self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
)
1136 def OnAbout(self
, evt
):
1140 (c) Roman Rolinsky <rollrom@users.sourceforge.net>
1141 Homepage: http://xrced.sourceforge.net\
1143 dlg
= wx
.MessageDialog(self
, str, 'About XRCed', wx
.OK | wx
.CENTRE
)
1147 def OnReadme(self
, evt
):
1148 text
= open(os
.path
.join(basePath
, 'README.txt'), 'r').read()
1149 dlg
= ScrolledMessageDialog(self
, text
, "XRCed README")
1153 # Simple emulation of python command line
1154 def OnDebugCMD(self
, evt
):
1157 exec raw_input('C:\> ')
1162 (etype
, value
, tb
) =sys
.exc_info()
1163 tblist
=traceback
.extract_tb(tb
)[1:]
1164 msg
=' '.join(traceback
.format_exception_only(etype
, value
)
1165 +traceback
.format_list(tblist
))
1168 def OnCreate(self
, evt
):
1169 # Ignore fake events generated while dragging
1171 g
.tools
.drag
= False
1173 selected
= tree
.selection
1174 if tree
.ctrl
: appendChild
= False
1175 else: appendChild
= not tree
.NeedInsert(selected
)
1176 xxx
= tree
.GetPyData(selected
)
1180 # If has previous item, insert after it, else append to parent
1182 parentLeaf
= tree
.GetItemParent(selected
)
1184 # If has next item, insert, else append to parent
1185 nextItem
= tree
.GetNextSibling(selected
)
1186 parentLeaf
= tree
.GetItemParent(selected
)
1187 # Expanded container (must have children)
1188 elif tree
.shift
and tree
.IsExpanded(selected
) \
1189 and tree
.GetChildrenCount(selected
, False):
1190 nextItem
= tree
.GetFirstChild(selected
)[0]
1191 parentLeaf
= selected
1193 nextItem
= wx
.TreeItemId()
1194 parentLeaf
= selected
1195 parent
= tree
.GetPyData(parentLeaf
)
1196 if parent
.hasChild
: parent
= parent
.child
1198 self
.CreateXXX(parent
, parentLeaf
, nextItem
, evt
.GetId())
1200 # Actual method to create object and add to XML and wx trees
1201 def CreateXXX(self
, parent
, parentLeaf
, nextItem
, id):
1202 selected
= tree
.selection
1203 # Create object_ref?
1204 if id == ID_NEW
.REF
:
1205 ref
= wx
.GetTextFromUser('Create reference to:', 'Create reference')
1207 xxx
= MakeEmptyRefXXX(parent
, ref
)
1208 elif id == ID_NEW
.COMMENT
:
1209 xxx
= MakeEmptyCommentXXX(parent
)
1211 # Create empty element
1212 if id >= ID_NEW
.CUSTOM
:
1213 className
= pullDownMenu
.customMap
[id]
1215 className
= pullDownMenu
.createMap
[id]
1216 xxx
= MakeEmptyXXX(parent
, className
)
1218 # Insert new node, register undo
1219 if xxx
.isElement
: # true object
1220 # Set default name for top-level windows
1221 if parent
.__class
__ == xxxMainNode
:
1222 cl
= xxx
.treeObject().__class
__
1223 frame
.maxIDs
[cl
] += 1
1224 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1225 # And for some other standard controls
1226 elif parent
.__class
__ == xxxStdDialogButtonSizer
:
1227 # ... we can even set automatically tree name
1228 xxx
.setTreeName(pullDownMenu
.stdButtonIDs
[id][0])
1229 obj
= xxx
.treeObject()
1231 elem
= g
.tree
.dom
.createElement('label')
1232 elem
.appendChild(g
.tree
.dom
.createTextNode(pullDownMenu
.stdButtonIDs
[id][1]))
1233 obj
.params
['label'] = xxxParam(elem
)
1234 xxx
.treeObject().node
.appendChild(elem
)
1235 # Else, set label if exists to class name
1236 elif 'label' in xxx
.treeObject().allParams
:
1238 if label
[:2] == 'wx': label
= label
[2:]
1239 xxx
.treeObject().set('label', label
.upper())
1240 # For comment nodes, simply add node
1241 newItem
= tree
.InsertNode(parentLeaf
, parent
, xxx
.node
, nextItem
)
1242 undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
))
1243 tree
.EnsureVisible(newItem
)
1244 tree
.SelectItem(newItem
)
1245 if not tree
.IsVisible(newItem
):
1246 tree
.ScrollTo(newItem
)
1249 if xxx
.isElement
and g
.testWin
and tree
.IsHighlatable(newItem
):
1250 if conf
.autoRefresh
:
1251 tree
.needUpdate
= True
1252 tree
.pendingHighLight
= newItem
1254 tree
.pendingHighLight
= None
1256 if not xxx
.isElement
:
1257 tree
.EditLabel(newItem
)
1261 # Replace one object with another
1262 def OnReplace(self
, evt
):
1263 selected
= tree
.selection
1264 xxx
= tree
.GetPyData(selected
).treeObject()
1266 parent
= elem
.parentNode
1267 undoMan
.RegisterUndo(UndoReplace(selected
))
1269 className
= pullDownMenu
.createMap
[evt
.GetId() - 1000]
1271 # Create temporary empty node (with default values)
1272 dummy
= MakeEmptyDOM(className
)
1273 if className
== 'spacer' and xxx
.className
!= 'spacer':
1275 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1276 klass
= xxxSizerItem
1278 klass
= xxxDict
[className
]
1279 # Remove non-compatible children
1280 if tree
.ItemHasChildren(selected
) and not klass
.hasChildren
:
1281 tree
.DeleteChildren(selected
)
1282 nodes
= elem
.childNodes
[:]
1285 if node
.nodeType
!= minidom
.Node
.ELEMENT_NODE
: continue
1289 if not klass
.hasChildren
: remove
= True
1290 elif tag
not in klass
.allParams
and \
1291 (not klass
.hasStyle
or tag
not in klass
.styles
):
1296 elem
.removeChild(node
)
1299 # Remove sizeritem child if spacer
1300 if className
== 'spacer' and xxx
.className
!= 'spacer':
1301 sizeritem
= elem
.parentNode
1302 assert sizeritem
.getAttribute('class') == 'sizeritem'
1303 sizeritem
.removeChild(elem
)
1306 tree
.GetPyData(selected
).hasChild
= False
1307 elif xxx
.className
== 'spacer' and className
!= 'spacer':
1308 # Create sizeritem element
1309 assert xxx
.parent
.isSizer
1310 elem
.setAttribute('class', 'sizeritem')
1311 node
= MakeEmptyDOM(className
)
1312 elem
.appendChild(node
)
1313 # Replace to point to new object
1314 xxx
= xxxSizerItem(xxx
.parent
, elem
)
1316 tree
.SetPyData(selected
, xxx
)
1319 # Copy parameters present in dummy but not in elem
1320 for node
in dummy
.childNodes
:
1321 if node
.tagName
not in tags
: elem
.appendChild(node
.cloneNode(True))
1325 elem
.setAttribute('class', className
)
1326 if elem
.hasAttribute('subclass'):
1327 elem
.removeAttribute('subclass') # clear subclassing
1328 # Re-create xxx element
1329 xxx
= MakeXXXFromDOM(xxx
.parent
, elem
)
1330 # Remove incompatible style flags
1331 if 'style' in xxx
.params
:
1332 styles
= map(string
.strip
, xxx
.params
['style'].value().split('|'))
1333 newStyles
= [s
for s
in styles
if s
in klass
.winStyles
or s
in genericStyles
]
1334 if newStyles
!= styles
:
1336 value
= reduce(lambda a
,b
: a
+'|'+b
, newStyles
)
1339 xxx
.params
['style'].update(value
)
1341 # Update parent in child objects
1342 if tree
.ItemHasChildren(selected
):
1343 i
, cookie
= tree
.GetFirstChild(selected
)
1345 x
= tree
.GetPyData(i
)
1347 if x
.hasChild
: x
.child
.parent
= xxx
1348 i
, cookie
= tree
.GetNextChild(selected
, cookie
)
1351 if tree
.GetPyData(selected
).hasChild
: # child container
1352 container
= tree
.GetPyData(selected
)
1353 container
.resetChild(xxx
)
1356 tree
.SetPyData(selected
, xxx
)
1357 tree
.SetItemText(selected
, xxx
.treeName())
1358 tree
.SetItemImage(selected
, xxx
.treeImage())
1360 # Set default name for top-level windows
1361 if parent
.__class
__ == xxxMainNode
:
1362 cl
= xxx
.treeObject().__class
__
1363 frame
.maxIDs
[cl
] += 1
1364 xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
]))
1367 g
.panel
.SetData(xxx
)
1371 #undoMan.RegisterUndo(UndoPasteCreate(parentLeaf, parent, newItem, selected))
1373 if g
.testWin
and tree
.IsHighlatable(selected
):
1374 if conf
.autoRefresh
:
1375 tree
.needUpdate
= True
1376 tree
.pendingHighLight
= selected
1378 tree
.pendingHighLight
= None
1382 # Expand/collapse subtree
1383 def OnExpand(self
, evt
):
1384 if tree
.selection
: tree
.ExpandAll(tree
.selection
)
1385 else: tree
.ExpandAll(tree
.root
)
1386 def OnCollapse(self
, evt
):
1387 if tree
.selection
: tree
.CollapseAll(tree
.selection
)
1388 else: tree
.CollapseAll(tree
.root
)
1390 def OnPullDownHighlight(self
, evt
):
1391 menuId
= evt
.GetMenuId()
1393 menu
= evt
.GetEventObject()
1395 help = menu
.GetHelpString(menuId
)
1396 self
.SetStatusText(help)
1398 self
.SetStatusText('')
1400 self
.SetStatusText('')
1402 def OnUpdateUI(self
, evt
):
1403 if evt
.GetId() in [wx
.ID_CUT
, wx
.ID_COPY
, self
.ID_DELETE
]:
1404 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1405 elif evt
.GetId() == wx
.ID_SAVE
:
1406 evt
.Enable(self
.modified
)
1407 elif evt
.GetId() in [wx
.ID_PASTE
, self
.ID_TOOL_PASTE
]:
1408 evt
.Enable(tree
.selection
is not None)
1409 elif evt
.GetId() in [self
.ID_TEST
,
1410 self
.ID_MOVEUP
, self
.ID_MOVEDOWN
,
1411 self
.ID_MOVELEFT
, self
.ID_MOVERIGHT
]:
1412 evt
.Enable(tree
.selection
is not None and tree
.selection
!= tree
.root
)
1413 elif evt
.GetId() in [self
.ID_LOCATE
, self
.ID_TOOL_LOCATE
,
1415 evt
.Enable(g
.testWin
is not None)
1416 elif evt
.GetId() == wx
.ID_UNDO
: evt
.Enable(undoMan
.CanUndo())
1417 elif evt
.GetId() == wx
.ID_REDO
: evt
.Enable(undoMan
.CanRedo())
1419 def OnIdle(self
, evt
):
1420 if self
.inIdle
: return # Recursive call protection
1422 #print 'onidle',tree.needUpdate,tree.pendingHighLight
1425 if conf
.autoRefresh
:
1427 #self.SetStatusText('Refreshing test window...')
1429 tree
.CreateTestWin(g
.testWin
.item
)
1430 #self.SetStatusText('')
1431 tree
.needUpdate
= False
1432 elif tree
.pendingHighLight
:
1434 tree
.HighLight(tree
.pendingHighLight
)
1436 # Remove highlight if any problem
1437 if g
.testWin
and g
.testWin
.highLight
:
1438 g
.testWin
.highLight
.Remove()
1439 tree
.pendingHighLight
= None
1446 def OnIconize(self
, evt
):
1448 conf
.x
, conf
.y
= self
.GetPosition()
1449 conf
.width
, conf
.height
= self
.GetSize()
1451 conf
.sashPos
= self
.splitter
.GetSashPosition()
1453 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1454 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1455 self
.miniFrame
.Show(False)
1457 if not conf
.embedPanel
:
1458 self
.miniFrame
.Show(True)
1461 def OnCloseWindow(self
, evt
):
1462 if not self
.AskSave(): return
1463 if g
.testWin
: g
.testWin
.Destroy()
1464 if not panel
.GetPageCount() == 2:
1465 panel
.page2
.Destroy()
1467 # If we don't do this, page does not get destroyed (a bug?)
1469 if not self
.IsIconized():
1470 conf
.x
, conf
.y
= self
.GetPosition()
1471 if wx
.Platform
== '__WXMAC__':
1472 conf
.width
, conf
.height
= self
.GetClientSize()
1474 conf
.width
, conf
.height
= self
.GetSize()
1476 conf
.sashPos
= self
.splitter
.GetSashPosition()
1478 conf
.panelX
, conf
.panelY
= self
.miniFrame
.GetPosition()
1479 conf
.panelWidth
, conf
.panelHeight
= self
.miniFrame
.GetSize()
1482 def CreateLocalConf(self
, path
):
1483 name
= os
.path
.splitext(path
)[0]
1485 return wx
.FileConfig(localFilename
=name
)
1489 conf
.localconf
= None
1491 self
.SetModified(False)
1497 # Numbers for new controls
1499 for cl
in [xxxPanel
, xxxDialog
, xxxFrame
,
1500 xxxMenuBar
, xxxMenu
, xxxToolBar
,
1501 xxxWizard
, xxxBitmap
, xxxIcon
]:
1503 # Restore handlers, menu, etc. to initial
1504 setHandlers(self
.handlers
[:])
1505 g
.pullDownMenu
.custom
= self
.custom
[:]
1506 # Remove modules imported from comment directives
1507 map(sys
.modules
.pop
, [m
for m
in sys
.modules
if m
not in self
.modules
])
1508 xxxParamComment
.locals = {} # clear local namespace
1509 xxxParamComment
.allow
= None # clear execution state
1511 def SetModified(self
, state
=True):
1512 self
.modified
= state
1513 name
= os
.path
.basename(self
.dataFile
)
1514 if not name
: name
= defaultName
1516 self
.SetTitle(progname
+ ': ' + name
+ ' *')
1518 self
.SetTitle(progname
+ ': ' + name
)
1520 def Open(self
, path
):
1521 if not os
.path
.exists(path
):
1522 wx
.LogError('File does not exists: %s' % path
)
1524 # Try to read the file
1528 dom
= minidom
.parse(f
)
1530 # Set encoding global variable and default encoding
1532 g
.currentEncoding
= dom
.encoding
1533 wx
.SetDefaultPyEncoding(g
.currentEncoding
.encode())
1535 g
.currentEncoding
= ''
1537 self
.dataFile
= path
= os
.path
.abspath(path
)
1538 dir = os
.path
.dirname(path
)
1539 if dir: os
.chdir(dir)
1540 # Allow importing modules from the same directory
1541 sys
.path
= sys_path
+ [dir]
1543 self
.SetTitle(progname
+ ': ' + os
.path
.basename(path
))
1544 conf
.localconf
= self
.CreateLocalConf(self
.dataFile
)
1546 # Nice exception printing
1547 inf
= sys
.exc_info()
1548 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1549 wx
.LogError('Error reading file: %s' % path
)
1554 def Indent(self
, node
, indent
= 0):
1555 if node
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1556 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1557 node
.parentNode
.insertBefore(text
, node
)
1558 return # no children
1559 # Copy child list because it will change soon
1560 children
= node
.childNodes
[:]
1561 # Main node doesn't need to be indented
1563 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1564 node
.parentNode
.insertBefore(text
, node
)
1566 # Append newline after last child, except for text nodes
1567 if children
[-1].nodeType
== minidom
.Node
.ELEMENT_NODE
:
1568 text
= self
.domCopy
.createTextNode('\n' + ' ' * indent
)
1569 node
.appendChild(text
)
1570 # Indent children which are elements
1572 if n
.nodeType
== minidom
.Node
.ELEMENT_NODE
or \
1573 n
.nodeType
== minidom
.Node
.COMMENT_NODE
:
1574 self
.Indent(n
, indent
+ 2)
1576 def Save(self
, path
):
1580 if tree
.selection
and panel
.IsModified():
1581 self
.OnRefresh(wx
.CommandEvent())
1582 if g
.currentEncoding
:
1583 f
= codecs
.open(path
, 'wt', g
.currentEncoding
)
1585 f
= codecs
.open(path
, 'wt')
1586 # Make temporary copy for formatting it
1587 # !!! We can't clone dom node, it works only once
1588 #self.domCopy = tree.dom.cloneNode(True)
1589 self
.domCopy
= MyDocument()
1590 mainNode
= self
.domCopy
.appendChild(tree
.mainNode
.cloneNode(True))
1591 # Remove first child (test element)
1592 testElem
= mainNode
.firstChild
1593 mainNode
.removeChild(testElem
)
1595 self
.Indent(mainNode
)
1596 self
.domCopy
.writexml(f
, encoding
= g
.currentEncoding
)
1598 self
.domCopy
.unlink()
1600 self
.SetModified(False)
1601 panel
.SetModified(False)
1602 conf
.localconf
.Flush()
1604 inf
= sys
.exc_info()
1605 wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1])
1606 wx
.LogError('Error writing file: %s' % path
)
1610 if not (self
.modified
or panel
.IsModified()): return True
1611 flags
= wx
.ICON_EXCLAMATION | wx
.YES_NO | wx
.CANCEL | wx
.CENTRE
1612 dlg
= wx
.MessageDialog( self
, 'File is modified. Save before exit?',
1613 'Save before too late?', flags
)
1614 say
= dlg
.ShowModal()
1617 if say
== wx
.ID_YES
:
1618 self
.OnSaveOrSaveAs(wx
.CommandEvent(wx
.ID_SAVE
))
1619 # If save was successful, modified flag is unset
1620 if not self
.modified
: return True
1621 elif say
== wx
.ID_NO
:
1622 self
.SetModified(False)
1623 panel
.SetModified(False)
1627 ################################################################################
1629 class PythonOptions(wx
.Dialog
):
1631 def __init__(self
, parent
, cfg
, dataFile
):
1632 pre
= wx
.PreDialog()
1633 g
.frame
.res
.LoadOnDialog(pre
, parent
, "PYTHON_OPTIONS")
1634 self
.PostCreate(pre
)
1637 self
.dataFile
= dataFile
1639 self
.AutoGenerateCB
= xrc
.XRCCTRL(self
, "AutoGenerateCB")
1640 self
.EmbedCB
= xrc
.XRCCTRL(self
, "EmbedCB")
1641 self
.GettextCB
= xrc
.XRCCTRL(self
, "GettextCB")
1642 self
.MakeXRSFileCB
= xrc
.XRCCTRL(self
, "MakeXRSFileCB")
1643 self
.FileNameTC
= xrc
.XRCCTRL(self
, "FileNameTC")
1644 self
.BrowseBtn
= xrc
.XRCCTRL(self
, "BrowseBtn")
1645 self
.GenerateBtn
= xrc
.XRCCTRL(self
, "GenerateBtn")
1646 self
.SaveOptsBtn
= xrc
.XRCCTRL(self
, "SaveOptsBtn")
1648 self
.Bind(wx
.EVT_BUTTON
, self
.OnBrowse
, self
.BrowseBtn
)
1649 self
.Bind(wx
.EVT_BUTTON
, self
.OnGenerate
, self
.GenerateBtn
)
1650 self
.Bind(wx
.EVT_BUTTON
, self
.OnSaveOpts
, self
.SaveOptsBtn
)
1652 if self
.cfg
.Read("filename", "") != "":
1653 self
.FileNameTC
.SetValue(self
.cfg
.Read("filename"))
1655 name
= os
.path
.splitext(os
.path
.split(dataFile
)[1])[0]
1657 self
.FileNameTC
.SetValue(name
)
1658 self
.AutoGenerateCB
.SetValue(self
.cfg
.ReadBool("autogenerate", False))
1659 self
.EmbedCB
.SetValue(self
.cfg
.ReadBool("embedResource", False))
1660 self
.MakeXRSFileCB
.SetValue(self
.cfg
.ReadBool("makeXRS", False))
1661 self
.GettextCB
.SetValue(self
.cfg
.ReadBool("genGettext", False))
1664 def OnBrowse(self
, evt
):
1665 path
= self
.FileNameTC
.GetValue()
1666 dirname
= os
.path
.abspath(os
.path
.dirname(path
))
1667 name
= os
.path
.split(path
)[1]
1668 dlg
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.py',
1669 wx
.SAVE | wx
.OVERWRITE_PROMPT
)
1670 if dlg
.ShowModal() == wx
.ID_OK
:
1671 path
= dlg
.GetPath()
1672 self
.FileNameTC
.SetValue(path
)
1676 def OnGenerate(self
, evt
):
1677 pypath
= self
.FileNameTC
.GetValue()
1678 embed
= self
.EmbedCB
.GetValue()
1679 genGettext
= self
.GettextCB
.GetValue()
1680 frame
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
)
1684 def OnSaveOpts(self
, evt
=None):
1685 self
.cfg
.Write("filename", self
.FileNameTC
.GetValue())
1686 self
.cfg
.WriteBool("autogenerate", self
.AutoGenerateCB
.GetValue())
1687 self
.cfg
.WriteBool("embedResource", self
.EmbedCB
.GetValue())
1688 self
.cfg
.WriteBool("makeXRS", self
.MakeXRSFileCB
.GetValue())
1689 self
.cfg
.WriteBool("genGettext", self
.GettextCB
.GetValue())
1691 self
.EndModal(wx
.ID_OK
)
1693 ################################################################################
1695 class PrefsDialog(wx
.Dialog
):
1697 def __init__(self
, parent
):
1698 pre
= wx
.PreDialog()
1699 g
.frame
.res
.LoadOnDialog(pre
, parent
, "DIALOG_PREFS")
1700 self
.PostCreate(pre
)
1701 self
.checkControls
= {} # map of check IDs to (control,dict,param)
1703 ##xxx = sys.modules['xxx']
1705 d
= xxx
.xxxSizerItem
.defaults_panel
1707 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_panel')
1708 id = self
.check_proportion_panel
.GetId()
1709 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1710 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_panel'),
1713 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_panel')
1714 id = self
.check_flag_panel
.GetId()
1715 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1716 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_panel'),
1719 d
= xxx
.xxxSizerItem
.defaults_control
1721 self
.check_proportion_panel
= xrc
.XRCCTRL(self
, 'check_proportion_control')
1722 id = self
.check_proportion_panel
.GetId()
1723 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1724 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'spin_proportion_control'),
1727 self
.check_flag_panel
= xrc
.XRCCTRL(self
, 'check_flag_control')
1728 id = self
.check_flag_panel
.GetId()
1729 wx
.EVT_CHECKBOX(self
, id, self
.OnCheck
)
1730 self
.checkControls
[id] = (xrc
.XRCCTRL(self
, 'text_flag_control'),
1733 for id,cdp
in self
.checkControls
.items():
1736 if isinstance(c
, wx
.SpinCtrl
):
1737 c
.SetValue(int(d
[p
]))
1740 self
.FindWindowById(id).SetValue(True)
1744 self
.radio_allow_exec
= xrc
.XRCCTRL(self
, 'radio_allow_exec')
1746 radio
= {'ask': 0, 'yes':1, 'no':2}
[g
.conf
.allowExec
]
1749 self
.radio_allow_exec
.SetSelection(radio
)
1751 def OnCheck(self
, evt
):
1752 self
.checkControls
[evt
.GetId()][0].Enable(evt
.IsChecked())
1755 ################################################################################
1757 # Parse string in form var1=val1[,var2=val2]* as dictionary
1758 def ReadDictFromString(s
):
1760 for vv
in s
.split(','):
1761 var
,val
= vv
.split(':')
1762 d
[var
.strip()] = val
1765 # Transform dictionary with strings into one string
1766 def DictToString(d
):
1767 return ','.join(map(':'.join
, d
.items()))
1770 print >> sys
.stderr
, 'usage: xrced [-dhiv] [file]'
1775 if wx
.VERSION
[:3] < MinWxVersion
:
1777 This version of XRCed may not work correctly on your version of wxWidgets. \
1778 Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion
)
1780 # Process comand-line
1783 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'dhiv')
1791 print 'XRCed version', version
1794 except getopt
.GetoptError
:
1795 if wx
.Platform
!= '__WXMAC__': # macs have some extra parameters
1796 print >> sys
.stderr
, 'Unknown option'
1800 self
.SetAppName('xrced')
1803 conf
= g
.conf
= wx
.Config(style
= wx
.CONFIG_USE_LOCAL_FILE
)
1804 conf
.localconf
= None
1805 conf
.autoRefresh
= conf
.ReadInt('autorefresh', True)
1806 pos
= conf
.ReadInt('x', -1), conf
.ReadInt('y', -1)
1807 size
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600)
1808 conf
.embedPanel
= conf
.ReadInt('embedPanel', True)
1809 conf
.showTools
= conf
.ReadInt('showTools', True)
1810 conf
.sashPos
= conf
.ReadInt('sashPos', 200)
1812 # read recently used files
1813 g
.fileHistory
= wx
.FileHistory()
1814 g
.fileHistory
.Load(conf
)
1816 if not conf
.embedPanel
:
1817 conf
.panelX
= conf
.ReadInt('panelX', -1)
1818 conf
.panelY
= conf
.ReadInt('panelY', -1)
1820 conf
.panelX
= conf
.panelY
= -1
1821 conf
.panelWidth
= conf
.ReadInt('panelWidth', 200)
1822 conf
.panelHeight
= conf
.ReadInt('panelHeight', 200)
1823 conf
.panic
= not conf
.HasEntry('nopanic')
1825 conf
.allowExec
= conf
.Read('Prefs/allowExec', 'ask')
1826 p
= 'Prefs/sizeritem_defaults_panel'
1828 if conf
.HasEntry(p
):
1829 ##sys.modules['xxx'].xxxSizerItem.defaults_panel = ReadDictFromString(conf.Read(p))
1830 xxx
.xxxSizerItem
.defaults_panel
= ReadDictFromString(conf
.Read(p
))
1831 p
= 'Prefs/sizeritem_defaults_control'
1832 if conf
.HasEntry(p
):
1833 ##sys.modules['xxx'].xxxSizerItem.defaults_control = ReadDictFromString(conf.Read(p))
1834 xxx
.xxxSizerItem
.defaults_control
= ReadDictFromString(conf
.Read(p
))
1837 wx
.FileSystem
.AddHandler(wx
.MemoryFSHandler())
1838 self
.toolArtProvider
= ToolArtProvider()
1839 wx
.ArtProvider
.Push(self
.toolArtProvider
)
1841 frame
= Frame(pos
, size
)
1842 # Mac does not set the correct size
1843 if wx
.Platform
== '__WXMAC__':
1844 frame
.SetClientSize(size
)
1848 plugins
= os
.getenv('XRCEDPATH')
1852 for dir in plugins
.split(':'):
1853 if os
.path
.isdir(dir) and \
1854 os
.path
.isfile(os
.path
.join(dir, '__init__.py')):
1856 dir = os
.path
.abspath(os
.path
.normpath(dir))
1857 sys
.path
= sys_path
+ [os
.path
.dirname(dir)]
1860 __import__(os
.path
.basename(dir), globals(), locals(), ['*'])
1862 print traceback
.print_exc()
1865 # Store important data
1866 frame
.handlers
= getHandlers()[:]
1867 frame
.custom
= g
.pullDownMenu
.custom
[:]
1868 frame
.modules
= sys
.modules
.copy()
1873 # Load file after showing
1876 frame
.open = frame
.Open(args
[0])
1884 wc
.WriteInt('autorefresh', conf
.autoRefresh
)
1885 wc
.WriteInt('x', conf
.x
)
1886 wc
.WriteInt('y', conf
.y
)
1887 wc
.WriteInt('width', conf
.width
)
1888 wc
.WriteInt('height', conf
.height
)
1889 wc
.WriteInt('embedPanel', conf
.embedPanel
)
1890 wc
.WriteInt('showTools', conf
.showTools
)
1891 if not conf
.embedPanel
:
1892 wc
.WriteInt('panelX', conf
.panelX
)
1893 wc
.WriteInt('panelY', conf
.panelY
)
1894 wc
.WriteInt('sashPos', conf
.sashPos
)
1895 wc
.WriteInt('panelWidth', conf
.panelWidth
)
1896 wc
.WriteInt('panelHeight', conf
.panelHeight
)
1897 wc
.WriteInt('nopanic', 1)
1898 g
.fileHistory
.Save(wc
)
1900 wc
.DeleteGroup('Prefs')
1901 wc
.Write('Prefs/allowExec', conf
.allowExec
)
1903 ##v = sys.modules['xxx'].xxxSizerItem.defaults_panel
1904 v
= xxx
.xxxSizerItem
.defaults_panel
1905 if v
: wc
.Write('Prefs/sizeritem_defaults_panel', DictToString(v
))
1906 ###v = sys.modules['xxx'].xxxSizerItem.defaults_control
1907 v
= xxx
.xxxSizerItem
.defaults_control
1908 if v
: wc
.Write('Prefs/sizeritem_defaults_control', DictToString(v
))
1913 app
= App(0, useBestVisual
=False)
1914 #app.SetAssertMode(wx.PYAPP_ASSERT_LOG)
1920 if __name__
== '__main__':