Merged modifications from the 2.6 branch
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@36607 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -854,6 +854,7 @@ class Calendar( wx.PyControl ):
|
||||
|
||||
def SetDayValue(self, day):
|
||||
self.set_day = day
|
||||
self.day = day
|
||||
|
||||
def SetMonth(self, month):
|
||||
if month >= 1 and month <= 12:
|
||||
|
@@ -28,10 +28,12 @@ DOC_MDI = 2
|
||||
DOC_NEW = 4
|
||||
DOC_SILENT = 8
|
||||
DOC_OPEN_ONCE = 16
|
||||
DOC_NO_VIEW = 32
|
||||
DEFAULT_DOCMAN_FLAGS = DOC_SDI & DOC_OPEN_ONCE
|
||||
|
||||
TEMPLATE_VISIBLE = 1
|
||||
TEMPLATE_INVISIBLE = 2
|
||||
TEMPLATE_NO_CREATE = (4 | TEMPLATE_VISIBLE)
|
||||
DEFAULT_TEMPLATE_FLAGS = TEMPLATE_VISIBLE
|
||||
|
||||
MAX_FILE_HISTORY = 9
|
||||
@@ -680,8 +682,10 @@ class Document(wx.EvtHandler):
|
||||
"""
|
||||
The default implementation calls DeleteContents (an empty
|
||||
implementation) sets the modified flag to false. Override this to
|
||||
supply additional behaviour when the document is closed with Close.
|
||||
supply additional behaviour when the document is opened with Open.
|
||||
"""
|
||||
if flags & DOC_NO_VIEW:
|
||||
return True
|
||||
return self.GetDocumentTemplate().CreateView(self, flags)
|
||||
|
||||
|
||||
@@ -1193,6 +1197,16 @@ class DocTemplate(wx.Object):
|
||||
return (self._flags & TEMPLATE_VISIBLE) == TEMPLATE_VISIBLE
|
||||
|
||||
|
||||
def IsNewable(self):
|
||||
"""
|
||||
Returns true if the document template can be shown in "New" dialogs,
|
||||
false otherwise.
|
||||
|
||||
This method has been added to wxPython and is not in wxWindows.
|
||||
"""
|
||||
return (self._flags & TEMPLATE_NO_CREATE) != TEMPLATE_NO_CREATE
|
||||
|
||||
|
||||
def GetDocumentName(self):
|
||||
"""
|
||||
Returns the document type name, as passed to the document template
|
||||
@@ -1250,8 +1264,9 @@ class DocTemplate(wx.Object):
|
||||
"""
|
||||
ext = FindExtension(path)
|
||||
if not ext: return False
|
||||
return ext in self.GetFileFilter()
|
||||
# return self.GetDefaultExtension() == FindExtension(path)
|
||||
|
||||
extList = self.GetFileFilter().replace('*','').split(';')
|
||||
return ext in extList
|
||||
|
||||
|
||||
class DocManager(wx.EvtHandler):
|
||||
@@ -1802,7 +1817,13 @@ class DocManager(wx.EvtHandler):
|
||||
will delete the oldest currently loaded document before creating a new
|
||||
one.
|
||||
|
||||
wxPython version supports the document manager's wx.lib.docview.DOC_OPEN_ONCE flag.
|
||||
wxPython version supports the document manager's wx.lib.docview.DOC_OPEN_ONCE
|
||||
and wx.lib.docview.DOC_NO_VIEW flag.
|
||||
|
||||
if wx.lib.docview.DOC_OPEN_ONCE is present, trying to open the same file multiple
|
||||
times will just return the same document.
|
||||
if wx.lib.docview.DOC_NO_VIEW is present, opening a file will generate the document,
|
||||
but not generate a corresponding view.
|
||||
"""
|
||||
templates = []
|
||||
for temp in self._templates:
|
||||
@@ -1817,16 +1838,13 @@ class DocManager(wx.EvtHandler):
|
||||
return None
|
||||
|
||||
if flags & DOC_NEW:
|
||||
for temp in templates[:]:
|
||||
if not temp.IsNewable():
|
||||
templates.remove(temp)
|
||||
if len(templates) == 1:
|
||||
temp = templates[0]
|
||||
newDoc = temp.CreateDocument(path, flags)
|
||||
if newDoc:
|
||||
newDoc.SetDocumentName(temp.GetDocumentName())
|
||||
newDoc.SetDocumentTemplate(temp)
|
||||
newDoc.OnNewDocument()
|
||||
return newDoc
|
||||
|
||||
temp = self.SelectDocumentType(templates)
|
||||
else:
|
||||
temp = self.SelectDocumentType(templates)
|
||||
if temp:
|
||||
newDoc = temp.CreateDocument(path, flags)
|
||||
if newDoc:
|
||||
@@ -1865,7 +1883,12 @@ class DocManager(wx.EvtHandler):
|
||||
document.SetDocumentModificationDate()
|
||||
|
||||
firstView = document.GetFirstView()
|
||||
if firstView and firstView.GetFrame():
|
||||
if not firstView and not (flags & DOC_NO_VIEW):
|
||||
document.GetDocumentTemplate().CreateView(document, flags)
|
||||
document.UpdateAllViews()
|
||||
firstView = document.GetFirstView()
|
||||
|
||||
if firstView and firstView.GetFrame() and not (flags & DOC_NO_VIEW):
|
||||
firstView.GetFrame().SetFocus() # Not in wxWindows code but useful nonetheless
|
||||
if hasattr(firstView.GetFrame(), "IsIconized") and firstView.GetFrame().IsIconized(): # Not in wxWindows code but useful nonetheless
|
||||
firstView.GetFrame().Iconize(False)
|
||||
@@ -1878,7 +1901,9 @@ class DocManager(wx.EvtHandler):
|
||||
newDoc.SetDocumentTemplate(temp)
|
||||
if not newDoc.OnOpenDocument(path):
|
||||
newDoc.DeleteAllViews() # Implicitly deleted by DeleteAllViews
|
||||
newDoc.GetFirstView().GetFrame().Destroy() # DeleteAllViews doesn't get rid of the frame, so we'll explicitly destroy it.
|
||||
frame = newDoc.GetFirstView().GetFrame()
|
||||
if frame:
|
||||
Destroy() # DeleteAllViews doesn't get rid of the frame, so we'll explicitly destroy it.
|
||||
return None
|
||||
self.AddFileToHistory(path)
|
||||
return newDoc
|
||||
@@ -2117,41 +2142,32 @@ class DocManager(wx.EvtHandler):
|
||||
This function is used in wxDocManager.CreateDocument.
|
||||
"""
|
||||
if wx.Platform == "__WXMSW__" or wx.Platform == "__WXGTK__" or wx.Platform == "__WXMAC__":
|
||||
allfilter = ''
|
||||
descr = ''
|
||||
for temp in templates:
|
||||
if temp.IsVisible():
|
||||
if len(descr) > 0:
|
||||
descr = descr + _('|')
|
||||
allfilter = allfilter + _(';')
|
||||
descr = descr + temp.GetDescription() + _(" (") + temp.GetFileFilter() + _(") |") + temp.GetFileFilter() # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
|
||||
allfilter = allfilter + temp.GetFileFilter()
|
||||
descr = _("All (%s)|%s|%s|Any (*.*) | *.*") % (allfilter, allfilter, descr) # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
|
||||
descr = _("All (*.*)|*.*|%s") % descr # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
|
||||
else:
|
||||
descr = _("*.*")
|
||||
|
||||
path = wx.FileSelector(_("Select a File"),
|
||||
self._lastDirectory,
|
||||
_(""),
|
||||
wildcard = descr,
|
||||
flags = wx.HIDE_READONLY,
|
||||
parent = self.FindSuitableParent())
|
||||
if path:
|
||||
if not FileExists(path):
|
||||
msgTitle = wx.GetApp().GetAppName()
|
||||
if not msgTitle:
|
||||
msgTitle = _("File Error")
|
||||
wx.MessageBox("Could not open '%s'." % FileNameFromPath(path),
|
||||
msgTitle,
|
||||
wx.OK | wx.ICON_EXCLAMATION,
|
||||
parent)
|
||||
return (None, None)
|
||||
self._lastDirectory = PathOnly(path)
|
||||
|
||||
dlg = wx.FileDialog(self.FindSuitableParent(),
|
||||
_("Select a File"),
|
||||
wildcard=descr,
|
||||
style=wx.OPEN|wx.FILE_MUST_EXIST|wx.CHANGE_DIR)
|
||||
# dlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
path = dlg.GetPath()
|
||||
else:
|
||||
path = None
|
||||
dlg.Destroy()
|
||||
|
||||
if path:
|
||||
theTemplate = self.FindTemplateForPath(path)
|
||||
return (theTemplate, path)
|
||||
|
||||
return (None, None)
|
||||
|
||||
return (None, None)
|
||||
|
||||
|
||||
def OnOpenFileFailure(self):
|
||||
@@ -3151,8 +3167,10 @@ class CommandProcessor(wx.Object):
|
||||
the history list.
|
||||
"""
|
||||
done = command.Do()
|
||||
if done and storeIt:
|
||||
self._commands.append(command)
|
||||
if done:
|
||||
del self._redoCommands[:]
|
||||
if storeIt:
|
||||
self._commands.append(command)
|
||||
if self._maxCommands > -1:
|
||||
if len(self._commands) > self._maxCommands:
|
||||
del self._commands[0]
|
||||
|
@@ -242,8 +242,8 @@ class FileBrowseButtonWithHistory( FileBrowseButton ):
|
||||
textControl.SetToolTipString( self.toolTip )
|
||||
textControl.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
|
||||
if self.changeCallback:
|
||||
textControl.Bind(wx.EVT_TEXT, self.changeCallback)
|
||||
textControl.Bind(wx.EVT_COMBOBOX, self.changeCallback)
|
||||
textControl.Bind(wx.EVT_TEXT, self.OnChanged)
|
||||
textControl.Bind(wx.EVT_COMBOBOX, self.OnChanged)
|
||||
if self.history:
|
||||
history=self.history
|
||||
self.history=None
|
||||
|
@@ -3,7 +3,7 @@
|
||||
# Ported From Jorgen Bodde & Julian Smart (Extended Demo) C++ Code By:
|
||||
#
|
||||
# Andrea Gavana, @ 23 Mar 2005
|
||||
# Latest Revision: 28 Mar 2005, 22.30 CET
|
||||
# Latest Revision: 05 Nov 2005, 23.30 CET
|
||||
#
|
||||
#
|
||||
# TODO List
|
||||
@@ -30,9 +30,14 @@
|
||||
# TODO: A Smart Way To Check Wether The Old - New Width Of The
|
||||
# Panel Changed, If So No Need To Resize The Fold Panel Items
|
||||
#
|
||||
# 5. Implementing Styles Like FPB_SINGLE_FOLD and FPB_EXCLUSIVE_FOLD
|
||||
# TODO: Jorgen Has Left Undone These Jobs. I Don't Really Get What They
|
||||
# Should Supposed To Do, So If Someone Could Enlight Me, Please Let Me Know.
|
||||
#
|
||||
# DONE List:
|
||||
#
|
||||
# 1. Implemented Styles Like FPB_SINGLE_FOLD and FPB_EXCLUSIVE_FOLD
|
||||
# Thanks To E. A. Tacao For His Nice Suggestions.
|
||||
#
|
||||
# 2. Added Some Maquillage To FoldPanelBar: When The Mouse Enters The Icon
|
||||
# Region, It Is Changed To wx.CURSOR_HAND.
|
||||
#
|
||||
#
|
||||
# For The Original TODO List From Jorgen, Please Refer To:
|
||||
@@ -106,7 +111,7 @@ FoldPanelBar is supported on the following platforms:
|
||||
* Mac OSX (Thanks To Robin Dunn For The CaptionBar Size Patch)
|
||||
|
||||
|
||||
Latest Revision: Andrea Gavana @ 30 Mar 2005, 22.30 CET
|
||||
Latest Revision: Andrea Gavana @ 05 Nov 2005, 23.30 CET
|
||||
|
||||
"""
|
||||
|
||||
@@ -179,7 +184,7 @@ FPB_EXTRA_Y = 4
|
||||
# pixels of the bmp to be aligned from the right filled with space
|
||||
FPB_BMP_RIGHTSPACE = 2
|
||||
|
||||
# Not yet supported but added for future reference. Single fold forces
|
||||
# Now supported! Single fold forces
|
||||
# other panels to close when they are open, and only opens the current panel.
|
||||
# This will allow the open panel to gain the full size left in the client area
|
||||
FPB_SINGLE_FOLD = 0x0001
|
||||
@@ -188,9 +193,9 @@ FPB_SINGLE_FOLD = 0x0001
|
||||
# show up at the top
|
||||
FPB_COLLAPSE_TO_BOTTOM = 0x0002
|
||||
|
||||
# Not yet supported, but added for future reference. Single fold plus panels
|
||||
# Now supported! Single fold plus panels
|
||||
# will be stacked at the bottom
|
||||
FPB_EXCLUSIVE_FOLD = FPB_SINGLE_FOLD | FPB_COLLAPSE_TO_BOTTOM
|
||||
FPB_EXCLUSIVE_FOLD = 0x0004
|
||||
|
||||
# Orientation Flag
|
||||
FPB_HORIZONTAL = wx.HORIZONTAL
|
||||
@@ -669,12 +674,13 @@ class CaptionBar(wx.Window):
|
||||
dc = wx.PaintDC(self)
|
||||
wndRect = self.GetRect()
|
||||
vertical = self.IsVertical()
|
||||
|
||||
|
||||
# TODO: Maybe first a memory DC should draw all, and then paint it on
|
||||
# the caption. This way a flickering arrow during resize is not visible
|
||||
|
||||
self.FillCaptionBackground(dc)
|
||||
dc.SetFont(self._style.GetCaptionFont())
|
||||
dc.SetTextForeground(self._style.GetCaptionColour())
|
||||
|
||||
if vertical:
|
||||
dc.DrawText(self._caption, 4, FPB_EXTRA_Y/2)
|
||||
@@ -734,27 +740,52 @@ class CaptionBar(wx.Window):
|
||||
"""
|
||||
Catches the mouse click-double click.
|
||||
|
||||
If clicked on the arrow (single) or double on the caption we
|
||||
change state and an event must be fired to let this panel
|
||||
collapse or expand.
|
||||
If clicked on the arrow (single) or double on the caption we change state
|
||||
and an event must be fired to let this panel collapse or expand.
|
||||
"""
|
||||
|
||||
send_event = False
|
||||
|
||||
send_event = False
|
||||
vertical = self.IsVertical()
|
||||
|
||||
if event.LeftDown() and self._foldIcons:
|
||||
|
||||
pt = event.GetPosition()
|
||||
rect = self.GetRect()
|
||||
vertical = self.IsVertical()
|
||||
|
||||
|
||||
drw = (rect.GetWidth() - self._iconWidth - self._rightIndent)
|
||||
if vertical and pt.x > drw or not vertical and \
|
||||
pt.y < (self._iconHeight + self._rightIndent):
|
||||
send_event = True
|
||||
|
||||
elif event.LeftDClick():
|
||||
self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
|
||||
send_event = True
|
||||
|
||||
elif event.Entering() and self._foldIcons:
|
||||
pt = event.GetPosition()
|
||||
rect = self.GetRect()
|
||||
|
||||
drw = (rect.GetWidth() - self._iconWidth - self._rightIndent)
|
||||
if vertical and pt.x > drw or not vertical and \
|
||||
pt.y < (self._iconHeight + self._rightIndent):
|
||||
self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
|
||||
else:
|
||||
self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
|
||||
|
||||
elif event.Leaving():
|
||||
self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
|
||||
|
||||
elif event.Moving():
|
||||
pt = event.GetPosition()
|
||||
rect = self.GetRect()
|
||||
|
||||
drw = (rect.GetWidth() - self._iconWidth - self._rightIndent)
|
||||
if vertical and pt.x > drw or not vertical and \
|
||||
pt.y < (self._iconHeight + self._rightIndent):
|
||||
self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
|
||||
else:
|
||||
self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
|
||||
|
||||
# send the collapse, expand event to the parent
|
||||
|
||||
if send_event:
|
||||
@@ -1172,7 +1203,7 @@ class FoldPanelBar(wx.Panel):
|
||||
|
||||
self._foldPanel.SetSize(foldrect[2:])
|
||||
|
||||
if self._extraStyle & FPB_COLLAPSE_TO_BOTTOM:
|
||||
if self._extraStyle & FPB_COLLAPSE_TO_BOTTOM or self._extraStyle & FPB_EXCLUSIVE_FOLD:
|
||||
rect = self.RepositionCollapsedToBottom()
|
||||
vertical = self.IsVertical()
|
||||
if vertical and rect.GetHeight() > 0 or not vertical and rect.GetWidth() > 0:
|
||||
@@ -1212,7 +1243,7 @@ class FoldPanelBar(wx.Panel):
|
||||
# should be drawn at the bottom. All panels that are expanded
|
||||
# are drawn on top. The last expanded panel gets all the extra space
|
||||
|
||||
if self._extraStyle & FPB_COLLAPSE_TO_BOTTOM:
|
||||
if self._extraStyle & FPB_COLLAPSE_TO_BOTTOM or self._extraStyle & FPB_EXCLUSIVE_FOLD:
|
||||
|
||||
offset = 0
|
||||
|
||||
@@ -1353,9 +1384,22 @@ class FoldPanelBar(wx.Panel):
|
||||
the bottom and the order where the panel originally was placed
|
||||
is restored.
|
||||
"""
|
||||
|
||||
fpbextrastyle = 0
|
||||
|
||||
if self._extraStyle & FPB_SINGLE_FOLD or self._extraStyle & FPB_EXCLUSIVE_FOLD:
|
||||
fpbextrastyle = 1
|
||||
for panel in self._panels:
|
||||
panel.Collapse()
|
||||
|
||||
foldpanel.Expand()
|
||||
self.RefreshPanelsFrom(foldpanel)
|
||||
|
||||
if fpbextrastyle:
|
||||
if self._extraStyle & FPB_EXCLUSIVE_FOLD:
|
||||
self.RepositionCollapsedToBottom()
|
||||
self.RefreshPanelsFrom(self._panels[0])
|
||||
else:
|
||||
self.RefreshPanelsFrom(foldpanel)
|
||||
|
||||
|
||||
def ApplyCaptionStyle(self, foldpanel, cbstyle):
|
||||
|
@@ -3,7 +3,7 @@
|
||||
# Ported From Angelo Mandato C++ Code By:
|
||||
#
|
||||
# Andrea Gavana, @ 27 Mar 2005
|
||||
# Latest Revision: 27 Apr 2005, 22.30 CET
|
||||
# Latest Revision: 05 Nov 2005, 22.30 CET
|
||||
#
|
||||
#
|
||||
# Original Web Site (For The C++ Code):
|
||||
@@ -11,6 +11,8 @@
|
||||
# http://www.spaceblue.com/codedetail.php?CodeID=7
|
||||
#
|
||||
#
|
||||
# Thanks to E. A. Tacao for his nice suggestions and improvements of the code.
|
||||
#
|
||||
# For all kind of problems, requests of enhancements and bug reports, please
|
||||
# write to me at:
|
||||
#
|
||||
@@ -33,7 +35,7 @@ browser window.
|
||||
Special thanks to Robin Dunn for the event binder for the 3 mouse buttons.
|
||||
|
||||
|
||||
Latest Revision: Andrea Gavana @ 11 May 2005, 21.00 CET
|
||||
Latest Revision: Andrea Gavana @ 05 Nov 2005, 22.30 CET
|
||||
|
||||
"""
|
||||
|
||||
@@ -212,15 +214,24 @@ class HyperLinkCtrl(StaticText):
|
||||
self.SetCursor(self._CursorHand)
|
||||
|
||||
if self._EnableRollover:
|
||||
self.SetForegroundColour(self._LinkRolloverColor)
|
||||
fontTemp = self.GetFont()
|
||||
fontTemp.SetUnderlined(self._RolloverUnderline)
|
||||
if self._Bold:
|
||||
fontTemp.SetWeight(wx.BOLD)
|
||||
|
||||
needRefresh = False
|
||||
|
||||
self.SetFont(fontTemp)
|
||||
self.Refresh()
|
||||
if self.GetFont() != fontTemp:
|
||||
self.SetFont(fontTemp)
|
||||
needRefresh = True
|
||||
|
||||
if self.GetForegroundColour() != self._LinkRolloverColor:
|
||||
self.SetForegroundColour(self._LinkRolloverColor)
|
||||
needRefresh = True
|
||||
|
||||
if needRefresh:
|
||||
self.Refresh()
|
||||
|
||||
else:
|
||||
# Restore The Original Cursor
|
||||
self.SetCursor(wx.NullCursor)
|
||||
@@ -301,12 +312,12 @@ class HyperLinkCtrl(StaticText):
|
||||
self.SetForegroundColour(self._LinkColour)
|
||||
fontTemp.SetUnderlined(self._LinkUnderline)
|
||||
|
||||
|
||||
if self._Bold:
|
||||
fontTemp.SetWeight(wx.BOLD)
|
||||
|
||||
self.SetFont(fontTemp)
|
||||
self.Refresh(OnRefresh)
|
||||
if self.GetFont() != fontTemp:
|
||||
self.SetFont(fontTemp)
|
||||
self.Refresh(OnRefresh)
|
||||
|
||||
|
||||
def DisplayError(self, ErrorMessage, ReportErrors=True):
|
||||
|
@@ -696,6 +696,8 @@ Event Handling
|
||||
self._SetKeycodeHandler(WXK_UP, self.IncrementValue)
|
||||
self._SetKeyHandler('-', self._OnChangeSign)
|
||||
|
||||
(Setting a func of None removes any keyhandler for the given key.)
|
||||
|
||||
"Navigation" keys are assumed to change the cursor position, and
|
||||
therefore don't cause automatic motion of the cursor as insertable
|
||||
characters do.
|
||||
@@ -2106,7 +2108,10 @@ class MaskedEditMixin:
|
||||
used by the control. <func> should take the event as argument
|
||||
and return False if no further action on the key is necessary.
|
||||
"""
|
||||
self._keyhandlers[keycode] = func
|
||||
if func:
|
||||
self._keyhandlers[keycode] = func
|
||||
elif self._keyhandlers.has_key(keycode):
|
||||
del self._keyhandlers[keycode]
|
||||
|
||||
|
||||
def _SetKeyHandler(self, char, func):
|
||||
@@ -2126,6 +2131,9 @@ class MaskedEditMixin:
|
||||
self._nav.append(keycode)
|
||||
if handler:
|
||||
self._keyhandlers[keycode] = handler
|
||||
elif self.keyhandlers.has_key(keycode):
|
||||
del self._keyhandlers[keycode]
|
||||
|
||||
|
||||
|
||||
def _AddNavKey(self, char, handler=None):
|
||||
@@ -2154,6 +2162,8 @@ class MaskedEditMixin:
|
||||
self._nav.append(keycode)
|
||||
if func:
|
||||
self._keyhandlers[keycode] = func
|
||||
elif self.keyhandlers.has_key(keycode):
|
||||
del self._keyhandlers[keycode]
|
||||
|
||||
|
||||
def _processMask(self, mask):
|
||||
@@ -2611,6 +2621,12 @@ class MaskedEditMixin:
|
||||
keycode = ord(key)
|
||||
if not self._keyhandlers.has_key(keycode):
|
||||
self._SetKeyHandler(key, self._OnChangeSign)
|
||||
elif self._isInt or self._isFloat:
|
||||
signkeys = ['-', '+', ' ', '(', ')']
|
||||
for key in signkeys:
|
||||
keycode = ord(key)
|
||||
if self._keyhandlers.has_key(keycode) and self._keyhandlers[keycode] == self._OnChangeSign:
|
||||
self._SetKeyHandler(key, None)
|
||||
|
||||
|
||||
|
||||
@@ -2674,14 +2690,15 @@ class MaskedEditMixin:
|
||||
self._SetKeycodeHandler(wx.WXK_UP, self._OnUpNumeric) # (adds "shift" to up arrow, and calls _OnChangeField)
|
||||
|
||||
# On ., truncate contents right of cursor to decimal point (if any)
|
||||
# leaves cusor after decimal point if floating point, otherwise at 0.
|
||||
if not self._keyhandlers.has_key(ord(self._decimalChar)):
|
||||
# leaves cursor after decimal point if floating point, otherwise at 0.
|
||||
if not self._keyhandlers.has_key(ord(self._decimalChar)) or self._keyhandlers[ord(self._decimalChar)] != self._OnDecimalPoint:
|
||||
self._SetKeyHandler(self._decimalChar, self._OnDecimalPoint)
|
||||
if not self._keyhandlers.has_key(ord(self._shiftDecimalChar)):
|
||||
|
||||
if not self._keyhandlers.has_key(ord(self._shiftDecimalChar)) or self._keyhandlers[ord(self._shiftDecimalChar)] != self._OnChangeField:
|
||||
self._SetKeyHandler(self._shiftDecimalChar, self._OnChangeField) # (Shift-'.' == '>' on US keyboards)
|
||||
|
||||
# Allow selective insert of groupchar in numbers:
|
||||
if not self._keyhandlers.has_key(ord(self._fields[0]._groupChar)):
|
||||
if not self._keyhandlers.has_key(ord(self._fields[0]._groupChar)) or self._keyhandlers[ord(self._fields[0]._groupChar)] != self._OnGroupChar:
|
||||
self._SetKeyHandler(self._fields[0]._groupChar, self._OnGroupChar)
|
||||
|
||||
## dbg(indent=0, suspend=0)
|
||||
@@ -3784,13 +3801,17 @@ class MaskedEditMixin:
|
||||
value = self._eraseSelection()
|
||||
integer = self._fields[0]
|
||||
start, end = integer._extent
|
||||
sel_start, sel_to = self._GetSelection()
|
||||
|
||||
#### dbg('adjusted pos:', pos)
|
||||
if chr(key) in ('-','+','(', ')') or (chr(key) == " " and pos == self._signpos):
|
||||
cursign = self._isNeg
|
||||
## dbg('cursign:', cursign)
|
||||
if chr(key) in ('-','(', ')'):
|
||||
self._isNeg = (not self._isNeg) ## flip value
|
||||
if sel_start <= self._signpos:
|
||||
self._isNeg = True
|
||||
else:
|
||||
self._isNeg = (not self._isNeg) ## flip value
|
||||
else:
|
||||
self._isNeg = False
|
||||
## dbg('isNeg?', self._isNeg)
|
||||
@@ -4098,7 +4119,7 @@ class MaskedEditMixin:
|
||||
# first space for sign, and last one if using parens.
|
||||
if( self._signOk
|
||||
and ((pos == self._signpos and key in (ord('-'), ord('+'), ord(' ')) )
|
||||
or self._useParens and pos == self._masklength -1)):
|
||||
or (self._useParens and pos == self._masklength -1))):
|
||||
## dbg('adjusted pos:', pos, indent=0)
|
||||
return pos
|
||||
|
||||
@@ -4106,6 +4127,7 @@ class MaskedEditMixin:
|
||||
field = self._FindField(pos)
|
||||
|
||||
## dbg('field._insertRight?', field._insertRight)
|
||||
## if self._signOk: dbg('self._signpos:', self._signpos)
|
||||
if field._insertRight: # if allow right-insert
|
||||
start, end = field._extent
|
||||
slice = self._GetValue()[start:end].strip()
|
||||
@@ -4140,12 +4162,14 @@ class MaskedEditMixin:
|
||||
## # restore selection
|
||||
## self._SetSelection(sel_start, pos)
|
||||
|
||||
elif self._signOk and sel_start == 0: # if selected to beginning and signed,
|
||||
# if selected to beginning and signed, and not changing sign explicitly:
|
||||
elif self._signOk and sel_start == 0 and key not in (ord('-'), ord('+'), ord(' ')):
|
||||
# adjust to past reserved sign position:
|
||||
pos = self._fields[0]._extent[0]
|
||||
## dbg('adjusting field to ', pos)
|
||||
self._SetInsertionPoint(pos)
|
||||
# restore selection
|
||||
self._SetSelection(pos, sel_to)
|
||||
# but keep original selection, to allow replacement of any sign:
|
||||
self._SetSelection(0, sel_to)
|
||||
else:
|
||||
pass # leave position/selection alone
|
||||
|
||||
@@ -4526,11 +4550,11 @@ class MaskedEditMixin:
|
||||
if self._signOk:
|
||||
text, signpos, right_signpos = self._getSignedValue()
|
||||
## dbg('text: "%s", signpos:' % text, signpos)
|
||||
if text and signpos != self._signpos:
|
||||
self._signpos = signpos
|
||||
if not text or text[signpos] not in ('-','('):
|
||||
self._isNeg = False
|
||||
## dbg('no valid sign found; new sign:', self._isNeg)
|
||||
if text and signpos != self._signpos:
|
||||
self._signpos = signpos
|
||||
elif text and self._valid and not self._isNeg and text[signpos] in ('-', '('):
|
||||
## dbg('setting _isNeg to True')
|
||||
self._isNeg = True
|
||||
@@ -5352,6 +5376,8 @@ class MaskedEditMixin:
|
||||
field = self._FindField(self._GetInsertionPoint())
|
||||
edit_start, edit_end = field._extent
|
||||
if field._selectOnFieldEntry:
|
||||
if self._isFloat or self._isInt and field == self._fields[0]:
|
||||
edit_start = 0
|
||||
self._SetInsertionPoint(edit_start)
|
||||
self._SetSelection(edit_start, edit_end)
|
||||
|
||||
@@ -5368,8 +5394,8 @@ class MaskedEditMixin:
|
||||
|
||||
if integer._selectOnFieldEntry:
|
||||
## dbg('select on field entry:')
|
||||
self._SetInsertionPoint(edit_start)
|
||||
self._SetSelection(edit_start, edit_end)
|
||||
self._SetInsertionPoint(0)
|
||||
self._SetSelection(0, edit_end)
|
||||
|
||||
elif integer._insertRight:
|
||||
## dbg('moving insertion point to end')
|
||||
@@ -6546,6 +6572,22 @@ __i=0
|
||||
|
||||
## CHANGELOG:
|
||||
## ====================
|
||||
## Version 1.9
|
||||
## 1. Now ignores kill focus events when being destroyed.
|
||||
## 2. Added missing call to set insertion point on changing fields.
|
||||
## 3. Modified SetKeyHandler() to accept None as means of removing one.
|
||||
## 4. Fixed keyhandler processing for group and decimal character changes.
|
||||
## 5. Fixed a problem that prevented input into the integer digit of a
|
||||
## integerwidth=1 numctrl, if the current value was 0.
|
||||
## 6. Fixed logic involving processing of "_signOk" flag, to remove default
|
||||
## sign key handlers if false, so that SetAllowNegative(False) in the
|
||||
## NumCtrl works properly.
|
||||
## 7. Fixed selection logic for numeric controls so that if selectOnFieldEntry
|
||||
## is true, and the integer portion of an integer format control is selected
|
||||
## and the sign position is selected, the sign keys will always result in a
|
||||
## negative value, rather than toggling the previous sign.
|
||||
##
|
||||
##
|
||||
## Version 1.8
|
||||
## 1. Fixed bug involving incorrect variable name, causing combobox autocomplete to fail.
|
||||
## 2. Added proper support for unicode version of wxPython
|
||||
|
@@ -762,12 +762,6 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin):
|
||||
if maskededit_kwargs.keys():
|
||||
self.SetCtrlParameters(**maskededit_kwargs)
|
||||
|
||||
# Record end of integer and place cursor there:
|
||||
integerEnd = self._fields[0]._extent[1]
|
||||
self.SetInsertionPoint(0)
|
||||
self.SetInsertionPoint(integerEnd)
|
||||
self.SetSelection(integerEnd, integerEnd)
|
||||
|
||||
# Go ensure all the format codes necessary are present:
|
||||
orig_intformat = intformat = self.GetFieldParameter(0, 'formatcodes')
|
||||
if 'r' not in intformat:
|
||||
@@ -780,6 +774,17 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin):
|
||||
else:
|
||||
self.SetCtrlParameters(formatcodes=intformat)
|
||||
|
||||
# Record end of integer and place cursor there unless selecting, or select entire field:
|
||||
integerStart, integerEnd = self._fields[0]._extent
|
||||
if not self._fields[0]._selectOnFieldEntry:
|
||||
self.SetInsertionPoint(0)
|
||||
self.SetInsertionPoint(integerEnd)
|
||||
self.SetSelection(integerEnd, integerEnd)
|
||||
else:
|
||||
self.SetInsertionPoint(0) # include any sign
|
||||
self.SetSelection(0, integerEnd)
|
||||
|
||||
|
||||
# Set min and max as appropriate:
|
||||
if kwargs.has_key('min'):
|
||||
min = kwargs['min']
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: wxPython.lib.mixins.grid
|
||||
# Name: wx.lib.mixins.grid
|
||||
# Purpose: Helpful mix-in classes for wx.Grid
|
||||
#
|
||||
# Author: Robin Dunn
|
||||
@@ -34,20 +34,15 @@ class GridAutoEditMixin:
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.__enableEdit = 0
|
||||
self.Bind(wx.EVT_IDLE, self.__OnIdle)
|
||||
self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.__OnSelectCell)
|
||||
|
||||
|
||||
def __OnIdle(self, evt):
|
||||
if self.__enableEdit:
|
||||
if self.CanEnableCellControl():
|
||||
self.EnableCellEditControl()
|
||||
self.__enableEdit = 0
|
||||
evt.Skip()
|
||||
def __DoEnableEdit(self):
|
||||
if self.CanEnableCellControl():
|
||||
self.EnableCellEditControl()
|
||||
|
||||
|
||||
def __OnSelectCell(self, evt):
|
||||
self.__enableEdit = 1
|
||||
wx.CallAfter(self.__DoEnableEdit)
|
||||
evt.Skip()
|
||||
|
||||
|
@@ -289,8 +289,7 @@ class Shape(ShapeEvtHandler):
|
||||
|
||||
def Delete(self):
|
||||
if self._parent:
|
||||
i = self._parent.GetChildren().index(self)
|
||||
self._parent.GetChildren(i).remove(self)
|
||||
self._parent.GetChildren().remove(self)
|
||||
|
||||
self.ClearText()
|
||||
self.ClearRegions()
|
||||
@@ -301,7 +300,8 @@ class Shape(ShapeEvtHandler):
|
||||
if self._canvas:
|
||||
self.RemoveFromCanvas(self._canvas)
|
||||
|
||||
self.GetEventHandler().OnDelete()
|
||||
if self.GetEventHandler():
|
||||
self.GetEventHandler().OnDelete()
|
||||
self._eventHandler = None
|
||||
|
||||
def __del__(self):
|
||||
|
@@ -15,14 +15,15 @@
|
||||
# add index to data list after parsing total pages for paging
|
||||
#----------------------------------------------------------------------------
|
||||
# 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net)
|
||||
#
|
||||
# o 2.5 compatability update.
|
||||
#
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# 11/23/2004 - Vernon Cole (wnvcole@peppermillcas.com)
|
||||
# o Generalize for non-2-dimensional sequences and non-text data
|
||||
# (can use as a simple text printer by supplying a list of strings.)
|
||||
# o Add a small _main_ for self test
|
||||
|
||||
import copy
|
||||
import os
|
||||
import sys
|
||||
|
||||
import types
|
||||
import wx
|
||||
|
||||
class PrintBase:
|
||||
@@ -268,10 +269,47 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase):
|
||||
pos_x = self.left_margin * self.pwidth + self.horizontal_offset # left margin
|
||||
self.column.append(pos_x)
|
||||
|
||||
#module logic expects two dimensional data -- fix input if needed
|
||||
if isinstance(self.data,types.StringTypes):
|
||||
self.data = [[copy.copy(self.data)]] # a string becomes a single cell
|
||||
try:
|
||||
rows = len(self.data)
|
||||
except TypeError:
|
||||
self.data = [[str(self.data)]] # a non-iterable becomes a single cell
|
||||
rows = 1
|
||||
first_value = self.data[0]
|
||||
|
||||
if isinstance(first_value, types.StringTypes): # a sequence of strings
|
||||
if self.label == [] and self.set_column == []:
|
||||
data = []
|
||||
for x in self.data: #becomes one column
|
||||
data.append([x])
|
||||
else:
|
||||
data = [self.data] #becames one row
|
||||
self.data = data
|
||||
first_value = data[0]
|
||||
try:
|
||||
column_total = len(first_value)
|
||||
except TypeError: # a sequence of non-iterables
|
||||
if self.label == [] and self.set_column == []:
|
||||
data = [] #becomes one column
|
||||
for x in self.data:
|
||||
data.append([str(x)])
|
||||
column_total = 1
|
||||
else:
|
||||
data = [self.data] #becomes one row
|
||||
column_total = len(self.data)
|
||||
self.data = data
|
||||
first_value = data[0]
|
||||
|
||||
if self.set_column == []:
|
||||
table_width = self.page_width - self.left_margin - self.right_margin
|
||||
width = table_width/(len(self.label))
|
||||
for val in self.label:
|
||||
if self.label == []:
|
||||
temp = first_value
|
||||
else:
|
||||
temp = self.label
|
||||
width = table_width/(len(temp))
|
||||
for val in temp:
|
||||
column_width = width * self.pwidth
|
||||
pos_x = pos_x + column_width
|
||||
self.column.append(pos_x) # position of each column
|
||||
@@ -290,13 +328,10 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase):
|
||||
print "Column Settings Incorrect", "\nColumn Value: " + str(self.column), "\nLabel Value: " + str(self.label)
|
||||
return
|
||||
|
||||
first_value = self.data[0]
|
||||
column_total = len(first_value)
|
||||
if column_total != len(self.column) -1:
|
||||
print "Column Settings Incorrect", first_value, self.column
|
||||
print "Cannot fit", first_value, 'in', len(self.column)-1, 'columns.'
|
||||
return
|
||||
|
||||
col = 0
|
||||
for col in range(column_total):
|
||||
try:
|
||||
align = set_column_align[col] # check if custom column alignment
|
||||
@@ -314,10 +349,8 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase):
|
||||
colour = set_column_txtcolour[col] # check if custom column text colour
|
||||
except:
|
||||
colour = self.GetFontColour(self.parent.text_font)
|
||||
|
||||
self.column_txtcolour.append(colour)
|
||||
|
||||
col = col + 1
|
||||
|
||||
def SetPointAdjust(self):
|
||||
f = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL) # setup using 10 point
|
||||
@@ -526,12 +559,14 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase):
|
||||
self.col = 0
|
||||
max_y = 0
|
||||
for vtxt in row_val:
|
||||
if not isinstance(vtxt,types.StringTypes):
|
||||
vtxt = str(vtxt)
|
||||
self.region = self.column[self.col+1] - self.column[self.col]
|
||||
self.indent = self.column[self.col]
|
||||
self.align = self.column_align[self.col]
|
||||
|
||||
fcolour = self.column_txtcolour[self.col] # set font colour
|
||||
celltext = self.GetCellText(self.data_cnt, self.col)
|
||||
celltext = self.GetCellTextColour(self.data_cnt, self.col)
|
||||
if celltext is not None:
|
||||
fcolour = celltext # override the column colour
|
||||
|
||||
@@ -554,7 +589,7 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase):
|
||||
except:
|
||||
return None
|
||||
|
||||
def GetCellText(self, row, col): # check if custom colour defined for the cell text
|
||||
def GetCellTextColour(self, row, col): # check if custom colour defined for the cell text
|
||||
try:
|
||||
set = self.cell_text[row]
|
||||
except:
|
||||
@@ -570,7 +605,8 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase):
|
||||
self.DrawColumns() # draw all vertical lines
|
||||
|
||||
def DrawGridLine(self):
|
||||
if self.draw == True:
|
||||
if self.draw == True \
|
||||
and len(self.column) > 2: #supress grid lines if only one column
|
||||
try:
|
||||
size = self.row_line_size[self.data_cnt]
|
||||
except:
|
||||
@@ -588,7 +624,8 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase):
|
||||
self.DC.DrawLine(self.column[0], y_out, self.end_x, y_out)
|
||||
|
||||
def DrawColumns(self):
|
||||
if self.draw == True:
|
||||
if self.draw == True \
|
||||
and len(self.column) > 2: #surpress grid line if only one column
|
||||
col = 0
|
||||
for val in self.column:
|
||||
try:
|
||||
@@ -720,8 +757,8 @@ class PrintTable:
|
||||
self.footer_type = "Pageof"
|
||||
|
||||
def SetMargins(self):
|
||||
self.left_margin = 1.0
|
||||
self.right_margin = 1.0 # only used if no column sizes
|
||||
self.left_margin = 0.5
|
||||
self.right_margin = 0.5 # only used if no column sizes
|
||||
|
||||
self.top_margin = 0.8
|
||||
self.bottom_margin = 1.0
|
||||
@@ -869,15 +906,15 @@ class PrintTable:
|
||||
self.footer.append(set)
|
||||
|
||||
def Preview(self):
|
||||
data = wx.PrintDialogData(self.printData)
|
||||
printout = SetPrintout(self)
|
||||
printout2 = SetPrintout(self)
|
||||
self.preview = wx.PrintPreview(printout, printout2, self.printData)
|
||||
self.preview = wx.PrintPreview(printout, printout2, data)
|
||||
if not self.preview.Ok():
|
||||
wxMessageBox("There was a problem printing!", "Printing", wx.OK)
|
||||
return
|
||||
|
||||
self.preview.SetZoom(60) # initial zoom value
|
||||
|
||||
frame = wx.PreviewFrame(self.preview, self.parentFrame, "Print preview")
|
||||
|
||||
frame.Initialize()
|
||||
@@ -887,14 +924,13 @@ class PrintTable:
|
||||
frame.Show(True)
|
||||
|
||||
def Print(self):
|
||||
pdd = wx.PrintDialogData()
|
||||
pdd.SetPrintData(self.printData)
|
||||
pdd = wx.PrintDialogData(self.printData)
|
||||
printer = wx.Printer(pdd)
|
||||
printout = SetPrintout(self)
|
||||
if not printer.Print(self.parentFrame, printout):
|
||||
wx.MessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wx.OK)
|
||||
else:
|
||||
self.printData = printer.GetPrintDialogData().GetPrintData()
|
||||
self.printData = wx.PrintData( printer.GetPrintDialogData().GetPrintData() )
|
||||
printout.Destroy()
|
||||
|
||||
def DoDrawing(self, DC):
|
||||
@@ -1091,8 +1127,23 @@ class SetPrintout(wx.Printout):
|
||||
self.canvas.DoDrawing(dc)
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = wx.PySimpleApp()
|
||||
frame = wx.Frame(None, -1, "Dummy wx frame for testing printout.py")
|
||||
frame.Show(True)
|
||||
ptbl = PrintTable(frame)
|
||||
ptbl.SetHeader('This is the test HEADER')
|
||||
# a single sequence will print out as a single column with no borders ...
|
||||
ptbl.data = (
|
||||
'This is the first line of text.',
|
||||
'This is the second line\nand the third. The fourth will be the number "4.0".',
|
||||
04.00,
|
||||
'This is the fifth line, but by design it is too long to fit in the width of a standard'\
|
||||
' page, so it will be forced to wrap around in order to fit without having '\
|
||||
'some of its verbose verbage truncated.',
|
||||
'Here we have the final line.'
|
||||
)
|
||||
#... but, if labels or columns are defined, a single sequence will print out as a single row
|
||||
##ptbl.label = ('One','Two','Three','Four','5')
|
||||
ptbl.Preview()
|
||||
app.MainLoop()
|
||||
|
@@ -194,8 +194,16 @@ class DocFrameMixIn:
|
||||
Saves all of the currently open documents.
|
||||
"""
|
||||
docs = wx.GetApp().GetDocumentManager().GetDocuments()
|
||||
|
||||
# save child documents first
|
||||
for doc in docs:
|
||||
doc.Save()
|
||||
if isinstance(doc, wx.lib.pydocview.ChildDocument):
|
||||
doc.Save()
|
||||
|
||||
# save parent and other documents later
|
||||
for doc in docs:
|
||||
if not isinstance(doc, wx.lib.pydocview.ChildDocument):
|
||||
doc.Save()
|
||||
|
||||
|
||||
def OnAbout(self, event):
|
||||
@@ -371,12 +379,13 @@ class DocMDIParentFrameMixIn:
|
||||
Create the specified embedded windows around the edges of the frame.
|
||||
"""
|
||||
frameSize = self.GetSize() # TODO: GetClientWindow.GetSize is still returning 0,0 since the frame isn't fully constructed yet, so using full frame size
|
||||
defaultHSize = int(frameSize[0] / 6)
|
||||
defaultVSize = int(frameSize[1] / 7)
|
||||
MIN_SIZE = 20
|
||||
defaultHSize = max(MIN_SIZE, int(frameSize[0] / 6))
|
||||
defaultVSize = max(MIN_SIZE, int(frameSize[1] / 7))
|
||||
defaultSubVSize = int(frameSize[1] / 2)
|
||||
config = wx.ConfigBase_Get()
|
||||
if windows & (EMBEDDED_WINDOW_LEFT | EMBEDDED_WINDOW_TOPLEFT | EMBEDDED_WINDOW_BOTTOMLEFT):
|
||||
self._leftEmbWindow = self._CreateEmbeddedWindow(self, (config.ReadInt("MDIEmbedLeftSize", defaultHSize), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_LEFT, visible = config.ReadInt("MDIEmbedLeftVisible", 1), sash = wx.SASH_RIGHT)
|
||||
self._leftEmbWindow = self._CreateEmbeddedWindow(self, (max(MIN_SIZE,config.ReadInt("MDIEmbedLeftSize", defaultHSize)), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_LEFT, visible = config.ReadInt("MDIEmbedLeftVisible", 1), sash = wx.SASH_RIGHT)
|
||||
else:
|
||||
self._leftEmbWindow = None
|
||||
if windows & EMBEDDED_WINDOW_TOPLEFT:
|
||||
@@ -388,7 +397,7 @@ class DocMDIParentFrameMixIn:
|
||||
else:
|
||||
self._bottomLeftEmbWindow = None
|
||||
if windows & (EMBEDDED_WINDOW_RIGHT | EMBEDDED_WINDOW_TOPRIGHT | EMBEDDED_WINDOW_BOTTOMRIGHT):
|
||||
self._rightEmbWindow = self._CreateEmbeddedWindow(self, (config.ReadInt("MDIEmbedRightSize", defaultHSize), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_RIGHT, visible = config.ReadInt("MDIEmbedRightVisible", 1), sash = wx.SASH_LEFT)
|
||||
self._rightEmbWindow = self._CreateEmbeddedWindow(self, (max(MIN_SIZE,config.ReadInt("MDIEmbedRightSize", defaultHSize)), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_RIGHT, visible = config.ReadInt("MDIEmbedRightVisible", 1), sash = wx.SASH_LEFT)
|
||||
else:
|
||||
self._rightEmbWindow = None
|
||||
if windows & EMBEDDED_WINDOW_TOPRIGHT:
|
||||
@@ -400,11 +409,11 @@ class DocMDIParentFrameMixIn:
|
||||
else:
|
||||
self._bottomRightEmbWindow = None
|
||||
if windows & EMBEDDED_WINDOW_TOP:
|
||||
self._topEmbWindow = self._CreateEmbeddedWindow(self, (-1, config.ReadInt("MDIEmbedTopSize", defaultVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_TOP, visible = config.ReadInt("MDIEmbedTopVisible", 1), sash = wx.SASH_BOTTOM)
|
||||
self._topEmbWindow = self._CreateEmbeddedWindow(self, (-1, max(MIN_SIZE,config.ReadInt("MDIEmbedTopSize", defaultVSize))), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_TOP, visible = config.ReadInt("MDIEmbedTopVisible", 1), sash = wx.SASH_BOTTOM)
|
||||
else:
|
||||
self._topEmbWindow = None
|
||||
if windows & EMBEDDED_WINDOW_BOTTOM:
|
||||
self._bottomEmbWindow = self._CreateEmbeddedWindow(self, (-1, config.ReadInt("MDIEmbedBottomSize", defaultVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomVisible", 1), sash = wx.SASH_TOP)
|
||||
self._bottomEmbWindow = self._CreateEmbeddedWindow(self, (-1, max(MIN_SIZE,config.ReadInt("MDIEmbedBottomSize", defaultVSize))), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomVisible", 1), sash = wx.SASH_TOP)
|
||||
else:
|
||||
self._bottomEmbWindow = None
|
||||
|
||||
@@ -572,11 +581,11 @@ class DocMDIParentFrameMixIn:
|
||||
self._LayoutFrame()
|
||||
|
||||
|
||||
def HideEmbeddedWindow(self):
|
||||
def HideEmbeddedWindow(self, window):
|
||||
"""
|
||||
Hides the embedded window specified by the embedded window location constant.
|
||||
"""
|
||||
self.ShowEmbeddedWindow(show = False)
|
||||
self.ShowEmbeddedWindow(window, show=False)
|
||||
|
||||
|
||||
class DocTabbedChildFrame(wx.Panel):
|
||||
@@ -645,7 +654,7 @@ class DocTabbedChildFrame(wx.Panel):
|
||||
"""
|
||||
Returns the frame's title.
|
||||
"""
|
||||
wx.GetApp().GetTopWindow().GetNotebookPageTitle(self)
|
||||
return wx.GetApp().GetTopWindow().GetNotebookPageTitle(self)
|
||||
|
||||
|
||||
def SetTitle(self, title):
|
||||
@@ -769,11 +778,22 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
|
||||
"""
|
||||
Creates the notebook to use for the tabbed document interface.
|
||||
"""
|
||||
self._notebook = wx.Notebook(self, wx.NewId())
|
||||
if wx.Platform != "__WXMAC__":
|
||||
self._notebook = wx.Notebook(self, wx.NewId())
|
||||
else:
|
||||
self._notebook = wx.Listbook(self, wx.NewId(), style=wx.LB_LEFT)
|
||||
# self._notebook.SetSizer(wx.NotebookSizer(self._notebook))
|
||||
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged)
|
||||
if wx.Platform != "__WXMAC__":
|
||||
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged)
|
||||
else:
|
||||
wx.EVT_LISTBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged)
|
||||
wx.EVT_RIGHT_DOWN(self._notebook, self.OnNotebookRightClick)
|
||||
wx.EVT_MOTION(self._notebook, self.OnNotebookMouseOver)
|
||||
wx.EVT_MIDDLE_DOWN(self._notebook, self.OnNotebookMiddleClick)
|
||||
|
||||
# wxBug: wx.Listbook does not implement HitTest the same way wx.Notebook
|
||||
# does, so for now don't fire MouseOver events.
|
||||
if wx.Platform != "__WXMAC__":
|
||||
wx.EVT_MOTION(self._notebook, self.OnNotebookMouseOver)
|
||||
|
||||
templates = wx.GetApp().GetDocumentManager().GetTemplates()
|
||||
iconList = wx.ImageList(16, 16, initialCount = len(templates))
|
||||
@@ -829,6 +849,7 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
|
||||
def OnNotebookMouseOver(self, event):
|
||||
# wxBug: On Windows XP the tooltips don't automatically disappear when you move the mouse and it is on a notebook tab, has nothing to do with this code!!!
|
||||
index, type = self._notebook.HitTest(event.GetPosition())
|
||||
|
||||
if index > -1:
|
||||
doc = self._notebook.GetPage(index).GetView().GetDocument()
|
||||
self._notebook.SetToolTip(wx.ToolTip(doc.GetFilename()))
|
||||
@@ -837,6 +858,17 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
|
||||
event.Skip()
|
||||
|
||||
|
||||
def OnNotebookMiddleClick(self, event):
|
||||
"""
|
||||
Handles middle clicks for the notebook, closing the document whose tab was
|
||||
clicked on.
|
||||
"""
|
||||
index, type = self._notebook.HitTest(event.GetPosition())
|
||||
if index > -1:
|
||||
doc = self._notebook.GetPage(index).GetView().GetDocument()
|
||||
if doc:
|
||||
doc.DeleteAllViews()
|
||||
|
||||
def OnNotebookRightClick(self, event):
|
||||
"""
|
||||
Handles right clicks for the notebook, enabling users to either close
|
||||
@@ -902,9 +934,19 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
|
||||
break
|
||||
if not found:
|
||||
self._notebook.SetPageImage(index, self._blankIconIndex)
|
||||
|
||||
# wxBug: the wxListbook used on Mac needs its tabs list resized
|
||||
# whenever a new tab is added, but the only way to do this is
|
||||
# to resize the entire control
|
||||
if wx.Platform == "__WXMAC__":
|
||||
content_size = self._notebook.GetSize()
|
||||
self._notebook.SetSize((content_size.x+2, -1))
|
||||
self._notebook.SetSize((content_size.x, -1))
|
||||
|
||||
self._notebook.Layout()
|
||||
|
||||
|
||||
|
||||
def RemoveNotebookPage(self, panel):
|
||||
"""
|
||||
Removes a document page from the notebook.
|
||||
@@ -925,7 +967,7 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
|
||||
|
||||
|
||||
def GetNotebookPageTitle(self, panel):
|
||||
self._notebook.GetPageText(self.GetNotebookPageIndex(panel))
|
||||
return self._notebook.GetPageText(self.GetNotebookPageIndex(panel))
|
||||
|
||||
|
||||
def SetNotebookPageTitle(self, panel, title):
|
||||
@@ -1296,7 +1338,7 @@ class DocOptionsService(DocService):
|
||||
DocService.__init__(self)
|
||||
self.ClearOptionsPanels()
|
||||
self._supportedModes = supportedModes
|
||||
self._toolOptionsID = wx.NewId()
|
||||
self._toolOptionsID = wx.ID_PREFERENCES
|
||||
if showGeneralOptions:
|
||||
self.AddOptionsPanel(GeneralOptionsPanel)
|
||||
|
||||
@@ -1370,6 +1412,7 @@ class DocOptionsService(DocService):
|
||||
if len(self._optionsPanels) == 0:
|
||||
return
|
||||
optionsDialog = OptionsDialog(wx.GetApp().GetTopWindow(), self._optionsPanels, self._docManager)
|
||||
optionsDialog.CenterOnParent()
|
||||
if optionsDialog.ShowModal() == wx.ID_OK:
|
||||
optionsDialog.OnOK(optionsDialog) # wxBug: wxDialog should be calling this automatically but doesn't
|
||||
optionsDialog.Destroy()
|
||||
@@ -1386,8 +1429,8 @@ class OptionsDialog(wx.Dialog):
|
||||
"""
|
||||
Initializes the options dialog with a notebook page that contains new
|
||||
instances of the passed optionsPanelClasses.
|
||||
"""
|
||||
wx.Dialog.__init__(self, parent, -1, _("Options"), size = (570, 365))
|
||||
"""
|
||||
wx.Dialog.__init__(self, parent, -1, _("Options"))
|
||||
|
||||
self._optionsPanels = []
|
||||
self._docManager = docManager
|
||||
@@ -1397,16 +1440,54 @@ class OptionsDialog(wx.Dialog):
|
||||
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
optionsNotebook = wx.Notebook(self, -1, size=(560, 325))
|
||||
if wx.Platform == "__WXMAC__":
|
||||
optionsNotebook = wx.Listbook(self, wx.NewId(), style=wx.LB_DEFAULT)
|
||||
else:
|
||||
optionsNotebook = wx.Notebook(self, wx.NewId(), style=wx.NB_MULTILINE) # NB_MULTILINE is windows platform only
|
||||
sizer.Add(optionsNotebook, 0, wx.ALL | wx.EXPAND, SPACE)
|
||||
for optionsPanelClass in optionsPanelClasses:
|
||||
optionsPanel = optionsPanelClass(optionsNotebook, -1)
|
||||
self._optionsPanels.append(optionsPanel)
|
||||
|
||||
if wx.Platform == "__WXMAC__":
|
||||
iconList = wx.ImageList(16, 16, initialCount = len(optionsPanelClasses))
|
||||
self._iconIndexLookup = []
|
||||
|
||||
for optionsPanelClass in optionsPanelClasses:
|
||||
optionsPanel = optionsPanelClass(optionsNotebook, -1)
|
||||
self._optionsPanels.append(optionsPanel)
|
||||
|
||||
# We need to populate the image list before setting notebook images
|
||||
if hasattr(optionsPanel, "GetIcon"):
|
||||
icon = optionsPanel.GetIcon()
|
||||
else:
|
||||
icon = None
|
||||
if icon:
|
||||
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((optionsPanel, iconIndex))
|
||||
|
||||
else:
|
||||
# use -1 to represent that this panel has no icon
|
||||
self._iconIndexLookup.append((optionsPanel, -1))
|
||||
|
||||
optionsNotebook.AssignImageList(iconList)
|
||||
|
||||
# Add icons to notebook
|
||||
for index in range(0, len(optionsPanelClasses)-1):
|
||||
iconIndex = self._iconIndexLookup[index][1]
|
||||
if iconIndex >= 0:
|
||||
optionsNotebook.SetPageImage(index, iconIndex)
|
||||
else:
|
||||
for optionsPanelClass in optionsPanelClasses:
|
||||
optionsPanel = optionsPanelClass(optionsNotebook, -1)
|
||||
self._optionsPanels.append(optionsPanel)
|
||||
|
||||
sizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE)
|
||||
self.SetSizer(sizer)
|
||||
self.Layout()
|
||||
if wx.Platform != '__WXMAC__' or len(optionsPanelClasses) < 6: # wxBug: Notebook tabs are truncated and user can't get to them on the Mac
|
||||
self.Fit()
|
||||
self.Fit()
|
||||
wx.CallAfter(self.DoRefresh)
|
||||
|
||||
|
||||
@@ -1512,6 +1593,11 @@ class GeneralOptionsPanel(wx.Panel):
|
||||
config.WriteInt("UseWinMDI", (self._documentRadioBox.GetStringSelection() == self._winMdiChoice))
|
||||
|
||||
|
||||
def GetIcon(self):
|
||||
""" Return icon for options panel on the Mac. """
|
||||
return wx.GetApp().GetDefaultIcon()
|
||||
|
||||
|
||||
class DocApp(wx.PySimpleApp):
|
||||
"""
|
||||
The DocApp class serves as the base class for pydocview applications and offers
|
||||
@@ -1587,7 +1673,16 @@ class DocApp(wx.PySimpleApp):
|
||||
frame = wx.lib.pydocview.DocMDIParentFrame(docManager, None, -1, self.GetAppName())
|
||||
frame.Show(True)
|
||||
|
||||
|
||||
def MacOpenFile(self, filename):
|
||||
self.GetDocumentManager().CreateDocument(os.path.normpath(filename), wx.lib.docview.DOC_SILENT)
|
||||
|
||||
# force display of running app
|
||||
topWindow = wx.GetApp().GetTopWindow()
|
||||
if topWindow.IsIconized():
|
||||
topWindow.Iconize(False)
|
||||
else:
|
||||
topWindow.Raise()
|
||||
|
||||
def DoBackgroundListenAndLoad(self):
|
||||
"""
|
||||
Open any files specified in the given command line argument passed in via shared memory
|
||||
@@ -1602,7 +1697,7 @@ class DocApp(wx.PySimpleApp):
|
||||
self._sharedMemory.flush()
|
||||
args = pickle.loads(data)
|
||||
for arg in args:
|
||||
if arg[0] != '/' and arg[0] != '-' and os.path.exists(arg):
|
||||
if (wx.Platform != "__WXMSW__" or arg[0] != "/") and arg[0] != '-' and os.path.exists(arg):
|
||||
self.GetDocumentManager().CreateDocument(os.path.normpath(arg), wx.lib.docview.DOC_SILENT)
|
||||
|
||||
# force display of running app
|
||||
@@ -1623,7 +1718,7 @@ class DocApp(wx.PySimpleApp):
|
||||
"""
|
||||
args = sys.argv[1:]
|
||||
for arg in args:
|
||||
if arg[0] != '/' and arg[0] != '-' and os.path.exists(arg):
|
||||
if (wx.Platform != "__WXMSW__" or arg[0] != "/") and arg[0] != '-' and os.path.exists(arg):
|
||||
self.GetDocumentManager().CreateDocument(os.path.normpath(arg), wx.lib.docview.DOC_SILENT)
|
||||
|
||||
|
||||
@@ -2022,7 +2117,7 @@ class DocApp(wx.PySimpleApp):
|
||||
splash_bmp = image
|
||||
else:
|
||||
splash_bmp = wx.Image(image).ConvertToBitmap()
|
||||
self._splash = wx.SplashScreen(splash_bmp,wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_NO_TIMEOUT,0, None, -1)
|
||||
self._splash = wx.SplashScreen(splash_bmp, wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_NO_TIMEOUT, 0, None, -1, style=wx.SIMPLE_BORDER|wx.FRAME_NO_TASKBAR)
|
||||
self._splash.Show()
|
||||
|
||||
|
||||
@@ -2351,7 +2446,7 @@ class AboutService(DocService):
|
||||
dlg = self._dlg(wx.GetApp().GetTopWindow(), self._image)
|
||||
else:
|
||||
dlg = self._dlg(wx.GetApp().GetTopWindow())
|
||||
dlg.CenterOnScreen()
|
||||
dlg.CenterOnParent()
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
@@ -2384,7 +2479,6 @@ class AboutDialog(wx.Dialog):
|
||||
sizer.Add(btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
|
||||
|
||||
self.SetSizer(sizer)
|
||||
self.SetAutoLayout(True)
|
||||
sizer.Fit(self)
|
||||
|
||||
|
||||
@@ -2457,6 +2551,7 @@ class FilePropertiesService(DocService):
|
||||
filename = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
|
||||
|
||||
filePropertiesDialog = FilePropertiesDialog(wx.GetApp().GetTopWindow(), filename)
|
||||
filePropertiesDialog.CenterOnParent()
|
||||
if filePropertiesDialog.ShowModal() == wx.ID_OK:
|
||||
pass # Handle OK
|
||||
filePropertiesDialog.Destroy()
|
||||
@@ -2928,13 +3023,20 @@ import cStringIO
|
||||
#----------------------------------------------------------------------
|
||||
def getNewData():
|
||||
return \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x00[IDAT8\x8d\xed\x93\xb1\n\x001\x08C\x13{\xff\xff\xc7mn\xb8El\x91\x16\
|
||||
\x97\x0e\x97M\x90\x97\x88JZCE\x8f/4\xba\xb2fZc\n\x00\x00i\xcd \t\x8d\xae\x08\
|
||||
\xb1\xad\x9c\x0e\x1eS\x1e\x01\xc8\xcf\xdcC\xa6\x112\xf7\x08:N\xb0\xd2\x0f\
|
||||
\xb8\x010\xdd\x81\xdf\xf1\x8eX\xfd\xc6\xf2\x08/D\xbd\x19(\xc8\xa5\xd9\xfa\
|
||||
\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x01\x04IDAT8\x8d\xa5\x93\xbdj\x02A\x10\xc7\x7f{gme\xe5c\xe4\t\x82\x85\
|
||||
\x85\x85oa\xe5+\xd8Z\xd8'e\xfa\x80\xd8\xd8X\x19R\xc4\x07\x90\x04\xd1J\x08\
|
||||
\x17\x0cr\\V\xe1\xe4\xfc\x80\xb58\xf7\xd8\xbd\x0f\xa280\xec\xec2\xbf\xff\xce\
|
||||
\xcc\xb2B8.\xf7X\xc9\xdc|L\x97J\xc7\xbe\x0c\x01\xf0\xd6\x01\x00RFtZu\x91Q\
|
||||
\x10\x8e\x9b\xf8\xe4\xf3[-w*\xf1\xafm\xec\xcf\x83\x89\x1a\xad\x94\xea\xbe\
|
||||
\x8c\x95\x99/\x1c\x17\xe7\xdaR\xcb%xh\xd4hw_\x95yn\xb5\xe0\xcb\x90\xea%\x0eO\
|
||||
\xf1\xba\xd9\xc7\xe5\xbf\x0f\xdfX]\xda)\x140A\r\x03<6klO\xf0w\x84~\xef\xc9\
|
||||
\xca/lA\xc3@\x02\xe7\x99U\x81\xb7\x0e\xa8\xec\xed\x04\x13\xde\x1c\xfe\x11\
|
||||
\x902\xb2@\xc8\xc2\x8b\xd9\xbcX\xc0\x045\xac\xc1 Jg\xe6\x08\xe8)\xa7o\xd5\
|
||||
\xb0\xbf\xcb\nd\x86x\x0b\x9c+p\x0b\x0c\xa9\x16~\xbc_\xeb\x9d\xd3\x03\xcb3q\
|
||||
\xefo\xbc\xfa/\x14\xd9\x19\x1f\xfb\x8aa\x87\xf2\xf7\x16\x00\x00\x00\x00IEND\
|
||||
\xaeB`\x82"
|
||||
|
||||
def getNewBitmap():
|
||||
return BitmapFromImage(getNewImage())
|
||||
@@ -2948,13 +3050,21 @@ def getOpenData():
|
||||
return \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x00\x95IDAT8\x8d\xa5\x92\xc1\x12\x03!\x08C\x13\xec\x87\xfb\xe3B\x0f.]\
|
||||
\xb0\x8e[m.\xea\x0c/\x06\x06R\n\xfe\xd1\xeb\xd7B\xd5f~\x17)\xdc2Pm\x16!\x7f\
|
||||
\xab6\xe3i\x0b\x9e\xe8\x93\xc0BD\x86\xdfV0\x00\x90R`\xda\xcc\x0c\x00\x0c\x00\
|
||||
\xc1\x05>\x9a\x87\x19t\x180\x981\xbd\xfd\xe4\xc4Y\x82\xf7\x14\xca\xe7\xb7\
|
||||
\xa6\t\xee6\x1c\xba\xe18\xab\xc1 \xc3\xb5N?L\xaa5\xb5\xd0\x8dw`JaJ\xb0\x0b\
|
||||
\x03!\xc1\t\xdc\xb9k\x0f\x9e\xd1\x0b\x18\xf6\xe0x\x95]\xf2\\\xb2\xd6\x1b}\
|
||||
\x14BL\xb9{t\xc7\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x01gIDAT8\x8d\xa5\x93=KBQ\x18\xc7\x7fWo)5\x1594DC\x04!\xd1\x0bM-\xd1\
|
||||
\xd0T\x81\xba\xb7\xf8\x01Z\x9a\xdb\xfa\x08AC\x10\x0e\xb5\x86\xbaDC`CMaN\xd9\
|
||||
\x0bQF7\xe2z\xc1kz\xcd\xc4\x97\xd3\xa0\xde\xbc\\oE\xfd\xa7s\xce\xf3\xfc\x7f\
|
||||
\xe7y\xce\x8b$\xb9\xdc\xfcG2@\xf1bC\x00\x18%\xcd\x12\x1c^\xdc\x97~\x04\x18\
|
||||
\xe7K\xa2of\x05\x80\xfe\x8e@\xc3\xc8\xf2zJ\x13\xac+\xe6\xfax(a\x81\xca\xa2w\
|
||||
\x8a\x86\x91\x85\xaanE\xf7\x0c\xe0\xf3\xcf\x03P}|3\x97\x93\x11U\xcc\x85\xd3&\
|
||||
D\xee\xf4\x88\xb2\xfa5)\xab(\x99"\x00\xb9\x87c\x0b;\x19\xf1\x0b\x80\xb9pZ\
|
||||
\xb2\x00\x00\xd3T\xcb\xa5\x00(\xe4Uf\xd7\xb6m\xbd\xa7\x0e\xd6\x89\xc7\xa2\
|
||||
\xc2\x04<_\xdf\xe3\x15\x1a\xb5V\xbfc\xab\x9b6S7\xc9FIC\xbf\xcb\xe0\x15\x1a\
|
||||
\xbe\xe9e|\xad@C\xbfu4\x9d\xecnQ\x99\xdci\x02\x00\xea\x1f\x1a\x15]a\xa8pcK\
|
||||
\xae\xbf?9\x82\x02\xc1\x90$\x1b\xba\x82<\xe8\xeb\x9a\\\xcb)\xdd|\x14r\x15<\
|
||||
\xad\xb1\xab\x99\x98bdb\xd4q\xa7\xefd\xbb\x05\xa7\xdd\x8f\x0e/\x9d\x01\x85\
|
||||
\xbc\nX+8K\\\x99\xe5\x02x\x16\xf6\xba\x02$\xc9\xe56\x1fF[\xda\x8bn\x9er\xa7\
|
||||
\x02\xc1\x90\xedoH\xed\xdf\x18\x8fE\xc5o\x0c\x8e\x80\xbf\xea\x13\xa8\x18\x89\
|
||||
5\xe7L\xb3:\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getOpenBitmap():
|
||||
return BitmapFromImage(getOpenImage())
|
||||
@@ -2968,13 +3078,20 @@ def getCopyData():
|
||||
return \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x00\x9fIDAT8\x8d\xa5\x93\xdb\x0e\x830\x0cC\xed\x84\xdfF\xeb\xb4\xef\xa6\
|
||||
\xde\x030z\t\x94\tK\x91z\xcb\x01\xbb*i\x8e\'\x9a\x00@yQ\xb4Is\x8e\x00\xb6\
|
||||
\x0f$Uu\x05\x0e\x01\x91$\r!\xa49\x94\x17I\x02\xc9_\xe3:Nq\x93}XL|\xeb\xe9\
|
||||
\x05\xa4p\rH\xa29h^[ Y\xd5\xb9\xb5\x17\x94gu\x19DA\x96\xe0c\xfe^\xcf\xe7Y\
|
||||
\x95\x05\x00M\xf5\x16Z;\x7f\xfdAd\xcf\xee\x1cj\xc1%|\xdan"LL\x19\xda\xe1}\
|
||||
\x90:\x00#\x95_l5\x04\xec\x89\x9f\xef?|\x8d\x97o\xe1\x8e\xbeJ\xfc\xb1\xde\
|
||||
\xea\xf8\xb9\xc4\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x01_IDAT8\x8d\x8d\x92\xbfK\x02a\x18\xc7?w\xfa\'\xd8\xd0\xa0\xe4v\xd0$M\
|
||||
\x8dB\x11\x11\xa5B\x7f@C\xd0RC{k8E\x834\xb45\n\x15\xfd\x80hhh\xd2\xadI\x82\
|
||||
\xa4!\xb8\x84\xca\xd4;\xa5\xf2R\xe1m\xd0\xfb\xf5^\x1e~\xe1\xe5^\x9e{\xbe\x9f\
|
||||
\xf7\xfb\xbcwJ\xa9\xa2\x0bFj\x98\xdf\x00\xd4\xea\x06\x00f\xdbbosQ!L\xa5\x8a.\
|
||||
\xaa_"\xb0\x8e\xce\xcb\xa2\xfc)\xc4N\xfeT(j\x84\xb1\xabT\xd1E,\x19w\x80\x8d\
|
||||
\x97Ww?A"\xd5n\xf2*\x96\x8c\x13K\xc6\xd1R\x1aZJcai\x1e\x80\xf4j\x9a\xed\xfd\
|
||||
\xa2\xf0\x01B\xe7\x1b\xa9\xd9\x1d>;\x03X\xd9X\xf7AToC\xb3\xeb\xc6\x96e\xb6-\
|
||||
\x1en\xef\xb999\x03\xe0\xea\xf2B\x00Dku\x83)\xcd\x85\x8c;}n9\r\x80\xd1\x87b\
|
||||
\xbe\x00\xb33\xc3\x04f\xdbr\x9a;\x03\xbfI\x86\x1a\xfd\xe0\x01\xaam\xec\x0c\
|
||||
\x86\r\xf6\x8d{\xcd\xf6;\x00\xb3\'\x01\xde?\x9a>\xba\x9cH6\xb7,x~\xaa:=Q\x9f\
|
||||
\xb9\xe7\x1fE\xae\xb7\\\xb6\x1f\xe0\x8d\x15H$\x99\x1b?\x12@\xd7\xdf\xd0\x0f\
|
||||
\nN!\x91\x98\x9e\xd8\x0c\x10\xbd>\xdeU\xeco\np\xf7\xf8\xebK\x14fvF\xc8ds\xce\
|
||||
\xff\xbd\xb6u(\xbc\x89\xbc\x17\xf6\x9f\x14E\x8d\x04\x8a\xdeDa\xcads\xca\x1f\
|
||||
\x0cI\xd4\xda\x88E\x9d\xc4\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getCopyBitmap():
|
||||
return BitmapFromImage(getCopyImage())
|
||||
@@ -2988,13 +3105,22 @@ def getPasteData():
|
||||
return \
|
||||
"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x00\xa1IDAT8\x8d\xa5\x93\xd9\x0e\xc3 \x0c\x04\xc7\xa6\xbf]\xc5U\xbf\xbb\
|
||||
\xd9>$4\\9\xaa\xacd\t\x0c\x1e/H6\xf3\xc4\x1d=FI\xcd\x1f\x95{\xf3d{\x003O]\
|
||||
\x01\x80\x94/\x0c\x8a\n\xa0\x01\x8a\x88\xdfaD m\x85y\xdd\xde\xc9\x10/\xc9\
|
||||
\xf9\xc0S2\xf3%\xf2\xba\x04\x94\xea\xfe`\xf4\x9c#U\x80\xbd.\x97\x015\xec&\
|
||||
\x00@\x9a\xba\x9c\xd9\x0b\x08\xe0\r4\x9fxU\xd2\x84\xe6\xa7N\x1dl\x1dkGe\xee\
|
||||
\x14\xd0>\xa3\x85\xfc\xe5`\x08]\x87I}\x84\x8e\x04!\xf3\xb48\x18\r\x8bf4\xea\
|
||||
\xde;\xbc9\xce_!\\\\T\xf75'\xd6\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
\x00\x01\x90IDAT8\x8d\x8d\x93?H\x02a\x18\x87\x9fSw\xb1\xa9!q\xc8\xb0?B\xd0\
|
||||
\x98\x10DS\x10\x98\x82C\xd1\x12\x1a\xcd\rb&\xad\x1a\x144F`[\xd4 hBPKC\x83P\
|
||||
\x8b4\xe4\xa9tP\x82\x98\x88`$\x82\x8b\xd8p\xddu\xa7\xa5\xfd\x96{\xbf\xef\xfd\
|
||||
\xbd\xcf\xf7~w\xf7\n\x82\xc1\x08@M\xect\xd1(x\x12ef\xcaN./\x11\\\xdc\xd3\xa6\
|
||||
pz\x8d\x82\x12\x0b\x82\xc1HM\xect-c\xf7\xaa!\x10\xc9\xe0]rR\xac\xb4\x01\xc8\
|
||||
\xe5%\xe2\xbbF5_|\x0c\xa9\x10\x03=\nD2\x00$\xef\x9e\xc9\xe5%ryI\xde?\xe8\xe8\
|
||||
|\xe9\xabT\x17\xc0\xd4\x0b\xd8\nl\xa8q\xfd\xa3%\xb7\xd9x\xe1\xad=\xc2q\xba\
|
||||
\xc2\x8e\xfbU\xe7\xef\x03\x00\x98m\xd6\xef\xa7\xb23\xc9\xdbm\x06\xfb\x8a\x8f\
|
||||
\xe0y\x8a\xc0\xc4\x10\x00\xc0\xcdEB\x8d\x97\xd7}j\xbc\xb0\xe6!~\x99d\xd11\
|
||||
\x04\xa0-R$]'\xa84M4\xca\x05p8\x7f\x07\xd4?Z\x98mr\x07\x95\xa6\x9c\xf6o{\xb0\
|
||||
\xce\xbb\x00\xb0\x03\xe9\xc3\xd8\xf0+h;x\xf9\xfc\xcb\xd5\x0bh>Pzw1>\x0bg\xa7\
|
||||
)]\xaaQ.\x00`\xdb\x0c\x0f\x00hN\xf4o{~=\xf9\xa9\x0eY\xb1\x8awI\xf3\x0ej\x05\
|
||||
\xb0\x98\x1f\x00x-\xd5\xb0\xce\xc3\xd1~LW\x98\x15\xab\xccM\x8f\xfe\xaf\x03\
|
||||
\x00w0\xccS\xfdgm\xfb\xc3\xd7\xf7++w\xd5\x16\x0f\x92\t\xe4\xe9zN\x86\xbe\xa7\
|
||||
1\xaa\xfbLY\xb1:\x10 (\xe3\x0c?\x03\xf2_\xb9W=\xc2\x17\x1c\xf8\x87\x9a\x03\
|
||||
\x12\xd7\xb9\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
|
||||
def getPasteBitmap():
|
||||
return BitmapFromImage(getPasteImage())
|
||||
@@ -3008,11 +3134,19 @@ def getSaveData():
|
||||
return \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x00lIDAT8\x8d\xc5\x93\xe1\n\xc0 \x08\x84=\xed\xc1}\xf1\xcd\xfd\x18B\x98\
|
||||
mX\x83\x1d\x04\x11\xfayV\x02,\xb4#\xde\xca&\xa2\xe6\x1b;\x0f\xab$\x82\x05\
|
||||
\x83\x03U\xbdaf\xe9\xea\x13]\xe5\x16\xa2\xd32\xc0].\x03\xa2Z<PU\x02\x90\xc5\
|
||||
\x0e\xd5S\xc0,p\xa6\xef[xs\xb0t\x89`A|\xff\x12\xe0\x11\xde\x0fS\xe5;\xbb#\
|
||||
\xfc>\x8d\x17\x18\xfd(\xb72\xc2\x06\x00\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x01\x1dIDAT8\x8d\x9d\x93=N\xc3@\x10\x85\xbf\xf5\xa2-\xf1\x11\xa0\x8dC\
|
||||
\x8f\x82\xa0\xe5\xa7\xa6\xe2\x04\xb4p\x00\x1a\xfb\x02\x11T\xf4\xa4\xa0\xc1\
|
||||
\xc1\\\x01\x90R"\xc5\xa4\x89RD\x14\x04$\xa2@\x01\xb1\x04C\xe1\xc8\xb1`\x1dC^\
|
||||
5;?\xef\xcd\x8cv\x94r4\xf1\xc5\xa7P\x82a\xff\xb7o\xfd@+\x94\xa3\xb9o"2\xa8K\
|
||||
\x18\x86R\x84\xc1\x87\xc8\xdd\xf3X|\xdf\x17\x11\x91\x9bc$\x8a"q\xf2\x8cZk\
|
||||
\xab\xfa\xd3\x18\x1e\xdf\x12\xba\xef\x06\x80\xdb\x13\x95\xc5\x1ckE\t\xd6\xb6\
|
||||
\xf7\xec\x04I\x92\x94\xaa\xff\xc4\\\x1d\xf0\xd2\xfd\x1bA\x99:\xc0B\xfe\xb1\
|
||||
\xbb\xf1@\x10\x043\xc5\x8f6\xaf\x00\xe8u\xc0]\x9e\x10\x0c\xfb@m\x92\xb0\xbf8\
|
||||
\xcd\x1e\xb5\xacm\xdb;\x18\xb5\xc0]%8}\xcd\x85+\x99\xd5\x8e\xbf2\xfb\xfc\xb0\
|
||||
g\x1f!U\xac\xe0y^\xe62\xc6p\xd6h\x14\x8e4s\x89\xc6\xa4\xcb[\xa9V\xffG\xa0\
|
||||
\xb5\xce\x8a\x97j[\xb4\xe3\xb8\x90@)\'\xfd\xbe\xd7\xf5\xe2\x83\xeau\xec~w\'\
|
||||
\x9a\x12\x00\\6\xc3\xd2\xab,\xec`^|\x03\xb6\xdf|Q.\xa7\x15\x89\x00\x00\x00\
|
||||
\x00IEND\xaeB`\x82'
|
||||
|
||||
def getSaveBitmap():
|
||||
return BitmapFromImage(getSaveImage())
|
||||
@@ -3026,17 +3160,20 @@ def getSaveAllData():
|
||||
return \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x01\tIDAT8\x8d\xa5\x93\xe1m\x830\x10\x85\xdfA\xd7H\x827\xf0\x02\xado\
|
||||
\x04\x8f`Fh\xfb\xb7\xad\xcd&$Y\x80\x11\xcc\x06\x8c\xe0E\xd2\xeb\x8f\x16\x04!\
|
||||
8R\xf3\xa4\x93Nw\xd2\xf3\xa7g\x9b\xa8(\xf1\x88\x9er\xcb\xc3~\')%x\xef\xa7Y\
|
||||
\x8c\x11J)\x00\xc0\xf1t&PQn\x163\x0b\x00\x99\xcb{/\x00\xc49\'T\x94(\xfe\x83\
|
||||
\x1dB\x98\xfa\x95\xc1a\xbf\x13\xf9\xbe\xc8\xd7\xe7\x87\x18c\xe0\xbd\x073\xa3\
|
||||
\xaek\x10\x11\xfa\xbe\xcfgPU\x15RJ\x8bSB\x08h\x9af1\xdb$\xc8aw]\x87\xae\xeb\
|
||||
\xd6\x04\xd7i\x1bc\xc0\xccPJ\xa1m[03\x98\x19Z\xeb\x951QQ\xc2\xbc<K\x8c\x11"\
|
||||
\x92\xc5N)M\xbd\xd6\x1a\xafo\xef\x94}\x07#6\x00Xk\x7f\xef\xfdO\xc7\xd3\x19\
|
||||
\xc0,\x83\x10\x02\x88h\xaa1m\xad\xf5M\xf4E\x06s\x93-\xcd\xf1\xef\x1a\x8c\'^c\
|
||||
\xdf5\x18\x95C\xbei`\xad\xc50\x0cp\xce-\x96[\xd8s\xd1\xa3\xdf\xf9\x075\xf1v>\
|
||||
\x92\xcb\xbc\xdd\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x01UIDAT8\x8d\x9d\x93\xbfK\xc3@\x1c\xc5\xdf%\x01g\xeb \x1d\x8a\x8b\x83M\
|
||||
\x11\xe9\x16\x8a\x8b\xff@\xa0\xdd\x14\'\x17\x17A2\xe9,\x08\xc9\x14\x82n.nn\
|
||||
\x9a\xde?\xe0R;\xb88\x99v\xe8`\x86\n."\x81\xb6\xb4\xb4~\x1d\xd2\xc4^\x92j\
|
||||
\xf5\x03\xc7\xfd~\xf7\xeeq\xc7<\x17\x84)\xa3\x1e\x04\x863\xfd\xf10\xac\xb7\
|
||||
\x8fe&,\xf2\\\x10\xf9\x06q\xce)I\x7fL\xf4\xda\'2M\x93\x88\x88\x1e.@\x9csb\
|
||||
\x92\x8c\xb8x.\xa8X6\xd0z\xb2c\xd1?9\x89\x1c\xfc\xd7\x89\x82\x04\xeb\x9f:Z\
|
||||
\xf5l\';9\xe0\xf1\xea\x14\xca\x12\xb0\xe2\xebh8 ))\x00\x00\xc5\xb2\x81\x8e\
|
||||
\xc4\xb1\xb5GB\xd9< \x14\xf6\t\xf7\xef&*Ga\xf6\x99\x02Y\x0c&\xc0\xc7\x08x\
|
||||
\xe9\x01A\x10\xa0y\xc9\x16\x17\x98\xdd\x1cQ\xd1\x8d\x9f\x05<\xcf\x136\xcf#\
|
||||
\x15b\xc4\xc9\xee\x1b,\xcb\x8a\xfbA\x10\xc4\xed\xf3\xc3\x01\x00\xc0o\x03J\
|
||||
\xa9&\xb3\x86c\xd3r![\xe47\x14 |\x14\xcf\xb7\x13JNZ7\xab\xc2\xe9\xddn7\x9e\
|
||||
\xbb>\xcb\x01\x98\xc9\xa0T\x93Y\x93\xdbH\xa2\xaa*4MC\xb5Z\xcdt \x84\x98\xfa(\
|
||||
S\xf2\xf9\xfc\xdc+0&\xc9\xa9\xc1\x86\xf3}\x1d\xbf\r\xacm\x84\xf5\xc2\x02\x00\
|
||||
Pw\xefR\x99d\xf1\x05z\x94\xd0b\xcb S\xf3\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getSaveAllBitmap():
|
||||
return BitmapFromImage(getSaveAllImage())
|
||||
@@ -3048,16 +3185,25 @@ def getSaveAllImage():
|
||||
#----------------------------------------------------------------------
|
||||
def getPrintData():
|
||||
return \
|
||||
"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x00\xa1IDAT8\x8d\xa5S[\x0e\x02!\x0c\xec\xd0\xbd\xb6\x1a\xf5\xda\x96\xd9\
|
||||
\x0f\xa1V\x96\x00\xbaMHI\xd3y\xf0(\x90T\xce\xc4\xd6+2\x1bg@$E\x97\x80\xd9H\
|
||||
\x8e\xf1\x00\xc6\x0e\xda&''\x05\x80\xab\x1f\x08\xa2\xfa\xcc\xc5\xd0\xc1H\xbd\
|
||||
\n\x89\xbc\xef\xc1\tV\xd5\x91\x14\xcc\xc6\x9a\xa5<#WV\xed\x8d\x18\x94\xc2\
|
||||
\xd1s'\xa2\xb2\xe7\xc2\xf4STAf\xe3\x16\x0bm\xdc\xae\x17'\xbf?\x9e\x0e\x8an\
|
||||
\x86G\xc8\xf6\xf9\x91I\xf5\x8b\xa0\n\xff}\x04w\x80\xa4ng\x06l/QD\x04u\x1aW\
|
||||
\x06(:\xf0\xfd\x99q\xce\xf6\xe2\x0e\xa5\xa2~.\x00=\xb5t\x00\x00\x00\x00IEND\
|
||||
\xaeB`\x82"
|
||||
\x00\x01\xa7IDAT8\x8d\xa5S=K\xc3P\x14=\xef\xb5 \x0e\xf6\x17\xb8$X\x10\xa7\
|
||||
\x82\xb4\n]\x05A\x07\xebd%\xfe\x02\x97\x82\xe0\xa0\x83\xa3\x88\xb5E\xfd\x07j\
|
||||
\x0bq\xea\x07\x18(8:5\x16\xa2H\xf1\x8bN\x12\tt\xe9\x8b\xddZ\x9eC|i\x93\xd4\
|
||||
\x0f\xf0\xc0\xe1\xe6\xbe\xdc{\xde\xb9\xc9{\x84\xd0\x10\xfe\x83\xb0x8m\xf6\
|
||||
\xb8i\xf7=/\xfb\xad\x07O\x9e]\x9f%\x01\x05BC 4\x84\x1d\xbd\xc7\xfdx\xb2\x1d^\
|
||||
\x99\x9c\x1f\xe6\x8ey\xb5Z\xe5\xa2^\x90\n\xa1\x83\xb91\xb2{;p\xf0\xfc\xe1\
|
||||
\xc4W\xdb\x89\xe3\xcb\x19\xa8\xaa\x8aJ\xb9\xc4\x87\r\xd0\xe1\xc4o\xf9/\x08\
|
||||
\x03\xc0\xc5\xf9\x19\x07\x80\xfb\xaf\x9d\xc5\xae-6(4\xed>\x9aoA\x01zq~\xc6\
|
||||
\x15E\x81\xa2(\xee\xe2\xd4\x84\x13\xe5H\xb0\xc1?\x06\x05\x80b\xb1\xe8\x16\
|
||||
\xbc\xda\x0e[\xcc\xa1i\xf71\xfcw\xf2\xf9\xbcG\x84\x14\n\x05\x1e\x8b\xc5\xa0\
|
||||
\xd5\xae\xb1\xbd\x95\x81eY#gm\xb7\xdb\x9e|cs\x1fw7\x97$lZm\xc4\x00,-. \x9b?\
|
||||
\xc1tT\x1e)\xc0\x18C$\x12\x01c\xce\x87\xe9\xbe\xeb\xa8\x94K\x9cNGeh\xb5k\x00\
|
||||
\x80\xd1\xa8#\x91H@\x96\xe5\x00%I\xc2\xe3K\x0b\x9a\xa6A\x92$W8\xbc\x92Z%\xeb\
|
||||
\xe95n4\xea\x01\xab\x9dN\xc7\xe3"9\x1fGr>\xeeYs\x8fr:\x9d\x06c\x0c\x86ax\nL\
|
||||
\xcb;\xbb\x1f\x84\xd0\x10*\xe5\x12WU\x15\xcd7`f\xf2\xc7z\x00\x80\xae\xeb\xc8\
|
||||
\xe5rXI\xad\x12"nc\xa5\\\xe2{G*\xba\xef\xfa\xaf\x02\xa2\xd9u \xe0?\xe7\xdfA4\
|
||||
\x03\xc0\'\xe3\x82\xc9\x18g\x90\x8e]\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getPrintBitmap():
|
||||
return BitmapFromImage(getPrintImage())
|
||||
@@ -3071,14 +3217,20 @@ def getPrintPreviewData():
|
||||
return \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x00\xa8IDAT8\x8d\x9d\x93K\x0e\xc30\x08Dg \xd7n\xcd\xc1\x9b\xd2E\x83E\\\
|
||||
\xffT$/\x82\xc5\x83\x19\x13\x02p,\x82\xa2\x1c\xde\x01p\xf71\x83\xe4\x14"\xab\
|
||||
\xeeQ\xec\xef\xb3\xdbe{\x82\x0c\xcb\xdf\xc7\xaa{\x86\xb7\xb0-@\xaf(\xc7\xd4\
|
||||
\x03\x9203P\x94\x14\xa5\x99\xa1\xf5b\x08\x88b+\x05~\xbejQ\x0f\xe2\xbd\x00\
|
||||
\xe0\x14\x05\xdc\x9d\xa2\xa0(\xcc\xec\x9b\xbb\xee(\xba~F\xea15a\n(\xcfG\x1d5\
|
||||
d\xe4\xdcTB\xc8\x88\xb1CB\x9b\x9b\x02\x02\x92O@\xaa\x0fXl\xe2\xcd\x0f\xf2g\
|
||||
\xad\x89\x8d\xbf\xf1\x06\xb9V9 \x0c\x1d\xff\xc6\x07\x8aF\x9e\x04\x12\xb5\xf9\
|
||||
O\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x01mIDAT8\x8d\x8d\x92\xbdK\x02a\x1c\xc7?w\x1a\x85E\x04588XHa\xd1\x14!AB\
|
||||
\r.\xbd\x07m-By.M\xfe\x03N\x05\x0e\xed\xf9\x124\x045\x04\x15\xdc\xda&4\xb5DC\
|
||||
J\x8a\x81E\t.\x82\x918\xd8\xf0pOw\xde\x19}\xe1\xe1w\xf7;>\xdf\xdf\xcbs\xca\
|
||||
\xddC\xb9C\x97\x1e\x8bU\xf9\x9c\xd8]V\xba\xbf\x9b\xa5\x02\xf8\xa6\xc6-ge=\
|
||||
\x0c@p)\xcc\xc1\xe1\xa5\xad\x80\xcd\xa0\x97\x86\xfb`5\xba\xf3\xa7\x89\xdb)Y\
|
||||
\xff\x16\xf1"{%s\xb77\xd7\x9d\xcd\xadm\xdb86\x03\x03\x0eE\xc2\x04\xdbPk\xc1y\
|
||||
2Edf\xday\x84\xe6\xdb\x93\x84\x8c\xd8h\x8bSk\xf5j\xdcdPj\x8eX`C\x06\x9c?\x8a\
|
||||
\xe3\xef/\xa3\xeb:\xb1\xfd=\xdb.,#4\xdav\x18-m\x01b\xd0\xc9\xe6N\xe5.Ts\xcbN\
|
||||
pz\x0e\xa2~\x91\x0bx\x00-m\xe9D-W>%h\xc0\x1f_\xbf\x15\xef\xeb\x90\xaf\xc1\
|
||||
\xe2\x18x="\x82\xb8\x15\xd9\x81yYf\x18\xe0\xac"\xc0\xc0\x10\x84\xc6D4\xcb\
|
||||
\xf2#u\xc3\xb2m`t\x00&\x07E4\xcb]x.QH\xa6\xec$\x13\xf83q^\xb44^\x8f\xb8\xa5"\
|
||||
p\x9c\x88\xa3\x91\xe1\x9d5\x00\x14Eu\xc9y\x9c\xa4\xeb\xba\xe5}\xb6\x9a\x01`\
|
||||
\xc1\x07\xf39\x97\xa2(\xaa\xab\x17+\xd5]\xe0\xf5dC\x9a\xfc\xcb\xc0\xc9\xd00\
|
||||
\xf9\x011\xc9\x87\xf3\xb4\xd1t\xaf\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getPrintPreviewBitmap():
|
||||
return BitmapFromImage(getPrintPreviewImage())
|
||||
@@ -3090,13 +3242,22 @@ def getPrintPreviewImage():
|
||||
#----------------------------------------------------------------------
|
||||
def getCutData():
|
||||
return \
|
||||
"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x00rIDAT8\x8d\xad\x93\xc1\x0e\xc0 \x08CW\xdco{\xf2\xbb';\xb18\x07\x9d\
|
||||
\x0b\xe3\xa2\x98\xe6\xb5$\x02H\xd92%\xde\xa3\xf6CY\xff\nH'\xf8\x05`\xb1Y\xfc\
|
||||
\x10\x00)`\xfdR\x82\x15w\n0W\xe6N\x01\xda\xab\x8e\xe7g\xc0\xe8\xae\xbdj\x04\
|
||||
\xda#\xe7;\xa8] \xbb\xbb\tL0\x8bX\xa5?\xd2c\x84\xb9 \r6\x96\x97\x0c\xf362\
|
||||
\xb1k\x90]\xe7\x13\x85\xca7&\xcf\xda\xcdU\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
\x00\x01HIDAT8\x8d\x85\x92OK\x02Q\x14\xc5\x7f\xa3\x05}\x1b\xa1\xc0\x9d\xb4\
|
||||
\xaaf6\x93a\x10\xe3^\x83l\xdf\xc6\xa5\x1bIA\xb4\xa0\x9cM\xe5"\x84\x18\xff\
|
||||
\x108\xbb\xf0\x93\xb4v\x15h\xa9\xaf\x16\xaf\x85\xbcat^\xd3\x81\xb79\xf7\xdc\
|
||||
\xf3\xce{\xf7b$\x92\x84O\xa7\xd3\x91\x9b\\\xf8\xd4\xeb\xb5\xb5z\x02\r\x9e\
|
||||
\x1e\x1f\xa4\x8eo5\x1b\x12`\xd0\xef\x05u\xadA.\x97\xc3u\xef\xd7LZ\xcd\x86\
|
||||
\xb4\xedlD\xab5\xd0A\x08\xc1l6e>_\xc4\x1b\x88o\x01@\xde\xc9\x07\x91k\xd7Ui\
|
||||
\x9a\x96\xd6xk\x93(\x14\xce\r@\x1e\x1e\x1cE\xc4\x9e\xe7\x91J\xa58\xce\x9e\
|
||||
\x18\x7f\x1a\x00,\x17\xab\x98\xb6\x9dE\x08!M\xd3\x8aDW0\x8cDR[P\xb1U\xa3\xef\
|
||||
\x8f"\xb7C\xcc\'\xee\xbdw\xf1</h\xceL\x86Z\x9d\xf6\to\x17\xbb2m90z\xc6\xf7!3\
|
||||
\x19\x92\xb6\x1c\xc6\xdd\xab\x886v\x8ci\xcb\t\x9a\x15\xc2K\xa45P\xb7\x17o+\
|
||||
\x00,\xa6\x9f\x00\x14o+\xec\x9f\x15X\xba\x97\xf1\tTC\x1c\xfe]e\x80v\xa9\xcc\
|
||||
\xb8\xeb2\xfb\xf8\xe2\xf5\xaeA\xbbT\xd6\xea"c\x1c\xf4{r\xfbe\xf5Y?\xa7\xd5\
|
||||
\x80W\xd1w\n7k\xa3\xd4\xee\x81\x8a\x18\x16\xea8\x80_\\\xa2\x8b\x88!\xd2S\x08\
|
||||
\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getCutBitmap():
|
||||
return BitmapFromImage(getCutImage())
|
||||
@@ -3110,12 +3271,24 @@ def getUndoData():
|
||||
return \
|
||||
"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x00lIDAT8\x8d\xed\x92Q\x0b\x800\x08\x84\xd5\xf5\xb7\x07W\xfdo\xed!\xaca\
|
||||
\xb2\x11{\xe9!a\xa0\xc7\xeec\x1ec\x96B3%S\xeeO\x00\x96\xd1\x05\xd3j\xed\x0c\
|
||||
\x10\xad\xdb\xce\x97\xc0R\xe8\x0c\x12\xe6\xbd\xcfQs\x1d\xb8\xf5\xd4\x90\x19#\
|
||||
\xc4\xfbG\x06\xa6\xd5X\x9a'\x0e*\r1\xee\xfd\x1a\xd0\x83\x98V\x03\x1a\xa1\xb7\
|
||||
k<@\x12\xec\xff\x95\xe7\x01\x07L\x0e(\xe5\xa4\xff\x1c\x88\x00\x00\x00\x00IEN\
|
||||
D\xaeB`\x82"
|
||||
\x00\x01\xa7IDAT8\x8d\xa5\x90\xbfK[Q\x18\x86\x9fs#\x8d\x7fBu\xc8\xd6\xc9\xc1\
|
||||
\xa1\x83\xd0\x16\xa1C@*\x98\xc4\xa2\x12\xda\x8e5\x9b\x83\x04\x07Aph\x17)\x16\
|
||||
\xdd\xd4\xc1\xa1Z\x1b\xc5&9\xa6P\xbaw\xa8\x9b\x9b\xa0S\xb0\xe2\x8f\\%1^\x8d\
|
||||
\xde\xfa9\x84s\xf1\xea\xa5\x06<p\x86\xc3\xf9\x9e\xe7\xbc\xefQ\xca\n\xf1\x90\
|
||||
\xd5t\xdf@\xba\x10\x95r\xcd\x01`\xee\xf5o\xd5\xb0 ]\x88\n@\xd7\xb3^\x00.\xaf\
|
||||
\xce\xd8\x9d>\x10\x80\x1fC[\x9eH\x05UH\x17\xa2r\x13\xac\x9d_Pq\x8f\x01(96\
|
||||
\xdf\x16\xd7X\xff\xb8\xaf\x02\x05\x066\xa0+5\xe6\xb3\x0b\x1c\xeeW\x00x\xd1\
|
||||
\xf3\x14\x80\xaf\x93\xbf\xd8\xcb\xb8\xeaN\x05\xd3\xd7\xbc\x9a\xd1\xdf\x19\
|
||||
\x8cL@\xa4~\x9f\x9a\xec\xa3\xb3\xa7\r\x80|.+>\xc1\xfb\xd5\xe72\xf0\xf2-U\xa7\
|
||||
\xec\x83c\xf1\x84\xd79\x9f\xcbJj\xa9/\xf8\x13\xcb\xe7U.\xaf\xcep\xa5\x06P\
|
||||
\x8f\x1d\xf1'\x8c\xc5\x13*\x9f\xcb\x8a'\xe8_l\x17\x80\xe57\x1b\xea\xd4\xae\
|
||||
\xc7w\xfe9\x94\x1c\xdb\x83\x1e\x0f4\t\xc0^\xc6UFb\xee\xacS\xdba\xf8\xd5\x08\
|
||||
\xdd\xd3O\xc4t7\xab\xb8m\x93Z\xf2w\xbe\xfdgJk-\xb3\xc5\x11\xc6\xde\x8dS\x95\
|
||||
\x8a\xd7\xbf\xe4\xd8\xec\x9c\xecr\xb2Sfm\xf9\x0f3\xc9\x15\xdf\xcb^\x82X<\xa1\
|
||||
\x06#\x13\x0c}\x1a\x06 \xdc\xfc\xc87\xf0?\xb8\x1e\xc1\n\xa1\xac\x10Zk\xe9\
|
||||
\x18k\x95\x9fGS\xf2\xa58*\x9f7S\xd2\x92\x0c\x8b\xd6Z\xccL\xd0\xf6\x1d\xb4\
|
||||
\xd6\xd2\x92\x0c\xcb\xea\xdf\x0f\r\xc1w\x047%\x8d\xc0\x81\x02#i\x04VV\x88k\
|
||||
\x82\xbe\xde\xc2\xb0\xb2\xea\xa7\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
|
||||
def getUndoBitmap():
|
||||
return BitmapFromImage(getUndoImage())
|
||||
@@ -3129,12 +3302,22 @@ def getRedoData():
|
||||
return \
|
||||
"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
|
||||
\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x00jIDAT8\x8d\xed\x92\xcd\n\xc0 \x0c\x83\x9bv\xaf\xed\x16\xf0\xbd\xd7]&\
|
||||
\xf8\x8f\xe0e\x87\t9$\xb6\x1f\xb5\x08\xa8\xc9\xce\xd1\xad\xeeO\x00\x8e\xdc\\\
|
||||
gp\xb2,\x80FL\tP\x13\xa8\tI\x17\xa1'\x9f$\xd2\xe6\xb9\xef\x86=\xa5\xfb\x1a\
|
||||
\xb8\xbc\x03h\x84\xdf\xc1\xeb|\x19\xd0k.\x00\xe4\xb8h\x94\xbf\xa3\x95\xef$\
|
||||
\xe7\xbbh\xf4\x7f\xe5}\xc0\x03&\x1b&\xe5\xc2\x03!\xa6\x00\x00\x00\x00IEND\
|
||||
\xaeB`\x82"
|
||||
\x00\x01\x88IDAT8\x8d\xa5\x92\xc1K\x02A\x14\xc6\xbfQ\t\xbc\x14tJ\xfb\x0f2\
|
||||
\x08\xbaD\xdd:\xe5!\xd2\xad$/\x82FP\x06\x99\x87\x04\xa1\x83D\x10\x0b\x85\xd4\
|
||||
\xa9\x8c (\x82<\xad\xce\xa9\xff\xc0[\xd2)\xbcu\t\xb2\xd0\xa5\xb5\x94\x14z\
|
||||
\x1dd\x87]\x1bBh\xe0\xc1\xf0\xde\xfb~3\xef\x9ba\xcc\xe1\xc4\x7f\x96K\x96\xdc\
|
||||
\xd6\xfcd\xeeO\x94;\xd67\xc0\x14Fg\xd7E\xae~\xa5S\xe3\xd3@!\xfe(\x051s\x84m\
|
||||
\xcdOV!\x004\xbf\r\x00\x80\xde\xae\xe2B\xbb\x94B\\\x00\x10\xb9\x9a\x12\xe2,W\
|
||||
Eqc~S\xec\xd7\x94\x18\xaa\xafY*e^l\x10\x87\xf5\xb4,W\xb1<\x98\x16q\x98W\xa1\
|
||||
\xb7\xab\x00\x80F\xa7\x0e\x00(\x164\xb2\x02\xc0\x1cN(\xb9qRr\xe3\xc49'\xe6p\
|
||||
\xc2\x1a3\xfb\xa3t\xfb\xbcK\xe7O[\xa4V\xc2\xe4K\x0e\xdb\xfa\\\x00\x10\xf3\
|
||||
\x1c\x00\x00\x02AEj\x94\xd11P\xffz\x93\x95\xba\x80^\xe1\xf4\xde\x08\x01@)\
|
||||
\xf3\xc2\xdek-!\xae5u\xe8\xcf-\x00\x80gi\x80l\x1e\xf4\xae\xc4j\x14c\x89!1o\
|
||||
\xad\xa9\x8b\xda\xc6\xf5\n\x16v&\xbb\x16\xc8~b\xb1\xa0\x91\xfa\x10G4\xb2h;\
|
||||
\xbd\xd1\xfe\x10=\xfc\xe8\x1eg\x91\xbc\xfc\x06\x81\xa0\xc2\xd2\x13\xa789\xbe\
|
||||
\x91\xde\xce\x14\x07\x82\nC\xaf\xeb\xd6\xe0\x9c\x93/9Lj%L\xa9\xf2\x1c\xa5\
|
||||
\xcas\xe4\r\xb9m\xaf\xf0'\xc0\x84xCnR+\xe1_\xe2\xbe\x00V\x88\xec\x9f\xf4\x05\
|
||||
0!\xb2\xfc\x0f\xe0\xc4\xb6\xad\x97R\xe5z\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
|
||||
def getRedoBitmap():
|
||||
return BitmapFromImage(getRedoImage())
|
||||
|
@@ -59,7 +59,12 @@ class Throbber(wx.PyPanel):
|
||||
overlay = None, # optional image to overlay on animation
|
||||
reverse = 0, # reverse direction at end of animation
|
||||
style = 0, # window style
|
||||
name = "throbber"):
|
||||
name = "throbber",
|
||||
rest = 0,
|
||||
current = 0,
|
||||
direction = 1,
|
||||
sequence = None
|
||||
):
|
||||
wx.PyPanel.__init__(self, parent, id, pos, size, style, name)
|
||||
self.name = name
|
||||
self.label = label
|
||||
@@ -89,8 +94,9 @@ class Throbber(wx.PyPanel):
|
||||
self.labelX = (width - extentX)/2
|
||||
self.labelY = (height - extentY)/2
|
||||
self.frameDelay = frameDelay
|
||||
self.current = 0
|
||||
self.direction = 1
|
||||
self.rest = rest
|
||||
self.current = current
|
||||
self.direction = direction
|
||||
self.autoReverse = reverse
|
||||
self.overlay = overlay
|
||||
if overlay is not None:
|
||||
@@ -116,14 +122,14 @@ class Throbber(wx.PyPanel):
|
||||
# while the throbber is running. self.sequence[0] should always
|
||||
# refer to whatever frame is to be shown when 'resting' and be sure
|
||||
# that no item in self.sequence >= self.frames or < 0!!!
|
||||
self.sequence = range(self.frames)
|
||||
self.SetSequence(sequence)
|
||||
|
||||
self.SetClientSize((width, height))
|
||||
|
||||
timerID = wx.NewId()
|
||||
self.timer = wx.Timer(self, timerID)
|
||||
|
||||
self.Bind(EVT_UPDATE_THROBBER, self.Rotate)
|
||||
self.Bind(EVT_UPDATE_THROBBER, self.Update)
|
||||
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
||||
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
|
||||
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroyWindow)
|
||||
@@ -157,18 +163,21 @@ class Throbber(wx.PyPanel):
|
||||
event.Skip()
|
||||
|
||||
|
||||
def Rotate(self, event):
|
||||
self.current += self.direction
|
||||
def Update(self, event):
|
||||
self.Next()
|
||||
|
||||
|
||||
def Wrap(self):
|
||||
if self.current >= len(self.sequence):
|
||||
if self.autoReverse:
|
||||
self.Reverse()
|
||||
self.current = len(self.sequence) - 1
|
||||
else:
|
||||
self.current = 1
|
||||
if self.current < 1:
|
||||
self.current = 0
|
||||
if self.current < 0:
|
||||
if self.autoReverse:
|
||||
self.Reverse()
|
||||
self.current = 1
|
||||
self.current = 0
|
||||
else:
|
||||
self.current = len(self.sequence) - 1
|
||||
self.Draw(wx.ClientDC(self))
|
||||
@@ -185,7 +194,7 @@ class Throbber(wx.PyPanel):
|
||||
def Rest(self):
|
||||
"""Stop the animation and return to frame 0"""
|
||||
self.Stop()
|
||||
self.current = 0
|
||||
self.current = self.rest
|
||||
self.Draw(wx.ClientDC(self))
|
||||
|
||||
|
||||
@@ -213,6 +222,65 @@ class Throbber(wx.PyPanel):
|
||||
self.running = not self.running
|
||||
|
||||
|
||||
def SetCurrent(self, current):
|
||||
"""Set current image"""
|
||||
running = self.Running()
|
||||
if not running:
|
||||
#FIXME: need to make sure value is within range!!!
|
||||
self.current = current
|
||||
self.Draw(wx.ClientDC(self))
|
||||
|
||||
|
||||
def SetRest(self, rest):
|
||||
"""Set rest image"""
|
||||
self.rest = rest
|
||||
|
||||
|
||||
def SetSequence(self, sequence = None):
|
||||
"""Order to display images"""
|
||||
|
||||
# self.sequence can be changed, but it's not recommended doing it
|
||||
# while the throbber is running. self.sequence[0] should always
|
||||
# refer to whatever frame is to be shown when 'resting' and be sure
|
||||
# that no item in self.sequence >= self.frames or < 0!!!
|
||||
|
||||
running = self.Running()
|
||||
self.Stop()
|
||||
|
||||
if sequence is not None:
|
||||
#FIXME: need to make sure values are within range!!!
|
||||
self.sequence = sequence
|
||||
else:
|
||||
self.sequence = range(self.frames)
|
||||
|
||||
if running:
|
||||
self.Start()
|
||||
|
||||
|
||||
def Increment(self):
|
||||
"""Display next image in sequence"""
|
||||
self.current += 1
|
||||
self.Wrap()
|
||||
|
||||
|
||||
def Decrement(self):
|
||||
"""Display previous image in sequence"""
|
||||
self.current -= 1
|
||||
self.Wrap()
|
||||
|
||||
|
||||
def Next(self):
|
||||
"""Display next image in sequence according to direction"""
|
||||
self.current += self.direction
|
||||
self.Wrap()
|
||||
|
||||
|
||||
def Previous(self):
|
||||
"""Display previous image in sequence according to direction"""
|
||||
self.current -= self.direction
|
||||
self.Wrap()
|
||||
|
||||
|
||||
def SetFrameDelay(self, frameDelay = 0.05):
|
||||
"""Delay between each frame"""
|
||||
self.frameDelay = frameDelay
|
||||
|
@@ -1,3 +1,81 @@
|
||||
0.9.5 (12/23/2005)
|
||||
-------------------
|
||||
|
||||
Applied a series of enhancments by Franz Steinaeusler, Adi Sieker, and
|
||||
Sebastian Haase, up until their 7-31-2005 version. (Their next
|
||||
version broke some existing functionality, and added some confusing
|
||||
hacks, and I didn't feel that the incremental gains were worth the
|
||||
loss at that point so I stopped at 7-31-2005.)
|
||||
|
||||
Their changes include the following:
|
||||
|
||||
* The Autocomplete and Calltip windows can now be opened manually with
|
||||
Ctrl-Space and Ctrl-Shift-Space.
|
||||
|
||||
* In the stand alone PyCrust app the various option settings, window
|
||||
size and position, and etc. are saved and restored at the next run.
|
||||
|
||||
* Added a help dialog bound to the F1 key that shows the key bindings.
|
||||
|
||||
* Added a new text completion function that suggests words from the
|
||||
history. Bound to Shift-Return.
|
||||
|
||||
* F11 will toggle the maximized state of the frame.
|
||||
|
||||
* switched to Bind() from wx.EVT_*().
|
||||
|
||||
* Display of line numbers can be toggled.
|
||||
|
||||
* F12 toggles a "free edit" mode of the shell buffer. This mode is
|
||||
useful, for example, if you would like to remove some output or
|
||||
errors or etc. from the buffer before doing a copy/paste. The free
|
||||
edit mode is designated by the use of a red, non-flashing caret.
|
||||
|
||||
* Ctrl-H will fold/unfold (hide/show) the selected lines.
|
||||
|
||||
|
||||
|
||||
On top of these changes I (Robin Dunn) added the following:
|
||||
|
||||
* General code cleanup and fixes.
|
||||
|
||||
* Use wx.StandardPaths to determine the location of the config files.
|
||||
|
||||
* Remove Orbtech attributions from the UI, they've been there long
|
||||
enough.
|
||||
|
||||
* Use wx.SP_LIVE_UPDATE on crust and filling windows.
|
||||
|
||||
* Extended the saving of the config info and other new features to the
|
||||
PyShell app too. Additionally, other apps that embed a PyCrust or a
|
||||
PyShell can pass their own wx.Config object and have the Py code
|
||||
save/restore its settings to/from there.
|
||||
|
||||
* All of the classes with config info get an opportunity to save/load
|
||||
their own settings instead of putting all the save/load code in one
|
||||
place that then has to reach all over the place to do anything.
|
||||
|
||||
* Enable editing of the startup python code, which will either be the
|
||||
file pointed to by PYTHONSTARTUP or a file in the config dir if
|
||||
PYTHONSTARTUP is not set in the environment.
|
||||
|
||||
* Added an option to skip the running of the startup code when
|
||||
PyShell or PyCrust starts.
|
||||
|
||||
* PyCrust adds a pp(item) function to the shell's namespace that
|
||||
pretty prints the item in the Display tab of the notebook. Added
|
||||
code to raise that tab when pp() is called.
|
||||
|
||||
* Added an option for whether to insert text for function parameters
|
||||
when popping up the call tip.
|
||||
|
||||
* Added Find and Find-Next functions that use the wx.FindReplaceDialog.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
0.9.4 (1/25/2004 to //2004)
|
||||
------------------------------
|
||||
|
||||
|
@@ -17,15 +17,26 @@ class App(wx.App):
|
||||
"""PyCrust standalone application."""
|
||||
|
||||
def OnInit(self):
|
||||
import os
|
||||
import wx
|
||||
from wx import py
|
||||
wx.InitAllImageHandlers()
|
||||
self.frame = py.crust.CrustFrame()
|
||||
self.frame.SetSize((800, 600))
|
||||
|
||||
self.SetAppName("pycrust")
|
||||
confDir = wx.StandardPaths.Get().GetUserDataDir()
|
||||
if not os.path.exists(confDir):
|
||||
os.mkdir(confDir)
|
||||
fileName = os.path.join(confDir, 'config')
|
||||
self.config = wx.FileConfig(localFilename=fileName)
|
||||
self.config.SetRecordDefaults(True)
|
||||
|
||||
self.frame = py.crust.CrustFrame(config=self.config, dataDir=confDir)
|
||||
## self.frame.startupFileName = os.path.join(confDir,'pycrust_startup')
|
||||
## self.frame.historyFileName = os.path.join(confDir,'pycrust_history')
|
||||
self.frame.Show()
|
||||
self.SetTopWindow(self.frame)
|
||||
return True
|
||||
|
||||
|
||||
|
||||
'''
|
||||
The main() function needs to handle being imported, such as with the
|
||||
pycrust script that wxPython installs:
|
||||
|
@@ -17,14 +17,21 @@ class App(wx.App):
|
||||
"""PyShell standalone application."""
|
||||
|
||||
def OnInit(self):
|
||||
import os
|
||||
import wx
|
||||
from wx import py
|
||||
wx.InitAllImageHandlers()
|
||||
self.frame = py.shell.ShellFrame()
|
||||
self.frame.SetSize((750, 525))
|
||||
|
||||
self.SetAppName("pyshell")
|
||||
confDir = wx.StandardPaths.Get().GetUserDataDir()
|
||||
if not os.path.exists(confDir):
|
||||
os.mkdir(confDir)
|
||||
fileName = os.path.join(confDir, 'config')
|
||||
self.config = wx.FileConfig(localFilename=fileName)
|
||||
self.config.SetRecordDefaults(True)
|
||||
|
||||
self.frame = py.shell.ShellFrame(config=self.config, dataDir=confDir)
|
||||
self.frame.Show()
|
||||
self.SetTopWindow(self.frame)
|
||||
self.frame.shell.SetFocus()
|
||||
return True
|
||||
|
||||
'''
|
||||
|
@@ -8,6 +8,7 @@ import wx
|
||||
|
||||
import os
|
||||
import pprint
|
||||
import re
|
||||
import sys
|
||||
|
||||
import dispatcher
|
||||
@@ -23,55 +24,95 @@ class Crust(wx.SplitterWindow):
|
||||
|
||||
name = 'Crust'
|
||||
revision = __revision__
|
||||
sashoffset = 300
|
||||
|
||||
def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
|
||||
size=wx.DefaultSize, style=wx.SP_3D,
|
||||
def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
|
||||
size=wx.DefaultSize, style=wx.SP_3D|wx.SP_LIVE_UPDATE,
|
||||
name='Crust Window', rootObject=None, rootLabel=None,
|
||||
rootIsNamespace=True, intro='', locals=None,
|
||||
InterpClass=None, *args, **kwds):
|
||||
rootIsNamespace=True, intro='', locals=None,
|
||||
InterpClass=None,
|
||||
startupScript=None, execStartupScript=True,
|
||||
*args, **kwds):
|
||||
"""Create Crust instance."""
|
||||
wx.SplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
||||
self.shell = Shell(parent=self, introText=intro,
|
||||
locals=locals, InterpClass=InterpClass,
|
||||
self.shell = Shell(parent=self, introText=intro,
|
||||
locals=locals, InterpClass=InterpClass,
|
||||
startupScript=startupScript,
|
||||
execStartupScript=execStartupScript,
|
||||
*args, **kwds)
|
||||
self.editor = self.shell
|
||||
if rootObject is None:
|
||||
rootObject = self.shell.interp.locals
|
||||
self.notebook = wx.Notebook(parent=self, id=-1)
|
||||
self.shell.interp.locals['notebook'] = self.notebook
|
||||
self.filling = Filling(parent=self.notebook,
|
||||
rootObject=rootObject,
|
||||
rootLabel=rootLabel,
|
||||
self.filling = Filling(parent=self.notebook,
|
||||
rootObject=rootObject,
|
||||
rootLabel=rootLabel,
|
||||
rootIsNamespace=rootIsNamespace)
|
||||
# Add 'filling' to the interpreter's locals.
|
||||
self.shell.interp.locals['filling'] = self.filling
|
||||
self.notebook.AddPage(page=self.filling, text='Namespace', select=True)
|
||||
|
||||
self.display = Display(parent=self.notebook)
|
||||
self.notebook.AddPage(page=self.display, text='Display')
|
||||
# Add 'pp' (pretty print) to the interpreter's locals.
|
||||
self.shell.interp.locals['pp'] = self.display.setItem
|
||||
self.display.nbTab = self.notebook.GetPageCount()-1
|
||||
|
||||
self.calltip = Calltip(parent=self.notebook)
|
||||
self.notebook.AddPage(page=self.calltip, text='Calltip')
|
||||
|
||||
self.sessionlisting = SessionListing(parent=self.notebook)
|
||||
self.notebook.AddPage(page=self.sessionlisting, text='Session')
|
||||
|
||||
self.dispatcherlisting = DispatcherListing(parent=self.notebook)
|
||||
self.notebook.AddPage(page=self.dispatcherlisting, text='Dispatcher')
|
||||
## from wxd import wx_
|
||||
## self.wxdocs = Filling(parent=self.notebook,
|
||||
## rootObject=wx_,
|
||||
## rootLabel='wx',
|
||||
## rootIsNamespace=False,
|
||||
## static=True)
|
||||
## self.notebook.AddPage(page=self.wxdocs, text='wxPython Docs')
|
||||
## from wxd import stc_
|
||||
## self.stcdocs = Filling(parent=self.notebook,
|
||||
## rootObject=stc_.StyledTextCtrl,
|
||||
## rootLabel='StyledTextCtrl',
|
||||
## rootIsNamespace=False,
|
||||
## static=True)
|
||||
## self.notebook.AddPage(page=self.stcdocs, text='StyledTextCtrl Docs')
|
||||
self.SplitHorizontally(self.shell, self.notebook, 300)
|
||||
self.SetMinimumPaneSize(1)
|
||||
|
||||
self.SplitHorizontally(self.shell, self.notebook, -self.sashoffset)
|
||||
self.SetMinimumPaneSize(100)
|
||||
|
||||
self.Bind(wx.EVT_SIZE, self.SplitterOnSize)
|
||||
self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnChanged)
|
||||
|
||||
|
||||
def OnChanged(self, event):
|
||||
"""update sash offset from the bottom of the window"""
|
||||
self.sashoffset = self.GetSize().height - event.GetSashPosition()
|
||||
event.Skip()
|
||||
|
||||
|
||||
# Make the splitter expand the top window when resized
|
||||
def SplitterOnSize(self, event):
|
||||
splitter = event.GetEventObject()
|
||||
sz = splitter.GetSize()
|
||||
splitter.SetSashPosition(sz.height - self.sashoffset, True)
|
||||
event.Skip()
|
||||
|
||||
|
||||
def LoadSettings(self, config):
|
||||
self.shell.LoadSettings(config)
|
||||
self.filling.LoadSettings(config)
|
||||
|
||||
pos = config.ReadInt('Sash/CrustPos', 400)
|
||||
wx.CallAfter(self.SetSashPosition, pos)
|
||||
def _updateSashPosValue():
|
||||
sz = self.GetSize()
|
||||
self.sashoffset = sz.height - self.GetSashPosition()
|
||||
wx.CallAfter(_updateSashPosValue)
|
||||
zoom = config.ReadInt('View/Zoom/Display', -99)
|
||||
if zoom != -99:
|
||||
self.display.SetZoom(zoom)
|
||||
|
||||
|
||||
def SaveSettings(self, config):
|
||||
self.shell.SaveSettings(config)
|
||||
self.filling.SaveSettings(config)
|
||||
|
||||
config.WriteInt('Sash/CrustPos', self.GetSashPosition())
|
||||
config.WriteInt('View/Zoom/Display', self.display.GetZoom())
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Display(editwindow.EditWindow):
|
||||
@@ -105,15 +146,20 @@ class Display(editwindow.EditWindow):
|
||||
"""Set item to pretty print in the notebook Display tab."""
|
||||
self.item = item
|
||||
self.Refresh()
|
||||
if self.GetParent().GetSelection() != self.nbTab:
|
||||
focus = wx.Window.FindFocus()
|
||||
self.GetParent().SetSelection(self.nbTab)
|
||||
wx.CallAfter(focus.SetFocus)
|
||||
|
||||
|
||||
|
||||
# TODO: Switch this to a editwindow.EditWindow
|
||||
class Calltip(wx.TextCtrl):
|
||||
"""Text control containing the most recent shell calltip."""
|
||||
|
||||
def __init__(self, parent=None, id=-1):
|
||||
style = (wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2)
|
||||
wx.TextCtrl.__init__(self, parent, id, style=style)
|
||||
self.SetBackgroundColour(wx.Colour(255, 255, 232))
|
||||
self.SetBackgroundColour(wx.Colour(255, 255, 208))
|
||||
dispatcher.connect(receiver=self.display, signal='Shell.calltip')
|
||||
|
||||
def display(self, calltip):
|
||||
@@ -123,6 +169,7 @@ class Calltip(wx.TextCtrl):
|
||||
self.AppendText(calltip)
|
||||
|
||||
|
||||
# TODO: Switch this to a editwindow.EditWindow
|
||||
class SessionListing(wx.TextCtrl):
|
||||
"""Text control containing all commands for session."""
|
||||
|
||||
@@ -161,44 +208,58 @@ class DispatcherListing(wx.TextCtrl):
|
||||
self.AppendText(text + '\n')
|
||||
|
||||
|
||||
class CrustFrame(frame.Frame):
|
||||
|
||||
class CrustFrame(frame.Frame, frame.ShellFrameMixin):
|
||||
"""Frame containing all the PyCrust components."""
|
||||
|
||||
name = 'CrustFrame'
|
||||
revision = __revision__
|
||||
|
||||
|
||||
def __init__(self, parent=None, id=-1, title='PyCrust',
|
||||
pos=wx.DefaultPosition, size=wx.DefaultSize,
|
||||
style=wx.DEFAULT_FRAME_STYLE,
|
||||
rootObject=None, rootLabel=None, rootIsNamespace=True,
|
||||
locals=None, InterpClass=None, *args, **kwds):
|
||||
locals=None, InterpClass=None,
|
||||
config=None, dataDir=None,
|
||||
*args, **kwds):
|
||||
"""Create CrustFrame instance."""
|
||||
frame.Frame.__init__(self, parent, id, title, pos, size, style)
|
||||
frame.ShellFrameMixin.__init__(self, config, dataDir)
|
||||
|
||||
if size == wx.DefaultSize:
|
||||
self.SetSize((800, 600))
|
||||
|
||||
intro = 'PyCrust %s - The Flakiest Python Shell' % VERSION
|
||||
intro += '\nSponsored by Orbtech - '
|
||||
intro += 'Your source for Python programming expertise.'
|
||||
self.SetStatusText(intro.replace('\n', ', '))
|
||||
self.crust = Crust(parent=self, intro=intro,
|
||||
rootObject=rootObject,
|
||||
rootLabel=rootLabel,
|
||||
rootIsNamespace=rootIsNamespace,
|
||||
locals=locals,
|
||||
InterpClass=InterpClass, *args, **kwds)
|
||||
InterpClass=InterpClass,
|
||||
startupScript=self.startupScript,
|
||||
execStartupScript=self.execStartupScript,
|
||||
*args, **kwds)
|
||||
self.shell = self.crust.shell
|
||||
|
||||
# Override the filling so that status messages go to the status bar.
|
||||
self.crust.filling.tree.setStatusText = self.SetStatusText
|
||||
|
||||
# Override the shell so that status messages go to the status bar.
|
||||
self.shell.setStatusText = self.SetStatusText
|
||||
# Fix a problem with the sash shrinking to nothing.
|
||||
self.crust.filling.SetSashPosition(200)
|
||||
# Set focus to the shell editor.
|
||||
|
||||
self.shell.SetFocus()
|
||||
self.LoadSettings()
|
||||
|
||||
|
||||
def OnClose(self, event):
|
||||
"""Event handler for closing."""
|
||||
self.SaveSettings()
|
||||
self.crust.shell.destroy()
|
||||
self.Destroy()
|
||||
|
||||
|
||||
def OnAbout(self, event):
|
||||
"""Display an About window."""
|
||||
title = 'About PyCrust'
|
||||
@@ -211,8 +272,33 @@ class CrustFrame(frame.Frame):
|
||||
'Platform: %s\n' % sys.platform + \
|
||||
'Python Version: %s\n' % sys.version.split()[0] + \
|
||||
'wxPython Version: %s\n' % wx.VERSION_STRING + \
|
||||
('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:]))
|
||||
('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:]))
|
||||
dialog = wx.MessageDialog(self, text, title,
|
||||
wx.OK | wx.ICON_INFORMATION)
|
||||
dialog.ShowModal()
|
||||
dialog.Destroy()
|
||||
|
||||
|
||||
|
||||
def LoadSettings(self):
|
||||
if self.config is not None:
|
||||
frame.ShellFrameMixin.LoadSettings(self)
|
||||
frame.Frame.LoadSettings(self, self.config)
|
||||
self.crust.LoadSettings(self.config)
|
||||
|
||||
|
||||
def SaveSettings(self):
|
||||
if self.config is not None:
|
||||
frame.ShellFrameMixin.SaveSettings(self)
|
||||
if self.autoSaveSettings:
|
||||
frame.Frame.SaveSettings(self, self.config)
|
||||
self.crust.SaveSettings(self.config)
|
||||
|
||||
|
||||
def DoSaveSettings(self):
|
||||
if self.config is not None:
|
||||
self.SaveSettings()
|
||||
self.config.Flush()
|
||||
|
||||
|
||||
|
||||
|
@@ -30,7 +30,7 @@ class EditorFrame(frame.Frame):
|
||||
self._defaultText = title + ' - the tastiest Python editor.'
|
||||
self._statusText = self._defaultText
|
||||
self.SetStatusText(self._statusText)
|
||||
wx.EVT_IDLE(self, self.OnIdle)
|
||||
self.Bind(wx.EVT_IDLE, self.OnIdle)
|
||||
self._setup()
|
||||
if filename:
|
||||
self.bufferCreate(filename)
|
||||
@@ -137,7 +137,7 @@ class EditorFrame(frame.Frame):
|
||||
self.bufferDestroy()
|
||||
buffer = Buffer()
|
||||
self.panel = panel = wx.Panel(parent=self, id=-1)
|
||||
wx.EVT_ERASE_BACKGROUND(panel, lambda x: x)
|
||||
panel.Bind (wx.EVT_ERASE_BACKGROUND, lambda x: x)
|
||||
editor = Editor(parent=panel)
|
||||
panel.editor = editor
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
@@ -318,7 +318,7 @@ class EditorNotebookFrame(EditorFrame):
|
||||
"""Create new buffer."""
|
||||
buffer = Buffer()
|
||||
panel = wx.Panel(parent=self.notebook, id=-1)
|
||||
wx.EVT_ERASE_BACKGROUND(panel, lambda x: x)
|
||||
panel.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: x)
|
||||
editor = Editor(parent=panel)
|
||||
panel.editor = editor
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
@@ -366,11 +366,9 @@ class EditorNotebook(wx.Notebook):
|
||||
def __init__(self, parent):
|
||||
"""Create EditorNotebook instance."""
|
||||
wx.Notebook.__init__(self, parent, id=-1, style=wx.CLIP_CHILDREN)
|
||||
wx.EVT_NOTEBOOK_PAGE_CHANGING(self, self.GetId(),
|
||||
self.OnPageChanging)
|
||||
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(),
|
||||
self.OnPageChanged)
|
||||
wx.EVT_IDLE(self, self.OnIdle)
|
||||
self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPageChanging, id=self.GetId())
|
||||
self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged, id=self.GetId())
|
||||
self.Bind(wx.EVT_IDLE, self.OnIdle)
|
||||
|
||||
def OnIdle(self, event):
|
||||
"""Event handler for idle time."""
|
||||
@@ -552,7 +550,7 @@ class EditorShellNotebook(wx.Notebook):
|
||||
self.AddPage(page=self.editor.window, text='Editor', select=True)
|
||||
self.AddPage(page=self.shell, text='Shell')
|
||||
self.editor.setFocus()
|
||||
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), self.OnPageChanged)
|
||||
self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged, id=self.GetId())
|
||||
|
||||
def OnPageChanged(self, event):
|
||||
"""Page changed event handler."""
|
||||
@@ -583,8 +581,8 @@ class Editor:
|
||||
self.id = self.window.GetId()
|
||||
self.buffer = None
|
||||
# Assign handlers for keyboard events.
|
||||
wx.EVT_CHAR(self.window, self.OnChar)
|
||||
wx.EVT_KEY_DOWN(self.window, self.OnKeyDown)
|
||||
self.window.Bind(wx.EVT_CHAR, self.OnChar)
|
||||
self.window.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
|
||||
|
||||
def _setBuffer(self, buffer, text):
|
||||
"""Set the editor to a buffer. Private callback called by buffer."""
|
||||
|
@@ -92,11 +92,10 @@ class EditWindow(stc.StyledTextCtrl):
|
||||
size = 0
|
||||
self.SetZoom(size)
|
||||
|
||||
def __config(self):
|
||||
"""Configure shell based on user preferences."""
|
||||
self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
|
||||
self.SetMarginWidth(1, 40)
|
||||
|
||||
def __config(self):
|
||||
self.setDisplayLineNumbers(False)
|
||||
|
||||
self.SetLexer(stc.STC_LEX_PYTHON)
|
||||
self.SetKeyWords(0, ' '.join(keyword.kwlist))
|
||||
|
||||
@@ -116,6 +115,7 @@ class EditWindow(stc.StyledTextCtrl):
|
||||
self.AutoCompStops(' .,;:([)]}\'"\\<>%^&+-=*/|`')
|
||||
# Do we want to automatically pop up command argument help?
|
||||
self.autoCallTip = True
|
||||
self.callTipInsert = True
|
||||
self.CallTipSetBackground(FACES['calltipbg'])
|
||||
self.CallTipSetForeground(FACES['calltipfg'])
|
||||
self.SetWrapMode(False)
|
||||
@@ -124,6 +124,16 @@ class EditWindow(stc.StyledTextCtrl):
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def setDisplayLineNumbers(self, state):
|
||||
self.lineNumbers = state
|
||||
if state:
|
||||
self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
|
||||
self.SetMarginWidth(1, 40)
|
||||
else:
|
||||
# Leave a small margin so the feature hidden lines marker can be seen
|
||||
self.SetMarginType(1, 0)
|
||||
self.SetMarginWidth(1, 10)
|
||||
|
||||
def setStyles(self, faces):
|
||||
"""Configure font size, typeface and color for lexer."""
|
||||
|
||||
@@ -136,7 +146,7 @@ class EditWindow(stc.StyledTextCtrl):
|
||||
|
||||
# Built in styles
|
||||
self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,
|
||||
"back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces)
|
||||
"back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % FACES)
|
||||
self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR,
|
||||
"face:%(mono)s" % faces)
|
||||
self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
|
||||
@@ -223,3 +233,65 @@ class EditWindow(stc.StyledTextCtrl):
|
||||
def CanPaste(self):
|
||||
"""Return True if pasting should succeed."""
|
||||
return stc.StyledTextCtrl.CanPaste(self) and self.CanEdit()
|
||||
|
||||
|
||||
def GetLastPosition(self):
|
||||
return self.GetLength()
|
||||
|
||||
def GetRange(self, start, end):
|
||||
return self.GetTextRange(start, end)
|
||||
|
||||
def GetSelection(self):
|
||||
return self.GetAnchor(), self.GetCurrentPos()
|
||||
|
||||
def SetSelection(self, start, end):
|
||||
self.SetSelectionStart(start)
|
||||
self.SetSelectionEnd(end)
|
||||
|
||||
def ShowPosition(self, pos):
|
||||
line = self.LineFromPosition(pos)
|
||||
#self.EnsureVisible(line)
|
||||
self.GotoLine(line)
|
||||
|
||||
def DoFindNext(self, findData, findDlg=None):
|
||||
backward = not (findData.GetFlags() & wx.FR_DOWN)
|
||||
matchcase = findData.GetFlags() & wx.FR_MATCHCASE
|
||||
end = self.GetLastPosition()
|
||||
textstring = self.GetRange(0, end)
|
||||
findstring = findData.GetFindString()
|
||||
if not matchcase:
|
||||
textstring.lower()
|
||||
findstring.lower()
|
||||
if backward:
|
||||
start = self.GetSelection()[0]
|
||||
loc = textstring.rfind(findstring, 0, start)
|
||||
else:
|
||||
start = self.GetSelection()[1]
|
||||
loc = textstring.find(findstring, start)
|
||||
|
||||
# if it wasn't found then restart at begining
|
||||
if loc == -1 and start != 0:
|
||||
if backward:
|
||||
start = end
|
||||
loc = textstring.rfind(findstring, 0, start)
|
||||
else:
|
||||
start = 0
|
||||
loc = textstring.find(findstring, start)
|
||||
|
||||
# was it still not found?
|
||||
if loc == -1:
|
||||
dlg = wx.MessageDialog(self, 'Unable to find the search text.',
|
||||
'Not found!',
|
||||
wx.OK | wx.ICON_INFORMATION)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
if findDlg:
|
||||
if loc == -1:
|
||||
wx.CallAfter(findDlg.SetFocus)
|
||||
return
|
||||
else:
|
||||
findDlg.Close()
|
||||
|
||||
# show and select the found text
|
||||
self.ShowPosition(loc)
|
||||
self.SetSelection(loc, loc + len(findstring))
|
||||
|
@@ -61,10 +61,10 @@ class FillingTree(wx.TreeCtrl):
|
||||
rootData = wx.TreeItemData(rootObject)
|
||||
self.item = self.root = self.AddRoot(rootLabel, -1, -1, rootData)
|
||||
self.SetItemHasChildren(self.root, self.objHasChildren(rootObject))
|
||||
wx.EVT_TREE_ITEM_EXPANDING(self, self.GetId(), self.OnItemExpanding)
|
||||
wx.EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemCollapsed)
|
||||
wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
|
||||
wx.EVT_TREE_ITEM_ACTIVATED(self, self.GetId(), self.OnItemActivated)
|
||||
self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding, id=self.GetId())
|
||||
self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=self.GetId())
|
||||
self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=self.GetId())
|
||||
self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated, id=self.GetId())
|
||||
if not static:
|
||||
dispatcher.connect(receiver=self.push, signal='Interpreter.push')
|
||||
|
||||
@@ -277,24 +277,49 @@ class Filling(wx.SplitterWindow):
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
|
||||
size=wx.DefaultSize, style=wx.SP_3D,
|
||||
size=wx.DefaultSize, style=wx.SP_3D|wx.SP_LIVE_UPDATE,
|
||||
name='Filling Window', rootObject=None,
|
||||
rootLabel=None, rootIsNamespace=False, static=False):
|
||||
"""Create a Filling instance."""
|
||||
wx.SplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
||||
|
||||
self.tree = FillingTree(parent=self, rootObject=rootObject,
|
||||
rootLabel=rootLabel,
|
||||
rootIsNamespace=rootIsNamespace,
|
||||
static=static)
|
||||
self.text = FillingText(parent=self, static=static)
|
||||
self.SplitVertically(self.tree, self.text, 130)
|
||||
|
||||
wx.FutureCall(1, self.SplitVertically, self.tree, self.text, 200)
|
||||
|
||||
self.SetMinimumPaneSize(1)
|
||||
|
||||
# Override the filling so that descriptions go to FillingText.
|
||||
self.tree.setText = self.text.SetText
|
||||
|
||||
# Display the root item.
|
||||
## self.tree.SelectItem(self.tree.root)
|
||||
self.tree.SelectItem(self.tree.root)
|
||||
self.tree.display()
|
||||
|
||||
self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnChanged)
|
||||
|
||||
def OnChanged(self, event):
|
||||
#this is important: do not evaluate this event=> otherwise, splitterwindow behaves strange
|
||||
#event.Skip()
|
||||
pass
|
||||
|
||||
|
||||
def LoadSettings(self, config):
|
||||
pos = config.ReadInt('Sash/FillingPos', 200)
|
||||
wx.FutureCall(250, self.SetSashPosition, pos)
|
||||
zoom = config.ReadInt('View/Zoom/Filling', -99)
|
||||
if zoom != -99:
|
||||
self.text.SetZoom(zoom)
|
||||
|
||||
def SaveSettings(self, config):
|
||||
config.WriteInt('Sash/FillingPos', self.GetSashPosition())
|
||||
config.WriteInt('View/Zoom/Filling', self.text.GetZoom())
|
||||
|
||||
|
||||
|
||||
class FillingFrame(wx.Frame):
|
||||
"""Frame containing the namespace tree component."""
|
||||
|
@@ -5,8 +5,9 @@ __cvsid__ = "$Id$"
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
import wx
|
||||
import os
|
||||
from version import VERSION
|
||||
|
||||
import editwindow
|
||||
|
||||
ID_NEW = wx.ID_NEW
|
||||
ID_OPEN = wx.ID_OPEN
|
||||
@@ -23,7 +24,9 @@ ID_COPY = wx.ID_COPY
|
||||
ID_PASTE = wx.ID_PASTE
|
||||
ID_CLEAR = wx.ID_CLEAR
|
||||
ID_SELECTALL = wx.ID_SELECTALL
|
||||
ID_EMPTYBUFFER = wx.NewId()
|
||||
ID_ABOUT = wx.ID_ABOUT
|
||||
ID_HELP = wx.NewId()
|
||||
ID_AUTOCOMP = wx.NewId()
|
||||
ID_AUTOCOMP_SHOW = wx.NewId()
|
||||
ID_AUTOCOMP_MAGIC = wx.NewId()
|
||||
@@ -31,11 +34,25 @@ ID_AUTOCOMP_SINGLE = wx.NewId()
|
||||
ID_AUTOCOMP_DOUBLE = wx.NewId()
|
||||
ID_CALLTIPS = wx.NewId()
|
||||
ID_CALLTIPS_SHOW = wx.NewId()
|
||||
ID_CALLTIPS_INSERT = wx.NewId()
|
||||
ID_COPY_PLUS = wx.NewId()
|
||||
ID_NAMESPACE = wx.NewId()
|
||||
ID_PASTE_PLUS = wx.NewId()
|
||||
ID_WRAP = wx.NewId()
|
||||
ID_TOGGLE_MAXIMIZE = wx.NewId()
|
||||
ID_USEAA = wx.NewId()
|
||||
ID_SHOW_LINENUMBERS = wx.NewId()
|
||||
ID_AUTO_SAVESETTINGS = wx.NewId()
|
||||
ID_SAVEHISTORY = wx.NewId()
|
||||
ID_SAVESETTINGS = wx.NewId()
|
||||
ID_DELSETTINGSFILE = wx.NewId()
|
||||
ID_EDITSTARTUPSCRIPT = wx.NewId()
|
||||
ID_EXECSTARTUPSCRIPT = wx.NewId()
|
||||
ID_STARTUP = wx.NewId()
|
||||
ID_SETTINGS = wx.NewId()
|
||||
ID_FIND = wx.ID_FIND
|
||||
ID_FINDNEXT = wx.NewId()
|
||||
|
||||
|
||||
|
||||
class Frame(wx.Frame):
|
||||
@@ -53,13 +70,28 @@ class Frame(wx.Frame):
|
||||
import images
|
||||
self.SetIcon(images.getPyIcon())
|
||||
self.__createMenus()
|
||||
wx.EVT_CLOSE(self, self.OnClose)
|
||||
|
||||
self.iconized = False
|
||||
self.findDlg = None
|
||||
self.findData = wx.FindReplaceData()
|
||||
self.findData.SetFlags(wx.FR_DOWN)
|
||||
|
||||
self.Bind(wx.EVT_CLOSE, self.OnClose)
|
||||
self.Bind(wx.EVT_ICONIZE, self.OnIconize)
|
||||
|
||||
|
||||
def OnIconize(self, event):
|
||||
"""Event handler for Iconize."""
|
||||
self.iconized = event.Iconized()
|
||||
|
||||
|
||||
def OnClose(self, event):
|
||||
"""Event handler for closing."""
|
||||
self.Destroy()
|
||||
|
||||
|
||||
def __createMenus(self):
|
||||
# File Menu
|
||||
m = self.fileMenu = wx.Menu()
|
||||
m.Append(ID_NEW, '&New \tCtrl+N',
|
||||
'New file')
|
||||
@@ -73,17 +105,18 @@ class Frame(wx.Frame):
|
||||
m.AppendSeparator()
|
||||
m.Append(ID_SAVE, '&Save... \tCtrl+S',
|
||||
'Save file')
|
||||
m.Append(ID_SAVEAS, 'Save &As \tShift+Ctrl+S',
|
||||
m.Append(ID_SAVEAS, 'Save &As \tCtrl+Shift+S',
|
||||
'Save file with new name')
|
||||
m.AppendSeparator()
|
||||
m.Append(ID_PRINT, '&Print... \tCtrl+P',
|
||||
'Print file')
|
||||
m.AppendSeparator()
|
||||
m.Append(ID_NAMESPACE, '&Update Namespace \tShift+Ctrl+N',
|
||||
m.Append(ID_NAMESPACE, '&Update Namespace \tCtrl+Shift+N',
|
||||
'Update namespace for autocompletion and calltips')
|
||||
m.AppendSeparator()
|
||||
m.Append(ID_EXIT, 'E&xit', 'Exit Program')
|
||||
m.Append(ID_EXIT, 'E&xit\tCtrl+Q', 'Exit Program')
|
||||
|
||||
# Edit
|
||||
m = self.editMenu = wx.Menu()
|
||||
m.Append(ID_UNDO, '&Undo \tCtrl+Z',
|
||||
'Undo the last action')
|
||||
@@ -94,105 +127,175 @@ class Frame(wx.Frame):
|
||||
'Cut the selection')
|
||||
m.Append(ID_COPY, '&Copy \tCtrl+C',
|
||||
'Copy the selection')
|
||||
m.Append(ID_COPY_PLUS, 'Cop&y Plus \tShift+Ctrl+C',
|
||||
m.Append(ID_COPY_PLUS, 'Cop&y Plus \tCtrl+Shift+C',
|
||||
'Copy the selection - retaining prompts')
|
||||
m.Append(ID_PASTE, '&Paste \tCtrl+V', 'Paste from clipboard')
|
||||
m.Append(ID_PASTE_PLUS, 'Past&e Plus \tShift+Ctrl+V',
|
||||
m.Append(ID_PASTE_PLUS, 'Past&e Plus \tCtrl+Shift+V',
|
||||
'Paste and run commands')
|
||||
m.AppendSeparator()
|
||||
m.Append(ID_CLEAR, 'Cle&ar',
|
||||
'Delete the selection')
|
||||
m.Append(ID_SELECTALL, 'Select A&ll \tCtrl+A',
|
||||
'Select all text')
|
||||
m.AppendSeparator()
|
||||
m.Append(ID_EMPTYBUFFER, 'E&mpty Buffer',
|
||||
'Delete all the contents of the edit buffer')
|
||||
m.Append(ID_FIND, '&Find Text \tCtrl+F',
|
||||
'Search for text in the edit buffer')
|
||||
m.Append(ID_FINDNEXT, 'Find &Next \tF3',
|
||||
'Find next/previous instance of the search text')
|
||||
|
||||
# View
|
||||
m = self.viewMenu = wx.Menu()
|
||||
m.Append(ID_WRAP, '&Wrap Lines\tCtrl+Shift+W',
|
||||
'Wrap lines at right edge', wx.ITEM_CHECK)
|
||||
m.Append(ID_SHOW_LINENUMBERS, '&Show Line Numbers\tCtrl+Shift+L', 'Show Line Numbers', wx.ITEM_CHECK)
|
||||
m.Append(ID_TOGGLE_MAXIMIZE, '&Toggle Maximize\tF11', 'Maximize/Restore Application')
|
||||
|
||||
# Options
|
||||
m = self.autocompMenu = wx.Menu()
|
||||
m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion',
|
||||
m.Append(ID_AUTOCOMP_SHOW, 'Show &Auto Completion\tCtrl+Shift+A',
|
||||
'Show auto completion list', wx.ITEM_CHECK)
|
||||
m.Append(ID_AUTOCOMP_MAGIC, 'Include Magic Attributes',
|
||||
m.Append(ID_AUTOCOMP_MAGIC, 'Include &Magic Attributes\tCtrl+Shift+M',
|
||||
'Include attributes visible to __getattr__ and __setattr__',
|
||||
wx.ITEM_CHECK)
|
||||
m.Append(ID_AUTOCOMP_SINGLE, 'Include Single Underscores',
|
||||
m.Append(ID_AUTOCOMP_SINGLE, 'Include Single &Underscores\tCtrl+Shift+U',
|
||||
'Include attibutes prefixed by a single underscore', wx.ITEM_CHECK)
|
||||
m.Append(ID_AUTOCOMP_DOUBLE, 'Include Double Underscores',
|
||||
m.Append(ID_AUTOCOMP_DOUBLE, 'Include &Double Underscores\tCtrl+Shift+D',
|
||||
'Include attibutes prefixed by a double underscore', wx.ITEM_CHECK)
|
||||
|
||||
m = self.calltipsMenu = wx.Menu()
|
||||
m.Append(ID_CALLTIPS_SHOW, 'Show Call Tips',
|
||||
m.Append(ID_CALLTIPS_SHOW, 'Show Call &Tips\tCtrl+Shift+T',
|
||||
'Show call tips with argument signature and docstring', wx.ITEM_CHECK)
|
||||
m.Append(ID_CALLTIPS_INSERT, '&Insert Call Tips\tCtrl+Shift+I',
|
||||
'&Insert Call Tips', wx.ITEM_CHECK)
|
||||
|
||||
m = self.optionsMenu = wx.Menu()
|
||||
m.AppendMenu(ID_AUTOCOMP, '&Auto Completion', self.autocompMenu,
|
||||
'Auto Completion Options')
|
||||
m.AppendMenu(ID_CALLTIPS, '&Call Tips', self.calltipsMenu,
|
||||
'Call Tip Options')
|
||||
m.Append(ID_WRAP, '&Wrap Lines',
|
||||
'Wrap lines at right edge', wx.ITEM_CHECK)
|
||||
|
||||
if wx.Platform == "__WXMAC__":
|
||||
m.Append(ID_USEAA, '&Use AntiAliasing',
|
||||
m.Append(ID_USEAA, '&Use AntiAliasing\tCtrl+Shift+A',
|
||||
'Use anti-aliased fonts', wx.ITEM_CHECK)
|
||||
|
||||
m.AppendSeparator()
|
||||
m.Append(ID_SAVEHISTORY, '&Save History\tAlt+Ctrl+A', 'Automatically save history on close', wx.ITEM_CHECK)
|
||||
self.startupMenu = wx.Menu()
|
||||
self.startupMenu.Append(ID_EXECSTARTUPSCRIPT, 'E&xecute Startup Script\tAlt+Ctrl+X', 'Execute Startup Script', wx.ITEM_CHECK)
|
||||
self.startupMenu.Append(ID_EDITSTARTUPSCRIPT, '&Edit Startup Script\tAlt+Ctrl+E', 'Edit Startup Script')
|
||||
m.AppendMenu(ID_STARTUP, '&Startup', self.startupMenu, 'Startup Options')
|
||||
|
||||
self.settingsMenu = wx.Menu()
|
||||
self.settingsMenu.Append(ID_AUTO_SAVESETTINGS, '&Auto Save Settings\tAlt+Ctrl+A', 'Automatically save settings on close', wx.ITEM_CHECK)
|
||||
self.settingsMenu.Append(ID_SAVESETTINGS, '&Save Settings\tAlt+Ctrl+S', 'Save settings now')
|
||||
self.settingsMenu.Append(ID_DELSETTINGSFILE, '&Revert to default\tAlt+Ctrl+R', 'Revert to the default settings')
|
||||
m.AppendMenu(ID_SETTINGS, '&Settings', self.settingsMenu, 'Settings Options')
|
||||
|
||||
m = self.helpMenu = wx.Menu()
|
||||
m.Append(ID_HELP, '&Help\tF1', 'Help!')
|
||||
m.AppendSeparator()
|
||||
m.Append(ID_ABOUT, '&About...', 'About this program')
|
||||
m.Append(ID_ABOUT, '&About...\tAlt+A', 'About this program')
|
||||
|
||||
b = self.menuBar = wx.MenuBar()
|
||||
b.Append(self.fileMenu, '&File')
|
||||
b.Append(self.editMenu, '&Edit')
|
||||
b.Append(self.viewMenu, '&View')
|
||||
b.Append(self.optionsMenu, '&Options')
|
||||
b.Append(self.helpMenu, '&Help')
|
||||
self.SetMenuBar(b)
|
||||
|
||||
wx.EVT_MENU(self, ID_NEW, self.OnFileNew)
|
||||
wx.EVT_MENU(self, ID_OPEN, self.OnFileOpen)
|
||||
wx.EVT_MENU(self, ID_REVERT, self.OnFileRevert)
|
||||
wx.EVT_MENU(self, ID_CLOSE, self.OnFileClose)
|
||||
wx.EVT_MENU(self, ID_SAVE, self.OnFileSave)
|
||||
wx.EVT_MENU(self, ID_SAVEAS, self.OnFileSaveAs)
|
||||
wx.EVT_MENU(self, ID_NAMESPACE, self.OnFileUpdateNamespace)
|
||||
wx.EVT_MENU(self, ID_PRINT, self.OnFilePrint)
|
||||
wx.EVT_MENU(self, ID_EXIT, self.OnExit)
|
||||
wx.EVT_MENU(self, ID_UNDO, self.OnUndo)
|
||||
wx.EVT_MENU(self, ID_REDO, self.OnRedo)
|
||||
wx.EVT_MENU(self, ID_CUT, self.OnCut)
|
||||
wx.EVT_MENU(self, ID_COPY, self.OnCopy)
|
||||
wx.EVT_MENU(self, ID_COPY_PLUS, self.OnCopyPlus)
|
||||
wx.EVT_MENU(self, ID_PASTE, self.OnPaste)
|
||||
wx.EVT_MENU(self, ID_PASTE_PLUS, self.OnPastePlus)
|
||||
wx.EVT_MENU(self, ID_CLEAR, self.OnClear)
|
||||
wx.EVT_MENU(self, ID_SELECTALL, self.OnSelectAll)
|
||||
wx.EVT_MENU(self, ID_ABOUT, self.OnAbout)
|
||||
wx.EVT_MENU(self, ID_AUTOCOMP_SHOW, self.OnAutoCompleteShow)
|
||||
wx.EVT_MENU(self, ID_AUTOCOMP_MAGIC, self.OnAutoCompleteMagic)
|
||||
wx.EVT_MENU(self, ID_AUTOCOMP_SINGLE, self.OnAutoCompleteSingle)
|
||||
wx.EVT_MENU(self, ID_AUTOCOMP_DOUBLE, self.OnAutoCompleteDouble)
|
||||
wx.EVT_MENU(self, ID_CALLTIPS_SHOW, self.OnCallTipsShow)
|
||||
wx.EVT_MENU(self, ID_WRAP, self.OnWrap)
|
||||
wx.EVT_MENU(self, ID_USEAA, self.OnUseAA)
|
||||
self.Bind(wx.EVT_MENU, self.OnFileNew, id=ID_NEW)
|
||||
self.Bind(wx.EVT_MENU, self.OnFileOpen, id=ID_OPEN)
|
||||
self.Bind(wx.EVT_MENU, self.OnFileRevert, id=ID_REVERT)
|
||||
self.Bind(wx.EVT_MENU, self.OnFileClose, id=ID_CLOSE)
|
||||
self.Bind(wx.EVT_MENU, self.OnFileSave, id=ID_SAVE)
|
||||
self.Bind(wx.EVT_MENU, self.OnFileSaveAs, id=ID_SAVEAS)
|
||||
self.Bind(wx.EVT_MENU, self.OnFileUpdateNamespace, id=ID_NAMESPACE)
|
||||
self.Bind(wx.EVT_MENU, self.OnFilePrint, id=ID_PRINT)
|
||||
self.Bind(wx.EVT_MENU, self.OnExit, id=ID_EXIT)
|
||||
self.Bind(wx.EVT_MENU, self.OnUndo, id=ID_UNDO)
|
||||
self.Bind(wx.EVT_MENU, self.OnRedo, id=ID_REDO)
|
||||
self.Bind(wx.EVT_MENU, self.OnCut, id=ID_CUT)
|
||||
self.Bind(wx.EVT_MENU, self.OnCopy, id=ID_COPY)
|
||||
self.Bind(wx.EVT_MENU, self.OnCopyPlus, id=ID_COPY_PLUS)
|
||||
self.Bind(wx.EVT_MENU, self.OnPaste, id=ID_PASTE)
|
||||
self.Bind(wx.EVT_MENU, self.OnPastePlus, id=ID_PASTE_PLUS)
|
||||
self.Bind(wx.EVT_MENU, self.OnClear, id=ID_CLEAR)
|
||||
self.Bind(wx.EVT_MENU, self.OnSelectAll, id=ID_SELECTALL)
|
||||
self.Bind(wx.EVT_MENU, self.OnEmptyBuffer, id=ID_EMPTYBUFFER)
|
||||
self.Bind(wx.EVT_MENU, self.OnAbout, id=ID_ABOUT)
|
||||
self.Bind(wx.EVT_MENU, self.OnHelp, id=ID_HELP)
|
||||
self.Bind(wx.EVT_MENU, self.OnAutoCompleteShow, id=ID_AUTOCOMP_SHOW)
|
||||
self.Bind(wx.EVT_MENU, self.OnAutoCompleteMagic, id=ID_AUTOCOMP_MAGIC)
|
||||
self.Bind(wx.EVT_MENU, self.OnAutoCompleteSingle, id=ID_AUTOCOMP_SINGLE)
|
||||
self.Bind(wx.EVT_MENU, self.OnAutoCompleteDouble, id=ID_AUTOCOMP_DOUBLE)
|
||||
self.Bind(wx.EVT_MENU, self.OnCallTipsShow, id=ID_CALLTIPS_SHOW)
|
||||
self.Bind(wx.EVT_MENU, self.OnCallTipsInsert, id=ID_CALLTIPS_INSERT)
|
||||
self.Bind(wx.EVT_MENU, self.OnWrap, id=ID_WRAP)
|
||||
self.Bind(wx.EVT_MENU, self.OnUseAA, id=ID_USEAA)
|
||||
self.Bind(wx.EVT_MENU, self.OnToggleMaximize, id=ID_TOGGLE_MAXIMIZE)
|
||||
self.Bind(wx.EVT_MENU, self.OnShowLineNumbers, id=ID_SHOW_LINENUMBERS)
|
||||
self.Bind(wx.EVT_MENU, self.OnAutoSaveSettings, id=ID_AUTO_SAVESETTINGS)
|
||||
self.Bind(wx.EVT_MENU, self.OnSaveHistory, id=ID_SAVEHISTORY)
|
||||
self.Bind(wx.EVT_MENU, self.OnSaveSettings, id=ID_SAVESETTINGS)
|
||||
self.Bind(wx.EVT_MENU, self.OnDelSettingsFile, id=ID_DELSETTINGSFILE)
|
||||
self.Bind(wx.EVT_MENU, self.OnEditStartupScript, id=ID_EDITSTARTUPSCRIPT)
|
||||
self.Bind(wx.EVT_MENU, self.OnExecStartupScript, id=ID_EXECSTARTUPSCRIPT)
|
||||
self.Bind(wx.EVT_MENU, self.OnFindText, id=ID_FIND)
|
||||
self.Bind(wx.EVT_MENU, self.OnFindNext, id=ID_FINDNEXT)
|
||||
|
||||
wx.EVT_UPDATE_UI(self, ID_NEW, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_OPEN, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_REVERT, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_CLOSE, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_SAVE, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_SAVEAS, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_NAMESPACE, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_PRINT, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_UNDO, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_REDO, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_CUT, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_COPY, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_COPY_PLUS, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_PASTE, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_PASTE_PLUS, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_CLEAR, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_SELECTALL, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_SHOW, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_MAGIC, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_SINGLE, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_DOUBLE, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_CALLTIPS_SHOW, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_WRAP, self.OnUpdateMenu)
|
||||
wx.EVT_UPDATE_UI(self, ID_USEAA, self.OnUpdateMenu)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_NEW)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_OPEN)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_REVERT)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CLOSE)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVE)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVEAS)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_NAMESPACE)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_PRINT)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_UNDO)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_REDO)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CUT)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_COPY)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_COPY_PLUS)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_PASTE)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_PASTE_PLUS)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CLEAR)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SELECTALL)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EMPTYBUFFER)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_SHOW)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_MAGIC)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_SINGLE)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_DOUBLE)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CALLTIPS_SHOW)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CALLTIPS_INSERT)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_WRAP)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_USEAA)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SHOW_LINENUMBERS)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTO_SAVESETTINGS)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVESETTINGS)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_DELSETTINGSFILE)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EXECSTARTUPSCRIPT)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVEHISTORY)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EDITSTARTUPSCRIPT)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_FIND)
|
||||
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_FINDNEXT)
|
||||
|
||||
self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
|
||||
self.Bind(wx.EVT_FIND, self.OnFindNext)
|
||||
self.Bind(wx.EVT_FIND_NEXT, self.OnFindNext)
|
||||
self.Bind(wx.EVT_FIND_CLOSE, self.OnFindClose)
|
||||
|
||||
|
||||
|
||||
def OnShowLineNumbers(self, event):
|
||||
win = wx.Window.FindFocus()
|
||||
if hasattr(win, 'lineNumbers'):
|
||||
win.lineNumbers = event.IsChecked()
|
||||
win.setDisplayLineNumbers(win.lineNumbers)
|
||||
|
||||
def OnToggleMaximize(self, event):
|
||||
self.Maximize(not self.IsMaximized())
|
||||
|
||||
def OnFileNew(self, event):
|
||||
self.bufferNew()
|
||||
@@ -222,39 +325,52 @@ class Frame(wx.Frame):
|
||||
self.Close(False)
|
||||
|
||||
def OnUndo(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.Undo()
|
||||
|
||||
def OnRedo(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.Redo()
|
||||
|
||||
def OnCut(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.Cut()
|
||||
|
||||
def OnCopy(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.Copy()
|
||||
|
||||
def OnCopyPlus(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.CopyWithPrompts()
|
||||
|
||||
def OnPaste(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.Paste()
|
||||
|
||||
def OnPastePlus(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.PasteAndRun()
|
||||
|
||||
def OnClear(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.Clear()
|
||||
|
||||
def OnEmptyBuffer(self, event):
|
||||
win = wx.Window.FindFocus()
|
||||
d = wx.MessageDialog(self,
|
||||
"Are you sure you want to clear the edit buffer,\n"
|
||||
"deleting all the text?",
|
||||
"Empty Buffer", wx.OK | wx.CANCEL | wx.ICON_QUESTION)
|
||||
answer = d.ShowModal()
|
||||
d.Destroy()
|
||||
if (answer == wx.ID_OK):
|
||||
win.ClearAll()
|
||||
if hasattr(win,'prompt'):
|
||||
win.prompt()
|
||||
|
||||
def OnSelectAll(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.SelectAll()
|
||||
|
||||
def OnAbout(self, event):
|
||||
@@ -266,38 +382,102 @@ class Frame(wx.Frame):
|
||||
dialog.ShowModal()
|
||||
dialog.Destroy()
|
||||
|
||||
def OnHelp(self, event):
|
||||
"""Display a Help window."""
|
||||
title = 'Help'
|
||||
text = "Type 'shell.help()' in the shell window."
|
||||
dialog = wx.MessageDialog(self, text, title,
|
||||
wx.OK | wx.ICON_INFORMATION)
|
||||
dialog.ShowModal()
|
||||
dialog.Destroy()
|
||||
|
||||
def OnAutoCompleteShow(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.autoComplete = event.IsChecked()
|
||||
|
||||
def OnAutoCompleteMagic(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.autoCompleteIncludeMagic = event.IsChecked()
|
||||
|
||||
def OnAutoCompleteSingle(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.autoCompleteIncludeSingle = event.IsChecked()
|
||||
|
||||
def OnAutoCompleteDouble(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.autoCompleteIncludeDouble = event.IsChecked()
|
||||
|
||||
def OnCallTipsShow(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.autoCallTip = event.IsChecked()
|
||||
|
||||
def OnCallTipsInsert(self, event):
|
||||
win = wx.Window.FindFocus()
|
||||
win.callTipInsert = event.IsChecked()
|
||||
|
||||
def OnWrap(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.SetWrapMode(event.IsChecked())
|
||||
wx.FutureCall(1, self.shell.EnsureCaretVisible)
|
||||
|
||||
def OnUseAA(self, event):
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
win.SetUseAntiAliasing(event.IsChecked())
|
||||
|
||||
def OnSaveHistory(self, event):
|
||||
self.saveHistory = event.IsChecked()
|
||||
|
||||
def OnAutoSaveSettings(self, event):
|
||||
self.autoSaveSettings = event.IsChecked()
|
||||
|
||||
def OnSaveSettings(self, event):
|
||||
self.DoSaveSettings()
|
||||
|
||||
def OnDelSettingsFile(self, event):
|
||||
if self.config is not None:
|
||||
d = wx.MessageDialog(
|
||||
self, "Do you want to revert to the default settings?\n" +
|
||||
"A restart is needed for the change to take effect",
|
||||
"Warning", wx.OK | wx.CANCEL | wx.ICON_QUESTION)
|
||||
answer = d.ShowModal()
|
||||
d.Destroy()
|
||||
if (answer == wx.ID_OK):
|
||||
self.config.DeleteAll()
|
||||
self.LoadSettings()
|
||||
|
||||
|
||||
def OnEditStartupScript(self, event):
|
||||
if hasattr(self, 'EditStartupScript'):
|
||||
self.EditStartupScript()
|
||||
|
||||
def OnExecStartupScript(self, event):
|
||||
self.execStartupScript = event.IsChecked()
|
||||
|
||||
|
||||
def OnFindText(self, event):
|
||||
if self.findDlg is not None:
|
||||
return
|
||||
win = wx.Window.FindFocus()
|
||||
self.findDlg = wx.FindReplaceDialog(win, self.findData, "Find",
|
||||
wx.FR_NOWHOLEWORD)
|
||||
self.findDlg.Show()
|
||||
|
||||
def OnFindNext(self, event):
|
||||
if isinstance(event, wx.FindDialogEvent):
|
||||
win = self.findDlg.GetParent()
|
||||
else:
|
||||
win = wx.Window.FindFocus()
|
||||
win.DoFindNext(self.findData, self.findDlg)
|
||||
|
||||
def OnFindClose(self, event):
|
||||
self.findDlg.Destroy()
|
||||
self.findDlg = None
|
||||
|
||||
|
||||
|
||||
def OnUpdateMenu(self, event):
|
||||
"""Update menu items based on current status and context."""
|
||||
win = wx.Window_FindFocus()
|
||||
win = wx.Window.FindFocus()
|
||||
id = event.GetId()
|
||||
event.Enable(True)
|
||||
try:
|
||||
@@ -341,6 +521,8 @@ class Frame(wx.Frame):
|
||||
event.Enable(win.CanCut())
|
||||
elif id == ID_SELECTALL:
|
||||
event.Enable(hasattr(win, 'SelectAll'))
|
||||
elif id == ID_EMPTYBUFFER:
|
||||
event.Enable(hasattr(win, 'ClearAll') and not win.GetReadOnly())
|
||||
elif id == ID_AUTOCOMP_SHOW:
|
||||
event.Check(win.autoComplete)
|
||||
elif id == ID_AUTOCOMP_MAGIC:
|
||||
@@ -351,12 +533,273 @@ class Frame(wx.Frame):
|
||||
event.Check(win.autoCompleteIncludeDouble)
|
||||
elif id == ID_CALLTIPS_SHOW:
|
||||
event.Check(win.autoCallTip)
|
||||
elif id == ID_CALLTIPS_INSERT:
|
||||
event.Check(win.callTipInsert)
|
||||
elif id == ID_WRAP:
|
||||
event.Check(win.GetWrapMode())
|
||||
elif id == ID_USEAA:
|
||||
event.Check(win.GetUseAntiAliasing())
|
||||
|
||||
elif id == ID_SHOW_LINENUMBERS:
|
||||
event.Check(win.lineNumbers)
|
||||
elif id == ID_AUTO_SAVESETTINGS:
|
||||
event.Check(self.autoSaveSettings)
|
||||
elif id == ID_SAVESETTINGS:
|
||||
event.Enable(self.config is not None and
|
||||
hasattr(self, 'DoSaveSettings'))
|
||||
elif id == ID_DELSETTINGSFILE:
|
||||
event.Enable(self.config is not None)
|
||||
|
||||
elif id == ID_EXECSTARTUPSCRIPT:
|
||||
event.Check(self.execStartupScript)
|
||||
|
||||
elif id == ID_SAVEHISTORY:
|
||||
event.Check(self.saveHistory and self.dataDir is not None)
|
||||
elif id == ID_EDITSTARTUPSCRIPT:
|
||||
event.Enable(hasattr(self, 'EditStartupScript'))
|
||||
|
||||
elif id == ID_FIND:
|
||||
event.Enable(hasattr(win, 'DoFindNext'))
|
||||
elif id == ID_FINDNEXT:
|
||||
event.Enable(hasattr(win, 'DoFindNext') and
|
||||
self.findData.GetFindString() != '')
|
||||
|
||||
else:
|
||||
event.Enable(False)
|
||||
except AttributeError:
|
||||
# This menu option is not supported in the current context.
|
||||
event.Enable(False)
|
||||
|
||||
|
||||
def OnActivate(self, event):
|
||||
"""
|
||||
Event Handler for losing the focus of the Frame. Should close
|
||||
Autocomplete listbox, if shown.
|
||||
"""
|
||||
if not event.GetActive():
|
||||
# If autocomplete active, cancel it. Otherwise, the
|
||||
# autocomplete list will stay visible on top of the
|
||||
# z-order after switching to another application
|
||||
win = wx.Window.FindFocus()
|
||||
if hasattr(win, 'AutoCompActive') and win.AutoCompActive():
|
||||
win.AutoCompCancel()
|
||||
event.Skip()
|
||||
|
||||
|
||||
|
||||
def LoadSettings(self, config):
|
||||
"""Called be derived classes to load settings specific to the Frame"""
|
||||
pos = wx.Point(config.ReadInt('Window/PosX', -1),
|
||||
config.ReadInt('Window/PosY', -1))
|
||||
|
||||
size = wx.Size(config.ReadInt('Window/Width', -1),
|
||||
config.ReadInt('Window/Height', -1))
|
||||
|
||||
self.SetSize(size)
|
||||
self.Move(pos)
|
||||
|
||||
|
||||
def SaveSettings(self, config):
|
||||
"""Called by derived classes to save Frame settings to a wx.Config object"""
|
||||
|
||||
# TODO: track position/size so we can save it even if the
|
||||
# frame is maximized or iconized.
|
||||
if not self.iconized and not self.IsMaximized():
|
||||
w, h = self.GetSize()
|
||||
config.WriteInt('Window/Width', w)
|
||||
config.WriteInt('Window/Height', h)
|
||||
|
||||
px, py = self.GetPosition()
|
||||
config.WriteInt('Window/PosX', px)
|
||||
config.WriteInt('Window/PosY', py)
|
||||
|
||||
|
||||
|
||||
|
||||
class ShellFrameMixin:
|
||||
"""
|
||||
A mix-in class for frames that will have a Shell or a Crust window
|
||||
and that want to add history, startupScript and other common
|
||||
functionality.
|
||||
"""
|
||||
def __init__(self, config, dataDir):
|
||||
self.config = config
|
||||
self.dataDir = dataDir
|
||||
self.startupScript = os.environ.get('PYTHONSTARTUP')
|
||||
if not self.startupScript and self.dataDir:
|
||||
self.startupScript = os.path.join(self.dataDir, 'startup')
|
||||
|
||||
self.autoSaveSettings = False
|
||||
self.saveHistory = False
|
||||
|
||||
# We need this one before we have a chance to load the settings...
|
||||
self.execStartupScript = True
|
||||
if self.config:
|
||||
self.execStartupScript = self.config.ReadBool('Options/ExecStartupScript', True)
|
||||
|
||||
|
||||
def OnHelp(self, event):
|
||||
"""Display a Help window."""
|
||||
import wx.lib.dialogs
|
||||
title = 'Help on key bindings'
|
||||
|
||||
text = wx.py.shell.HELP_TEXT
|
||||
|
||||
dlg = wx.lib.dialogs.ScrolledMessageDialog(self, text, title, size = ((700, 540)))
|
||||
fnt = wx.Font(10, wx.TELETYPE, wx.NORMAL, wx.NORMAL)
|
||||
dlg.GetChildren()[0].SetFont(fnt)
|
||||
dlg.GetChildren()[0].SetInsertionPoint(0)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
|
||||
def LoadSettings(self):
|
||||
if self.config is not None:
|
||||
self.autoSaveSettings = self.config.ReadBool('Options/AutoSaveSettings', False)
|
||||
self.execStartupScript = self.config.ReadBool('Options/ExecStartupScript', True)
|
||||
self.saveHistory = self.config.ReadBool('Options/SaveHistory', False)
|
||||
self.LoadHistory()
|
||||
|
||||
|
||||
def SaveSettings(self):
|
||||
if self.config is not None:
|
||||
# always save this one
|
||||
self.config.WriteBool('Options/AutoSaveSettings', self.autoSaveSettings)
|
||||
if self.autoSaveSettings:
|
||||
self.config.WriteBool('Options/SaveHistory', self.saveHistory)
|
||||
self.config.WriteBool('Options/ExecStartupScript', self.execStartupScript)
|
||||
self.SaveHistory()
|
||||
|
||||
|
||||
|
||||
def SaveHistory(self):
|
||||
if self.dataDir:
|
||||
try:
|
||||
# always open the file so that when we are not
|
||||
# saving the history, the old file is emptied.
|
||||
name = os.path.join(self.dataDir, 'history')
|
||||
f = file(name, 'w')
|
||||
if self.saveHistory:
|
||||
hist = '\n'.join(self.shell.history)
|
||||
f.write(hist)
|
||||
f.close()
|
||||
except:
|
||||
d = wx.MessageDialog(self, "Error saving history file.",
|
||||
"Error", wx.ICON_EXCLAMATION)
|
||||
d.ShowModal()
|
||||
d.Destroy()
|
||||
|
||||
|
||||
def LoadHistory(self):
|
||||
if self.dataDir:
|
||||
name = os.path.join(self.dataDir, 'history')
|
||||
if os.path.exists(name):
|
||||
try:
|
||||
f = file(name, 'U')
|
||||
hist = f.read()
|
||||
f.close()
|
||||
self.shell.history = hist.split('\n')
|
||||
except:
|
||||
d = wx.MessageDialog(self, "Error loading history file.",
|
||||
"Error", wx.ICON_EXCLAMATION)
|
||||
d.ShowModal()
|
||||
d.Destroy()
|
||||
|
||||
|
||||
def bufferHasChanged(self):
|
||||
# the shell buffers can always be saved
|
||||
return True
|
||||
|
||||
def bufferSave(self):
|
||||
import time
|
||||
appname = wx.GetApp().GetAppName()
|
||||
default = appname + '-' + time.strftime("%Y%m%d-%H%M.py")
|
||||
fileName = wx.FileSelector("Save File As", "Saving",
|
||||
default_filename=default,
|
||||
default_extension="py",
|
||||
wildcard="*.py",
|
||||
flags = wx.SAVE | wx.OVERWRITE_PROMPT)
|
||||
if not fileName:
|
||||
return
|
||||
|
||||
text = self.shell.GetText()
|
||||
|
||||
## This isn't working currently...
|
||||
## d = wx.MessageDialog(self,u'Save source code only?\nAnswering yes will only save lines starting with >>> and ...',u'Question', wx.YES_NO | wx.ICON_QUESTION)
|
||||
## yes_no = d.ShowModal()
|
||||
## if yes_no == wx.ID_YES:
|
||||
## m = re.findall('^[>\.]{3,3} (.*)\r', text, re.MULTILINE | re.LOCALE)
|
||||
## text = '\n'.join(m)
|
||||
## d.Destroy()
|
||||
|
||||
try:
|
||||
f = open(fileName, "w")
|
||||
f.write(text)
|
||||
f.close()
|
||||
except:
|
||||
d = wx.MessageDialog(self, u'Error saving session',u'Error',
|
||||
wx.OK | wx.ICON_ERROR)
|
||||
d.ShowModal()
|
||||
d.Destroy()
|
||||
|
||||
|
||||
def EditStartupScript(self):
|
||||
if os.path.exists(self.startupScript):
|
||||
text = file(self.startupScript, 'U').read()
|
||||
else:
|
||||
text = ''
|
||||
|
||||
dlg = EditStartupScriptDialog(self, self.startupScript, text)
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
text = dlg.GetText()
|
||||
try:
|
||||
f = file(self.startupScript, 'w')
|
||||
f.write(text)
|
||||
f.close()
|
||||
except:
|
||||
d = wx.MessageDialog(self, "Error saving startup file.",
|
||||
"Error", wx.ICON_EXCLAMATION)
|
||||
d.ShowModal()
|
||||
d.Destroy()
|
||||
|
||||
|
||||
|
||||
class EditStartupScriptDialog(wx.Dialog):
|
||||
def __init__(self, parent, fileName, text):
|
||||
wx.Dialog.__init__(self, parent, size=(425,350),
|
||||
title="Edit Startup Script",
|
||||
style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
|
||||
|
||||
pst = wx.StaticText(self, -1, "Path:")
|
||||
ptx = wx.TextCtrl(self, -1, fileName, style=wx.TE_READONLY)
|
||||
self.editor = editwindow.EditWindow(self)
|
||||
self.editor.SetText(text)
|
||||
wx.CallAfter(self.editor.SetFocus)
|
||||
|
||||
ok = wx.Button(self, wx.ID_OK)
|
||||
cancel = wx.Button(self, wx.ID_CANCEL)
|
||||
|
||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
pthSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
pthSizer.Add(pst, flag=wx.ALIGN_CENTER_VERTICAL)
|
||||
pthSizer.Add((5,5))
|
||||
pthSizer.Add(ptx, 1)
|
||||
mainSizer.Add(pthSizer, 0, wx.EXPAND|wx.ALL, 10)
|
||||
|
||||
mainSizer.Add(self.editor, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 10)
|
||||
|
||||
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnSizer.Add((5,5), 1)
|
||||
btnSizer.Add(ok)
|
||||
btnSizer.Add((5,5), 1)
|
||||
btnSizer.Add(cancel)
|
||||
btnSizer.Add((5,5), 1)
|
||||
mainSizer.Add(btnSizer, 0, wx.EXPAND|wx.ALL, 10)
|
||||
|
||||
self.SetSizer(mainSizer)
|
||||
self.Layout()
|
||||
|
||||
|
||||
def GetText(self):
|
||||
return self.editor.GetText()
|
||||
|
@@ -42,7 +42,8 @@ class Interpreter(InteractiveInterpreter):
|
||||
self.more = 0
|
||||
# List of lists to support recursive push().
|
||||
self.commandBuffer = []
|
||||
self.startupScript = os.environ.get('PYTHONSTARTUP')
|
||||
self.startupScript = None
|
||||
|
||||
|
||||
def push(self, command):
|
||||
"""Send command to the interpreter to be executed.
|
||||
|
@@ -31,7 +31,7 @@ NAVKEYS = (wx.WXK_END, wx.WXK_LEFT, wx.WXK_RIGHT,
|
||||
wx.WXK_UP, wx.WXK_DOWN, wx.WXK_PRIOR, wx.WXK_NEXT)
|
||||
|
||||
|
||||
class ShellFrame(frame.Frame):
|
||||
class ShellFrame(frame.Frame, frame.ShellFrameMixin):
|
||||
"""Frame containing the shell component."""
|
||||
|
||||
name = 'Shell Frame'
|
||||
@@ -40,19 +40,31 @@ class ShellFrame(frame.Frame):
|
||||
def __init__(self, parent=None, id=-1, title='PyShell',
|
||||
pos=wx.DefaultPosition, size=wx.DefaultSize,
|
||||
style=wx.DEFAULT_FRAME_STYLE, locals=None,
|
||||
InterpClass=None, *args, **kwds):
|
||||
InterpClass=None,
|
||||
config=None, dataDir=None,
|
||||
*args, **kwds):
|
||||
"""Create ShellFrame instance."""
|
||||
frame.Frame.__init__(self, parent, id, title, pos, size, style)
|
||||
frame.ShellFrameMixin.__init__(self, config, dataDir)
|
||||
|
||||
if size == wx.DefaultSize:
|
||||
self.SetSize((750, 525))
|
||||
|
||||
intro = 'PyShell %s - The Flakiest Python Shell' % VERSION
|
||||
intro += '\nSponsored by Orbtech - ' + \
|
||||
'Your source for Python programming expertise.'
|
||||
self.SetStatusText(intro.replace('\n', ', '))
|
||||
self.shell = Shell(parent=self, id=-1, introText=intro,
|
||||
locals=locals, InterpClass=InterpClass,
|
||||
startupScript=self.startupScript,
|
||||
execStartupScript=self.execStartupScript,
|
||||
*args, **kwds)
|
||||
|
||||
# Override the shell so that status messages go to the status bar.
|
||||
self.shell.setStatusText = self.SetStatusText
|
||||
|
||||
self.shell.SetFocus()
|
||||
self.LoadSettings()
|
||||
|
||||
|
||||
def OnClose(self, event):
|
||||
"""Event handler for closing."""
|
||||
# This isn't working the way I want, but I'll leave it for now.
|
||||
@@ -60,6 +72,7 @@ class ShellFrame(frame.Frame):
|
||||
if event.CanVeto():
|
||||
event.Veto(True)
|
||||
else:
|
||||
self.SaveSettings()
|
||||
self.shell.destroy()
|
||||
self.Destroy()
|
||||
|
||||
@@ -82,21 +95,28 @@ class ShellFrame(frame.Frame):
|
||||
dialog.Destroy()
|
||||
|
||||
|
||||
class ShellFacade:
|
||||
"""Simplified interface to all shell-related functionality.
|
||||
def LoadSettings(self):
|
||||
if self.config is not None:
|
||||
frame.ShellFrameMixin.LoadSettings(self)
|
||||
frame.Frame.LoadSettings(self, self.config)
|
||||
self.shell.LoadSettings(self.config)
|
||||
|
||||
This is a semi-transparent facade, in that all attributes of other
|
||||
are accessible, even though only some are visible to the user."""
|
||||
def SaveSettings(self):
|
||||
if self.config is not None:
|
||||
frame.ShellFrameMixin.SaveSettings(self)
|
||||
if self.autoSaveSettings:
|
||||
frame.Frame.SaveSettings(self, self.config)
|
||||
self.shell.SaveSettings(self.config)
|
||||
|
||||
name = 'Shell Interface'
|
||||
revision = __revision__
|
||||
def DoSaveSettings(self):
|
||||
if self.config is not None:
|
||||
self.SaveSettings()
|
||||
self.config.Flush()
|
||||
|
||||
|
||||
def __init__(self, other):
|
||||
"""Create a ShellFacade instance."""
|
||||
d = self.__dict__
|
||||
d['other'] = other
|
||||
d['helpText'] = \
|
||||
"""
|
||||
|
||||
|
||||
HELP_TEXT = """\
|
||||
* Key bindings:
|
||||
Home Go to the beginning of the command or line.
|
||||
Shift+Home Select to the beginning of the command or line.
|
||||
@@ -104,6 +124,7 @@ Shift+End Select to the end of the line.
|
||||
End Go to the end of the line.
|
||||
Ctrl+C Copy selected text, removing prompts.
|
||||
Ctrl+Shift+C Copy selected text, retaining prompts.
|
||||
Alt+C Copy to the clipboard, including prefixed prompts.
|
||||
Ctrl+X Cut selected text.
|
||||
Ctrl+V Paste from clipboard.
|
||||
Ctrl+Shift+V Paste and run multiple commands from clipboard.
|
||||
@@ -119,8 +140,31 @@ Ctrl+Enter Insert new line into multiline command.
|
||||
Ctrl+] Increase font size.
|
||||
Ctrl+[ Decrease font size.
|
||||
Ctrl+= Default font size.
|
||||
Ctrl-Space Show Auto Completion.
|
||||
Ctrl-Alt-Space Show Call Tip.
|
||||
Alt+Shift+C Clear Screen.
|
||||
Shift+Enter Complete Text from History.
|
||||
Ctrl+F Search (backwards) TODO: regexp-wholeWords-...
|
||||
Ctrl+G Search next
|
||||
Ctrl+H "hide" lines containing selection / "unhide"
|
||||
F12 on/off "free-edit" mode
|
||||
"""
|
||||
|
||||
class ShellFacade:
|
||||
"""Simplified interface to all shell-related functionality.
|
||||
|
||||
This is a semi-transparent facade, in that all attributes of other
|
||||
are accessible, even though only some are visible to the user."""
|
||||
|
||||
name = 'Shell Interface'
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, other):
|
||||
"""Create a ShellFacade instance."""
|
||||
d = self.__dict__
|
||||
d['other'] = other
|
||||
d['helpText'] = HELP_TEXT
|
||||
|
||||
def help(self):
|
||||
"""Display some useful information about how to use the shell."""
|
||||
self.write(self.helpText)
|
||||
@@ -151,6 +195,7 @@ Ctrl+= Default font size.
|
||||
'autoCompleteIncludeDouble',
|
||||
'autoCompleteIncludeMagic',
|
||||
'autoCompleteIncludeSingle',
|
||||
'callTipInsert',
|
||||
'clear',
|
||||
'pause',
|
||||
'prompt',
|
||||
@@ -167,6 +212,7 @@ Ctrl+= Default font size.
|
||||
return list
|
||||
|
||||
|
||||
|
||||
class Shell(editwindow.EditWindow):
|
||||
"""Shell based on StyledTextCtrl."""
|
||||
|
||||
@@ -175,26 +221,32 @@ class Shell(editwindow.EditWindow):
|
||||
|
||||
def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
|
||||
size=wx.DefaultSize, style=wx.CLIP_CHILDREN,
|
||||
introText='', locals=None, InterpClass=None, *args, **kwds):
|
||||
introText='', locals=None, InterpClass=None,
|
||||
startupScript=None, execStartupScript=True,
|
||||
*args, **kwds):
|
||||
"""Create Shell instance."""
|
||||
editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
|
||||
self.wrap()
|
||||
if locals is None:
|
||||
import __main__
|
||||
locals = __main__.__dict__
|
||||
|
||||
# Grab these so they can be restored by self.redirect* methods.
|
||||
self.stdin = sys.stdin
|
||||
self.stdout = sys.stdout
|
||||
self.stderr = sys.stderr
|
||||
|
||||
# Import a default interpreter class if one isn't provided.
|
||||
if InterpClass == None:
|
||||
from interpreter import Interpreter
|
||||
else:
|
||||
Interpreter = InterpClass
|
||||
|
||||
# Create a replacement for stdin.
|
||||
self.reader = PseudoFileIn(self.readline, self.readlines)
|
||||
self.reader.input = ''
|
||||
self.reader.isreading = False
|
||||
|
||||
# Set up the interpreter.
|
||||
self.interp = Interpreter(locals=locals,
|
||||
rawin=self.raw_input,
|
||||
@@ -202,15 +254,20 @@ class Shell(editwindow.EditWindow):
|
||||
stdout=PseudoFileOut(self.writeOut),
|
||||
stderr=PseudoFileErr(self.writeErr),
|
||||
*args, **kwds)
|
||||
|
||||
# Set up the buffer.
|
||||
self.buffer = Buffer()
|
||||
|
||||
# Find out for which keycodes the interpreter will autocomplete.
|
||||
self.autoCompleteKeys = self.interp.getAutoCompleteKeys()
|
||||
|
||||
# Keep track of the last non-continuation prompt positions.
|
||||
self.promptPosStart = 0
|
||||
self.promptPosEnd = 0
|
||||
|
||||
# Keep track of multi-line commands.
|
||||
self.more = False
|
||||
|
||||
# Create the command history. Commands are added into the
|
||||
# front of the list (ie. at index 0) as they are entered.
|
||||
# self.historyIndex is the current position in the history; it
|
||||
@@ -220,23 +277,46 @@ class Shell(editwindow.EditWindow):
|
||||
# command, not in the history.
|
||||
self.history = []
|
||||
self.historyIndex = -1
|
||||
|
||||
#seb add mode for "free edit"
|
||||
self.noteMode = 0
|
||||
self.MarkerDefine(0,stc.STC_MARK_ROUNDRECT) # marker for hidden
|
||||
self.searchTxt = ""
|
||||
|
||||
# Assign handlers for keyboard events.
|
||||
wx.EVT_CHAR(self, self.OnChar)
|
||||
wx.EVT_KEY_DOWN(self, self.OnKeyDown)
|
||||
self.Bind(wx.EVT_CHAR, self.OnChar)
|
||||
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
|
||||
|
||||
# Assign handler for idle time.
|
||||
self.waiting = False
|
||||
wx.EVT_IDLE(self, self.OnIdle)
|
||||
self.Bind(wx.EVT_IDLE, self.OnIdle)
|
||||
|
||||
# Display the introductory banner information.
|
||||
self.showIntro(introText)
|
||||
|
||||
# Assign some pseudo keywords to the interpreter's namespace.
|
||||
self.setBuiltinKeywords()
|
||||
|
||||
# Add 'shell' to the interpreter's local namespace.
|
||||
self.setLocalShell()
|
||||
|
||||
## NOTE: See note at bottom of this file...
|
||||
## #seb: File drag and drop
|
||||
## self.SetDropTarget( FileDropTarget(self) )
|
||||
|
||||
# Do this last so the user has complete control over their
|
||||
# environment. They can override anything they want.
|
||||
self.execStartupScript(self.interp.startupScript)
|
||||
if execStartupScript:
|
||||
if startupScript is None:
|
||||
startupScript = os.environ.get('PYTHONSTARTUP')
|
||||
self.execStartupScript(startupScript)
|
||||
else:
|
||||
self.prompt()
|
||||
|
||||
wx.CallAfter(self.ScrollToLine, 0)
|
||||
|
||||
|
||||
|
||||
def destroy(self):
|
||||
del self.interp
|
||||
|
||||
@@ -270,29 +350,32 @@ class Shell(editwindow.EditWindow):
|
||||
__builtin__.close = __builtin__.exit = __builtin__.quit = \
|
||||
'Click on the close button to leave the application.'
|
||||
|
||||
|
||||
def quit(self):
|
||||
"""Quit the application."""
|
||||
|
||||
# XXX Good enough for now but later we want to send a close event.
|
||||
|
||||
# In the close event handler we can make sure they want to
|
||||
# quit. Other applications, like PythonCard, may choose to
|
||||
# hide rather than quit so we should just post the event and
|
||||
# let the surrounding app decide what it wants to do.
|
||||
self.write('Click on the close button to leave the application.')
|
||||
|
||||
|
||||
def setLocalShell(self):
|
||||
"""Add 'shell' to locals as reference to ShellFacade instance."""
|
||||
self.interp.locals['shell'] = ShellFacade(other=self)
|
||||
|
||||
|
||||
def execStartupScript(self, startupScript):
|
||||
"""Execute the user's PYTHONSTARTUP script if they have one."""
|
||||
if startupScript and os.path.isfile(startupScript):
|
||||
text = 'Startup script executed: ' + startupScript
|
||||
self.push('print %r; execfile(%r)' % (text, startupScript))
|
||||
self.interp.startupScript = startupScript
|
||||
else:
|
||||
self.push('')
|
||||
|
||||
|
||||
def about(self):
|
||||
"""Display information about Py."""
|
||||
text = """
|
||||
@@ -302,17 +385,24 @@ Py Shell Revision: %s
|
||||
Py Interpreter Revision: %s
|
||||
Python Version: %s
|
||||
wxPython Version: %s
|
||||
wxPython PlatformInfo: %s
|
||||
Platform: %s""" % \
|
||||
(__author__, VERSION, self.revision, self.interp.revision,
|
||||
sys.version.split()[0], wx.VERSION_STRING, sys.platform)
|
||||
sys.version.split()[0], wx.VERSION_STRING, str(wx.PlatformInfo),
|
||||
sys.platform)
|
||||
self.write(text.strip())
|
||||
|
||||
|
||||
def OnChar(self, event):
|
||||
"""Keypress event handler.
|
||||
|
||||
Only receives an event if OnKeyDown calls event.Skip() for the
|
||||
corresponding event."""
|
||||
|
||||
if self.noteMode:
|
||||
event.Skip()
|
||||
return
|
||||
|
||||
# Prevent modification of previously submitted
|
||||
# commands/responses.
|
||||
if not self.CanEdit():
|
||||
@@ -343,11 +433,12 @@ Platform: %s""" % \
|
||||
self.ReplaceSelection('')
|
||||
command = self.GetTextRange(stoppos, currpos) + '('
|
||||
self.write('(')
|
||||
self.autoCallTipShow(command)
|
||||
self.autoCallTipShow(command, self.GetCurrentPos() == self.GetTextLength())
|
||||
else:
|
||||
# Allow the normal event handling to take place.
|
||||
event.Skip()
|
||||
|
||||
|
||||
def OnKeyDown(self, event):
|
||||
"""Key down event handler."""
|
||||
|
||||
@@ -364,12 +455,64 @@ Platform: %s""" % \
|
||||
currpos = self.GetCurrentPos()
|
||||
endpos = self.GetTextLength()
|
||||
selecting = self.GetSelectionStart() != self.GetSelectionEnd()
|
||||
|
||||
if controlDown and key in (ord('H'), ord('h')):
|
||||
li = self.GetCurrentLine()
|
||||
m = self.MarkerGet(li)
|
||||
if m & 1<<0:
|
||||
startP = self.PositionFromLine(li)
|
||||
self.MarkerDelete(li, 0)
|
||||
maxli = self.GetLineCount()
|
||||
li += 1 # li stayed visible as header-line
|
||||
li0 = li
|
||||
while li<maxli and self.GetLineVisible(li) == 0:
|
||||
li += 1
|
||||
endP = self.GetLineEndPosition(li-1)
|
||||
self.ShowLines(li0, li-1)
|
||||
self.SetSelection( startP, endP ) # select reappearing text to allow "hide again"
|
||||
return
|
||||
startP,endP = self.GetSelection()
|
||||
endP-=1
|
||||
startL,endL = self.LineFromPosition(startP), self.LineFromPosition(endP)
|
||||
|
||||
if endL == self.LineFromPosition(self.promptPosEnd): # never hide last prompt
|
||||
endL -= 1
|
||||
|
||||
m = self.MarkerGet(startL)
|
||||
self.MarkerAdd(startL, 0)
|
||||
self.HideLines(startL+1,endL)
|
||||
self.SetCurrentPos( startP ) # to ensure caret stays visible !
|
||||
|
||||
if key == wx.WXK_F12: #seb
|
||||
if self.noteMode:
|
||||
# self.promptPosStart not used anyway - or ?
|
||||
self.promptPosEnd = self.PositionFromLine( self.GetLineCount()-1 ) + len(str(sys.ps1))
|
||||
self.GotoLine(self.GetLineCount())
|
||||
self.GotoPos(self.promptPosEnd)
|
||||
self.prompt() #make sure we have a prompt
|
||||
self.SetCaretForeground("black")
|
||||
self.SetCaretWidth(1) #default
|
||||
self.SetCaretPeriod(500) #default
|
||||
else:
|
||||
self.SetCaretForeground("red")
|
||||
self.SetCaretWidth(4)
|
||||
self.SetCaretPeriod(0) #steady
|
||||
|
||||
self.noteMode = not self.noteMode
|
||||
return
|
||||
if self.noteMode:
|
||||
event.Skip()
|
||||
return
|
||||
|
||||
# Return (Enter) is used to submit a command to the
|
||||
# interpreter.
|
||||
if not controlDown and key == wx.WXK_RETURN:
|
||||
if (not controlDown and not shiftDown and not altDown) and key == wx.WXK_RETURN:
|
||||
if self.CallTipActive():
|
||||
self.CallTipCancel()
|
||||
self.processLine()
|
||||
#Complete Text (from already typed words)
|
||||
elif shiftDown and key == wx.WXK_RETURN:
|
||||
self.OnShowCompHistory()
|
||||
# Ctrl+Return (Cntrl+Enter) is used to insert a line break.
|
||||
elif controlDown and key == wx.WXK_RETURN:
|
||||
if self.CallTipActive():
|
||||
@@ -433,6 +576,9 @@ Platform: %s""" % \
|
||||
elif (controlDown and not shiftDown and key in (ord('V'), ord('v'))) \
|
||||
or (shiftDown and not controlDown and key == wx.WXK_INSERT):
|
||||
self.Paste()
|
||||
elif controlDown and key == wx.WXK_SPACE:
|
||||
"""AutoComplete and Calltips manually."""
|
||||
self.OnCallTipAutoCompleteManually (shiftDown)
|
||||
# Paste from the clipboard, run commands.
|
||||
elif controlDown and shiftDown and key in (ord('V'), ord('v')):
|
||||
self.PasteAndRun()
|
||||
@@ -481,6 +627,49 @@ Platform: %s""" % \
|
||||
else:
|
||||
event.Skip()
|
||||
|
||||
def OnShowCompHistory(self):
|
||||
"""Show possible autocompletion Words from already typed words."""
|
||||
|
||||
#copy from history
|
||||
his = self.history[:]
|
||||
|
||||
#put together in one string
|
||||
joined = " ".join (his)
|
||||
import re
|
||||
|
||||
#sort out only "good" words
|
||||
newlist = re.split("[ \.\[\]=}(\)\,0-9\"]", joined)
|
||||
|
||||
#length > 1 (mix out "trash")
|
||||
thlist = []
|
||||
for i in newlist:
|
||||
if len (i) > 1:
|
||||
thlist.append (i)
|
||||
|
||||
#unique (no duplicate words
|
||||
#oneliner from german python forum => unique list
|
||||
unlist = [thlist[i] for i in xrange(len(thlist)) if thlist[i] not in thlist[:i]]
|
||||
|
||||
#sort lowercase
|
||||
unlist.sort(lambda a, b: cmp(a.lower(), b.lower()))
|
||||
|
||||
#this is more convenient, isn't it?
|
||||
self.AutoCompSetIgnoreCase(True)
|
||||
|
||||
#join again together in a string
|
||||
stringlist = " ".join(unlist)
|
||||
|
||||
#pos von 0 noch ausrechnen
|
||||
|
||||
#how big is the offset?
|
||||
cpos = self.GetCurrentPos() - 1
|
||||
while chr (self.GetCharAt (cpos)).isalnum():
|
||||
cpos -= 1
|
||||
|
||||
#the most important part
|
||||
self.AutoCompShow(self.GetCurrentPos() - cpos -1, stringlist)
|
||||
|
||||
|
||||
def clearCommand(self):
|
||||
"""Delete the current, unexecuted command."""
|
||||
startpos = self.promptPosEnd
|
||||
@@ -589,6 +778,7 @@ Platform: %s""" % \
|
||||
self.write(os.linesep)
|
||||
else:
|
||||
self.push(command)
|
||||
wx.FutureCall(1, self.EnsureCaretVisible)
|
||||
# Or replace the current command with the other command.
|
||||
else:
|
||||
# If the line contains a command (even an invalid one).
|
||||
@@ -665,9 +855,10 @@ Platform: %s""" % \
|
||||
text = text[ps2size:]
|
||||
return text
|
||||
|
||||
def push(self, command):
|
||||
def push(self, command, silent = False):
|
||||
"""Send command to the interpreter for execution."""
|
||||
self.write(os.linesep)
|
||||
if not silent:
|
||||
self.write(os.linesep)
|
||||
busy = wx.BusyCursor()
|
||||
self.waiting = True
|
||||
self.more = self.interp.push(command)
|
||||
@@ -675,7 +866,8 @@ Platform: %s""" % \
|
||||
del busy
|
||||
if not self.more:
|
||||
self.addHistory(command.rstrip())
|
||||
self.prompt()
|
||||
if not silent:
|
||||
self.prompt()
|
||||
|
||||
def addHistory(self, command):
|
||||
"""Add command to the command history."""
|
||||
@@ -817,7 +1009,7 @@ Platform: %s""" % \
|
||||
finally:
|
||||
file.close()
|
||||
|
||||
def autoCompleteShow(self, command):
|
||||
def autoCompleteShow(self, command, offset = 0):
|
||||
"""Display auto-completion popup list."""
|
||||
self.AutoCompSetAutoHide(self.autoCompleteAutoHide)
|
||||
self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
|
||||
@@ -827,19 +1019,19 @@ Platform: %s""" % \
|
||||
includeDouble=self.autoCompleteIncludeDouble)
|
||||
if list:
|
||||
options = ' '.join(list)
|
||||
offset = 0
|
||||
#offset = 0
|
||||
self.AutoCompShow(offset, options)
|
||||
|
||||
def autoCallTipShow(self, command):
|
||||
def autoCallTipShow(self, command, insertcalltip = True, forceCallTip = False):
|
||||
"""Display argument spec and docstring in a popup window."""
|
||||
if self.CallTipActive():
|
||||
self.CallTipCancel()
|
||||
(name, argspec, tip) = self.interp.getCallTip(command)
|
||||
if tip:
|
||||
dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip)
|
||||
if not self.autoCallTip:
|
||||
if not self.autoCallTip and not forceCallTip:
|
||||
return
|
||||
if argspec:
|
||||
if argspec and insertcalltip and self.callTipInsert:
|
||||
startpos = self.GetCurrentPos()
|
||||
self.write(argspec + ')')
|
||||
endpos = self.GetCurrentPos()
|
||||
@@ -852,6 +1044,53 @@ Platform: %s""" % \
|
||||
# fallback.
|
||||
tippos = max(tippos, fallback)
|
||||
self.CallTipShow(tippos, tip)
|
||||
|
||||
def OnCallTipAutoCompleteManually (self, shiftDown):
|
||||
"""AutoComplete and Calltips manually."""
|
||||
if self.AutoCompActive():
|
||||
self.AutoCompCancel()
|
||||
currpos = self.GetCurrentPos()
|
||||
stoppos = self.promptPosEnd
|
||||
|
||||
cpos = currpos
|
||||
#go back until '.' is found
|
||||
pointavailpos = -1
|
||||
while cpos >= stoppos:
|
||||
if self.GetCharAt(cpos) == ord ('.'):
|
||||
pointavailpos = cpos
|
||||
break
|
||||
cpos -= 1
|
||||
|
||||
#word from non whitespace until '.'
|
||||
if pointavailpos != -1:
|
||||
#look backward for first whitespace char
|
||||
textbehind = self.GetTextRange (pointavailpos + 1, currpos)
|
||||
pointavailpos += 1
|
||||
|
||||
if not shiftDown:
|
||||
#call AutoComplete
|
||||
stoppos = self.promptPosEnd
|
||||
textbefore = self.GetTextRange(stoppos, pointavailpos)
|
||||
self.autoCompleteShow(textbefore, len (textbehind))
|
||||
else:
|
||||
#call CallTips
|
||||
cpos = pointavailpos
|
||||
begpos = -1
|
||||
while cpos > stoppos:
|
||||
if chr(self.GetCharAt(cpos)).isspace():
|
||||
begpos = cpos
|
||||
break
|
||||
cpos -= 1
|
||||
if begpos == -1:
|
||||
begpos = cpos
|
||||
ctips = self.GetTextRange (begpos, currpos)
|
||||
ctindex = ctips.find ('(')
|
||||
if ctindex != -1 and not self.CallTipActive():
|
||||
#insert calltip, if current pos is '(', otherwise show it only
|
||||
self.autoCallTipShow(ctips[:ctindex + 1], \
|
||||
self.GetCharAt(currpos - 1) == ord('(') and self.GetCurrentPos() == self.GetTextLength(),\
|
||||
True)
|
||||
|
||||
|
||||
def writeOut(self, text):
|
||||
"""Replacement for stdout."""
|
||||
@@ -1034,3 +1273,101 @@ Platform: %s""" % \
|
||||
This number of points is added to the size of all fonts. It
|
||||
may be positive to magnify or negative to reduce."""
|
||||
self.SetZoom(points)
|
||||
|
||||
|
||||
|
||||
def LoadSettings(self, config):
|
||||
self.autoComplete = config.ReadBool('Options/AutoComplete', True)
|
||||
self.autoCompleteIncludeMagic = config.ReadBool('Options/AutoCompleteIncludeMagic', True)
|
||||
self.autoCompleteIncludeSingle = config.ReadBool('Options/AutoCompleteIncludeSingle', True)
|
||||
self.autoCompleteIncludeDouble = config.ReadBool('Options/AutoCompleteIncludeDouble', True)
|
||||
|
||||
self.autoCallTip = config.ReadBool('Options/AutoCallTip', True)
|
||||
self.callTipInsert = config.ReadBool('Options/CallTipInsert', True)
|
||||
self.SetWrapMode(config.ReadBool('View/WrapMode', True))
|
||||
|
||||
useAA = config.ReadBool('Options/UseAntiAliasing', self.GetUseAntiAliasing())
|
||||
self.SetUseAntiAliasing(useAA)
|
||||
self.lineNumbers = config.ReadBool('View/ShowLineNumbers', True)
|
||||
self.setDisplayLineNumbers (self.lineNumbers)
|
||||
zoom = config.ReadInt('View/Zoom/Shell', -99)
|
||||
if zoom != -99:
|
||||
self.SetZoom(zoom)
|
||||
|
||||
|
||||
|
||||
def SaveSettings(self, config):
|
||||
config.WriteBool('Options/AutoComplete', self.autoComplete)
|
||||
config.WriteBool('Options/AutoCompleteIncludeMagic', self.autoCompleteIncludeMagic)
|
||||
config.WriteBool('Options/AutoCompleteIncludeSingle', self.autoCompleteIncludeSingle)
|
||||
config.WriteBool('Options/AutoCompleteIncludeDouble', self.autoCompleteIncludeDouble)
|
||||
config.WriteBool('Options/AutoCallTip', self.autoCallTip)
|
||||
config.WriteBool('Options/CallTipInsert', self.callTipInsert)
|
||||
config.WriteBool('Options/UseAntiAliasing', self.GetUseAntiAliasing())
|
||||
config.WriteBool('View/WrapMode', self.GetWrapMode())
|
||||
config.WriteBool('View/ShowLineNumbers', self.lineNumbers)
|
||||
config.WriteInt('View/Zoom/Shell', self.GetZoom())
|
||||
|
||||
|
||||
|
||||
## NOTE: The DnD of file names is disabled until I can figure out how
|
||||
## best to still allow DnD of text.
|
||||
|
||||
|
||||
## #seb : File drag and drop
|
||||
## class FileDropTarget(wx.FileDropTarget):
|
||||
## def __init__(self, obj):
|
||||
## wx.FileDropTarget.__init__(self)
|
||||
## self.obj = obj
|
||||
## def OnDropFiles(self, x, y, filenames):
|
||||
## if len(filenames) == 1:
|
||||
## txt = 'r\"%s\"' % filenames[0]
|
||||
## else:
|
||||
## txt = '( '
|
||||
## for f in filenames:
|
||||
## txt += 'r\"%s\" , ' % f
|
||||
## txt += ')'
|
||||
## self.obj.AppendText(txt)
|
||||
## pos = self.obj.GetCurrentPos()
|
||||
## self.obj.SetCurrentPos( pos )
|
||||
## self.obj.SetSelection( pos, pos )
|
||||
|
||||
|
||||
|
||||
## class TextAndFileDropTarget(wx.DropTarget):
|
||||
## def __init__(self, shell):
|
||||
## wx.DropTarget.__init__(self)
|
||||
## self.shell = shell
|
||||
## self.compdo = wx.DataObjectComposite()
|
||||
## self.textdo = wx.TextDataObject()
|
||||
## self.filedo = wx.FileDataObject()
|
||||
## self.compdo.Add(self.textdo)
|
||||
## self.compdo.Add(self.filedo, True)
|
||||
|
||||
## self.SetDataObject(self.compdo)
|
||||
|
||||
## def OnDrop(self, x, y):
|
||||
## return True
|
||||
|
||||
## def OnData(self, x, y, result):
|
||||
## self.GetData()
|
||||
## if self.textdo.GetTextLength() > 1:
|
||||
## text = self.textdo.GetText()
|
||||
## # *** Do somethign with the dragged text here...
|
||||
## self.textdo.SetText('')
|
||||
## else:
|
||||
## filenames = str(self.filename.GetFilenames())
|
||||
## if len(filenames) == 1:
|
||||
## txt = 'r\"%s\"' % filenames[0]
|
||||
## else:
|
||||
## txt = '( '
|
||||
## for f in filenames:
|
||||
## txt += 'r\"%s\" , ' % f
|
||||
## txt += ')'
|
||||
## self.shell.AppendText(txt)
|
||||
## pos = self.shell.GetCurrentPos()
|
||||
## self.shell.SetCurrentPos( pos )
|
||||
## self.shell.SetSelection( pos, pos )
|
||||
|
||||
## return result
|
||||
|
||||
|
@@ -6,4 +6,4 @@ __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
VERSION = '0.9.4'
|
||||
VERSION = '0.9.5'
|
||||
|
Reference in New Issue
Block a user