]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/tools/XRCed/xrced.py
   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 # Cleanup recursive import sideeffects, otherwise we can't create undoMan 
  33 undo
.ParamPage 
= ParamPage
 
  34 undoMan 
= g
.undoMan 
= UndoManager() 
  36 # Set application path for loading resources 
  37 if __name__ 
== '__main__': 
  38     basePath 
= os
.path
.dirname(sys
.argv
[0]) 
  40     basePath 
= os
.path
.dirname(__file__
) 
  42 # 1 adds CMD command to Help menu 
  46 <HTML><H2>Welcome to XRC<font color="blue">ed</font></H2><H3><font color="green">DON'T PANIC :)</font></H3> 
  47 Read this note before clicking on anything!<P> 
  48 To start select tree root, then popup menu with your right mouse button, 
  49 select "Append Child", and then any command.<P> 
  50 Or just press one of the buttons on the tools palette.<P> 
  51 Enter XML ID, change properties, create children.<P> 
  52 To test your interface select Test command (View menu).<P> 
  53 Consult README file for the details.</HTML> 
  56 defaultIDs 
= {xxxPanel
:'PANEL', xxxDialog
:'DIALOG', xxxFrame
:'FRAME', 
  57               xxxMenuBar
:'MENUBAR', xxxMenu
:'MENU', xxxToolBar
:'TOOLBAR', 
  58               xxxWizard
:'WIZARD', xxxBitmap
:'BITMAP', xxxIcon
:'ICON'} 
  60 defaultName 
= 'UNTITLED.xrc' 
  62 ################################################################################ 
  64 # ScrolledMessageDialog - modified from wxPython lib to set fixed-width font 
  65 class ScrolledMessageDialog(wx
.Dialog
): 
  66     def __init__(self
, parent
, msg
, caption
, pos 
= wx
.DefaultPosition
, size 
= (500,300)): 
  67         from wx
.lib
.layoutf 
import Layoutf
 
  68         wx
.Dialog
.__init
__(self
, parent
, -1, caption
, pos
, size
) 
  69         text 
= wx
.TextCtrl(self
, -1, msg
, wx
.DefaultPosition
, 
  70                              wx
.DefaultSize
, wx
.TE_MULTILINE | wx
.TE_READONLY
) 
  71         text
.SetFont(g
.modernFont()) 
  72         dc 
= wx
.WindowDC(text
) 
  73         # !!! possible bug - GetTextExtent without font returns sysfont dims 
  74         w
, h 
= dc
.GetFullTextExtent(' ', g
.modernFont())[:2] 
  75         ok 
= wx
.Button(self
, wx
.ID_OK
, "OK") 
  76         text
.SetConstraints(Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self
,ok
))) 
  77         text
.SetSize((w 
* 80 + 30, h 
* 40)) 
  79         ok
.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!25', (self
,))) 
  80         self
.SetAutoLayout(True) 
  82         self
.CenterOnScreen(wx
.BOTH
) 
  84 ################################################################################ 
  86 # Event handler for using during location 
  87 class Locator(wx
.EvtHandler
): 
  88     def ProcessEvent(self
, evt
): 
  91 class Frame(wx
.Frame
): 
  92     def __init__(self
, pos
, size
): 
  93         wx
.Frame
.__init
__(self
, None, -1, '', pos
, size
) 
  95         frame 
= g
.frame 
= self
 
  96         bar 
= self
.CreateStatusBar(2) 
  97         bar
.SetStatusWidths([-1, 40]) 
  98         self
.SetIcon(images
.getIconIcon()) 
 103         # Load our own resources 
 104         self
.res 
= xrc
.XmlResource('') 
 105         # !!! Blocking of assert failure occurring in older unicode builds 
 107             quietlog 
= wx
.LogNull() 
 108             self
.res
.Load(os
.path
.join(basePath
, 'xrced.xrc')) 
 109         except wx
._core
.PyAssertionError
: 
 110             print 'PyAssertionError was ignored' 
 113         menuBar 
= wx
.MenuBar() 
 116         menu
.Append(wx
.ID_NEW
, '&New\tCtrl-N', 'New file') 
 117         menu
.AppendSeparator() 
 118         menu
.Append(wx
.ID_OPEN
, '&Open...\tCtrl-O', 'Open XRC file') 
 119         self
.recentMenu 
= wx
.Menu() 
 120         self
.AppendRecent(self
.recentMenu
) 
 121         menu
.AppendMenu(-1, 'Open Recent', self
.recentMenu
, 'Open a recent file') 
 122         menu
.AppendSeparator() 
 123         menu
.Append(wx
.ID_SAVE
, '&Save\tCtrl-S', 'Save XRC file') 
 124         menu
.Append(wx
.ID_SAVEAS
, 'Save &As...', 'Save XRC file under different name') 
 125         self
.ID_GENERATE_PYTHON 
= wx
.NewId() 
 126         menu
.Append(self
.ID_GENERATE_PYTHON
, '&Generate Python...',  
 127                     'Generate a Python module that uses this XRC') 
 128         menu
.AppendSeparator() 
 129         menu
.Append(wx
.ID_EXIT
, '&Quit\tCtrl-Q', 'Exit application') 
 131         menuBar
.Append(menu
, '&File') 
 134         menu
.Append(wx
.ID_UNDO
, '&Undo\tCtrl-Z', 'Undo') 
 135         menu
.Append(wx
.ID_REDO
, '&Redo\tCtrl-Y', 'Redo') 
 136         menu
.AppendSeparator() 
 137         menu
.Append(wx
.ID_CUT
, 'Cut\tCtrl-X', 'Cut to the clipboard') 
 138         menu
.Append(wx
.ID_COPY
, '&Copy\tCtrl-C', 'Copy to the clipboard') 
 139         menu
.Append(wx
.ID_PASTE
, '&Paste\tCtrl-V', 'Paste from the clipboard') 
 140         self
.ID_DELETE 
= wx
.NewId() 
 141         menu
.Append(self
.ID_DELETE
, '&Delete\tCtrl-D', 'Delete object') 
 142         menu
.AppendSeparator() 
 143         self
.ID_LOCATE 
= wx
.NewId() 
 144         self
.ID_TOOL_LOCATE 
= wx
.NewId() 
 145         self
.ID_TOOL_PASTE 
= wx
.NewId() 
 146         menu
.Append(self
.ID_LOCATE
, '&Locate\tCtrl-L', 'Locate control in test window and select it') 
 147         menuBar
.Append(menu
, '&Edit') 
 150         self
.ID_EMBED_PANEL 
= wx
.NewId() 
 151         menu
.Append(self
.ID_EMBED_PANEL
, '&Embed Panel', 
 152                     'Toggle embedding properties panel in the main window', True) 
 153         menu
.Check(self
.ID_EMBED_PANEL
, conf
.embedPanel
) 
 154         self
.ID_SHOW_TOOLS 
= wx
.NewId() 
 155         menu
.Append(self
.ID_SHOW_TOOLS
, 'Show &Tools', 'Toggle tools', True) 
 156         menu
.Check(self
.ID_SHOW_TOOLS
, conf
.showTools
) 
 157         menu
.AppendSeparator() 
 158         self
.ID_TEST 
= wx
.NewId() 
 159         menu
.Append(self
.ID_TEST
, '&Test\tF5', 'Show test window') 
 160         self
.ID_REFRESH 
= wx
.NewId() 
 161         menu
.Append(self
.ID_REFRESH
, '&Refresh\tCtrl-R', 'Refresh test window') 
 162         self
.ID_AUTO_REFRESH 
= wx
.NewId() 
 163         menu
.Append(self
.ID_AUTO_REFRESH
, '&Auto-refresh\tCtrl-A', 
 164                     'Toggle auto-refresh mode', True) 
 165         menu
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
) 
 166         self
.ID_TEST_HIDE 
= wx
.NewId() 
 167         menu
.Append(self
.ID_TEST_HIDE
, '&Hide\tCtrl-H', 'Close test window') 
 168         menuBar
.Append(menu
, '&View') 
 171         menu
