| 1 | #!/bin/python |
| 2 | import sys, os |
| 3 | from wxPython.wx import * |
| 4 | from string import * |
| 5 | |
| 6 | # Process the command line. Not much to do; |
| 7 | # just get the name of the project file if it's given. Simple. |
| 8 | projfile = 'Unnamed' |
| 9 | if len(sys.argv) > 1: |
| 10 | projfile = sys.argv[1] |
| 11 | |
| 12 | |
| 13 | def MsgBox (window, string): |
| 14 | dlg=wxMessageDialog(window, string, 'wxProject', wxOK) |
| 15 | dlg.ShowModal() |
| 16 | dlg.Destroy() |
| 17 | |
| 18 | class main_window(wxFrame): |
| 19 | def __init__(self, parent, id, title): |
| 20 | wxFrame.__init__(self, parent, -1, title, size = (500, 500), |
| 21 | style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE) |
| 22 | |
| 23 | |
| 24 | # ------------------------------------------------------------------------------------ |
| 25 | # Set up menu bar for the program. |
| 26 | # ------------------------------------------------------------------------------------ |
| 27 | self.mainmenu = wxMenuBar() # Create menu bar. |
| 28 | mainwindow = self |
| 29 | |
| 30 | menu=wxMenu() # Make a menu (will be the Project menu) |
| 31 | |
| 32 | exitID=wxNewId() # Make a new ID for a menu entry. |
| 33 | menu.Append(exitID, '&Open', 'Open project') # Name the ID by adding it to the menu. |
| 34 | EVT_MENU(self, exitID, self.OnProjectOpen) # Create and assign a menu event. |
| 35 | exitID=wxNewId() |
| 36 | menu.Append(exitID, '&New', 'New project') |
| 37 | EVT_MENU(self, exitID, self.OnProjectNew) |
| 38 | exitID=wxNewId() |
| 39 | menu.Append(exitID, 'E&xit', 'Exit program') |
| 40 | EVT_MENU(self, exitID, self.OnProjectExit) |
| 41 | |
| 42 | self.mainmenu.Append (menu, '&Project') # Add the project menu to the menu bar. |
| 43 | |
| 44 | |
| 45 | menu=wxMenu() # Make a menu (will be the File menu) |
| 46 | |
| 47 | exitID=wxNewId() |
| 48 | menu.Append(exitID, '&Add', 'Add file to project') |
| 49 | EVT_MENU(self, exitID, self.OnFileAdd) |
| 50 | exitID=wxNewId() |
| 51 | menu.Append(exitID, '&Remove', 'Remove file from project') |
| 52 | EVT_MENU(self, exitID, self.OnFileRemove) |
| 53 | exitID=wxNewId() |
| 54 | menu.Append(exitID, '&Open', 'Open file for editing') |
| 55 | EVT_MENU(self, exitID, self.OnFileOpen) |
| 56 | exitID=wxNewId() |
| 57 | menu.Append(exitID, '&Save', 'Save file') |
| 58 | EVT_MENU(self, exitID, self.OnFileSave) |
| 59 | |
| 60 | self.mainmenu.Append (menu, '&File') # Add the file menu to the menu bar. |
| 61 | |
| 62 | self.SetMenuBar (self.mainmenu) # Attach the menu bar to the window. |
| 63 | |
| 64 | |
| 65 | # ------------------------------------------------------------------------------------ |
| 66 | # Create the splitter window. |
| 67 | # ------------------------------------------------------------------------------------ |
| 68 | splitter = wxSplitterWindow (self, -1, style=wxNO_3D|wxSP_3D) |
| 69 | splitter.SetMinimumPaneSize (1) |
| 70 | |
| 71 | # ------------------------------------------------------------------------------------ |
| 72 | # Create the tree on the left. |
| 73 | # ------------------------------------------------------------------------------------ |
| 74 | tID = wxNewId() |
| 75 | self.tree = wxTreeCtrl (splitter, tID, style=wxTR_HAS_BUTTONS | |
| 76 | wxTR_EDIT_LABELS | |
| 77 | wxTR_HAS_VARIABLE_ROW_HEIGHT) |
| 78 | EVT_TREE_BEGIN_LABEL_EDIT(self.tree, tID, self.OnTreeLabelEdit) |
| 79 | EVT_TREE_END_LABEL_EDIT(self.tree, tID, self.OnTreeLabelEditEnd) |
| 80 | EVT_TREE_ITEM_ACTIVATED(self.tree, tID, self.OnTreeItemActivated) |
| 81 | |
| 82 | # ------------------------------------------------------------------------------------ |
| 83 | # Create the editor on the right. |
| 84 | # ------------------------------------------------------------------------------------ |
| 85 | self.editor = wxTextCtrl(splitter, -1, style=wxTE_MULTILINE) |
| 86 | self.editor.Enable (0) |
| 87 | |
| 88 | # ------------------------------------------------------------------------------------ |
| 89 | # Install the tree and the editor. |
| 90 | # ------------------------------------------------------------------------------------ |
| 91 | splitter.SplitVertically (self.tree, self.editor) |
| 92 | splitter.SetSashPosition (180, True) |
| 93 | |
| 94 | self.Show(True) |
| 95 | |
| 96 | # Some global state variables. |
| 97 | self.projectdirty = False |
| 98 | |
| 99 | # ---------------------------------------------------------------------------------------- |
| 100 | # Some nice little handlers. |
| 101 | # ---------------------------------------------------------------------------------------- |
| 102 | |
| 103 | |
| 104 | def project_open(self, project_file): |
| 105 | try: |
| 106 | input = open (project_file, 'r') |
| 107 | |
| 108 | self.tree.DeleteAllItems() |
| 109 | |
| 110 | self.project_file = project_file |
| 111 | name = replace (input.readline(), "\n", "") |
| 112 | self.SetTitle (name) |
| 113 | self.root = self.tree.AddRoot(name) |
| 114 | self.activeitem = self.root |
| 115 | for line in input.readlines(): |
| 116 | self.tree.AppendItem (self.root, replace(line, "\n", "")) |
| 117 | input.close |
| 118 | self.tree.Expand (self.root) |
| 119 | |
| 120 | self.editor.Clear() |
| 121 | self.editor.Enable (False) |
| 122 | |
| 123 | self.projectdirty = False |
| 124 | except IOError: |
| 125 | pass |
| 126 | |
| 127 | def project_save(self): |
| 128 | try: |
| 129 | output = open (self.project_file, 'w+') |
| 130 | output.write (self.tree.GetItemText (self.root) + "\n") |
| 131 | |
| 132 | count = self.tree.GetChildrenCount (self.root) |
| 133 | iter = 0 |
| 134 | child = '' |
| 135 | for i in range(count): |
| 136 | if i == 0: |
| 137 | (child,iter) = self.tree.GetFirstChild(self.root,iter) |
| 138 | else: |
| 139 | (child,iter) = self.tree.GetNextChild(self.root,iter) |
| 140 | output.write (self.tree.GetItemText(child) + "\n") |
| 141 | output.close() |
| 142 | self.projectdirty = False |
| 143 | except IOError: |
| 144 | dlg_m = wxMessageDialog (self, 'There was an error saving the project file.', |
| 145 | 'Error!', wxOK) |
| 146 | dlg_m.ShowModal() |
| 147 | dlg_m.Destroy() |
| 148 | |
| 149 | # ---------------------------------------------------------------------------------------- |
| 150 | # Event handlers from here on out. |
| 151 | # ---------------------------------------------------------------------------------------- |
| 152 | |
| 153 | def OnProjectOpen(self, event): |
| 154 | open_it = True |
| 155 | if self.projectdirty: |
| 156 | dlg=wxMessageDialog(self, 'The project has been changed. Save?', 'wxProject', |
| 157 | wxYES_NO | wxCANCEL) |
| 158 | result = dlg.ShowModal() |
| 159 | if result == wxID_YES: |
| 160 | self.project_save() |
| 161 | if result == wxID_CANCEL: |
| 162 | open_it = False |
| 163 | dlg.Destroy() |
| 164 | if open_it: |
| 165 | dlg = wxFileDialog(self, "Choose a project to open", ".", "", "*.wxp", wxOPEN) |
| 166 | if dlg.ShowModal() == wxID_OK: |
| 167 | self.project_open(dlg.GetPath()) |
| 168 | dlg.Destroy() |
| 169 | |
| 170 | def OnProjectNew(self, event): |
| 171 | open_it = True |
| 172 | if self.projectdirty: |
| 173 | dlg=wxMessageDialog(self, 'The project has been changed. Save?', 'wxProject', |
| 174 | wxYES_NO | wxCANCEL) |
| 175 | result = dlg.ShowModal() |
| 176 | if result == wxID_YES: |
| 177 | self.project_save() |
| 178 | if result == wxID_CANCEL: |
| 179 | open_it = False |
| 180 | dlg.Destroy() |
| 181 | |
| 182 | if open_it: |
| 183 | dlg = wxTextEntryDialog (self, "Name for new project:", "New Project", |
| 184 | "New project", wxOK | wxCANCEL) |
| 185 | if dlg.ShowModal() == wxID_OK: |
| 186 | newproj = dlg.GetValue() |
| 187 | dlg.Destroy() |
| 188 | dlg = wxFileDialog (self, "Place to store new project", ".", "", "*.wxp", |
| 189 | wxSAVE) |
| 190 | if dlg.ShowModal() == wxID_OK: |
| 191 | try: |
| 192 | proj = open (dlg.GetPath(), 'w') |
| 193 | proj.write (newproj + "\n") |
| 194 | proj.close() |
| 195 | self.project_open (dlg.GetPath()) |
| 196 | except IOError: |
| 197 | dlg_m = wxMessageDialog (self, |
| 198 | 'There was an error saving the new project file.', |
| 199 | 'Error!', wxOK) |
| 200 | dlg_m.ShowModal() |
| 201 | dlg_m.Destroy() |
| 202 | dlg.Destroy() |
| 203 | |
| 204 | def OnProjectExit(self, event): |
| 205 | close = True |
| 206 | if self.projectdirty: |
| 207 | dlg=wxMessageDialog(self, 'The project has been changed. Save?', 'wxProject', |
| 208 | wxYES_NO | wxCANCEL) |
| 209 | result = dlg.ShowModal() |
| 210 | if result == wxID_YES: |
| 211 | self.project_save() |
| 212 | if result == wxID_CANCEL: |
| 213 | close = False |
| 214 | dlg.Destroy() |
| 215 | if close: |
| 216 | self.Close() |
| 217 | |
| 218 | def OnFileAdd(self, event): |
| 219 | dlg = wxFileDialog (self, "Choose a file to add", ".", "", "*.*", wxOPEN) |
| 220 | if dlg.ShowModal() == wxID_OK: |
| 221 | path = os.path.split(dlg.GetPath()) |
| 222 | self.tree.AppendItem (self.root, path[1]) |
| 223 | self.tree.Expand (self.root) |
| 224 | self.project_save() |
| 225 | |
| 226 | def OnFileRemove(self, event): |
| 227 | item = self.tree.GetSelection() |
| 228 | if item != self.root: |
| 229 | self.tree.Delete (item) |
| 230 | self.project_save() |
| 231 | |
| 232 | def OnFileOpen(self, event): |
| 233 | item = self.tree.GetSelection() |
| 234 | |
| 235 | def OnFileSave(self, event): |
| 236 | if self.activeitem != self.root: |
| 237 | self.editor.SaveFile (self.tree.GetItemText (self.activeitem)) |
| 238 | |
| 239 | |
| 240 | def OnTreeLabelEdit(self, event): |
| 241 | item=event.GetItem() |
| 242 | if item != self.root: |
| 243 | event.Veto() |
| 244 | |
| 245 | def OnTreeLabelEditEnd(self, event): |
| 246 | self.projectdirty = True |
| 247 | |
| 248 | def OnTreeItemActivated(self, event): |
| 249 | go_ahead = True |
| 250 | if self.activeitem != self.root: |
| 251 | if self.editor.IsModified(): |
| 252 | dlg=wxMessageDialog(self, 'The edited file has changed. Save it?', |
| 253 | 'wxProject', wxYES_NO | wxCANCEL) |
| 254 | result = dlg.ShowModal() |
| 255 | if result == wxID_YES: |
| 256 | self.editor.SaveFile (self.tree.GetItemText (self.activeitem)) |
| 257 | if result == wxID_CANCEL: |
| 258 | go_ahead = False |
| 259 | dlg.Destroy() |
| 260 | if go_ahead: |
| 261 | self.tree.SetItemBold (self.activeitem, 0) |
| 262 | |
| 263 | if go_ahead: |
| 264 | item=event.GetItem() |
| 265 | self.activeitem = item |
| 266 | if item != self.root: |
| 267 | self.tree.SetItemBold (item, 1) |
| 268 | self.editor.Enable (1) |
| 269 | self.editor.LoadFile (self.tree.GetItemText(item)) |
| 270 | self.editor.SetInsertionPoint (0) |
| 271 | self.editor.SetFocus() |
| 272 | else: |
| 273 | self.editor.Clear() |
| 274 | self.editor.Enable (0) |
| 275 | |
| 276 | class App(wxApp): |
| 277 | def OnInit(self): |
| 278 | frame = main_window(None, -1, "wxProject - " + projfile) |
| 279 | self.SetTopWindow(frame) |
| 280 | if (projfile != 'Unnamed'): |
| 281 | frame.project_open (projfile) |
| 282 | return True |
| 283 | |
| 284 | app = App(0) |
| 285 | app.MainLoop() |
| 286 | |