4 This sample comes from an IBM developerWorks article at 
   5 http://www-106.ibm.com/developerworks/library/l-wxpy/index.html 
   7 This small program was adapted to demonstrate the current guide lines 
   8 on http://wiki.wxpython.org/index.cgi/wxPython_20Style_20Guide. 
   9 Changes are noted in readme.txt. 
  16 # Process the command line.  Not much to do; 
  17 # just get the name of the project file if it's given. Simple. 
  20     projfile 
= sys
.argv
[1] 
  23 def MsgDlg(window
, string
, caption
='wxProject', style
=wx
.YES_NO|wx
.CANCEL
): 
  24     """Common MessageDialog.""" 
  25     dlg 
= wx
.MessageDialog(window
, string
, caption
, style
) 
  26     result 
= dlg
.ShowModal() 
  31 class main_window(wx
.Frame
): 
  32     """wxProject MainFrame.""" 
  33     def __init__(self
, parent
, title
): 
  34         """Create the wxProject MainFrame.""" 
  35         wx
.Frame
.__init
__(self
, parent
, title
=title
, size
=(500, 500), 
  36                           style
=wx
.DEFAULT_FRAME_STYLE|wx
.NO_FULL_REPAINT_ON_RESIZE
) 
  39         # Set up menu bar for the program. 
  40         self
.mainmenu 
= wx
.MenuBar()                  # Create menu bar. 
  42         # Make the 'Project' menu. 
  45         item 
= menu
.Append(wx
.ID_OPEN
, '&Open', 'Open project')  # Append a new menu 
  46         self
.Bind(wx
.EVT_MENU
, self
.OnProjectOpen
, item
)  # Create and assign a menu event. 
  48         item 
= menu
.Append(wx
.ID_NEW
, '&New', 'New project') 
  49         self
.Bind(wx
.EVT_MENU
, self
.OnProjectNew
, item
) 
  51         item 
= menu
.Append(wx
.ID_EXIT
, 'E&xit', 'Exit program') 
  52         self
.Bind(wx
.EVT_MENU
, self
.OnProjectExit
, item
) 
  54         self
.mainmenu
.Append(menu
, '&Project')  # Add the project menu to the menu bar. 
  56         # Make the 'File' menu. 
  59         item 
= menu
.Append(wx
.ID_ANY
, '&Add', 'Add file to project') 
  60         self
.Bind(wx
.EVT_MENU
, self
.OnFileAdd
, item
) 
  62         item 
= menu
.Append(wx
.ID_ANY
, '&Remove', 'Remove file from project') 
  63         self
.Bind(wx
.EVT_MENU
, self
.OnFileRemove
, item
) 
  65         item 
= menu
.Append(wx
.ID_ANY
, '&Open', 'Open file for editing') 
  66         self
.Bind(wx
.EVT_MENU
, self
.OnFileOpen
, item
) 
  68         item 
= menu
.Append(wx
.ID_ANY
, '&Save', 'Save file') 
  69         self
.Bind(wx
.EVT_MENU
, self
.OnFileSave
, item
) 
  71         self
.mainmenu
.Append(menu
, '&File') # Add the file menu to the menu bar. 
  73         # Attach the menu bar to the window. 
  74         self
.SetMenuBar(self
.mainmenu
) 
  76         # Create the splitter window. 
  77         splitter 
= wx
.SplitterWindow(self
, style
=wx
.NO_3D|wx
.SP_3D
) 
  78         splitter
.SetMinimumPaneSize(1) 
  80         # Create the tree on the left. 
  81         self
.tree 
= wx
.TreeCtrl(splitter
, style
=wx
.TR_DEFAULT_STYLE
) 
  82         self
.tree
.Bind(wx
.EVT_TREE_BEGIN_LABEL_EDIT
, self
.OnTreeLabelEdit
) 
  83         self
.tree
.Bind(wx
.EVT_TREE_END_LABEL_EDIT
, self
.OnTreeLabelEditEnd
) 
  84         self
.tree
.Bind(wx
.EVT_TREE_ITEM_ACTIVATED
, self
.OnTreeItemActivated
) 
  86         # Create the editor on the right. 
  87         self
