From b792147db7e5ceb5da741f5f6e27fea79944a04c Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Thu, 5 May 2005 00:10:29 +0000 Subject: [PATCH] More updates from Morgan Hua git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33956 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- .../ide/activegrid/tool/AbstractEditor.py | 51 +- .../samples/ide/activegrid/tool/CodeEditor.py | 109 +-- .../ide/activegrid/tool/DebuggerService.py | 74 +- .../ide/activegrid/tool/FindInDirService.py | 6 +- .../ide/activegrid/tool/FindService.py | 22 +- wxPython/samples/ide/activegrid/tool/IDE.py | 5 + .../ide/activegrid/tool/ImageEditor.py | 11 + .../ide/activegrid/tool/OutlineService.py | 7 +- .../ide/activegrid/tool/ProjectEditor.py | 719 +++++++++++++----- .../ide/activegrid/tool/STCTextEditor.py | 71 +- .../samples/ide/activegrid/tool/UICommon.py | 1 + .../samples/ide/activegrid/tool/checker.py | 15 +- .../samples/ide/activegrid/util/__init__.py | 24 +- wxPython/samples/pydocview/FindService.py | 22 +- wxPython/samples/pydocview/TextEditor.py | 2 +- wxPython/wx/lib/docview.py | 10 +- wxPython/wx/lib/pydocview.py | 18 +- 17 files changed, 745 insertions(+), 422 deletions(-) diff --git a/wxPython/samples/ide/activegrid/tool/AbstractEditor.py b/wxPython/samples/ide/activegrid/tool/AbstractEditor.py index 8bda44696d..1361b422e8 100644 --- a/wxPython/samples/ide/activegrid/tool/AbstractEditor.py +++ b/wxPython/samples/ide/activegrid/tool/AbstractEditor.py @@ -21,6 +21,7 @@ _ = wx.GetTranslation SELECT_BRUSH = wx.Brush("BLUE", wx.SOLID) SHAPE_BRUSH = wx.Brush("WHEAT", wx.SOLID) LINE_BRUSH = wx.BLACK_BRUSH +INACTIVE_SELECT_BRUSH = wx.Brush("LIGHT BLUE", wx.SOLID) def GetRawModel(model): @@ -59,7 +60,7 @@ class CanvasView(wx.lib.docview.View): frame.Layout() self.Activate() return True - + def OnActivateView(self, activate, activeView, deactiveView): if activate and self._canvas: @@ -70,6 +71,17 @@ class CanvasView(wx.lib.docview.View): wx.CallAfter(self._canvas.SetFocus) + def OnFocus(self, event): + self._canvas.SetFocus() + self.FocusColorPropertyShape(True) + event.Skip() + + + def OnKillFocus(self, event): + self.FocusColorPropertyShape(False) + event.Skip() + + def OnClose(self, deleteWindow = True): statusC = wx.GetApp().CloseChildDocuments(self.GetDocument()) statusP = wx.lib.docview.View.OnClose(self, deleteWindow = deleteWindow) @@ -90,6 +102,17 @@ class CanvasView(wx.lib.docview.View): wx.EVT_MOTION(self._canvas, self.OnLeftDrag) wx.EVT_LEFT_DCLICK(self._canvas, self.OnLeftDoubleClick) wx.EVT_KEY_DOWN(self._canvas, self.OnKeyPressed) + + # need this otherwise mouse clicks don't set focus to this view + wx.EVT_LEFT_DOWN(self._canvas, self.OnFocus) + wx.EVT_LEFT_DCLICK(self._canvas, self.OnFocus) + wx.EVT_RIGHT_DOWN(self._canvas, self.OnFocus) + wx.EVT_RIGHT_DCLICK(self._canvas, self.OnFocus) + wx.EVT_MIDDLE_DOWN(self._canvas, self.OnFocus) + wx.EVT_MIDDLE_DCLICK(self._canvas, self.OnFocus) + + wx.EVT_KILL_FOCUS(self._canvas, self.OnKillFocus) + wx.EVT_SET_FOCUS(self._canvas, self.OnFocus) maxWidth = 2000 maxHeight = 16000 @@ -513,6 +536,32 @@ class CanvasView(wx.lib.docview.View): dc.EndDrawing() + def FocusColorPropertyShape(self, gotFocus=False): + # no need to change highlight if no PropertyService is running + propertyService = wx.GetApp().GetService(PropertyService.PropertyService) + if not propertyService: + return + + if not self._propShape: + return + + dc = wx.ClientDC(self._canvas) + self._canvas.PrepareDC(dc) + dc.BeginDrawing() + + # draw deactivated selection + if self._propShape and self._propShape in self._diagram.GetShapeList(): + if gotFocus: + self._propShape.SetBrush(SELECT_BRUSH) + else: + self._propShape.SetBrush(INACTIVE_SELECT_BRUSH) + if (self._propShape._textColourName in ["BLACK", "WHITE"]): # Would use GetTextColour() but it is broken + self._propShape.SetTextColour("WHITE", 0) + self._propShape.Draw(dc) + + dc.EndDrawing() + + #---------------------------------------------------------------------------- # Property Service methods #---------------------------------------------------------------------------- diff --git a/wxPython/samples/ide/activegrid/tool/CodeEditor.py b/wxPython/samples/ide/activegrid/tool/CodeEditor.py index 7acf803359..d8a158a0ee 100644 --- a/wxPython/samples/ide/activegrid/tool/CodeEditor.py +++ b/wxPython/samples/ide/activegrid/tool/CodeEditor.py @@ -117,7 +117,6 @@ class CodeView(STCTextEditor.TextView): def ProcessUpdateUIEvent(self, event): if not self.GetCtrl(): return False - hasText = self.GetCtrl().GetTextLength() > 0 id = event.GetId() if id == EXPAND_TEXT_ID: event.Enable(self.GetCtrl().CanLineExpand(self.GetCtrl().GetCurrentLine())) @@ -125,49 +124,29 @@ class CodeView(STCTextEditor.TextView): elif id == COLLAPSE_TEXT_ID: event.Enable(self.GetCtrl().CanLineCollapse(self.GetCtrl().GetCurrentLine())) return True - elif id == EXPAND_TOP_ID: - event.Enable(hasText) - return True - elif id == COLLAPSE_TOP_ID: - event.Enable(hasText) - return True - elif id == EXPAND_ALL_ID: - event.Enable(hasText) - return True - elif id == COLLAPSE_ALL_ID: - event.Enable(hasText) + elif (id == EXPAND_TOP_ID + or id == COLLAPSE_TOP_ID + or id == EXPAND_ALL_ID + or id == COLLAPSE_ALL_ID + or id == AUTO_COMPLETE_ID + or id == CLEAN_WHITESPACE + or id == INDENT_LINES_ID + or id == DEDENT_LINES_ID + or id == COMMENT_LINES_ID + or id == UNCOMMENT_LINES_ID): + event.Enable(self.GetCtrl().GetTextLength() > 0) return True elif id == CHECK_CODE_ID: event.Enable(False) return True - elif id == AUTO_COMPLETE_ID: - event.Enable(hasText) - return True - elif id == CLEAN_WHITESPACE: - event.Enable(hasText) - return True - elif id == SET_INDENT_WIDTH_ID: + elif (id == SET_INDENT_WIDTH_ID + or id == FOLDING_ID): event.Enable(True) return True elif id == USE_TABS_ID: event.Enable(True) event.Check(self.GetCtrl().GetUseTabs()) return True - elif id == INDENT_LINES_ID: - event.Enable(hasText) - return True - elif id == DEDENT_LINES_ID: - event.Enable(hasText) - return True - elif id == COMMENT_LINES_ID: - event.Enable(hasText) - return True - elif id == UNCOMMENT_LINES_ID: - event.Enable(hasText) - return True - elif id == FOLDING_ID: - event.Enable(True) - return True else: return STCTextEditor.TextView.ProcessUpdateUIEvent(self, event) @@ -625,52 +604,22 @@ class CodeService(STCTextEditor.TextService): def ProcessUpdateUIEvent(self, event): id = event.GetId() - if id == EXPAND_TEXT_ID: - event.Enable(False) - return True - elif id == COLLAPSE_TEXT_ID: - event.Enable(False) - return True - elif id == EXPAND_TOP_ID: - event.Enable(False) - return True - elif id == COLLAPSE_TOP_ID: - event.Enable(False) - return True - elif id == EXPAND_ALL_ID: - event.Enable(False) - return True - elif id == COLLAPSE_ALL_ID: - event.Enable(False) - return True - elif id == CHECK_CODE_ID: - event.Enable(False) - return True - elif id == AUTO_COMPLETE_ID: - event.Enable(False) - return True - elif id == CLEAN_WHITESPACE: - event.Enable(False) - return True - elif id == SET_INDENT_WIDTH_ID: - event.Enable(False) - return True - elif id == USE_TABS_ID: - event.Enable(False) - return True - elif id == INDENT_LINES_ID: - event.Enable(False) - return True - elif id == DEDENT_LINES_ID: - event.Enable(False) - return True - elif id == COMMENT_LINES_ID: - event.Enable(False) - return True - elif id == UNCOMMENT_LINES_ID: - event.Enable(False) - return True - elif id == FOLDING_ID: + if (id == EXPAND_TEXT_ID + or id == COLLAPSE_TEXT_ID + or id == EXPAND_TOP_ID + or id == COLLAPSE_TOP_ID + or id == EXPAND_ALL_ID + or id == COLLAPSE_ALL_ID + or id == CHECK_CODE_ID + or id == AUTO_COMPLETE_ID + or id == CLEAN_WHITESPACE + or id == SET_INDENT_WIDTH_ID + or id == USE_TABS_ID + or id == INDENT_LINES_ID + or id == DEDENT_LINES_ID + or id == COMMENT_LINES_ID + or id == UNCOMMENT_LINES_ID + or id == FOLDING_ID): event.Enable(False) return True else: diff --git a/wxPython/samples/ide/activegrid/tool/DebuggerService.py b/wxPython/samples/ide/activegrid/tool/DebuggerService.py index f87bafa760..ae8f60cfe6 100644 --- a/wxPython/samples/ide/activegrid/tool/DebuggerService.py +++ b/wxPython/samples/ide/activegrid/tool/DebuggerService.py @@ -31,7 +31,6 @@ import SimpleXMLRPCServer import xmlrpclib import os import threading -import process import Queue import SocketServer import ProjectEditor @@ -43,10 +42,18 @@ import DebuggerHarness import traceback import StringIO if wx.Platform == '__WXMSW__': - import win32api + try: + import win32api + _PYWIN32_INSTALLED = True + except ImportError: + _PYWIN32_INSTALLED = False _WINDOWS = True else: _WINDOWS = False + +if not _WINDOWS or _PYWIN32_INSTALLED: + import process + _ = wx.GetTranslation _VERBOSE = False @@ -1560,10 +1567,8 @@ class DebuggerService(Service.Service): elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS: event.Enable(self.HasBreakpointsSet()) return True - elif an_id == DebuggerService.RUN_ID: - event.Enable(self.HasAnyFiles()) - return True - elif an_id == DebuggerService.DEBUG_ID: + elif (an_id == DebuggerService.RUN_ID + or an_id == DebuggerService.DEBUG_ID): event.Enable(self.HasAnyFiles()) return True else: @@ -1574,6 +1579,9 @@ class DebuggerService(Service.Service): #---------------------------------------------------------------------------- def OnDebugProject(self, event): + if _WINDOWS and not _PYWIN32_INSTALLED: + wx.MessageBox(_("Python for Windows extensions (pywin32) is required to debug on Windows machines. Please go to http://sourceforge.net/projects/pywin32/, download and install pywin32.")) + return if not Executor.GetPythonExecutablePath(): return if DebugCommandUI.DebuggerRunning(): @@ -1636,13 +1644,13 @@ class DebuggerService(Service.Service): yesNoMsg = wx.MessageDialog(frame, _("Files have been modified.\nWould you like to save all files before running?"), _("Run"), - wx.YES_NO + wx.YES_NO|wx.ICON_QUESTION ) else: yesNoMsg = wx.MessageDialog(frame, _("Files have been modified.\nWould you like to save all files before debugging?"), _("Debug"), - wx.YES_NO + wx.YES_NO|wx.ICON_QUESTION ) if yesNoMsg.ShowModal() == wx.ID_YES: docs = wx.GetApp().GetDocumentManager().GetDocuments() @@ -1653,6 +1661,9 @@ class DebuggerService(Service.Service): DebugCommandUI.ShutdownAllDebuggers() def OnRunProject(self, event): + if _WINDOWS and not _PYWIN32_INSTALLED: + wx.MessageBox(_("Python for Windows extensions (pywin32) is required to run on Windows machines. Please go to http://sourceforge.net/projects/pywin32/, download and install pywin32.")) + return if not Executor.GetPythonExecutablePath(): return projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) @@ -1892,9 +1903,6 @@ class CommandPropertiesDialog(wx.Dialog): self._lastArguments = config.Read("LastRunArguments") self._argsEntry = wx.TextCtrl(self, -1, str(self._lastArguments)) self._argsEntry.SetToolTipString(str(self._lastArguments)) - def TextChanged(event): - self._argsEntry.SetToolTipString(event.GetString()) - self.Bind(wx.EVT_TEXT, TextChanged, self._argsEntry) flexGridSizer.Add(argsStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) flexGridSizer.Add(self._argsEntry, 1, flag=wx.EXPAND) @@ -1911,7 +1919,7 @@ class CommandPropertiesDialog(wx.Dialog): self.Bind(wx.EVT_TEXT, TextChanged2, self._startEntry) flexGridSizer.Add(self._startEntry, 1, wx.EXPAND) - self._findDir = wx.Button(self, -1, _("Browse..."), size=(60,-1)) + self._findDir = wx.Button(self, -1, _("Browse...")) self.Bind(wx.EVT_BUTTON, self.OnFindDirClick, self._findDir) flexGridSizer.Add(self._findDir, 0, wx.RIGHT, 10) @@ -1935,12 +1943,12 @@ class CommandPropertiesDialog(wx.Dialog): cpPanelBorderSizer.Add(flexGridSizer, 0, wx.ALL, 10) box = wx.BoxSizer(wx.HORIZONTAL) - self._okButton = wx.Button(self, wx.ID_OK, okButtonName, size=(75,-1)) + self._okButton = wx.Button(self, wx.ID_OK, okButtonName) self._okButton.SetDefault() self._okButton.SetHelpText(_("The ") + okButtonName + _(" button completes the dialog")) box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5) self.Bind(wx.EVT_BUTTON, self.OnOKClick, self._okButton) - btn = wx.Button(self, wx.ID_CANCEL, _("Cancel"), size=(75,-1)) + btn = wx.Button(self, wx.ID_CANCEL, _("Cancel")) btn.SetHelpText(_("The Cancel button cancels the dialog.")) box.Add(btn, 0, wx.ALIGN_RIGHT|wx.ALL, 5) cpPanelBorderSizer.Add(box, 0, wx.ALIGN_RIGHT|wx.BOTTOM, 5) @@ -2115,15 +2123,15 @@ import cStringIO #---------------------------------------------------------------------- def getBreakData(): return \ -'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x11\x08\x06\ -\x00\x00\x00\xd4\xaf,\xc4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00\x97IDAT8\x8d\xbdSA\x0e\xc3 \x0c\x8b\x13\xfe=\x1e^\xe2\x1dF\xbb\x8c\ -\xd2\x0c\xa9\xda,q\x88\x05\x8e\x1d\x00P\x93;\xd0[\xa7W\x04\xe8\x8d\x0f\xdfxU\ -c%\x02\xbd\xbd\x05HQ+Xv\xb0\xa3VN\xf9\xd4\x01\xbd\x11j\x18\x1d\x00\x10\xa8AD\ -\xa4\xa4\xd6_\x9b\x19\xbb\x03\xd8c|\x8f\x00\xe0\x93\xa8g>\x15 C\xee:\xe7\x8f\ -\x08\xdesj\xcf\xe6\xde(\xddn\xec\x18f0w\xe0m;\x8d\x9b\xe4\xb1\xd4\n\xa6\x0e2\ -\xc4{\x1f\xeb\xdf?\xe5\xff\t\xa8\x1a$\x0cg\xac\xaf\xb0\xf4\x992<\x01\xec\xa0\ -U9V\xf9\x18\xc8\x00\x00\x00\x00IEND\xaeB`\x82' +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\ +\x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\ +\x00\x85IDAT(\x91\xbd\x92A\x16\x03!\x08CI\xdf\xdc\x0b\x8e\xe6\xd1\xe0d\xe9\ +\x82\xd6\xc7(\x9di7\xfd\xab<\x14\x13Q\xb8\xbb\xfc\xc2\xe3\xd3\x82\x99\xb9\ +\xe9\xaeq\xe1`f)HF\xc4\x8dC2\x06\xbf\x8a4\xcf\x1e\x03K\xe5h\x1bH\x02\x98\xc7\ +\x03\x98\xa9z\x07\x00%\xd6\xa9\xd27\x90\xac\xbbk\xe5\x15I\xcdD$\xdc\xa7\xceT\ +5a\xce\xf3\xe4\xa0\xaa\x8bO\x12\x11\xabC\xcb\x9c}\xd57\xef\xb0\xf3\xb7\x86p\ +\x97\xf7\xb5\xaa\xde\xb9\xfa|-O\xbdjN\x9b\xf8\x06A\xcb\x00\x00\x00\x00IEND\ +\xaeB`\x82' def getBreakBitmap(): return BitmapFromImage(getBreakImage()) @@ -2163,14 +2171,18 @@ def getClearOutputIcon(): #---------------------------------------------------------------------- def getCloseData(): return \ -'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x12\x00\x00\x00\x12\x08\x06\ -\x00\x00\x00V\xce\x8eW\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\ -\x00\x86IDAT8\x8d\xed\x90\xb1\r\x80 \x10E_"c\xd80\x02-\x138\x87;8\x8f\x8d\ -\x8b\xb0\x02\xa5\xad\rS\x88\xcd\x11) \x82\xb6\xbe\xea\xf2\xc9\xbd\xfc\x03~\ -\xdeb\x81\xb9\x90\xabJ^%\x00N\x849\x0e\xf0\x85\xbc\x8a\x12YZR2\xc7\x1eIB\xcb\ -\xb2\xcb\x9at\x9d\x95c\xa5Y|\x92\x0c\x0f\xa2\r8e\x1e\x81\x1d8z\xdb8\xee?Ig\ -\xfa\xb7\x92)\xcb\xacd\x01XZ$QD\xba\xf0\xa6\x80\xd5\x18cZ\x1b\x95$?\x1f\xb9\ -\x00\x1d\x94\x1e*e_\x8a~\x00\x00\x00\x00IEND\xaeB`\x82' +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\ +\x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\ +\x00\xedIDAT(\x91\xa5\x90!\xae\x840\x10\x86g_\xd6"*kz\x82j\xb0h\x1c\t\' x\ +\x92Z\xc2\x05\x10\x95\x18\x0e\x00\x02M\x82 \xe1\nMF#jz\x80\xea&+\x9a\x10\x96\ +\xdd}\xfb\xc8\x1b\xd7?\xdf\x97\xfe3\xb7u]\xe1\xca\xfc\\\xa2\xff- \xe24M\xc7\ +\xc49wJ\xee\xc7G]\xd7\x8c1\xc6\x18\xe7\xdc\'B\x08k\xed1y\xfaa\x1cG\xad\xb5\ +\x94\x12\x11\x9dsy\x9e+\xa5\x84\x10;\r\x00\xb7\xd3\x95\x8c1UU\x05A\x00\x00\ +\xd6\xda,\xcb\x92$\xf9\xb8\x03\x00PJ\x85\x10Zk\xa5\xd4+\xfdF\x00\x80\xae\xeb\ +\x08!\x84\x90y\x9e\x11\xf1\x8bP\x96\xa5\xef\xdd\xb6\xad\xb5VJ\xf9\x9b\xe0\ +\xe9\xa6i8\xe7\xbe\xdb\xb6mi\x9a\x0e\xc3\xf0F\x88\xe3\x18\x00\xfa\xbe\x0f\ +\xc3\xd0\'\x9c\xf3eY\xa2(*\x8ab\xc7\x9e\xaed\x8c\xa1\x94\xben\xf5\xb1\xd2W\ +\xfa,\xfce.\x0b\x0f\xb8\x96e\x90gS\xe0v\x00\x00\x00\x00IEND\xaeB`\x82' def getCloseBitmap(): return BitmapFromImage(getCloseImage()) diff --git a/wxPython/samples/ide/activegrid/tool/FindInDirService.py b/wxPython/samples/ide/activegrid/tool/FindInDirService.py index ed02188c4c..b52287a4fe 100644 --- a/wxPython/samples/ide/activegrid/tool/FindInDirService.py +++ b/wxPython/samples/ide/activegrid/tool/FindInDirService.py @@ -120,7 +120,7 @@ class FindInDirService(FindService.FindService): dlg.Destroy() wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton) - subfolderCtrl = wx.CheckBox(frame, -1, _("Search in subfolders")) + subfolderCtrl = wx.CheckBox(frame, -1, _("Search in subdirectories")) subfolderCtrl.SetValue(config.ReadInt(FIND_MATCHDIRSUBFOLDERS, True)) contentSizer.Add(subfolderCtrl, 0, wx.BOTTOM, SPACE) @@ -152,7 +152,7 @@ class FindInDirService(FindService.FindService): findBtn = wx.Button(frame, wx.ID_OK, _("Find")) findBtn.SetDefault() buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) - buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL, _("Cancel")), 0) + buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL), 0) borderSizer.Add(buttonSizer, 0, wx.ALL, SPACE) frame.SetSizer(borderSizer) @@ -311,7 +311,7 @@ class FindInDirService(FindService.FindService): findBtn = wx.Button(frame, wx.ID_OK, _("Find")) findBtn.SetDefault() buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) - buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL, _("Cancel")), 0) + buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL), 0) borderSizer.Add(buttonSizer, 0, wx.ALL, SPACE) frame.SetSizer(borderSizer) diff --git a/wxPython/samples/ide/activegrid/tool/FindService.py b/wxPython/samples/ide/activegrid/tool/FindService.py index da5235b5d9..2fac20da23 100644 --- a/wxPython/samples/ide/activegrid/tool/FindService.py +++ b/wxPython/samples/ide/activegrid/tool/FindService.py @@ -97,19 +97,11 @@ class FindService(wx.lib.pydocview.DocService): def ProcessUpdateUIEvent(self, event): id = event.GetId() - if id == FindService.FIND_ID: - event.Enable(False) - return True - elif id == FindService.FIND_PREVIOUS_ID: - event.Enable(False) - return True - elif id == FindService.FIND_NEXT_ID: - event.Enable(False) - return True - elif id == FindService.REPLACE_ID: - event.Enable(False) - return True - elif id == FindService.GOTO_LINE_ID: + if (id == FindService.FIND_ID + or id == FindService.FIND_PREVIOUS_ID + or id == FindService.FIND_NEXT_ID + or id == FindService.REPLACE_ID + or id == FindService.GOTO_LINE_ID): event.Enable(False) return True else: @@ -362,7 +354,7 @@ class FindDialog(wx.Dialog): findBtn = wx.Button(self, FindService.FINDONE_ID, _("Find Next")) findBtn.SetDefault() wx.EVT_BUTTON(self, FindService.FINDONE_ID, self.OnActionEvent) - cancelBtn = wx.Button(self, wx.ID_CANCEL, _("Cancel")) + cancelBtn = wx.Button(self, wx.ID_CANCEL) wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnClose) buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) buttonSizer.Add(cancelBtn, 0) @@ -457,7 +449,7 @@ class FindReplaceDialog(FindDialog): findBtn = wx.Button(self, FindService.FINDONE_ID, _("Find Next")) findBtn.SetDefault() wx.EVT_BUTTON(self, FindService.FINDONE_ID, self.OnActionEvent) - cancelBtn = wx.Button(self, wx.ID_CANCEL, _("Cancel")) + cancelBtn = wx.Button(self, wx.ID_CANCEL) wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnClose) replaceBtn = wx.Button(self, FindService.REPLACEONE_ID, _("Replace")) wx.EVT_BUTTON(self, FindService.REPLACEONE_ID, self.OnActionEvent) diff --git a/wxPython/samples/ide/activegrid/tool/IDE.py b/wxPython/samples/ide/activegrid/tool/IDE.py index 947a2da16a..995cfbf9e9 100644 --- a/wxPython/samples/ide/activegrid/tool/IDE.py +++ b/wxPython/samples/ide/activegrid/tool/IDE.py @@ -348,7 +348,12 @@ class IDEApplication(wx.lib.pydocview.DocApp): if not welcomeService.RunWelcomeIfFirstTime(): if os.path.exists("activegrid/tool/data/tips.txt"): wx.CallAfter(self.ShowTip, docManager.FindSuitableParent(), wx.CreateFileTipProvider("activegrid/tool/data/tips.txt", 0)) + else: + if os.path.exists("activegrid/tool/data/tips.txt"): + wx.CallAfter(self.ShowTip, docManager.FindSuitableParent(), wx.CreateFileTipProvider("activegrid/tool/data/tips.txt", 0)) + wx.UpdateUIEvent.SetUpdateInterval(200) # Overhead of updating menus was too much. Change to update every 200 milliseconds. + return True diff --git a/wxPython/samples/ide/activegrid/tool/ImageEditor.py b/wxPython/samples/ide/activegrid/tool/ImageEditor.py index 623f129ca3..6691236169 100644 --- a/wxPython/samples/ide/activegrid/tool/ImageEditor.py +++ b/wxPython/samples/ide/activegrid/tool/ImageEditor.py @@ -41,12 +41,23 @@ class ImageView(wx.lib.docview.View): panel = wx.Panel(frame, -1) bitmap = wx.Image(doc.GetFilename()).ConvertToBitmap() self._ctrl = wx.StaticBitmap(panel, -1, bitmap, (0,0), (bitmap.GetWidth(), bitmap.GetHeight())) + wx.EVT_LEFT_DOWN(self._ctrl, self.OnFocus) + wx.EVT_LEFT_DCLICK(self._ctrl, self.OnFocus) + wx.EVT_RIGHT_DOWN(self._ctrl, self.OnFocus) + wx.EVT_RIGHT_DCLICK(self._ctrl, self.OnFocus) + wx.EVT_MIDDLE_DOWN(self._ctrl, self.OnFocus) + wx.EVT_MIDDLE_DCLICK(self._ctrl, self.OnFocus) panel.SetClientSize(bitmap.GetSize()) frame.SetClientSize(panel.GetSize()) self.Activate() return True + def OnFocus(self, event): + self._ctrl.SetFocus() + event.Skip() + + def OnClose(self, deleteWindow = True): statusC = wx.GetApp().CloseChildDocuments(self.GetDocument()) statusP = wx.lib.docview.View.OnClose(self, deleteWindow = deleteWindow) diff --git a/wxPython/samples/ide/activegrid/tool/OutlineService.py b/wxPython/samples/ide/activegrid/tool/OutlineService.py index 858fbade75..c04f1ecc1f 100644 --- a/wxPython/samples/ide/activegrid/tool/OutlineService.py +++ b/wxPython/samples/ide/activegrid/tool/OutlineService.py @@ -156,11 +156,8 @@ class OutlineView(Service.ServiceView): treeCtrl.Expand(child) (child, cookie) = treeCtrl.GetNextChild(parentItem, cookie) - # wxBug: This causes a crash, tried using ScrollTo which crashed as well. Then tried calling it with wx.CallAfter and that crashed as well, with both EnsureVisible and ScrollTo - # self.GetControl().EnsureVisible(self.GetControl().GetRootItem()) - # So doing the following massive hack which forces the treectrl to scroll up to the top item - treeCtrl.Collapse(parentItem) - treeCtrl.Expand(parentItem) + if parentItem: + treeCtrl.EnsureVisible(parentItem) class OutlineTreeCtrl(wx.TreeCtrl): diff --git a/wxPython/samples/ide/activegrid/tool/ProjectEditor.py b/wxPython/samples/ide/activegrid/tool/ProjectEditor.py index f19fcf535f..cb407d8318 100644 --- a/wxPython/samples/ide/activegrid/tool/ProjectEditor.py +++ b/wxPython/samples/ide/activegrid/tool/ProjectEditor.py @@ -19,11 +19,10 @@ import wx from wxPython.lib.rcsizer import RowColSizer import time import Service -import MessageService -import DebuggerService import sys import activegrid.util.xmlmarshaller import UICommon +import Wizard from IDE import ACTIVEGRID_BASE_IDE if not ACTIVEGRID_BASE_IDE: import ProcessModelEditor @@ -36,11 +35,19 @@ else: _WINDOWS = False +#---------------------------------------------------------------------------- +# Constants +#---------------------------------------------------------------------------- +SPACE = 10 +HALF_SPACE = 5 + + #---------------------------------------------------------------------------- # XML Marshalling Methods #---------------------------------------------------------------------------- LOCAL_TYPE_MAPPING = { "projectmodel" : "activegrid.tool.ProjectEditor.ProjectModel", } + def load(fileObject): xml = fileObject.read() projectModel = activegrid.util.xmlmarshaller.unmarshal(xml, knownTypes=LOCAL_TYPE_MAPPING) @@ -58,15 +65,16 @@ def save(fileObject, projectModel): class ProjectModel: __xmlname__ = "projectmodel" - __xmlrename__ = { "_files":"files", "_homepath":"homepath" } + __xmlrename__ = { "_files":"files"} + def __init__(self): - self._homepath = None self._files = [] - - + + class ProjectDocument(wx.lib.docview.Document): + def __init__(self): wx.lib.docview.Document.__init__(self) self._projectModel = ProjectModel() @@ -79,27 +87,62 @@ class ProjectDocument(wx.lib.docview.Document): def OnCreate(self, path, flags): projectService = wx.GetApp().GetService(ProjectService) if projectService.GetView(): + # All project documents share the same view. view = projectService.GetView() self.AddView(view) + + if view.GetDocument(): + # All project documents need to share the same command processor, + # to enable redo/undo of cross project document commands + cmdProcessor = view.GetDocument().GetCommandProcessor() + if cmdProcessor: + self.SetCommandProcessor(cmdProcessor) else: view = self.GetDocumentTemplate().CreateView(self, flags) projectService.SetView(view) + + return view def LoadObject(self, fileObject): self._projectModel = activegrid.tool.ProjectEditor.load(fileObject) + self._projectModel._files = self.RelativeToAbsPath(self._projectModel._files) return True def SaveObject(self, fileObject): + absPath = self._projectModel._files + self._projectModel._files = self.AbsToRelativePath(absPath) # temporarily change it to relative paths for saving activegrid.tool.ProjectEditor.save(fileObject, self._projectModel) + self._projectModel._files = absPath # swap it back to absolute path return True - def OnSaveDocument(self, filename): - self._projectModel._homepath = wx.lib.docview.PathOnly(filename) - return wx.lib.docview.Document.OnSaveDocument(self, filename) + def AbsToRelativePath(self, paths): + curPath = os.path.dirname(self.GetFilename()) + curPathLen = len(curPath) + + newFilePaths = [] + for path in paths: + if path.startswith(curPath): + path = "." + path[curPathLen:] # use relative path + else: + pass # use absolute path + newFilePaths.append(path) + return newFilePaths + + + def RelativeToAbsPath(self, paths): + newFilePaths = [] + for path in paths: + if path.startswith("."): # relative to project file + curPath = os.path.dirname(self.GetFilename()) + path = os.path.normpath(os.path.join(curPath, path)) + elif not ACTIVEGRID_BASE_IDE: + print "Warning: absolute path '%s' found in project file, this may affect deployment" % path + newFilePaths.append(path) + return newFilePaths def OnOpenDocument(self, filename): @@ -132,47 +175,6 @@ class ProjectDocument(wx.lib.docview.Document): return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed self.Modify(False) - - # if the project file has moved, then ask the user if we should readjust the paths of all the files in the project - newHomepath = wx.lib.docview.PathOnly(filename) - if newHomepath != self._projectModel._homepath: - wx.GetApp().CloseSplash() - msgTitle = wx.GetApp().GetAppName() - if not msgTitle: - msgTitle = _("Project Moved") - projectService = wx.GetApp().GetService(activegrid.tool.ProjectEditor.ProjectService) - yesNoMsg = wx.MessageDialog(frame, - _("The project file '%s' was moved from:\n '%s'\nto:\n '%s'.\n\nWould you like to automatically adjust the project contents accordingly?") % (wx.lib.docview.FileNameFromPath(filename), self._projectModel._homepath, wx.lib.docview.PathOnly(filename)), - msgTitle, - wx.YES_NO | wx.STAY_ON_TOP - ) - if projectService.GetSuppressOpenProjectMessages() or yesNoMsg.ShowModal() == wx.ID_YES: - if not projectService.GetSuppressOpenProjectMessages(): - messageService = wx.GetApp().GetService(MessageService.MessageService) - messageService.ShowWindow() - messageView = messageService.GetView() - messageView.ClearLines() - messageView.AddLines(_("The project file '%s' was moved from:\n '%s'\nto:\n '%s'\n") % (wx.lib.docview.FileNameFromPath(filename), self._projectModel._homepath, wx.lib.docview.PathOnly(filename))) - messageView.AddLines(_("Updating file references:\n")) - - for index, filepath in enumerate(self._projectModel._files): - if filepath.startswith(self._projectModel._homepath + os.sep): - newfile = newHomepath + filepath[len(self._projectModel._homepath):len(filepath)] - if os.path.exists(newfile): - self._projectModel._files[index] = newfile - if not projectService.GetSuppressOpenProjectMessages(): - messageView.AddLines(_(" Success: '%s' location changed from '%s' to '%s'\n") % (wx.lib.docview.FileNameFromPath(filepath), wx.lib.docview.PathOnly(filepath), newHomepath)) - self.Modify(True) - else: - if not projectService.GetSuppressOpenProjectMessages(): - messageView.AddLines(_(" Failure: Couldn't find '%s', file wasn't located at '%s'\n") % (wx.lib.docview.FileNameFromPath(filepath), newHomepath)) - else: - if not projectService.GetSuppressOpenProjectMessages(): - messageView.AddLines(_( " Unmodified: '%s' location wasn't relative to '%s'\n") % (filepath, self._projectModel._homepath)) - self._projectModel._homepath = newHomepath - if not projectService.GetSuppressOpenProjectMessages(): - messageView.AddLines(_("Project file updated.")) - self.SetFilename(filename, True) view.AddProjectToView(self) self.SetDocumentModificationDate() @@ -255,8 +257,6 @@ class ProjectDocument(wx.lib.docview.Document): return filename in self.GetFiles() -import Wizard - class NewProjectWizard(Wizard.BaseWizard): WIZTITLE = _("New Project Wizard") @@ -267,7 +267,8 @@ class NewProjectWizard(Wizard.BaseWizard): Wizard.BaseWizard.__init__(self, parent, self.WIZTITLE) self._projectLocationPage = self.CreateProjectLocation(self) wx.wizard.EVT_WIZARD_PAGE_CHANGING(self, self.GetId(), self.OnWizPageChanging) - + + def CreateProjectLocation(self,wizard): page = Wizard.TitledWizardPage(wizard, _("Project File Location")) @@ -279,6 +280,7 @@ class NewProjectWizard(Wizard.BaseWizard): wizard.FitToPage(page) return page + def RunWizard(self, existingTables = None, existingRelationships = None): status = wx.wizard.Wizard.RunWizard(self, self._projectLocationPage) if status: @@ -327,8 +329,10 @@ class NewProjectWizard(Wizard.BaseWizard): wiz.Destroy() self.Show(True) + class ProjectTemplate(wx.lib.docview.DocTemplate): + def CreateDocument(self, path, flags): if path: return wx.lib.docview.DocTemplate.CreateDocument(self, path, flags) @@ -338,8 +342,10 @@ class ProjectTemplate(wx.lib.docview.DocTemplate): wiz.Destroy() return None # never return the doc, otherwise docview will think it is a new file and rename it + class ProjectAddFilesCommand(wx.lib.docview.Command): + def __init__(self, projectDoc, files): wx.lib.docview.Command.__init__(self, canUndo = True) self._projectDoc = projectDoc @@ -348,7 +354,7 @@ class ProjectAddFilesCommand(wx.lib.docview.Command): def GetName(self): if len(self._files) == 1: - return _("Add File") + return _("Add File %s") % os.path.basename(self._files[0]) else: return _("Add Files") @@ -363,29 +369,56 @@ class ProjectAddFilesCommand(wx.lib.docview.Command): class ProjectRemoveFilesCommand(wx.lib.docview.Command): - def __init__(self, projectDoc, files): + + def __init__(self, files): wx.lib.docview.Command.__init__(self, canUndo = True) - self._projectDoc = projectDoc self._files = files def GetName(self): if len(self._files) == 1: - return _("Remove File") + return _("Remove File %s") % os.path.basename((self._files[0])[1]) else: return _("Remove Files") def Do(self): - return self._projectDoc.RemoveFiles(self._files) + status = False + projects = [] + for data in self._files: + proj, filename = data + if proj not in projects: + projects.append(proj) + for project in projects: + files = [] + for data in self._files: + proj, filename = data + if project == proj: + files.append(filename) + status = project.RemoveFiles(files) or status + return status def Undo(self): - return self._projectDoc.AddFiles(self._files) - + status = False + projects = [] + for data in self._files: + proj, filename = data + if proj not in projects: + projects.append(proj) + for project in projects: + files = [] + for data in self._files: + proj, filename = data + if project == proj: + files.append(filename) + status = project.AddFiles(files) or status + return status + class ProjectRenameFileCommand(wx.lib.docview.Command): + def __init__(self, projectDoc, oldFile, newFile, isProject = False): wx.lib.docview.Command.__init__(self, canUndo = True) self._projectDoc = projectDoc @@ -395,7 +428,7 @@ class ProjectRenameFileCommand(wx.lib.docview.Command): def GetName(self): - return _("Rename File") + return _("Rename File %s to %s") % (os.path.basename(self._oldFile), os.path.basename(self._newFile)) def Do(self): @@ -407,6 +440,11 @@ class ProjectRenameFileCommand(wx.lib.docview.Command): class ProjectTreeCtrl(wx.TreeCtrl): + + + #---------------------------------------------------------------------------- + # Overridden Methods + #---------------------------------------------------------------------------- def __init__(self, parent, id, style): wx.TreeCtrl.__init__(self, parent, id, style = style) @@ -417,18 +455,20 @@ class ProjectTreeCtrl(wx.TreeCtrl): for template in templates: icon = template.GetIcon() if icon: - if icon.GetHeight() != 16: - icon.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32 - if icon.GetWidth() != 16: - icon.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32 + if icon.GetHeight() != 16 or icon.GetWidth() != 16: + icon.SetHeight(16) + icon.SetWidth(16) + if wx.GetApp().GetDebug(): + print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template._docTypeName iconIndex = iconList.AddIcon(icon) self._iconIndexLookup.append((template, iconIndex)) icon = getBlankIcon() - if icon.GetHeight() != 16: - icon.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32 - if icon.GetWidth() != 16: - icon.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32 + if icon.GetHeight() != 16 or icon.GetWidth() != 16: + icon.SetHeight(16) + icon.SetWidth(16) + if wx.GetApp().GetDebug(): + print "Warning: getBlankIcon isn't 16x16, not crossplatform" self._blankIconIndex = iconList.AddIcon(icon) self.AssignImageList(iconList) @@ -461,6 +501,31 @@ class ProjectTreeCtrl(wx.TreeCtrl): return item + #---------------------------------------------------------------------------- + # Client Data + #---------------------------------------------------------------------------- + + def SetData(self, item, longFilename, projectDoc=None): + self.SetPyData(item, (longFilename, projectDoc)) + + + def GetData(self, item): + """ returns longFilename and optional + """ + data = self.GetPyData(item) + if not data: + return (None, None) + return data + + + def GetLongFilename(self, item): + return self.GetData(item)[0] + + + def GetProjectDoc(self, item): + return self.GetData(item)[1] + + class ProjectView(wx.lib.docview.View): @@ -471,7 +536,6 @@ class ProjectView(wx.lib.docview.View): def __init__(self, service = None): wx.lib.docview.View.__init__(self) self._service = service # not used, but kept to match other Services - self._lastDirectory = "" self._treeCtrl = None self._editingSoDontKillFocus = False self._checkEditMenu = True @@ -563,6 +627,8 @@ class ProjectView(wx.lib.docview.View): sizer = wx.BoxSizer() self._treeCtrl = ProjectTreeCtrl(frame, -1, style = wx.TR_HIDE_ROOT | wx.TR_HAS_BUTTONS | wx.TR_EDIT_LABELS | wx.TR_DEFAULT_STYLE | wx.TR_MULTIPLE) self._treeCtrl.AddRoot(_("Projects")) + wx.EVT_TREE_BEGIN_DRAG(self._treeCtrl, self._treeCtrl.GetId(), self.OnBeginDrag) + wx.EVT_TREE_END_DRAG(self._treeCtrl, self._treeCtrl.GetId(), self.OnEndDrag) if self._embeddedWindow: sizer.Add(self._treeCtrl) @@ -594,6 +660,48 @@ class ProjectView(wx.lib.docview.View): return True + def OnBeginDrag(self, event): + item = event.GetItem() + if item.IsOk(): + if item == self._treeCtrl.GetRootItem(): + return + self._draggingItem = item + event.Allow() + + + def OnEndDrag(self, event): + item = event.GetItem() + if item.IsOk(): + # don't allow object to be dragged to itself + if item == self._draggingItem: + return + + rootItem = self._treeCtrl.GetRootItem() + + # don't let object replace root view + if item == rootItem: + wx.MessageBox(_("Cannot replace root view with item.")) + return + + # don't allow object to be dragged to a direct descendant + ancestor = self._treeCtrl.GetItemParent(item) + while ancestor != rootItem: + if ancestor == self._draggingItem: + wx.MessageBox(_("Cannot make item direct descendant of self.")) + return + else: + ancestor = self._treeCtrl.GetItemParent(ancestor) + + if self._treeCtrl.GetItemParent(item) == self._treeCtrl.GetItemParent(self._draggingItem): + # put it in same folder as it was originally, no-op. + return + if item == self._treeCtrl.GetItemParent(self._draggingItem): + # put it in same folder as it was originally, no-op. + return + + self.GetDocument().GetCommandProcessor().Submit(ProjectEditorMoveCommand(self, item, self._draggingItem)) + + def WriteProjectConfig(self): frame = self.GetFrame() config = wx.ConfigBase_Get() @@ -649,15 +757,19 @@ class ProjectView(wx.lib.docview.View): files = hint[2] self._treeCtrl.UnselectAll() self._treeCtrl.Expand(projectItem) + item = None for file in files: item = self._treeCtrl.AppendItem(projectItem, os.path.basename(file)) - self._treeCtrl.SetPyData(item, file) + self._treeCtrl.SetData(item, file) self._treeCtrl.SelectItem(item) - self._treeCtrl.EnsureVisible(item) # wxBug: Doesn't work + self._treeCtrl.EnsureVisible(item) self._treeCtrl.SortChildren(projectItem) + if item: + self._treeCtrl.EnsureVisible(item) # need to be called after SortChildren elif hint[0] == "remove": projectItem = self._GetProjectItem(hint[1]) files = hint[2] + self._treeCtrl.UnselectAll() children = self._GetChildItems(projectItem) for child in children: if self._GetItemFile(child) in files: @@ -670,7 +782,7 @@ class ProjectView(wx.lib.docview.View): for child in children: if self._GetItemFile(child) in files: self._treeCtrl.SelectItem(child) - self._treeCtrl.EnsureVisible(child) # wxBug: Doesn't work + self._treeCtrl.EnsureVisible(child) elif hint[0] == "rename": projectItem = self._GetProjectItem(hint[1]) self._treeCtrl.SetItemText(projectItem, os.path.basename(hint[2])) @@ -681,11 +793,17 @@ class ProjectView(wx.lib.docview.View): if id == ProjectService.ADD_FILES_TO_PROJECT_ID: self.OnAddFileToProject(event) return True + elif id == ProjectService.ADD_ALL_FILES_TO_PROJECT_ID: + self.OnAddDirToProject(event) + return True elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID: return False # Implement this one in the service elif id == ProjectService.RENAME_ID: self.OnRename(event) return True + elif id == ProjectService.DELETE_FILE_ID: + self.OnDeleteFile(event) + return True elif id == wx.ID_CUT: self.OnCut(event) return True @@ -695,7 +813,8 @@ class ProjectView(wx.lib.docview.View): elif id == wx.ID_PASTE: self.OnPaste(event) return True - elif id == wx.ID_CLEAR or id == ProjectService.REMOVE_FROM_PROJECT: + elif (id == wx.ID_CLEAR + or id == ProjectService.REMOVE_FROM_PROJECT): self.OnClear(event) return True elif id == wx.ID_SELECTALL: @@ -710,6 +829,7 @@ class ProjectView(wx.lib.docview.View): else: return False + def ProcessUpdateUIEvent(self, event): # Hack: The edit menu is not being set for projects that are preloaded at startup, so make sure it is OK here if self._checkEditMenu: @@ -717,37 +837,31 @@ class ProjectView(wx.lib.docview.View): if doc and not doc.GetCommandProcessor().GetEditMenu(): doc.GetCommandProcessor().SetEditMenu(wx.GetApp().GetEditMenu(self._GetParentFrame())) self._checkEditMenu = False + id = event.GetId() - if id == ProjectService.ADD_FILES_TO_PROJECT_ID: - event.Enable(self._HasProjectsSelected() or self._HasFilesSelected()) + if (id == wx.ID_CUT + or id == wx.ID_COPY + or id == ProjectService.RENAME_ID + or id == ProjectService.ADD_FILES_TO_PROJECT_ID + or id == ProjectService.ADD_ALL_FILES_TO_PROJECT_ID + or id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID + or id == ProjectService.DELETE_FILE_ID): + event.Enable(self._HasSelection()) return True elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID: event.Enable(False) return True - elif id == ProjectService.RENAME_ID: - event.Enable(self._HasFilesSelected() or self._HasProjectsSelected()) - return True - elif id == wx.ID_CUT: - event.Enable(self._AreSelectedItemsFromSameProject()) - return True - elif id == wx.ID_COPY: - event.Enable(self._HasFilesSelected()) - return True elif id == wx.ID_PASTE: event.Enable(self.CanPaste()) return True - elif id == wx.ID_CLEAR or id == ProjectService.REMOVE_FROM_PROJECT: - event.Enable(self._AreSelectedItemsFromSameProject()) - return True elif id == wx.ID_SELECTALL: event.Enable(self._HasFiles()) return True - elif id == ProjectService.OPEN_SELECTION_ID: + elif (id == wx.ID_CLEAR + or id == ProjectService.REMOVE_FROM_PROJECT + or id == ProjectService.OPEN_SELECTION_ID): event.Enable(self._HasFilesSelected()) return True - elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID: - event.Enable(self._HasProjectsSelected() or self._HasFilesSelected()) - return True else: return False @@ -800,10 +914,10 @@ class ProjectView(wx.lib.docview.View): def AddProjectToView(self, document): rootItem = self._treeCtrl.GetRootItem() projectItem = self._treeCtrl.AppendItem(rootItem, self._MakeProjectName(document)) - self._treeCtrl.SetPyData(projectItem, document) + self._treeCtrl.SetData(projectItem, document.GetFilename(), document) for file in document.GetFiles(): fileItem = self._treeCtrl.AppendItem(projectItem, os.path.basename(file)) - self._treeCtrl.SetPyData(fileItem, file) + self._treeCtrl.SetData(fileItem, file) self._treeCtrl.SortChildren(rootItem) self._treeCtrl.SortChildren(projectItem) self._treeCtrl.UnselectAll() @@ -847,22 +961,160 @@ class ProjectView(wx.lib.docview.View): descr = descr + _("|") + _("Any (*.*) | *.*") else: descr = _("*.*") + + startDirectory = os.path.dirname(self.GetDocument().GetFilename()) + if True or _WINDOWS: - dialog = wx.FileDialog(self.GetFrame(), _("Add Files"), self._lastDirectory, "", descr, wx.OPEN | wx.HIDE_READONLY | wx.MULTIPLE) + dialog = wx.FileDialog(self.GetFrame(), _("Add Files"), startDirectory, "", descr, wx.OPEN | wx.HIDE_READONLY | wx.MULTIPLE) if dialog.ShowModal() != wx.ID_OK: return paths = dialog.GetPaths() dialog.Destroy() else: - paths = wx.FileSelector(_("Add Files"), self._lastDirectory, "", wildcard = descr, flags = wx.OPEN | wx.HIDE_READONLY | wx.MULTIPLE, parent=self.GetFrame()) + paths = wx.FileSelector(_("Add Files"), startDirectory, "", wildcard = descr, flags = wx.OPEN | wx.HIDE_READONLY | wx.MULTIPLE, parent=self.GetFrame()) if type(paths) == types.StringType: paths = [paths] if len(paths): - self._lastDirectory = wx.lib.docview.PathOnly(paths[0]) self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), paths)) self.Activate(True) # after add, should put focus on project editor + def OnAddDirToProject(self, event): + frame = wx.Dialog(None, -1, _("Add All Files from Directory to Project"), size= (320,200)) + borderSizer = wx.BoxSizer(wx.HORIZONTAL) + + contentSizer = wx.BoxSizer(wx.VERTICAL) + lineSizer = wx.BoxSizer(wx.HORIZONTAL) + lineSizer.Add(wx.StaticText(frame, -1, _("Directory:")), 0, wx.ALIGN_CENTER | wx.RIGHT, HALF_SPACE) + dirCtrl = wx.TextCtrl(frame, -1, os.path.dirname(self.GetDocument().GetFilename()), size=(200,-1)) + dirCtrl.SetToolTipString(dirCtrl.GetValue()) + lineSizer.Add(dirCtrl, 0, wx.LEFT, HALF_SPACE) + findDirButton = wx.Button(frame, -1, "Browse...") + lineSizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE) + contentSizer.Add(lineSizer, 0, wx.BOTTOM, SPACE) + + def OnBrowseButton(event): + dlg = wx.DirDialog(frame, _("Choose a directory:"), style=wx.DD_DEFAULT_STYLE) + dir = dirCtrl.GetValue() + if len(dir): + dlg.SetPath(dir) + if dlg.ShowModal() == wx.ID_OK: + dirCtrl.SetValue(dlg.GetPath()) + dirCtrl.SetToolTipString(dirCtrl.GetValue()) + dirCtrl.SetInsertionPointEnd() + + dlg.Destroy() + wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton) + + visibleTemplates = [] + for template in self.GetDocumentManager()._templates: + if template.IsVisible(): + visibleTemplates.append(template) + + choices = [] + allfilter = '' + descr = '' + for template in visibleTemplates: + if len(descr) > 0: + descr = descr + _('|') + allfilter = allfilter + _(';') + descr = template.GetDescription() + _(" (") + template.GetFileFilter() + _(")") + choices.append(descr) + allfilter = allfilter + template.GetFileFilter() + choices.insert(0, _("All (%s)") % allfilter) + filterChoice = wx.Choice(frame, -1, size=(210, -1), choices=choices) + filterChoice.SetSelection(0) + filterChoice.SetToolTipString(_("Select file type filter.")) + lineSizer = wx.BoxSizer(wx.HORIZONTAL) + lineSizer.Add(wx.StaticText(frame, -1, _("Files of type:")), 0, wx.ALIGN_CENTER | wx.RIGHT, HALF_SPACE) + lineSizer.Add(filterChoice, 1, wx.LEFT, HALF_SPACE) + contentSizer.Add(lineSizer, 0, wx.BOTTOM|wx.EXPAND, SPACE) + + subfolderCtrl = wx.CheckBox(frame, -1, _("Add files from subdirectories")) + subfolderCtrl.SetValue(True) + contentSizer.Add(subfolderCtrl, 0, wx.BOTTOM, SPACE) + + borderSizer.Add(contentSizer, 0, wx.TOP|wx.BOTTOM|wx.LEFT, SPACE) + + buttonSizer = wx.BoxSizer(wx.VERTICAL) + findBtn = wx.Button(frame, wx.ID_OK, _("Add")) + findBtn.SetDefault() + buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) + buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL), 0) + borderSizer.Add(buttonSizer, 0, wx.ALL, SPACE) + + frame.SetSizer(borderSizer) + frame.Fit() + + status = frame.ShowModal() + + passedCheck = False + while status == wx.ID_OK and not passedCheck: + if not os.path.exists(dirCtrl.GetValue()): + dlg = wx.MessageDialog(frame, + _("'%s' does not exist.") % dirCtrl.GetValue(), + _("Find in Directory"), + wx.OK | wx.ICON_EXCLAMATION + ) + dlg.ShowModal() + dlg.Destroy() + + status = frame.ShowModal() + else: + passedCheck = True + + if status == wx.ID_OK: + frame.Destroy() + + wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) + + doc = self.GetDocument() + searchSubfolders = subfolderCtrl.IsChecked() + dirString = dirCtrl.GetValue() + + if os.path.isfile(dirString): + # If they pick a file explicitly, we won't prevent them from adding it even if it doesn't match the filter. + # We'll assume they know what they're doing. + paths = [dirString] + else: + paths = [] + + index = filterChoice.GetSelection() + if index: + template = visibleTemplates[index-1] + + # do search in files on disk + for root, dirs, files in os.walk(dirString): + if not searchSubfolders and root != dirString: + break + + for name in files: + if index == 0: # all + for template in visibleTemplates: + if template.FileMatchesTemplate(name): + filename = os.path.join(root, name) + + # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. + if doc.IsFileInProject(filename): + break + + paths.append(filename) + break + else: # use selected filter + if template.FileMatchesTemplate(name): + filename = os.path.join(root, name) + # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. + if not doc.IsFileInProject(filename): + paths.append(filename) + + wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) + + doc.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc, paths)) + self.Activate(True) # after add, should put focus on project editor + else: + frame.Destroy() + + def DoAddFilesToProject(self, filenames): # method used by Drag-n-Drop to add files to current Project self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), filenames)) @@ -870,8 +1122,7 @@ class ProjectView(wx.lib.docview.View): def DoSelectFiles(self, filenames): # method used by Drag-n-Drop to select files in current Project - for selection in self._treeCtrl.GetSelections(): - self._treeCtrl.SelectItem(selection, False) + self._treeCtrl.UnselectAll() for file in filenames: item = self._GetFileItem(longFileName=file) if item: @@ -929,7 +1180,7 @@ class ProjectView(wx.lib.docview.View): else: # Project context itemIDs = [wx.ID_CLOSE, wx.ID_SAVE, wx.ID_SAVEAS, None] menuBar = self._GetParentFrame().GetMenuBar() - itemIDs = itemIDs + [wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID, None, ProjectService.ADD_FILES_TO_PROJECT_ID, ProjectService.REMOVE_FROM_PROJECT, None, wx.ID_UNDO, wx.ID_REDO, None, wx.ID_CUT, wx.ID_COPY, wx.ID_PASTE, wx.ID_CLEAR, None, wx.ID_SELECTALL, None, ProjectService.RENAME_ID] + itemIDs = itemIDs + [ProjectService.ADD_FILES_TO_PROJECT_ID, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, ProjectService.REMOVE_FROM_PROJECT, None, wx.ID_UNDO, wx.ID_REDO, None, wx.ID_CUT, wx.ID_COPY, wx.ID_PASTE, wx.ID_CLEAR, None, wx.ID_SELECTALL, ProjectService.RENAME_ID, ProjectService.DELETE_FILE_ID, None, wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID] for itemID in itemIDs: if not itemID: menu.AppendSeparator() @@ -948,9 +1199,12 @@ class ProjectView(wx.lib.docview.View): self._treeCtrl.PopupMenu(menu, wx.Point(event.GetX(), event.GetY())) menu.Destroy() + def OnRunSelectedPM(self, event): projectService = wx.GetApp().GetService(ProjectService) - projectService.OnRunProcessModel(event, runSelected=True) + if projectService: + projectService.OnRunProcessModel(event, runSelected=True) + def OnRename(self, event): if self._treeCtrl.GetSelections(): @@ -974,14 +1228,16 @@ class ProjectView(wx.lib.docview.View): if self._IsItemFile(item): oldFile = self._GetItemFile(item) newFile = os.path.join(os.path.split(oldFile)[0], newName) - if not self._GetItemProject(item).GetCommandProcessor().Submit(ProjectRenameFileCommand(self.GetDocument(), oldFile, newFile)): + project = self._GetItemProject(item) + if not project.GetCommandProcessor().Submit(ProjectRenameFileCommand(project, oldFile, newFile)): event.Veto() return self._treeCtrl.SortChildren(self._treeCtrl.GetItemParent(self._treeCtrl.GetSelections()[0])) elif self._IsItemProject(item): oldFile = self._GetItemProject(item).GetFilename() newFile = os.path.join(os.path.split(oldFile)[0], newName) - if not self._GetItemProject(item).GetCommandProcessor().Submit(ProjectRenameFileCommand(self.GetDocument(), oldFile, newFile, True)): + project = self._GetItemProject(item) + if not project.GetCommandProcessor().Submit(ProjectRenameFileCommand(project, oldFile, newFile, True)): event.Veto() return self._treeCtrl.SortChildren(self._treeCtrl.GetRootItem()) @@ -1002,9 +1258,8 @@ class ProjectView(wx.lib.docview.View): def OnCut(self, event): - if self._AreSelectedItemsFromSameProject(): - self.OnCopy(event) - self.OnClear(event) + self.OnCopy(event) + self.OnClear(event) def OnCopy(self, event): @@ -1012,7 +1267,7 @@ class ProjectView(wx.lib.docview.View): items = self._treeCtrl.GetSelections() for item in items: if self._IsItemFile(item): - file = self._treeCtrl.GetPyData(item) + file = self._treeCtrl.GetLongFilename(item) fileDataObject.AddFile(file) if len(fileDataObject.GetFilenames()) > 0 and wx.TheClipboard.Open(): wx.TheClipboard.SetData(fileDataObject) @@ -1028,15 +1283,57 @@ class ProjectView(wx.lib.docview.View): def OnClear(self, event): - if self._AreSelectedItemsFromSameProject(): - items = self._treeCtrl.GetSelections() - files = [] - for item in items: - if self._IsItemFile(item): - files.append(self._GetItemFile(item)) - self.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(self._GetItemProject(items[0]), files)) + items = self._treeCtrl.GetSelections() + files = [] + for item in items: + if self._IsItemFile(item): + files.append((self._GetItemProject(item), self._GetItemFile(item))) + self.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(files)) + def OnDeleteFile(self, event): + yesNoMsg = wx.MessageDialog(self.GetFrame(), + _("Delete cannot be reversed.\n\nRemove the selected files from the\nprojects and file system permanently?"), + _("Delete File"), + wx.YES_NO|wx.ICON_QUESTION) + if yesNoMsg.ShowModal() == wx.ID_NO: + return + + items = self._treeCtrl.GetSelections() + files = [] + delFiles = [] + for item in items: + if self._IsItemFile(item): + filename = self._GetItemFile(item) + files.append((self._GetItemProject(item), filename)) + if filename not in delFiles: + delFiles.append(filename) + + # remove selected files from projects + projects = [] + for data in files: + proj, filename = data + if proj not in projects: + projects.append(proj) + for project in projects: + filenames = [] + for data in files: + proj, filename = data + if project == proj: + filenames.append(filename) + project.RemoveFiles(filenames) + + # remove selected files from file system + for filename in delFiles: + if os.path.exists(filename): + try: + os.remove(filename) + except: + wx.MessageBox("Could not delete '%s'. %s" % (os.path.basename(filename), sys.exc_value), + _("Delete File"), + wx.OK | wx.ICON_EXCLAMATION) + + def OnKeyPressed(self, event): key = event.KeyCode() if key == wx.WXK_DELETE: @@ -1072,7 +1369,7 @@ class ProjectView(wx.lib.docview.View): yesNoMsg = wx.MessageDialog(self.GetFrame(), _("The file '%s' was not found in '%s'.\n\nWould you like to browse for the file?") % (wx.lib.docview.FileNameFromPath(filepath), wx.lib.docview.PathOnly(filepath)), msgTitle, - wx.YES_NO + wx.YES_NO|wx.ICON_QUESTION ) if yesNoMsg.ShowModal() == wx.ID_NO: continue @@ -1094,6 +1391,17 @@ class ProjectView(wx.lib.docview.View): filepath = newpath doc = self.GetDocumentManager().CreateDocument(filepath, wx.lib.docview.DOC_SILENT) + if not doc: + shortFilename = self._treeCtrl.GetItemText(item) + if shortFilename.endswith(".agp"): + projItem = self._GetProjectItem(shortFilename=shortFilename) + self._treeCtrl.UnselectAll() + if not self._treeCtrl.IsExpanded(projItem): + self._treeCtrl.Expand(projItem) + if not self._treeCtrl.IsVisible(projItem): + self._treeCtrl.EnsureVisible(projItem) + if not self._treeCtrl.IsSelected(projItem): + self._treeCtrl.SelectItem(projItem) except IOError, (code, message): msgTitle = wx.GetApp().GetAppName() @@ -1115,15 +1423,14 @@ class ProjectView(wx.lib.docview.View): return self._treeCtrl.GetCount() > 1 # 1 item = root item, don't count as having files - def _HasProjectsSelected(self): + def _HasSelection(self): if not self._treeCtrl: return False + items = self._treeCtrl.GetSelections() - if not items: - return False - for item in items: - if self._IsItemProject(item): - return True + if items: + return True + return False @@ -1144,11 +1451,17 @@ class ProjectView(wx.lib.docview.View): # Return the tree item for a project - def _GetProjectItem(self, project): - children = self._GetChildItems(self._treeCtrl.GetRootItem()) - for child in children: - if self._treeCtrl.GetPyData(child) == project: - return child + def _GetProjectItem(self, project=None, shortFilename=None): + rootItem = self._treeCtrl.GetRootItem() + (child, cookie) = self._treeCtrl.GetFirstChild(rootItem) + while child.IsOk(): + if project: + if self._treeCtrl.GetProjectDoc(child) == project: + return child + elif shortFilename: + if self._treeCtrl.GetItemText(child) == shortFilename: + return child + (child, cookie) = self._treeCtrl.GetNextChild(rootItem, cookie) return None @@ -1157,15 +1470,15 @@ class ProjectView(wx.lib.docview.View): if self._IsItemRoot(item): return None if self._IsItemProject(item): - return self._treeCtrl.GetPyData(item) + return self._treeCtrl.GetProjectDoc(item) if self._IsItemFile(item): - return self._treeCtrl.GetPyData(self._treeCtrl.GetItemParent(item)) + return self._treeCtrl.GetProjectDoc(self._treeCtrl.GetItemParent(item)) return None def _GetItemFile(self, item): if self._IsItemFile(item): - return self._treeCtrl.GetPyData(item) + return self._treeCtrl.GetLongFilename(item) else: return None @@ -1173,39 +1486,20 @@ class ProjectView(wx.lib.docview.View): def _GetFileItem(self, shortFileName = None, longFileName = None): """ Returns the tree item for a file given the short (display) or long (fullpath) file name. """ - if shortFileName: - project_children = self._GetChildItems(self._treeCtrl.GetRootItem()) - for child in project_children: - file_children = self._GetChildItems(child) - for file_child in file_children: - if self._treeCtrl.GetItemText(file_child) == shortFileName: - return file_child - return None - else: - project_children = self._GetChildItems(self._treeCtrl.GetRootItem()) - for child in project_children: - file_children = self._GetChildItems(child) - for file_child in file_children: - if self._treeCtrl.GetPyData(file_child) == longFileName: - return file_child - return None - - - def GetFilePathFromTreeName(self, shortFileName): - """ - Returns the data object given a short (display) file name for a file. The data - object should be the full path. - """ - return self._GetItemFile(self._GetFileItem(shortFileName)) - - - def SelectFileInTree(self, shortFileName): - item = self._GetFileItem(shortFileName) - if item: - for selection in self._treeCtrl.GetSelections(): - self._treeCtrl.SelectItem(selection, False) - self._treeCtrl.SelectItem(item, True) - self._treeCtrl.EnsureVisible(item) + rootItem = self._treeCtrl.GetRootItem() + (project, cookie) = self._treeCtrl.GetFirstChild(rootItem) + while project.IsOk(): + (child, cookie2) = self._treeCtrl.GetFirstChild(project) + while child.IsOk(): + if shortFileName: + if self._treeCtrl.GetItemText(child) == shortFileName: + return child + else: + if self._treeCtrl.GetLongFilename(child) == longFileName: + return child + (child, cookie2) = self._treeCtrl.GetNextChild(project, cookie) + (project, cookie) = self._treeCtrl.GetNextChild(rootItem, cookie) + return None def _IsItemRoot(self, item): @@ -1213,19 +1507,19 @@ class ProjectView(wx.lib.docview.View): def _IsItemProject(self, item): - return isinstance(self._treeCtrl.GetPyData(item), ProjectDocument) + return self._treeCtrl.GetProjectDoc(item) != None def _IsItemFile(self, item): - return isinstance(self._treeCtrl.GetPyData(item), types.StringTypes) + return self._treeCtrl.GetProjectDoc(item) == None def _IsItemProcessModelFile(self, item): if ACTIVEGRID_BASE_IDE: return False - if isinstance(self._treeCtrl.GetPyData(item), types.StringTypes): - filename = self._treeCtrl.GetPyData(item) + if self._IsItemFile(item): + filename = self._treeCtrl.GetLongFilename(item) ext = None for template in self.GetDocumentManager().GetTemplates(): if template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument: @@ -1240,23 +1534,6 @@ class ProjectView(wx.lib.docview.View): return False - def _AreSelectedItemsFromSameProject(self): - if not self._treeCtrl: - return False - items = self._treeCtrl.GetSelections() - if not items: - return False - project = self._GetItemProject(items[0]) - if project == None: - return False - for item in items: - if not self._IsItemFile(item): - return False - if self._GetItemProject(item) != project: - return False - return True - - def _GetChildItems(self, parentItem): children = [] (child, cookie) = self._treeCtrl.GetFirstChild(parentItem) @@ -1294,9 +1571,6 @@ class ProjectPropertiesDialog(wx.Dialog): def __init__(self, parent, filename): wx.Dialog.__init__(self, parent, -1, _("Project Properties"), size = (310, 330)) - HALF_SPACE = 5 - SPACE = 10 - filePropertiesService = wx.GetApp().GetService(wx.lib.pydocview.FilePropertiesService) notebook = wx.Notebook(self, -1) @@ -1354,8 +1628,6 @@ class ProjectOptionsPanel(wx.Panel): def __init__(self, parent, id): wx.Panel.__init__(self, parent, id) self._useSashMessageShown = False - SPACE = 10 - HALF_SPACE = 5 config = wx.ConfigBase_Get() self._projSaveDocsCheckBox = wx.CheckBox(self, -1, _("Remember open projects")) self._projSaveDocsCheckBox.SetValue(config.ReadInt("ProjectSaveDocs", True)) @@ -1404,7 +1676,9 @@ class ProjectService(Service.Service): RENAME_ID = wx.NewId() OPEN_SELECTION_ID = wx.NewId() REMOVE_FROM_PROJECT = wx.NewId() - + DELETE_FILE_ID = wx.NewId() + ADD_ALL_FILES_TO_PROJECT_ID = wx.NewId() + #---------------------------------------------------------------------------- # Overridden methods @@ -1457,8 +1731,6 @@ class ProjectService(Service.Service): def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None): Service.Service.InstallControls(self, frame, menuBar, toolBar, statusBar, document) - config = wx.ConfigBase_Get() - projectMenu = wx.Menu() ## accelTable = wx.AcceleratorTable([ @@ -1468,9 +1740,13 @@ class ProjectService(Service.Service): isProjectDocument = document and document.GetDocumentTemplate().GetDocumentType() == ProjectDocument if wx.GetApp().IsMDI() or isProjectDocument: if not menuBar.FindItemById(ProjectService.ADD_FILES_TO_PROJECT_ID): - projectMenu.Append(ProjectService.ADD_FILES_TO_PROJECT_ID, _("&Add Files to Project..."), _("Adds a document to the current project")) + projectMenu.Append(ProjectService.ADD_FILES_TO_PROJECT_ID, _("Add &Files to Project..."), _("Adds a document to the current project")) wx.EVT_MENU(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessEvent) wx.EVT_UPDATE_UI(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent) + if not menuBar.FindItemById(ProjectService.ADD_ALL_FILES_TO_PROJECT_ID): + projectMenu.Append(ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, _("Add All Files to Project..."), _("Adds a directory's documents to the current project")) + wx.EVT_MENU(frame, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, frame.ProcessEvent) + wx.EVT_UPDATE_UI(frame, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent) if not menuBar.FindItemById(ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID): projectMenu.Append(ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID, _("&Add Active File to Project..."), _("Adds the active document to a project")) wx.EVT_MENU(frame, ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID, frame.ProcessEvent) @@ -1479,10 +1755,13 @@ class ProjectService(Service.Service): menuBar.Insert(viewMenuIndex + 1, projectMenu, _("&Project")) editMenu = menuBar.GetMenu(menuBar.FindMenu(_("&Edit"))) if not menuBar.FindItemById(ProjectService.RENAME_ID): - editMenu.AppendSeparator() editMenu.Append(ProjectService.RENAME_ID, _("&Rename"), _("Renames the active item")) wx.EVT_MENU(frame, ProjectService.RENAME_ID, frame.ProcessEvent) wx.EVT_UPDATE_UI(frame, ProjectService.RENAME_ID, frame.ProcessUpdateUIEvent) + if not menuBar.FindItemById(ProjectService.DELETE_FILE_ID): + editMenu.Append(ProjectService.DELETE_FILE_ID, _("Delete File"), _("Delete the file from the project and file system.")) + wx.EVT_MENU(frame, ProjectService.DELETE_FILE_ID, frame.ProcessEvent) + wx.EVT_UPDATE_UI(frame, ProjectService.DELETE_FILE_ID, frame.ProcessUpdateUIEvent) return True @@ -1554,19 +1833,19 @@ class ProjectService(Service.Service): return True id = event.GetId() - if id == ProjectService.RUNPM_ID or id == ProjectService.RUN_SELECTED_PM_ID or id == ProjectService.RUN_CURRENT_PM_ID: + if (id == ProjectService.RUNPM_ID + or id == ProjectService.RUN_SELECTED_PM_ID + or id == ProjectService.RUN_CURRENT_PM_ID): event.Enable(self._HasOpenedProjects() and self._HasProcessModel()) return True - elif id == ProjectService.ADD_FILES_TO_PROJECT_ID: - event.Enable(False) - return True elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID: event.Enable(self._CanAddCurrentFileToProject()) return True - elif id == ProjectService.RENAME_ID: - event.Enable(False) - return True - elif id == ProjectService.OPEN_SELECTION_ID: + elif (id == ProjectService.ADD_FILES_TO_PROJECT_ID + or id == ProjectService.ADD_ALL_FILES_TO_PROJECT_ID + or id == ProjectService.RENAME_ID + or id == ProjectService.OPEN_SELECTION_ID + or id == ProjectService.DELETE_FILE_ID): event.Enable(False) return True elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID: @@ -1611,7 +1890,7 @@ class ProjectService(Service.Service): yesNoMsg = wx.MessageDialog(frame, _("Files have been modified. Process may not reflect your current changes.\n\nWould you like to save all files before running?"), _("Run Process"), - wx.YES_NO + wx.YES_NO|wx.ICON_QUESTION ) if yesNoMsg.ShowModal() == wx.ID_YES: wx.GetTopLevelParent(frame).OnFileSaveAll(None) @@ -1728,6 +2007,7 @@ class ProjectService(Service.Service): strings = map(lambda project: project.GetPrintableName(), projects) return strings + def OnAddCurrentFileToProject(self, event): if not self._CanAddCurrentFileToProject(): return @@ -1778,6 +2058,41 @@ class ProjectService(Service.Service): view.SetExpandedProjects(eval(expandedString)) return openedDocs + +class ProjectEditorMoveCommand(wx.lib.docview.Command): + + def __init__(self, view, newPositionItem, item): + wx.lib.docview.Command.__init__(self, canUndo = True) + self._view = view + self._item = item + self._file = view._treeCtrl.GetLongFilename(item) + if view._IsItemFile(item): + self._projectOld = view._GetItemProject(item) + else: # view._IsItemProject(item): + self._projectOld = None + self._projectNew = view._GetItemProject(newPositionItem) + + + def GetName(self): + return _("Move File %s") % os.path.basename(self._file) + + + def Do(self): + if self._projectOld: + self._projectOld.RemoveFile(self._file) + if self._projectNew: + self._projectNew.AddFile(self._file) + return True + + + def Undo(self): + if self._projectNew: + self._projectNew.RemoveFile(self._file) + if self._projectOld: + self._projectOld.AddFile(self._file) + return True + + #---------------------------------------------------------------------------- # Icon Bitmaps - generated by encode_bitmaps.py #---------------------------------------------------------------------------- diff --git a/wxPython/samples/ide/activegrid/tool/STCTextEditor.py b/wxPython/samples/ide/activegrid/tool/STCTextEditor.py index fd57104569..8d27a19d24 100644 --- a/wxPython/samples/ide/activegrid/tool/STCTextEditor.py +++ b/wxPython/samples/ide/activegrid/tool/STCTextEditor.py @@ -293,10 +293,6 @@ class TextView(wx.lib.docview.View): if not self.GetCtrl(): return False - hasSelection = self.GetCtrl().GetSelectionStart() != self.GetCtrl().GetSelectionEnd() - hasText = self.GetCtrl().GetTextLength() > 0 - notOnLastChar = self.GetCtrl().GetSelectionStart() != self.GetCtrl().GetTextLength() - id = event.GetId() if id == wx.ID_UNDO: event.Enable(self.GetCtrl().CanUndo()) @@ -306,41 +302,44 @@ class TextView(wx.lib.docview.View): event.Enable(self.GetCtrl().CanRedo()) event.SetText(_("Redo") + '\t' + _('Ctrl+Y')) return True - elif id == wx.ID_CUT: - event.Enable(hasSelection) - return True - elif id == wx.ID_COPY: + elif (id == wx.ID_CUT + or id == wx.ID_COPY + or id == wx.ID_CLEAR): + hasSelection = self.GetCtrl().GetSelectionStart() != self.GetCtrl().GetSelectionEnd() event.Enable(hasSelection) return True elif id == wx.ID_PASTE: event.Enable(self.GetCtrl().CanPaste()) return True - elif id == wx.ID_CLEAR: - event.Enable(hasSelection) - return True elif id == wx.ID_SELECTALL: + hasText = self.GetCtrl().GetTextLength() > 0 event.Enable(hasText) return True elif id == TEXT_ID: event.Enable(True) return True elif id == VIEW_WHITESPACE_ID: + hasText = self.GetCtrl().GetTextLength() > 0 event.Enable(hasText) event.Check(self.GetCtrl().GetViewWhiteSpace()) return True elif id == VIEW_EOL_ID: + hasText = self.GetCtrl().GetTextLength() > 0 event.Enable(hasText) event.Check(self.GetCtrl().GetViewEOL()) return True elif id == VIEW_INDENTATION_GUIDES_ID: + hasText = self.GetCtrl().GetTextLength() > 0 event.Enable(hasText) event.Check(self.GetCtrl().GetIndentationGuides()) return True elif id == VIEW_RIGHT_EDGE_ID: + hasText = self.GetCtrl().GetTextLength() > 0 event.Enable(hasText) event.Check(self.GetCtrl().GetViewRightEdge()) return True elif id == VIEW_LINE_NUMBERS_ID: + hasText = self.GetCtrl().GetTextLength() > 0 event.Enable(hasText) event.Check(self.GetCtrl().GetViewLineNumbers()) return True @@ -364,19 +363,23 @@ class TextView(wx.lib.docview.View): event.Check(self.GetCtrl().CanWordWrap() and self.GetCtrl().GetWordWrap()) return True elif id == FindService.FindService.FIND_ID: + hasText = self.GetCtrl().GetTextLength() > 0 event.Enable(hasText) return True elif id == FindService.FindService.FIND_PREVIOUS_ID: + hasText = self.GetCtrl().GetTextLength() > 0 event.Enable(hasText and self._FindServiceHasString() and self.GetCtrl().GetSelection()[0] > 0) return True elif id == FindService.FindService.FIND_NEXT_ID: + hasText = self.GetCtrl().GetTextLength() > 0 event.Enable(hasText and self._FindServiceHasString() and self.GetCtrl().GetSelection()[0] < self.GetCtrl().GetLength()) return True elif id == FindService.FindService.REPLACE_ID: + hasText = self.GetCtrl().GetTextLength() > 0 event.Enable(hasText) return True elif id == FindService.FindService.GOTO_LINE_ID: @@ -745,40 +748,18 @@ class TextService(wx.lib.pydocview.DocService): def ProcessUpdateUIEvent(self, event): id = event.GetId() - if id == TEXT_ID: - event.Enable(False) - return True - elif id == VIEW_WHITESPACE_ID: - event.Enable(False) - return True - elif id == VIEW_EOL_ID: - event.Enable(False) - return True - elif id == VIEW_INDENTATION_GUIDES_ID: - event.Enable(False) - return True - elif id == VIEW_RIGHT_EDGE_ID: - event.Enable(False) - return True - elif id == VIEW_LINE_NUMBERS_ID: - event.Enable(False) - return True - elif id == ZOOM_ID: - event.Enable(False) - return True - elif id == ZOOM_NORMAL_ID: - event.Enable(False) - return True - elif id == ZOOM_IN_ID: - event.Enable(False) - return True - elif id == ZOOM_OUT_ID: - event.Enable(False) - return True - elif id == CHOOSE_FONT_ID: - event.Enable(False) - return True - elif id == WORD_WRAP_ID: + if (id == TEXT_ID + or id == VIEW_WHITESPACE_ID + or id == VIEW_EOL_ID + or id == VIEW_INDENTATION_GUIDES_ID + or id == VIEW_RIGHT_EDGE_ID + or id == VIEW_LINE_NUMBERS_ID + or id == ZOOM_ID + or id == ZOOM_NORMAL_ID + or id == ZOOM_IN_ID + or id == ZOOM_OUT_ID + or id == CHOOSE_FONT_ID + or id == WORD_WRAP_ID): event.Enable(False) return True else: diff --git a/wxPython/samples/ide/activegrid/tool/UICommon.py b/wxPython/samples/ide/activegrid/tool/UICommon.py index 226fe2a302..52c6a152dc 100644 --- a/wxPython/samples/ide/activegrid/tool/UICommon.py +++ b/wxPython/samples/ide/activegrid/tool/UICommon.py @@ -88,6 +88,7 @@ def AddFilesToCurrentProject(paths, save=False): paths.remove(path) if paths: projectDocument.GetCommandProcessor().Submit(ProjectEditor.ProjectAddFilesCommand(projectDocument, paths)) + projectDocument.GetFirstView().DoSelectFiles([paths[0]]) if save: projectDocument.OnSaveDocument(projectDocument.GetFilename()) diff --git a/wxPython/samples/ide/activegrid/tool/checker.py b/wxPython/samples/ide/activegrid/tool/checker.py index bf62cfa2ec..23b4372727 100644 --- a/wxPython/samples/ide/activegrid/tool/checker.py +++ b/wxPython/samples/ide/activegrid/tool/checker.py @@ -721,7 +721,15 @@ def processFiles(files, cfg = None, pre_process_cb = None) : if callable(pre_process_cb) : pre_process_cb(moduleName) module = Module(moduleName, fullpath = filename) - + + # reload the given module, otherwise won't get new syntax errors. + sysModule = sys.modules.get(moduleName) + if sysModule: + try: + reload(sysModule) + except: + pass + module.load(warnings) utils.popConfig() return warnings @@ -749,7 +757,7 @@ def checkSyntax(filename, messageView): _cfg, files, suppressions = Config.setupFromArgs([filename]) if not files : return 0 - + global _output, _statusDlg, _count _output = messageView # wxBug: Need to show progress dialog box, or message window never gets updated until the method returns @@ -757,7 +765,8 @@ def checkSyntax(filename, messageView): _count = 0 # insert this here, so we find files in the local dir before std library - sys.path.insert(0, '') + if sys.path[0] != '' : + sys.path.insert(0, '') importWarnings = processFiles(files, _cfg, _print_processing) fixupBuiltinModules() diff --git a/wxPython/samples/ide/activegrid/util/__init__.py b/wxPython/samples/ide/activegrid/util/__init__.py index 905f93a0ab..b5380e6b13 100644 --- a/wxPython/samples/ide/activegrid/util/__init__.py +++ b/wxPython/samples/ide/activegrid/util/__init__.py @@ -1,3 +1,15 @@ +#---------------------------------------------------------------------------- +# Name: __init__.py +# Purpose: Utilities +# +# Author: Joel Hare +# +# Created: 7/28/04 +# CVS-ID: $Id$ +# Copyright: (c) 2004-2005 ActiveGrid, Inc. +# License: wxWindows License +#---------------------------------------------------------------------------- + import logging import cStringIO import traceback @@ -33,7 +45,7 @@ def setattrignorecase(object, name, value): ## object.__dict__[attr] = value ## return object.__dict__[name] = value - + def getattrignorecase(object, name): for attr in object.__dict__: if attr.lower() == name.lower(): @@ -44,18 +56,18 @@ def getattrignorecase(object, name): return object.__dict__[name] -def defaultLoad(fileObject): +def defaultLoad(fileObject, knownTypes=None): xml = fileObject.read() - loadedObject = xmlmarshaller.unmarshal(xml) + loadedObject = xmlmarshaller.unmarshal(xml, knownTypes=knownTypes) if hasattr(fileObject, 'name'): loadedObject.fileName = os.path.abspath(fileObject.name) loadedObject.initialize() return loadedObject -def defaultSave(fileObject, objectToSave): - xml = xmlmarshaller.marshal(objectToSave, prettyPrint=True) +def defaultSave(fileObject, objectToSave, knownTypes=None): + xml = xmlmarshaller.marshal(objectToSave, prettyPrint=True, knownTypes=knownTypes) fileObject.write(xml) - + fileObject.close() def clone(objectToClone): xml = xmlmarshaller.marshal(objectToClone, prettyPrint=True) diff --git a/wxPython/samples/pydocview/FindService.py b/wxPython/samples/pydocview/FindService.py index da5235b5d9..2fac20da23 100644 --- a/wxPython/samples/pydocview/FindService.py +++ b/wxPython/samples/pydocview/FindService.py @@ -97,19 +97,11 @@ class FindService(wx.lib.pydocview.DocService): def ProcessUpdateUIEvent(self, event): id = event.GetId() - if id == FindService.FIND_ID: - event.Enable(False) - return True - elif id == FindService.FIND_PREVIOUS_ID: - event.Enable(False) - return True - elif id == FindService.FIND_NEXT_ID: - event.Enable(False) - return True - elif id == FindService.REPLACE_ID: - event.Enable(False) - return True - elif id == FindService.GOTO_LINE_ID: + if (id == FindService.FIND_ID + or id == FindService.FIND_PREVIOUS_ID + or id == FindService.FIND_NEXT_ID + or id == FindService.REPLACE_ID + or id == FindService.GOTO_LINE_ID): event.Enable(False) return True else: @@ -362,7 +354,7 @@ class FindDialog(wx.Dialog): findBtn = wx.Button(self, FindService.FINDONE_ID, _("Find Next")) findBtn.SetDefault() wx.EVT_BUTTON(self, FindService.FINDONE_ID, self.OnActionEvent) - cancelBtn = wx.Button(self, wx.ID_CANCEL, _("Cancel")) + cancelBtn = wx.Button(self, wx.ID_CANCEL) wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnClose) buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) buttonSizer.Add(cancelBtn, 0) @@ -457,7 +449,7 @@ class FindReplaceDialog(FindDialog): findBtn = wx.Button(self, FindService.FINDONE_ID, _("Find Next")) findBtn.SetDefault() wx.EVT_BUTTON(self, FindService.FINDONE_ID, self.OnActionEvent) - cancelBtn = wx.Button(self, wx.ID_CANCEL, _("Cancel")) + cancelBtn = wx.Button(self, wx.ID_CANCEL) wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnClose) replaceBtn = wx.Button(self, FindService.REPLACEONE_ID, _("Replace")) wx.EVT_BUTTON(self, FindService.REPLACEONE_ID, self.OnActionEvent) diff --git a/wxPython/samples/pydocview/TextEditor.py b/wxPython/samples/pydocview/TextEditor.py index 2e432cfb61..496c489802 100644 --- a/wxPython/samples/pydocview/TextEditor.py +++ b/wxPython/samples/pydocview/TextEditor.py @@ -7,7 +7,7 @@ # Created: 8/15/03 # CVS-ID: $Id$ # Copyright: (c) 2003-2005 ActiveGrid, Inc. -# License: ASL 2.0 http://apache.org/licenses/LICENSE-2.0 +# License: wxWindows License #---------------------------------------------------------------------------- import wx import wx.lib.docview diff --git a/wxPython/wx/lib/docview.py b/wxPython/wx/lib/docview.py index 5a2a46ad50..a945a14969 100644 --- a/wxPython/wx/lib/docview.py +++ b/wxPython/wx/lib/docview.py @@ -215,16 +215,13 @@ class Document(wx.EvtHandler): self._documentModified = modify - def SetDocumentModificationDate(self, filename=None): + def SetDocumentModificationDate(self): """ Saves the file's last modification date. This is used to check if the file has been modified outside of the application. This method has been added to wxPython and is not in wxWindows. """ - if not filename: - filename = self.GetFilename() - self._documentModificationDate = os.path.getmtime(filename) - print "debug print, file: %s set modification date to %s" % (filename, self._documentModificationDate) + self._documentModificationDate = os.path.getmtime(self.GetFilename()) def GetDocumentModificationDate(self): @@ -365,7 +362,6 @@ class Document(wx.EvtHandler): """ check for file modification outside of application """ if os.path.exists(self.GetFilename()) and os.path.getmtime(self.GetFilename()) != self.GetDocumentModificationDate(): - print "debug print, File %s: new mod date %s, original mod date %s" % (self.GetFilename(), os.path.getmtime(self.GetFilename()), self.GetDocumentModificationDate()) msgTitle = wx.GetApp().GetAppName() if not msgTitle: msgTitle = _("Application") @@ -468,6 +464,7 @@ class Document(wx.EvtHandler): if backupFilename: os.remove(filename) os.rename(backupFilename, filename) + self.SetDocumentModificationDate() wx.MessageBox("Could not save '%s'. %s" % (FileNameFromPath(filename), sys.exc_value), msgTitle, @@ -596,7 +593,6 @@ class Document(wx.EvtHandler): """ check for file modification outside of application """ if os.path.exists(self.GetFilename()) and os.path.getmtime(self.GetFilename()) != self.GetDocumentModificationDate(): - print "debug print, File %s: new mod date %s, original mod date %s" % (self.GetFilename(), os.path.getmtime(self.GetFilename()), self.GetDocumentModificationDate()) msgTitle = wx.GetApp().GetAppName() if not msgTitle: msgTitle = _("Warning") diff --git a/wxPython/wx/lib/pydocview.py b/wxPython/wx/lib/pydocview.py index 2a2a544878..e35c564548 100644 --- a/wxPython/wx/lib/pydocview.py +++ b/wxPython/wx/lib/pydocview.py @@ -780,18 +780,20 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn): for template in templates: icon = template.GetIcon() if icon: - if icon.GetHeight() != 16: - icon.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32 - if icon.GetWidth() != 16: - icon.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32 + if icon.GetHeight() != 16 or icon.GetWidth() != 16: + icon.SetHeight(16) + icon.SetWidth(16) + if wx.GetApp().GetDebug(): + print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template._docTypeName iconIndex = iconList.AddIcon(icon) self._iconIndexLookup.append((template, iconIndex)) icon = getBlankIcon() - if icon.GetHeight() != 16: - icon.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32 - if icon.GetWidth() != 16: - icon.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32 + if icon.GetHeight() != 16 or icon.GetWidth() != 16: + icon.SetHeight(16) + icon.SetWidth(16) + if wx.GetApp().GetDebug(): + print "Warning: getBlankIcon isn't 16x16, not crossplatform" self._blankIconIndex = iconList.AddIcon(icon) self._notebook.AssignImageList(iconList)