.Append(wx
.ID_ABOUT
, '&About...', 'About XCRed') 
 172         self
.ID_README 
= wx
.NewId() 
 173         menu
.Append(self
.ID_README
, '&Readme...', 'View the README file') 
 175             self
.ID_DEBUG_CMD 
= wx
.NewId() 
 176             menu
.Append(self
.ID_DEBUG_CMD
, 'CMD', 'Python command line') 
 177             wx
.EVT_MENU(self
, self
.ID_DEBUG_CMD
, self
.OnDebugCMD
) 
 178         menuBar
.Append(menu
, '&Help') 
 180         self
.menuBar 
= menuBar
 
 181         self
.SetMenuBar(menuBar
) 
 184         tb 
= self
.CreateToolBar(wx
.TB_HORIZONTAL | wx
.NO_BORDER | wx
.TB_FLAT
) 
 185         tb
.SetToolBitmapSize((24,24)) 
 186         new_bmp  
= wx
.ArtProvider
.GetBitmap(wx
.ART_NORMAL_FILE
, wx
.ART_TOOLBAR
) 
 187         open_bmp 
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_OPEN
, wx
.ART_TOOLBAR
) 
 188         save_bmp 
= wx
.ArtProvider
.GetBitmap(wx
.ART_FILE_SAVE
, wx
.ART_TOOLBAR
) 
 189         undo_bmp 
= wx
.ArtProvider
.GetBitmap(wx
.ART_UNDO
, wx
.ART_TOOLBAR
) 
 190         redo_bmp 
= wx
.ArtProvider
.GetBitmap(wx
.ART_REDO
, wx
.ART_TOOLBAR
) 
 191         cut_bmp  
= wx
.ArtProvider
.GetBitmap(wx
.ART_CUT
, wx
.ART_TOOLBAR
) 
 192         copy_bmp 
= wx
.ArtProvider
.GetBitmap(wx
.ART_COPY
, wx
.ART_TOOLBAR
) 
 193         paste_bmp
= wx
.ArtProvider
.GetBitmap(wx
.ART_PASTE
, wx
.ART_TOOLBAR
) 
 195         tb
.AddSimpleTool(wx
.ID_NEW
, new_bmp
, 'New', 'New file') 
 196         tb
.AddSimpleTool(wx
.ID_OPEN
, open_bmp
, 'Open', 'Open file') 
 197         tb
.AddSimpleTool(wx
.ID_SAVE
, save_bmp
, 'Save', 'Save file') 
 198         tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
)) 
 199         tb
.AddSimpleTool(wx
.ID_UNDO
, undo_bmp
, 'Undo', 'Undo') 
 200         tb
.AddSimpleTool(wx
.ID_REDO
, redo_bmp
, 'Redo', 'Redo') 
 201         tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
)) 
 202         tb
.AddSimpleTool(wx
.ID_CUT
, cut_bmp
, 'Cut', 'Cut') 
 203         tb
.AddSimpleTool(wx
.ID_COPY
, copy_bmp
, 'Copy', 'Copy') 
 204         tb
.AddSimpleTool(self
.ID_TOOL_PASTE
, paste_bmp
, 'Paste', 'Paste') 
 205         tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
)) 
 206         tb
.AddSimpleTool(self
.ID_TOOL_LOCATE
, 
 207                         images
.getLocateBitmap(), #images.getLocateArmedBitmap(), 
 208                         'Locate', 'Locate control in test window and select it', True) 
 209         tb
.AddControl(wx
.StaticLine(tb
, -1, size
=(-1,23), style
=wx
.LI_VERTICAL
)) 
 210         tb
.AddSimpleTool(self
.ID_TEST
, images
.getTestBitmap(), 'Test', 'Test window') 
 211         tb
.AddSimpleTool(self
.ID_REFRESH
, images
.getRefreshBitmap(), 
 212                          'Refresh', 'Refresh view') 
 213         tb
.AddSimpleTool(self
.ID_AUTO_REFRESH
, images
.getAutoRefreshBitmap(), 
 214                          'Auto-refresh', 'Toggle auto-refresh mode', True) 
 215 #        if wx.Platform == '__WXGTK__': 
 216 #            tb.AddSeparator()   # otherwise auto-refresh sticks in status line 
 217         tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
) 
 221         self
.minWidth 
= tb
.GetSize()[0] # minimal width is the size of toolbar 
 224         wx
.EVT_MENU(self
, wx
.ID_NEW
, self
.OnNew
) 
 225         wx
.EVT_MENU(self
, wx
.ID_OPEN
, self
.OnOpen
) 
 226         wx
.EVT_MENU(self
, wx
.ID_SAVE
, self
.OnSaveOrSaveAs
) 
 227         wx
.EVT_MENU(self
, wx
.ID_SAVEAS
, self
.OnSaveOrSaveAs
) 
 228         wx
.EVT_MENU(self
, self
.ID_GENERATE_PYTHON
, self
.OnGeneratePython
) 
 229         wx
.EVT_MENU(self
, wx
.ID_EXIT
, self
.OnExit
) 
 231         wx
.EVT_MENU(self
, wx
.ID_UNDO
, self
.OnUndo
) 
 232         wx
.EVT_MENU(self
, wx
.ID_REDO
, self
.OnRedo
) 
 233         wx
.EVT_MENU(self
, wx
.ID_CUT
, self
.OnCutDelete
) 
 234         wx
.EVT_MENU(self
, wx
.ID_COPY
, self
.OnCopy
) 
 235         wx
.EVT_MENU(self
, wx
.ID_PASTE
, self
.OnPaste
) 
 236         wx
.EVT_MENU(self
, self
.ID_TOOL_PASTE
, self
.OnPaste
) 
 237         wx
.EVT_MENU(self
, self
.ID_DELETE
, self
.OnCutDelete
) 
 238         wx
.EVT_MENU(self
, self
.ID_LOCATE
, self
.OnLocate
) 
 239         wx
.EVT_MENU(self
, self
.ID_TOOL_LOCATE
, self
.OnLocate
) 
 241         wx
.EVT_MENU(self
, self
.ID_EMBED_PANEL
, self
.OnEmbedPanel
) 
 242         wx
.EVT_MENU(self
, self
.ID_SHOW_TOOLS
, self
.OnShowTools
) 
 243         wx
.EVT_MENU(self
, self
.ID_TEST
, self
.OnTest
) 
 244         wx
.EVT_MENU(self
, self
.ID_REFRESH
, self
.OnRefresh
) 
 245         wx
.EVT_MENU(self
, self
.ID_AUTO_REFRESH
, self
.OnAutoRefresh
) 
 246         wx
.EVT_MENU(self
, self
.ID_TEST_HIDE
, self
.OnTestHide
) 
 248         wx
.EVT_MENU(self
, wx
.ID_ABOUT
, self
.OnAbout
) 
 249         wx
.EVT_MENU(self
, self
.ID_README
, self
.OnReadme
) 
 252         wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVE
, self
.OnUpdateUI
) 
 253         wx
.EVT_UPDATE_UI(self
, wx
.ID_CUT
, self
.OnUpdateUI
) 
 254         wx
.EVT_UPDATE_UI(self
, wx
.ID_COPY
, self
.OnUpdateUI
) 
 255         wx
.EVT_UPDATE_UI(self
, wx
.ID_PASTE
, self
.OnUpdateUI
) 
 256         wx
.EVT_UPDATE_UI(self
, self
.ID_LOCATE
, self
.OnUpdateUI
) 
 257         wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_LOCATE
, self
.OnUpdateUI
) 
 258         wx
.EVT_UPDATE_UI(self
, self
.ID_TOOL_PASTE
, self
.OnUpdateUI
) 
 259         wx
.EVT_UPDATE_UI(self
, wx
.ID_UNDO
, self
.OnUpdateUI
) 
 260         wx
.EVT_UPDATE_UI(self
, wx
.ID_REDO
, self
.OnUpdateUI
) 
 261         wx
.EVT_UPDATE_UI(self
, self
.ID_DELETE
, self
.OnUpdateUI
) 
 262         wx