.editor 
= wx
.TextCtrl(splitter
, style
=wx
.TE_MULTILINE
) 
  90         # Install the tree and the editor. 
  91         splitter
.SplitVertically(self
.tree
, self
.editor
) 
  92         splitter
.SetSashPosition(180, True) 
  94         # Some global state variables. 
  95         self
.projectdirty 
= False 
  99         self
.Bind(wx
.EVT_CLOSE
, self
.OnProjectExit
) 
 103     # ---------------------------------------------------------------------------------------- 
 104     # Some nice little handlers. 
 105     # ---------------------------------------------------------------------------------------- 
 107     def project_open(self
, project_file
): 
 108         """Open and process a wxProject file.""" 
 110             input = open(project_file
, 'r') 
 111             self
.tree
.DeleteAllItems() 
 113             self
.project_file 
= project_file
 
 114             name 
= input.readline().replace ('\n', '') 
 117             # create the file elements in the tree control. 
 118             self
.root 
= self
.tree
.AddRoot(name
) 
 119             self
.activeitem 
= self
.root
 
 120             for line 
in input.readlines(): 
 121                 self
.tree
.AppendItem(self
.root
, line
.replace ('\n', '')) 
 123             self
.tree
.Expand(self
.root
) 
 126             self
.editor
.Enable(False) 
 128             self
.projectdirty 
= False 
 132     def project_save(self
): 
 133         """Save a wxProject file.""" 
 135             output 
= open(self
.project_file
, 'w+') 
 136             output
.write(self
.tree
.GetItemText(self
.root
) + '\n') 
 137             count 
= self
.tree
.GetChildrenCount(self
.root
)  # collect all file (tree) items. 
 140             for i 
in range(count
): 
 142                   child
, cookie 
= self
.tree
.GetFirstChild(self
.root
) 
 144                   child
, cookie 
= self
.tree
.GetNextChild(self
.root
, cookie
) 
 145                output
.write(self
.tree
.GetItemText(child
) + '\n') 
 147             self
.projectdirty 
= False 
 149             MsgDlg(self
, 'There was an error saving the new project file.', 'Error!', wx
.OK
) 
 151     def CheckProjectDirty(self
): 
 152         """Were the current project changed? If so, save it before.""" 
 154         if self
.projectdirty
: 
 155             # save the current project file first. 
 156             result 
= MsgDlg(self
, 'The project has been changed.  Save?') 
 157             if result 
== wx
.ID_YES
: 
 159             if result 
== wx
.ID_CANCEL
: 
 163     def CheckTreeRootItem(self
): 
 164         """Is there any root item?""" 
 166             MsgDlg(self
, 'Please create or open a project before.', 'Error!', wx
.OK
) 
 170     # ---------------------------------------------------------------------------------------- 
 171     # Event handlers from here on out. 
 172     # ---------------------------------------------------------------------------------------- 
 174     def OnProjectOpen(self
, event
): 
 175         """Open a wxProject file.""" 
 176         open_it 
= self
.CheckProjectDirty() 
 178             dlg 
= wx
.FileDialog(self
, 'Choose a project to open', '.', '', '*.wxp', wx
.OPEN
) 
 179             if dlg
.ShowModal() == wx
.ID_OK
: 
 180                 self
.project_open(dlg
.GetPath()) 
 183     def OnProjectNew(self
, event
): 
 184         """Create a new wxProject.""" 
 185         open_it 
= self
.CheckProjectDirty() 
 187             dlg 
= wx
.TextEntryDialog(self
, 'Name for new project:', 'New Project', 
 188                                      'New project', wx
.OK|wx
.CANCEL
) 
 189             if dlg
.ShowModal() == wx
.ID_OK
: 
 190                 newproj 
= dlg
.GetValue() 
 192                 dlg 
= wx
.FileDialog(self
, 'Place to store new project.', '.', '', '*.wxp', wx
.SAVE
) 
 193                 if dlg
.ShowModal() == wx
.ID_OK
: 
 195                         # save the project file. 
 196                         proj 
= open(dlg
.GetPath(), 'w') 
 197                         proj
