7153b2cb86
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37421 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
319 lines
11 KiB
Python
319 lines
11 KiB
Python
#!/usr/bin/env python
|
|
|
|
"""
|
|
This sample comes from an IBM developerWorks article at
|
|
http://www-106.ibm.com/developerworks/library/l-wxpy/index.html
|
|
|
|
This small program was adapted to demonstrate the current guide lines
|
|
on http://wiki.wxpython.org/index.cgi/wxPython_20Style_20Guide.
|
|
Changes are noted in readme.txt.
|
|
"""
|
|
|
|
import sys, os
|
|
import wx
|
|
|
|
|
|
# Process the command line. Not much to do;
|
|
# just get the name of the project file if it's given. Simple.
|
|
projfile = 'Unnamed'
|
|
if len(sys.argv) > 1:
|
|
projfile = sys.argv[1]
|
|
|
|
|
|
def MsgDlg(window, string, caption='wxProject', style=wx.YES_NO|wx.CANCEL):
|
|
"""Common MessageDialog."""
|
|
dlg = wx.MessageDialog(window, string, caption, style)
|
|
result = dlg.ShowModal()
|
|
dlg.Destroy()
|
|
return result
|
|
|
|
|
|
class main_window(wx.Frame):
|
|
"""wxProject MainFrame."""
|
|
def __init__(self, parent, title):
|
|
"""Create the wxProject MainFrame."""
|
|
wx.Frame.__init__(self, parent, title=title, size=(500, 500),
|
|
style=wx.DEFAULT_FRAME_STYLE|wx.NO_FULL_REPAINT_ON_RESIZE)
|
|
|
|
|
|
# Set up menu bar for the program.
|
|
self.mainmenu = wx.MenuBar() # Create menu bar.
|
|
|
|
# Make the 'Project' menu.
|
|
menu = wx.Menu()
|
|
|
|
item = menu.Append(wx.ID_OPEN, '&Open', 'Open project') # Append a new menu
|
|
self.Bind(wx.EVT_MENU, self.OnProjectOpen, item) # Create and assign a menu event.
|
|
|
|
item = menu.Append(wx.ID_NEW, '&New', 'New project')
|
|
self.Bind(wx.EVT_MENU, self.OnProjectNew, item)
|
|
|
|
item = menu.Append(wx.ID_EXIT, 'E&xit', 'Exit program')
|
|
self.Bind(wx.EVT_MENU, self.OnProjectExit, item)
|
|
|
|
self.mainmenu.Append(menu, '&Project') # Add the project menu to the menu bar.
|
|
|
|
# Make the 'File' menu.
|
|
menu = wx.Menu()
|
|
|
|
item = menu.Append(wx.ID_ANY, '&Add', 'Add file to project')
|
|
self.Bind(wx.EVT_MENU, self.OnFileAdd, item)
|
|
|
|
item = menu.Append(wx.ID_ANY, '&Remove', 'Remove file from project')
|
|
self.Bind(wx.EVT_MENU, self.OnFileRemove, item)
|
|
|
|
item = menu.Append(wx.ID_ANY, '&Open', 'Open file for editing')
|
|
self.Bind(wx.EVT_MENU, self.OnFileOpen, item)
|
|
|
|
item = menu.Append(wx.ID_ANY, '&Save', 'Save file')
|
|
self.Bind(wx.EVT_MENU, self.OnFileSave, item)
|
|
|
|
self.mainmenu.Append(menu, '&File') # Add the file menu to the menu bar.
|
|
|
|
# Attach the menu bar to the window.
|
|
self.SetMenuBar(self.mainmenu)
|
|
|
|
# Create the splitter window.
|
|
splitter = wx.SplitterWindow(self, style=wx.NO_3D|wx.SP_3D)
|
|
splitter.SetMinimumPaneSize(1)
|
|
|
|
# Create the tree on the left.
|
|
self.tree = wx.TreeCtrl(splitter, style=wx.TR_DEFAULT_STYLE)
|
|
self.tree.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnTreeLabelEdit)
|
|
self.tree.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnTreeLabelEditEnd)
|
|
self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnTreeItemActivated)
|
|
|
|
# Create the editor on the right.
|
|
self.editor = wx.TextCtrl(splitter, style=wx.TE_MULTILINE)
|
|
self.editor.Enable(0)
|
|
|
|
# Install the tree and the editor.
|
|
splitter.SplitVertically(self.tree, self.editor)
|
|
splitter.SetSashPosition(180, True)
|
|
|
|
# Some global state variables.
|
|
self.projectdirty = False
|
|
self.root = None
|
|
self.close = False
|
|
|
|
self.Bind(wx.EVT_CLOSE, self.OnProjectExit)
|
|
|
|
self.Show(True)
|
|
|
|
# ----------------------------------------------------------------------------------------
|
|
# Some nice little handlers.
|
|
# ----------------------------------------------------------------------------------------
|
|
|
|
def project_open(self, project_file):
|
|
"""Open and process a wxProject file."""
|
|
try:
|
|
input = open(project_file, 'r')
|
|
self.tree.DeleteAllItems()
|
|
|
|
self.project_file = project_file
|
|
name = input.readline().replace ('\n', '')
|
|
self.SetTitle(name)
|
|
|
|
# create the file elements in the tree control.
|
|
self.root = self.tree.AddRoot(name)
|
|
self.activeitem = self.root
|
|
for line in input.readlines():
|
|
self.tree.AppendItem(self.root, line.replace ('\n', ''))
|
|
input.close()
|
|
self.tree.Expand(self.root)
|
|
|
|
self.editor.Clear()
|
|
self.editor.Enable(False)
|
|
|
|
self.projectdirty = False
|
|
except IOError:
|
|
pass
|
|
|
|
def project_save(self):
|
|
"""Save a wxProject file."""
|
|
try:
|
|
output = open(self.project_file, 'w+')
|
|
output.write(self.tree.GetItemText(self.root) + '\n')
|
|
count = self.tree.GetChildrenCount(self.root) # collect all file (tree) items.
|
|
iter = 0
|
|
child = ''
|
|
for i in range(count):
|
|
if i == 0:
|
|
child, cookie = self.tree.GetFirstChild(self.root)
|
|
else:
|
|
child, cookie = self.tree.GetNextChild(self.root, cookie)
|
|
output.write(self.tree.GetItemText(child) + '\n')
|
|
output.close()
|
|
self.projectdirty = False
|
|
except IOError:
|
|
MsgDlg(self, 'There was an error saving the new project file.', 'Error!', wx.OK)
|
|
|
|
def CheckProjectDirty(self):
|
|
"""Were the current project changed? If so, save it before."""
|
|
open_it = True
|
|
if self.projectdirty:
|
|
# save the current project file first.
|
|
result = MsgDlg(self, 'The project has been changed. Save?')
|
|
if result == wx.ID_YES:
|
|
self.project_save()
|
|
if result == wx.ID_CANCEL:
|
|
open_it = False
|
|
return open_it
|
|
|
|
def CheckTreeRootItem(self):
|
|
"""Is there any root item?"""
|
|
if not self.root:
|
|
MsgDlg(self, 'Please create or open a project before.', 'Error!', wx.OK)
|
|
return False
|
|
return True
|
|
|
|
# ----------------------------------------------------------------------------------------
|
|
# Event handlers from here on out.
|
|
# ----------------------------------------------------------------------------------------
|
|
|
|
def OnProjectOpen(self, event):
|
|
"""Open a wxProject file."""
|
|
open_it = self.CheckProjectDirty()
|
|
if open_it:
|
|
dlg = wx.FileDialog(self, 'Choose a project to open', '.', '', '*.wxp', wx.OPEN)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
self.project_open(dlg.GetPath())
|
|
dlg.Destroy()
|
|
|
|
def OnProjectNew(self, event):
|
|
"""Create a new wxProject."""
|
|
open_it = self.CheckProjectDirty()
|
|
if open_it:
|
|
dlg = wx.TextEntryDialog(self, 'Name for new project:', 'New Project',
|
|
'New project', wx.OK|wx.CANCEL)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
newproj = dlg.GetValue()
|
|
dlg.Destroy()
|
|
dlg = wx.FileDialog(self, 'Place to store new project.', '.', '', '*.wxp', wx.SAVE)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
try:
|
|
# save the project file.
|
|
proj = open(dlg.GetPath(), 'w')
|
|
proj.write(newproj + '\n')
|
|
proj.close()
|
|
self.project_open(dlg.GetPath())
|
|
except IOError:
|
|
MsgDlg(self, 'There was an error saving the new project file.', 'Error!', wx.OK)
|
|
dlg.Destroy()
|
|
|
|
def SaveCurrentFile(self):
|
|
"""Check and save current file."""
|
|
go_ahead = True
|
|
if self.root:
|
|
if self.activeitem != self.root:
|
|
if self.editor.IsModified(): # Save modified file before
|
|
result = MsgDlg(self, 'The edited file has changed. Save it?')
|
|
if result == wx.ID_YES:
|
|
self.editor.SaveFile(self.tree.GetItemText(self.activeitem))
|
|
if result == wx.ID_CANCEL:
|
|
go_ahead = False
|
|
if go_ahead:
|
|
self.tree.SetItemBold(self.activeitem, 0)
|
|
return go_ahead
|
|
|
|
def OnProjectExit(self, event):
|
|
"""Quit the program."""
|
|
if not self.close:
|
|
self.close = True
|
|
if not self.SaveCurrentFile():
|
|
self.close = False
|
|
if self.projectdirty and self.close:
|
|
result = MsgDlg(self, 'The project has been changed. Save?')
|
|
if result == wx.ID_YES:
|
|
self.project_save()
|
|
if result == wx.ID_CANCEL:
|
|
self.close = False
|
|
if self.close:
|
|
self.Close()
|
|
else:
|
|
event.Skip()
|
|
|
|
def OnFileAdd(self, event):
|
|
"""Adds a file to the current project."""
|
|
if not self.CheckTreeRootItem():
|
|
return
|
|
|
|
dlg = wx.FileDialog(self, 'Choose a file to add.', '.', '', '*.*', wx.OPEN)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
path = os.path.split(dlg.GetPath())
|
|
self.tree.AppendItem(self.root, path[1])
|
|
self.tree.Expand(self.root)
|
|
self.project_save()
|
|
|
|
def OnFileRemove(self, event):
|
|
"""Removes a file to the current project."""
|
|
if not self.CheckTreeRootItem():
|
|
return
|
|
item = self.tree.GetSelection()
|
|
if item != self.root:
|
|
self.tree.Delete(item)
|
|
self.project_save()
|
|
|
|
def OnFileOpen(self, event):
|
|
"""Opens current selected file."""
|
|
if self.root:
|
|
item = self.tree.GetSelection()
|
|
if item != self.root:
|
|
self.OnTreeItemActivated(None, item)
|
|
return
|
|
MsgDlg(self, 'There is no file to load.', 'Error!', wx.OK)
|
|
|
|
def OnFileSave(self, event):
|
|
"""Saves current selected file."""
|
|
if self.root:
|
|
if self.activeitem != self.root:
|
|
self.editor.SaveFile(self.tree.GetItemText(self.activeitem))
|
|
return
|
|
MsgDlg(self, 'There is no file to save.', 'Error!', wx.OK)
|
|
|
|
|
|
def OnTreeLabelEdit(self, event):
|
|
"""Edit tree label (only root label can be edited)."""
|
|
item = event.GetItem()
|
|
if item != self.root:
|
|
event.Veto()
|
|
|
|
def OnTreeLabelEditEnd(self, event):
|
|
"""End editing the tree label."""
|
|
self.projectdirty = True
|
|
|
|
|
|
def OnTreeItemActivated(self, event, item=None):
|
|
"""Tree item was activated: try to open this file."""
|
|
go_ahead = self.SaveCurrentFile()
|
|
|
|
if go_ahead:
|
|
if event:
|
|
item = event.GetItem()
|
|
self.activeitem = item
|
|
if item != self.root:
|
|
# load the current selected file
|
|
self.tree.SetItemBold(item, 1)
|
|
self.editor.Enable(1)
|
|
self.editor.LoadFile(self.tree.GetItemText(item))
|
|
self.editor.SetInsertionPoint(0)
|
|
self.editor.SetFocus()
|
|
else:
|
|
self.editor.Clear()
|
|
self.editor.Enable(0)
|
|
|
|
|
|
class App(wx.App):
|
|
"""wxProject Application."""
|
|
def OnInit(self):
|
|
"""Create the wxProject Application."""
|
|
frame = main_window(None, 'wxProject - ' + projfile)
|
|
if projfile != 'Unnamed':
|
|
frame.project_open(projfile)
|
|
return True
|
|
|
|
|
|
if __name__ == '__main__':
|
|
app = App(0)
|
|
app.MainLoop()
|