.EVT_UPDATE_UI(self
, self
.ID_TEST
, self
.OnUpdateUI
) 
 263         wx
.EVT_UPDATE_UI(self
, self
.ID_REFRESH
, self
.OnUpdateUI
) 
 266         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 267         sizer
.Add(wx
.StaticLine(self
, -1), 0, wx
.EXPAND
) 
 268         # Horizontal sizer for toolbar and splitter 
 269         self
.toolsSizer 
= sizer1 
= wx
.BoxSizer() 
 270         splitter 
= wx
.SplitterWindow(self
, -1, style
=wx
.SP_3DSASH
) 
 271         self
.splitter 
= splitter
 
 272         splitter
.SetMinimumPaneSize(100) 
 275         g
.tree 
= tree 
= XML_Tree(splitter
, -1) 
 277         # Init pull-down menu data 
 279         g
.pullDownMenu 
= pullDownMenu 
= PullDownMenu(self
) 
 281         # Vertical toolbar for GUI buttons 
 282         g
.tools 
= tools 
= Tools(self
) 
 283         tools
.Show(conf
.showTools
) 
 284         if conf
.showTools
: sizer1
.Add(tools
, 0, wx
.EXPAND
) 
 286         tree
.RegisterKeyEvents() 
 288         # !!! frame styles are broken 
 289         # Miniframe for not embedded mode 
 290         miniFrame 
= wx
.Frame(self
, -1, 'Properties & Style', 
 291                             (conf
.panelX
, conf
.panelY
), 
 292                             (conf
.panelWidth
, conf
.panelHeight
)) 
 293         self
.miniFrame 
= miniFrame
 
 294         sizer2 
= wx
.BoxSizer() 
 295         miniFrame
.SetAutoLayout(True) 
 296         miniFrame
.SetSizer(sizer2
) 
 297         wx
.EVT_CLOSE(self
.miniFrame
, self
.OnCloseMiniFrame
) 
 298         # Create panel for parameters 
 301             panel 
= Panel(splitter
) 
 302             # Set plitter windows 
 303             splitter
.SplitVertically(tree
, panel
, conf
.sashPos
) 
 305             panel 
= Panel(miniFrame
) 
 306             sizer2
.Add(panel
, 1, wx
.EXPAND
) 
 308             splitter
.Initialize(tree
) 
 309         sizer1
.Add(splitter
, 1, wx
.EXPAND
) 
 310         sizer
.Add(sizer1
, 1, wx
.EXPAND
) 
 311         self
.SetAutoLayout(True) 
 318         wx
.EVT_IDLE(self
, self
.OnIdle
) 
 319         wx
.EVT_CLOSE(self
, self
.OnCloseWindow
) 
 320         wx
.EVT_KEY_DOWN(self
, tools
.OnKeyDown
) 
 321         wx
.EVT_KEY_UP(self
, tools
.OnKeyUp
) 
 322         wx
.EVT_ICONIZE(self
, self
.OnIconize
) 
 324     def AppendRecent(self
, menu
): 
 325         # add recently used files to the menu 
 326         for id,name 
in conf
.recentfiles
.iteritems(): 
 328             wx
.EVT_MENU(self
,id,self
.OnRecentFile
) 
 331     def OnRecentFile(self
,evt
): 
 332         # open recently used file 
 333         if not self
.AskSave(): return 
 336             path
=conf
.recentfiles
[evt
.GetId()] 
 338                 self
.SetStatusText('Data loaded') 
 340                 self
.SetStatusText('Failed') 
 342             self
.SetStatusText('No such file') 
 345     def OnNew(self
, evt
): 
 346         if not self
.AskSave(): return 
 349     def OnOpen(self
, evt
): 
 350         if not self
.AskSave(): return 
 351         dlg 
= wx
.FileDialog(self
, 'Open', os
.path
.dirname(self
.dataFile
), 
 352                            '', '*.xrc', wx
.OPEN | wx
.CHANGE_DIR
) 
 353         if dlg
.ShowModal() == wx
.ID_OK
: 
 355             self
.SetStatusText('Loading...') 
 359                     self
.SetStatusText('Data loaded') 
 361                     self
.SetStatusText('Failed') 
 362                 self
.SaveRecent(path
) 
 367     def OnSaveOrSaveAs(self
, evt
): 
 368         if evt
.GetId() == wx
.ID_SAVEAS 
or not self
.dataFile
: 
 369             if self
.dataFile
: name 
= '' 
 370             else: name 
= defaultName
 
 371             dirname 
= os
.path
.abspath(os
.path
.dirname(self
.dataFile
)) 
 372             dlg 
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.xrc', 
 373                                wx
.SAVE | wx
.OVERWRITE_PROMPT | wx
.CHANGE_DIR
) 
 374             if dlg
.ShowModal() == wx
.ID_OK
: 
 382                 # if we already have a localconf then it needs to be 
 383                 # copied to a new config with the new name 
 385                 nc 
= self
.CreateLocalConf(path
) 
 386                 flag
, key
, idx 
= lc
.GetFirstEntry() 
 388                     nc
.Write(key
, lc
.Read(key
)) 
 389                     flag
, key
, idx 
= lc
.GetNextEntry(idx
) 
 392                 # otherwise create a new one 
 393                 conf
.localconf 
= self
.CreateLocalConf(path
) 
 396         self
.SetStatusText('Saving...') 
 400                 tmpFile
,tmpName 
= tempfile
.mkstemp(prefix
='xrced-') 
 402                 self
.Save(tmpName
) # save temporary file first 
 403                 shutil
.move(tmpName
, path
) 
 405                 if conf
.localconf
.ReadBool("autogenerate", False): 
 406                     pypath 
= conf
.localconf
.Read("filename") 
 407                     embed 
= conf
.localconf
.ReadBool("embedResource", False) 
 408                     genGettext 
= conf
.localconf
.ReadBool("genGettext", False) 
 409                     self
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
) 
 411                 self
.SetStatusText('Data saved') 
 412                 self
.SaveRecent(path
) 
 414                 self
.SetStatusText('Failed') 
 418     def SaveRecent(self
,path
): 
 419         # append to recently used files 
 420         if path 
not in conf
.recentfiles
.values(): 
 422             self
.recentMenu
.Append(newid
, path
) 
 423             wx
.EVT_MENU(self
, newid
, self
.OnRecentFile
) 
 424             conf
.recentfiles
[newid
] = path
 
 426     def GeneratePython(self
, dataFile
, pypath
, embed
, genGettext
): 
 428             import wx
.tools
.pywxrc
 
 429             rescomp 
= wx
.tools
.pywxrc
.XmlResourceCompiler() 
 430             rescomp
.MakePythonModule([dataFile
], pypath
, embed
, genGettext
) 
 433             wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1]) 
 434             wx
.LogError('Error generating python code : %s' % pypath
) 
 438     def OnGeneratePython(self
, evt
): 
 439         if self
.modified 
or not conf
.localconf
: 
 440             wx
.MessageBox("Save the XRC file first!", "Error") 
 443         dlg 
= PythonOptions(self
, conf
.localconf
, self
.dataFile
) 
 448     def OnExit(self
, evt
): 
 451     def OnUndo(self
, evt
): 
 452         # Extra check to not mess with idle updating 
 453         if undoMan
.CanUndo(): 
 456     def OnRedo(self
, evt
): 
 457         if undoMan
.CanRedo(): 
 460     def OnCopy(self
, evt
): 
 461         selected 
= tree
.selection
 
 462         if not selected
: return         # key pressed event 
 463         xxx 
= tree
.GetPyData(selected
) 
 464         if wx
.TheClipboard
.Open(): 
 465             data 
= wx
.CustomDataObject('XRCED') 
 466             # Set encoding in header 
 468             s 
= xxx
.element
.toxml(encoding
=expat
.native_encoding
) 
 469             data
.SetData(cPickle
.dumps(s
)) 
 470             wx
.TheClipboard
.SetData(data
) 
 471             wx