.write(newproj 
+ '\n') 
 199                         self
.project_open(dlg
.GetPath()) 
 201                         MsgDlg(self
, 'There was an error saving the new project file.', 'Error!', wx
.OK
) 
 204     def SaveCurrentFile(self
): 
 205         """Check and save current file.""" 
 208             if self
.activeitem 
!= self
.root
: 
 209                 if self
.editor
.IsModified():  # Save modified file before 
 210                     result 
= MsgDlg(self
, 'The edited file has changed.  Save it?') 
 211                     if result 
== wx
.ID_YES
: 
 212                         self
.editor
.SaveFile(self
.tree
.GetItemText(self
.activeitem
)) 
 213                     if result 
== wx
.ID_CANCEL
: 
 216                     self
.tree
.SetItemBold(self
.activeitem
, 0) 
 219     def OnProjectExit(self
, event
): 
 220         """Quit the program.""" 
 223             if not self
.SaveCurrentFile(): 
 225             if self
.projectdirty 
and self
.close
: 
 226                 result 
= MsgDlg(self
, 'The project has been changed.  Save?') 
 227                 if result 
== wx
.ID_YES
: 
 229                 if result 
== wx
.ID_CANCEL
: 
 236     def OnFileAdd(self
, event
): 
 237         """Adds a file to the current project.""" 
 238         if not self
.CheckTreeRootItem(): 
 241         dlg 
= wx
.FileDialog(self
, 'Choose a file to add.', '.', '', '*.*', wx
.OPEN
) 
 242         if dlg
.ShowModal() == wx
.ID_OK
: 
 243             path 
= os
.path
.split(dlg
.GetPath()) 
 244             self
.tree
.AppendItem(self
.root
, path
[1]) 
 245             self
.tree
.Expand(self
.root
) 
 248     def OnFileRemove(self
, event
): 
 249         """Removes a file to the current project.""" 
 250         if not self
.CheckTreeRootItem(): 
 252         item 
= self
.tree
.GetSelection() 
 253         if item 
!= self
.root
: 
 254             self
.tree
.Delete(item
) 
 257     def OnFileOpen(self
, event
): 
 258         """Opens current selected file.""" 
 260             item 
= self
.tree
.GetSelection() 
 261             if item 
!= self
.root
: 
 262                 self
.OnTreeItemActivated(None, item
) 
 264         MsgDlg(self
, 'There is no file to load.', 'Error!', wx
.OK
) 
 266     def OnFileSave(self
, event
): 
 267         """Saves current selected file.""" 
 269             if self
.activeitem 
!= self
.root
: 
 270                 self
.editor
.SaveFile(self
.tree
.GetItemText(self
.activeitem
)) 
 272         MsgDlg(self
, 'There is no file to save.', 'Error!', wx
.OK
) 
 275     def OnTreeLabelEdit(self
, event
): 
 276         """Edit tree label (only root label can be edited).""" 
 277         item 
= event
.GetItem() 
 278         if item 
!= self
.root
: 
 281     def OnTreeLabelEditEnd(self
, event
): 
 282         """End editing the tree label.""" 
 283         self
.projectdirty 
= True 
 286     def OnTreeItemActivated(self
, event
, item
=None): 
 287         """Tree item was activated: try to open this file.""" 
 288         go_ahead 
= self
.SaveCurrentFile() 
 292                 item 
= event
.GetItem() 
 293             self
.activeitem 
= item
 
 294             if item 
!= self
.root
: 
 295                 # load the current selected file 
 296                 self
.tree
.SetItemBold(item
, 1) 
 297                 self
.editor
.Enable(1) 
 298                 self
.editor
.LoadFile(self
.tree
.GetItemText(item
)) 
 299                 self
.editor
.SetInsertionPoint(0) 
 300                 self
.editor
.SetFocus() 
 303                 self
.editor
.Enable(0) 
 307     """wxProject Application.""" 
 309         """Create the wxProject Application.""" 
 310         frame 
= main_window(None, 'wxProject - ' + projfile
) 
 311         if projfile 
!= 'Unnamed': 
 312             frame
.project_open(projfile
) 
 316 if __name__ 
== '__main__':