.TheClipboard
.Close() 
 472             self
.SetStatusText('Copied') 
 474             wx
.MessageBox("Unable to open the clipboard", "Error") 
 476     def OnPaste(self
, evt
): 
 477         selected 
= tree
.selection
 
 478         if not selected
: return         # key pressed event 
 479         # For pasting with Ctrl pressed 
 481         if evt
.GetId() == pullDownMenu
.ID_PASTE_SIBLING
: appendChild 
= False 
 482         elif evt
.GetId() == self
.ID_TOOL_PASTE
: 
 483             if g
.tree
.ctrl
: appendChild 
= False 
 484             else: appendChild 
= not tree
.NeedInsert(selected
) 
 485         else: appendChild 
= not tree
.NeedInsert(selected
) 
 486         xxx 
= tree
.GetPyData(selected
) 
 488             # If has next item, insert, else append to parent 
 489             nextItem 
= tree
.GetNextSibling(selected
) 
 490             parentLeaf 
= tree
.GetItemParent(selected
) 
 491         # Expanded container (must have children) 
 492         elif tree
.IsExpanded(selected
) and tree
.GetChildrenCount(selected
, False): 
 493             # Insert as first child 
 494             nextItem 
= tree
.GetFirstChild(selected
)[0] 
 495             parentLeaf 
= selected
 
 497             # No children or unexpanded item - appendChild stays True 
 498             nextItem 
= wx
.TreeItemId()   # no next item 
 499             parentLeaf 
= selected
 
 500         parent 
= tree
.GetPyData(parentLeaf
).treeObject() 
 502         # Create a copy of clipboard pickled element 
 504         if wx
.TheClipboard
.Open(): 
 505             data 
= wx
.CustomDataObject('XRCED') 
 506             if wx
.TheClipboard
.IsSupported(data
.GetFormat()): 
 507                 success 
= wx
.TheClipboard
.GetData(data
) 
 508             wx
.TheClipboard
.Close() 
 512                 "There is no data in the clipboard in the required format", 
 516         xml 
= cPickle
.loads(data
.GetData()) # xml representation of element 
 517         elem 
= minidom
.parseString(xml
).childNodes
[0] 
 518         # Tempopary xxx object to test things 
 519         xxx 
= MakeXXXFromDOM(parent
, elem
) 
 520         # Check compatibility 
 524         if x
.__class
__ in [xxxDialog
, xxxFrame
, xxxWizard
]: 
 526             if parent
.__class
__ != xxxMainNode
: error 
= True 
 527         elif x
.__class
__ == xxxMenuBar
: 
 528             # Menubar can be put in frame or dialog 
 529             if parent
.__class
__ not in [xxxMainNode
, xxxFrame
, xxxDialog
]: error 
= True 
 530         elif x
.__class
__ == xxxToolBar
: 
 531             # Toolbar can be top-level of child of panel or frame 
 532             if parent
.__class
__ not in [xxxMainNode
, xxxPanel
, xxxFrame
] and \
 
 533                not parent
.isSizer
: error 
= True 
 534         elif x
.__class
__ == xxxPanel 
and parent
.__class
__ == xxxMainNode
: 
 536         elif x
.__class
__ == xxxSpacer
: 
 537             if not parent
.isSizer
: error 
= True 
 538         elif x
.__class
__ == xxxSeparator
: 
 539             if not parent
.__class
__ in [xxxMenu
, xxxToolBar
]: error 
= True 
 540         elif x
.__class
__ == xxxTool
: 
 541             if parent
.__class
__ != xxxToolBar
: error 
= True 
 542         elif x
.__class
__ == xxxMenu
: 
 543             if not parent
.__class
__ in [xxxMainNode
, xxxMenuBar
, xxxMenu
]: error 
= True 
 544         elif x
.__class
__ == xxxMenuItem
: 
 545             if not parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error 
= True 
 546         elif x
.isSizer 
and parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]: 
 548         else:                           # normal controls can be almost anywhere 
 549             if parent
.__class
__ == xxxMainNode 
or \
 
 550                parent
.__class
__ in [xxxMenuBar
, xxxMenu
]: error 
= True 
 552             if parent
.__class
__ == xxxMainNode
: parentClass 
= 'root' 
 553             else: parentClass 
= parent
.className
 
 554             wx
.LogError('Incompatible parent/child: parent is %s, child is %s!' % 
 555                        (parentClass
, x
.className
)) 
 558         # Check parent and child relationships. 
 559         # If parent is sizer or notebook, child is of wrong class or 
 560         # parent is normal window, child is child container then detach child. 
 561         isChildContainer 
= isinstance(xxx
, xxxChildContainer
) 
 562         parentIsBook 
= parent
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
] 
 563         if isChildContainer 
and \
 
 564            ((parent
.isSizer 
and not isinstance(xxx
, xxxSizerItem
)) or \
 
 565             (parentIsBook 
and not isinstance(xxx
, xxxPage
)) or \
 
 566            not (parent
.isSizer 
or parentIsBook
)): 
 567             elem
.removeChild(xxx
.child
.element
) # detach child 
 568             elem
.unlink()           # delete child container 
 569             elem 
= xxx
.child
.element 
# replace 
 570             # This may help garbage collection 
 571             xxx
.child
.parent 
= None 
 572             isChildContainer 
= False 
 573         # Parent is sizer or notebook, child is not child container 
 574         if parent
.isSizer 
and not isChildContainer 
and not isinstance(xxx
, xxxSpacer
): 
 575             # Create sizer item element 
 576             sizerItemElem 
= MakeEmptyDOM(parent
.itemTag
) 
 577             sizerItemElem
.appendChild(elem
) 
 579         elif isinstance(parent
, xxxNotebook
) and not isChildContainer
: 
 580             pageElem 
= MakeEmptyDOM('notebookpage') 
 581             pageElem
.appendChild(elem
) 
 583         elif isinstance(parent
, xxxChoicebook
) and not isChildContainer
: 
 584             pageElem 
= MakeEmptyDOM('choicebookpage') 
 585             pageElem
.appendChild(elem
) 
 587         elif isinstance(parent
, xxxListbook
) and not isChildContainer
: 
 588             pageElem 
= MakeEmptyDOM('listbookpage') 
 589             pageElem
.appendChild(elem
) 
 591         # Insert new node, register undo 
 592         newItem 
= tree
.InsertNode(parentLeaf
, parent
, elem
, nextItem
) 
 593         undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
)) 
 594         # Scroll to show new item (!!! redundant?) 
 595         tree
.EnsureVisible(newItem
) 
 596         tree
.SelectItem(newItem
) 
 597         if not tree
.IsVisible(newItem
): 
 598             tree
.ScrollTo(newItem
) 
 601         if g
.testWin 
and tree
.IsHighlatable(newItem
): 
 603                 tree
.needUpdate 
= True 
 604                 tree
.pendingHighLight 
= newItem
 
 606                 tree
.pendingHighLight 
= None 
 608         self
.SetStatusText('Pasted') 
 611     def OnCutDelete(self
, evt
): 
 612         selected 
= tree
.selection
 
 613         if not selected
: return         # key pressed event 
 615         if evt
.GetId() == wx
.ID_CUT
: 
 617             status 
= 'Removed to clipboard' 
 619             self
.lastOp 
= 'DELETE' 
 623             # If deleting top-level item, delete testWin 
 624             if selected 
== g
.testWin
.item
: 
 628                 # Remove highlight, update testWin 
 629                 if g
.testWin
.highLight
: 
 630                     g
.testWin
.highLight
.Remove() 
 631                 tree
.needUpdate 
= True 
 634         index 
= tree
.ItemFullIndex(selected
) 
 635         parent 
= tree
.GetPyData(tree
.GetItemParent(selected
)).treeObject() 
 636         elem 
= tree
.RemoveLeaf(selected
) 
 637         undoMan
.RegisterUndo(UndoCutDelete(index
, parent
, elem
)) 
 638         if evt
.GetId() == wx
.ID_CUT
: 
 639             if wx
.TheClipboard
.Open(): 
 640                 data 
= wx
.CustomDataObject('XRCED') 
 642                 s 
= elem
.toxml(encoding
=expat
.native_encoding
) 
 643                 data
.SetData(cPickle
.dumps(s
)) 
 644                 wx
.TheClipboard
.SetData(data
) 
 645                 wx
.TheClipboard
.Close() 
 647                 wx
.MessageBox("Unable to open the clipboard", "Error") 
 648         tree
.pendingHighLight 
= None 
 650         tree
.selection 
= None 
 655         self
.SetStatusText(status
) 
 657     def OnSubclass(self
, evt
): 
 658         selected 
= tree
.selection
 
 659         xxx 
= tree
.GetPyData(selected
).treeObject() 
 661         subclass 
= xxx
.subclass
 
 662         dlg 
= wx
.TextEntryDialog(self
, 'Subclass:', defaultValue
=subclass
) 
 663         if dlg
.ShowModal() == wx
.ID_OK
: 
 664             subclass 
= dlg
.GetValue() 
 666                 elem
.setAttribute('subclass', subclass
) 
 667             elif elem
.hasAttribute('subclass'): 
 668                 elem
.removeAttribute('subclass') 
 670             xxx
.subclass 
= elem
.getAttribute('subclass') 
 671             tree
.SetItemText(selected
, xxx
.treeName()) 
 672             panel
.pages
[0].box
.SetLabel(xxx
.panelName()) 
 675     def OnEmbedPanel(self
, evt
): 
 676         conf
.embedPanel 
= evt
.IsChecked() 
 678             # Remember last dimentions 
 679             conf
.panelX
, conf
.panelY 
= self
.miniFrame
.GetPosition() 
 680             conf
.panelWidth
, conf
.panelHeight 
= self
.miniFrame
.GetSize() 
 681             size 
= self
.GetSize() 
 682             pos 
= self
.GetPosition() 
 683             sizePanel 
= panel
.GetSize() 
 684             panel
.Reparent(self
.splitter
) 
 685             self
.miniFrame
.GetSizer().Remove(panel
) 
 687             self
.SetDimensions(pos
.x
, pos
.y
, size
.width 
+ sizePanel
.width
, size
.height
) 
 688             self
.splitter
.SplitVertically(tree
, panel
, conf
.sashPos
) 
 689             self
.miniFrame
.Show(False) 
 691             conf
.sashPos 
= self
.splitter
.GetSashPosition() 
 692             pos 
= self
.GetPosition() 
 693             size 
= self
.GetSize() 
 694             sizePanel 
= panel
.GetSize() 
 695             self
.splitter
.Unsplit(panel
) 
 696             sizer 
= self
.miniFrame
.GetSizer() 
 697             panel
.Reparent(self
.miniFrame
) 
 699             sizer
.Add(panel
, 1, wx
.EXPAND
) 
 700             self
.miniFrame
.Show(True) 
 701             self
.miniFrame
.SetDimensions(conf
.panelX
, conf
.panelY
, 
 702                                          conf
.panelWidth
, conf
.panelHeight
) 
 704             self
.SetDimensions(pos
.x
, pos
.y
, 
 705                                max(size
.width 
- sizePanel
.width
, self
.minWidth
), size
.height
) 
 707     def OnShowTools(self
, evt
): 
 708         conf
.showTools 
= evt
.IsChecked() 
 709         g
.tools
.Show(conf
.showTools
) 
 711             self
.toolsSizer
.Prepend(g
.tools
, 0, wx
.EXPAND
) 
 713             self
.toolsSizer
.Remove(g
.tools
) 
 714         self
.toolsSizer
.Layout() 
 716     def OnTest(self
, evt
): 
 717         if not tree
.selection
: return   # key pressed event 
 718         tree
.ShowTestWindow(tree
.selection
) 
 720     def OnTestHide(self
, evt
): 
 721         tree
.CloseTestWindow() 
 723     # Find object by relative position 
 724     def FindObject(self
, item
, obj
): 
 725         # We simply perform depth-first traversal, sinse it's too much 
 726         # hassle to deal with all sizer/window combinations 
 727         w 
= tree
.FindNodeObject(item
) 
 728         if w 
== obj 
or isinstance(w
, wx
.GBSizerItem
) and w
.GetWindow() == obj
: 
 730         if tree
.ItemHasChildren(item
): 
 731             child 
= tree
.GetFirstChild(item
)[0] 
 733                 found 
= self
.FindObject(child
, obj
) 
 734                 if found
: return found
 
 735                 child 
= tree
.GetNextSibling(child
) 
 738     def OnTestWinLeftDown(self
, evt
): 
 739         pos 
= evt
.GetPosition() 
 740         self
.SetHandler(g
.testWin
) 
 741         g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
) 
 742         item 
= self
.FindObject(g
.testWin
.item
, evt
.GetEventObject()) 
 744             tree
.EnsureVisible(item
) 
 745             tree
.SelectItem(item
) 
 746         self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, False) 
 748             self
.SetStatusText('Selected %s' % tree
.GetItemText(item
)) 
 750             self
.SetStatusText('Locate failed!') 
 752     def SetHandler(self
, w
, h
=None): 
 755             w
.SetCursor(wx
.CROSS_CURSOR
) 
 758             w
.SetCursor(wx
.NullCursor
) 
 759         for ch 
in w
.GetChildren(): 
 760             self
.SetHandler(ch
, h
) 
 762     def OnLocate(self
, evt
): 
 764             if evt
.GetId() == self
.ID_LOCATE 
or \
 
 765                evt
.GetId() == self
.ID_TOOL_LOCATE 
and evt
.IsChecked(): 
 766                 self
.SetHandler(g
.testWin
, g
.testWin
) 
 767                 g
.testWin
.Connect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
, self
.OnTestWinLeftDown
) 
 768                 if evt
.GetId() == self
.ID_LOCATE
: 
 769                     self
.tb
.ToggleTool(self
.ID_TOOL_LOCATE
, True) 
 770             elif evt
.GetId() == self
.ID_TOOL_LOCATE 
and not evt
.IsChecked(): 
 771                 self
.SetHandler(g
.testWin
, None) 
 772                 g
.testWin
.Disconnect(wx
.ID_ANY
, wx
.ID_ANY
, wx
.wxEVT_LEFT_DOWN
) 
 773             self
.SetStatusText('Click somewhere in your test window now') 
 775     def OnRefresh(self
, evt
): 
 776         # If modified, apply first 
 777         selection 
= tree
.selection
 
 779             xxx 
= tree
.GetPyData(selection
) 
 780             if xxx 
and panel
.IsModified(): 
 781                 tree
.Apply(xxx
, selection
) 
 784             tree
.CreateTestWin(g
.testWin
.item
) 
 785         panel
.modified 
= False 
 786         tree
.needUpdate 
= False 
 788     def OnAutoRefresh(self
, evt
): 
 789         conf
.autoRefresh 
= evt
.IsChecked() 
 790         self
.menuBar
.Check(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
) 
 791         self
.tb
.ToggleTool(self
.ID_AUTO_REFRESH
, conf
.autoRefresh
) 
 793     def OnAbout(self
, evt
): 
 797 (c) Roman Rolinsky <rollrom@users.sourceforge.net> 
 798 Homepage: http://xrced.sourceforge.net\ 
 800         dlg 
= wx
.MessageDialog(self
, str, 'About XRCed', wx
.OK | wx
.CENTRE
) 
 804     def OnReadme(self
, evt
): 
 805         text 
= open(os
.path
.join(basePath
, 'README.txt'), 'r').read() 
 806         dlg 
= ScrolledMessageDialog(self
, text
, "XRCed README") 
 810     # Simple emulation of python command line 
 811     def OnDebugCMD(self
, evt
): 
 814                 exec raw_input('C:\> ') 
 819                 (etype
, value
, tb
) =sys
.exc_info() 
 820                 tblist 
=traceback
.extract_tb(tb
)[1:] 
 821                 msg 
=' '.join(traceback
.format_exception_only(etype
, value
) 
 822                         +traceback
.format_list(tblist
)) 
 825     def OnCreate(self
, evt
): 
 826         selected 
= tree
.selection
 
 827         if tree
.ctrl
: appendChild 
= False 
 828         else: appendChild 
= not tree
.NeedInsert(selected
) 
 829         xxx 
= tree
.GetPyData(selected
) 
 833                 # If has previous item, insert after it, else append to parent 
 835                 parentLeaf 
= tree
.GetItemParent(selected
) 
 837                 # If has next item, insert, else append to parent 
 838                 nextItem 
= tree
.GetNextSibling(selected
) 
 839                 parentLeaf 
= tree
.GetItemParent(selected
) 
 840         # Expanded container (must have children) 
 841         elif tree
.shift 
and tree
.IsExpanded(selected
) \
 
 842            and tree
.GetChildrenCount(selected
, False): 
 843             nextItem 
= tree
.GetFirstChild(selected
)[0] 
 844             parentLeaf 
= selected
 
 846             nextItem 
= wx
.TreeItemId() 
 847             parentLeaf 
= selected
 
 848         parent 
= tree
.GetPyData(parentLeaf
) 
 849         if parent
.hasChild
: parent 
= parent
.child
 
 852         if evt
.GetId() == ID_NEW
.REF
: 
 853             ref 
= wx
.GetTextFromUser('Create reference to:', 'Create reference') 
 855             xxx 
= MakeEmptyRefXXX(parent
, ref
) 
 857             # Create empty element 
 858             className 
= pullDownMenu
.createMap
[evt
.GetId()] 
 859             xxx 
= MakeEmptyXXX(parent
, className
) 
 861         # Set default name for top-level windows 
 862         if parent
.__class
__ == xxxMainNode
: 
 863             cl 
= xxx
.treeObject().__class
__ 
 864             frame
.maxIDs
[cl
] += 1 
 865             xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
])) 
 866         # And for some other standard controls 
 867         elif parent
.__class
__ == xxxStdDialogButtonSizer
: 
 868             xxx
.setTreeName(pullDownMenu
.stdButtonIDs
[evt
.GetId()][0]) 
 869             # We can even set label 
 870             obj 
= xxx
.treeObject() 
 871             elem 
= g
.tree
.dom
.createElement('label') 
 872             elem
.appendChild(g
.tree
.dom
.createTextNode(pullDownMenu
.stdButtonIDs
[evt
.GetId()][1])) 
 873             obj
.params
['label'] = xxxParam(elem
) 
 874             xxx
.treeObject().element
.appendChild(elem
) 
 876         # Insert new node, register undo 
 878         newItem 
= tree
.InsertNode(parentLeaf
, parent
, elem
, nextItem
) 
 879         undoMan
.RegisterUndo(UndoPasteCreate(parentLeaf
, parent
, newItem
, selected
)) 
 880         tree
.EnsureVisible(newItem
) 
 881         tree
.SelectItem(newItem
) 
 882         if not tree
.IsVisible(newItem
): 
 883             tree
.ScrollTo(newItem
) 
 886         if g
.testWin 
and tree
.IsHighlatable(newItem
): 
 888                 tree
.needUpdate 
= True 
 889                 tree
.pendingHighLight 
= newItem
 
 891                 tree
.pendingHighLight 
= None 
 895     # Replace one object with another 
 896     def OnReplace(self
, evt
): 
 897         selected 
= tree
.selection
 
 898         xxx 
= tree
.GetPyData(selected
).treeObject() 
 900         parent 
= elem
.parentNode
 
 901         undoMan
.RegisterUndo(UndoReplace(selected
)) 
 903         className 
= pullDownMenu
.createMap
[evt
.GetId() - 1000] 
 904         # Create temporary empty node (with default values) 
 905         dummy 
= MakeEmptyDOM(className
) 
 906         if className 
== 'spacer' and xxx
.className 
!= 'spacer': 
 908         elif xxx
.className 
== 'spacer' and className 
!= 'spacer': 
 911             klass 
= xxxDict
[className
] 
 912         # Remove non-compatible children 
 913         if tree
.ItemHasChildren(selected
) and not klass
.hasChildren
: 
 914             tree
.DeleteChildren(selected
) 
 915         nodes 
= elem
.childNodes
[:] 
 918             if node
.nodeType 
!= minidom
.Node
.ELEMENT_NODE
: continue 
 922                 if not klass
.hasChildren
:  remove 
= True 
 923             elif tag 
not in klass
.allParams 
and \
 
 924                      (not klass
.hasStyle 
or tag 
not in klass
.styles
): 
 929                 elem
.removeChild(node
) 
 932         # Remove sizeritem child if spacer 
 933         if className 
== 'spacer' and xxx
.className 
!= 'spacer': 
 934             sizeritem 
= elem
.parentNode
 
 935             assert sizeritem
.getAttribute('class') == 'sizeritem' 
 936             sizeritem
.removeChild(elem
) 
 939             tree
.GetPyData(selected
).hasChild 
= false
 
 940         elif xxx
.className 
== 'spacer' and className 
!= 'spacer': 
 941             # Create sizeritem element 
 942             assert xxx
.parent
.isSizer
 
 943             elem
.setAttribute('class', 'sizeritem') 
 944             node 
= MakeEmptyDOM(className
) 
 945             elem
.appendChild(node
) 
 946             # Replace to point to new object 
 947             xxx 
= xxxSizerItem(xxx
.parent
, elem
) 
 949             tree
.SetPyData(selected
, xxx
) 
 952             # Copy parameters present in dummy but not in elem 
 953             for node 
in dummy
.childNodes
: 
 954                 if node
.tagName 
not in tags
:  elem
.appendChild(node
.cloneNode(True)) 
 958         elem
.setAttribute('class', className
) 
 959         if elem
.hasAttribute('subclass'): 
 960             elem
.removeAttribute('subclass') # clear subclassing 
 961         # Re-create xxx element 
 962         xxx 
= MakeXXXFromDOM(xxx
.parent
, elem
) 
 963         # Update parent in child objects 
 964         if tree
.ItemHasChildren(selected
): 
 965             i
, cookie 
= tree
.GetFirstChild(selected
) 
 967                 x 
= tree
.GetPyData(i
) 
 969                 if x
.hasChild
: x
.child
.parent 
= xxx
 
 970                 i
, cookie 
= tree
.GetNextChild(selected
, cookie
) 
 973         if tree
.GetPyData(selected
).hasChild
: # child container 
 974             container 
= tree
.GetPyData(selected
) 
 975             container
.child 
= xxx
 
 976             container
.hasChildren 
= xxx
.hasChildren
 
 977             container
.isSizer 
= xxx
.isSizer
 
 980             tree
.SetPyData(selected
, xxx
) 
 981         tree
.SetItemText(selected
, xxx
.treeName()) 
 982         tree
.SetItemImage(selected
, xxx
.treeImage()) 
 984         # Set default name for top-level windows 
 985         if parent
.__class
__ == xxxMainNode
: 
 986             cl 
= xxx
.treeObject().__class
__ 
 987             frame
.maxIDs
[cl
] += 1 
 988             xxx
.setTreeName('%s%d' % (defaultIDs
[cl
], frame
.maxIDs
[cl
])) 
 995         #undoMan.RegisterUndo(UndoPasteCreate(parentLeaf, parent, newItem, selected)) 
 997         if g
.testWin 
and tree
.IsHighlatable(selected
): 
 999                 tree
.needUpdate 
= True 
1000                 tree
.pendingHighLight 
= selected
 
1002                 tree
.pendingHighLight 
= None 
1006     # Expand/collapse subtree 
1007     def OnExpand(self
, evt
): 
1008         if tree
.selection
: tree
.ExpandAll(tree
.selection
) 
1009         else: tree
.ExpandAll(tree
.root
) 
1010     def OnCollapse(self
, evt
): 
1011         if tree
.selection
: tree
.CollapseAll(tree
.selection
) 
1012         else: tree
.CollapseAll(tree
.root
) 
1014     def OnPullDownHighlight(self
, evt
): 
1015         menuId 
= evt
.GetMenuId() 
1017             menu 
= evt
.GetEventObject() 
1018             help = menu
.GetHelpString(menuId
) 
1019             self
.SetStatusText(help) 
1021             self
.SetStatusText('') 
1023     def OnUpdateUI(self
, evt
): 
1024         if evt
.GetId() in [wx
.ID_CUT
, wx
.ID_COPY
, self
.ID_DELETE
]: 
1025             evt
.Enable(tree
.selection 
is not None and tree
.selection 
!= tree
.root
) 
1026         elif evt
.GetId() == wx
.ID_SAVE
: 
1027             evt
.Enable(self
.modified
) 
1028         elif evt
.GetId() in [wx
.ID_PASTE
, self
.ID_TOOL_PASTE
]: 
1029             evt
.Enable(tree
.selection 
is not None) 
1030         elif evt
.GetId() == self
.ID_TEST
: 
1031             evt
.Enable(tree
.selection 
is not None and tree
.selection 
!= tree
.root
) 
1032         elif evt
.GetId() in [self
.ID_LOCATE
, self
.ID_TOOL_LOCATE
]: 
1033             evt
.Enable(g
.testWin 
is not None) 
1034         elif evt
.GetId() == wx
.ID_UNDO
:  evt
.Enable(undoMan
.CanUndo()) 
1035         elif evt
.GetId() == wx
.ID_REDO
:  evt
.Enable(undoMan
.CanRedo()) 
1037     def OnIdle(self
, evt
): 
1038         if self
.inIdle
: return          # Recursive call protection 
1042                 if conf
.autoRefresh
: 
1044                         self
.SetStatusText('Refreshing test window...') 
1046                         tree
.CreateTestWin(g
.testWin
.item
) 
1047                         self
.SetStatusText('') 
1048                     tree
.needUpdate 
= False 
1049             elif tree
.pendingHighLight
: 
1051                     tree
.HighLight(tree
.pendingHighLight
) 
1053                     # Remove highlight if any problem 
1054                     if g
.testWin
.highLight
: 
1055                         g
.testWin
.highLight
.Remove() 
1056                     tree
.pendingHighLight 
= None 
1063     # We don't let close panel window 
1064     def OnCloseMiniFrame(self
, evt
): 
1067     def OnIconize(self
, evt
): 
1068         conf
.x
, conf
.y 
= self
.GetPosition() 
1069         conf
.width
, conf
.height 
= self
.GetSize() 
1071             conf
.sashPos 
= self
.splitter
.GetSashPosition() 
1073             conf
.panelX
, conf
.panelY 
= self
.miniFrame
.GetPosition() 
1074             conf
.panelWidth
, conf
.panelHeight 
= self
.miniFrame
.GetSize() 
1075             self
.miniFrame
.Iconize() 
1078     def OnCloseWindow(self
, evt
): 
1079         if not self
.AskSave(): return 
1080         if g
.testWin
: g
.testWin
.Destroy() 
1081         if not panel
.GetPageCount() == 2: 
1082             panel
.page2
.Destroy() 
1084             # If we don't do this, page does not get destroyed (a bug?) 
1086         if not self
.IsIconized(): 
1087             conf
.x
, conf
.y 
= self
.GetPosition() 
1088             conf
.width
, conf
.height 
= self
.GetSize() 
1090                 conf
.sashPos 
= self
.splitter
.GetSashPosition() 
1092                 conf
.panelX
, conf
.panelY 
= self
.miniFrame
.GetPosition() 
1093                 conf
.panelWidth
, conf
.panelHeight 
= self
.miniFrame
.GetSize() 
1097     def CreateLocalConf(self
, path
): 
1098         name 
= os
.path
.splitext(path
)[0] 
1100         return wx
.FileConfig(localFilename
=name
) 
1105         conf
.localconf 
= None 
1107         self
.SetModified(False) 
1113         # Numbers for new controls 
1115         for cl 
in [xxxPanel
, xxxDialog
, xxxFrame
, 
1116                    xxxMenuBar
, xxxMenu
, xxxToolBar
, 
1117                    xxxWizard
, xxxBitmap
, xxxIcon
]: 
1120     def SetModified(self
, state
=True): 
1121         self
.modified 
= state
 
1122         name 
= os
.path
.basename(self
.dataFile
) 
1123         if not name
: name 
= defaultName
 
1125             self
.SetTitle(progname 
+ ': ' + name 
+ ' *') 
1127             self
.SetTitle(progname 
+ ': ' + name
) 
1129     def Open(self
, path
): 
1130         if not os
.path
.exists(path
): 
1131             wx
.LogError('File does not exists: %s' % path
) 
1133         # Try to read the file 
1137             dom 
= minidom
.parse(f
) 
1139             # Set encoding global variable and default encoding 
1141                 g
.currentEncoding 
= dom
.encoding
 
1142                 wx
.SetDefaultPyEncoding(g
.currentEncoding
.encode()) 
1144                 g
.currentEncoding 
= '' 
1146             self
.dataFile 
= path 
= os
.path
.abspath(path
) 
1147             dir = os
.path
.dirname(path
) 
1148             if dir: os
.chdir(dir) 
1150             self
.SetTitle(progname 
+ ': ' + os
.path
.basename(path
)) 
1151             conf
.localconf 
= self
.CreateLocalConf(self
.dataFile
) 
1153             # Nice exception printing 
1154             inf 
= sys
.exc_info() 
1155             wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1]) 
1156             wx
.LogError('Error reading file: %s' % path
) 
1161     def Indent(self
, node
, indent 
= 0): 
1162         # Copy child list because it will change soon 
1163         children 
= node
.childNodes
[:] 
1164         # Main node doesn't need to be indented 
1166             text 
= self
.domCopy
.createTextNode('\n' + ' ' * indent
) 
1167             node
.parentNode
.insertBefore(text
, node
) 
1169             # Append newline after last child, except for text nodes 
1170             if children
[-1].nodeType 
== minidom
.Node
.ELEMENT_NODE
: 
1171                 text 
= self
.domCopy
.createTextNode('\n' + ' ' * indent
) 
1172                 node
.appendChild(text
) 
1173             # Indent children which are elements 
1175                 if n
.nodeType 
== minidom
.Node
.ELEMENT_NODE
: 
1176                     self
.Indent(n
, indent 
+ 2) 
1178     def Save(self
, path
): 
1182             if tree
.selection 
and panel
.IsModified(): 
1183                 self
.OnRefresh(wx
.CommandEvent()) 
1184             if g
.currentEncoding
: 
1185                 f 
= codecs
.open(path
, 'wt', g
.currentEncoding
) 
1187                 f 
= codecs
.open(path
, 'wt') 
1188             # Make temporary copy for formatting it 
1189             # !!! We can't clone dom node, it works only once 
1190             #self.domCopy = tree.dom.cloneNode(True) 
1191             self
.domCopy 
= MyDocument() 
1192             mainNode 
= self
.domCopy
.appendChild(tree
.mainNode
.cloneNode(True)) 
1193             # Remove first child (test element) 
1194             testElem 
= mainNode
.firstChild
 
1195             mainNode
.removeChild(testElem
) 
1197             self
.Indent(mainNode
) 
1198             self
.domCopy
.writexml(f
, encoding 
= g
.currentEncoding
) 
1200             self
.domCopy
.unlink() 
1202             self
.SetModified(False) 
1203             panel
.SetModified(False) 
1204             conf
.localconf
.Flush() 
1206             inf 
= sys
.exc_info() 
1207             wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1]) 
1208             wx
.LogError('Error writing file: %s' % path
) 
1212         if not (self
.modified 
or panel
.IsModified()): return True 
1213         flags 
= wx
.ICON_EXCLAMATION | wx
.YES_NO | wx
.CANCEL | wx
.CENTRE
 
1214         dlg 
= wx
.MessageDialog( self
, 'File is modified. Save before exit?', 
1215                                'Save before too late?', flags 
) 
1216         say 
= dlg
.ShowModal() 
1219         if say 
== wx
.ID_YES
: 
1220             self
.OnSaveOrSaveAs(wx
.CommandEvent(wx
.ID_SAVE
)) 
1221             # If save was successful, modified flag is unset 
1222             if not self
.modified
: return True 
1223         elif say 
== wx
.ID_NO
: 
1224             self
.SetModified(False) 
1225             panel
.SetModified(False) 
1232 ################################################################################ 
1234 class PythonOptions(wx
.Dialog
): 
1236     def __init__(self
, parent
, cfg
, dataFile
): 
1237         pre 
= wx
.PreDialog() 
1238         g
.frame
.res
.LoadOnDialog(pre
, parent
, "PYTHON_OPTIONS") 
1239         self
.PostCreate(pre
) 
1242         self
.dataFile 
= dataFile
 
1244         self
.AutoGenerateCB 
= xrc
.XRCCTRL(self
, "AutoGenerateCB") 
1245         self
.EmbedCB 
= xrc
.XRCCTRL(self
, "EmbedCB") 
1246         self
.GettextCB 
= xrc
.XRCCTRL(self
, "GettextCB") 
1247         self
.MakeXRSFileCB 
= xrc
.XRCCTRL(self
, "MakeXRSFileCB") 
1248         self
.FileNameTC 
= xrc
.XRCCTRL(self
, "FileNameTC") 
1249         self
.BrowseBtn 
= xrc
.XRCCTRL(self
, "BrowseBtn") 
1250         self
.GenerateBtn 
= xrc
.XRCCTRL(self
, "GenerateBtn") 
1251         self
.SaveOptsBtn 
= xrc
.XRCCTRL(self
, "SaveOptsBtn") 
1253         self
.Bind(wx
.EVT_BUTTON
, self
.OnBrowse
, self
.BrowseBtn
) 
1254         self
.Bind(wx
.EVT_BUTTON
, self
.OnGenerate
, self
.GenerateBtn
) 
1255         self
.Bind(wx
.EVT_BUTTON
, self
.OnSaveOpts
, self
.SaveOptsBtn
) 
1257         if self
.cfg
.Read("filename", "") != "": 
1258             self
.FileNameTC
.SetValue(self
.cfg
.Read("filename")) 
1260             name 
= os
.path
.splitext(dataFile
)[0] 
1262             self
.FileNameTC
.SetValue(name
) 
1263         self
.AutoGenerateCB
.SetValue(self
.cfg
.ReadBool("autogenerate", False)) 
1264         self
.EmbedCB
.SetValue(self
.cfg
.ReadBool("embedResource", False)) 
1265         self
.MakeXRSFileCB
.SetValue(self
.cfg
.ReadBool("makeXRS", False)) 
1266         self
.GettextCB
.SetValue(self
.cfg
.ReadBool("genGettext", False)) 
1269     def OnBrowse(self
, evt
): 
1270         path 
= self
.FileNameTC
.GetValue() 
1271         dirname 
= os
.path
.abspath(os
.path
.dirname(path
)) 
1272         name 
= os
.path
.split(path
)[1] 
1273         dlg 
= wx
.FileDialog(self
, 'Save As', dirname
, name
, '*.py', 
1274                                wx
.SAVE | wx
.OVERWRITE_PROMPT
) 
1275         if dlg
.ShowModal() == wx
.ID_OK
: 
1276             path 
= dlg
.GetPath() 
1277             self
.FileNameTC
.SetValue(path
) 
1281     def OnGenerate(self
, evt
): 
1282         pypath 
= self
.FileNameTC
.GetValue() 
1283         embed 
= self
.EmbedCB
.GetValue() 
1284         genGettext 
= self
.GettextCB
.GetValue() 
1285         frame
.GeneratePython(self
.dataFile
, pypath
, embed
, genGettext
) 
1289     def OnSaveOpts(self
, evt
=None): 
1290         self
.cfg
.Write("filename", self
.FileNameTC
.GetValue()) 
1291         self
.cfg
.WriteBool("autogenerate", self
.AutoGenerateCB
.GetValue()) 
1292         self
.cfg
.WriteBool("embedResource", self
.EmbedCB
.GetValue()) 
1293         self
.cfg
.WriteBool("makeXRS", self
.MakeXRSFileCB
.GetValue()) 
1294         self
.cfg
.WriteBool("genGettext", self
.GettextCB
.GetValue()) 
1296         self
.EndModal(wx
.ID_OK
) 
1299 ################################################################################ 
1302     print >> sys
.stderr
, 'usage: xrced [-dhiv] [file]' 
1307         if wx
.VERSION
[:3] < MinWxVersion
: 
1309 This version of XRCed may not work correctly on your version of wxWidgets. \ 
1310 Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion
) 
1312         # Process comand-line 
1315             opts
, args 
= getopt
.getopt(sys
.argv
[1:], 'dhiv') 
1323                     print 'XRCed version', version
 
1326         except getopt
.GetoptError
: 
1327             if wx
.Platform 
!= '__WXMAC__': # macs have some extra parameters 
1328                 print >> sys
.stderr
, 'Unknown option' 
1332         self
.SetAppName('xrced') 
1335         conf 
= g
.conf 
= wx
.Config(style 
= wx
.CONFIG_USE_LOCAL_FILE
) 
1336         conf
.localconf 
= None 
1337         conf
.autoRefresh 
= conf
.ReadInt('autorefresh', True) 
1338         pos 
= conf
.ReadInt('x', -1), conf
.ReadInt('y', -1) 
1339         size 
= conf
.ReadInt('width', 800), conf
.ReadInt('height', 600) 
1340         conf
.embedPanel 
= conf
.ReadInt('embedPanel', True) 
1341         conf
.showTools 
= conf
.ReadInt('showTools', True) 
1342         conf
.sashPos 
= conf
.ReadInt('sashPos', 200) 
1343         # read recently used files 
1344         recentfiles
=conf
.Read('recentFiles','') 
1347             for fil 
in recentfiles
.split('|'): 
1348                 conf
.recentfiles
[wx
.NewId()]=fil
 
1349         if not conf
.embedPanel
: 
1350             conf
.panelX 
= conf
.ReadInt('panelX', -1) 
1351             conf
.panelY 
= conf
.ReadInt('panelY', -1) 
1353             conf
.panelX 
= conf
.panelY 
= -1 
1354         conf
.panelWidth 
= conf
.ReadInt('panelWidth', 200) 
1355         conf
.panelHeight 
= conf
.ReadInt('panelHeight', 200) 
1356         conf
.panic 
= not conf
.HasEntry('nopanic') 
1358         wx
.FileSystem
.AddHandler(wx
.MemoryFSHandler()) 
1360         frame 
= Frame(pos
, size
) 
1363         # Load file after showing 
1366             frame
.open = frame
.Open(args
[0]) 
1374         wc
.WriteInt('autorefresh', conf
.autoRefresh
) 
1375         wc
.WriteInt('x', conf
.x
) 
1376         wc
.WriteInt('y', conf
.y
) 
1377         wc
.WriteInt('width', conf
.width
) 
1378         wc
.WriteInt('height', conf
.height
) 
1379         wc
.WriteInt('embedPanel', conf
.embedPanel
) 
1380         wc
.WriteInt('showTools', conf
.showTools
) 
1381         if not conf
.embedPanel
: 
1382             wc
.WriteInt('panelX', conf
.panelX
) 
1383             wc
.WriteInt('panelY', conf
.panelY
) 
1384         wc
.WriteInt('sashPos', conf
.sashPos
) 
1385         wc
.WriteInt('panelWidth', conf
.panelWidth
) 
1386         wc
.WriteInt('panelHeight', conf
.panelHeight
) 
1387         wc
.WriteInt('nopanic', True) 
1388         wc
.Write('recentFiles', '|'.join(conf
.recentfiles
.values()[-5:])) 
1392     app 
= App(0, useBestVisual
=False) 
1393     #app.SetAssertMode(wx.PYAPP_ASSERT_LOG) 
1399 if __name__ 
== '__main__':