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:
@@ -147,6 +147,15 @@ WX_CONFIG = None # Usually you shouldn't need to touch this, but you can set
|
||||
# version, port, etc. and it will be looked for on the
|
||||
# default $PATH.
|
||||
|
||||
SYS_WX_CONFIG = None # When installing an in tree build, setup.py uses wx-config
|
||||
# for two different purposes. First, to determine the prefix
|
||||
# where files will be installed, and secondly, to initialise
|
||||
# build_options.py with the correct options for it.
|
||||
# WX_CONFIG is used for the first task. SYS_WX_CONFIG may
|
||||
# be set independently, to the value that should appear in
|
||||
# build_options.py, if it is different to that. The default
|
||||
# is to use the value of WX_CONFIG.
|
||||
|
||||
WXPORT = 'gtk2' # On Linux/Unix there are several ports of wxWidgets available.
|
||||
# Setting this value lets you select which will be used for
|
||||
# the wxPython build. Possibilites are 'gtk', 'gtk2' and
|
||||
@@ -255,8 +264,8 @@ for flag in [ 'BUILD_ACTIVEX', 'BUILD_ANIMATE', 'BUILD_DLLWIDGET',
|
||||
sys.argv[x] = ''
|
||||
|
||||
# String options
|
||||
for option in ['WX_CONFIG', 'WXDLLVER', 'BUILD_BASE', 'WXPORT', 'SWIG',
|
||||
'CONTRIBS_INC', 'WXPY_SRC', 'FLAVOUR',
|
||||
for option in ['WX_CONFIG', 'SYS_WX_CONFIG', 'WXDLLVER', 'BUILD_BASE',
|
||||
'WXPORT', 'SWIG', 'CONTRIBS_INC', 'WXPY_SRC', 'FLAVOUR',
|
||||
]:
|
||||
for x in range(len(sys.argv)):
|
||||
if sys.argv[x].find(option) == 0:
|
||||
@@ -272,6 +281,9 @@ sys.argv = filter(None, sys.argv)
|
||||
# build options file
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
if SYS_WX_CONFIG is None:
|
||||
SYS_WX_CONFIG = WX_CONFIG
|
||||
|
||||
build_options_template = """
|
||||
UNICODE=%d
|
||||
UNDEF_NDEBUG=%d
|
||||
@@ -284,7 +296,7 @@ MONOLITHIC=%d
|
||||
FINAL=%d
|
||||
HYBRID=%d
|
||||
""" % (UNICODE, UNDEF_NDEBUG, INSTALL_MULTIVERSION, FLAVOUR, EP_ADD_OPTS,
|
||||
WX_CONFIG, WXPORT, MONOLITHIC, FINAL, HYBRID)
|
||||
SYS_WX_CONFIG, WXPORT, MONOLITHIC, FINAL, HYBRID)
|
||||
|
||||
try:
|
||||
from build_options import *
|
||||
|
||||
@@ -29,10 +29,16 @@ class TestPanel(wx.Panel):
|
||||
mask = wx.Mask(bmp, wx.BLUE)
|
||||
|
||||
bmp.SetMask(mask)
|
||||
b = wx.BitmapButton(self, 30, bmp, (20, 20),
|
||||
b = wx.BitmapButton(self, -1, bmp, (20, 20),
|
||||
(bmp.GetWidth()+10, bmp.GetHeight()+10))
|
||||
b.SetToolTipString("This is a bitmap button.")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnClick, b)
|
||||
|
||||
b = wx.BitmapButton(self, -1, bmp, (20, 120),
|
||||
(bmp.GetWidth()+10, bmp.GetHeight()+10),
|
||||
style = wx.NO_BORDER)
|
||||
b.SetToolTipString("This is a bitmap button with \nwx.NO_BORDER style.")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnClick, b)
|
||||
|
||||
|
||||
def OnClick(self, event):
|
||||
|
||||
@@ -27,7 +27,8 @@ class TestPanel(wx.Panel):
|
||||
self, -1, size=(450, -1), changeCallback = self.dbbCallback
|
||||
)
|
||||
|
||||
self.fbbh.SetHistory(['You', 'can', 'put', 'some', 'filenames', 'here'])
|
||||
self.fbbh.callCallback = False
|
||||
self.fbbh.SetHistory(['You', 'can', 'put', 'some', 'filenames', 'here'], 4)
|
||||
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer.Add(self.fbb, 0, wx.ALL, 5)
|
||||
@@ -45,6 +46,8 @@ class TestPanel(wx.Panel):
|
||||
def fbbhCallback(self, evt):
|
||||
if hasattr(self, 'fbbh'):
|
||||
value = evt.GetString()
|
||||
if not value:
|
||||
return
|
||||
self.log.write('FileBrowseButtonWithHistory: %s\n' % value)
|
||||
history = self.fbbh.GetHistory()
|
||||
if value not in history:
|
||||
|
||||
@@ -344,6 +344,10 @@ class Extended(wx.Frame):
|
||||
# or normal
|
||||
|
||||
if event.IsChecked():
|
||||
self.GetMenuBar().Check(self._singlestyle, False)
|
||||
self.GetMenuBar().Check(self._exclusivestyle, False)
|
||||
self._flags = self._flags & ~fpb.FPB_SINGLE_FOLD
|
||||
self._flags = self._flags & ~fpb.FPB_EXCLUSIVE_FOLD
|
||||
self._flags = self._flags | fpb.FPB_COLLAPSE_TO_BOTTOM
|
||||
else:
|
||||
self._flags = self._flags & ~fpb.FPB_COLLAPSE_TO_BOTTOM
|
||||
@@ -352,13 +356,15 @@ class Extended(wx.Frame):
|
||||
|
||||
|
||||
def OnCreateNormalStyle(self, event):
|
||||
|
||||
|
||||
# recreate with style where only one panel at the time is
|
||||
# allowed to be opened
|
||||
|
||||
# TODO: Not yet implemented even in the C++ class!!!!
|
||||
|
||||
if event.IsChecked():
|
||||
self.GetMenuBar().Check(self._bottomstyle, False)
|
||||
self.GetMenuBar().Check(self._exclusivestyle, False)
|
||||
self._flags = self._flags & ~fpb.FPB_EXCLUSIVE_FOLD
|
||||
self._flags = self._flags & ~fpb.FPB_COLLAPSE_TO_BOTTOM
|
||||
self._flags = self._flags | fpb.FPB_SINGLE_FOLD
|
||||
else:
|
||||
self._flags = self._flags & ~fpb.FPB_SINGLE_FOLD
|
||||
@@ -366,6 +372,23 @@ class Extended(wx.Frame):
|
||||
self.ReCreateFoldPanel(self._flags)
|
||||
|
||||
|
||||
def OnCreateExclusiveStyle(self, event):
|
||||
|
||||
# recreate with style where only one panel at the time is
|
||||
# allowed to be opened and the others are collapsed to bottom
|
||||
|
||||
if event.IsChecked():
|
||||
self.GetMenuBar().Check(self._singlestyle, False)
|
||||
self.GetMenuBar().Check(self._bottomstyle, False)
|
||||
self._flags = self._flags & ~fpb.FPB_SINGLE_FOLD
|
||||
self._flags = self._flags & ~fpb.FPB_COLLAPSE_TO_BOTTOM
|
||||
self._flags = self._flags | fpb.FPB_EXCLUSIVE_FOLD
|
||||
else:
|
||||
self._flags = self._flags & ~fpb.FPB_EXCLUSIVE_FOLD
|
||||
|
||||
self.ReCreateFoldPanel(self._flags)
|
||||
|
||||
|
||||
def OnCollapseMe(self, event):
|
||||
|
||||
for i in range(0, self._pnl.GetCount()):
|
||||
@@ -487,8 +510,9 @@ class Extended(wx.Frame):
|
||||
|
||||
FPBTEST_QUIT = wx.NewId()
|
||||
FPBTEST_REFRESH = wx.NewId()
|
||||
FPB_BOTTOM_STICK = wx.NewId()
|
||||
FPB_BOTTOM_FOLD = wx.NewId()
|
||||
FPB_SINGLE_FOLD = wx.NewId()
|
||||
FPB_EXCLUSIVE_FOLD = wx.NewId()
|
||||
FPBTEST_TOGGLE_WINDOW = wx.NewId()
|
||||
FPBTEST_ABOUT = wx.NewId()
|
||||
|
||||
@@ -504,10 +528,13 @@ class Extended(wx.Frame):
|
||||
# make fold panel menu
|
||||
|
||||
fpb_menu = wx.Menu()
|
||||
fpb_menu.AppendCheckItem(FPB_BOTTOM_STICK, "Create with &fpb.FPB_COLLAPSE_TO_BOTTOM")
|
||||
fpb_menu.AppendCheckItem(FPB_BOTTOM_FOLD, "Create with &fpb.FPB_COLLAPSE_TO_BOTTOM")
|
||||
|
||||
# Not Yet Implemented In The C++ class!!!
|
||||
# fpb_menu.AppendCheckItem(FPB_SINGLE_FOLD, _T("Create with &FPB_SINGLE_FOLD"))
|
||||
# Now Implemented!
|
||||
fpb_menu.AppendCheckItem(FPB_SINGLE_FOLD, "Create with &fpb.FPB_SINGLE_FOLD")
|
||||
|
||||
# Now Implemented!
|
||||
fpb_menu.AppendCheckItem(FPB_EXCLUSIVE_FOLD, "Create with &fpb.FPB_EXCLUSIVE_FOLD")
|
||||
|
||||
fpb_menu.AppendSeparator()
|
||||
fpb_menu.Append(FPBTEST_TOGGLE_WINDOW, "&Toggle FoldPanelBar")
|
||||
@@ -528,8 +555,13 @@ class Extended(wx.Frame):
|
||||
self.Bind(wx.EVT_MENU, self.OnAbout, id=FPBTEST_ABOUT)
|
||||
self.Bind(wx.EVT_MENU, self.OnQuit, id=FPBTEST_QUIT)
|
||||
self.Bind(wx.EVT_MENU, self.OnToggleWindow, id=FPBTEST_TOGGLE_WINDOW)
|
||||
self.Bind(wx.EVT_MENU, self.OnCreateBottomStyle, id=FPB_BOTTOM_STICK)
|
||||
self.Bind(wx.EVT_MENU, self.OnCreateBottomStyle, id=FPB_BOTTOM_FOLD)
|
||||
self.Bind(wx.EVT_MENU, self.OnCreateNormalStyle, id=FPB_SINGLE_FOLD)
|
||||
self.Bind(wx.EVT_MENU, self.OnCreateExclusiveStyle, id=FPB_EXCLUSIVE_FOLD)
|
||||
|
||||
self._bottomstyle = FPB_BOTTOM_FOLD
|
||||
self._singlestyle = FPB_SINGLE_FOLD
|
||||
self._exclusivestyle = FPB_EXCLUSIVE_FOLD
|
||||
|
||||
return menu_bar
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ class MyCanvasBase(glcanvas.GLCanvas):
|
||||
# initial mouse position
|
||||
self.lastx = self.x = 30
|
||||
self.lasty = self.y = 30
|
||||
self.size = None
|
||||
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
|
||||
self.Bind(wx.EVT_SIZE, self.OnSize)
|
||||
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
||||
@@ -93,7 +94,7 @@ class MyCanvasBase(glcanvas.GLCanvas):
|
||||
|
||||
|
||||
def OnSize(self, event):
|
||||
size = self.GetClientSize()
|
||||
size = self.size = self.GetClientSize()
|
||||
if self.GetContext():
|
||||
self.SetCurrent()
|
||||
glViewport(0, 0, size.width, size.height)
|
||||
@@ -111,6 +112,7 @@ class MyCanvasBase(glcanvas.GLCanvas):
|
||||
|
||||
def OnMouseDown(self, evt):
|
||||
self.CaptureMouse()
|
||||
self.x, self.y = self.lastx, self.lasty = evt.GetPosition()
|
||||
|
||||
|
||||
def OnMouseUp(self, evt):
|
||||
@@ -119,7 +121,7 @@ class MyCanvasBase(glcanvas.GLCanvas):
|
||||
|
||||
def OnMouseMotion(self, evt):
|
||||
if evt.Dragging() and evt.LeftIsDown():
|
||||
self.x, self.y = self.lastx, self.lasty
|
||||
self.lastx, self.lasty = self.x, self.y
|
||||
self.x, self.y = evt.GetPosition()
|
||||
self.Refresh(False)
|
||||
|
||||
@@ -129,25 +131,25 @@ class MyCanvasBase(glcanvas.GLCanvas):
|
||||
class CubeCanvas(MyCanvasBase):
|
||||
def InitGL(self):
|
||||
# set viewing projection
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0);
|
||||
glMatrixMode(GL_PROJECTION)
|
||||
glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0)
|
||||
|
||||
# position viewer
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glTranslatef(0.0, 0.0, -2.0);
|
||||
glMatrixMode(GL_MODELVIEW)
|
||||
glTranslatef(0.0, 0.0, -2.0)
|
||||
|
||||
# position object
|
||||
glRotatef(self.y, 1.0, 0.0, 0.0);
|
||||
glRotatef(self.x, 0.0, 1.0, 0.0);
|
||||
glRotatef(self.y, 1.0, 0.0, 0.0)
|
||||
glRotatef(self.x, 0.0, 1.0, 0.0)
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
glEnable(GL_LIGHTING)
|
||||
glEnable(GL_LIGHT0)
|
||||
|
||||
|
||||
def OnDraw(self):
|
||||
# clear color and depth buffers
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
|
||||
# draw six faces of a cube
|
||||
glBegin(GL_QUADS)
|
||||
@@ -188,8 +190,15 @@ class CubeCanvas(MyCanvasBase):
|
||||
glVertex3f(-0.5, 0.5,-0.5)
|
||||
glEnd()
|
||||
|
||||
glRotatef((self.lasty - self.y)/100., 1.0, 0.0, 0.0);
|
||||
glRotatef((self.lastx - self.x)/100., 0.0, 1.0, 0.0);
|
||||
if self.size is None:
|
||||
self.size = self.GetClientSize()
|
||||
w, h = self.size
|
||||
w = max(w, 1.0)
|
||||
h = max(h, 1.0)
|
||||
xScale = 180.0 / w
|
||||
yScale = 180.0 / h
|
||||
glRotatef((self.y - self.lasty) * yScale, 1.0, 0.0, 0.0);
|
||||
glRotatef((self.x - self.lastx) * xScale, 0.0, 1.0, 0.0);
|
||||
|
||||
self.SwapBuffers()
|
||||
|
||||
@@ -199,9 +208,9 @@ class CubeCanvas(MyCanvasBase):
|
||||
|
||||
class ConeCanvas(MyCanvasBase):
|
||||
def InitGL( self ):
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glMatrixMode(GL_PROJECTION)
|
||||
# camera frustrum setup
|
||||
glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0);
|
||||
glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0)
|
||||
glMaterial(GL_FRONT, GL_AMBIENT, [0.2, 0.2, 0.2, 1.0])
|
||||
glMaterial(GL_FRONT, GL_DIFFUSE, [0.8, 0.8, 0.8, 1.0])
|
||||
glMaterial(GL_FRONT, GL_SPECULAR, [1.0, 0.0, 1.0, 1.0])
|
||||
@@ -209,7 +218,7 @@ class ConeCanvas(MyCanvasBase):
|
||||
glLight(GL_LIGHT0, GL_AMBIENT, [0.0, 1.0, 0.0, 1.0])
|
||||
glLight(GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0])
|
||||
glLight(GL_LIGHT0, GL_SPECULAR, [1.0, 1.0, 1.0, 1.0])
|
||||
glLight(GL_LIGHT0, GL_POSITION, [1.0, 1.0, 1.0, 0.0]);
|
||||
glLight(GL_LIGHT0, GL_POSITION, [1.0, 1.0, 1.0, 0.0])
|
||||
glLightModel(GL_LIGHT_MODEL_AMBIENT, [0.2, 0.2, 0.2, 1.0])
|
||||
glEnable(GL_LIGHTING)
|
||||
glEnable(GL_LIGHT0)
|
||||
@@ -217,25 +226,28 @@ class ConeCanvas(MyCanvasBase):
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
# position viewer
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glMatrixMode(GL_MODELVIEW)
|
||||
# position viewer
|
||||
glTranslatef(0.0, 0.0, -2.0);
|
||||
|
||||
|
||||
|
||||
def OnDraw(self):
|
||||
# clear color and depth buffers
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
# use a fresh transformation matrix
|
||||
glPushMatrix()
|
||||
# position object
|
||||
glTranslate(0.0, 0.0, -2.0);
|
||||
glRotate(30.0, 1.0, 0.0, 0.0);
|
||||
glRotate(30.0, 0.0, 1.0, 0.0);
|
||||
#glTranslate(0.0, 0.0, -2.0)
|
||||
glRotate(30.0, 1.0, 0.0, 0.0)
|
||||
glRotate(30.0, 0.0, 1.0, 0.0)
|
||||
|
||||
glTranslate(0, -1, 0)
|
||||
glRotate(250, 1, 0, 0)
|
||||
glutSolidCone(0.5, 1, 30, 5)
|
||||
glPopMatrix()
|
||||
glRotatef((self.lasty - self.y)/100., 0.0, 0.0, 1.0);
|
||||
glRotatef(0.0, (self.lastx - self.x)/100., 1.0, 0.0);
|
||||
glRotatef((self.y - self.lasty), 0.0, 0.0, 1.0);
|
||||
glRotatef((self.x - self.lastx), 1.0, 0.0, 0.0);
|
||||
# push into visible buffer
|
||||
self.SwapBuffers()
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ class TestPanel(wx.Panel):
|
||||
|
||||
|
||||
def OnRightLink(self, event):
|
||||
pos = event.GetPosition()
|
||||
pos = self._hyper3.GetPosition() + event.GetPosition()
|
||||
menuPopUp = wx.Menu("Having a nice day?")
|
||||
ID_MENU_YES = wx.NewId()
|
||||
ID_MENU_NO = wx.NewId()
|
||||
|
||||
@@ -56,7 +56,7 @@ class TestLayoutConstraints(wx.Panel):
|
||||
lc.centreY.SameAs (self.panelA, wx.CentreY)
|
||||
lc.height.AsIs ()
|
||||
lc.width.PercentOf (self.panelA, wx.Width, 50)
|
||||
b.SetConstraints(lc);
|
||||
b.SetConstraints(lc)
|
||||
|
||||
b = wx.Button(self.panelB, 100, ' Panel B ')
|
||||
lc = wx.LayoutConstraints()
|
||||
@@ -64,7 +64,7 @@ class TestLayoutConstraints(wx.Panel):
|
||||
lc.right.SameAs (self.panelB, wx.Right, 4)
|
||||
lc.height.AsIs ()
|
||||
lc.width.AsIs ()
|
||||
b.SetConstraints(lc);
|
||||
b.SetConstraints(lc)
|
||||
|
||||
self.panelD = wx.Window(self.panelC, -1, style=wx.SIMPLE_BORDER)
|
||||
self.panelD.SetBackgroundColour(wx.GREEN)
|
||||
@@ -78,14 +78,14 @@ class TestLayoutConstraints(wx.Panel):
|
||||
lc.left.RightOf (self.panelD)
|
||||
lc.height.AsIs ()
|
||||
lc.width.AsIs ()
|
||||
b.SetConstraints(lc);
|
||||
b.SetConstraints(lc)
|
||||
|
||||
lc = wx.LayoutConstraints()
|
||||
lc.bottom.PercentOf (self.panelC, wx.Height, 50)
|
||||
lc.right.PercentOf (self.panelC, wx.Width, 50)
|
||||
lc.height.SameAs (b, wx.Height)
|
||||
lc.width.SameAs (b, wx.Width)
|
||||
self.panelD.SetConstraints(lc);
|
||||
self.panelD.SetConstraints(lc)
|
||||
|
||||
|
||||
def OnButton(self, event):
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
|
||||
import wx
|
||||
|
||||
import MDIDemo
|
||||
import MDISashDemo
|
||||
import os
|
||||
import sys
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
@@ -25,14 +24,14 @@ class TestPanel(wx.Panel):
|
||||
self.SetSizer(box)
|
||||
|
||||
|
||||
# These are spawned as new processes because on Mac there can be
|
||||
# some problems related to having regular frames and MDI frames in
|
||||
# the same app.
|
||||
def ShowMDIDemo(self, evt):
|
||||
frame = MDIDemo.MyParentFrame()
|
||||
frame.Show()
|
||||
os.spawnl(os.P_NOWAIT, sys.executable, sys.executable, "MDIDemo.py")
|
||||
|
||||
def ShowMDISashDemo(self, evt):
|
||||
frame = MDISashDemo.MyParentFrame()
|
||||
frame.Show()
|
||||
|
||||
os.spawnl(os.P_NOWAIT, sys.executable, sys.executable, "MDISashDemo.py")
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
@@ -51,6 +51,7 @@ _treeList = [
|
||||
'GIFAnimationCtrl',
|
||||
'HyperLinkCtrl',
|
||||
'MultiSplitterWindow',
|
||||
'Throbber',
|
||||
]),
|
||||
|
||||
# managed windows == things with a (optional) caption you can close
|
||||
@@ -803,7 +804,8 @@ class DemoModules:
|
||||
def LoadDict(self, modID):
|
||||
if self.name != __name__:
|
||||
source = self.modules[modID][1]
|
||||
description = self.modules[modID][3]
|
||||
#description = self.modules[modID][3]
|
||||
description = self.modules[modID][2]
|
||||
|
||||
try:
|
||||
self.modules[modID][0] = {}
|
||||
@@ -1211,6 +1213,7 @@ class wxPythonDemo(wx.Frame):
|
||||
self.SetMenuBar(self.mainmenu)
|
||||
|
||||
self.finddata = wx.FindReplaceData()
|
||||
self.finddata.SetFlags(wx.FR_DOWN)
|
||||
|
||||
if 0:
|
||||
# This is another way to set Accelerators, in addition to
|
||||
@@ -1528,9 +1531,7 @@ class wxPythonDemo(wx.Frame):
|
||||
|
||||
self.nb.SetSelection(1)
|
||||
self.finddlg = wx.FindReplaceDialog(self, self.finddata, "Find",
|
||||
wx.FR_NOUPDOWN |
|
||||
wx.FR_NOMATCHCASE |
|
||||
wx.FR_NOWHOLEWORD)
|
||||
wx.FR_NOMATCHCASE | wx.FR_NOWHOLEWORD)
|
||||
self.finddlg.Show(True)
|
||||
|
||||
|
||||
@@ -1543,13 +1544,22 @@ class wxPythonDemo(wx.Frame):
|
||||
self.nb.SetSelection(1)
|
||||
end = editor.GetLastPosition()
|
||||
textstring = editor.GetRange(0, end).lower()
|
||||
start = editor.GetSelection()[1]
|
||||
findstring = self.finddata.GetFindString().lower()
|
||||
loc = textstring.find(findstring, start)
|
||||
backward = not (self.finddata.GetFlags() & wx.FR_DOWN)
|
||||
if backward:
|
||||
start = editor.GetSelection()[0]
|
||||
loc = textstring.rfind(findstring, 0, start)
|
||||
else:
|
||||
start = editor.GetSelection()[1]
|
||||
loc = textstring.find(findstring, start)
|
||||
if loc == -1 and start != 0:
|
||||
# string not found, start at beginning
|
||||
start = 0
|
||||
loc = textstring.find(findstring, start)
|
||||
if backward:
|
||||
start = end
|
||||
loc = textstring.rfind(findstring, 0, start)
|
||||
else:
|
||||
start = 0
|
||||
loc = textstring.find(findstring, start)
|
||||
if loc == -1:
|
||||
dlg = wx.MessageDialog(self, 'Find String Not Found',
|
||||
'Find String Not Found in Demo File',
|
||||
|
||||
@@ -22,7 +22,8 @@ class TestPanel(wx.Panel):
|
||||
self.cmd = wx.TextCtrl(self, -1, 'python -u data/echo.py')
|
||||
self.exBtn = wx.Button(self, -1, 'Execute')
|
||||
|
||||
self.out = wx.TextCtrl(self, -1, '', style=wx.TE_MULTILINE|wx.TE_READONLY)
|
||||
self.out = wx.TextCtrl(self, -1, '',
|
||||
style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_RICH2)
|
||||
|
||||
self.inp = wx.TextCtrl(self, -1, '', style=wx.TE_PROCESS_ENTER)
|
||||
self.sndBtn = wx.Button(self, -1, 'Send')
|
||||
|
||||
@@ -75,33 +75,33 @@ class PythonSTC(stc.StyledTextCtrl):
|
||||
|
||||
if self.fold_symbols == 0:
|
||||
# Arrow pointing right for contracted folders, arrow pointing down for expanded
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
|
||||
|
||||
elif self.fold_symbols == 1:
|
||||
# Plus for contracted folders, minus for expanded
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
|
||||
|
||||
elif self.fold_symbols == 2:
|
||||
# Like a flattened tree control using circular headers and curved joins
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040");
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
|
||||
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040")
|
||||
|
||||
elif self.fold_symbols == 3:
|
||||
# Like a flattened tree control using square headers
|
||||
@@ -286,7 +286,7 @@ class PythonSTC(stc.StyledTextCtrl):
|
||||
for lineNum in range(lineCount):
|
||||
if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
|
||||
expanding = not self.GetFoldExpanded(lineNum)
|
||||
break;
|
||||
break
|
||||
|
||||
lineNum = 0
|
||||
|
||||
@@ -342,7 +342,7 @@ class PythonSTC(stc.StyledTextCtrl):
|
||||
else:
|
||||
line = self.Expand(line, False, force, visLevels-1)
|
||||
else:
|
||||
line = line + 1;
|
||||
line = line + 1
|
||||
|
||||
return line
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
import os
|
||||
|
||||
import wx
|
||||
import wx.lib.printout as printout
|
||||
|
||||
@@ -9,6 +8,7 @@ import wx.lib.printout as printout
|
||||
buttonDefs = {
|
||||
814 : ('PreviewWide', 'Preview print of a wide table'),
|
||||
815 : ('PreviewNarrow', 'Preview print of a narrow table with color highlights'),
|
||||
816 : ('PreviewText', 'Preview print of a text file'),
|
||||
818 : ('OnPreviewMatrix', 'Preview print of a narrow column grid without a table header'),
|
||||
817 : ('PreviewLine', 'Preview print to demonstrate the use of line breaks'),
|
||||
819 : ('PrintWide', 'Direct print (no preview) of a wide table'),
|
||||
@@ -150,6 +150,17 @@ class TablePanel(wx.Panel):
|
||||
prt.SetFooter()
|
||||
prt.Preview()
|
||||
|
||||
def PreviewText(self):
|
||||
prt = printout.PrintTable(self.frame)
|
||||
prt.SetHeader("PROCLAMATION")
|
||||
file = open('data/proclamation.txt')
|
||||
data = []
|
||||
for txt in file:
|
||||
data.append(txt.strip())
|
||||
file.close()
|
||||
prt.data = data
|
||||
prt.Preview()
|
||||
|
||||
def PrintWide(self):
|
||||
self.ReadData()
|
||||
prt = printout.PrintTable(self.frame)
|
||||
|
||||
@@ -69,6 +69,13 @@ class TestPanel(wx.Panel):
|
||||
pointSize = 8, family = wx.DEFAULT, style = wx.NORMAL, weight = wx.BOLD
|
||||
))
|
||||
|
||||
self.customThrobber = \
|
||||
throb.Throbber(self, -1, images, size=(36, 36),
|
||||
frameDelay = 0.1,
|
||||
rest = 4,
|
||||
sequence = [ 1, 5, 2, 7, 3, 6, 4, 4, 4, 4, 7, 2, 2, 0 ]
|
||||
)
|
||||
|
||||
box = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer = wx.GridBagSizer()
|
||||
box.Add(sizer, 1, wx.EXPAND|wx.ALL, 5)
|
||||
@@ -90,6 +97,18 @@ class TestPanel(wx.Panel):
|
||||
|
||||
row += 1
|
||||
|
||||
# Add custom throbber to sizer.
|
||||
row += 2
|
||||
sizer.Add(
|
||||
self.customThrobber, (row, 0), (1, 1),
|
||||
flag = wx.ALIGN_CENTER|wx.ALL, border=2
|
||||
)
|
||||
|
||||
sizer.Add(
|
||||
wx.StaticText(self, -1, 'with custom & manual sequences'),
|
||||
(row, 1), flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT
|
||||
)
|
||||
|
||||
# start and stop buttons
|
||||
startButton = wx.Button(self, -1, "Start")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnStartAnimation, startButton)
|
||||
@@ -104,9 +123,54 @@ class TestPanel(wx.Panel):
|
||||
])
|
||||
|
||||
sizer.Add(
|
||||
buttonBox, (len(self.throbbers) + 3, 0), (1, 3), flag = wx.ALIGN_CENTER
|
||||
buttonBox, (len(self.throbbers) + 2, 0), (1, 3), flag = wx.ALIGN_CENTER
|
||||
)
|
||||
|
||||
# Buttoms for the custom throbber.
|
||||
nextButton = wx.Button(self, -1, "Next")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnNext, nextButton)
|
||||
|
||||
prevButton = wx.Button(self, -1, "Previous")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnPrevious, prevButton)
|
||||
|
||||
incButton = wx.Button(self, -1, "Increment")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnIncrement, incButton)
|
||||
|
||||
decButton = wx.Button(self, -1, "Decrement")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnDecrement, decButton)
|
||||
|
||||
revButton = wx.Button(self, -1, "Reverse")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnReverse, revButton)
|
||||
|
||||
restButton = wx.Button(self, -1, "Rest")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnRest, restButton)
|
||||
|
||||
startButton = wx.Button(self, -1, "Start")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnStart, startButton)
|
||||
|
||||
stopButton = wx.Button(self, -1, "Stop")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnStop, stopButton)
|
||||
|
||||
customBox1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
customBox1.AddMany([
|
||||
(nextButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5),
|
||||
(prevButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5),
|
||||
(incButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5),
|
||||
(decButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5),
|
||||
(revButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5),
|
||||
])
|
||||
|
||||
customBox2 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
customBox2.AddMany([
|
||||
(restButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5),
|
||||
(startButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5),
|
||||
(stopButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5),
|
||||
])
|
||||
|
||||
sizer.Add( customBox1, (len(self.throbbers) + 5, 0), (1, 3), flag = wx.ALIGN_CENTER )
|
||||
sizer.Add( customBox2, (len(self.throbbers) + 6, 0), (1, 3), flag = wx.ALIGN_CENTER )
|
||||
|
||||
# Layout.
|
||||
self.SetSizer(box)
|
||||
self.SetAutoLayout(True)
|
||||
self.Layout()
|
||||
@@ -130,6 +194,30 @@ class TestPanel(wx.Panel):
|
||||
for t in self.throbbers.keys():
|
||||
self.throbbers[t]['throbber'].Rest()
|
||||
|
||||
def OnNext(self, event):
|
||||
self.customThrobber.Next()
|
||||
|
||||
def OnPrevious(self, event):
|
||||
self.customThrobber.Previous()
|
||||
|
||||
def OnIncrement(self, event):
|
||||
self.customThrobber.Increment()
|
||||
|
||||
def OnDecrement(self, event):
|
||||
self.customThrobber.Decrement()
|
||||
|
||||
def OnReverse(self, event):
|
||||
self.customThrobber.Reverse()
|
||||
|
||||
def OnRest(self, event):
|
||||
self.customThrobber.Rest()
|
||||
|
||||
def OnStart(self, event):
|
||||
self.customThrobber.Start()
|
||||
|
||||
def OnStop(self, event):
|
||||
self.customThrobber.Stop()
|
||||
|
||||
def ShutdownDemo(self):
|
||||
for t in self.throbbers.keys():
|
||||
self.throbbers[t]['throbber'].Rest()
|
||||
|
||||
@@ -71,11 +71,11 @@ class MyCustomPanelXmlHandler(xrc.XmlResourceHandler):
|
||||
def __init__(self):
|
||||
xrc.XmlResourceHandler.__init__(self)
|
||||
# Specify the styles recognized by objects of this type
|
||||
self.AddStyle("wxNO_3D", wx.NO_3D);
|
||||
self.AddStyle("wxTAB_TRAVERSAL", wx.TAB_TRAVERSAL);
|
||||
self.AddStyle("wxWS_EX_VALIDATE_RECURSIVELY", wx.WS_EX_VALIDATE_RECURSIVELY);
|
||||
self.AddStyle("wxCLIP_CHILDREN", wx.CLIP_CHILDREN);
|
||||
self.AddWindowStyles();
|
||||
self.AddStyle("wxNO_3D", wx.NO_3D)
|
||||
self.AddStyle("wxTAB_TRAVERSAL", wx.TAB_TRAVERSAL)
|
||||
self.AddStyle("wxWS_EX_VALIDATE_RECURSIVELY", wx.WS_EX_VALIDATE_RECURSIVELY)
|
||||
self.AddStyle("wxCLIP_CHILDREN", wx.CLIP_CHILDREN)
|
||||
self.AddWindowStyles()
|
||||
|
||||
# This method and the next one are required for XmlResourceHandlers
|
||||
def CanHandle(self, node):
|
||||
|
||||
115
wxPython/demo/data/proclamation.txt
Normal file
115
wxPython/demo/data/proclamation.txt
Normal file
@@ -0,0 +1,115 @@
|
||||
EMANCIPATION PROCLAMATION:
|
||||
By the President of the United States of America:
|
||||
A PROCLAMATION
|
||||
|
||||
Whereas on the 22nd day of September, A.D. 1862, a proclamation
|
||||
was issued by the President of the United States, containing,
|
||||
among other things, the following, to wit:
|
||||
|
||||
"That on the 1st day of January, A.D. 1863, all persons held as
|
||||
slaves within any State or designated part of a State the people
|
||||
whereof shall then be in rebellion against the United States shall
|
||||
be then, thenceforward, and forever free; and the executive
|
||||
government of the United States, including the military and naval
|
||||
authority thereof, will recognize and maintain the freedom of such
|
||||
persons and will do no act or acts to repress such persons, or any
|
||||
of them, in any efforts they may make for their actual freedom.
|
||||
|
||||
"That the executive will on the 1st day of January aforesaid,
|
||||
by proclamation, designate the States and parts of States, if any,
|
||||
in which the people thereof, respectively, shall then be in
|
||||
rebellion against the United States; and the fact that any State
|
||||
or the people thereof shall on that day be in good faith
|
||||
represented in the Congress of the United States by members
|
||||
chosen thereto at elections wherein a majority of the qualified
|
||||
voters of such States shall have participated shall, in the
|
||||
absence of strong countervailing testimony, be deemed conclusive
|
||||
evidence that such State and the people thereof are not then
|
||||
in rebellion against the United States."
|
||||
|
||||
Now, therefore, I, Abraham Lincoln, President of the United
|
||||
States, by virtue of the power in me vested as Commander-In-Chief
|
||||
of the Army and Navy of the United States in time of actual armed
|
||||
rebellion against the authority and government of the United States,
|
||||
and as a fit and necessary war measure for supressing said
|
||||
rebellion, do, on this 1st day of January, A.D. 1863, and in
|
||||
accordance with my purpose so to do, publicly proclaimed for the
|
||||
full period of one hundred days from the first day above mentioned,
|
||||
order and designate as the States and parts of States wherein the
|
||||
people thereof, respectively, are this day in rebellion against
|
||||
the United States the following, to wit:
|
||||
|
||||
Arkansas, Texas, Louisiana (except the parishes of St. Bernard,
|
||||
Palquemines, Jefferson, St. John, St. Charles, St. James, Ascension,
|
||||
Assumption, Terrebone, Lafourche, St. Mary, St. Martin, and Orleans,
|
||||
including the city of New Orleans), Mississippi, Alabama, Florida,
|
||||
Georgia, South Carolina, North Carolina, and Virginia (except the
|
||||
forty-eight counties designated as West Virginia, and also the
|
||||
counties of Berkeley, Accomac, Morthhampton, Elizabeth City, York,
|
||||
Princess Anne, and Norfolk, including the cities of Norfolk and
|
||||
Portsmouth), and which excepted parts are for the present left
|
||||
precisely as if this proclamation were not issued.
|
||||
|
||||
And by virtue of the power and for the purpose aforesaid, I do
|
||||
order and declare that all persons held as slaves within said
|
||||
designated States and parts of States are, and henceforward shall
|
||||
be, free; and that the Executive Government of the United States,
|
||||
including the military and naval authorities thereof, will
|
||||
recognize and maintain the freedom of said persons.
|
||||
|
||||
And I hereby enjoin upon the people so declared to be free to
|
||||
abstain from all violence, unless in necessary self-defence; and
|
||||
I recommend to them that, in all case when allowed, they labor
|
||||
faithfully for reasonable wages.
|
||||
|
||||
And I further declare and make known that such persons of
|
||||
suitable condition will be received into the armed service of
|
||||
the United States to garrison forts, positions, stations, and
|
||||
other places, and to man vessels of all sorts in said service.
|
||||
|
||||
And upon this act, sincerely believed to be an act of justice,
|
||||
warranted by the Constitution upon military necessity, I invoke
|
||||
the considerate judgment of mankind and the gracious favor
|
||||
of Almighty God.
|
||||
|
||||
(signed)
|
||||
ABRAHAM LINCOLN
|
||||
-------------------------------------
|
||||
|
||||
On Jan. 1, 1863, U.S. President Abraham Lincoln declared free
|
||||
all slaves residing in territory in rebellion against the federal
|
||||
government. This Emancipation Proclamation actually freed few
|
||||
people. It did not apply to slaves in border states fighting on
|
||||
the Union side; nor did it affect slaves in southern areas already
|
||||
under Union control. Naturally, the states in rebellion did not
|
||||
act on Lincoln's order. But the proclamation did show Americans--
|
||||
and the world--that the civil war was now being fought to end slavery.
|
||||
|
||||
Lincoln had been reluctant to come to this position. A believer
|
||||
in white supremacy, he initially viewed the war only in terms of
|
||||
preserving the Union. As pressure for abolition mounted in
|
||||
Congress and the country, however, Lincoln became more sympathetic
|
||||
to the idea. On Sept. 22, 1862, he issued a preliminary proclamation
|
||||
announcing that emancipation would become effective on Jan. 1, 1863,
|
||||
in those states still in rebellion. Although the Emancipation
|
||||
Proclamation did not end slavery in America--this was achieved
|
||||
by the passage of the 13TH Amendment to the Constitution on Dec.
|
||||
18, 1865--it did make that accomplishment a basic war goal and
|
||||
a virtual certainty.
|
||||
|
||||
DOUGLAS T. MILLER
|
||||
|
||||
Bibliography: Commager, Henry Steele, The Great Proclamation
|
||||
(1960); Donovan, Frank, Mr. Lincoln's Proclamation (1964);
|
||||
Franklin, John Hope, ed., The Emancipation Proclamation (1964).
|
||||
|
||||
-------------------------------------
|
||||
|
||||
Prepared by Gerald Murphy (The Cleveland Free-Net - aa300)
|
||||
Distributed by the Cybercasting Services Division of the
|
||||
National Public Telecomputing Network (NPTN).
|
||||
|
||||
Permission is hereby granted to download, reprint, and/or otherwise
|
||||
redistribute this file, provided appropriate point of origin
|
||||
credit is given to the preparer(s) and the National Public
|
||||
Telecomputing Network.
|
||||
@@ -419,7 +419,7 @@ EOF
|
||||
$INSTALLROOT \
|
||||
$RESOURCEDIR
|
||||
|
||||
mv $PKGNAME.pkg $DMGROOT
|
||||
mv $PKGNAME.pkg $DMGROOT/$PKGNAME.pkg
|
||||
|
||||
rm $RESOURCEDIR/postflight
|
||||
rm $RESOURCEDIR/preflight
|
||||
@@ -569,7 +569,7 @@ EOF
|
||||
if [ ! -e $TARBALLDIR/wxPython-demo-$VERSION.tar.gz ]; then
|
||||
cat > "$DMGAPPS/Samples/Build ERROR.txt" <<EOF
|
||||
|
||||
The wxPython-demo tarball was not found when building this disk image!
|
||||
The wxPython-$VERSION-demo tarball was not found when building this disk image!
|
||||
|
||||
EOF
|
||||
cp "$DMGAPPS/Samples/Build ERROR.txt" $DMGAPPS
|
||||
|
||||
@@ -23,17 +23,11 @@ will be created.
|
||||
import sys, os, time
|
||||
|
||||
KEEP_TEMPS = 1
|
||||
ISCC = r"%s\InnoSetup2Ex\ISCC.exe %s"
|
||||
# default InnoSetup installer location
|
||||
ISCC = r"C:\progra~1\innose~1\ISCC.exe %s"
|
||||
|
||||
# see if we can find Inno Setup 4 and use that if so
|
||||
USING_INNO4=False
|
||||
try:
|
||||
import _winreg as wreg
|
||||
key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, "Software\Bjornar Henden\ISTool4\Prefs")
|
||||
INNO_FOLDER = wreg.QueryValueEx(key,'InnoFolder')[0]
|
||||
USING_INNO4=True
|
||||
except:
|
||||
pass
|
||||
if os.environ.has_key("INNO4"):
|
||||
ISCC = os.environ["INNO4"]
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
@@ -403,7 +397,7 @@ Source: "demo\data\*.mpg"; DestDir: "{app}\demo\data";
|
||||
;;Source: "demo\dllwidget\makefile.*"; DestDir: "{app}\demo\dllwidget";
|
||||
|
||||
Source: "licence\*.txt"; DestDir: "{app}\docs\licence";
|
||||
Source: "%(WXDIR)s\docs\htmlhelp\wx.chm"; DestDir: "{app}\docs";
|
||||
;;Source: "%(WXDIR)s\docs\htmlhelp\wx.chm"; DestDir: "{app}\docs";
|
||||
;;Source: "%(WXDIR)s\docs\htmlhelp\ogl.chm"; DestDir: "{app}\docs";
|
||||
Source: "docs\README.txt"; DestDir: "{app}\docs"; Flags: isreadme;
|
||||
Source: "docs\*.txt"; DestDir: "{app}\docs";
|
||||
@@ -628,8 +622,7 @@ def main():
|
||||
ISSDEMOFILE = "__wxPythonDemo.iss"
|
||||
IFSFILE = "__wxPython.ifs"
|
||||
IFSFILEREF = "CodeFile = " + IFSFILE
|
||||
if USING_INNO4:
|
||||
IFSFILEREF = ""
|
||||
IFSFILEREF = ""
|
||||
UNINSTALL_BATCH = get_batch_files()
|
||||
PKGDIR = open('src/wx.pth').read()
|
||||
LOCALE = build_locale_string(PKGDIR)
|
||||
@@ -669,18 +662,12 @@ def main():
|
||||
global IFS_Template
|
||||
global ISS_DocDemo_Template
|
||||
|
||||
if USING_INNO4:
|
||||
ISS_Template = ISS_Template + "\n[Code]\n" + IFS_Template
|
||||
ISS_Template = ISS_Template + "\n[Code]\n" + IFS_Template
|
||||
|
||||
f = open(ISSFILE, "w")
|
||||
f.write(ISS_Template % vars())
|
||||
f.close()
|
||||
|
||||
if not USING_INNO4:
|
||||
f = open(IFSFILE, "w")
|
||||
f.write(IFS_Template % vars())
|
||||
f.close()
|
||||
|
||||
f = open(ISSDEMOFILE, "w")
|
||||
f.write(ISS_DocDemo_Template % vars())
|
||||
f.close()
|
||||
@@ -688,16 +675,9 @@ def main():
|
||||
TOOLS = os.environ['TOOLS']
|
||||
if TOOLS.startswith('/cygdrive'):
|
||||
TOOLS = r"c:\TOOLS" # temporary hack until I convert everything over to bash
|
||||
if USING_INNO4:
|
||||
print "Hello world!"
|
||||
ISCC = os.path.join(INNO_FOLDER, "iscc.exe")
|
||||
ISCC = r'"' + ISCC + '" %s'
|
||||
os.system(ISCC % (ISSFILE))
|
||||
#os.system(ISCC % (ISSDEMOFILE))
|
||||
else:
|
||||
print "not found..."
|
||||
os.system(ISCC % (TOOLS, ISSFILE))
|
||||
os.system(ISCC % (TOOLS, ISSDEMOFILE))
|
||||
|
||||
os.system(ISCC % (ISSFILE))
|
||||
os.system(ISCC % (ISSDEMOFILE))
|
||||
|
||||
if not KEEP_TEMPS:
|
||||
time.sleep(1)
|
||||
|
||||
@@ -29,7 +29,7 @@ rm -f `find _distrib_tgz/wxPython-$VERSION -name ".#*"`
|
||||
cd _distrib_tgz
|
||||
|
||||
tar cvf ../dist/wxPython-demo-$VERSION.tar wxPython-$VERSION
|
||||
gzip -9 ../dist/wxPython-demo-$VERSION.tar
|
||||
gzip -9 -f ../dist/wxPython-demo-$VERSION.tar
|
||||
|
||||
cd ..
|
||||
rm -r _distrib_tgz
|
||||
|
||||
@@ -9,7 +9,7 @@ fi
|
||||
|
||||
|
||||
VERSION=`python -c "import setup;print setup.VERSION"`
|
||||
CONTRIBS="ogl gizmos"
|
||||
CONTRIBS="gizmos"
|
||||
DEST=wxPython-$VERSION/docs
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ done
|
||||
popd
|
||||
cp ../distrib/viewdocs.py $DEST
|
||||
cp ../distrib/README.viewdocs.txt $DEST/README.txt
|
||||
cp ../docs/xml/wxPython-metadata.xml $DEST
|
||||
##cp ../docs/xml/wxPython-metadata.xml $DEST
|
||||
|
||||
rm -f ../dist/wxPython-docs-$VERSION.tar.gz
|
||||
tar cvf ../dist/wxPython-docs-$VERSION.tar $DEST
|
||||
|
||||
@@ -22,7 +22,6 @@ if os.access(basePath, os.W_OK):
|
||||
args = ['',
|
||||
'--cache='+basePath,
|
||||
os.path.join(basePath, 'wx.zip'),
|
||||
os.path.join(basePath, 'ogl.zip'),
|
||||
]
|
||||
|
||||
# add any other .zip files found
|
||||
|
||||
@@ -118,7 +118,7 @@ Provides: wxPython
|
||||
|
||||
%description -n %{pkgname}%{ver2}-%{port}-%{chartype}
|
||||
wxPython is a GUI toolkit for the Python programming language. It
|
||||
allows Python programmers to create programs with a robust, highly
|
||||
allows Python programmers to create programs with a robust, highly
|
||||
functional graphical user interface, simply and easily. It is
|
||||
implemented as a Python extension module (native code) that wraps the
|
||||
popular wxWidgets cross platform GUI library, which is written in C++.
|
||||
|
||||
@@ -18,26 +18,28 @@ The following deprecated items have been removed:
|
||||
|
||||
* wx.PrintDialogData SetSetupDialog and GetSetupDialog methods
|
||||
|
||||
* wx.FontMapper SetConfig method
|
||||
|
||||
|
||||
|
||||
|
||||
2.6.1.1
|
||||
|
||||
2.6.2.1
|
||||
-------
|
||||
|
||||
wxMSW: Fix for bug #1211907, popup menu indenting inconsistent with
|
||||
bitmaps.
|
||||
bitmaps.
|
||||
|
||||
wxMac: Don't send an event for wx.RadioButton deselections, just the
|
||||
selections. This was done to make it consistent with the other
|
||||
platforms.
|
||||
platforms.
|
||||
|
||||
wxMSW: Always set flat toolbar style, even under XP with themes: this
|
||||
is necessary or separators aren't shown at all.
|
||||
|
||||
Fixes for bug #1217872, pydocview.DocService not correctly initialized
|
||||
Fixes for bug #1217872, pydocview.DocService not correctly initialized.
|
||||
|
||||
Fix for bug #1217874, Error in parameter name in DocManager.CreateView
|
||||
Fix for bug #1217874, Error in parameter name in DocManager.CreateView.
|
||||
|
||||
Added wrappers for the wx.RendererNative class.
|
||||
|
||||
@@ -46,7 +48,7 @@ MultiSplitterWindow class. This class is much like the standard
|
||||
wx.SplitterWindow class, except it allows more than one split, so it
|
||||
can manage more than two child windows.
|
||||
|
||||
Docview and IDE patch from Morag Hua with fix for bug #1217890
|
||||
Docview and IDE patch from Morgan Hua with fix for bug #1217890
|
||||
"Closing view crashes Python" plus some new features::
|
||||
|
||||
New feature added to the IDE is 'Extensions'. Under
|
||||
@@ -57,6 +59,173 @@ Docview and IDE patch from Morag Hua with fix for bug #1217890
|
||||
|
||||
Some fixes to XRCed to make encoding errors a bit more user friendly.
|
||||
|
||||
XRCed changes from Roman Rolinsky:
|
||||
|
||||
* Added new controls (Choicebook, Listbook, StatusBar,
|
||||
DatePicker), and completed style flags. Test window is opened
|
||||
for an available parent control if no specific view
|
||||
defined. Better handling of exceptions (highlighting does not
|
||||
'stick' anymore).
|
||||
|
||||
* Use system clipboard for Copy/Paste.
|
||||
|
||||
* Improved some dialogs (window styles, growable cols). Changed
|
||||
the range for wxSpinCtrl min/max to all integers (default 0/100
|
||||
is not always good).
|
||||
|
||||
Updates for wx.lib.foldpanelbar and wx.lib.hyperlink from Andrea
|
||||
Gavana.
|
||||
|
||||
Fix for Bug #1283496: wxPython TheClipboard class causes problems for
|
||||
pychecker. Ensure the app has been created before initializing
|
||||
wx.TheClipboard.
|
||||
|
||||
Fix for Bug #1352602: FileBrowseButtonWithHistory can't type in Value.
|
||||
|
||||
wxHTML: Added space after list item number.
|
||||
|
||||
wx.lib.printout: Applied patch #1384440.
|
||||
|
||||
wxMSW: Fix for Bug #1293225 Window_FromHWND crashes if parent is
|
||||
None.
|
||||
|
||||
Fix for Bug #1261669, use a wx.TE_RICH2 style for the Process demo so
|
||||
it doesn't fill up too soon.
|
||||
|
||||
Applied Patch #1354389: wxPython MenuItem SetBitmaps fix.
|
||||
|
||||
Applied Patch #1239456: wxPython wx.DataObject.GetAllFormats fix.
|
||||
|
||||
Applied Patch # #1230107 which allows image handlers to be written in
|
||||
Python by deriving from wx.PyImageHandler.
|
||||
|
||||
Applied patch #1072210: generalize printout.py to allow text printing.
|
||||
|
||||
Applied patch #1243907: Give Throbber much more flexibility by
|
||||
allowing the user to set the rest image, the direction, the current
|
||||
index, custom sequence. Allows user to manually step through the
|
||||
sequence with Next(), Previous(), Increment(), Decrement() &
|
||||
SetCurrent(). Very handy if you have multiple throbbers that you want
|
||||
to synchronize with a single timer.
|
||||
|
||||
Fix for bug #1336711: wx.lib.calendar.CalenDlg can yield incorrect
|
||||
result.
|
||||
|
||||
Applied patch from Morgan Hua for updates to ActiveGrid code
|
||||
(pydocview, ActiveGrid IDE, etc.)
|
||||
|
||||
Applied patch #1326241: Supporting "setup.py install --install-headers=path"
|
||||
|
||||
Applied patch from Morgan Hua to fix bug #1219423: CommandManager
|
||||
should not repeat old commands after a branch.
|
||||
|
||||
Applied patch #1238825 adding search backward capabilities to the
|
||||
demo. Modified to use the up/down options in the wx.FindReplaceDialog
|
||||
instead of a separate menu item.
|
||||
|
||||
Fix for bug #1266745 and #1387725 in the wx.FindReplaceDialog on MSW.
|
||||
Actually check we are using MSLU before doing the hack designed to
|
||||
workaround a bug in MSLU!
|
||||
|
||||
wxMSW: wx.lib.iewin.IEHtmlWindow now properly handles tabbing, return
|
||||
and other special keys properly.
|
||||
|
||||
Lots of PyCrust enhancments started by Franz Steinaeusler, Adi Sieker,
|
||||
and Sebastian Haase, and which in turn were further enhanced, fixed
|
||||
tweaked and finished up by me. The 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.
|
||||
|
||||
* General code cleanup and fixes.
|
||||
|
||||
* Use wx.StandardPaths to determine the location of the config
|
||||
files.
|
||||
|
||||
* 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.
|
||||
|
||||
|
||||
Applied patches from Will Sadkin for wx.lib.masked modules:
|
||||
|
||||
* Now ignores kill focus events when being destroyed.
|
||||
|
||||
* Added missing call to set insertion point on changing fields.
|
||||
|
||||
* Modified SetKeyHandler() to accept None as means of removing
|
||||
one.
|
||||
|
||||
* Fixed keyhandler processing for group and decimal character
|
||||
changes.
|
||||
|
||||
* Fixed a problem that prevented input into the integer digit of a
|
||||
integerwidth=1 numctrl, if the current value was 0.
|
||||
|
||||
* Fixed logic involving processing of "_signOk" flag, to remove
|
||||
default sign key handlers if false, so that
|
||||
SetAllowNegative(False) in the NumCtrl works properly.
|
||||
|
||||
* 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.
|
||||
|
||||
wx.FontMapper.SetConfig is deprecated. You should instead just set an
|
||||
application-wide config object with wx.Config.Set, which wx.FontMapper
|
||||
will use by default.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -92,7 +261,7 @@ wx.TopLevelWindow.ShowFullScreen.
|
||||
Applied patch #1213066 correct device names for Joystick in Linux.
|
||||
|
||||
wxGTK: Applied patch #1207162 wx.TextCtrl.SetStyle fix for overlapping
|
||||
calls.
|
||||
calls.
|
||||
|
||||
wx.FileConfig: fixed DeleteEntry to set the dirty flag properly so the
|
||||
change will get written at the next flush.
|
||||
@@ -107,7 +276,7 @@ change will get written at the next flush.
|
||||
|
||||
Added wx.BrushFromBitmap to create a stippled brush in a single step.
|
||||
Also added missing brysh style flags: wx.STIPPLE_MASK
|
||||
wx.STIPPLE_MASK_OPAQUE.
|
||||
wx.STIPPLE_MASK_OPAQUE.
|
||||
|
||||
wxMSW: Fix for default control colours when the system text fg colour
|
||||
is not black.
|
||||
@@ -116,7 +285,7 @@ wxGTK: Patch #1171754, It is now possible to have a menu item that
|
||||
both has an icon and is a submenu.
|
||||
|
||||
wxMSW: Patch #1197009, better refreshes when windows are moved and
|
||||
resized.
|
||||
resized.
|
||||
|
||||
wxMSW: Patch #1197468. Keeps track of pending size/position changes
|
||||
in case there is more than one adjustment for a window in a single
|
||||
@@ -177,7 +346,7 @@ wxMSW: Fix for wrong sash colour of wx.SplitterWindow in the silver
|
||||
theme on XP.
|
||||
|
||||
Added a wx.xrc.XmlResourceHandler for the Ticker class. See
|
||||
wx/lib/ticker_xrc.py
|
||||
wx/lib/ticker_xrc.py
|
||||
|
||||
wxSTC: Fixed CmdKeyAssign key bindings for Ctrl-Backspace.
|
||||
|
||||
@@ -200,7 +369,7 @@ XP themes.
|
||||
|
||||
More updates to the docview library modules and sample apps from the
|
||||
ActiveGrid folks. Their sample IDE is now able to integrate with
|
||||
Subversion.
|
||||
Subversion.
|
||||
|
||||
wx.grid.Grid: Ensure that the grid gets the focus when it is
|
||||
left-clicked. Note that if you have custom widgets that handle the
|
||||
@@ -218,7 +387,7 @@ window itself, not the borders, scrollbars, etc. (Bug #1204069)
|
||||
|
||||
Print framework: Add more paper sizes and code to fallback to an
|
||||
explicit paper size if a known paper size is not found for the
|
||||
printer.
|
||||
printer.
|
||||
|
||||
wxMac: Applied patch for bug #1206181 Option-key decodes are wrong,
|
||||
also applied patch for bug #1205691 Modified Fn keys don't work.
|
||||
@@ -236,7 +405,7 @@ The default DoGetBestSize is updated to not always return the current
|
||||
size if the window has no sizer, children, or minsize set. Instead
|
||||
the current size is set as the minsize. This solves the occasional
|
||||
problem where a sizer may cause a childless panel to grow but never
|
||||
shrink.
|
||||
shrink.
|
||||
|
||||
wxMSW: When converting a wx.Icon to a bitmap check if the icon has an
|
||||
alpha channel and set the bitmap to use it.
|
||||
@@ -309,7 +478,7 @@ EVT_KEY_UP and EVT_TEXT events from its embedded text control.
|
||||
wxMac: Corrected refresh bugs in wxGrid.
|
||||
|
||||
XRCed: Updated to version 0.1.5.
|
||||
* Added wxWizard, wxWizardPageSimple (only from pull-down menu).
|
||||
* Added wxWizard, wxWizardPageSimple (only from pull-down menu).
|
||||
* Hide command for test window.
|
||||
* Replacing classes works better.
|
||||
* Added Locate tool.
|
||||
@@ -317,7 +486,7 @@ XRCed: Updated to version 0.1.5.
|
||||
|
||||
|
||||
|
||||
2.5.5.1
|
||||
2.5.5.1
|
||||
-------
|
||||
* 8-Apr-2005
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -497,6 +497,39 @@ public:
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// A wxImageHandler that can be derived from in Python.
|
||||
//
|
||||
|
||||
class wxPyImageHandler: public wxImageHandler {
|
||||
protected:
|
||||
PyObject *m_self;
|
||||
|
||||
// used for interning method names as PyStrings
|
||||
static PyObject* m_DoCanRead_Name;
|
||||
static PyObject* m_GetImageCount_Name;
|
||||
static PyObject* m_LoadFile_Name;
|
||||
static PyObject* m_SaveFile_Name;
|
||||
|
||||
// converstion helpers
|
||||
PyObject* py_InputStream(wxInputStream* stream);
|
||||
PyObject* py_Image(wxImage* image);
|
||||
PyObject* py_OutputStream(wxOutputStream* stream);
|
||||
|
||||
public:
|
||||
wxPyImageHandler();
|
||||
~wxPyImageHandler();
|
||||
void _SetSelf(PyObject *self);
|
||||
|
||||
virtual bool LoadFile(wxImage* image, wxInputStream& stream,
|
||||
bool verbose=true, int index=-1 );
|
||||
virtual bool SaveFile(wxImage* image, wxOutputStream& stream,
|
||||
bool verbose=true );
|
||||
virtual int GetImageCount(wxInputStream& stream );
|
||||
virtual bool DoCanRead(wxInputStream &stream);
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// This class holds an instance of a Python Shadow Class object and assists
|
||||
// with looking up and invoking Python callback methods from C++ virtual
|
||||
|
||||
@@ -11,37 +11,45 @@
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
import wx
|
||||
from IDE import ACTIVEGRID_BASE_IDE, getSplashBitmap
|
||||
import os.path
|
||||
from IDE import ACTIVEGRID_BASE_IDE, getSplashBitmap, getIDESplashBitmap
|
||||
import activegrid.util.sysutils as sysutilslib
|
||||
_ = wx.GetTranslation
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Package License Data for AboutDialog
|
||||
# Package, License, URL
|
||||
# If no information is available, put a None as a place holder.
|
||||
#
|
||||
# NO GPL Allowed. Only LGPL, BSD, and Public Domain Based Licenses!
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
|
||||
licenseData = [
|
||||
("ActiveGrid", "ASL 2.0", "http://apache.org/licenses/LICENSE-2.0"),
|
||||
("Python 2.3", "Python Software Foundation License", "http://www.python.org/2.3/license.html"),
|
||||
("wxPython 2.5", "wxWidgets 2 - LGPL", "http://wxwidgets.org/newlicen.htm"),
|
||||
("wxWidgets", "wxWindows Library License 3", "http://www.wxwidgets.org/manuals/2.5.4/wx_wxlicense.html"),
|
||||
licenseData = [ # add licenses for base IDE features
|
||||
("ActiveGrid", "Apache License, Version 2.0", "http://apache.org/licenses/LICENSE-2.0"),
|
||||
("Python 2.4", "Python Software Foundation License", "http://www.python.org/2.4/license.html"),
|
||||
("wxPython 2.6", "wxWidgets 2 - LGPL", "http://wxwidgets.org/newlicen.htm"),
|
||||
("wxWidgets", "wxWindows Library License 3", "http://www.wxwidgets.org/manuals/2.6.1/wx_wxlicense.html"),
|
||||
("pychecker", "MetaSlash - BSD", "http://pychecker.sourceforge.net/COPYRIGHT"),
|
||||
("process.py", "See file", "http://starship.python.net/~tmick/"),
|
||||
("pysvn", "Apache License", "http://pysvn.tigris.org/"),
|
||||
("pysvn", "Apache License, Version 2.0", "http://pysvn.tigris.org/"),
|
||||
]
|
||||
|
||||
if not ACTIVEGRID_BASE_IDE: # add licenses for database connections only if not the base IDE
|
||||
if not ACTIVEGRID_BASE_IDE: # add licenses for non-base IDE features such as database connections
|
||||
licenseData += [
|
||||
("pydb2", "LGPL", "http://sourceforge.net/projects/pydb2"),
|
||||
("pysqlite", "Python License (CNRI)", "http://sourceforge.net/projects/pysqlite"),
|
||||
("mysql-python", "GPL, Python License (CNRI), Zope Public License", "http://sourceforge.net/projects/mysql-python"),
|
||||
("cx_Oracle", "Computronix", "http://http://www.computronix.com/download/License(cxOracle).txt"),
|
||||
("cx_Oracle", "Computronix", "http://www.computronix.com/download/License(cxOracle).txt"),
|
||||
("SQLite", "Public Domain", "http://www.sqlite.org/copyright.html"),
|
||||
("PyGreSQL", "BSD", "http://www.pygresql.org"),
|
||||
("pyXML", "CNRI Python License", "http://sourceforge.net/softwaremap/trove_list.php?form_cat=194"),
|
||||
("Zolera Soap Infrastructure", "Zope Public License 2.0", "http://www.zope.org/Resources/License/"),
|
||||
("Sarissa", "LGPL", "http://sourceforge.net/projects/sarissa/"),
|
||||
("Dynarch DHTML Calendar", "LGPL", "http://www.dynarch.com/projects/calendar/"),
|
||||
]
|
||||
|
||||
if wx.Platform == '__WXMSW__':
|
||||
if wx.Platform == '__WXMSW__': # add Windows only licenses
|
||||
licenseData += [("pywin32", "Python Software Foundation License", "http://sourceforge.net/projects/pywin32/")]
|
||||
|
||||
class AboutDialog(wx.Dialog):
|
||||
@@ -56,10 +64,25 @@ class AboutDialog(wx.Dialog):
|
||||
|
||||
aboutPage = wx.Panel(nb, -1)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
splash_bmp = getSplashBitmap()
|
||||
|
||||
if not ACTIVEGRID_BASE_IDE:
|
||||
splash_bmp = getSplashBitmap()
|
||||
else:
|
||||
splash_bmp = getIDESplashBitmap()
|
||||
|
||||
# find version number from
|
||||
versionFilepath = os.path.join(sysutilslib.mainModuleDir, "version.txt")
|
||||
if os.path.exists(versionFilepath):
|
||||
versionfile = open(versionFilepath, 'r')
|
||||
versionLines = versionfile.readlines()
|
||||
versionfile.close()
|
||||
version = "".join(versionLines)
|
||||
else:
|
||||
version = _("Version Unknown - %s not found" % versionFilepath)
|
||||
|
||||
image = wx.StaticBitmap(aboutPage, -1, splash_bmp, (0,0), (splash_bmp.GetWidth(), splash_bmp.GetHeight()))
|
||||
sizer.Add(image, 0, wx.ALIGN_CENTER|wx.ALL, 0)
|
||||
sizer.Add(wx.StaticText(aboutPage, -1, wx.GetApp().GetAppName() + _("\nVersion 0.7 Early Access\n\nCopyright (c) 2003-2005 ActiveGrid Incorporated and Contributors. All rights reserved.")), 0, wx.ALIGN_LEFT|wx.ALL, 10)
|
||||
sizer.Add(wx.StaticText(aboutPage, -1, wx.GetApp().GetAppName() + _("\n%s\n\nCopyright (c) 2003-2005 ActiveGrid Incorporated and Contributors. All rights reserved.") % version), 0, wx.ALIGN_LEFT|wx.ALL, 10)
|
||||
sizer.Add(wx.StaticText(aboutPage, -1, _("http://www.activegrid.com")), 0, wx.ALIGN_LEFT|wx.LEFT|wx.BOTTOM, 10)
|
||||
aboutPage.SetSizer(sizer)
|
||||
nb.AddPage(aboutPage, _("Copyright"))
|
||||
@@ -78,12 +101,16 @@ class AboutDialog(wx.Dialog):
|
||||
maxHeight = h
|
||||
grid.SetColLabelSize(maxHeight + 6) # add a 6 pixel margin
|
||||
|
||||
maxW = 0
|
||||
for row, data in enumerate(licenseData):
|
||||
package = data[0]
|
||||
license = data[1]
|
||||
url = data[2]
|
||||
if package:
|
||||
grid.SetRowLabelValue(row, package)
|
||||
w, h = dc.GetTextExtent(package)
|
||||
if w > maxW:
|
||||
maxW = w
|
||||
if license:
|
||||
grid.SetCellValue(row, 0, license)
|
||||
if url:
|
||||
@@ -95,8 +122,9 @@ class AboutDialog(wx.Dialog):
|
||||
grid.EnableDragRowSize(False)
|
||||
grid.SetRowLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE)
|
||||
grid.SetLabelBackgroundColour(wx.WHITE)
|
||||
grid.AutoSizeColumn(0, 100)
|
||||
grid.AutoSizeColumn(1, 100)
|
||||
grid.AutoSizeColumn(0)
|
||||
grid.AutoSizeColumn(1)
|
||||
grid.SetRowLabelSize(maxW + 10)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer.Add(grid, 1, wx.EXPAND|wx.ALL, 10)
|
||||
licensePage.SetSizer(sizer)
|
||||
@@ -104,7 +132,7 @@ class AboutDialog(wx.Dialog):
|
||||
|
||||
creditsPage = wx.Panel(nb, -1)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer.Add(wx.StaticText(creditsPage, -1, _("ActiveGrid Development Team:\n\nLawrence Bruhmuller\nEric Chu\nMatt Fryer\nJoel Hare\nMorgan Hua\nAlan Mullendore\nJeff Norton\nKevin Wang\nPeter Yared")), 0, wx.ALIGN_LEFT|wx.ALL, 10)
|
||||
sizer.Add(wx.StaticText(creditsPage, -1, _("ActiveGrid Development Team:\n\nLarry Abrahams\nLawrence Bruhmuller\nEric Chu\nBeth Fryer\nMatt Fryer\nJoel Hare\nMorgan Hua\nMatt McNulty\nPratik Mehta\nAlan Mullendore\nJeff Norton\nSimon Toens\nKevin Wang\nPeter Yared")), 0, wx.ALIGN_LEFT|wx.ALL, 10)
|
||||
creditsPage.SetSizer(sizer)
|
||||
nb.AddPage(creditsPage, _("Credits"))
|
||||
|
||||
@@ -114,7 +142,8 @@ class AboutDialog(wx.Dialog):
|
||||
sizer.Add(btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
|
||||
|
||||
self.SetSizer(sizer)
|
||||
self.SetAutoLayout(True)
|
||||
sizer.Fit(self)
|
||||
self.Layout()
|
||||
self.Fit()
|
||||
grid.ForceRefresh() # wxBug: Get rid of unnecessary scrollbars
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,19 @@ SHAPE_BRUSH = wx.Brush("WHEAT", wx.SOLID)
|
||||
LINE_BRUSH = wx.BLACK_BRUSH
|
||||
INACTIVE_SELECT_BRUSH = wx.Brush("LIGHT BLUE", wx.SOLID)
|
||||
|
||||
NORMALFONT = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
||||
SLANTFONT = wx.Font(NORMALFONT.GetPointSize(), NORMALFONT.GetFamily(), wx.SLANT, NORMALFONT.GetWeight())
|
||||
BOLDFONT = wx.Font(NORMALFONT.GetPointSize(), NORMALFONT.GetFamily(), NORMALFONT.GetStyle(), wx.BOLD)
|
||||
|
||||
DEFAULT_BACKGROUND_COLOR = wx.Colour(0xEE, 0xEE, 0xEE)
|
||||
HEADER_BRUSH = wx.Brush(wx.Colour(0xDB, 0xEB, 0xFF), wx.SOLID)
|
||||
BODY_BRUSH = wx.Brush(wx.WHITE, wx.SOLID)
|
||||
|
||||
|
||||
PARKING_VERTICAL = 1
|
||||
PARKING_HORIZONTAL = 2
|
||||
PARKING_OFFSET = 30 # space between shapes
|
||||
|
||||
|
||||
def GetRawModel(model):
|
||||
if hasattr(model, "GetRawModel"):
|
||||
@@ -32,6 +45,27 @@ def GetRawModel(model):
|
||||
return rawModel
|
||||
|
||||
|
||||
def GetLabel(model):
|
||||
model = GetRawModel(model)
|
||||
if hasattr(model, "__xmlname__"):
|
||||
label = model.__xmlname__
|
||||
try:
|
||||
if (len(label) > 0):
|
||||
label = label[0].upper() + label[1:]
|
||||
if (hasattr(model, "complexType")):
|
||||
label += ': %s/%s' % (model.complexType.name, model.name)
|
||||
else:
|
||||
if model.name:
|
||||
label += ': %s' % model.name
|
||||
elif model.ref:
|
||||
label += ': %s' % model.ref
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
label = str(model)
|
||||
return label
|
||||
|
||||
|
||||
class CanvasView(wx.lib.docview.View):
|
||||
|
||||
|
||||
@@ -40,9 +74,10 @@ class CanvasView(wx.lib.docview.View):
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def __init__(self, brush = SHAPE_BRUSH):
|
||||
def __init__(self, brush=SHAPE_BRUSH, background=DEFAULT_BACKGROUND_COLOR):
|
||||
wx.lib.docview.View.__init__(self)
|
||||
self._brush = brush
|
||||
self._backgroundColor = background
|
||||
self._canvas = None
|
||||
self._pt1 = None
|
||||
self._pt2 = None
|
||||
@@ -68,6 +103,7 @@ class CanvasView(wx.lib.docview.View):
|
||||
frame.SetSizer(sizer)
|
||||
frame.Layout()
|
||||
self.Activate()
|
||||
wx.EVT_RIGHT_DOWN(self._canvas, self.OnRightClick)
|
||||
return True
|
||||
|
||||
|
||||
@@ -145,12 +181,20 @@ class CanvasView(wx.lib.docview.View):
|
||||
|
||||
self._canvas.SetScrollbars(20, 20, self._maxWidth / 20, self._maxHeight / 20)
|
||||
|
||||
self._canvas.SetBackgroundColour(wx.WHITE)
|
||||
self._canvas.SetBackgroundColour(self._backgroundColor)
|
||||
self._diagram = ogl.Diagram()
|
||||
self._canvas.SetDiagram(self._diagram)
|
||||
self._diagram.SetCanvas(self._canvas)
|
||||
self._canvas.SetFont(NORMALFONT)
|
||||
|
||||
|
||||
def OnClear(self, event):
|
||||
""" Deletion of selected objects from view.
|
||||
*Must Override*
|
||||
"""
|
||||
self.SetPropertyModel(None)
|
||||
|
||||
|
||||
def OnKeyPressed(self, event):
|
||||
key = event.KeyCode()
|
||||
if key == wx.WXK_DELETE:
|
||||
@@ -159,7 +203,42 @@ class CanvasView(wx.lib.docview.View):
|
||||
event.Skip()
|
||||
|
||||
|
||||
def OnRightClick(self, event):
|
||||
""" force selection underneath right click position. """
|
||||
self.Activate()
|
||||
self._canvas.SetFocus()
|
||||
|
||||
dc = wx.ClientDC(self._canvas)
|
||||
self._canvas.PrepareDC(dc)
|
||||
x, y = event.GetLogicalPosition(dc) # this takes into account scrollbar offset
|
||||
shape = self._canvas.FindShape(x, y)[0]
|
||||
|
||||
model = None
|
||||
if not shape:
|
||||
self.SetSelection(None)
|
||||
self.SetPropertyShape(None)
|
||||
elif hasattr(shape, "GetModel"):
|
||||
self.BringToFront(shape)
|
||||
self.SetPropertyShape(shape)
|
||||
self.SetSelection(shape)
|
||||
shape.Select(True, dc)
|
||||
model = shape.GetModel()
|
||||
elif shape.GetParent() and isinstance(shape.GetParent(), ogl.CompositeShape): # ComplexTypeHeader for ComplexTypeShape
|
||||
self.BringToFront(shape)
|
||||
self.SetPropertyShape(shape.GetParent())
|
||||
self.SetSelection(shape.GetParent())
|
||||
shape.GetParent().Select(True, dc)
|
||||
model = shape.GetParent().GetModel()
|
||||
|
||||
self.SetPropertyModel(model)
|
||||
|
||||
return (shape, model)
|
||||
|
||||
|
||||
def OnLeftClick(self, event):
|
||||
self.Activate()
|
||||
self._canvas.SetFocus()
|
||||
|
||||
self.EraseRubberBand()
|
||||
|
||||
dc = wx.ClientDC(self._canvas)
|
||||
@@ -322,21 +401,24 @@ class CanvasView(wx.lib.docview.View):
|
||||
dc.EndDrawing()
|
||||
|
||||
|
||||
def FindParkingSpot(self, width, height):
|
||||
def FindParkingSpot(self, width, height, parking=PARKING_HORIZONTAL, x=PARKING_OFFSET, y=PARKING_OFFSET):
|
||||
""" given a width and height, find a upper left corner where shape can be parked without overlapping other shape """
|
||||
offset = 30 # space between shapes
|
||||
x = offset
|
||||
y = offset
|
||||
maxX = 700 # max distance to the right where we'll place tables
|
||||
max = 700 # max distance to the right where we'll place tables
|
||||
noParkingSpot = True
|
||||
|
||||
while noParkingSpot:
|
||||
point = self.isSpotOccupied(x, y, width, height)
|
||||
if point:
|
||||
x = point[0] + offset
|
||||
if x > maxX:
|
||||
x = offset
|
||||
y = point[1] + offset
|
||||
if parking == PARKING_HORIZONTAL:
|
||||
x = point[0] + PARKING_OFFSET
|
||||
if x > max:
|
||||
x = PARKING_OFFSET
|
||||
y = point[1] + PARKING_OFFSET
|
||||
else: # parking == PARKING_VERTICAL:
|
||||
y = point[1] + PARKING_OFFSET
|
||||
if y > max:
|
||||
y = PARKING_OFFSET
|
||||
x = point[0] + PARKING_OFFSET
|
||||
else:
|
||||
noParkingSpot = False
|
||||
|
||||
@@ -351,7 +433,7 @@ class CanvasView(wx.lib.docview.View):
|
||||
y2 = y + height
|
||||
|
||||
for shape in self._diagram.GetShapeList():
|
||||
if isinstance(shape, ogl.RectangleShape) or isinstance(shape, ogl.EllipseShape):
|
||||
if isinstance(shape, ogl.RectangleShape) or isinstance(shape, ogl.EllipseShape) or isinstance(shape, ogl.PolygonShape):
|
||||
if shape.GetParent() and isinstance(shape.GetParent(), ogl.CompositeShape):
|
||||
# skip, part of a composite shape
|
||||
continue
|
||||
@@ -381,7 +463,7 @@ class CanvasView(wx.lib.docview.View):
|
||||
# Canvas methods
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
def AddShape(self, shape, x = None, y = None, pen = None, brush = None, text = None, eventHandler = None):
|
||||
def AddShape(self, shape, x = None, y = None, pen = None, brush = None, text = None, eventHandler = None, shown=True):
|
||||
if isinstance(shape, ogl.CompositeShape):
|
||||
dc = wx.ClientDC(self._canvas)
|
||||
self._canvas.PrepareDC(dc)
|
||||
@@ -403,7 +485,7 @@ class CanvasView(wx.lib.docview.View):
|
||||
shape.AddText(text)
|
||||
shape.SetShadowMode(ogl.SHADOW_NONE)
|
||||
self._diagram.AddShape(shape)
|
||||
shape.Show(True)
|
||||
shape.Show(shown)
|
||||
if not eventHandler:
|
||||
eventHandler = EditorCanvasShapeEvtHandler(self)
|
||||
eventHandler.SetShape(shape)
|
||||
@@ -424,16 +506,21 @@ class CanvasView(wx.lib.docview.View):
|
||||
for line in shape.GetLines():
|
||||
shape.RemoveLine(line)
|
||||
self._diagram.RemoveShape(line)
|
||||
line.Delete()
|
||||
for obj in self._diagram.GetShapeList():
|
||||
for line in obj.GetLines():
|
||||
if self.IsShapeContained(shape, line.GetTo()) or self.IsShapeContained(shape, line.GetFrom()):
|
||||
obj.RemoveLine(line)
|
||||
self._diagram.RemoveShape(line)
|
||||
line.Delete()
|
||||
if line == shape:
|
||||
obj.RemoveLine(line)
|
||||
self._diagram.RemoveShape(line)
|
||||
line.Delete()
|
||||
|
||||
shape.RemoveFromCanvas(self._canvas)
|
||||
self._diagram.RemoveShape(shape)
|
||||
shape.Delete()
|
||||
|
||||
|
||||
def IsShapeContained(self, parent, shape):
|
||||
@@ -448,29 +535,22 @@ class CanvasView(wx.lib.docview.View):
|
||||
def UpdateShape(self, model):
|
||||
for shape in self._diagram.GetShapeList():
|
||||
if hasattr(shape, "GetModel") and shape.GetModel() == model:
|
||||
oldw, oldh = shape.GetBoundingBoxMax()
|
||||
oldx = shape.GetX()
|
||||
oldy = shape.GetY()
|
||||
|
||||
x, y, w, h = model.getEditorBounds()
|
||||
newX = x + w / 2
|
||||
newY = y + h / 2
|
||||
changed = False
|
||||
if isinstance(shape, ogl.CompositeShape):
|
||||
if shape.GetX() != newX or shape.GetY() != newY:
|
||||
dc = wx.ClientDC(self._canvas)
|
||||
self._canvas.PrepareDC(dc)
|
||||
shape.SetSize(w, h, True) # wxBug: SetSize must be before Move because links won't go to the right place
|
||||
shape.Move(dc, newX, newY) # wxBug: Move must be before SetSize because links won't go to the right place
|
||||
changed = True
|
||||
else:
|
||||
oldw, oldh = shape.GetBoundingBoxMax()
|
||||
oldx = shape.GetX()
|
||||
oldy = shape.GetY()
|
||||
if oldw != w or oldh != h or oldx != newX or oldy != newY:
|
||||
shape.SetSize(w, h)
|
||||
shape.SetX(newX)
|
||||
shape.SetY(newY)
|
||||
changed = True
|
||||
if changed:
|
||||
|
||||
if oldw != w or oldh != h or oldx != newX or oldy != newY:
|
||||
dc = wx.ClientDC(self._canvas)
|
||||
self._canvas.PrepareDC(dc)
|
||||
shape.SetSize(w, h, True) # wxBug: SetSize must be before Move because links won't go to the right place
|
||||
shape.Move(dc, newX, newY) # wxBug: Move must be after SetSize because links won't go to the right place
|
||||
shape.ResetControlPoints()
|
||||
self._canvas.Refresh()
|
||||
|
||||
break
|
||||
|
||||
|
||||
@@ -481,6 +561,10 @@ class CanvasView(wx.lib.docview.View):
|
||||
return None
|
||||
|
||||
|
||||
def GetShapeCount(self):
|
||||
return self._diagram.GetCount()
|
||||
|
||||
|
||||
def GetSelection(self):
|
||||
return filter(lambda shape: shape.Selected(), self._diagram.GetShapeList())
|
||||
|
||||
@@ -526,7 +610,10 @@ class CanvasView(wx.lib.docview.View):
|
||||
|
||||
|
||||
def ScrollVisible(self, shape):
|
||||
xUnit, yUnit = shape._canvas.GetScrollPixelsPerUnit()
|
||||
if not shape:
|
||||
return
|
||||
|
||||
xUnit, yUnit = self._canvas.GetScrollPixelsPerUnit()
|
||||
scrollX, scrollY = self._canvas.GetViewStart() # in scroll units
|
||||
scrollW, scrollH = self._canvas.GetSize() # in pixels
|
||||
w, h = shape.GetBoundingBoxMax() # in pixels
|
||||
@@ -564,7 +651,10 @@ class CanvasView(wx.lib.docview.View):
|
||||
|
||||
# erase old selection if it still exists
|
||||
if self._propShape and self._propShape in self._diagram.GetShapeList():
|
||||
self._propShape.SetBrush(self._brush)
|
||||
if hasattr(self._propShape, "DEFAULT_BRUSH"):
|
||||
self._propShape.SetBrush(self._propShape.DEFAULT_BRUSH)
|
||||
else:
|
||||
self._propShape.SetBrush(self._brush)
|
||||
if (self._propShape._textColourName in ["BLACK", "WHITE"]): # Would use GetTextColour() but it is broken
|
||||
self._propShape.SetTextColour("BLACK", 0)
|
||||
self._propShape.Draw(dc)
|
||||
@@ -667,9 +757,10 @@ class EditorCanvasShapeEvtHandler(ogl.ShapeEvtHandler):
|
||||
if shape:
|
||||
model = shape.GetModel()
|
||||
|
||||
self._view.SetSelection(model, keys == self.SHIFT_KEY or keys == self.CONTROL_KEY)
|
||||
self._view.SetPropertyShape(shape)
|
||||
self._view.SetPropertyModel(model)
|
||||
if model:
|
||||
self._view.SetSelection(model, keys == self.SHIFT_KEY or keys == self.CONTROL_KEY)
|
||||
self._view.SetPropertyShape(shape)
|
||||
self._view.SetPropertyModel(model)
|
||||
|
||||
|
||||
def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
|
||||
@@ -686,7 +777,7 @@ class EditorCanvasShapeEvtHandler(ogl.ShapeEvtHandler):
|
||||
|
||||
def OnMovePre(self, dc, x, y, oldX, oldY, display):
|
||||
""" Prevent objects from being dragged outside of viewable area """
|
||||
if (x > self._view._maxWidth) or (y > self._view._maxHeight):
|
||||
if (x < 0) or (y < 0) or (x > self._view._maxWidth) or (y > self._view._maxHeight):
|
||||
return False
|
||||
|
||||
return ogl.ShapeEvtHandler.OnMovePre(self, dc, x, y, oldX, oldY, display)
|
||||
|
||||
@@ -21,6 +21,7 @@ import string
|
||||
import sys
|
||||
import DebuggerService
|
||||
import MarkerService
|
||||
from UICommon import CaseInsensitiveCompare
|
||||
_ = wx.GetTranslation
|
||||
if wx.Platform == '__WXMSW__':
|
||||
_WINDOWS = True
|
||||
@@ -354,18 +355,6 @@ class CodeView(STCTextEditor.TextView):
|
||||
return ['Put', 'Editor Specific', 'Keywords', 'Here']
|
||||
|
||||
|
||||
def CaseInsensitiveCompare(self, s1, s2):
|
||||
""" GetAutoCompleteKeywordList() method used to show keywords in case insensitive order """
|
||||
s1L = s1.lower()
|
||||
s2L = s2.lower()
|
||||
if s1L == s2L:
|
||||
return 0
|
||||
elif s1L < s2L:
|
||||
return -1
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
def GetAutoCompleteKeywordList(self, context, hint):
|
||||
""" Replace this method with Editor specific keywords """
|
||||
kw = self.GetAutoCompleteDefaultKeywords()
|
||||
@@ -380,7 +369,7 @@ class CodeView(STCTextEditor.TextView):
|
||||
else:
|
||||
replaceLen = 0
|
||||
|
||||
kw.sort(self.CaseInsensitiveCompare)
|
||||
kw.sort(CaseInsensitiveCompare)
|
||||
return " ".join(kw), replaceLen
|
||||
|
||||
|
||||
@@ -410,6 +399,7 @@ class CodeView(STCTextEditor.TextView):
|
||||
|
||||
def OnSetIndentWidth(self):
|
||||
dialog = wx.TextEntryDialog(self._GetParentFrame(), _("Enter new indent width (2-10):"), _("Set Indent Width"), "%i" % self.GetCtrl().GetIndent())
|
||||
dialog.CenterOnParent()
|
||||
if dialog.ShowModal() == wx.ID_OK:
|
||||
try:
|
||||
indent = int(dialog.GetValue())
|
||||
@@ -480,7 +470,7 @@ class CodeView(STCTextEditor.TextView):
|
||||
if hint == "ViewStuff":
|
||||
self.GetCtrl().SetViewDefaults()
|
||||
elif hint == "Font":
|
||||
font, color = self.GetFontAndColorFromConfig()
|
||||
font, color = self.GetCtrl().GetFontAndColorFromConfig()
|
||||
self.GetCtrl().SetFont(font)
|
||||
self.GetCtrl().SetFontColor(color)
|
||||
else:
|
||||
|
||||
@@ -310,6 +310,13 @@ class RunCommandUI(wx.Panel):
|
||||
self._textCtrl.SetFontColor(wx.BLACK)
|
||||
self._textCtrl.StyleClearAll()
|
||||
self._textCtrl.SetReadOnly(True)
|
||||
|
||||
def StopAndRemoveUI(self, event):
|
||||
self.StopExecution()
|
||||
self.StopExecution()
|
||||
index = self._noteBook.GetSelection()
|
||||
self._noteBook.GetPage(index).Show(False)
|
||||
self._noteBook.RemovePage(index)
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Event handling
|
||||
@@ -322,10 +329,7 @@ class RunCommandUI(wx.Panel):
|
||||
self.StopExecution()
|
||||
|
||||
elif id == self.CLOSE_TAB_ID:
|
||||
self.StopExecution()
|
||||
index = self._noteBook.GetSelection()
|
||||
self._noteBook.GetPage(index).Show(False)
|
||||
self._noteBook.RemovePage(index)
|
||||
self.StopAndRemoveUI(event)
|
||||
|
||||
def OnDoubleClick(self, event):
|
||||
# Looking for a stack trace line.
|
||||
@@ -368,7 +372,7 @@ class RunCommandUI(wx.Panel):
|
||||
# FACTOR THIS INTO DocManager
|
||||
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
|
||||
for openDoc in openDocs:
|
||||
if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)):
|
||||
if(isinstance(openDoc, CodeEditor.CodeDocument)):
|
||||
openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
|
||||
|
||||
foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM)
|
||||
@@ -419,8 +423,9 @@ class DebugCommandUI(wx.Panel):
|
||||
def ReturnPortToPool(port):
|
||||
config = wx.ConfigBase_Get()
|
||||
startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
|
||||
if port in range(startingPort, startingPort + PORT_COUNT):
|
||||
DebugCommandUI.debuggerPortList.append(port)
|
||||
val = int(startingPort) + int(PORT_COUNT)
|
||||
if int(port) >= startingPort and (int(port) <= val):
|
||||
DebugCommandUI.debuggerPortList.append(int(port))
|
||||
|
||||
ReturnPortToPool = staticmethod(ReturnPortToPool)
|
||||
|
||||
@@ -588,7 +593,7 @@ class DebugCommandUI(wx.Panel):
|
||||
self._tb.EnableTool(self.ADD_WATCH_ID, False)
|
||||
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
|
||||
for openDoc in openDocs:
|
||||
if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)):
|
||||
if(isinstance(openDoc, CodeEditor.CodeDocument)):
|
||||
openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
|
||||
if self.framesTab:
|
||||
self.framesTab.ClearWhileRunning()
|
||||
@@ -662,7 +667,7 @@ class DebugCommandUI(wx.Panel):
|
||||
def DeleteCurrentLineMarkers(self):
|
||||
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
|
||||
for openDoc in openDocs:
|
||||
if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)):
|
||||
if(isinstance(openDoc, CodeEditor.CodeDocument)):
|
||||
openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
|
||||
|
||||
def LoadFramesListXML(self, framesXML):
|
||||
@@ -848,7 +853,7 @@ class WatchDialog(wx.Dialog):
|
||||
self.label_4 = wx.StaticText(self, -1, ",frame.f_globals, frame.f_locals)")
|
||||
self.radio_box_1 = wx.RadioBox(self, -1, "Watch Information", choices=[WatchDialog.WATCH_ALL_FRAMES, WatchDialog.WATCH_THIS_FRAME, WatchDialog.WATCH_ONCE], majorDimension=0, style=wx.RA_SPECIFY_ROWS)
|
||||
|
||||
self._okButton = wx.Button(self, wx.ID_OK, "OK", size=(75,-1))
|
||||
self._okButton = wx.Button(self, wx.ID_OK, "OK")
|
||||
self._okButton.SetDefault()
|
||||
self._okButton.SetHelpText(_("The OK button completes the dialog"))
|
||||
def OnOkClick(event):
|
||||
@@ -861,7 +866,7 @@ class WatchDialog(wx.Dialog):
|
||||
self.EndModal(wx.ID_OK)
|
||||
self.Bind(wx.EVT_BUTTON, OnOkClick, self._okButton)
|
||||
|
||||
self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel"), size=(75,-1))
|
||||
self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
|
||||
self._cancelButton.SetHelpText(_("The Cancel button cancels the dialog."))
|
||||
|
||||
self.__set_properties()
|
||||
@@ -900,7 +905,6 @@ class WatchDialog(wx.Dialog):
|
||||
box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
|
||||
box.Add(self._cancelButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
|
||||
sizer_1.Add(box, 1, wx.EXPAND, 0)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer_1)
|
||||
self.Layout()
|
||||
|
||||
@@ -979,30 +983,31 @@ class FramesUI(wx.SplitterWindow):
|
||||
#sizer.Fit(panel)
|
||||
|
||||
return panel
|
||||
|
||||
def ReplaceLastLine(self, command):
|
||||
line = self._interCtrl.GetLineCount() - 1
|
||||
self._interCtrl.GotoLine(line)
|
||||
start = self._interCtrl.GetCurrentPos()
|
||||
self._interCtrl.SetTargetStart(start)
|
||||
end = self._interCtrl.GetLineEndPosition(line)
|
||||
self._interCtrl.SetTargetEnd(end)
|
||||
self._interCtrl.ReplaceTarget(">>> " + command)
|
||||
self._interCtrl.GotoLine(line)
|
||||
self._interCtrl.SetSelectionStart(self._interCtrl.GetLineEndPosition(line))
|
||||
|
||||
def ExecuteCommand(self, command):
|
||||
if not len(self.command_list) or not command == self.command_list[len(self.command_list) -1]:
|
||||
self.command_list.append(command)
|
||||
self.command_index = len(self.command_list) - 1
|
||||
retval = self._ui._callback._debuggerServer.execute_in_frame(self._framesChoiceCtrl.GetStringSelection(), command)
|
||||
self._interCtrl.AddText("\n" + str(retval))
|
||||
self._interCtrl.ScrollToLine(self._interCtrl.GetLineCount())
|
||||
# Refresh the tree view in case this command resulted in changes there. TODO: Need to reopen tree items.
|
||||
self.PopulateTreeFromFrameMessage(self._framesChoiceCtrl.GetStringSelection())
|
||||
|
||||
def MakeInspectConsoleTab(self, parent, id):
|
||||
self.command_list = []
|
||||
self.command_index = 0
|
||||
def ExecuteCommand(command):
|
||||
if not len(self.command_list) or not command == self.command_list[len(self.command_list) -1]:
|
||||
self.command_list.append(command)
|
||||
self.command_index = len(self.command_list) - 1
|
||||
retval = self._ui._callback._debuggerServer.execute_in_frame(self._framesChoiceCtrl.GetStringSelection(), command)
|
||||
self._interCtrl.AddText("\n" + str(retval))
|
||||
self._interCtrl.ScrollToLine(self._interCtrl.GetLineCount())
|
||||
# Refresh the tree view in case this command resulted in changes there. TODO: Need to reopen tree items.
|
||||
self.PopulateTreeFromFrameMessage(self._framesChoiceCtrl.GetStringSelection())
|
||||
|
||||
def ReplaceLastLine(command):
|
||||
line = self._interCtrl.GetLineCount() - 1
|
||||
self._interCtrl.GotoLine(line)
|
||||
start = self._interCtrl.GetCurrentPos()
|
||||
self._interCtrl.SetTargetStart(start)
|
||||
end = self._interCtrl.GetLineEndPosition(line)
|
||||
self._interCtrl.SetTargetEnd(end)
|
||||
self._interCtrl.ReplaceTarget(">>> " + command)
|
||||
self._interCtrl.GotoLine(line)
|
||||
self._interCtrl.SetSelectionStart(self._interCtrl.GetLineEndPosition(line))
|
||||
|
||||
def OnKeyPressed(event):
|
||||
key = event.KeyCode()
|
||||
@@ -1011,13 +1016,13 @@ class FramesUI(wx.SplitterWindow):
|
||||
return
|
||||
elif key == wx.WXK_RETURN:
|
||||
command = self._interCtrl.GetLine(self._interCtrl.GetCurrentLine())[4:]
|
||||
ExecuteCommand(command)
|
||||
self.ExecuteCommand(command)
|
||||
self._interCtrl.AddText("\n>>> ")
|
||||
return
|
||||
elif key == wx.WXK_UP:
|
||||
if not len(self.command_list):
|
||||
return
|
||||
ReplaceLastLine(self.command_list[self.command_index])
|
||||
self.ReplaceLastLine(self.command_list[self.command_index])
|
||||
if self.command_index == 0:
|
||||
self.command_index = len(self.command_list) - 1
|
||||
else:
|
||||
@@ -1030,7 +1035,7 @@ class FramesUI(wx.SplitterWindow):
|
||||
self.command_index = self.command_index + 1
|
||||
else:
|
||||
self.command_index = 0
|
||||
ReplaceLastLine(self.command_list[self.command_index])
|
||||
self.ReplaceLastLine(self.command_list[self.command_index])
|
||||
return
|
||||
event.Skip()
|
||||
|
||||
@@ -1081,6 +1086,12 @@ class FramesUI(wx.SplitterWindow):
|
||||
self.Bind(wx.EVT_MENU, self.OnView, id=self.viewID)
|
||||
item = wx.MenuItem(menu, self.viewID, "View in Dialog")
|
||||
menu.AppendItem(item)
|
||||
if not hasattr(self, "toInteractID"):
|
||||
self.toInteractID = wx.NewId()
|
||||
self.Bind(wx.EVT_MENU, self.OnSendToInteract, id=self.toInteractID)
|
||||
item = wx.MenuItem(menu, self.toInteractID, "Send to Interact")
|
||||
menu.AppendItem(item)
|
||||
|
||||
offset = wx.Point(x=0, y=20)
|
||||
menuSpot = event.GetPoint() + offset
|
||||
self._treeCtrl.PopupMenu(menu, menuSpot)
|
||||
@@ -1105,13 +1116,33 @@ class FramesUI(wx.SplitterWindow):
|
||||
value = self._treeCtrl.GetItemText(self._introspectItem,1)
|
||||
dlg = wx.lib.dialogs.ScrolledMessageDialog(self, value, title, style=wx.DD_DEFAULT_STYLE | wx.RESIZE_BORDER)
|
||||
dlg.Show()
|
||||
|
||||
|
||||
def OnSendToInteract(self, event):
|
||||
value = ""
|
||||
prevItem = ""
|
||||
for item in self._parentChain:
|
||||
|
||||
if item.find(prevItem + '[') != -1:
|
||||
value += item[item.find('['):]
|
||||
continue
|
||||
if value != "":
|
||||
value = value + '.'
|
||||
if item == 'globals':
|
||||
item = 'globals()'
|
||||
if item != 'locals':
|
||||
value += item
|
||||
prevItem = item
|
||||
print value
|
||||
self.ReplaceLastLine(value)
|
||||
self.ExecuteCommand(value)
|
||||
|
||||
def OnWatch(self, event):
|
||||
try:
|
||||
if hasattr(self, '_parentChain'):
|
||||
wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", self._parentChain)
|
||||
else:
|
||||
wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", None)
|
||||
wd.CenterOnParent()
|
||||
if wd.ShowModal() == wx.ID_OK:
|
||||
name, text, send_frame, run_once = wd.GetSettings()
|
||||
if send_frame:
|
||||
@@ -1125,6 +1156,7 @@ class FramesUI(wx.SplitterWindow):
|
||||
nodeList = domDoc.getElementsByTagName('watch')
|
||||
if len(nodeList) == 1:
|
||||
watchValue = nodeList.item(0).getAttribute("message")
|
||||
wd.Destroy()
|
||||
except:
|
||||
tp, val, tb = sys.exc_info()
|
||||
traceback.print_exception(tp, val, tb)
|
||||
@@ -1147,6 +1179,8 @@ class FramesUI(wx.SplitterWindow):
|
||||
tree = self._treeCtrl
|
||||
parent = tree.GetItemParent(self._introspectItem)
|
||||
treeNode = self.AppendSubTreeFromNode(thingToWalk, thingToWalk.getAttribute('name'), parent, insertBefore=self._introspectItem)
|
||||
if thingToWalk.getAttribute('name').find('[') == -1:
|
||||
self._treeCtrl.SortChildren(treeNode)
|
||||
self._treeCtrl.Expand(treeNode)
|
||||
tree.Delete(self._introspectItem)
|
||||
except:
|
||||
@@ -1297,7 +1331,8 @@ class FramesUI(wx.SplitterWindow):
|
||||
if intro == "True":
|
||||
tree.SetItemHasChildren(n, True)
|
||||
tree.SetPyData(n, "Introspect")
|
||||
|
||||
if name.find('[') == -1:
|
||||
self._treeCtrl.SortChildren(treeNode)
|
||||
return treeNode
|
||||
|
||||
def StripOuterSingleQuotes(self, string):
|
||||
@@ -1613,7 +1648,7 @@ class DebuggerService(Service.Service):
|
||||
RUN_ID = wx.NewId()
|
||||
DEBUG_ID = wx.NewId()
|
||||
DEBUG_WEBSERVER_ID = wx.NewId()
|
||||
|
||||
RUN_WEBSERVER_ID = wx.NewId()
|
||||
|
||||
def ComparePaths(first, second):
|
||||
one = DebuggerService.ExpandPath(first)
|
||||
@@ -1695,6 +1730,9 @@ class DebuggerService(Service.Service):
|
||||
debuggerMenu.Append(DebuggerService.DEBUG_WEBSERVER_ID, _("Debug Internal Web Server"), _("Debugs the internal webservier"))
|
||||
wx.EVT_MENU(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessEvent)
|
||||
wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessUpdateUIEvent)
|
||||
debuggerMenu.Append(DebuggerService.RUN_WEBSERVER_ID, _("Restart Internal Web Server"), _("Restarts the internal webservier"))
|
||||
wx.EVT_MENU(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessEvent)
|
||||
wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessUpdateUIEvent)
|
||||
|
||||
debuggerMenu.AppendSeparator()
|
||||
|
||||
@@ -1709,6 +1747,11 @@ class DebuggerService(Service.Service):
|
||||
|
||||
viewMenuIndex = menuBar.FindMenu(_("&Project"))
|
||||
menuBar.Insert(viewMenuIndex + 1, debuggerMenu, _("&Run"))
|
||||
|
||||
toolBar.AddSeparator()
|
||||
toolBar.AddTool(DebuggerService.RUN_ID, getRunningManBitmap(), shortHelpString = _("Run"), longHelpString = _("Run"))
|
||||
toolBar.AddTool(DebuggerService.DEBUG_ID, getDebuggingManBitmap(), shortHelpString = _("Debug"), longHelpString = _("Debug"))
|
||||
toolBar.Realize()
|
||||
|
||||
return True
|
||||
|
||||
@@ -1742,6 +1785,9 @@ class DebuggerService(Service.Service):
|
||||
elif an_id == DebuggerService.DEBUG_WEBSERVER_ID:
|
||||
self.OnDebugWebServer(event)
|
||||
return True
|
||||
elif an_id == DebuggerService.RUN_WEBSERVER_ID:
|
||||
self.OnRunWebServer(event)
|
||||
return True
|
||||
return False
|
||||
|
||||
def ProcessUpdateUIEvent(self, event):
|
||||
@@ -1778,13 +1824,13 @@ class DebuggerService(Service.Service):
|
||||
return
|
||||
self.ShowWindow(True)
|
||||
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
|
||||
project = projectService.GetView().GetDocument()
|
||||
try:
|
||||
dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Debug Python File', projectService, None, pythonOnly=True, okButtonName="Debug", debugging=True)
|
||||
except:
|
||||
return
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings()
|
||||
projectPath, fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings()
|
||||
dlg.Destroy()
|
||||
else:
|
||||
dlg.Destroy()
|
||||
@@ -1822,7 +1868,13 @@ class DebuggerService(Service.Service):
|
||||
page.Execute(args, startIn=os.getcwd(), environment=os.environ)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def OnRunWebServer(self, event):
|
||||
if not Executor.GetPythonExecutablePath():
|
||||
return
|
||||
import WebServerService
|
||||
wsService = wx.GetApp().GetService(WebServerService.WebServerService)
|
||||
wsService.ShutDownAndRestart()
|
||||
|
||||
def HasAnyFiles(self):
|
||||
docs = wx.GetApp().GetDocumentManager().GetDocuments()
|
||||
@@ -1849,10 +1901,12 @@ class DebuggerService(Service.Service):
|
||||
_("Debug"),
|
||||
wx.YES_NO|wx.ICON_QUESTION
|
||||
)
|
||||
yesNoMsg.CenterOnParent()
|
||||
if yesNoMsg.ShowModal() == wx.ID_YES:
|
||||
docs = wx.GetApp().GetDocumentManager().GetDocuments()
|
||||
for doc in docs:
|
||||
doc.Save()
|
||||
yesNoMsg.Destroy()
|
||||
|
||||
def OnExit(self):
|
||||
DebugCommandUI.ShutdownAllDebuggers()
|
||||
@@ -1865,15 +1919,13 @@ class DebuggerService(Service.Service):
|
||||
if not Executor.GetPythonExecutablePath():
|
||||
return
|
||||
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
|
||||
project = projectService.GetView().GetDocument()
|
||||
try:
|
||||
dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Run', projectService, None)
|
||||
except:
|
||||
return
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings()
|
||||
|
||||
|
||||
projectPath, fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings()
|
||||
dlg.Destroy()
|
||||
else:
|
||||
dlg.Destroy()
|
||||
@@ -1881,7 +1933,12 @@ class DebuggerService(Service.Service):
|
||||
self.PromptToSaveFiles()
|
||||
# This will need to change when we can run more than .py and .bpel files.
|
||||
if not isPython:
|
||||
projectService.RunProcessModel(fileToRun)
|
||||
projects = projectService.FindProjectByFile(projectPath)
|
||||
if not projects:
|
||||
return
|
||||
project = projects[0]
|
||||
deployFilePath = project.GenerateDeployment()
|
||||
projectService.RunProcessModel(fileToRun, project.GetAppInfo().language, deployFilePath)
|
||||
return
|
||||
|
||||
self.ShowWindow(True)
|
||||
@@ -1901,10 +1958,16 @@ class DebuggerService(Service.Service):
|
||||
fileName = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
|
||||
if line < 0:
|
||||
line = view.GetCtrl().GetCurrentLine()
|
||||
else:
|
||||
view = None
|
||||
if self.BreakpointSet(fileName, line + 1):
|
||||
self.ClearBreak(fileName, line + 1)
|
||||
if view:
|
||||
view.GetCtrl().Refresh()
|
||||
else:
|
||||
self.SetBreak(fileName, line + 1)
|
||||
if view:
|
||||
view.GetCtrl().Refresh()
|
||||
# Now refresh all the markers icons in all the open views.
|
||||
self.ClearAllBreakpointMarkers()
|
||||
self.SetAllBreakpointMarkers()
|
||||
@@ -1939,6 +2002,10 @@ class DebuggerService(Service.Service):
|
||||
else:
|
||||
return self._masterBPDict[expandedName]
|
||||
|
||||
def SetBreakpointList(self, fileName, bplist):
|
||||
expandedName = DebuggerService.ExpandPath(fileName)
|
||||
self._masterBPDict[expandedName] = bplist
|
||||
|
||||
def BreakpointSet(self, fileName, line):
|
||||
expandedName = DebuggerService.ExpandPath(fileName)
|
||||
if not self._masterBPDict.has_key(expandedName):
|
||||
@@ -1977,16 +2044,20 @@ class DebuggerService(Service.Service):
|
||||
def ClearAllBreakpointMarkers(self):
|
||||
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
|
||||
for openDoc in openDocs:
|
||||
if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)):
|
||||
if isinstance(openDoc, CodeEditor.CodeDocument):
|
||||
openDoc.GetFirstView().MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
|
||||
|
||||
|
||||
def UpdateBreakpointsFromMarkers(self, view, fileName):
|
||||
newbpLines = view.GetMarkerLines(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
|
||||
self.SetBreakpointList(fileName, newbpLines)
|
||||
|
||||
def GetMasterBreakpointDict(self):
|
||||
return self._masterBPDict
|
||||
|
||||
def SetAllBreakpointMarkers(self):
|
||||
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
|
||||
for openDoc in openDocs:
|
||||
if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)):
|
||||
if(isinstance(openDoc, CodeEditor.CodeDocument)):
|
||||
self.SetCurrentBreakpointMarkers(openDoc.GetFirstView())
|
||||
|
||||
def SetCurrentBreakpointMarkers(self, view):
|
||||
@@ -2052,6 +2123,11 @@ class DebuggerOptionsPanel(wx.Panel):
|
||||
config.Write("DebuggerHostName", self._LocalHostTextCtrl.GetValue())
|
||||
if self._PortNumberTextCtrl.IsInBounds():
|
||||
config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue())
|
||||
|
||||
|
||||
def GetIcon(self):
|
||||
return getContinueIcon()
|
||||
|
||||
|
||||
class CommandPropertiesDialog(wx.Dialog):
|
||||
|
||||
@@ -2070,10 +2146,8 @@ class CommandPropertiesDialog(wx.Dialog):
|
||||
if not self._projectNameList:
|
||||
wx.MessageBox(_("To run or debug you must have an open runnable file or project containing runnable files. Use File->Open to open the file you wish to run or debug."), _("Nothing to Run"))
|
||||
raise BadBadBad
|
||||
if _WINDOWS:
|
||||
wx.Dialog.__init__(self, parent, -1, title)
|
||||
else:
|
||||
wx.Dialog.__init__(self, parent, -1, title, size=(390,270))
|
||||
|
||||
wx.Dialog.__init__(self, parent, -1, title)
|
||||
|
||||
projStaticText = wx.StaticText(self, -1, _("Project:"))
|
||||
fileStaticText = wx.StaticText(self, -1, _("File:"))
|
||||
@@ -2082,43 +2156,43 @@ class CommandPropertiesDialog(wx.Dialog):
|
||||
pythonPathStaticText = wx.StaticText(self, -1, _("PYTHONPATH:"))
|
||||
postpendStaticText = _("Postpend win32api path")
|
||||
cpPanelBorderSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self._projList = wx.Choice(self, -1, (200,-1), choices=self._projectNameList)
|
||||
self._projList = wx.Choice(self, -1, choices=self._projectNameList)
|
||||
self.Bind(wx.EVT_CHOICE, self.EvtListBox, self._projList)
|
||||
HALF_SPACE = 5
|
||||
flexGridSizer = wx.FlexGridSizer(cols = 3, vgap = 10, hgap = 10)
|
||||
GAP = HALF_SPACE
|
||||
if wx.Platform == "__WXMAC__":
|
||||
GAP = 10
|
||||
flexGridSizer = wx.GridBagSizer(GAP, GAP)
|
||||
|
||||
flexGridSizer.Add(projStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
flexGridSizer.Add(self._projList, 1, flag=wx.EXPAND)
|
||||
flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
|
||||
flexGridSizer.Add(projStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
flexGridSizer.Add(self._projList, (0,1), (1,2), flag=wx.EXPAND)
|
||||
|
||||
flexGridSizer.Add(fileStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
self._fileList = wx.Choice(self, -1, (200,-1))
|
||||
flexGridSizer.Add(fileStaticText, (1,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
self._fileList = wx.Choice(self, -1)
|
||||
self.Bind(wx.EVT_CHOICE, self.OnFileSelected, self._fileList)
|
||||
flexGridSizer.Add(self._fileList, 1, flag=wx.EXPAND)
|
||||
flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
|
||||
flexGridSizer.Add(self._fileList, (1,1), (1,2), flag=wx.EXPAND)
|
||||
|
||||
config = wx.ConfigBase_Get()
|
||||
self._lastArguments = config.Read("LastRunArguments")
|
||||
self._argsEntry = wx.TextCtrl(self, -1, str(self._lastArguments))
|
||||
self._argsEntry.SetToolTipString(str(self._lastArguments))
|
||||
|
||||
flexGridSizer.Add(argsStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
flexGridSizer.Add(self._argsEntry, 1, flag=wx.EXPAND)
|
||||
flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
|
||||
flexGridSizer.Add(argsStaticText, (2,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
flexGridSizer.Add(self._argsEntry, (2,1), (1,2), flag=wx.EXPAND)
|
||||
|
||||
flexGridSizer.Add(startInStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
flexGridSizer.Add(startInStaticText, (3,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
self._lastStartIn = config.Read("LastRunStartIn")
|
||||
if not self._lastStartIn:
|
||||
self._lastStartIn = str(os.getcwd())
|
||||
self._startEntry = wx.TextCtrl(self, -1, self._lastStartIn)
|
||||
self._startEntry.SetToolTipString(self._lastStartIn)
|
||||
|
||||
flexGridSizer.Add(self._startEntry, 1, wx.EXPAND)
|
||||
flexGridSizer.Add(self._startEntry, (3,1), flag=wx.EXPAND)
|
||||
self._findDir = wx.Button(self, -1, _("Browse..."))
|
||||
self.Bind(wx.EVT_BUTTON, self.OnFindDirClick, self._findDir)
|
||||
flexGridSizer.Add(self._findDir, 0, wx.RIGHT, 10)
|
||||
flexGridSizer.Add(self._findDir, (3,2))
|
||||
|
||||
flexGridSizer.Add(pythonPathStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
flexGridSizer.Add(pythonPathStaticText, (4,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
if os.environ.has_key('PYTHONPATH'):
|
||||
startval = os.environ['PYTHONPATH']
|
||||
else:
|
||||
@@ -2126,34 +2200,29 @@ class CommandPropertiesDialog(wx.Dialog):
|
||||
self._lastPythonPath = config.Read("LastPythonPath", startval)
|
||||
self._pythonPathEntry = wx.TextCtrl(self, -1, self._lastPythonPath)
|
||||
self._pythonPathEntry.SetToolTipString(self._lastPythonPath)
|
||||
flexGridSizer.Add(self._pythonPathEntry, 1, wx.EXPAND)
|
||||
flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
|
||||
flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
|
||||
flexGridSizer.Add(self._pythonPathEntry, (4,1), (1,2), flag=wx.EXPAND)
|
||||
|
||||
if debugging and _WINDOWS:
|
||||
self._postpendCheckBox = wx.CheckBox(self, -1, postpendStaticText)
|
||||
checked = bool(config.ReadInt("PythonPathPostpend", 1))
|
||||
self._postpendCheckBox.SetValue(checked)
|
||||
flexGridSizer.Add(self._postpendCheckBox, 1, wx.EXPAND)
|
||||
flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
|
||||
cpPanelBorderSizer.Add(flexGridSizer, 0, wx.ALL, 10)
|
||||
flexGridSizer.Add(self._postpendCheckBox, (5,1), flag=wx.EXPAND)
|
||||
cpPanelBorderSizer.Add(flexGridSizer, 0, flag=wx.ALL, border=10)
|
||||
|
||||
box = wx.BoxSizer(wx.HORIZONTAL)
|
||||
box = wx.StdDialogButtonSizer()
|
||||
self._okButton = wx.Button(self, wx.ID_OK, okButtonName)
|
||||
self._okButton.SetDefault()
|
||||
self._okButton.SetHelpText(_("The ") + okButtonName + _(" button completes the dialog"))
|
||||
box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
|
||||
box.AddButton(self._okButton)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnOKClick, self._okButton)
|
||||
btn = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
|
||||
btn.SetHelpText(_("The Cancel button cancels the dialog."))
|
||||
box.Add(btn, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
|
||||
cpPanelBorderSizer.Add(box, 0, wx.ALIGN_RIGHT|wx.BOTTOM, 5)
|
||||
box.AddButton(btn)
|
||||
box.Realize()
|
||||
cpPanelBorderSizer.Add(box, 0, flag=wx.ALIGN_RIGHT|wx.ALL, border=5)
|
||||
|
||||
self.SetSizer(cpPanelBorderSizer)
|
||||
if _WINDOWS:
|
||||
self.GetSizer().Fit(self)
|
||||
|
||||
self.Layout()
|
||||
|
||||
|
||||
# Set up selections based on last values used.
|
||||
self._fileNameList = None
|
||||
self._selectedFileIndex = 0
|
||||
@@ -2168,6 +2237,9 @@ class CommandPropertiesDialog(wx.Dialog):
|
||||
self._selectedProjectIndex = selectedIndex
|
||||
self._selectedProjectDocument = self._projectDocumentList[selectedIndex]
|
||||
self.PopulateFileList(self._selectedProjectDocument, lastFile)
|
||||
|
||||
cpPanelBorderSizer.Fit(self)
|
||||
|
||||
|
||||
def OnOKClick(self, event):
|
||||
startIn = self._startEntry.GetValue()
|
||||
@@ -2193,6 +2265,7 @@ class CommandPropertiesDialog(wx.Dialog):
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
||||
def GetSettings(self):
|
||||
projectPath = self._selectedProjectDocument.GetFilename()
|
||||
filename = self._fileNameList[self._selectedFileIndex]
|
||||
args = self._argsEntry.GetValue()
|
||||
startIn = self._startEntry.GetValue()
|
||||
@@ -2207,7 +2280,7 @@ class CommandPropertiesDialog(wx.Dialog):
|
||||
else:
|
||||
env['PYTHONPATH'] = self._pythonPathEntry.GetValue()
|
||||
|
||||
return filename, args, startIn, isPython, env
|
||||
return projectPath, filename, args, startIn, isPython, env
|
||||
|
||||
def OnFileSelected(self, event):
|
||||
self._selectedFileIndex = self._fileList.GetSelection()
|
||||
@@ -2229,16 +2302,17 @@ class CommandPropertiesDialog(wx.Dialog):
|
||||
self._argsEntry.SetValue(self._lastArguments)
|
||||
|
||||
|
||||
|
||||
def OnFindDirClick(self, event):
|
||||
dlg = wx.DirDialog(self, "Choose a starting directory:", self._startEntry.GetValue(),
|
||||
style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON)
|
||||
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
self._startEntry.SetValue(dlg.GetPath())
|
||||
|
||||
dlg.Destroy()
|
||||
|
||||
|
||||
def EvtListBox(self, event):
|
||||
if event.GetString():
|
||||
index = self._projectNameList.index(event.GetString())
|
||||
@@ -2524,3 +2598,76 @@ def getAddWatchImage():
|
||||
|
||||
def getAddWatchIcon():
|
||||
return wx.IconFromBitmap(getAddWatchBitmap())
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def getRunningManData():
|
||||
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\x86IDAT8\x8d\xa5\x93\xb1K\x02Q\x1c\xc7\xbf\xcf\x9a\x1bZl\x88\xb4\
|
||||
\x04\x83\x10\xa2\x96\xc0A\xa8\x96\x96\xf4h\xe9\xf0\x1f\xd0\xcd(Bpi\x13nH\xb2\
|
||||
%\x9d\x1a"\xb9)\xb4\x16i\x10\n\x13MA\x84\xa3&\xa1\xa1A\xa1E\xbdw\x97\xa2\xbd\
|
||||
\x06\xf1(\xef,\xac\xef\xf6x\xdf\xf7}\x9f\xdf\x97\xf7\x081M\xe0?\x9a\xfc\xcd \
|
||||
\\\xdc2\x99\xb6A[\x14\x91C\x9e\x8c\x1d\x00\x00\xd5\xa7*\x9a\x8a\xfa7\x82u\
|
||||
\xfb\x14dj\x03mQ\xc3}\xf2\xb5\x83\xc7B\x9e\x89\xf7/\xda\xba\xd1\x94\x01\x00j\
|
||||
CF\xe2t\xef\x1b>\x1f\x8c3Q\xf0\x11\xd3p\xa2yf\x1a\xbc\xcb\n\xdee\x85\xdd>\
|
||||
\x07\xb5!C\xe9\xb4\xb1\xe9=b\x03\x8fc\xc3\xcf\xbcN\xb3\x9e`@\x11\xb9\xaa`\
|
||||
\x7fg\x19\'\x97y\xd8\x96\xfa\xf8\x95\xf23d\xa5O4\xbfh\x87(\xf8\x88a\xc0 $|~\
|
||||
\x87n\xf7\x03\xaa\xf2\x8e\xc0\xee\n\x00 \x91\xab\xc3\xeb4\xc3\xed\xe1\xb4qF\
|
||||
\x96\xb8`\xb3h\xb7\xa6Jo\xa0\x9d\x1eD\xc1G\xc4!\x9f\xae\x03\x00\xa8\xd5jh4e\
|
||||
\r\xb9\xf0P\x82T,\x83\xf3\x0bl\xd8k\x18\xe0\xf6p\x84vz\xa0M\x8aB\xf2\x98\x84\
|
||||
\x03[\xb0.XP\xcafu^m\x04>\x18\xd7\x9aM\xe4\xea\xba\xc0x\xec\x8c\xa9\xca*^\
|
||||
\xa5\x1b}\xc0u*\xc9B\xd14\x12\xe8\x97%\x15\xcbF`\xdaH\xba\x80P4\r)\x13#R\xc6\
|
||||
\xf0\xdc\x8f2\x01\x80\x94\x89\xe9>\xc9(\xcd:\xb6\xd9\x1aw\xa0\x95i\xf8\x0e\
|
||||
\xc6\xd1\'\'\x86\xa2\xd5\x8d \xbe@\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getRunningManBitmap():
|
||||
return BitmapFromImage(getRunningManImage())
|
||||
|
||||
def getRunningManImage():
|
||||
stream = cStringIO.StringIO(getRunningManData())
|
||||
return ImageFromStream(stream)
|
||||
|
||||
def getRunningManIcon():
|
||||
icon = EmptyIcon()
|
||||
icon.CopyFromBitmap(getRunningManBitmap())
|
||||
return icon
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def getDebuggingManData():
|
||||
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\xafIDAT8\x8d\x8d\x93\xbfK[Q\x14\xc7?7\n:\t\xb5SA\xc1?@\xc1A\x9c,%\
|
||||
\xd0\xa9\x83\xb5\x98!(b\t\xbc\xa7q("m\x1c\n5V]D\xd4-\xf8\x83\xa7\xa2\t\xa1\
|
||||
\xa6\xed$8\x08\x92\xa1\x8b\x14A\xd0YB"\xa4\xf4\x87\x90\x97K\xa8\xcb\xed\xf0\
|
||||
\xc8m\xae\xfa\xd4\x03\x07.\xe7\x9e\xf3\xfd\x9e\x9f\x88@\x1d\xb5\xba\x94\xca\
|
||||
\xaa\xeb\xb6\xbb4\xc0\x03d&\xb1\xa7\xfc\xfe\x0c\x80L\xdaQ\xd2\xad\x90I;F\x80\
|
||||
++\xbe\xe0bve\xdf\xd7y\xfemH\xc4\x162\xaa\xbb\xa5D(\x1c\x11\xb7\x02\x88@\x9d\
|
||||
f?*4\xd1\xf6\xa2\x0f\x80\x93\xf4\x8e\xe1\xb8\xf2\xf1\xb5\x18\x9cH(\x80\xe4bT\
|
||||
\x83\xd5W\x1f\xa1pD\x8c|\xd8T\x00\xdf\xd6\xd7\xe8\x1f\xb3tp\xf1\n^\xfe\xf8\
|
||||
\xa5^u7\x00P\x1eYP\xd2\x95\x1c\xa4\xa6\x84\x18\x8do\xab*C&\xed\xa8\xafG\x7f\
|
||||
\xe9\x1f\xb3x\xdc\x08\xad\x8f \x7f\tg%\xf8Y\x82\xe3\x8de\x86\x82\xcdF9\xba\
|
||||
\x84\xc1\x89\x84*K\t\xc0\xf0\xbbq:\x9f\xfcO\x7f?\xe7\x01\x9c\xff\x86Br\x8e\
|
||||
\x83\xd4\x94\x06\xd0SH.F\xc5P\xb0\x19\xe9z \xf9KOmkN\x07\x03\x14/r\xb4?\x8b\
|
||||
\xe8\xc6\xeb\x1e\x00l\x1f\xfe\xd15\x17\xaf<\xdb\xd37\xef\xd9\x9d\xb4\xe9\x8a\
|
||||
\xadj\xbfx\xb4\x878(#\x03\x00\xe9JF{[\xf92\xeb\xb1V\x99\xbbb\xab|\x9f\xb7\
|
||||
\x8d\xa9\x9cf\x1dq\x9au\xc4\x8dM\x0c\x85#\xa2x\x91cw\xd2\xd6i\x83\trk\x13\
|
||||
\x9f\x0fL\xab\xda\xe6\xd4\xd6Y+\xf1h\x8f\xb9T~G\xd2\x11\xb4\xd4\xe7O[\xf7\
|
||||
\x1e\xd6\x9d\xc7\xe4\xb7\xbe\x86\xf8\xb1?\xf4\x9c\xff\x01\xbe\xe9\xaf\x96\
|
||||
\xf0\x7fPA\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getDebuggingManBitmap():
|
||||
return BitmapFromImage(getDebuggingManImage())
|
||||
|
||||
def getDebuggingManImage():
|
||||
stream = cStringIO.StringIO(getDebuggingManData())
|
||||
return ImageFromStream(stream)
|
||||
|
||||
def getDebuggingManIcon():
|
||||
icon = EmptyIcon()
|
||||
icon.CopyFromBitmap(getDebuggingManBitmap())
|
||||
return icon
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
import wx
|
||||
import wx.lib.pydocview
|
||||
import MessageService
|
||||
import ProjectEditor
|
||||
import os
|
||||
import os.path
|
||||
import pickle
|
||||
import activegrid.util.xmlutils as xmlutils
|
||||
|
||||
_ = wx.GetTranslation
|
||||
|
||||
@@ -38,7 +39,7 @@ EXTENSIONS_CONFIG_STRING = "Extensions"
|
||||
class Extension:
|
||||
|
||||
|
||||
def __init__(self, menuItemName):
|
||||
def __init__(self, menuItemName=None):
|
||||
self.menuItemName = menuItemName
|
||||
self.id = 0
|
||||
self.menuItemDesc = ''
|
||||
@@ -46,32 +47,51 @@ class Extension:
|
||||
self.commandPreArgs = ''
|
||||
self.commandPostArgs = ''
|
||||
self.fileExt = None
|
||||
|
||||
self.opOnSelectedFile = True
|
||||
|
||||
|
||||
class ExtensionService(wx.lib.pydocview.DocService):
|
||||
|
||||
EXTENSIONS_KEY = "/AG_Extensions"
|
||||
|
||||
def __init__(self):
|
||||
self.LoadExtensions()
|
||||
|
||||
|
||||
def __getExtensionKeyName(extensionName):
|
||||
return "%s/%s" % (ExtensionService.EXTENSIONS_KEY, extensionName)
|
||||
|
||||
|
||||
__getExtensionKeyName = staticmethod(__getExtensionKeyName)
|
||||
|
||||
|
||||
def LoadExtensions(self):
|
||||
self._extensions = []
|
||||
|
||||
extensionNames = []
|
||||
config = wx.ConfigBase_Get()
|
||||
pickledExtensions = config.Read(EXTENSIONS_CONFIG_STRING)
|
||||
if pickledExtensions:
|
||||
try:
|
||||
self._extensions = pickle.loads(pickledExtensions.encode('ascii'))
|
||||
except:
|
||||
tp, val, tb = sys.exc_info()
|
||||
traceback.print_exception(tp,val,tb)
|
||||
self._extensions = []
|
||||
else:
|
||||
self._extensions = []
|
||||
|
||||
path = config.GetPath()
|
||||
try:
|
||||
config.SetPath(ExtensionService.EXTENSIONS_KEY)
|
||||
cont, value, index = config.GetFirstEntry()
|
||||
while cont:
|
||||
extensionNames.append(value)
|
||||
cont, value, index = config.GetNextEntry(index)
|
||||
finally:
|
||||
config.SetPath(path)
|
||||
|
||||
for extensionName in extensionNames:
|
||||
extensionData = config.Read(self.__getExtensionKeyName(extensionName))
|
||||
if extensionData:
|
||||
extension = xmlutils.unmarshal(extensionData.encode('utf-8'))
|
||||
self._extensions.append(extension)
|
||||
|
||||
|
||||
def SaveExtensions(self):
|
||||
config = wx.ConfigBase_Get()
|
||||
config.Write(EXTENSIONS_CONFIG_STRING, pickle.dumps(self._extensions))
|
||||
config.DeleteGroup(ExtensionService.EXTENSIONS_KEY)
|
||||
for extension in self._extensions:
|
||||
config.Write(self.__getExtensionKeyName(extension.menuItemName), xmlutils.marshal(extension))
|
||||
|
||||
|
||||
def GetExtensions(self):
|
||||
@@ -82,6 +102,10 @@ class ExtensionService(wx.lib.pydocview.DocService):
|
||||
self._extensions = extensions
|
||||
|
||||
|
||||
def CheckSumExtensions(self):
|
||||
return xmlutils.marshal(self._extensions)
|
||||
|
||||
|
||||
def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
|
||||
toolsMenuIndex = menuBar.FindMenu(_("&Tools"))
|
||||
if toolsMenuIndex > -1:
|
||||
@@ -100,8 +124,15 @@ class ExtensionService(wx.lib.pydocview.DocService):
|
||||
wx.EVT_UPDATE_UI(frame, ext.id, frame.ProcessUpdateUIEvent)
|
||||
|
||||
if toolsMenuIndex == -1:
|
||||
formatMenuIndex = menuBar.FindMenu(_("&Format"))
|
||||
menuBar.Insert(formatMenuIndex + 1, toolsMenu, _("&Tools"))
|
||||
index = menuBar.FindMenu(_("&Run"))
|
||||
if index == -1:
|
||||
index = menuBar.FindMenu(_("&Project"))
|
||||
if index == -1:
|
||||
index = menuBar.FindMenu(_("&Format"))
|
||||
if index == -1:
|
||||
index = menuBar.FindMenu(_("&View"))
|
||||
menuBar.Insert(index + 1, toolsMenu, _("&Tools"))
|
||||
|
||||
|
||||
def ProcessEvent(self, event):
|
||||
id = event.GetId()
|
||||
@@ -126,6 +157,14 @@ class ExtensionService(wx.lib.pydocview.DocService):
|
||||
if fileExt in doc.GetDocumentTemplate().GetFileFilter():
|
||||
event.Enable(True)
|
||||
return True
|
||||
if extension.opOnSelectedFile and isinstance(doc, ProjectEditor.ProjectDocument):
|
||||
filename = doc.GetFirstView().GetSelectedFile()
|
||||
if filename:
|
||||
template = wx.GetApp().GetDocumentManager().FindTemplateForPath(filename)
|
||||
for fileExt in extension.fileExt:
|
||||
if fileExt in template.GetFileFilter():
|
||||
event.Enable(True)
|
||||
return True
|
||||
event.Enable(False)
|
||||
return False
|
||||
return False
|
||||
@@ -136,7 +175,12 @@ class ExtensionService(wx.lib.pydocview.DocService):
|
||||
doc = wx.GetApp().GetDocumentManager().GetCurrentDocument()
|
||||
if not doc:
|
||||
return
|
||||
filename = doc.GetFilename()
|
||||
if extension.opOnSelectedFile and isinstance(doc, ProjectEditor.ProjectDocument):
|
||||
filename = doc.GetFirstView().GetSelectedFile()
|
||||
if not filename:
|
||||
filename = doc.GetFilename()
|
||||
else:
|
||||
filename = doc.GetFilename()
|
||||
ext = os.path.splitext(filename)[1]
|
||||
if not '*' in extension.fileExt:
|
||||
if not ext or ext[1:] not in extension.fileExt:
|
||||
@@ -171,99 +215,107 @@ class ExtensionOptionsPanel(wx.Panel):
|
||||
def __init__(self, parent, id):
|
||||
wx.Panel.__init__(self, parent, id)
|
||||
|
||||
extOptionsPanelBorderSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
extOptionsPanelBorderSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
extOptionsPanelSizer = wx.FlexGridSizer(cols=2, hgap=SPACE, vgap=HALF_SPACE)
|
||||
extOptionsPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
extCtrlSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
extCtrlSizer.Add(wx.StaticText(self, -1, _("Extensions:")), 0)
|
||||
self._extListBox = wx.ListBox(self, -1, size=(-1,185), style=wx.LB_SINGLE)
|
||||
extCtrlSizer.Add(wx.StaticText(self, -1, _("External Tools:")), 0, wx.BOTTOM, HALF_SPACE)
|
||||
self._extListBox = wx.ListBox(self, -1, size=(-1,160), style=wx.LB_SINGLE)
|
||||
self.Bind(wx.EVT_LISTBOX, self.OnListBoxSelect, self._extListBox)
|
||||
extCtrlSizer.Add(self._extListBox, 1, wx.TOP | wx.BOTTOM | wx.EXPAND, SPACE)
|
||||
buttonSizer = wx.GridSizer(rows=1, hgap=10, vgap=5)
|
||||
extCtrlSizer.Add(self._extListBox, 1, wx.BOTTOM | wx.EXPAND, SPACE)
|
||||
buttonSizer = wx.GridSizer(cols=2, vgap=5, hgap=10)
|
||||
self._moveUpButton = wx.Button(self, -1, _("Move Up"))
|
||||
self.Bind(wx.EVT_BUTTON, self.OnMoveUp, self._moveUpButton)
|
||||
buttonSizer.Add(self._moveUpButton, 0)
|
||||
buttonSizer.Add(self._moveUpButton, 1, wx.EXPAND)
|
||||
self._moveDownButton = wx.Button(self, -1, _("Move Down"))
|
||||
self.Bind(wx.EVT_BUTTON, self.OnMoveDown, self._moveDownButton)
|
||||
buttonSizer.Add(self._moveDownButton, 0)
|
||||
extCtrlSizer.Add(buttonSizer, 0, wx.ALIGN_CENTER | wx.BOTTOM, HALF_SPACE)
|
||||
buttonSizer = wx.GridSizer(rows=1, hgap=10, vgap=5)
|
||||
self._addButton = wx.Button(self, -1, _("Add"))
|
||||
buttonSizer.Add(self._moveDownButton, 1, wx.EXPAND)
|
||||
self._addButton = wx.Button(self, wx.ID_ADD)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnAdd, self._addButton)
|
||||
buttonSizer.Add(self._addButton, 0)
|
||||
self._deleteButton = wx.Button(self, wx.ID_DELETE)
|
||||
buttonSizer.Add(self._addButton, 1, wx.EXPAND)
|
||||
self._deleteButton = wx.Button(self, wx.ID_DELETE, label=_("Delete")) # get rid of accelerator for letter d in "&Delete"
|
||||
self.Bind(wx.EVT_BUTTON, self.OnDelete, self._deleteButton)
|
||||
buttonSizer.Add(self._deleteButton, 0)
|
||||
buttonSizer.Add(self._deleteButton, 1, wx.EXPAND)
|
||||
extCtrlSizer.Add(buttonSizer, 0, wx.ALIGN_CENTER)
|
||||
extOptionsPanelSizer.Add(extCtrlSizer, 0)
|
||||
extOptionsPanelSizer.Add(extCtrlSizer, 0, wx.EXPAND)
|
||||
|
||||
self._extDetailPanel = wx.Panel(self)
|
||||
staticBox = wx.StaticBox(self._extDetailPanel, label=_("Selected Extension"))
|
||||
staticBoxSizer = wx.StaticBoxSizer(staticBox)
|
||||
self._extDetailPanel.SetSizer(staticBoxSizer)
|
||||
extDetailSizer = wx.FlexGridSizer(cols=1, hgap=5, vgap=3)
|
||||
staticBoxSizer.AddSizer(extDetailSizer, 0, wx.ALL, 5)
|
||||
staticBox = wx.StaticBox(self, label=_("Selected External Tool"))
|
||||
staticBoxSizer = wx.StaticBoxSizer(staticBox, wx.VERTICAL)
|
||||
|
||||
extDetailSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=3)
|
||||
extDetailSizer.AddGrowableCol(1,1)
|
||||
|
||||
extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Name:")))
|
||||
self._menuItemNameTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
|
||||
extDetailSizer.Add(self._menuItemNameTextCtrl, 1, wx.EXPAND)
|
||||
extDetailSizer.Add(self._menuItemNameTextCtrl, 0, wx.EXPAND)
|
||||
self.Bind(wx.EVT_TEXT, self.SaveCurrentItem, self._menuItemNameTextCtrl)
|
||||
|
||||
extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Description:")))
|
||||
self._menuItemDescTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
|
||||
extDetailSizer.Add(self._menuItemDescTextCtrl, 1, wx.EXPAND)
|
||||
extDetailSizer.Add(self._menuItemDescTextCtrl, 0, wx.EXPAND)
|
||||
|
||||
extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Path:")))
|
||||
self._commandTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
|
||||
findFileButton = wx.Button(self._extDetailPanel, -1, _("Browse..."))
|
||||
def OnBrowseButton(event):
|
||||
fileDlg = wx.FileDialog(self, _("Choose an Executable:"), style=wx.OPEN | wx.HIDE_READONLY)
|
||||
fileDlg = wx.FileDialog(self, _("Choose an Executable:"), style=wx.OPEN|wx.FILE_MUST_EXIST|wx.HIDE_READONLY|wx.CHANGE_DIR)
|
||||
path = self._commandTextCtrl.GetValue()
|
||||
if path:
|
||||
fileDlg.SetPath(path)
|
||||
# fileDlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog
|
||||
if fileDlg.ShowModal() == wx.ID_OK:
|
||||
self._commandTextCtrl.SetValue(fileDlg.GetPath())
|
||||
self._commandTextCtrl.SetInsertionPointEnd()
|
||||
self._commandTextCtrl.SetToolTipString(fileDlg.GetPath())
|
||||
fileDlg.Destroy()
|
||||
wx.EVT_BUTTON(findFileButton, -1, OnBrowseButton)
|
||||
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsizer.Add(self._commandTextCtrl, 1, wx.EXPAND)
|
||||
hsizer.Add(findFileButton, 0, wx.LEFT, HALF_SPACE)
|
||||
extDetailSizer.Add(hsizer, 0)
|
||||
extDetailSizer.Add(hsizer, 0, wx.EXPAND)
|
||||
|
||||
extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Pre Arguments:")))
|
||||
extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Pre Args:")))
|
||||
self._commandPreArgsTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
|
||||
extDetailSizer.Add(self._commandPreArgsTextCtrl, 1, wx.EXPAND)
|
||||
extDetailSizer.Add(self._commandPreArgsTextCtrl, 0, wx.EXPAND)
|
||||
|
||||
extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Post Arguments:")))
|
||||
extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Post Args:")))
|
||||
self._commandPostArgsTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
|
||||
extDetailSizer.Add(self._commandPostArgsTextCtrl, 1, wx.EXPAND)
|
||||
extDetailSizer.Add(self._commandPostArgsTextCtrl, 0, wx.EXPAND)
|
||||
|
||||
extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("File Extensions (Comma Separated):")))
|
||||
extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("File Extensions:")))
|
||||
self._fileExtTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
|
||||
self._fileExtTextCtrl.SetToolTipString(_("""For example: "txt, text" or "*" for all files"""))
|
||||
extDetailSizer.Add(self._fileExtTextCtrl, 1, wx.EXPAND)
|
||||
self._fileExtTextCtrl.SetToolTipString(_("""For example: "txt, text" (comma separated) or "*" for all files"""))
|
||||
extDetailSizer.Add(self._fileExtTextCtrl, 0, wx.EXPAND)
|
||||
|
||||
extOptionsPanelSizer.Add(self._extDetailPanel, 0)
|
||||
self._selFileCtrl = wx.CheckBox(self._extDetailPanel, -1, _("Operate on Selected File"))
|
||||
extDetailSizer.Add(self._selFileCtrl)
|
||||
self._selFileCtrl.SetToolTipString(_("If focus is in the project, instead of operating on the project file, operate on the selected file."))
|
||||
|
||||
extOptionsPanelBorderSizer.Add(extOptionsPanelSizer, 0, wx.ALL | wx.EXPAND, SPACE)
|
||||
self.SetSizer(extOptionsPanelBorderSizer)
|
||||
self.Layout()
|
||||
parent.AddPage(self, _("Extensions"))
|
||||
self._extDetailPanel.SetSizer(extDetailSizer)
|
||||
staticBoxSizer.Add(self._extDetailPanel, 1, wx.ALL|wx.EXPAND, SPACE)
|
||||
|
||||
extOptionsPanelSizer.Add(staticBoxSizer, 1, wx.LEFT|wx.EXPAND, SPACE)
|
||||
|
||||
extOptionsPanelBorderSizer.Add(extOptionsPanelSizer, 1, wx.ALL|wx.EXPAND, SPACE)
|
||||
self.SetSizer(extOptionsPanelBorderSizer)
|
||||
|
||||
if self.PopulateItems():
|
||||
self._extListBox.SetSelection(0)
|
||||
self.OnListBoxSelect(None)
|
||||
self.OnListBoxSelect()
|
||||
|
||||
self.Layout()
|
||||
|
||||
parent.AddPage(self, _("External Tools"))
|
||||
|
||||
|
||||
def OnOK(self, optionsDialog):
|
||||
self.SaveCurrentItem()
|
||||
extensionsService = wx.GetApp().GetService(ExtensionService)
|
||||
oldExtensions = extensionsService.GetExtensions()
|
||||
extensionsService.SetExtensions(self._extensions)
|
||||
extensionsService.SaveExtensions()
|
||||
if oldExtensions.__repr__() != self._extensions.__repr__():
|
||||
if extensionsService.CheckSumExtensions() != self._oldExtensions: # see PopulateItems() note about self._oldExtensions
|
||||
msgTitle = wx.GetApp().GetAppName()
|
||||
if not msgTitle:
|
||||
msgTitle = _("Document Options")
|
||||
@@ -277,6 +329,7 @@ class ExtensionOptionsPanel(wx.Panel):
|
||||
extensionsService = wx.GetApp().GetService(ExtensionService)
|
||||
import copy
|
||||
self._extensions = copy.deepcopy(extensionsService.GetExtensions())
|
||||
self._oldExtensions = extensionsService.CheckSumExtensions() # wxBug: need to make a copy now since the deepcopy reorders fields, so we must compare the prestine copy with the modified copy
|
||||
for extension in self._extensions:
|
||||
self._extListBox.Append(extension.menuItemName, extension)
|
||||
self._currentItem = None
|
||||
@@ -284,9 +337,9 @@ class ExtensionOptionsPanel(wx.Panel):
|
||||
return len(self._extensions)
|
||||
|
||||
|
||||
def OnListBoxSelect(self, event):
|
||||
def OnListBoxSelect(self, event=None):
|
||||
self.SaveCurrentItem()
|
||||
if not self._extListBox.GetSelections():
|
||||
if self._extListBox.GetSelection() == wx.NOT_FOUND:
|
||||
self._currentItemIndex = -1
|
||||
self._currentItem = None
|
||||
self._deleteButton.Enable(False)
|
||||
@@ -316,43 +369,52 @@ class ExtensionOptionsPanel(wx.Panel):
|
||||
extension.fileExt = None
|
||||
else:
|
||||
extension.fileExt = fileExt.split(',')
|
||||
extension.opOnSelectedFile = self._selFileCtrl.GetValue()
|
||||
|
||||
|
||||
def LoadItem(self, extension):
|
||||
if extension:
|
||||
self._menuItemDescTextCtrl.SetValue(extension.menuItemDesc or '')
|
||||
self._commandTextCtrl.SetValue(extension.command or '')
|
||||
self._commandTextCtrl.SetToolTipString(extension.command or '')
|
||||
self._commandPreArgsTextCtrl.SetValue(extension.commandPreArgs or '')
|
||||
self._commandPostArgsTextCtrl.SetValue(extension.commandPostArgs or '')
|
||||
if extension.fileExt:
|
||||
self._fileExtTextCtrl.SetValue(extension.fileExt.__repr__()[1:-1].replace("'","")) # Make the list a string, strip the brakcet on either side
|
||||
list = ""
|
||||
for ext in extension.fileExt:
|
||||
if list:
|
||||
list = list + ", "
|
||||
list = list + ext
|
||||
self._fileExtTextCtrl.SetValue(list)
|
||||
else:
|
||||
self._fileExtTextCtrl.SetValue('')
|
||||
self._selFileCtrl.SetValue(extension.opOnSelectedFile)
|
||||
self._menuItemNameTextCtrl.SetValue(extension.menuItemName or '') # Do the name last since it triggers the write event that updates the entire item
|
||||
self._extDetailPanel.Enable()
|
||||
else:
|
||||
self._menuItemNameTextCtrl.SetValue('')
|
||||
self._menuItemDescTextCtrl.SetValue('')
|
||||
self._commandTextCtrl.SetValue('')
|
||||
self._commandTextCtrl.SetToolTipString(_("Path to executable"))
|
||||
self._commandPreArgsTextCtrl.SetValue('')
|
||||
self._commandPostArgsTextCtrl.SetValue('')
|
||||
self._fileExtTextCtrl.SetValue('')
|
||||
self._selFileCtrl.SetValue(True)
|
||||
self._extDetailPanel.Enable(False)
|
||||
|
||||
|
||||
def OnAdd(self, event):
|
||||
self.SaveCurrentItem()
|
||||
extensionNames = map(lambda extension: extension.menuItemName, self._extensions)
|
||||
name = _("Untitled")
|
||||
count = 1
|
||||
while name in extensionNames:
|
||||
while self._extListBox.FindString(name) != wx.NOT_FOUND:
|
||||
count = count + 1
|
||||
name = _("Untitled %s") % count
|
||||
name = _("Untitled%s") % count
|
||||
extension = Extension(name)
|
||||
self._extensions.append(extension)
|
||||
self._extListBox.Append(extension.menuItemName, extension)
|
||||
self._extListBox.SetSelection(self._extListBox.GetCount() - 1)
|
||||
self.OnListBoxSelect(None)
|
||||
self._extListBox.SetStringSelection(extension.menuItemName)
|
||||
self.OnListBoxSelect()
|
||||
self._menuItemNameTextCtrl.SetFocus()
|
||||
self._menuItemNameTextCtrl.SetSelection(-1, -1)
|
||||
|
||||
@@ -364,7 +426,7 @@ class ExtensionOptionsPanel(wx.Panel):
|
||||
if self._currentItemIndex > -1:
|
||||
self._extListBox.SetSelection(self._currentItemIndex)
|
||||
self._currentItem = None # Don't update it since it no longer exists
|
||||
self.OnListBoxSelect(None)
|
||||
self.OnListBoxSelect()
|
||||
|
||||
|
||||
def OnMoveUp(self, event):
|
||||
@@ -374,7 +436,7 @@ class ExtensionOptionsPanel(wx.Panel):
|
||||
self._extListBox.Insert(itemAboveString, self._currentItemIndex)
|
||||
self._extListBox.SetClientData(self._currentItemIndex, itemAboveData)
|
||||
self._currentItemIndex = self._currentItemIndex - 1
|
||||
self.OnListBoxSelect(None) # Reset buttons
|
||||
self.OnListBoxSelect() # Reset buttons
|
||||
|
||||
|
||||
def OnMoveDown(self, event):
|
||||
@@ -384,4 +446,4 @@ class ExtensionOptionsPanel(wx.Panel):
|
||||
self._extListBox.Insert(itemBelowString, self._currentItemIndex)
|
||||
self._extListBox.SetClientData(self._currentItemIndex, itemBelowData)
|
||||
self._currentItemIndex = self._currentItemIndex + 1
|
||||
self.OnListBoxSelect(None) # Reset buttons
|
||||
self.OnListBoxSelect() # Reset buttons
|
||||
|
||||
@@ -79,8 +79,7 @@ class FindInDirService(FindService.FindService):
|
||||
id = event.GetId()
|
||||
if id == FindInDirService.FINDALL_ID:
|
||||
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
|
||||
view = projectService.GetView()
|
||||
if view and view.GetDocument() and view.GetDocument().GetFiles():
|
||||
if projectService.GetFilesFromCurrentProject():
|
||||
event.Enable(True)
|
||||
else:
|
||||
event.Enable(False)
|
||||
@@ -94,7 +93,7 @@ class FindInDirService(FindService.FindService):
|
||||
def ShowFindDirDialog(self, findString=None):
|
||||
config = wx.ConfigBase_Get()
|
||||
|
||||
frame = wx.Dialog(None, -1, _("Find in Directory"), size= (320,200))
|
||||
frame = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("Find in Directory"), size= (320,200))
|
||||
borderSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
contentSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
@@ -112,11 +111,11 @@ class FindInDirService(FindService.FindService):
|
||||
dir = dirCtrl.GetValue()
|
||||
if len(dir):
|
||||
dlg.SetPath(dir)
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
dirCtrl.SetValue(dlg.GetPath())
|
||||
dirCtrl.SetToolTipString(dirCtrl.GetValue())
|
||||
dirCtrl.SetInsertionPointEnd()
|
||||
|
||||
dlg.Destroy()
|
||||
wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton)
|
||||
|
||||
@@ -128,6 +127,9 @@ class FindInDirService(FindService.FindService):
|
||||
lineSizer.Add(wx.StaticLine(frame, -1, size = (10,-1)), 0, flag=wx.EXPAND)
|
||||
contentSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM, border=HALF_SPACE)
|
||||
|
||||
if wx.Platform == "__WXMAC__":
|
||||
contentSizer.Add((-1, 10), 0, wx.EXPAND)
|
||||
|
||||
lineSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
lineSizer.Add(wx.StaticText(frame, -1, _("Find what:")), 0, wx.ALIGN_CENTER | wx.RIGHT, HALF_SPACE)
|
||||
if not findString:
|
||||
@@ -151,13 +153,17 @@ class FindInDirService(FindService.FindService):
|
||||
buttonSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
findBtn = wx.Button(frame, wx.ID_OK, _("Find"))
|
||||
findBtn.SetDefault()
|
||||
buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE)
|
||||
BTM_SPACE = HALF_SPACE
|
||||
if wx.Platform == "__WXMAC__":
|
||||
BTM_SPACE = SPACE
|
||||
buttonSizer.Add(findBtn, 0, wx.BOTTOM, BTM_SPACE)
|
||||
buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL), 0)
|
||||
borderSizer.Add(buttonSizer, 0, wx.ALL, SPACE)
|
||||
|
||||
frame.SetSizer(borderSizer)
|
||||
frame.Fit()
|
||||
|
||||
frame.CenterOnParent()
|
||||
status = frame.ShowModal()
|
||||
|
||||
passedCheck = False
|
||||
@@ -168,6 +174,7 @@ class FindInDirService(FindService.FindService):
|
||||
_("Find in Directory"),
|
||||
wx.OK | wx.ICON_EXCLAMATION
|
||||
)
|
||||
dlg.CenterOnParent()
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
@@ -178,6 +185,7 @@ class FindInDirService(FindService.FindService):
|
||||
_("Find in Directory"),
|
||||
wx.OK | wx.ICON_EXCLAMATION
|
||||
)
|
||||
dlg.CenterOnParent()
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
@@ -197,10 +205,8 @@ class FindInDirService(FindService.FindService):
|
||||
regExpr = regExprCtrl.IsChecked()
|
||||
self.SaveFindConfig(findString, wholeWord, matchCase, regExpr)
|
||||
|
||||
|
||||
frame.Destroy()
|
||||
if status == wx.ID_OK:
|
||||
frame.Destroy()
|
||||
|
||||
messageService = wx.GetApp().GetService(MessageService.MessageService)
|
||||
messageService.ShowWindow()
|
||||
|
||||
@@ -267,7 +273,6 @@ class FindInDirService(FindService.FindService):
|
||||
|
||||
return True
|
||||
else:
|
||||
frame.Destroy()
|
||||
return False
|
||||
|
||||
|
||||
@@ -285,7 +290,7 @@ class FindInDirService(FindService.FindService):
|
||||
def ShowFindAllDialog(self, findString=None):
|
||||
config = wx.ConfigBase_Get()
|
||||
|
||||
frame = wx.Dialog(None, -1, _("Find in Project"), size= (320,200))
|
||||
frame = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("Find in Project"), size= (320,200))
|
||||
borderSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
contentSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
@@ -310,13 +315,17 @@ class FindInDirService(FindService.FindService):
|
||||
buttonSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
findBtn = wx.Button(frame, wx.ID_OK, _("Find"))
|
||||
findBtn.SetDefault()
|
||||
buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE)
|
||||
BTM_SPACE = HALF_SPACE
|
||||
if wx.Platform == "__WXMAC__":
|
||||
BTM_SPACE = SPACE
|
||||
buttonSizer.Add(findBtn, 0, wx.BOTTOM, BTM_SPACE)
|
||||
buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL), 0)
|
||||
borderSizer.Add(buttonSizer, 0, wx.ALL, SPACE)
|
||||
|
||||
frame.SetSizer(borderSizer)
|
||||
frame.Fit()
|
||||
|
||||
frame.CenterOnParent()
|
||||
status = frame.ShowModal()
|
||||
|
||||
# save user choice state for this and other Find Dialog Boxes
|
||||
@@ -326,9 +335,8 @@ class FindInDirService(FindService.FindService):
|
||||
regExpr = regExprCtrl.IsChecked()
|
||||
self.SaveFindConfig(findString, wholeWord, matchCase, regExpr)
|
||||
|
||||
frame.Destroy()
|
||||
if status == wx.ID_OK:
|
||||
frame.Destroy()
|
||||
|
||||
messageService = wx.GetApp().GetService(MessageService.MessageService)
|
||||
messageService.ShowWindow()
|
||||
|
||||
@@ -412,7 +420,6 @@ class FindInDirService(FindService.FindService):
|
||||
|
||||
return True
|
||||
else:
|
||||
frame.Destroy()
|
||||
return False
|
||||
|
||||
|
||||
@@ -442,8 +449,9 @@ class FindInDirService(FindService.FindService):
|
||||
break
|
||||
|
||||
if not foundView:
|
||||
doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT)
|
||||
foundView = doc.GetFirstView()
|
||||
doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE)
|
||||
if doc:
|
||||
foundView = doc.GetFirstView()
|
||||
|
||||
if foundView:
|
||||
foundView.GetFrame().SetFocus()
|
||||
|
||||
@@ -121,6 +121,7 @@ class FindService(wx.lib.pydocview.DocService):
|
||||
self._findDialog = None
|
||||
|
||||
self._replaceDialog = FindReplaceDialog(self.GetDocumentManager().FindSuitableParent(), -1, _("Replace"), size=(320,200), findString=findString)
|
||||
self._replaceDialog.CenterOnParent()
|
||||
self._replaceDialog.Show(True)
|
||||
else:
|
||||
if self._replaceDialog != None:
|
||||
@@ -129,6 +130,7 @@ class FindService(wx.lib.pydocview.DocService):
|
||||
self._replaceDialog = None
|
||||
|
||||
self._findDialog = FindDialog(self.GetDocumentManager().FindSuitableParent(), -1, _("Find"), size=(320,200), findString=findString)
|
||||
self._findDialog.CenterOnParent()
|
||||
self._findDialog.Show(True)
|
||||
|
||||
|
||||
@@ -152,6 +154,7 @@ class FindService(wx.lib.pydocview.DocService):
|
||||
""" Display Goto Line Number dialog box """
|
||||
line = -1
|
||||
dialog = wx.TextEntryDialog(parent, _("Enter line number to go to:"), _("Go to Line"))
|
||||
dialog.CenterOnParent()
|
||||
if dialog.ShowModal() == wx.ID_OK:
|
||||
try:
|
||||
line = int(dialog.GetValue())
|
||||
@@ -356,7 +359,10 @@ class FindDialog(wx.Dialog):
|
||||
wx.EVT_BUTTON(self, FindService.FINDONE_ID, self.OnActionEvent)
|
||||
cancelBtn = wx.Button(self, wx.ID_CANCEL)
|
||||
wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnClose)
|
||||
buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE)
|
||||
BTM_SPACE = HALF_SPACE
|
||||
if wx.Platform == "__WXMAC__":
|
||||
BTM_SPACE = SPACE
|
||||
buttonSizer.Add(findBtn, 0, wx.BOTTOM, BTM_SPACE)
|
||||
buttonSizer.Add(cancelBtn, 0)
|
||||
gridSizer.Add(buttonSizer, pos=(0,2), span=(3,1))
|
||||
|
||||
@@ -455,9 +461,14 @@ class FindReplaceDialog(FindDialog):
|
||||
wx.EVT_BUTTON(self, FindService.REPLACEONE_ID, self.OnActionEvent)
|
||||
replaceAllBtn = wx.Button(self, FindService.REPLACEALL_ID, _("Replace All"))
|
||||
wx.EVT_BUTTON(self, FindService.REPLACEALL_ID, self.OnActionEvent)
|
||||
buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE)
|
||||
buttonSizer.Add(replaceBtn, 0, wx.BOTTOM, HALF_SPACE)
|
||||
buttonSizer.Add(replaceAllBtn, 0, wx.BOTTOM, HALF_SPACE)
|
||||
|
||||
BTM_SPACE = HALF_SPACE
|
||||
if wx.Platform == "__WXMAC__":
|
||||
BTM_SPACE = SPACE
|
||||
|
||||
buttonSizer.Add(findBtn, 0, wx.BOTTOM, BTM_SPACE)
|
||||
buttonSizer.Add(replaceBtn, 0, wx.BOTTOM, BTM_SPACE)
|
||||
buttonSizer.Add(replaceAllBtn, 0, wx.BOTTOM, BTM_SPACE)
|
||||
buttonSizer.Add(cancelBtn, 0)
|
||||
gridSizer.Add(buttonSizer, pos=(0,2), span=(3,1))
|
||||
|
||||
@@ -495,12 +506,24 @@ def getFindData():
|
||||
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\x81IDAT8\x8d\xa5S\xc1\x16\xc0\x10\x0ckk\xff\xff\xc7d\x87\xad^U\r\
|
||||
\x93S\xe5U$\n\xb3$:\xc1e\x17(\x19Z\xb3$\x9e\xf1DD\xe2\x15\x01x\xea\x93\xef\
|
||||
\x04\x989\xea\x1b\xf2U\xc0\xda\xb4\xeb\x11\x1f:\xd8\xb5\xff8\x93\xd4\xa9\xae\
|
||||
@/S\xaaUwJ3\x85\xc0\x81\xee\xeb.q\x17C\x81\xd5XU \x1a\x93\xc6\x18\x8d\x90\
|
||||
\xe8}\x89\x00\x9a&\x9b_k\x94\x0c\xdf\xd78\xf8\x0b\x99Y\xb4\x08c\x9e\xfe\xc6\
|
||||
\xe3\x087\xf9\xd0D\x180\xf1#\x8e\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x01\xb1IDAT8\x8d\xa5\x93=o\xd3P\x14\x86\x1f\xa7\x11\x95<\xdc\xc6\xecN+5\
|
||||
[\x86B\x99\xacLQ2Zr[\x89\xa1\xfd\x0b%\x95\x90\x00\xf1\x03\x80\x01\x98\x80\
|
||||
\x19G\xac\x0cm\xff@Y\xd9:\xd9Ck\x94\xd6\xddb\x94\x9b\x98\xc8\xd2e1C\xe5\x8b\
|
||||
\xdd\x14\x96\xbe\xdb=\x1f\xefy\xef\xf90\x8c\xda\x12wA\xbd\xfc\x18\xfa\x9fs\
|
||||
\x80\xf9|\x0e\xc0\x93\xc1\x81\x01\xf0\xe6\xf5\xab\x1c`:\x9d\x02\xf0\xf6\xdd{\
|
||||
\xa3\xc8\xa9\xddd\xec\xf5z\xb4Z\xeb\x00\x1c\x1f\x1d\xe6\x85\xdd\xf3<\x06\x83\
|
||||
\xc1\x82\xbd\xa2 \x0cCL\xd3d<\x1e\x13\xc71\xb6m\x030\x1a\x8d\x08\x82\x00\x80\
|
||||
\xb3\xb3s:\x9d\x8e\xce\xa9(h6\x9b8\x8e\x83m\xdb4\x1a\r\x82 \xe0\xc5\xf3g\xb9\
|
||||
eY\xb4\xdbm\x1c\xc7Y\xe8\x81&\xf8\xf4\xf1C\xde\xedv+\xce\x97Owx\xfc\xe8k\xc5\
|
||||
\xb6\xb7\xb7\x8b\xef\x0foW \x84\xe0\xea\xea\x02\xa5\x94n\x18\x80\x94\x92\xd9\
|
||||
l\x02@\x96e\x95>\xd4nVO\xd3\xb9\x0e\xba\r\xa6i\xd2\xef\xf7\xf0\xfd!\xc7G\x87\
|
||||
y\xed:)\xd5\x01J\xfd\xd6c\xfc~\x9a\xfc\x93\xe8\xf2\xf2\x02(Ma6\x9b \x84@)\
|
||||
\xa5\t}\xff\x0b\xd0\'I~R\x14\xca\xb2L\xfb\x97\x97\xef-\xeeA!_J\x89\xeb\xba\
|
||||
\xb8\xae\xab\xbf\x06\x7f\x97\xacP[\x87\xeb9\x0b!H\x92\ta\x18"\xa5\xd4U\xbd\
|
||||
\xadm\xe3\xe1\x83\x8d<\x8a~\x90\xa6\xbf\x88\xe3\x18)\xa5&\xa9\x03X\x96E\xab\
|
||||
\xb5\x8em7\xf5\xc2\x94\xb1\xba\xba\xc6\xe6\xe6\x06++\xf7\x89\xa2\xa8\xe2\xd3\
|
||||
=89\xf9Va.\x14\x14\xd8\xdf?X VJa\x14\xd7X\xde\xef2\xbc\xadm\xe3\x7f~\xe3\xae\
|
||||
\xe7\xfc\x07\x84;\xc5\x82\xa1m&\x95\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
|
||||
def getFindBitmap():
|
||||
|
||||
@@ -76,7 +76,6 @@ class HtmlView(CodeEditor.CodeView):
|
||||
## sizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
## sizer.Add(self._notebook, 1, wx.EXPAND)
|
||||
## frame.SetSizer(sizer)
|
||||
## frame.SetAutoLayout(True)
|
||||
##
|
||||
##
|
||||
## def OnNotebookChanging(self, event):
|
||||
@@ -120,7 +119,7 @@ class HtmlCtrl(CodeEditor.CodeCtrl):
|
||||
|
||||
|
||||
def SetViewDefaults(self):
|
||||
CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Html", hasWordWrap = False, hasTabs = True)
|
||||
CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Html", hasWordWrap = True, hasTabs = True)
|
||||
|
||||
|
||||
def GetFontAndColorFromConfig(self):
|
||||
@@ -160,6 +159,10 @@ class HtmlOptionsPanel(STCTextEditor.TextOptionsPanel):
|
||||
STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Html", label = "HTML", hasWordWrap = True, hasTabs = True)
|
||||
|
||||
|
||||
def GetIcon(self):
|
||||
return getHTMLIcon()
|
||||
|
||||
|
||||
HTMLKEYWORDS = [
|
||||
"A", "ABBR", "ACRONYM", "ADDRESS", "APPLET", "AREA", "B", "BASE", "BASEFONT", "BDO", "BIG", "BLOCKQUOTE",
|
||||
"BODY", "BR", "BUTTON", "CAPTION", "CENTER", "CITE", "CODE", "COL", "COLGROUP", "DD", "DEL", "DFN", "DIR",
|
||||
@@ -199,16 +202,26 @@ def getHTMLData():
|
||||
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\xd3IDAT8\x8dcddbf\xa0\x040\xfe\xbf\xd1\xf3\x9f\x12\x03X\xfe}\xbeI\
|
||||
\x91\x0b\x98(\xd2=(\x0c`\x90W\xd2\xfc\x0f\x030\xb6\xbc\x92\xe6\x7f\x1d\x03\
|
||||
\xf3\xffN\xae\xde\xff\xff\xff\xff\xff\xdf\xc0\xd8\xfa\xff\xb5;O\xfe_\xbb\xf3\
|
||||
\xe4\xbf\x8e\x819\\\xcd\xd7_\xff\xff\xb3<|x\x9dAAY\x0b\xc5\xd0\x07w\xaf1\xd8\
|
||||
\xdbZ0\xec\xdd\xb5\x85\x81\x81\x81\x81\xe1\xdd\xf3\x1b\x0c\xab\x97\xcef\xe0`\
|
||||
ca\xf8\xfa\xf1\x19\\\x1d\x17+\x03\x03\x0b\x03\x03\x03Cqq>\xc3\xd3\x17o\x18V,\
|
||||
]\n\x97de\xe7\x81\xb3\x199\xc4\x18\x0e\x1d:\xc2 "*\xce\xf0\x8f\x11!\x8e\xd3\
|
||||
\x0b\xd8\xd8\xa7\x8e\xed\xf9\x7f\xf1\xcca\x14o\xca+i\xfeg\xfc{:\x95\xa2\x844\
|
||||
\xf0\xd1H\xb1\x01\x8c\x94\xe6F\x8a]\x00\x00YXz\xf0\x97\x87\'\x1a\x00\x00\x00\
|
||||
\x00IEND\xaeB`\x82'
|
||||
\x00\x01\xeeIDAT8\x8d}\x92?h\x13a\x18\xc6\x7fw=\x8d\xb4\x98\xa9-uP\x1a\xc9p$\
|
||||
\xdc`\xd0C\x8d\x8b)\xc5!Z\x11\xcc\xd0A\xd0*\xa8\x93\x8b8\x18\x11\x14RD\x07\t\
|
||||
N\xfe\xc1\x0cRAtS\x1c,\xcd\x10\x8c\xd8S\xba$9"\x11L\r\x96\x92\xa4.\xda#i\xa5\
|
||||
\xe7p^r\x97?\xbe\xd3\xf1~\xdf\xf3{\x9f\xe7\xbbW\xf8T(\x998j\xb9V\x07 _\xde\
|
||||
\x0e\xc0\xad\x19U\xe0?%\x01\x0c\xef\x19owv\xf9\xff\x01\x96\x88N\x850\x92)\
|
||||
\xf3\xde\x95s}!Rgcx\xdb\x9f\xd6\xf7Z\x13"\xa7\xcf\x00\xf4\x85t\x01\xea\x9b\
|
||||
\xedV\xfa\xd53\x00\xb2z\xb3\x7f\x84\xe5Z\xbd\x15\xc1)>x,\x04\x84,\xc0\xed\'\
|
||||
\xfd\x01\x9dB\xdb:\xc0\x8a\xb1E\xa3\xb2A8\xe0!\x9cL\x99\x00\x83;\x83D\x0fxQ\
|
||||
\x15Y\xe8\x19\xc1\x16\xff\xfe\xf2\x11V\xaf\xb1\x03\x90G\xe0\xf5\xe7\n\xd5\
|
||||
\xf58\xb0\xc4\xfc"\xbcL\xbf7c\x91#\x82h\xff\xae\xb5\xa6{\xf2\xdc\x9bi\x17\
|
||||
\xf8\xc6\x85\xaf\x9c\xbf:\x03\xc0\xe8P\x82\x8bwN\xa2\xe5\x8a\xa6\xe8\x9cjW\
|
||||
\xf1\xed\x1c`M\x05P\x94\xa7=\xf3\xcf\xa6&\x91\x8c_\x85\xd6c\xad\x18[\xae\x0b\
|
||||
\'\xf6\xef\xe6h4\r\xc0\xcf\x1f\xd0\xa8l0:\x94 \x937\x00\xc8\xe4\r\xeb\r:\x85\
|
||||
\xe3J\x0cy\xe41\xde\xb1\xbb\xd4\xbf\x97\x11\x07|\x00T\xcbz\x97\x0b\xb1\x97\
|
||||
\xb5jY\xa71\xf6\x0e-Wb65\xc9\x8b\xf9\xe7,\xaenZg\xebq\xd7])\xab7\xc9\xea\xee\
|
||||
\x8c\xdaB\x90\xf8u\xbde\x13n\xb6\x96I[\x08\xa2N$(~\x8b#\xfb\x12H\x1f\x1e^\
|
||||
\xeaZQ-W4\x0f\x9f\xaa\x01~\x8eO\r\x92\xc9\x1b\xc8>KlC\xbc{!\x1c\xf0\xf4\x8e\
|
||||
\xa0*\xb2\x90|\xb4\xcf\xe1\xa0-v\xd6\xe5\xb3\xd3\x08\x828\xd0\x8b\x01X\xcb\
|
||||
\xa2\xe5J\xdc\x7f\xe0o\xc3\'\n\x84\x03\x1eb\x91C\xa8\x8a,\xfc\x05\xf6\x0e\
|
||||
\xbfa\x1f\xe7Z\xfb\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
|
||||
def getHTMLBitmap():
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
#----------------------------------------------------------------------------
|
||||
import wx
|
||||
import wx.lib.docview
|
||||
import sys
|
||||
_ = wx.GetTranslation
|
||||
|
||||
|
||||
@@ -36,10 +37,17 @@ class ImageView(wx.lib.docview.View):
|
||||
_("New Image File"),
|
||||
wx.OK | wx.ICON_EXCLAMATION)
|
||||
return False
|
||||
|
||||
try:
|
||||
self._bitmap = wx.Image(doc.GetFilename()).ConvertToBitmap()
|
||||
except:
|
||||
wx.MessageBox(_("Error loading '%s'. %s") % (doc.GetPrintableName(), sys.exc_value),
|
||||
_("Open Image File"),
|
||||
wx.OK | wx.ICON_EXCLAMATION)
|
||||
return False
|
||||
|
||||
frame = wx.GetApp().CreateDocumentFrame(self, doc, flags)
|
||||
panel = wx.Panel(frame, -1)
|
||||
self._bitmap = wx.Image(doc.GetFilename()).ConvertToBitmap()
|
||||
self._ctrl = wx.StaticBitmap(panel, -1, self._bitmap, (0,0), (self._bitmap.GetWidth(), self._bitmap.GetHeight()))
|
||||
wx.EVT_LEFT_DOWN(self._ctrl, self.OnFocus)
|
||||
wx.EVT_LEFT_DCLICK(self._ctrl, self.OnFocus)
|
||||
@@ -85,15 +93,21 @@ import cStringIO
|
||||
|
||||
def getImageData():
|
||||
return \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\
|
||||
\x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
|
||||
\x00\x9aIDAT(\x91\x95\x92\xc1\r\xc50\x08C\xdd\xaa\xeb\xc12\xec\x90\x9b\x97!\
|
||||
\x0b\xb0\x03\x19\xe8\x1fR\xa9U\xf2\xd5\xb4>DH\xf8\t\x13\xb1E\x04\xbe\xe8\x00\
|
||||
@\xf2\x8d\xb5\xd6z\x02\x00\xccl\t\x98\x19\xc9}\xe9#y\x8f\xb0\x00H\xba\xc3\
|
||||
\xfd\x8a\xbd\x9e0\xe8xn\x9b\x99*q[r\x01`\xfa\x8f?\x91\x86-\x07\x8d\x00Iww\
|
||||
\xf7\xce\xcc\xf0>\xbb\x01\xa8j)e\x80G\xa0\xb7[k\x00J)\xfdU\xd5\xd6Z\x87O_D\
|
||||
\x88\x88\x88dff>\x17"r\x02y\xd33\xb3E\xc4\xcb\xe3\xeb\xda\xbe\x9e\xf7\x0f\
|
||||
\xa0B\x86\xd5X\x16\xcc\xea\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
'\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\x017IDAT8\x8dcddbfh\x9f\xb3\xf3?\x03\x0e\xf0\xfc\xc5[\x0c\xb1\xfb\x0f\
|
||||
\x9f10000l\x9e]\xc2\xc8\x02\x13,Ot\xc6e\x06V\xe0\x9f1\x81\x81\x81\x81\x81\
|
||||
\x81\x05Y\xf0\xdc\x0b\x88C\x1e|\xfc\xc2\xf0\xe3\xf7\x01\x86{\x1fO20000(\xf1\
|
||||
\x9b3p\xb0:\xc0\xd5\x05\xa9\xf3\xc2\xd9L\xe8&\xa3kf```8\xfah-\xc3\xb57\x9d\
|
||||
\x0c?~\x1f\xc0p\t\x86\x01\xe8\x9aa\xe0\xf9\xc7\'X\xc5Q\x0c\x90\xe1c\xc4P\xf4\
|
||||
\xfc\xe3\x13\x14\xb6\x02?\x0f~\x17(\xf1\x9bc\xd5\xcc\xc0\xc0\xc0 \xc9/\x03g_\
|
||||
\xbbx\ta\x00,\xaa\xc4\xb8\x18\x18\x8c%\xd5\xb0j\x86\x19n$\xc1\x88"\xc6\x82\
|
||||
\xaeH]X\x9d!T#\x96\xe1\xec\xf3[\x0cG\x1f\xade````\xb0\x96\x0bf0\x96TcP\x17V\
|
||||
\xc70\x14\xc3\x00\x98!\xea\xc2\xea\x0c\xb7\x1a\x1a\x19\x18\x18\x18\x18\xa2\
|
||||
\xd6,\xc0\xa6\x0c\xe1\x05J\x00\x0b\x03\x03"iz,\xd3A\x91|l\xf2\x8a\x81\x81\
|
||||
\x81\x81au\x87\x18\x8a\xf8\xd5\x8aW\xc4\xb9@VN\x0c\x9f4v\x03\x94\x05LH2\x04%\
|
||||
\x10wD]!h#N\x03`\xb9\x0b\x06`\t\x85\x10\x00\x00\xe4\x0ecz\x94h\xf0\x8e\x00\
|
||||
\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
|
||||
def getImageBitmap():
|
||||
|
||||
@@ -14,6 +14,35 @@ import wx
|
||||
import Service
|
||||
import STCTextEditor
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Utility
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
def ClearMessages():
|
||||
messageService = wx.GetApp().GetService(MessageService)
|
||||
view = messageService.GetView()
|
||||
if view:
|
||||
view.ClearLines()
|
||||
|
||||
|
||||
def ShowMessages(messages, clear=False):
|
||||
if ((messages != None) and (len(messages) > 0)):
|
||||
messageService = wx.GetApp().GetService(MessageService)
|
||||
messageService.ShowWindow(True)
|
||||
view = messageService.GetView()
|
||||
if view:
|
||||
if (clear):
|
||||
view.ClearLines()
|
||||
for message in messages:
|
||||
view.AddLines(message)
|
||||
view.AddLines("\n")
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Classes
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
|
||||
class MessageView(Service.ServiceView):
|
||||
""" Reusable Message View for any document.
|
||||
When an item is selected, the document view is called back (with DoSelectCallback) to highlight and display the corresponding item in the document view.
|
||||
@@ -36,52 +65,52 @@ class MessageView(Service.ServiceView):
|
||||
txtCtrl.SetFontColor(wx.BLACK)
|
||||
txtCtrl.StyleClearAll()
|
||||
txtCtrl.UpdateStyles()
|
||||
wx.EVT_SET_FOCUS(txtCtrl, self.OnFocus)
|
||||
|
||||
return txtCtrl
|
||||
|
||||
def GetDocument(self):
|
||||
return None
|
||||
|
||||
## def ProcessEvent(self, event):
|
||||
## stcControl = self.GetControl()
|
||||
## if not isinstance(stcControl, wx.stc.StyledTextCtrl):
|
||||
## return wx.lib.docview.View.ProcessUpdateUIEvent(self, event)
|
||||
## id = event.GetId()
|
||||
## if id == wx.ID_CUT:
|
||||
## stcControl.Cut()
|
||||
## return True
|
||||
## elif id == wx.ID_COPY:
|
||||
## stcControl.Copy()
|
||||
## return True
|
||||
## elif id == wx.ID_PASTE:
|
||||
## stcControl.Paste()
|
||||
## return True
|
||||
## elif id == wx.ID_CLEAR:
|
||||
## stcControl.Clear()
|
||||
## return True
|
||||
## elif id == wx.ID_SELECTALL:
|
||||
## stcControl.SetSelection(0, -1)
|
||||
## return True
|
||||
##
|
||||
##
|
||||
## def ProcessUpdateUIEvent(self, event):
|
||||
## stcControl = self.GetControl()
|
||||
## if not isinstance(stcControl, wx.stc.StyledTextCtrl):
|
||||
## return wx.lib.docview.View.ProcessUpdateUIEvent(self, event)
|
||||
## id = event.GetId()
|
||||
## if id == wx.ID_CUT:
|
||||
## event.Enable(stcControl.CanCut())
|
||||
## return True
|
||||
## elif id == wx.ID_COPY:
|
||||
## event.Enable(stcControl.CanCopy())
|
||||
## return True
|
||||
## elif id == wx.ID_PASTE:
|
||||
## event.Enable(stcControl.CanPaste())
|
||||
## return True
|
||||
## elif id == wx.ID_CLEAR:
|
||||
## event.Enable(True) # wxBug: should be stcControl.CanCut()) but disabling clear item means del key doesn't work in control as expected
|
||||
## return True
|
||||
## elif id == wx.ID_SELECTALL:
|
||||
## event.Enable(stcControl.GetTextLength() > 0)
|
||||
## return True
|
||||
def OnFocus(self, event):
|
||||
wx.GetApp().GetDocumentManager().ActivateView(self)
|
||||
event.Skip()
|
||||
|
||||
def ProcessEvent(self, event):
|
||||
stcControl = self.GetControl()
|
||||
if not isinstance(stcControl, wx.stc.StyledTextCtrl):
|
||||
return wx.lib.docview.View.ProcessEvent(self, event)
|
||||
id = event.GetId()
|
||||
if id == wx.ID_COPY:
|
||||
stcControl.Copy()
|
||||
return True
|
||||
elif id == wx.ID_CLEAR:
|
||||
stcControl.Clear()
|
||||
return True
|
||||
elif id == wx.ID_SELECTALL:
|
||||
stcControl.SetSelection(0, -1)
|
||||
return True
|
||||
|
||||
|
||||
def ProcessUpdateUIEvent(self, event):
|
||||
stcControl = self.GetControl()
|
||||
if not isinstance(stcControl, wx.stc.StyledTextCtrl):
|
||||
return wx.lib.docview.View.ProcessUpdateUIEvent(self, event)
|
||||
id = event.GetId()
|
||||
if id == wx.ID_CUT or id == wx.ID_PASTE:
|
||||
# I don't think cut or paste makes sense from a message/log window.
|
||||
event.Enable(False)
|
||||
return True
|
||||
elif id == wx.ID_COPY:
|
||||
hasSelection = (stcControl.GetSelectionStart() != stcControl.GetSelectionEnd())
|
||||
event.Enable(hasSelection)
|
||||
return True
|
||||
elif id == wx.ID_CLEAR:
|
||||
event.Enable(True) # wxBug: should be stcControl.CanCut()) but disabling clear item means del key doesn't work in control as expected
|
||||
return True
|
||||
elif id == wx.ID_SELECTALL:
|
||||
event.Enable(stcControl.GetTextLength() > 0)
|
||||
return True
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
@@ -139,5 +168,3 @@ class MessageService(Service.Service):
|
||||
|
||||
def _CreateView(self):
|
||||
return MessageView(self)
|
||||
|
||||
|
||||
|
||||
@@ -321,7 +321,7 @@ class OutlineService(Service.Service):
|
||||
|
||||
def __init__(self, serviceName, embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM):
|
||||
Service.Service.__init__(self, serviceName, embeddedWindowLocation)
|
||||
self._validTemplates = []
|
||||
self._validViewTypes = []
|
||||
|
||||
|
||||
def _CreateView(self):
|
||||
@@ -493,9 +493,8 @@ class OutlineService(Service.Service):
|
||||
if self.GetView():
|
||||
currView = wx.GetApp().GetDocumentManager().GetCurrentView()
|
||||
if currView:
|
||||
for template in self._validTemplates:
|
||||
type = template.GetViewType()
|
||||
if isinstance(currView, type):
|
||||
for viewType in self._validViewTypes:
|
||||
if isinstance(currView, viewType):
|
||||
self.LoadOutline(currView)
|
||||
foundRegisteredView = True
|
||||
break
|
||||
@@ -506,14 +505,14 @@ class OutlineService(Service.Service):
|
||||
self._timer.Start(1000) # 1 second interval
|
||||
|
||||
|
||||
def AddTemplateForBackgroundHandler(self, template):
|
||||
self._validTemplates.append(template)
|
||||
def AddViewTypeForBackgroundHandler(self, viewType):
|
||||
self._validViewTypes.append(viewType)
|
||||
|
||||
|
||||
def GetTemplatesForBackgroundHandler(self):
|
||||
return self._validTemplates
|
||||
def GetViewTypesForBackgroundHandler(self):
|
||||
return self._validViewTypes
|
||||
|
||||
|
||||
def RemoveTemplateForBackgroundHandler(self, template):
|
||||
self._validTemplates.remove(template)
|
||||
def RemoveViewTypeForBackgroundHandler(self, viewType):
|
||||
self._validViewTypes.remove(viewType)
|
||||
|
||||
|
||||
@@ -219,6 +219,10 @@ class PHPOptionsPanel(STCTextEditor.TextOptionsPanel):
|
||||
STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "PHP", label = "PHP", hasWordWrap = True, hasTabs = True)
|
||||
|
||||
|
||||
def GetIcon(self):
|
||||
return getPHPIcon()
|
||||
|
||||
|
||||
PHPKEYWORDS = [
|
||||
"and", "or", "xor", "__FILE__", "exception", "__LINE__", "array", "as", "break", "case",
|
||||
"class", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif",
|
||||
@@ -274,14 +278,22 @@ import cStringIO
|
||||
|
||||
def getPHPData():
|
||||
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\x8dclh8\xf0\x9f\x81\x02\xc0D\x89f\xaa\x18\xc0\x82M0<\\\x1c\
|
||||
\xce^\xb9\xf2%y.\xd0\xd4\xd4$\xde\x05\xf8l\x0c\x0f\x17\x87\x8baS\xc7x\xfd\
|
||||
\xfa\xf5\xff\xc8\xb6]\xbf~\x1d\xc3\x05\xf8\xc4\x98\x90\x05\xae_\xbf\x8e\xa1\
|
||||
\x88\x90\xd8 \x8aF\x98\x93`~\xc3\x05\xd0\xd5\xc1\r\x80\t\xc0B\xf7\xfa\xf5\
|
||||
\xeb(l\\\xeaP\xbc\x80\x1c\x85\xb8\xd8\xe8|&b\x9c\x8dn;2`\x1c\xf0\xdc\x08\x00\
|
||||
\x8e\xf2S\xed\xb0\xbe\xaa\xbc\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x01GIDAT8\x8d\x8d\x931O\xc2@\x14\xc7\x7fW\xfa\x11\x1c\xe430\xb88\x18'\
|
||||
\x8c\x89\x0e\x0c\xc4\xd9\xdd\x85\xc9\xc5`\x82\x1b\t\x84\x98\x98\xe0\xa4_\x01\
|
||||
cd`t$\xb8h\xd0\xb8\xabD0\xd4\xd0\xb4%H $\xe7P\x0e{@\xa9\xff\xe4\r\xf7\xee~\
|
||||
\xff\xf7\xee^+\x1a\xcd\x8ed*\xab\xef\x02\xd0\xea\xda\x00\xb8\xce\x90\xb3\xa3\
|
||||
}\xc1*5\x9a\x1d\xf9\xf6#g\xf1\xea\xf9qyS\x97\xf5o)\x8f\xcfo\xa50b\x84\x85\
|
||||
\xb1\xca\xdc\x9b\xc0\xde\xe1\x01'\xa7U\x19v\xc6\xb4\xfa.\xeb\xc4\x01\x18L\
|
||||
\xfc\xa4;\xf2\xdb\x7f\xac\xdd\xd3s<\xda\x03+\xb4\x88\x19\x04\x15\x0c\xb0\x93\
|
||||
\xde\xc5\x9b\x80=\x86\xf6\xc5U\xa8\x81v\x05\x05\xab\xf6\xedq(\xf7\xd7A\xabk\
|
||||
\xb36\xd2\x93A\xd8\x1aF\x18\xcc\x83\xb0\x08\x7f\xbc\xb7\xc2\r\\g8\x03\x97\
|
||||
\xc1Q2{\x8e\xa7\x81/\xd7\xb5\x85C\xc9\xc46\xc9\x84>\xcaR!-`\xfa\x88\xab\xe0b\
|
||||
>\xb5\xb4\xb2\xfa6\xcc\xf6\xa7\xc5f\x00V\xc0\xc3\xf3\x17w\x95\xa7YN\xad\x83\
|
||||
\xfbP\x95\x06@un\xce\xd9\\\x8d\xad\x8d\xf8\xbf\xd6F\xa5\x9c\x11\x95rF\xfbaT\
|
||||
\xc50\x15\xf3)\xb29\xbfc!\x8c\x98v\xaf\xe0f\x14\\*\xa4\x85f\x10|\x9c(\xa9)\
|
||||
\xfc\x02?r\xb8\xfc~J.\xd0\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
|
||||
def getPHPBitmap():
|
||||
return BitmapFromImage(getPHPImage())
|
||||
|
||||
@@ -133,6 +133,10 @@ class PerlOptionsPanel(STCTextEditor.TextOptionsPanel):
|
||||
STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Perl", label = "Perl", hasWordWrap = True, hasTabs = True)
|
||||
|
||||
|
||||
def GetIcon(self):
|
||||
return getPerlIcon()
|
||||
|
||||
|
||||
PERLKEYWORDS = [
|
||||
"abs",
|
||||
"accept",
|
||||
@@ -392,24 +396,22 @@ import cStringIO
|
||||
|
||||
def getPerlData():
|
||||
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\x01\x81IDAT8\x8d\xa5S1n\xe30\x10\x1cJ\xf9\x80;U\x04\x04~\xc06\xdc\xa9\
|
||||
\x10\xd4\xb3K\xf2\x01\xf9\x01F\x92\xce\x8d:vI\x84\xdc\xd5\xaa\xdc%\xd1\x17\
|
||||
\x0c\x17ns\xa7\x07,\x16\xe0G6E@B\x91\x9c*\x0b\x10 \xb9\xe4\xecpg\xa8T\x92\
|
||||
\xe27q5^\xbc\xbf\xbd\n\x00\\\xdf\xdc\xaa\xb0\xf7\xfc\xf4(\xcc\x8c<\xcfqw\xff\
|
||||
\xa0\xa6\x00PI\x8aa\x18\xa4m[\xd9\xedvb\xad\x95a\x18D%)\xfa\xbe\x97\xc5b!\
|
||||
\xd6Z\xb1\xd6J\xdb\xb6\xa2\x92\x14\xe3\x91\x00\xc0r\xb5VZ\xeb\x08z<\x1e\xf1\
|
||||
\xfe\xf6*]\xd7\xc1\x18\x03c\x0c\xea\xba\x063\xe3\xff\xbf\x0f\xf9\xf1\tD\x14\
|
||||
\xe7\xce9\xec\xf7{\x00\x80\xf7\xfe\x1b\xf88\x920\xf1\xde\xc7j\xcc\x8c,\xcb\
|
||||
\xe2:\xe4\xeb\xba\x06\x80o,"\x03\xad5\x0e\x87C\xacz>\x9fAD\xb1\xba\xd6\x1aD\
|
||||
\x04f\x063\xcf\x19\\\xdf\xdc\xaa\xa2(p:\x9d\xe0\xbd\x07\x11\xc19\x07\xad5\
|
||||
\x98\x19\xce9l\xb7[\x10\x11\xf2<\x9f\x03\x00\xc0\xcb\x9f\xbf\xaa,\xcbX!\xcb2\
|
||||
t]\x17\xf3M\xd3\xc4\'\xc5\x98\xca\x12d\xddl6\x12d\x0c\x12\xab$\x85\xb5Vf2N\
|
||||
\x83\x88P\x14\x05\xbc\xf7h\x9a\x06UUE\xda\xc6\x98\xcbM\x1c\x871\x06\xde{TU\
|
||||
\x05\xe0\xcb\'\xe1RY\x96X\xae\xd6\xd1\x91\x17\x19\x00_]_\xae\xd6\x8a\x88\xf0\
|
||||
\xfc\xf4(\xe1\xd2\xb4\x07?\x02\x8c\x0f\x8e\x1d85\xd2\xc5\x06\xf6}?\xf3|\x18\
|
||||
\xb3\xdco\xbf\xf3\'`\xa6\xbc1\xa7\xd6\xcb\xbf\x00\x00\x00\x00IEND\xaeB`\x82'\
|
||||
\x00\x01CIDAT8\x8d\x95\x93\xbfN\x02A\x10\x87\xbf[\xef\x05\xach|\x02m}\x008\
|
||||
\x881Z\xd2\x1a\x13\x0bKx\x02{\xa3\xa13\xc6\xc6\xc6\xd2DZ+s\\\x83\x95\x1d\xa2\
|
||||
&V\x104\x01/p\x01\t\xa0\xe8X\xc0\x9d\x87\xdc^\xf0\x97Lfw3\xdf\xec\xcc\xfe1\
|
||||
\xca\x95\xba0\x95\xeb\xf5\x01h\xb4\xda\x00x\xde\x90\x83\xfd\r\x838\x95+u\xa9\
|
||||
\rDj\x03\x91\xe7\xbe\xc8}wb\xa7\xc5\xb2\xdc\xbe\x89\xe4\x8f\xae\xc4PK\xe8L\
|
||||
\xc5%\xef\x8da{7K\xee\xf0Rt1\xa6\xeb\xf5Y\x01>\xbea\xf45Y\xec\x8e&\xe5\xdf]\
|
||||
\xdb4\xdd\x0e\xaf/-\xed&&\x110\xc0\xfa\x96\xc5\xf1N\x06\x80\xe5\xb5\xac6\x81\
|
||||
\x82y\xb87\x9e\r\xeaT\x8b3s+\x95\x14+\x95\x14\x00\xd5h\xb5\xe9\x8e\xe6a\x7f\
|
||||
\xf70\x14\xf6\xfeXy\xde0\x08\xf2\xe1\xf6gt\xb9V*)v\xc9\t\xae\xd5.9\x86\x19\
|
||||
\x05\x9e\xefe\xe6i\x8dT\xd3\xed\xfc\x0b\x0e\xb7\x00\xd3C\xd4\x95\x1c'\xbf\
|
||||
\x15\x15\xbe\xe3\xc6;l\x9e\xdc\x00\xbf\xfe/`\x97\x1c#|\x0e&@\xb1p\x16\x04>U\
|
||||
\x1fI\x00\x17\xb9<\t\xa0\xc9*\t\x1e\xf4\xa5D\xbd\xeft:-q~\xe1\xbf\xb0\x88b\
|
||||
\x13\x84{\x8d\x9a\x03\xfc\x00\xea\x7f\xa9A\xa7\xc3Vo\x00\x00\x00\x00IEND\xae\
|
||||
B`\x82"
|
||||
|
||||
|
||||
def getPerlBitmap():
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@ import keyword # for GetAutoCompleteKeywordList
|
||||
import sys # for GetAutoCompleteKeywordList
|
||||
import MessageService # for OnCheckCode
|
||||
import OutlineService
|
||||
from UICommon import CaseInsensitiveCompare
|
||||
try:
|
||||
import checker # for pychecker
|
||||
_CHECKER_INSTALLED = True
|
||||
@@ -69,8 +70,11 @@ class PythonView(CodeEditor.CodeView):
|
||||
|
||||
def OnActivateView(self, activate, activeView, deactiveView):
|
||||
STCTextEditor.TextView.OnActivateView(self, activate, activeView, deactiveView)
|
||||
if activate:
|
||||
wx.CallAfter(self.LoadOutline) # need CallAfter because document isn't loaded yet
|
||||
if activate and self.GetCtrl():
|
||||
if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
|
||||
self.LoadOutline()
|
||||
else:
|
||||
wx.CallAfter(self.LoadOutline) # need CallAfter because document isn't loaded yet
|
||||
|
||||
|
||||
def OnClose(self, deleteWindow = True):
|
||||
@@ -99,7 +103,7 @@ class PythonView(CodeEditor.CodeView):
|
||||
filterkw = filter(lambda item: item.lower().startswith(lowerHint), kw) # remove variables and methods that don't match hint
|
||||
kw = filterkw
|
||||
|
||||
kw.sort(self.CaseInsensitiveCompare)
|
||||
kw.sort(CaseInsensitiveCompare)
|
||||
|
||||
if hint:
|
||||
replaceLen = len(hint)
|
||||
@@ -119,6 +123,7 @@ class PythonView(CodeEditor.CodeView):
|
||||
# pychecker only works on files, doesn't take a stream or string input
|
||||
if self.GetDocument().IsModified():
|
||||
dlg = wx.MessageDialog(self.GetFrame(), _("'%s' has been modfied and must be saved first. Save file and check code?") % filename, _("Check Code"))
|
||||
dlg.CenterOnParent()
|
||||
val = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
if val == wx.ID_OK:
|
||||
@@ -167,7 +172,7 @@ class PythonView(CodeEditor.CodeView):
|
||||
break
|
||||
|
||||
if not foundView:
|
||||
doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT)
|
||||
doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE)
|
||||
foundView = doc.GetFirstView()
|
||||
|
||||
if foundView:
|
||||
@@ -269,11 +274,29 @@ class PythonInterpreterView(wx.lib.docview.View):
|
||||
return True
|
||||
|
||||
|
||||
class PythonInterpreterDocument(wx.lib.docview.Document):
|
||||
""" Generate Unique Doc Type """
|
||||
pass
|
||||
|
||||
|
||||
class PythonService(CodeEditor.CodeService):
|
||||
|
||||
|
||||
def __init__(self):
|
||||
CodeEditor.CodeService.__init__(self)
|
||||
docManager = wx.GetApp().GetDocumentManager()
|
||||
pythonInterpreterTemplate = wx.lib.docview.DocTemplate(docManager,
|
||||
_("Python Interpreter"),
|
||||
"*.Foobar",
|
||||
"Foobar",
|
||||
".Foobar",
|
||||
_("Python Interpreter Document"),
|
||||
_("Python Interpreter View"),
|
||||
PythonInterpreterDocument,
|
||||
PythonInterpreterView,
|
||||
flags = wx.lib.docview.TEMPLATE_INVISIBLE,
|
||||
icon = getPythonIcon())
|
||||
docManager.AssociateTemplate(pythonInterpreterTemplate)
|
||||
|
||||
|
||||
def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
|
||||
@@ -308,7 +331,7 @@ class PythonService(CodeEditor.CodeService):
|
||||
docManager = wx.GetApp().GetDocumentManager()
|
||||
event.Check(False)
|
||||
for doc in docManager.GetDocuments():
|
||||
if isinstance(doc.GetFirstView(), PythonInterpreterView):
|
||||
if isinstance(doc, PythonInterpreterDocument):
|
||||
event.Check(True)
|
||||
break
|
||||
return True
|
||||
@@ -318,28 +341,20 @@ class PythonService(CodeEditor.CodeService):
|
||||
|
||||
def OnViewPythonInterpreter(self, event):
|
||||
for doc in wx.GetApp().GetDocumentManager().GetDocuments():
|
||||
if isinstance(doc.GetFirstView(), PythonInterpreterView):
|
||||
doc.GetFirstView().GetDocument().DeleteAllViews()
|
||||
if isinstance(doc, PythonInterpreterDocument):
|
||||
doc.DeleteAllViews()
|
||||
return
|
||||
|
||||
docManager = self.GetDocumentManager()
|
||||
template = wx.lib.docview.DocTemplate(docManager,
|
||||
_("Python Interpreter"),
|
||||
"*.Foobar",
|
||||
"Foobar",
|
||||
".Foobar",
|
||||
_("Python Interpreter Document"),
|
||||
_("Python Interpreter View"),
|
||||
wx.lib.docview.Document,
|
||||
PythonInterpreterView,
|
||||
flags = wx.lib.docview.TEMPLATE_INVISIBLE)
|
||||
newDoc = template.CreateDocument('', wx.lib.docview.DOC_SILENT)
|
||||
if newDoc:
|
||||
newDoc.SetDocumentName(template.GetDocumentName())
|
||||
newDoc.SetDocumentTemplate(template)
|
||||
newDoc.OnNewDocument()
|
||||
newDoc.SetWriteable(False)
|
||||
newDoc.GetFirstView().GetFrame().SetTitle(_("Python Interpreter"))
|
||||
for template in self.GetDocumentManager().GetTemplates():
|
||||
if template.GetDocumentType() == PythonInterpreterDocument:
|
||||
newDoc = template.CreateDocument('', wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE)
|
||||
if newDoc:
|
||||
newDoc.SetDocumentName(template.GetDocumentName())
|
||||
newDoc.SetDocumentTemplate(template)
|
||||
newDoc.OnNewDocument()
|
||||
newDoc.SetWriteable(False)
|
||||
newDoc.GetFirstView().GetFrame().SetTitle(_("Python Interpreter"))
|
||||
break
|
||||
|
||||
|
||||
class PythonCtrl(CodeEditor.CodeCtrl):
|
||||
@@ -355,7 +370,7 @@ class PythonCtrl(CodeEditor.CodeCtrl):
|
||||
|
||||
|
||||
def SetViewDefaults(self):
|
||||
CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Python", hasWordWrap = False, hasTabs = True)
|
||||
CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Python", hasWordWrap = True, hasTabs = True)
|
||||
|
||||
|
||||
def GetFontAndColorFromConfig(self):
|
||||
@@ -544,40 +559,56 @@ class PythonOptionsPanel(wx.Panel):
|
||||
choosePathButton = wx.Button(self, -1, _("Browse..."))
|
||||
pathSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
HALF_SPACE = 5
|
||||
pathSizer.Add(pathLabel, 0, wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, HALF_SPACE)
|
||||
pathSizer.Add(self._pathTextCtrl, 0, wx.ALIGN_LEFT | wx.EXPAND | wx.RIGHT, HALF_SPACE)
|
||||
pathSizer.Add(choosePathButton, 0, wx.ALIGN_RIGHT | wx.LEFT, HALF_SPACE)
|
||||
SPACE = 10
|
||||
pathSizer.Add(pathLabel, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.TOP, HALF_SPACE)
|
||||
pathSizer.Add(self._pathTextCtrl, 1, wx.EXPAND|wx.LEFT|wx.TOP, HALF_SPACE)
|
||||
pathSizer.Add(choosePathButton, 0, wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT|wx.TOP, HALF_SPACE)
|
||||
wx.EVT_BUTTON(self, choosePathButton.GetId(), self.OnChoosePath)
|
||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
mainSizer.Add(pathSizer, 0, wx.LEFT | wx.RIGHT | wx.TOP, 10)
|
||||
mainSizer.Add(pathSizer, 0, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, SPACE)
|
||||
|
||||
self._otherOptions = STCTextEditor.TextOptionsPanel(self, -1, configPrefix = "Python", label = "Python", hasWordWrap = False, hasTabs = True, addPage=False)
|
||||
mainSizer.Add(self._otherOptions)
|
||||
self._otherOptions = STCTextEditor.TextOptionsPanel(self, -1, configPrefix = "Python", label = "Python", hasWordWrap = True, hasTabs = True, addPage=False)
|
||||
mainSizer.Add(self._otherOptions, 0, wx.EXPAND|wx.BOTTOM, SPACE)
|
||||
self.SetSizer(mainSizer)
|
||||
parent.AddPage(self, _("Python"))
|
||||
|
||||
|
||||
def OnChoosePath(self, event):
|
||||
defaultDir = os.path.dirname(self._pathTextCtrl.GetValue().strip())
|
||||
defaultFile = os.path.basename(self._pathTextCtrl.GetValue().strip())
|
||||
if _WINDOWS:
|
||||
wildcard = _("*.exe")
|
||||
wildcard = _("Executable (*.exe)|*.exe|All (*.*)|*.*")
|
||||
if not defaultFile:
|
||||
defaultFile = "python.exe"
|
||||
else:
|
||||
wildcard = _("*")
|
||||
path = wx.FileSelector(_("Select a File"),
|
||||
_(""),
|
||||
_(""),
|
||||
wildcard = wildcard ,
|
||||
flags = wx.HIDE_READONLY,
|
||||
parent = wx.GetApp().GetTopWindow())
|
||||
if path:
|
||||
self._pathTextCtrl.SetValue(path)
|
||||
self._pathTextCtrl.SetToolTipString(self._pathTextCtrl.GetValue())
|
||||
self._pathTextCtrl.SetInsertionPointEnd()
|
||||
dlg = wx.FileDialog(wx.GetApp().GetTopWindow(),
|
||||
_("Select a File"),
|
||||
defaultDir=defaultDir,
|
||||
defaultFile=defaultFile,
|
||||
wildcard=wildcard,
|
||||
style=wx.OPEN|wx.FILE_MUST_EXIST|wx.HIDE_READONLY)
|
||||
# dlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
path = dlg.GetPath()
|
||||
if path:
|
||||
self._pathTextCtrl.SetValue(path)
|
||||
self._pathTextCtrl.SetToolTipString(self._pathTextCtrl.GetValue())
|
||||
self._pathTextCtrl.SetInsertionPointEnd()
|
||||
dlg.Destroy()
|
||||
|
||||
|
||||
def OnOK(self, optionsDialog):
|
||||
if len(self._pathTextCtrl.GetValue()) > 0:
|
||||
config = wx.ConfigBase_Get()
|
||||
config.Write("ActiveGridPythonLocation", self._pathTextCtrl.GetValue())
|
||||
config = wx.ConfigBase_Get()
|
||||
config.Write("ActiveGridPythonLocation", self._pathTextCtrl.GetValue().strip())
|
||||
|
||||
self._otherOptions.OnOK(optionsDialog)
|
||||
|
||||
|
||||
def GetIcon(self):
|
||||
return getPythonIcon()
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Icon Bitmaps - generated by encode_bitmaps.py
|
||||
#----------------------------------------------------------------------------
|
||||
@@ -587,18 +618,28 @@ import cStringIO
|
||||
|
||||
def getPythonData():
|
||||
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\xd5IDAT8\x8d\x8d\x93Y\x0e\xc3 \x0cD\x9fM\xcf\xddNr2.\x96\xb8\x1f\
|
||||
\x05\n\x84.#Y\x10\xa3\x19o\xb1\x99'*\xe2<\x82\x0e\xe6\xc9\xf8\x01\xef?\xa4\
|
||||
\xf7)]\x05\x970O\xcdr\xce!\x119\xe7\x00\x02\x88\xfe}i\xb5\x848\x8f\xa8\x19\
|
||||
\xcc\x19}+\xc5\xcc\xd3\x92<CZ\x0b\x99\xc4\xb2N\x01<\x80\xad\xdc?\x88\xf8\x1c\
|
||||
X\x8f7\xe1\x1f\xdc*\xa9a+\xe1\xa3\xdc\xe7\xb4\xf6\xd1\xe5\xb6'\xc3@\xc5\xa0#\
|
||||
\xab\x94\xd1\x0bL\xf0\xe6\x17\xa8v\xc3\x8aS\xa0.\x8be\x13\xe3\x15\x8f\xe1\
|
||||
\xa5D\xee\xc9\xdb~%\xc7y\x84\xbb'sO\xd6\xd4\x17\xe4~\xc4\xf5\xef\xac\xa7\r\
|
||||
\xbbp?b&\x0f\x89i\x14\x93\xca\x14z\xc5oh\x02E\xc4<\xd92\x03\xe0:B^\xc4K#\xe7\
|
||||
\xe5\x00\x02\xfd\xb9H\x9ex\x02\x9a\x05a\xd2\xd3c\xc0\xcc\x00\x00\x00\x00IEND\
|
||||
\xaeB`\x82"
|
||||
\x00\x01\xe7IDAT8\x8d}\x921h\x13Q\x18\xc7\x7fw\xb9\x0ei\x9d*\xbd\xeb\x10\x8f\
|
||||
,\x99\x1c*A[\xaa\x19B\xe8\xd0\xb1\x0e%K\x87\x88T2\x88Cqp\tD\x14i\xe9\xe0V\
|
||||
\xdaQ\xb7\xe0P\xa1\x8b\xa0(\x95$z\xd5Q1\x90\xa2\xd7\x9a4^\x87\xa0`\x92!w9\
|
||||
\x87\xf8.\xb9\xa6\xc97\xbd\xef{\xef\xfb\xbd\xff\xfb\xbfO*~;v\xf9\x1f\xad\xba\
|
||||
\x05@\xf9\xd4\x06\xc0::$\xbb\x96\x92\x18\x11\n@(4\xdd\xcdB\xd3\xd4\x1d\x85\
|
||||
\x8b\x97\xe1\xe3;\x83\x99\xe5\x15\xb2\xe0\x8e\x82\xc8\xa3\xe8\x003\xcb+\xac\
|
||||
\xaee\xdda\xfb\xb2\x90\rPw\x14\x00\x9a\xb5\n\xbf\xfflSz\x9d\xa2Y\xdc"zca\xe8\
|
||||
\x05\xb2h\x14\xcd\xd0\xf3B\x9f\x98\xe5\xf9\xde\x13"\xaaB\xc7\xb1\xcfU!\x0b\
|
||||
\xc3D4k\x15\xac\x93\x03\xf4\x89Y\xaf\x96\xffT\x028\x17\xa2\xf4\'\xcdZ\x85\
|
||||
\xf7F\x06{\xaa\x80ev\xc1\x91\xb91>\x18\x0f\xb8\xb7\x95a\xe9\xca\x0b:\x8e\xed\
|
||||
\xca\x01E\x1a\x00\x98\r\x89\x92\x91\xa1\xda\xd8\x87\x06ha\x1f\x1b\x80\xcd\
|
||||
\x9d%\xe0\xa5\x0f"[G\x87\x98\x8d\xde/ia\x05-\xac`\x996\xf9\\\x0b\xcb\xb4)\
|
||||
\x1bmOMn\xf7\xd5\xf0\'\\\x8b\xdces\xe7\x8d\xef\x80h\xd6\xc2\n\xf9\\\x0b]\xf5\
|
||||
\xab\xf2\xcdApR#\xf1kp4b\xc9 \xf9\\\x0b\x80\xe4\xcdE\xaf\xdeqlW\xaeVL\xaf`~\
|
||||
\xd9\x03@W\xd3\x00\xc4\x13\x0b\xc4\x92A\xcf\xd0\xf9\xe8:\x89\xebW\x01(|\xfd\
|
||||
\xe1\xbe-~F\xbas\xff\x91\xf75\x82n\x9d\x1c\xf0}\xfciw\xdd\xe7A<\xd1\x1b\xa8j\
|
||||
c\x9f\xb2\xd1F\x92\xe4\x80O\x12\xc0\xc6\xb3\x14\xf6Ta\xe0)g\x81\xba\x9a\xf6\
|
||||
\x9b(\x07\x14I@\x84lq\xb8?\xe6\xa3\xeb\x00\xdc\xba\x9d\xf4+\x10*~\xfem\xf3\
|
||||
\xf8\xe1\x06\xc7\xa7\xdb\xe8j\x9a\xf8\xdc\xa4\xb7\x1f[\\\xe5\xd2\x851/\xff\
|
||||
\x07\xac\x9b\xd1e\x12\x96\x0f\xfd\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
|
||||
def getPythonBitmap():
|
||||
|
||||
@@ -80,6 +80,13 @@ class TextDocument(wx.lib.docview.Document):
|
||||
pass
|
||||
|
||||
|
||||
# Use this to override MultiClient.Select to prevent yellow background.
|
||||
def MultiClientSelectBGNotYellow(a):
|
||||
a.GetParent().multiView.UnSelect()
|
||||
a.selected = True
|
||||
#a.SetBackgroundColour(wx.Colour(255,255,0)) # Yellow
|
||||
a.Refresh()
|
||||
|
||||
class TextView(wx.lib.docview.View):
|
||||
MARKER_NUM = 0
|
||||
MARKER_MASK = 0x1
|
||||
@@ -102,6 +109,12 @@ class TextView(wx.lib.docview.View):
|
||||
|
||||
|
||||
def GetCtrl(self):
|
||||
if wx.Platform == "__WXMAC__":
|
||||
# look for active one first
|
||||
self._textEditor = self._GetActiveCtrl(self._dynSash)
|
||||
if self._textEditor == None: # it is possible none are active
|
||||
# look for any existing one
|
||||
self._textEditor = self._FindCtrl(self._dynSash)
|
||||
return self._textEditor
|
||||
|
||||
|
||||
@@ -116,9 +129,19 @@ class TextView(wx.lib.docview.View):
|
||||
|
||||
def OnCreate(self, doc, flags):
|
||||
frame = wx.GetApp().CreateDocumentFrame(self, doc, flags, style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
|
||||
self._dynSash = wx.gizmos.DynamicSashWindow(frame, -1, style=wx.CLIP_CHILDREN)
|
||||
self._dynSash._view = self
|
||||
self._textEditor = self.GetCtrlClass()(self._dynSash, -1, style=wx.NO_BORDER)
|
||||
# wxBug: DynamicSashWindow doesn't work on Mac, so revert to
|
||||
# multisash implementation
|
||||
if wx.Platform == "__WXMAC__":
|
||||
wx.lib.multisash.MultiClient.Select = MultiClientSelectBGNotYellow
|
||||
self._dynSash = wx.lib.multisash.MultiSash(frame, -1)
|
||||
self._dynSash.SetDefaultChildClass(self.GetCtrlClass()) # wxBug: MultiSash instantiates the first TextCtrl with this call
|
||||
|
||||
self._textEditor = self.GetCtrl() # wxBug: grab the TextCtrl from the MultiSash datastructure
|
||||
else:
|
||||
self._dynSash = wx.gizmos.DynamicSashWindow(frame, -1, style=wx.CLIP_CHILDREN)
|
||||
self._dynSash._view = self
|
||||
self._textEditor = self.GetCtrlClass()(self._dynSash, -1, style=wx.NO_BORDER)
|
||||
wx.EVT_LEFT_DOWN(self._textEditor, self.OnLeftClick)
|
||||
self._CreateSizer(frame)
|
||||
self.Activate()
|
||||
frame.Show(True)
|
||||
@@ -130,14 +153,18 @@ class TextView(wx.lib.docview.View):
|
||||
sizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer.Add(self._dynSash, 1, wx.EXPAND)
|
||||
frame.SetSizer(sizer)
|
||||
frame.SetAutoLayout(True)
|
||||
|
||||
|
||||
def OnLeftClick(self, event):
|
||||
self.Activate()
|
||||
event.Skip()
|
||||
|
||||
|
||||
def OnUpdate(self, sender = None, hint = None):
|
||||
if hint == "ViewStuff":
|
||||
self.GetCtrl().SetViewDefaults()
|
||||
elif hint == "Font":
|
||||
font, color = self.GetFontAndColorFromConfig()
|
||||
font, color = self.GetCtrl().GetFontAndColorFromConfig()
|
||||
self.GetCtrl().SetFont(font)
|
||||
self.GetCtrl().SetFontColor(color)
|
||||
|
||||
@@ -195,7 +222,7 @@ class TextView(wx.lib.docview.View):
|
||||
self.GetCtrl().SetViewEOL(not self.GetCtrl().GetViewEOL())
|
||||
return True
|
||||
elif id == VIEW_INDENTATION_GUIDES_ID:
|
||||
self.GetCtrl().SetViewIndentationGuides(not self.GetCtrl().GetViewIndentationGuides())
|
||||
self.GetCtrl().SetIndentationGuides(not self.GetCtrl().GetIndentationGuides())
|
||||
return True
|
||||
elif id == VIEW_RIGHT_EDGE_ID:
|
||||
self.GetCtrl().SetViewRightEdge(not self.GetCtrl().GetViewRightEdge())
|
||||
@@ -352,6 +379,29 @@ class TextView(wx.lib.docview.View):
|
||||
def _GetParentFrame(self):
|
||||
return wx.GetTopLevelParent(self.GetFrame())
|
||||
|
||||
def _GetActiveCtrl(self, parent):
|
||||
""" Walk through the MultiSash windows and find the active Control """
|
||||
if isinstance(parent, wx.lib.multisash.MultiClient) and parent.selected:
|
||||
return parent.child
|
||||
if hasattr(parent, "GetChildren"):
|
||||
for child in parent.GetChildren():
|
||||
found = self._GetActiveCtrl(child)
|
||||
if found:
|
||||
return found
|
||||
return None
|
||||
|
||||
|
||||
def _FindCtrl(self, parent):
|
||||
""" Walk through the MultiSash windows and find the first TextCtrl """
|
||||
if isinstance(parent, self.GetCtrlClass()):
|
||||
return parent
|
||||
if hasattr(parent, "GetChildren"):
|
||||
for child in parent.GetChildren():
|
||||
found = self._FindCtrl(child)
|
||||
if found:
|
||||
return found
|
||||
return None
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Methods for TextDocument to call
|
||||
@@ -401,6 +451,7 @@ class TextView(wx.lib.docview.View):
|
||||
data.SetInitialFont(self.GetCtrl().GetFont())
|
||||
data.SetColour(self.GetCtrl().GetFontColor())
|
||||
fontDialog = wx.FontDialog(self.GetFrame(), data)
|
||||
fontDialog.CenterOnParent()
|
||||
if fontDialog.ShowModal() == wx.ID_OK:
|
||||
data = fontDialog.GetFontData()
|
||||
self.GetCtrl().SetFont(data.GetChosenFont())
|
||||
@@ -614,7 +665,13 @@ class TextView(wx.lib.docview.View):
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def GetMarkerLines(self, mask=MARKER_MASK):
|
||||
retval = []
|
||||
for lineNum in range(self.GetCtrl().GetLineCount()):
|
||||
if self.GetCtrl().MarkerGet(lineNum) & mask:
|
||||
retval.append(lineNum)
|
||||
return retval
|
||||
|
||||
def GetMarkerCount(self):
|
||||
return self._markerCount
|
||||
|
||||
@@ -807,9 +864,9 @@ class TextOptionsPanel(wx.Panel):
|
||||
textPanelSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
textFontSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
textFontSizer.Add(fontLabel, 0, wx.ALIGN_LEFT | wx.RIGHT | wx.TOP, HALF_SPACE)
|
||||
textFontSizer.Add(self._sampleTextCtrl, 0, wx.ALIGN_LEFT | wx.EXPAND | wx.RIGHT, HALF_SPACE)
|
||||
textFontSizer.Add(self._sampleTextCtrl, 1, wx.ALIGN_LEFT | wx.EXPAND | wx.RIGHT, HALF_SPACE)
|
||||
textFontSizer.Add(chooseFontButton, 0, wx.ALIGN_RIGHT | wx.LEFT, HALF_SPACE)
|
||||
textPanelSizer.Add(textFontSizer, 0, wx.ALL, HALF_SPACE)
|
||||
textPanelSizer.Add(textFontSizer, 0, wx.ALL|wx.EXPAND, HALF_SPACE)
|
||||
if self._hasWordWrap:
|
||||
textPanelSizer.Add(self._wordWrapCheckBox, 0, wx.ALL, HALF_SPACE)
|
||||
textPanelSizer.Add(self._viewWhitespaceCheckBox, 0, wx.ALL, HALF_SPACE)
|
||||
@@ -823,7 +880,7 @@ class TextOptionsPanel(wx.Panel):
|
||||
textIndentWidthSizer.Add(indentWidthLabel, 0, wx.ALIGN_LEFT | wx.RIGHT | wx.TOP, HALF_SPACE)
|
||||
textIndentWidthSizer.Add(self._indentWidthChoice, 0, wx.ALIGN_LEFT | wx.EXPAND, HALF_SPACE)
|
||||
textPanelSizer.Add(textIndentWidthSizer, 0, wx.ALL, HALF_SPACE)
|
||||
textPanelBorderSizer.Add(textPanelSizer, 0, wx.ALL, SPACE)
|
||||
textPanelBorderSizer.Add(textPanelSizer, 0, wx.ALL|wx.EXPAND, SPACE)
|
||||
## styleButton = wx.Button(self, -1, _("Choose Style..."))
|
||||
## wx.EVT_BUTTON(self, styleButton.GetId(), self.OnChooseStyle)
|
||||
## textPanelBorderSizer.Add(styleButton, 0, wx.ALL, SPACE)
|
||||
@@ -856,6 +913,7 @@ class TextOptionsPanel(wx.Panel):
|
||||
## #'HTML', 'html',
|
||||
## #'XML', 'xml',
|
||||
## config)
|
||||
## dlg.CenterOnParent()
|
||||
## try:
|
||||
## dlg.ShowModal()
|
||||
## finally:
|
||||
@@ -868,6 +926,7 @@ class TextOptionsPanel(wx.Panel):
|
||||
data.SetInitialFont(self._textFont)
|
||||
data.SetColour(self._textColor)
|
||||
fontDialog = wx.FontDialog(self, data)
|
||||
fontDialog.CenterOnParent()
|
||||
if fontDialog.ShowModal() == wx.ID_OK:
|
||||
data = fontDialog.GetFontData()
|
||||
self._textFont = data.GetChosenFont()
|
||||
@@ -909,6 +968,10 @@ class TextOptionsPanel(wx.Panel):
|
||||
document.UpdateAllViews(hint = "ViewStuff")
|
||||
if doFontUpdate:
|
||||
document.UpdateAllViews(hint = "Font")
|
||||
|
||||
|
||||
def GetIcon(self):
|
||||
return getTextIcon()
|
||||
|
||||
|
||||
class TextCtrl(wx.stc.StyledTextCtrl):
|
||||
@@ -958,8 +1021,27 @@ class TextCtrl(wx.stc.StyledTextCtrl):
|
||||
self.SetFontColor(color)
|
||||
self.MarkerDefineDefault()
|
||||
|
||||
# for multisash initialization
|
||||
if isinstance(parent, wx.lib.multisash.MultiClient):
|
||||
while parent.GetParent():
|
||||
parent = parent.GetParent()
|
||||
if hasattr(parent, "GetView"):
|
||||
break
|
||||
if hasattr(parent, "GetView"):
|
||||
textEditor = parent.GetView()._textEditor
|
||||
if textEditor:
|
||||
doc = textEditor.GetDocPointer()
|
||||
if doc:
|
||||
self.SetDocPointer(doc)
|
||||
|
||||
|
||||
def OnFocus(self, event):
|
||||
# wxBug: On Mac, the STC control may fire a focus/kill focus event
|
||||
# on shutdown even if the control is in an invalid state. So check
|
||||
# before handling the event.
|
||||
if self.IsBeingDeleted():
|
||||
return
|
||||
|
||||
self.SetSelBackground(1, "BLUE")
|
||||
self.SetSelForeground(1, "WHITE")
|
||||
if hasattr(self, "_dynSash"):
|
||||
@@ -968,6 +1050,11 @@ class TextCtrl(wx.stc.StyledTextCtrl):
|
||||
|
||||
|
||||
def OnKillFocus(self, event):
|
||||
# wxBug: On Mac, the STC control may fire a focus/kill focus event
|
||||
# on shutdown even if the control is in an invalid state. So check
|
||||
# before handling the event.
|
||||
if self.IsBeingDeleted():
|
||||
return
|
||||
self.SetSelBackground(0, "BLUE")
|
||||
self.SetSelForeground(0, "WHITE")
|
||||
self.SetSelBackground(1, "#C0C0C0")
|
||||
@@ -1328,13 +1415,21 @@ import cStringIO
|
||||
|
||||
def getTextData():
|
||||
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\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\xa7JU!$\x12\x1d\
|
||||
\xeb\t\t8n\x81\xb4\x86J\xfa]h\x0ee\x83\xb4\xc6\x14\x00\x00R\xcc \t\xcd\xa1\
|
||||
\x08\xd2\xa3\xe1\x08*\t$\x1d\xc4\x012\x0b\x00\xce\xe4\xc8\xe0\t}\xf7\x8f\rV\
|
||||
\xd9\x1a\xec\xe0\xbf\xc1\xd7\x06\xd9\xf5UX\xfdF+m\x03\xb8\x00\xe4\xc74B"x\
|
||||
\xf1\xf4\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x015IDAT8\x8d\xad\x90\xb1N\xc2P\x14\x86\xbf\x02/\xe0\xec#\x18g\xc3\xe6T\
|
||||
\x13':1\x18H\x98\x14\x12\x17G\x177\x17\x9c4a\xc5\xc0d0\xc2\xccdLx\x02^@+\t\
|
||||
\xc1\x90\xf6r\xdb\xc6\x94\xe5:\\\xdbP)\xc5DOr\x92\x9b{\xff\xfb\xfd\xff9\xc6h\
|
||||
l+\xbek.\x02\x00\xec\x99\x03\x80\xeb\xf8\\\x9d\x1d\x1bd\xd5hl\xab\xd7O\x15\
|
||||
\xf7x\xa1\xfb\xeeq\xa4^>\x94\xba\xb8yRF.\xcf\xa6.D\xa0Nw\x18C\xad\xb2\x19\
|
||||
\x9f\x0f\xca\x165\xd1V\xed\xebZj\x92\xc2\\\x04\xec\x02\xd5\x8a\x89\xb7\xd4\
|
||||
\x97n\xa8\xe3?\x0f\x86\x08\x19dNP\x00\xf0\x96\xd0\x7f\xd0\t\x84\x0c(U-\x0eK&\
|
||||
\xd3P\x8bz\xcdV6 \x8a\xed\x86\x99f\xe9\x00{\xe6\xb0\x13\xc2\xa0\xd3\xd7\t\
|
||||
\x84\x9f\x10\xec\x9dTp\x1d\xb1=A\xa9j\x01\xc4\xb1\x01&\xfe\x9a~\x1d\xe0:Zu\
|
||||
\x7f\xdb\x05@J/!(\xd6\x1bL\xde\xec\xcd\x00!\x03\xa6!\x1c\x9dVR\x9d\xdf\xe5\
|
||||
\x96\x04\xd1au\xd3\xab3\xef\x9f_f\x03\xa2\xa5\x15\xeb\x8d\xc4\xc36\xe7\x18 \
|
||||
\xa5G\xaf\xd9J\xb8f\xcd\xfc\xb3\x0c#\x97\xff\xb58\xadr\x7f\xfa\xfd\x1f\x80/\
|
||||
\x04\x1f\x8fW\x0e^\xc3\x12\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
|
||||
|
||||
def getTextBitmap():
|
||||
@@ -1356,12 +1451,20 @@ def getZoomInData():
|
||||
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\x00wIDAT8\x8d\xa5\x93Q\x12\x80 \x08D\xb5\xe9X\xee\xe9\xb7{\xd5Gc\xa9\
|
||||
\xacX\xca\x1f\xa0\x8fE0\x92<\xc3\x82\xed*\x08\xa0\xf2I~\x07\x000\x17T,\xdb\
|
||||
\xd6;\x08\xa4\x00\xa4GA\xab\xca\x00\xbc*\x1eD\xb4\x90\xa4O\x1e\xe3\x16f\xcc(\
|
||||
\xc8\x95F\x95\x8d\x02\xef\xa1n\xa0\xce\xc5v\x91zc\xacU\xbey\x03\xf0.\xa8\xb8\
|
||||
\x04\x8c\xac\x04MM\xa1lA\xfe\x85?\x90\xe5=X\x06\\\xebCA\xb3Q\xf34\x14\x00\
|
||||
\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x01TIDAT8\x8d\x8d\x93\xbbJ\x03A\x14\x86\xbf\xd9,\xc6\xd8E%`)VF[{\xc1v\
|
||||
\xf1\x82\x8f\xb0\xb94\xda\xa5\x13\x11\x8b`\xa9h\x10F\xe3#H.\xa6\x15\xccKhg\
|
||||
\x10\xc1B\x8bTF\x90\xc0X\x8c3\xbb\xd9\xcdF\x7f\x18\xf6\xec\x9cs\xbe\xfd\xe70\
|
||||
+\x84\x93"\xacb\xc1W\xe1\xf7\xeb\xfa\x8d`\x82\xdcXcI\x8e\x02AM\x02\t\xe1\xa4\
|
||||
(\x16|uz)y\x19\xc0\xc9\xdd;\x99\xee!\x00\xd9\xbd\x00\xd6\xaf\x95\xc7B\xac\
|
||||
\x03\xd3\x1c\xd6\xc2t\x10\xf7\x13\x8e\xe0\x14\x0b\xbe\xa2$m\xf3\xca\xea\xacM\
|
||||
\xe6\xd2\xc1\xcaWdl>#\x0e\x8c\xed\xe7n\x90|\xa8\x96m\xbc~ y\x04Z\xcd\x86\xda\
|
||||
\xda\xde\xb1Gq\x00\xb2S\t\xfeB\x9aK\xa8\xb1\x0e\xf2\x15I.\xad\x0bo\x8f\xf4\
|
||||
\x97\xab\xe7z\x88\x1f\xdf\xf0\xfa9\x1e\xe0x\x9eG\xbf\x16X\xcd\xb8Ar\xc6\xd5\
|
||||
\x0b4\xd4\xf3\xbcd\x07F_\xc3 \x1e\x0c\xa3Y\x08\x9f\x1f~\xefA\xab\xd9P\x9dN\
|
||||
\x07\x80\xddcI\xc6\x85\xf9\xb4.8\xabhwK\xbd+6\x16\xf5\xdeZ=%F\x00\xa0\xa7\
|
||||
\x0b`@F\xc6\xf6\xd3\xc5&@\x0c"\xa2\xff\x82\x01\x85-\xb7\x9a\re\x00QH\x0c0N\
|
||||
\x06\x1a\x85\xbcym}\x0f\xfe\x92\x19\xdc\xf2~\xdb\xee\xdd\xf7\xf4\xf3_\x0e\
|
||||
\xa2N\xc2\xfa\x01MYp\xbc\xe4a\x0f\xa9\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getZoomInBitmap():
|
||||
return BitmapFromImage(getZoomInImage())
|
||||
@@ -1375,11 +1478,20 @@ def getZoomOutData():
|
||||
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\x00qIDAT8\x8d\xa5\x92Q\x0e\xc0 \x08C-z\xff\x13O\xd9\xd7\x16"\x05\x8d\
|
||||
\xf6O\xa2\x8f"\x05\xa4\x96\x1b5V\xd4\xd1\xd5\x9e!\x15\xdb\x00\x1d]\xe7\x07\
|
||||
\xac\xf6Iv.B*fW\x0e\x90u\xc9 d\x84\x87v\x82\xb4\xf5\x08\'r\x0e\xa2N\x91~\x07\
|
||||
\xd9G\x95\xe2W\xeb\x00\x19\xc4\xd6\\FX\x12\xa3 \xb1:\x05\xacdAG[\xb0y9r`u\
|
||||
\x9d\x83k\xc0\x0b#3@0A\x0c"\x93\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x01RIDAT8\x8d\x8d\x93\xbbJ\x03A\x14\x86\xbf\xd9\x04\x93\x90J\x0cj#Dl\
|
||||
\xf4\x01\xec\x05\xdb\xc5\x0b>B\x92]\x1b+\xed,D\xb0\xb4\x08\x9afc|\x04\xc9\
|
||||
\x85\xb4>\x84\x95`\x93\x80`\x15\xd8*\x98\x84\xc0X\xcc\xce\xde7\xf8\xc30\x97=\
|
||||
\xf3\xcd\x7f\xce\xcc\na\xe4\x08\xabQ\xaf\xc9\xf0\xfc\xa5\xf3*X\xa1|b\xa3\xe5\
|
||||
D\x81 W\x81\x840r4\xea5\xf9\xf0\xe40Y@\xf3+\xf8\xb8\xbe\x16\x8c\xdd\x96\x9d\
|
||||
\n1\xf4\xc0\xdf\xdc\xb6\x01\xa8\xca\x19[\x05\xfc\x96%aY\x96\x0c\xdb\xae\xca\
|
||||
\x99\xea7\x8b\x91@w.\xf9x\xbcL\xb8\xf0k\xa0O\x1e{\xd31Q\x1d\xdd\xaaC\xfa\xbd\
|
||||
\xae<=;\xf7!F<\xd7,md\xc4\xf8\x0e\xf6\xaf\x1d\xb6\x8b*p\xa7\x0c\x95\xd0\x86\
|
||||
\xc9\x02\xbe\xa7\xe9\x00\xc34M\xdc\x96MA\xa8[,y\xc8r>h\x00ow6\xa6if;\x98K\
|
||||
\x95\xd6\xef\x12(\xc0t\x99~b8\x7f\xf0\xdeA\xbf\xd7\x95\xc3\xe1\x10\x80\x8b{\
|
||||
\x87R\x1e*\xde\xd55oTq\xf7Fm\x8ew\xd5\xdaa\'\'"\x00P\xd5\x05\xd0 -m\xfb\xf3\
|
||||
\xf9\x04 \x01\x11\xf1\x7fA\x83\xc2\x96\xfb\xbd\xae\xd4\x808$\x01H\x93\x86\
|
||||
\xc6!?\xe6 x\xca\xab\xa4\x0bwp5\xf0\xd7\xdeG\xaa\xff\x97\x83\xb8\x93\xb0\xfe\
|
||||
\x00\xc3\xa8ov\xfd\xe4\x9c\xa2\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
|
||||
def getZoomOutBitmap():
|
||||
|
||||
@@ -99,6 +99,7 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
_("Comment"),
|
||||
_("SVN Log Message"))
|
||||
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
retcode = True
|
||||
message = dlg.GetValue()
|
||||
@@ -141,11 +142,12 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
dlg.Fit()
|
||||
dlg.Layout()
|
||||
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
retcode = True
|
||||
username = usernameTxt.GetValue().strip()
|
||||
password = passwordTxt.GetValue()
|
||||
save = savePasswordCheckBox.IsChecked()
|
||||
save = savePasswordCheckbox.IsChecked()
|
||||
else:
|
||||
retcode = False
|
||||
username = None
|
||||
@@ -195,6 +197,7 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
acceptedFailures = 0
|
||||
save = False
|
||||
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
cert = certRadio.GetStringSelection()
|
||||
if cert == _("Accept Always"):
|
||||
@@ -206,6 +209,7 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
acceptedFailures = trustDict.get('failures')
|
||||
save = False
|
||||
|
||||
dlg.Destroy()
|
||||
return retcode, acceptedFailures, save
|
||||
|
||||
|
||||
@@ -238,10 +242,11 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
dlg.Fit()
|
||||
dlg.Layout()
|
||||
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
retcode = True
|
||||
password = passwordTxt.GetValue()
|
||||
save = savePasswordCheckBox.IsChecked()
|
||||
save = savePasswordCheckbox.IsChecked()
|
||||
else:
|
||||
retcode = False
|
||||
password = None
|
||||
@@ -253,10 +258,11 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
|
||||
def SSLClientCert(self):
|
||||
dlg = wx.FileDialog(wx.GetApp().GetTopWindow(),
|
||||
message="Choose certificate", defaultDir=os.getcwd(),
|
||||
style=wx.OPEN|wx.CHANGE_DIR
|
||||
message="Choose certificate",
|
||||
style=wx.OPEN|wx.FILE_MUST_EXIST|wx.CHANGE_DIR
|
||||
)
|
||||
|
||||
# dlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
retcode = True
|
||||
certfile = dlg.GetPath()
|
||||
@@ -321,8 +327,14 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
if id == SVNService.SVN_UPDATE_ID:
|
||||
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
|
||||
|
||||
filenames = self.GetCurrentDocuments()[:]
|
||||
filenames.sort(self.BasenameCaseInsensitiveCompare)
|
||||
filenames = self.GetCurrentDocuments()
|
||||
if filenames:
|
||||
filenames = filenames[:]
|
||||
filenames.sort(self.BasenameCaseInsensitiveCompare)
|
||||
else:
|
||||
folderPath = self.GetCurrentFolder()
|
||||
if folderPath:
|
||||
filenames = [folderPath]
|
||||
|
||||
messageService = wx.GetApp().GetService(MessageService.MessageService)
|
||||
messageService.ShowWindow()
|
||||
@@ -346,7 +358,10 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
_("Updated file '%s' is currently open. Close it?") % os.path.basename(filename),
|
||||
_("Close File"),
|
||||
wx.YES_NO|wx.ICON_QUESTION)
|
||||
if yesNoMsg.ShowModal() == wx.ID_YES:
|
||||
yesNoMsg.CenterOnParent()
|
||||
status = yesNoMsg.ShowModal()
|
||||
yesNoMsg.Destroy()
|
||||
if status == wx.ID_YES:
|
||||
doc.DeleteAllViews()
|
||||
break
|
||||
else:
|
||||
@@ -377,8 +392,8 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
view.ClearLines()
|
||||
view.AddLines(_("SVN Update:\n"))
|
||||
|
||||
projects = self.GetCurrentProjects()
|
||||
for project in projects:
|
||||
project = self.GetCurrentProject()
|
||||
if project:
|
||||
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
|
||||
for doc in openDocs:
|
||||
if doc.GetFilename() == project:
|
||||
@@ -400,7 +415,9 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
_("Updated file '%s' is currently open. Close it?") % os.path.basename(filename),
|
||||
_("Close File"),
|
||||
wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
|
||||
yesNoMsg.CenterOnParent()
|
||||
status = yesNoMsg.ShowModal()
|
||||
yesNoMsg.Destroy()
|
||||
if status == wx.ID_YES:
|
||||
doc.DeleteAllViews()
|
||||
elif status == wx.ID_NO:
|
||||
@@ -428,8 +445,8 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
|
||||
elif id == SVNService.SVN_CHECKIN_ALL_ID:
|
||||
filenames = []
|
||||
projects = self.GetCurrentProjects()
|
||||
for project in projects:
|
||||
project = self.GetCurrentProject()
|
||||
if project:
|
||||
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
|
||||
for doc in openDocs:
|
||||
if doc.GetFilename() == project:
|
||||
@@ -447,7 +464,9 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
_("'%s' has unsaved modifications. Save it before commit?") % os.path.basename(filename),
|
||||
_("SVN Commit"),
|
||||
wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
|
||||
yesNoMsg.CenterOnParent()
|
||||
status = yesNoMsg.ShowModal()
|
||||
yesNoMsg.Destroy()
|
||||
if status == wx.ID_YES:
|
||||
doc.Save()
|
||||
elif status == wx.ID_NO:
|
||||
@@ -474,11 +493,12 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
fileList.Check(i, True)
|
||||
sizer.Add(fileList, 0, wx.EXPAND|wx.TOP, HALF_SPACE)
|
||||
|
||||
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
buttonSizer = wx.StdDialogButtonSizer()
|
||||
okBtn = wx.Button(dlg, wx.ID_OK)
|
||||
okBtn.SetDefault()
|
||||
buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE)
|
||||
buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0)
|
||||
buttonSizer.AddButton(okBtn)
|
||||
buttonSizer.AddButton(wx.Button(dlg, wx.ID_CANCEL))
|
||||
buttonSizer.Realize()
|
||||
|
||||
contentSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
contentSizer.Add(sizer, 0, wx.ALL, SPACE)
|
||||
@@ -488,6 +508,7 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
dlg.Fit()
|
||||
dlg.Layout()
|
||||
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
|
||||
|
||||
@@ -544,7 +565,9 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
_("'%s' has unsaved modifications. Save it before commit?") % os.path.basename(filename),
|
||||
_("SVN Commit"),
|
||||
wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
|
||||
yesNoMsg.CenterOnParent()
|
||||
status = yesNoMsg.ShowModal()
|
||||
yesNoMsg.Destroy()
|
||||
if status == wx.ID_YES:
|
||||
doc.Save()
|
||||
elif status == wx.ID_NO:
|
||||
@@ -571,12 +594,13 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
fileList.Check(i, True)
|
||||
sizer.Add(fileList, 0, wx.EXPAND|wx.TOP, HALF_SPACE)
|
||||
|
||||
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
buttonSizer = wx.StdDialogButtonSizer()
|
||||
okBtn = wx.Button(dlg, wx.ID_OK)
|
||||
okBtn.SetDefault()
|
||||
buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE)
|
||||
buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0)
|
||||
|
||||
buttonSizer.AddButton(okBtn)
|
||||
buttonSizer.AddButton(wx.Button(dlg, wx.ID_CANCEL))
|
||||
buttonSizer.Realize()
|
||||
|
||||
contentSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
contentSizer.Add(sizer, 0, wx.ALL, SPACE)
|
||||
contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE)
|
||||
@@ -585,6 +609,7 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
dlg.Fit()
|
||||
dlg.Layout()
|
||||
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
|
||||
|
||||
@@ -654,11 +679,11 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
dir = localPath.GetValue()
|
||||
if len(dir):
|
||||
dirDlg.SetPath(dir)
|
||||
dirDlg.CenterOnParent()
|
||||
if dirDlg.ShowModal() == wx.ID_OK:
|
||||
localPath.SetValue(dirDlg.GetPath())
|
||||
localPath.SetToolTipString(localPath.GetValue())
|
||||
localPath.SetInsertionPointEnd()
|
||||
|
||||
dirDlg.Destroy()
|
||||
wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton)
|
||||
|
||||
@@ -667,11 +692,12 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
sizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE)
|
||||
gridSizer.Add(sizer, 0)
|
||||
|
||||
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
buttonSizer = wx.StdDialogButtonSizer()
|
||||
okBtn = wx.Button(dlg, wx.ID_OK)
|
||||
okBtn.SetDefault()
|
||||
buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE)
|
||||
buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0)
|
||||
buttonSizer.AddButton(okBtn)
|
||||
buttonSizer.AddButton(wx.Button(dlg, wx.ID_CANCEL))
|
||||
buttonSizer.Realize()
|
||||
|
||||
contentSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
contentSizer.Add(gridSizer, 0, wx.ALL, SPACE)
|
||||
@@ -681,6 +707,7 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
dlg.Fit()
|
||||
dlg.Layout()
|
||||
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
|
||||
|
||||
@@ -737,7 +764,10 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
_("Reverted file '%s' is currently open. Close it?") % os.path.basename(doc.GetFilename()),
|
||||
_("Close File"),
|
||||
wx.YES_NO|wx.ICON_QUESTION)
|
||||
if yesNoMsg.ShowModal() == wx.ID_YES:
|
||||
yesNoMsg.CenterOnParent()
|
||||
status = yesNoMsg.ShowModal()
|
||||
yesNoMsg.Destroy()
|
||||
if status == wx.ID_YES:
|
||||
doc.DeleteAllViews()
|
||||
|
||||
except pysvn.ClientError, e:
|
||||
@@ -819,8 +849,7 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
def ProcessUpdateUIEvent(self, event):
|
||||
id = event.GetId()
|
||||
|
||||
if id in [SVNService.SVN_UPDATE_ID,
|
||||
SVNService.SVN_CHECKIN_ID,
|
||||
if id in [SVNService.SVN_CHECKIN_ID,
|
||||
SVNService.SVN_REVERT_ID,
|
||||
SVNService.SVN_ADD_ID,
|
||||
SVNService.SVN_DELETE_ID]:
|
||||
@@ -830,13 +859,20 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
event.Enable(False)
|
||||
return True
|
||||
|
||||
elif id == SVNService.SVN_UPDATE_ID:
|
||||
if self.GetCurrentDocuments() or self.GetCurrentFolder():
|
||||
event.Enable(True)
|
||||
else:
|
||||
event.Enable(False)
|
||||
return True
|
||||
|
||||
elif id == SVNService.SVN_CHECKOUT_ID:
|
||||
event.Enable(True)
|
||||
return True
|
||||
|
||||
elif (id == SVNService.SVN_UPDATE_ALL_ID
|
||||
or id == SVNService.SVN_CHECKIN_ALL_ID):
|
||||
if self.GetCurrentProjects():
|
||||
if self.GetCurrentProject():
|
||||
event.Enable(True)
|
||||
else:
|
||||
event.Enable(False)
|
||||
@@ -845,27 +881,20 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
return False
|
||||
|
||||
|
||||
def GetCurrentProjects(self):
|
||||
def GetCurrentProject(self):
|
||||
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
|
||||
if projectService:
|
||||
projView = projectService.GetView()
|
||||
|
||||
if projView.HasFocus():
|
||||
filenames = projView.GetSelectedProjects()
|
||||
if len(filenames):
|
||||
return filenames
|
||||
else:
|
||||
return None
|
||||
return projView.GetSelectedProject()
|
||||
return None
|
||||
|
||||
|
||||
def GetCurrentDocuments(self):
|
||||
|
||||
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
|
||||
if projectService:
|
||||
projView = projectService.GetView()
|
||||
|
||||
if projView.HasFocus():
|
||||
if projView.FilesHasFocus():
|
||||
filenames = projView.GetSelectedFiles()
|
||||
if len(filenames):
|
||||
return filenames
|
||||
@@ -881,6 +910,19 @@ class SVNService(wx.lib.pydocview.DocService):
|
||||
return filenames
|
||||
|
||||
|
||||
def GetCurrentFolder(self):
|
||||
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
|
||||
if projectService:
|
||||
projView = projectService.GetView()
|
||||
|
||||
if projView.FilesHasFocus():
|
||||
folderPath = projView.GetSelectedPhysicalFolder()
|
||||
if folderPath:
|
||||
return folderPath
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def BasenameCaseInsensitiveCompare(self, s1, s2):
|
||||
s1L = os.path.basename(s1).lower()
|
||||
s2L = os.path.basename(s2).lower()
|
||||
@@ -903,6 +945,7 @@ class SVNOptionsPanel(wx.Panel):
|
||||
|
||||
borderSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5)
|
||||
sizer.AddGrowableCol(1, 1)
|
||||
|
||||
sizer.Add(wx.StaticText(self, -1, _("SVN Config Dir:")), 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
|
||||
@@ -919,18 +962,18 @@ class SVNOptionsPanel(wx.Panel):
|
||||
dir = self._svnConfigDir.GetValue()
|
||||
if len(dir):
|
||||
dirDlg.SetPath(dir)
|
||||
dirDlg.CenterOnParent()
|
||||
if dirDlg.ShowModal() == wx.ID_OK:
|
||||
self._svnConfigDir.SetValue(dirDlg.GetPath())
|
||||
self._svnConfigDir.SetToolTipString(self._svnConfigDir.GetValue())
|
||||
self._svnConfigDir.SetInsertionPointEnd()
|
||||
|
||||
dirDlg.Destroy()
|
||||
wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton)
|
||||
|
||||
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsizer.Add(self._svnConfigDir, 1, wx.EXPAND)
|
||||
hsizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE)
|
||||
sizer.Add(hsizer, 0)
|
||||
sizer.Add(hsizer, 0, wx.EXPAND)
|
||||
|
||||
|
||||
svnUrlList = ReadSvnUrlList()
|
||||
@@ -941,7 +984,7 @@ class SVNOptionsPanel(wx.Panel):
|
||||
self._svnURLCombobox.SetStringSelection(svnUrlList[0])
|
||||
else:
|
||||
self._svnURLCombobox.SetToolTipString(_("Set Repository URL"))
|
||||
sizer.Add(self._svnURLCombobox, 0)
|
||||
sizer.Add(self._svnURLCombobox, 0, wx.EXPAND)
|
||||
|
||||
|
||||
sizer.Add(wx.StaticText(self, -1, _("SVN_SSH:")), 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
@@ -956,6 +999,7 @@ class SVNOptionsPanel(wx.Panel):
|
||||
|
||||
def OnBrowseFileButton(event):
|
||||
dirDlg = wx.FileDialog(self, _("Choose a file:"), style=wx.OPEN|wx.CHANGE_DIR)
|
||||
# dirDlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog
|
||||
if dirDlg.ShowModal() == wx.ID_OK:
|
||||
self._svnSSH.SetValue(dirDlg.GetPath())
|
||||
self._svnSSH.SetToolTipString(self._svnSSH.GetValue())
|
||||
@@ -966,15 +1010,19 @@ class SVNOptionsPanel(wx.Panel):
|
||||
hsizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsizer.Add(self._svnSSH, 1, wx.EXPAND)
|
||||
hsizer.Add(findSSHButton, 0, wx.LEFT, HALF_SPACE)
|
||||
sizer.Add(hsizer, 0)
|
||||
sizer.Add(hsizer, 0, wx.EXPAND)
|
||||
|
||||
|
||||
borderSizer.Add(sizer, 0, wx.ALL, SPACE)
|
||||
borderSizer.Add(sizer, 0, wx.ALL|wx.EXPAND, SPACE)
|
||||
self.SetSizer(borderSizer)
|
||||
self.Layout()
|
||||
parent.AddPage(self, _("SVN"))
|
||||
|
||||
|
||||
def GetIcon(self):
|
||||
return wx.NullIcon
|
||||
|
||||
|
||||
def OnOK(self, optionsDialog):
|
||||
config = wx.ConfigBase_Get()
|
||||
|
||||
|
||||
@@ -106,6 +106,8 @@ class ServiceView(wx.EvtHandler):
|
||||
if (self._service.GetEmbeddedWindowLocation() == wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM):
|
||||
if ServiceView.bottomTab == None:
|
||||
ServiceView.bottomTab = wx.Notebook(frame, wx.NewId(), (0,0), (100,100), wx.LB_DEFAULT, "Bottom Tab")
|
||||
wx.EVT_RIGHT_DOWN(ServiceView.bottomTab, self.OnNotebookRightClick)
|
||||
wx.EVT_MIDDLE_DOWN(ServiceView.bottomTab, self.OnNotebookMiddleClick)
|
||||
sizer.Add(ServiceView.bottomTab, 1, wx.TOP|wx.EXPAND, 4)
|
||||
def OnFrameResize(event):
|
||||
ServiceView.bottomTab.SetSize(ServiceView.bottomTab.GetParent().GetSize())
|
||||
@@ -125,10 +127,46 @@ class ServiceView(wx.EvtHandler):
|
||||
sizer.Add(self._control, 1, wx.EXPAND, 0)
|
||||
frame.SetSizer(sizer)
|
||||
frame.Layout()
|
||||
|
||||
self.Activate()
|
||||
return True
|
||||
|
||||
|
||||
def OnNotebookMiddleClick(self, event):
|
||||
index, type = ServiceView.bottomTab.HitTest(event.GetPosition())
|
||||
# 0 tab is always message. This code assumes the rest are run/debug windows
|
||||
if index > 0:
|
||||
page = ServiceView.bottomTab.GetPage(index)
|
||||
if hasattr(page, 'StopAndRemoveUI'):
|
||||
page.StopAndRemoveUI(event)
|
||||
|
||||
|
||||
def OnNotebookRightClick(self, event):
|
||||
index, type = ServiceView.bottomTab.HitTest(event.GetPosition())
|
||||
menu = wx.Menu()
|
||||
x, y = event.GetX(), event.GetY()
|
||||
# 0 tab is always message. This code assumes the rest are run/debug windows
|
||||
if index > 0:
|
||||
page = ServiceView.bottomTab.GetPage(index)
|
||||
id = wx.NewId()
|
||||
menu.Append(id, _("Close"))
|
||||
def OnRightMenuSelect(event):
|
||||
if hasattr(page, 'StopAndRemoveUI'):
|
||||
page.StopAndRemoveUI(event)
|
||||
wx.EVT_MENU(ServiceView.bottomTab, id, OnRightMenuSelect)
|
||||
if ServiceView.bottomTab.GetPageCount() > 1:
|
||||
id = wx.NewId()
|
||||
menu.Append(id, _("Close All but \"Message\""))
|
||||
def OnRightMenuSelect(event):
|
||||
for i in range(ServiceView.bottomTab.GetPageCount()-1, 0, -1): # Go from len-1 to 1
|
||||
page = ServiceView.bottomTab.GetPage(i)
|
||||
if hasattr(page, 'StopAndRemoveUI'):
|
||||
page.StopAndRemoveUI(event)
|
||||
wx.EVT_MENU(ServiceView.bottomTab, id, OnRightMenuSelect)
|
||||
|
||||
ServiceView.bottomTab.PopupMenu(menu, wx.Point(x, y))
|
||||
menu.Destroy()
|
||||
|
||||
|
||||
def OnCloseWindow(self, event):
|
||||
frame = self.GetFrame()
|
||||
config = wx.ConfigBase_Get()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Name: UICommon.py
|
||||
# Purpose: Shared UI stuff
|
||||
#
|
||||
# Author: Matt Fryer
|
||||
# Author: Matt Fryer, Morgan Hua
|
||||
#
|
||||
# Created: 3/10/05
|
||||
# CVS-ID: $Id$
|
||||
@@ -13,18 +13,67 @@
|
||||
import os
|
||||
import os.path
|
||||
import wx
|
||||
import string
|
||||
import ProjectEditor
|
||||
import activegrid.util as utillib
|
||||
import activegrid.util.sysutils as sysutils
|
||||
import activegrid.util.strutils as strutils
|
||||
import activegrid.util.appdirs as appdirs
|
||||
_ = wx.GetTranslation
|
||||
|
||||
def CreateDirectoryControl( parent, fileLabel, dirLabel, fileExtension, startingName="", startingDirectory=""):
|
||||
def CreateDirectoryControl( parent, fileLabel=_("File Name:"), dirLabel=_("Directory"), fileExtension="*", startingName="", startingDirectory=None, choiceDirs=None, appDirDefaultStartDir=False, returnAll=False):
|
||||
|
||||
if not choiceDirs:
|
||||
choiceDirs = []
|
||||
projectDirs = []
|
||||
|
||||
if appDirDefaultStartDir:
|
||||
appDirectory = wx.ConfigBase_Get().Read(ProjectEditor.PROJECT_DIRECTORY_KEY, ProjectEditor.NEW_PROJECT_DIRECTORY_DEFAULT)
|
||||
else:
|
||||
appDirectory = wx.ConfigBase_Get().Read(ProjectEditor.PROJECT_DIRECTORY_KEY)
|
||||
if appDirectory:
|
||||
choiceDirs.append(appDirectory)
|
||||
if appDirDefaultStartDir and not startingDirectory:
|
||||
startingDirectory = appDirectory
|
||||
|
||||
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
|
||||
if projectService:
|
||||
curProjectDoc = projectService.GetCurrentProject()
|
||||
if curProjectDoc:
|
||||
homeDir = curProjectDoc.GetAppDocMgr().homeDir
|
||||
if homeDir and (homeDir not in choiceDirs):
|
||||
choiceDirs.append(homeDir)
|
||||
if not startingDirectory:
|
||||
startingDirectory = homeDir
|
||||
|
||||
for projectDoc in projectService.GetOpenProjects():
|
||||
if projectDoc == curProjectDoc:
|
||||
continue
|
||||
homeDir = projectDoc.GetAppDocMgr().homeDir
|
||||
if homeDir and (homeDir not in projectDirs):
|
||||
projectDirs.append(homeDir)
|
||||
projectDirs.sort(CaseInsensitiveCompare)
|
||||
for projectDir in projectDirs:
|
||||
if projectDir not in choiceDirs:
|
||||
choiceDirs.append(projectDir)
|
||||
|
||||
if startingDirectory and (startingDirectory not in choiceDirs):
|
||||
choiceDirs.insert(0, startingDirectory)
|
||||
|
||||
if os.getcwd() not in choiceDirs:
|
||||
choiceDirs.append(os.getcwd())
|
||||
if appdirs.documents_folder not in choiceDirs:
|
||||
choiceDirs.append(appdirs.documents_folder)
|
||||
|
||||
if not startingDirectory:
|
||||
startingDirectory = os.getcwd()
|
||||
|
||||
nameControl = wx.TextCtrl(parent, -1, startingName, size=(-1,-1))
|
||||
nameLabelText = wx.StaticText(parent, -1, fileLabel)
|
||||
dirLabelText = wx.StaticText(parent, -1, dirLabel)
|
||||
dirControl = wx.TextCtrl(parent, -1, startingDirectory, size=(-1,-1))
|
||||
dirControl = wx.ComboBox(parent, -1, startingDirectory, size=(-1,-1), choices=choiceDirs)
|
||||
dirControl.SetToolTipString(startingDirectory)
|
||||
button = wx.Button(parent, -1, _("Browse..."), size=(60,-1))
|
||||
button = wx.Button(parent, -1, _("Browse..."))
|
||||
allControls = [nameControl, nameLabelText, dirLabelText, dirControl, button]
|
||||
|
||||
def OnFindDirClick(event):
|
||||
name = ""
|
||||
@@ -35,54 +84,210 @@ def CreateDirectoryControl( parent, fileLabel, dirLabel, fileExtension, starting
|
||||
name = nameCtrlValue
|
||||
else:
|
||||
name = _("%s.%s") % (nameCtrlValue, fileExtension)
|
||||
path = wx.FileSelector(_("Choose a filename and directory"),
|
||||
"",
|
||||
"%s" % name,
|
||||
wildcard=_("*.%s") % fileExtension ,
|
||||
flags=wx.SAVE,
|
||||
parent=parent)
|
||||
|
||||
dlg = wx.FileDialog(parent, _("Choose a filename and directory"),
|
||||
defaultDir = dirControl.GetValue().strip(),
|
||||
defaultFile = name,
|
||||
wildcard= "*.%s" % fileExtension,
|
||||
style=wx.SAVE|wx.CHANGE_DIR)
|
||||
|
||||
if dlg.ShowModal() != wx.ID_OK:
|
||||
dlg.Destroy()
|
||||
return
|
||||
path = dlg.GetPath()
|
||||
dlg.Destroy()
|
||||
|
||||
if path:
|
||||
dir, filename = os.path.split(path)
|
||||
if dirControl.FindString(dir) == wx.NOT_FOUND:
|
||||
dirControl.Insert(dir, 0)
|
||||
dirControl.SetValue(dir)
|
||||
dirControl.SetToolTipString(dir)
|
||||
nameControl.SetValue(filename)
|
||||
|
||||
parent.Bind(wx.EVT_BUTTON, OnFindDirClick, button)
|
||||
|
||||
def Validate(allowOverwriteOnPrompt=False):
|
||||
if nameControl.GetValue() == "":
|
||||
wx.MessageBox(_("Please provide a filename."), _("Provide a Filename"))
|
||||
def Validate(allowOverwriteOnPrompt=False, infoString='', noFirstCharDigit=False):
|
||||
projName = nameControl.GetValue().strip()
|
||||
if projName == "":
|
||||
wx.MessageBox(_("Please provide a %sfile name.") % infoString, _("Provide a File Name"))
|
||||
return False
|
||||
if nameControl.GetValue().find(' ') != -1:
|
||||
wx.MessageBox(_("Please provide a filename that does not contains spaces."), _("Spaces in Filename"))
|
||||
if noFirstCharDigit and projName[0].isdigit():
|
||||
wx.MessageBox(_("File name cannot start with a number. Please enter a different name."), _("Invalid File Name"))
|
||||
return False
|
||||
if projName.find(' ') != -1:
|
||||
wx.MessageBox(_("Please provide a %sfile name that does not contains spaces.") % infoString, _("Spaces in File Name"))
|
||||
return False
|
||||
if not os.path.exists(dirControl.GetValue()):
|
||||
wx.MessageBox(_("That directory does not exist. Please choose an existing directory."), _("Provide a Valid Directory"))
|
||||
wx.MessageBox(_("That %sdirectory does not exist. Please choose an existing directory.") % infoString, _("Provide a Valid Directory"))
|
||||
return False
|
||||
|
||||
filePath = os.path.join(dirControl.GetValue(), MakeNameEndInExtension(nameControl.GetValue(), "." + fileExtension))
|
||||
filePath = os.path.join(dirControl.GetValue(), MakeNameEndInExtension(projName, "." + fileExtension))
|
||||
if os.path.exists(filePath):
|
||||
if allowOverwriteOnPrompt:
|
||||
res = wx.MessageBox(_("That file already exists. Would you like to overwrite it."), "File Exists", style=wx.YES_NO|wx.NO_DEFAULT)
|
||||
res = wx.MessageBox(_("That %sfile already exists. Would you like to overwrite it.") % infoString, "File Exists", style=wx.YES_NO|wx.NO_DEFAULT)
|
||||
return (res == wx.YES)
|
||||
else:
|
||||
wx.MessageBox(_("That file already exists. Please choose a different name."), "File Exists")
|
||||
wx.MessageBox(_("That %sfile already exists. Please choose a different name.") % infoString, "File Exists")
|
||||
return False
|
||||
return True
|
||||
HALF_SPACE = 5
|
||||
flexGridSizer = wx.FlexGridSizer(cols = 3, vgap = HALF_SPACE, hgap = HALF_SPACE)
|
||||
flexGridSizer.AddGrowableCol(1,1)
|
||||
flexGridSizer.Add(nameLabelText, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.TOP|wx.RIGHT, HALF_SPACE)
|
||||
flexGridSizer.Add(nameLabelText, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
flexGridSizer.Add(nameControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
|
||||
flexGridSizer.Add(button, flag=wx.ALIGN_RIGHT|wx.LEFT, border=HALF_SPACE)
|
||||
|
||||
flexGridSizer.Add(dirLabelText, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.TOP|wx.RIGHT, border=HALF_SPACE)
|
||||
flexGridSizer.Add(dirControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border=HALF_SPACE)
|
||||
flexGridSizer.Add(dirLabelText, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
|
||||
flexGridSizer.Add(dirControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
|
||||
flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0)
|
||||
return nameControl, dirControl, flexGridSizer, Validate
|
||||
if returnAll:
|
||||
return nameControl, dirControl, flexGridSizer, Validate, allControls
|
||||
else:
|
||||
return nameControl, dirControl, flexGridSizer, Validate
|
||||
|
||||
def AddFilesToCurrentProject(paths, save=False):
|
||||
|
||||
def CreateDirectoryOnlyControl( parent, dirLabel=_("Location:"), startingDirectory=None, choiceDirs=None, appDirDefaultStartDir=False):
|
||||
|
||||
if not choiceDirs:
|
||||
choiceDirs = []
|
||||
projectDirs = []
|
||||
|
||||
if appDirDefaultStartDir:
|
||||
appDirectory = wx.ConfigBase_Get().Read(ProjectEditor.PROJECT_DIRECTORY_KEY, ProjectEditor.NEW_PROJECT_DIRECTORY_DEFAULT)
|
||||
else:
|
||||
appDirectory = wx.ConfigBase_Get().Read(ProjectEditor.PROJECT_DIRECTORY_KEY)
|
||||
if appDirectory:
|
||||
choiceDirs.append(appDirectory)
|
||||
if appDirDefaultStartDir and not startingDirectory:
|
||||
startingDirectory = appDirectory
|
||||
|
||||
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
|
||||
if projectService:
|
||||
curProjectDoc = projectService.GetCurrentProject()
|
||||
if curProjectDoc:
|
||||
homeDir = curProjectDoc.GetAppDocMgr().homeDir
|
||||
if homeDir and (homeDir not in choiceDirs):
|
||||
choiceDirs.append(homeDir)
|
||||
if not startingDirectory:
|
||||
startingDirectory = homeDir
|
||||
|
||||
for projectDoc in projectService.GetOpenProjects():
|
||||
if projectDoc == curProjectDoc:
|
||||
continue
|
||||
homeDir = projectDoc.GetAppDocMgr().homeDir
|
||||
if homeDir and (homeDir not in projectDirs):
|
||||
projectDirs.append(homeDir)
|
||||
projectDirs.sort(CaseInsensitiveCompare)
|
||||
for projectDir in projectDirs:
|
||||
if projectDir not in choiceDirs:
|
||||
choiceDirs.append(projectDir)
|
||||
|
||||
if startingDirectory and (startingDirectory not in choiceDirs):
|
||||
choiceDirs.insert(0, startingDirectory)
|
||||
|
||||
if os.getcwd() not in choiceDirs:
|
||||
choiceDirs.append(os.getcwd())
|
||||
if appdirs.documents_folder not in choiceDirs:
|
||||
choiceDirs.append(appdirs.documents_folder)
|
||||
|
||||
|
||||
if not startingDirectory:
|
||||
startingDirectory = os.getcwd()
|
||||
|
||||
dirLabelText = wx.StaticText(parent, -1, dirLabel)
|
||||
dirControl = wx.ComboBox(parent, -1, startingDirectory, size=(-1,-1), choices=choiceDirs)
|
||||
dirControl.SetToolTipString(startingDirectory)
|
||||
button = wx.Button(parent, -1, _("Browse..."))
|
||||
|
||||
def OnFindDirClick(event):
|
||||
dlg = wx.DirDialog(wx.GetApp().GetTopWindow(),
|
||||
_("Choose a directory:"),
|
||||
defaultPath=dirControl.GetValue().strip(),
|
||||
style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON)
|
||||
dlg.CenterOnParent()
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
dir = dlg.GetPath()
|
||||
if dirControl.FindString(dir) == wx.NOT_FOUND:
|
||||
dirControl.Insert(dir, 0)
|
||||
dirControl.SetValue(dir)
|
||||
dirControl.SetToolTipString(dir)
|
||||
dlg.Destroy()
|
||||
|
||||
parent.Bind(wx.EVT_BUTTON, OnFindDirClick, button)
|
||||
|
||||
def Validate(allowOverwriteOnPrompt=False):
|
||||
dirName = dirControl.GetValue().strip()
|
||||
if dirName == "":
|
||||
wx.MessageBox(_("Please provide a directory."), _("Provide a Directory"))
|
||||
return False
|
||||
if not os.path.exists(dirName):
|
||||
wx.MessageBox(_("That directory does not exist. Please choose an existing directory."), _("Provide a Valid Directory"))
|
||||
return False
|
||||
return True
|
||||
|
||||
HALF_SPACE = 5
|
||||
flexGridSizer = wx.FlexGridSizer(cols = 3, vgap = HALF_SPACE, hgap = HALF_SPACE)
|
||||
flexGridSizer.AddGrowableCol(1,1)
|
||||
flexGridSizer.Add(dirLabelText, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.RIGHT, border=HALF_SPACE)
|
||||
flexGridSizer.Add(dirControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border=HALF_SPACE)
|
||||
flexGridSizer.Add(button, flag=wx.ALIGN_RIGHT|wx.LEFT, border=HALF_SPACE)
|
||||
|
||||
return dirControl, flexGridSizer, Validate
|
||||
|
||||
|
||||
def CreateNameOnlyControl( parent, fileLabel, startingName="", startingDirectoryControl=None):
|
||||
|
||||
fileLabelText = wx.StaticText(parent, -1, fileLabel)
|
||||
nameControl = wx.TextCtrl(parent, -1, startingName, size=(-1,-1))
|
||||
|
||||
def Validate(allowOverwriteOnPrompt=False, noFirstCharDigit=False):
|
||||
projName = nameControl.GetValue().strip()
|
||||
if projName == "":
|
||||
wx.MessageBox(_("Blank name. Please enter a valid name."), _("Project Name"))
|
||||
return False
|
||||
if noFirstCharDigit and projName[0].isdigit():
|
||||
wx.MessageBox(_("Name cannot start with a number. Please enter a valid name."), _("Project Name"))
|
||||
return False
|
||||
if projName.find(' ') != -1:
|
||||
wx.MessageBox(_("Spaces in name. Name cannot have spaces.") % infoString, _("Project Name"))
|
||||
return False
|
||||
path = os.path.join(startingDirectoryControl.GetValue().strip(), projName)
|
||||
if os.path.exists(path):
|
||||
if os.path.isdir(path):
|
||||
message = _("Project '%s' already exists. Would you like to overwrite the contents of the project?") % projName
|
||||
else: # os.path.isfile(path):
|
||||
message = _("'%s' already exists as a file. Would you like to replace it with the project?") % nameControl.GetValue().strip()
|
||||
|
||||
yesNoMsg = wx.MessageDialog(wx.GetApp().GetTopWindow(),
|
||||
message,
|
||||
_("Project Directory Exists"),
|
||||
wx.YES_NO|wx.ICON_QUESTION
|
||||
)
|
||||
yesNoMsg.CenterOnParent()
|
||||
status = yesNoMsg.ShowModal()
|
||||
yesNoMsg.Destroy()
|
||||
if status == wx.ID_NO:
|
||||
return False
|
||||
return True
|
||||
|
||||
HALF_SPACE = 5
|
||||
flexGridSizer = wx.FlexGridSizer(cols = 2, vgap = HALF_SPACE, hgap = HALF_SPACE)
|
||||
flexGridSizer.AddGrowableCol(1,1)
|
||||
flexGridSizer.Add(fileLabelText, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.TOP|wx.RIGHT, border=HALF_SPACE)
|
||||
flexGridSizer.Add(nameControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border=HALF_SPACE)
|
||||
|
||||
return nameControl, flexGridSizer, Validate
|
||||
|
||||
|
||||
def GetCurrentProject():
|
||||
projectDocument = None
|
||||
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
|
||||
if projectService:
|
||||
projectDocument = projectService.GetCurrentProject()
|
||||
return projectDocument
|
||||
|
||||
def AddFilesToCurrentProject(paths, folderPath=None, types=None, names=None, save=False):
|
||||
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
|
||||
if projectService:
|
||||
projectDocument = projectService.GetCurrentProject()
|
||||
@@ -92,11 +297,22 @@ def AddFilesToCurrentProject(paths, save=False):
|
||||
if path in files:
|
||||
paths.remove(path)
|
||||
if paths:
|
||||
projectDocument.GetCommandProcessor().Submit(ProjectEditor.ProjectAddFilesCommand(projectDocument, paths))
|
||||
projectDocument.GetFirstView().DoSelectFiles([paths[0]])
|
||||
projectDocument.GetCommandProcessor().Submit(ProjectEditor.ProjectAddFilesCommand(projectDocument, paths, folderPath=folderPath, types=types, names=names))
|
||||
if save:
|
||||
projectDocument.OnSaveDocument(projectDocument.GetFilename())
|
||||
|
||||
def AddFilesToProject(projectDocument, paths, types=None, names=None, save=False):
|
||||
if projectDocument:
|
||||
files = projectDocument.GetFiles()
|
||||
for path in paths:
|
||||
if path in files:
|
||||
paths.remove(path)
|
||||
if paths:
|
||||
projectDocument.GetCommandProcessor().Submit(ProjectEditor.ProjectAddFilesCommand(projectDocument, paths, types=types, names=names))
|
||||
if save:
|
||||
projectDocument.OnSaveDocument(projectDocument.GetFilename())
|
||||
|
||||
|
||||
def MakeNameEndInExtension(name, extension):
|
||||
if not name:
|
||||
return name
|
||||
@@ -106,23 +322,130 @@ def MakeNameEndInExtension(name, extension):
|
||||
else:
|
||||
return name + extension
|
||||
|
||||
# Lame
|
||||
def PluralName(name):
|
||||
if not name:
|
||||
return name
|
||||
if name.endswith('us'):
|
||||
return name[0:-2] + 'ii'
|
||||
elif name.endswith('s'):
|
||||
return name
|
||||
elif name.endswith('y'):
|
||||
return name[0:-1] + 'ies'
|
||||
else:
|
||||
return name + 's'
|
||||
|
||||
|
||||
def GetPythonExecPath():
|
||||
pythonExecPath = wx.ConfigBase_Get().Read("ActiveGridPythonLocation")
|
||||
if not pythonExecPath:
|
||||
pythonExecPath = utillib.pythonExecPath
|
||||
pythonExecPath = sysutils.pythonExecPath
|
||||
return pythonExecPath
|
||||
|
||||
|
||||
def _DoRemoveRecursive(path, skipFile=None, skipped=False):
|
||||
if path == skipFile:
|
||||
skipped = True
|
||||
elif os.path.isdir(path):
|
||||
for file in os.listdir(path):
|
||||
file_or_dir = os.path.join(path,file)
|
||||
if skipFile == file_or_dir:
|
||||
skipped = True
|
||||
elif os.path.isdir(file_or_dir) and not os.path.islink(file_or_dir):
|
||||
if _DoRemoveRecursive(file_or_dir, skipFile): # it's a directory recursive call to function again
|
||||
skipped = True
|
||||
else:
|
||||
os.remove(file_or_dir) # it's a file, delete it
|
||||
if not skipped:
|
||||
os.rmdir(path) # delete the directory here
|
||||
else:
|
||||
os.remove(path)
|
||||
|
||||
return skipped
|
||||
|
||||
|
||||
def RemoveRecursive(path, skipFile=None):
|
||||
_DoRemoveRecursive(path, skipFile)
|
||||
|
||||
|
||||
def CaseInsensitiveCompare(s1, s2):
|
||||
""" Method used by sort() to sort values in case insensitive order """
|
||||
return strutils.caseInsensitiveCompare(s1, s2)
|
||||
|
||||
|
||||
def GetAnnotation(model, elementName):
|
||||
""" Get an object's annotation used for tooltips """
|
||||
if hasattr(model, "__xsdcomplextype__"):
|
||||
ct = model.__xsdcomplextype__
|
||||
if ct:
|
||||
el = ct.findElement(elementName)
|
||||
if el and el.annotation:
|
||||
return el.annotation
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Methods for finding application level info
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
def GetProjectForDoc(doc):
|
||||
""" Given a document find which project it belongs to.
|
||||
Tries to intelligently resolve conflicts if it is in more than one open project.
|
||||
"""
|
||||
projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
|
||||
|
||||
projectDoc = projectService.FindProjectFromMapping(doc)
|
||||
if projectDoc:
|
||||
return projectDoc
|
||||
|
||||
projectDoc = projectService.GetCurrentProject()
|
||||
if not projectDoc:
|
||||
return None
|
||||
if projectDoc.IsFileInProject(doc.GetFilename()):
|
||||
return projectDoc
|
||||
|
||||
projects = []
|
||||
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
|
||||
for openDoc in openDocs:
|
||||
if openDoc == projectDoc:
|
||||
continue
|
||||
if(isinstance(openDoc, ProjectEditor.ProjectDocument)):
|
||||
if openDoc.IsFileInProject(doc.GetFilename()):
|
||||
projects.append(openDoc)
|
||||
|
||||
if projects:
|
||||
if len(projects) == 1:
|
||||
return projects[0]
|
||||
else:
|
||||
choices = [os.path.basename(project.GetFilename()) for project in projects]
|
||||
dlg = wx.SingleChoiceDialog(wx.GetApp().GetTopWindow(), _("'%s' found in more than one project.\nWhich project should be used for this operation?") % os.path.basename(doc.GetFilename()), _("Select Project"), choices, wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.OK|wx.CENTRE)
|
||||
dlg.CenterOnParent()
|
||||
projectDoc = None
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
i = dlg.GetSelection()
|
||||
projectDoc = projects[i]
|
||||
dlg.Destroy()
|
||||
return projectDoc
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def GetAppInfoForDoc(doc):
|
||||
""" Get the AppInfo for a given document """
|
||||
projectDoc = GetProjectForDoc(doc)
|
||||
if projectDoc:
|
||||
return projectDoc.GetAppInfo()
|
||||
return None
|
||||
|
||||
|
||||
def GetAppDocMgrForDoc(doc):
|
||||
""" Get the AppDocMgr for a given document """
|
||||
projectDoc = GetProjectForDoc(doc)
|
||||
if projectDoc:
|
||||
return projectDoc.GetModel()
|
||||
return None
|
||||
|
||||
|
||||
def GetAppInfoLanguage(doc=None):
|
||||
from activegrid.server.deployment import LANGUAGE_DEFAULT
|
||||
if doc:
|
||||
language = doc.GetAppInfo().language
|
||||
else:
|
||||
language = None
|
||||
|
||||
if not language:
|
||||
config = wx.ConfigBase_Get()
|
||||
language = config.Read(ProjectEditor.APP_LAST_LANGUAGE, LANGUAGE_DEFAULT)
|
||||
|
||||
if doc:
|
||||
doc.GetAppInfo().language = language # once it is selected, it must be set.
|
||||
|
||||
return language
|
||||
|
||||
@@ -39,7 +39,7 @@ class BaseWizard(wx.wizard.Wizard):
|
||||
class TitledWizardPage(wx.wizard.PyWizardPage):
|
||||
|
||||
|
||||
def __init__(self, parent, title):
|
||||
def __init__(self, parent, title=None):
|
||||
self._prev = None
|
||||
self._prevFunc = None
|
||||
self._next = None
|
||||
@@ -48,13 +48,22 @@ class TitledWizardPage(wx.wizard.PyWizardPage):
|
||||
self.SetSizer(wx.BoxSizer(wx.VERTICAL))
|
||||
self.MakePageTitle(title)
|
||||
|
||||
|
||||
def SetTitle(self, title):
|
||||
if not title: title = ""
|
||||
self.title.SetLabel(title)
|
||||
|
||||
def MakePageTitle(self, title):
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
title = wx.StaticText(self, -1, title)
|
||||
title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
|
||||
sizer.Add(title, 0, wx.ALIGN_LEFT | wx.ALL, 5)
|
||||
sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND | wx.ALL, 5)
|
||||
if not title: title = ""
|
||||
self.title = wx.StaticText(self, -1, title)
|
||||
self.title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
|
||||
# the code below used to add a 5 pixel border in all directions
|
||||
# but I found that the left margin was not aligned properly because
|
||||
# only a few of the wizards made sure that pages themselves added
|
||||
# the 5 pixel left border. If we still want to inset 5 more pixels,
|
||||
# we should add a wx.HORIZONTAL sizer here to take care of it.
|
||||
sizer.Add(self.title, 0, wx.ALIGN_LEFT | wx.TOP | wx.BOTTOM, 5)
|
||||
sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
|
||||
self.GetSizer().Add(sizer)
|
||||
|
||||
|
||||
@@ -115,689 +124,6 @@ import cStringIO
|
||||
|
||||
def getWizardData():
|
||||
return \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00}\x00\x00\x00\xfa\x08\x06\
|
||||
\x00\x00\x00\x8c5HE\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00 \
|
||||
\x00IDATx\x9c\xec\x9dy\x9cdUy\xf7\xbf\xe7\xdc\xbd\x96\xdegzVfe`\x86u\xd8WY\
|
||||
\x14\x90M\x10\x11D\x11W4\x89Fc\xe4M\xd4\xa8\xd1\x88\x91D\r\x1a\xb7\x98\x98\
|
||||
\xa8o\xd4\x08\xae\x08\x18EDE@\x04E\xf6}\xf6\xadgz\xaf\xae\xedn\xe7\xbc\x7f\
|
||||
\x9c[\xd5\xd53=\xc3$\x8c\xd0\xf3v\xff>\x9f\xea\xea\xbau\xebn\xbf\xf3<\xe79\
|
||||
\xcfr\x8e\xf8\xe4\'?\xa9\x99\xc1\xb4\xc15\xd7\\\x83\r\xf0\xc0\x03\x0f\xbc\
|
||||
\xd8\xd72\x83\x17\x00\xdf\xbe\xe1Fq\xcd5\xd7h\xbb\xb1\xe1[\xdf\xfa\xd6\x8by=\
|
||||
3x\x01\xf0\xed\x1bn\x04@\xbe\xc8\xd71\x83\x17\x013\xa4OC\xcc\x90>\r1C\xfa4\
|
||||
\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\
|
||||
\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\
|
||||
\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\
|
||||
\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\
|
||||
\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\
|
||||
\x103\xa4OC\xcc\x90>\ra?\xf7.S\x05j\xa7\xcf\xbb\xb6\xd7\xddM})P-\xbf\x97\xcd\
|
||||
w\xdd\xfc~\xb2\xe3\xb7\x9eG\x81V\xd9\x19D\xf6#9\xf1\x1aZO.&\xb9\x18\xd1\xf2\
|
||||
\xeb\xc9.\xb4\xe5\xd0\x8d\xf7\x89\x87T\x13\xf7\xc9\xce\xbd\xf3i\x9b\xf7\xa1\
|
||||
\x15\x88\xc9\xe9\xddOHW@\xda\xf2\xb9q\xe7r\xc2MON\x9bB\xa2\x10\xc4\xd9\x1e6`\
|
||||
\xa1\xb3o\xccQT\xd60tF\xae\xccN!\x18\'\xbd\xde\xf2\x9d\x95\x1dg\x92\x07\xaf[\
|
||||
64\xfe\x97\xa0\x859\xbbl\xec\xa3v\xfaa\xa4\xc1\x12\xe0\x8c\xef\x9ff\xbbY\x80\
|
||||
\xa5Ss\xfeD\x83\x10 ]\xb4\xcc\xae:\xdb\x14\x85u\xa4N\xf0<\x07t\x0c\xa20\xe9\
|
||||
\x13\xd9OH\x87]%u\xf2oa\\ 4*k\x1ez\xc2\x1e\r\xc2\xc7\x05G\xeet\x04\x05\xda\
|
||||
\xca\xa4\xb9\xf1\xbde\x9e,\xd2H\x90\xb0\x98\x8c;!\x0cI\xe6\xe0\x89aD\x02\x08\
|
||||
\xf4\xce\x8f\xbb\xd1(\x04`7~\xd8\xd0J\x12\x8d R \xe2\x98\xbcT 5H\x1b\xa4h^\
|
||||
\xb9\x06\x94\x80z\xa8\xf1\x1c\x1fGj\xd2$\xc4\x92\xbb\xef\xb9\xf7#\xd2w&f\xd7\
|
||||
o\x1bhH\x94yo\xfc\xc6\xa5\xf1\xe0\x1bD\xb5\xeegag\x92\xdc\xd0"v\x93M-$\xc8`\
|
||||
\xc2\xefZ\x05\xba\x01A\x82 F\x93"D\x84$E\x88\x86v\xf1\xb1\xd0\x08\xb2\xc6\
|
||||
\xd4P"\x8d\x83\xc8\x04D\n*F\xa5)JZ\xd8\xb6\x87\x94\x16\x96g\x83\xca$]+\xe2zJ\
|
||||
\xa4b\xb4t\xb0}\x1b\x04\xd8\x9e \x05R\x04\xca\xf2\xd1)\x14w\xc3\xfb~D:d\xca1\
|
||||
{\x9f\xfc\x8e\x04\x99\xc0\xa0\xb0\x9a\xf4\x8cKY\xabdN8\x82nl\x91\x93\xf6\xcf\
|
||||
\x91\x98\xd8\xc1\xec|U\x13\x8f\xdch\\2kt\x12\x81\x06\x92\x96\xe3\xb6\x9c]$\
|
||||
\xa8z\x19)\x15\xb8\x16\xd2\xb2\x91\xd84\x0c\x810V\xb8\xae\xd3<\x8b\xb0M/\xa0\
|
||||
Z\xce\xaa\x80zj4\x8d+\xd9#\xb3\xfb\r\xe9:\x93@\xb1\xd3\xf6\x9d?\x1b\x8e[\x1f\
|
||||
\x87\xc1\xcej\xb8\xf5\xf7\xb2\xf5\x0b\xbd\xd3;\xe6A\xb6jbh4\xac\xf1&(\xb2\
|
||||
\x06#qv9\x911\x0fB n\xd9\xa0\x0c\xf1\xd9Ae>\xa0A\xa3i0\xc6n\xd0\x02\x12GRJ \
|
||||
\x95`\xc9\xac\x8fo9\xbe\x02*U\xd8\xb8i\x1b###tuu1\xff\x80^\xda\xbcIn\x98\xfd\
|
||||
\x86\xf4\xbd\x18Y6\xc8n<\xd0\xe6\x937\xca\xbbU\x9dC\x0bY\x93\x11\xde\xd8\xa1\
|
||||
y\\\x1ar\xd7\xfc\x9d\xd5\xd8eg=\xbf\x13\xe1\xbaq,\xb1\xd3=\x08\x89F\xa2\x04\
|
||||
\xe6\x1d\x9b\x88\xc4\xd8iXXB \xb2k\x8e\x05Tm\xd3d$F_lZ\x17\xf3\xe4\xc3\x0f\
|
||||
\xf0\xd8\xc3\x0f\xd0\xb7e\x1d\xe5\x91!.\xbe\xe8B.\xbe\xf0\x02\xda\x0b\xd6n\
|
||||
\xb5\x12\xec7\xa4\xc3\xee\x89o\xe9\xe7w?f\x9b\xf0\xef8\xd9\x8d\xe1Mv\xfcV\
|
||||
\xb5\xa1\xc9\xfax@Il\xdd\xf2\xb0Z\x89nj\x95\x16\xa3O\xec\xfa\xafi<\x99\xf4\
|
||||
\xe24\xc7\x12\x8d\xf7\x10\x00;k\x04\x06\xe5\x10\xb6\xf7\xc1\xd6Q\xb8\xeb\xe9\
|
||||
ml\x19\x1ef\xe33O\xb2y\xcdcD#}\xcciw9b\xf9B\x0e?\xe4P\xae~\xc3\x15\xb4\x07\
|
||||
\x0e\xb6HI\xaa\x15r\xbe\x0f\xb2U\x1f\x8cc?"}o\xd1h\x04\xc20\xab\'6\x16\xa3\
|
||||
\x8a\x13 \x1d\'\xb59\xe6\xb6h\x92\'\x94y\xa9l\x18\xa7\xedI\x1aUf\x9d\x8bL\
|
||||
\xb34U\x819F\x9a\xd9\x01\xa6\x8b\xb5@\x0b\xb4\xb0\x891dG\x18\xb2\x13\xa0?\
|
||||
\x86M[S\x1e{\xeaY\x9exr-\x9b7\xf532P\xa1R\x8e\x18K,\xca\xb9"\xb1\x10\x88\xa8\
|
||||
\x84\xabl\x16.Z\xc6\xe9G\xaf\xe2\xd5\xe7\x9e\xc2\x91K\x0bx\x80\xd7\xb8\x7fK\
|
||||
\x82\xae\x01\xfb\xf9\x90m\x97\xbe{\xb7;\xecl\xc7\x9bm\xf5(\xc2w]\xc2p\x0c\
|
||||
\xdf\x95f\x1c\xab\x12P\nl\x1f\xa4\x83q\x81\x88\x89G\x91\nR\x05:1d\x8a\x86\
|
||||
\xd2m4\x18\xd5\xb4\xc6+\xd5\x1a^\xae\x8d\xc1J\x85B>O\x04\xd44\x14\x04\xe4\
|
||||
\x91\xa4\x11\x8cE\x1a\xbf(\xd8R\x82\xdf<\xd4\xc7\xedw\xdf\xc7#k\xd61X\xa9\
|
||||
\x93\x08\x9b0\x11D1\xd8V\x8e\xc0mC\xdb6\xd54\xc2\xb2]\x92h\x0cG\xa7\xac\\\
|
||||
\xb1\x8c\xd7]x&\x17\x9f\xd2C\x0e\xa8\xd7\xa0\x18`\xeeIG\xec\xde\xe44\xd8oH\
|
||||
\xdf\x1b(\x05J)\xb46"i\xdb6B\x18\xbb\xd9q]@\x19)\x17"s^\xa4\x18\tU\x90jb)QBd\
|
||||
t\n\xa4\x16\xc6\x95c\x8f\xabI\x9di\x84\xc68?\xd3\x19D@\x92\xf3\xa8\x01:\x9fg\
|
||||
\x04\xd8Q\x87\x8d\x9b\xca<\xf3\xd0\xef\x91\x03\x9bx\xd7\x9f\\I\xe0\x19\xe9\
|
||||
\x969\xf8\xc2W\xbf\xc3\xc6\xa1*\xa9\x97g8tHq\xb0\xfd\x80\xa0\xadH\x12\x0bv\
|
||||
\x94C\x84V\x14\x02\x97\xda\xe0f\x8a~\xc2KO9\x8e\xb7^y\x06\x07\xf7\x18\x034\
|
||||
\xaaAOn\x12\xaf\xe3\x1e\xa4d\xff!}\xa2\xcf\xb4e\xf3\xb8d\x0bI\xd3)\xd1\xb4\
|
||||
\xdf5\xa4\x99W,\xd2\x8a\x9c\xe7\xd3\xe8A\x8d\xd4\x02\xc2&\xc4%\x15\xb2\xd9\
|
||||
\xc7\x02XB\x90f\x8f(!#\x96\xf1.=e\\M?\xb5\x06\xd6m\x1e\xe0\xb1\'\xd7\xb1nc\
|
||||
\x1fO?\xb3\x1e\xe9\xfa(m1\xb8\xeea\xbe\xf0\x81\xd7S\xaaA)\x821\x05\xff\xf9\
|
||||
\x83\x87\xd98\x10\xe2v\x1f\xc0h\xa4\xc9\xe5<\xeaI\x8a\xd6\x82\x18\x1bK\x82\
|
||||
\xe3iD*\xf0\xa8q\xf8\x01\x05.;\xffd^~\xd6\xa1t\xb9\x868W\x80\x93\x83\xb8^\
|
||||
\xc7\xf62\x0f\xa1t\x19\xb7\\&\xc7\xfeCz\x03\x13\xfc\xcf\x06\n\xa8\xd5C\x10\
|
||||
\x16\x96ec\xb7v\xbfb\xdc\xa5\x19\'\x16\x81\x03B%\xe3\xbf\xb4l\xd2\xd4#\xb1lB\
|
||||
\xa0\x8e!\xb2q\x1a/{/\x01\xdb\x87a\xe3\x96:k7la\xdd\xc6\xed\xac\xd9\xb4\x95\
|
||||
\r\x9b\xfb\x19\x18.#\x1c\x9f(\x11X\xd2\xa3\xad\xb3\x8b\xb1\xb4\x83\x9c\xc8\
|
||||
\x11F1G\x1c\x7f&\xe7_p4\x0eP\x08`\xcdZ\xf8\xfe-?\x03\xa7H-\xb6(\x8d\x96!/\
|
||||
\xc0\xb2 \rI*#t\xe4\x02\x0e9\xf0\x00\x0e9\xe8 \x96\xcf\xf29\xe7\x88v\x96\xf4\
|
||||
@\xde5\xd7\x13\xd7S\xb4N\xb0\x02\xc78o\xa0\xe91L\x91\xa4\x18w\xd4d\xd8\xffH\
|
||||
\x87I\x89\xf7}\xaf\xe9\xa1\x0fS\x9a\x8d\xbd\xe1\xf4J\x00\x1c#E\x8e\xc8\x91VK\
|
||||
\xd8\xb9<H\x8fjj\xc8.\x01C\x11\x0c\x96\xa0\xaf\x0f\xd6\xaeY\xcb\xfa\'\x1fc\
|
||||
\xf3\xb6a\x9e\xd9P\xa7\x96\xfa\xc4\x1a\xb4\xe5 \xbd\x1c\xca\x0e\x88\xd4\x01D\
|
||||
~\x82\x9f\x0b\x08+\xa3H\xa1H\xeb)a\x1a\x11\x96C|Wr\xc5U\xafaL\x81-\xe1\xd9M\
|
||||
\xf0\xb1O\xfc3\xb1\x16T\xeb\x11\xa9\x8e\xe8\x9e\xddK=\x0e\xe9l\x0f8\xfa\x88\
|
||||
\x838\xe4\xc0\x85Twl\xa6o\xe3\xb3\xac\xe8\xacp\xd9\xcbz\x99\xef\x80\xa74Q\
|
||||
\xb5\x8e\x1bx\xb8\x9e&\xac\xd4Ij1\xb6\xefg\xcfc\x9c\xf0=\xad\xbb\xb6\xff\x90\
|
||||
>\x89zou\x89\xb6\xc6\xc0\xa45\xd1KU\x8f\xc1\xf1!V0:\xa2\x98\xdfe\x11\xe9\x1c\
|
||||
\xb6\xf6\x88\x04\x8c\xc5\xf0\xf1\xcf\xdc\xcc\x9a\xfe*Ol\x1ab\xdbp\x19\xa5\
|
||||
\x149\xd7\xa1\xe0YH\xe9\x93x\xb3I\x94G\xac\x04\x89\xb0H\xa5\x8d\xd2\xb69\xab\
|
||||
L\xa8%\x80\xeda\xb9\x16\xae\x15\x91ss\xc8\xa4\xca\xca\x15\x8b9s\xb5i|)p\xeb\
|
||||
\xed?\xe3\x91\'\x9e$\xd7s A\x10\xd0\xb3`\x01\x0b\x96-\xe3\xa4\x13\x172\xb0\
|
||||
\xbd\xca\x03\xf7\xdc\xc67o\xfb:g\x1e\xb7\x8a\xbf~\xeb\xe5,\xea4\x12\xab\xeb\
|
||||
\x11x\x127pH\xc3\x1a\x96e\xe1\xe5\xf3\x00\xd4jU\x82\\\xa1\xd9\xd5\xed\xd9a\
|
||||
\xbd?\x91\xfe\x1c\x08\x13\x8c\x07U\x8eG6c\x05\xa52\x8cU\xe1w\x8f\xad\'\xac\
|
||||
\xd5\xa9\xecX\xc7;\xdfr.\xb6\xef\x11i\xa3\xca\xcb\x11\xfc\xe0\'wSq\xbbH\xfcY\
|
||||
\x04\xdds\xf0\xfd\x00tB\xbdZ"\xac\x8d!\xdda\x12K\x92Z\x0e\xb1\xb4A8\x803\xee\
|
||||
t\x11\n\xe9(\xe2\xd2\x10\x92\x10\x9dT\xe8is\xb9\xf4\xa5\'\xe3c\xba\x89\xbb\
|
||||
\x1ex\x8a[~|\x0b\xc7\x1cw4+\x8fz)\x87\x1e\xb3\x98\xa7\xd6\xc1\x1f\x1e|\x8c\
|
||||
\xcf}\xea\xdf\x98\xdd&9\xf3\x84\x83\xf9\xf8\x9f}\x88\xc3\x16\xd8\x88z\r\xbfV\
|
||||
%\x08|\x94\xe3\x92*\x0b\xcb\x12X\xbe\xa1-M5B\x08\x82\\\x9b\xb9\x04\xc8\\\xcf\
|
||||
0\x1eQ\xdc\x15\x93lm\x98*\xd9a\xf4\xf3h\x17B\x8d\x8f\x93[%U\xb4^\xd8\xc4KiHh\
|
||||
CE5=ir|\xef\xc66\xd5\xb2\xef\xb3[C\xfa\x06\x86Y\xb3~\x0b\xeb\xd6of\xeb\xb6\
|
||||
\x1d\xf4\x0f\x8eR*U(\xd7b\x84\x9d#\x8d#t}\x84K_{.s\x03\x9a\x1e/\xed\x80\xdf9\
|
||||
\x87\x9ah\'T\x1e\xd5jL\xa9j\xa2Z\x16\x02\xcb\xf1\x11B\xa1\x85BK\xc5\xb8\x0f=\
|
||||
\xc9\x1c.\x1a\x92:mmyjcezr\x16A\xa4X>\xbb\xc0\xa5\xa7xh\x8c\xb17&:\xf9\xd8\
|
||||
\xa7?\xcb\x83\x0fo\xe4\xde\xdf=\xc1\xf7n\xfa\x11\xe5\xb1*s\xe6t\xf2\xfa\x0bN\
|
||||
\xe6e\xa7\x1c\xcaQK \x07\xb8h\x02_e!\xb42\xd2\x9fE\x9ay\xf0\x1b\xae i\x8dG\
|
||||
\xda&\xf4vZ\xed\xe4j\x9c\x88I\x18\xadS+\xf5\x13\xb4u\x9a\xa7\x11+\x90.qX\xc3\
|
||||
q\x1c\xb0\xed\x89$\xa6\xb1\x19+9\xce\xc4\xc34\x9d\x16\r\x96$$\nt\x089\x87zX\
|
||||
\xc6\xf7\xbd\xe6-\x84\xf5\x08\xcf\xcb14\x92\x90\xef4FU5\xfb6\x02b\r\xfd\x03\
|
||||
\xb0q\x8bb\xd3\xe6\xadl\xee\xdb\xce\x86-[\xd8\xb8e\x07\xdb\x07\x86I-3\xe4I\
|
||||
\x85\x8b\xd6\x0e\xa9\xf0Q\x14\x8cq\x17\x80\xadS|\x1f\xea\xf6\x08\x1b\xab0+\
|
||||
\x00\'5\xb6S\xa5\nc*\xa2\xee\x08\xa4c\x91\x92\xdd\xb7\xd2\xa4\x96\xc0q\x8b\
|
||||
\xe4,\x9fr\xb5N\x12\xa6\xe0f\x11\x0f\x9d\x00\t\xc2\xd1\x14r\x16#\x1b\x1ea\
|
||||
\xf9\xfcY8\xb5a\xda\xa9\xf1\xc1\xb7\xfc\x19\x1d\t\x945|\xe5\xc7\xdb\xb9\xfd\
|
||||
\xfe\x87x\xfa\xf1\xc7\xb1\x89\t\x1c\xc5\xbcN\x8fs^y\x06\xaf:\xefx\xe6w\x185\
|
||||
\xeeb\x0emi\r\xda5B\xe7\x18\x15&E\xab\xaf\x7fw\xd8\xf3pmr\xd2\xb5"h+\x00)i=F\
|
||||
Z\xdd\xa0\xc0\t\x82\xa6\xcb1\x8d\x12\x94RH)\x91\xb6\x8d\xd8\x99p\x1aWe\xa1\
|
||||
\xb5y6q\x15\xbc\xbc$J\x03,\x01\xa9\xe5\x91 \xb3\xc0\x81\x8d\xed;\x94cp:m\x1e\
|
||||
\xdb\n\xf7=\xbe\x9d5[w\xb0cd\x98\x07\x1f\x7f\x92\xa1\xe1\x1aa\xa2\x89\x12\r\
|
||||
\xc2A:>J:\x84\xa9K\x98\xce\xc6q\xf3(lt6\x866\xc1\x8c,\x14\xa2S<\x15\x92\x88\
|
||||
\x94\x9a\xcc1\x10\x92Y\xb7\x11\x12\xd7\xd8\x00\x96$L5:\x8a\xc0\xb5\x91\xb96\
|
||||
\xa4\x94\x88\xa4J\x12%\x0c\x8dV\x10\x96\x8b\x1bxX\x96&Ik\xc4\xe1($\x15$!\xb6\
|
||||
/9\xe2\xc0\xf9\x1c\xb2t!\xe7\x9dv*\xa7\xaf\x0ep1\xae\xd4k\xaf\xbf\x95\xef\
|
||||
\xdc\xfd4\xe4;\x11B\xe2\xdb\x92\xd3O<\x82\xab.=\x9bU\x0bhz\xd3LzG2\xae\xe2\
|
||||
\xb4e\x04O\xb4<\xd2=\x12\xdeB\xfc\xff\x88t,\xd2Ha9\x0e2(\xa2\xb4D\x0b(\x95\
|
||||
\xc6\xb0\x1d\x85\xeb{\xd8\x9e\x8bF6;\x82\x18\xe3\xc0L1\t J\x9b8\xbf\xc4\xb8"\
|
||||
\x95\x03\xa2\xc3\xec[Q\xc6C\xd8\x19\x04\xa4\x80EL\x14\xc3\xc3On\xe0o\xae\xfd\
|
||||
<\xc3\xaa\x8b2\x05\x06*\x11N\x90\xa3\xad\xdd\xa7\x16\xa6DV\x8e\xc4\x92h\xc7A\
|
||||
K\x0f!=\xb4\xf4A\xd9\xd8\xbe \x8e3/\x94H\x91$\x08\x1d\x9b+\x14)B$h\x99\x12\
|
||||
\x93\xa0\xec\x1aC\x95\x86\xf2\t1\x8a\x14t\x9cP\xc8\xe7\xf1\xbdv\xa2\xd4\xa6T\
|
||||
IH\xc2\x9a\xb1\x87\x1d\t\xf9<\xaeoc\'U\xc2\xd1\x1dX\xd1(+f\x179\xee\xf0\xc38\
|
||||
x\xd9B\x0e_u K\x96\xc0C\x8f\x86<\xfa\xd43\x14f\x1f\xca\xfc\xf9\xf0\x85o>\xc1\
|
||||
-\xf7>\x86\xa5\x13\xba\x04\x9c\xf9\xd2\x13y\xcd\xabN`Yo\x96$\xa3L(t\xe7\xc8\
|
||||
\x19\x8d\x86\xfb\xdc\x0c\xff\x8f\xb1+\xe9J#\xdd\x80\x08\x9b\x14\x17%`\xf3vX\
|
||||
\xd0[\x04\x8c[\xa3\xc2\xf8P\xa8\xd1\xc35-h\x01\x89\x80\xb2\x82\xad\xdb\x15\
|
||||
\x1b\xd6od\xeb\x8e\n\x8f=1\xc4\xb6\xbe\x01|_Q\xf4k|\xfa#WR\x04\x02\x1c\\\x07\
|
||||
\x0e9l\x11\x1d\x0b\x0e\xe2\xee\xfb6RX\xb8\x84\xb0\xdd&\x12\x82\xca\xe8\x08\
|
||||
\x96\xe5!\xdc\x1cJ\xbahe\x11k\tI\x16\x96\xd4\x99w\xdbvi\xf8\xc2\x15`i\x85 \
|
||||
\xc5R\x86x-\x14\x89V`[\x0c\x8fVQ\xe4\x8c\xe7N@\x1c\xa6\xf8\xaeK-\xac18ZC%\
|
||||
\x0e\x8e_ \x97\x0f\xf0dB\xaa\xea\xa4n\x85\xf2\xd80\x9ecq\xd6)\xab\xb9\xf8\
|
||||
\x9ccY\xb5\x0c\xfa7\xc1\xe3\x0f\xaf\xe5_\xbf\xf4\x9fl\xdc\xbc\x89TH\xbe\xf4\
|
||||
\xd5\xf7\x91\xcb\xc3\'\xbft\x1f7\xdd\xfa\xdf\xf4\x14s\\\xf6\xb23\xb8\xfc\xdc\
|
||||
\x13Y2\xcf<\xbb\xb0\x06\xb9\xc0\x0c\xe3\x06\xb6\x0f1\xaf\xb7\xab%\xa6\xcfN\
|
||||
\xf1\xf6?6\xe9\x96c\xe2\xb3J"\xa5!\xb9\xad\x17\x06ScLI1\xee\x8d\x1a\xac\xc0\
|
||||
\xb6~\x18\x1c\x89x\xec\xc9g\xd9\xd6?\xc8\x9aM[\xd8\xda\xb7\x83R\xa5F\xaa\x05\
|
||||
\x08\x0b%|:\xe7\xae`\xc3\xfa!\xda\xf2\x1a/\x1d\xe0\xee\x87\x868\xfb\x88.\x12\
|
||||
m2\x85F+p\xe69\x17\xf2\xcbM?\xa6\xe6t\x91\xc6\x02\xb7\xad@4\x9c\x82NI*\x0eX\
|
||||
\xbe\xb1)l\x99\x89\x87\x00\xdb1\x07\xa8\xd6\xccU\xa5\xc6x\xd4\xa9m\xd4\xbbv\
|
||||
\x10J\x81%\xd0i\x88\xe3\nF\x86B$9,\xed\x9b\xe0G=\xa4^\x19\xc5o\xeb\xa43\x9f#\
|
||||
\x8e4\xb5x\x8c4\x1eF\x11\xe3\x881\xce;i5\xa7\x9dq\x11\xc7\x1d\xe2R\x03~~\'|\
|
||||
\xe8\x1f\xefe\xed\xba\xadDaB\x14\xa6X\xf4\xf0\xe9\x7f|\x1b\xddy\xf8\xfa\x7f\
|
||||
\xfd\x81_|\xf7\x8b\xbc\xf3u\x97p\xc5+_\xc1\xb2Nsyv\n\x8e\x05E\x17\xa2\xb1\
|
||||
\x18\xc7s\x987\xab\xab%N\xd4 }\\\x90\x1aMa_q\xbf\x0b\xe9\x89\x82XZHiS\x03\
|
||||
\x9e\xd8\x92\xc5o7E\x0c\x0e\x0c\xb1i\xcbV6n\xddF\xdf\xc00\xa3\xa5\n\x95zB=Q\
|
||||
\xe0\xfa$Z\x92`\xa1\xadnd\xe0\xa1\xb4 JS\xa2\x04J\x1b\x07 \xd7A)\xad\x90\x17\
|
||||
yn\xf8\xe1m\xbc\xec\x88\xd7\xe0d\xb1\xeaYy8\xf5\x84^\xe6\xfc\xb0\x9b5[F\xc0i\
|
||||
#\xaaE\x90@\xd0\xdeI\xb9&\xd1"\x1b\x17\xa7\n\x92\xba1 E\x96\x15\xe8f\xca13\
|
||||
\x1e\x95e\x11)3`\xb7\xb4\xc2C b\x85\xeb\xd9\x8c\x0c\x8c!\xe8D\xe2\x98\x04\n\
|
||||
\xad\t<\x97rRg\xa4RFk\xcd\xbc\xf9\x0b9\xe5\xe4\xe39\xeb\xb4y\xacZ`\x0e\xfd\
|
||||
\xdb\xdf\x0f\xf3\xc1\xeb~\xc6\x83\x8f\xaeed\xccBY9\x90\x05\xa4\xb0(\x14\xbb\
|
||||
\xb9\xfa\xaa\x0b9j\x05|\xee\xf3\xbfbx\xeb\xa3\xfc\xfc\x86\x7f\xa1\xb7\xd3\
|
||||
\xa1\xcdR\x08\xa5Qq\x8c%$\x8e4n57\xe7Ld\xb6\xa5\xd3\x9e,\xffn_a\x17\xd2\x85t\
|
||||
PH"`\xfd(\xfc\xf5G>\xc7\xe6\xed5\xea\xa9\x0b\xc2EH\x1b--\x94\xb4\xd0\xf8\xc4\
|
||||
Z\x92h\x89\'\x0b\xc4\x1ab%P\t\x90\xd8Y\x9fd\x81\xa3\xc0\xad\xd3\xde\x99\xa7V\
|
||||
\x95\xe4l\x87\x87\x1e\x7f\x96\xdb\xefz\x86\xd7\x9cr \xb6N\xb0\x84\xcd\x1c\
|
||||
\x17\xce>\xfe`\xbeq\xdb\x1fH\xf3\x01\xd50\x81(\xa4\x16V\xd1\xb6\x9b\r\x01\
|
||||
\x95I:\xd1\n\x07\x10Z R\x8d\xaa\'&\x94)e\xa6\x92\xa4\xe94\x85 M4Bid\x92`\xa5\
|
||||
\x16\xa5\xc1a,\x0e\xc0B\xa0\x05x\x8e\x8b\xef\xfb,]y8\'\x9dx<\xc7\x9f`3;\x075\
|
||||
\xe0\xae_\x0e\xf1o_\xb9\x83\xc7\xd7m\xa5\x16\x83\x14\x1e\xbe\xd7\x85\xdd&(\
|
||||
\x97*X\xc9 m\x81\xc79\'\x1c\xcf%g\xc2\xb3\x0f\xa7\xbc\xe9\x15\xa7r\xe0\xfc\
|
||||
\xd3(ZP/\xf7\xe1\x15r\xe6z\xbc,\xf6\x1a\xd7M\xc3u<v\xee\xc9\x1b\xe3\xaf?BW\
|
||||
\xbe{\xd25PU\t\x15i\xb3}(dc\xdf\x00V~\x01R\xe4\x89\x85\x87V\x90jE\xaaMF\xa9\
|
||||
\x906\xc2\xb2)\xc7\tH\x1b\xe1\xd8\x08a\x99\xfeR7\xee@c;\x92\xd1\xfe\x1d\xa0S\
|
||||
\xc6|\x89R\x1e\xdf\xbb\xf5W\\z\xca\x81\xd8\xb1"\t+\xcc.\xe6\xb9\xfaU+\xb8\
|
||||
\xf9\'w\xb0\xb9\xaf\x0c~7^{\'q\x9a\x18\x89N\xe3,\xb6\r\xae\xd48B#u\x8a\x16\
|
||||
\x1a\xad5If\xb1\xa7\xcd\xfc\xb2\xcc\x18"\xc1\x11\t\xe81\xac4$\xac\x0c\x98\
|
||||
\x1b\x95\t\x02\x1b\xcfs\xf8\xfa\xd7\xde\x8b\xb6\xa1\x94\xc0\x9dw\xc3On\xff\
|
||||
\x15\xeb\x9e}\n+)!\xbd\x1c\x83tBl,\xae$\xb5\x10a\x05W\x8fq@O\x91C\x16w\xf3w\
|
||||
\xefX\x89\x03,9\xdc\xc2V\x10HP\xe1\x18\x85|\xc1$5\xca,\x04\x9b&\xa6\x8f\xb4]\
|
||||
P\x19\xe1I\xc6\xc4N\x03n\x89B5\xd5\xc0\xbe\xf3\xa3\xedr$\x05\xf8\x99j\x7fv\
|
||||
\xcd::\xba{\xd8<\\\'\xc9\x07\x84I\x16\x9dr\xb2\x9f\xa5\x11\xd8\x8a \xb0\xa0\
|
||||
\x1a\x03\xa1q\x056.\xbey\x03)\xc9H\x89\xe2\xac^\xc6*\x11\xf58&\x8a\x03\x9e\
|
||||
\xdd^\xe7\xa6_<\xc1\xa5g\xac\xc4\xb3lT\x0cK\np\xf1\xa9\xab\xb8\xf1\x97O0\x10\
|
||||
\x8f\xa1\x9c.T\xea\xc0X\x84W(\xa0uLT\x1b%t \xe8\xcc\xa3I)\x8d\x8e -\x10B \
|
||||
\xb0\xf0\xb4\x83T.:\x15$\xb1\xc6J\xca\xf8n\x15\xcf\x1b!\xc8\x179\xe2\xd0\xa3\
|
||||
\xb0t\x02\xa2\x8a\xa4\x8db\x11~\xf5 |\xef\x8e\'\xf8\xc3CO\x90*A\xac%q\xadH \
|
||||
\x1d,\xbf\x13T\x07\xe4|`\x8c(\x1d\xc1\xaa\x0f\xd3\xa6\x868\xe3\x88\xc5\xbc\
|
||||
\xe7\xcd\x172\x0b\xf0P\xc6\xb0\x14\nR\x89t\x023\xce\x16\xc6\x85\xa4Q\x08+K\
|
||||
\xd4\xd0r|d\xe50\xd1y\x95\xa5~\tT\x96\xe8\xd5`f/\xd2\xc6\xfe7\xa4\x9b\x8b\
|
||||
\x968\xc0\xdc9\xb3\x19\x1d\x1a\xc4\xcb\xcd\'t\xbcq\x07\x8c\x94F\xf2\x92\x04\
|
||||
\x92\x88Z\xb9d\xbc\x1c\x00\xc4\xd9\r\x8c{\xdb\xa4V\x88\x9cO\xa5n\x86HX.:\xef\
|
||||
\xb2v\xa8\x8f\x9b\xefy\x9aSOXI\x87\x96\xe4|\xf0\x81W\x9fs"\xb7\xdf\xfb0\xa3Q\
|
||||
\x88\xf0\x02b\x95\xd0\xd6\xe5\x13U\xcb\x08\xa9i\xef\xea\xa0\x1a\xd7\x18\xd9\
|
||||
\xbe\x03l\x81\xd7\xd5\x0eI\x84\x8e\xebx2\xc5S\t\xb5\xd1\xad$\xd5\x1aK\xe7\
|
||||
\xccc\xc5\xaaE\xac8x\x01g_\xb0\x8a\xdeb\xc3\x01\x12C\\\xa3\x9c\xd8\xdc\xf3\
|
||||
\xdbM\xbc\xf7c\xdf\xc6\xed=\x84Z5!\xad\xc6\xb8\xddsi\xebj\'\x1c\xd9Ne\xb8\n\
|
||||
\xb3z!\x89!\xa9b\xa7c\x1c~\xd0\x02\xdep\xf1\xe5\\|\xf2B\xda\x01c\xde\xc5Y\
|
||||
\xb6\x8dm\x98\xd4Y\x9f-%\xa9\x90\xa4Y~,\x183\xa4\x99\xb65A@\x1a<4\xbel\x06z\
|
||||
\x9f\'\xd5\xe3\xd8\x8d\xce\xd0\xd8\x08\x96.\xe8\xc2\xd61\xa9V$ue,\xe5F\x02\
|
||||
\xa2\x94&\xf1^H\xd3GY\xc6h\x92Z \xb2\xa1\x90\xcc\xd2\x91\x94\xb0\xd1\xb6\x8b\
|
||||
\x8a1\x16x\x02\xa2\xbd\x97j%\xe1\x96\xfb\xb7r\xd2\xfdc\\\xf1\x92"hc\x9b\x1d\
|
||||
\xba\xcc\xe1\x94\xa3W\xb1\xe9\x97O\x12bAm\x8cR8\x8a\xd45\x94v\t\xcb\x1e\xc2.\
|
||||
`\xb5-@\x0bIRMpH\xb0b\r\xe10\xedm\x82W\x9eu\x14\xe7\x9fy\x12\x07/\xcf\xa1$X\
|
||||
\x1e\xac/\xc1\xadw\x8e2\xf0\xec\xef\xf8\xe8kO\xa6\xcd+\x1089\xfa\x06\x86\x99\
|
||||
;o!}\x89&\xd7\xd6\x8e\xd5\xe51Z\xa922R!\xb0S:\x9c\x94t\xe01T\\a\xc5\xf2\xf9\
|
||||
\x9cz\xc2I\x1c\xb1j\x01G\xae* \x80\x11@\x11\xe0b\x9b<V\x89q\xac\xb4D\x83\xb4\
|
||||
\x84$\xa3\xbc\xc1\xb1\x16\xe3!}\xa9w\xd3\x8fk\xd8%\xa9\xf2yb\x17\xd2m\x01u\
|
||||
\x15cI\x97\x9ev8r\xd5r~\xf5\xc8v(ta\xfcF\x1a\xa2\xd0\\\x8c\xef\x984#\xdb\xc9\
|
||||
2\x15\x1aw\xa8\xb2\xb4b\x95\xa5\xa9IT"\x8d\xe1\x92\nH4\x1a\x17\xd99\x8f\xd1\
|
||||
\x81\x88/\x7f\xf7\x0eN;\xf5"z\x04\xe8\n\xe4\np\xf9Eg\xf2\xe3{\x1eckm\x14\x02\
|
||||
\x17\x94C\xb1\x98\xc3q\\\xc2ZD\x1a\xd5\x90i\x88\x8e#\xa2\xea\x18+\x97/\xe1\
|
||||
\xd4\x13^\xce\xa9\'\xceb\xf1\x02\xe8q\x8dl\xf4\r\xc2\xe3O\xf7s\xdbo\x9e\xe6\
|
||||
\xb7\x0f?\xcd\xe0\xd8(\x87-\xc8\xe1\xbe\xf9\xa5$qH\x05X\xbba+\xa5j\x8d\xb0\
|
||||
\xae\t\xed\xd0\xe4\x98\xc5\x11N\xc1\xa1-\'H\xc7\x06\x99\x9b\x83\x8b\xcf9\x93\
|
||||
b\xde\xa6P\x80\x97\x1c^\xa0-\xcbP\xcd5\xf9\xb1H\x11H\xa4I\x89nI\x9f\xddY9\
|
||||
\xb7\xfa\xd0M\x8atK\x97\xde\xd4\xe8YU\xcd$\xa1\xe4}J\xbaQ91\x0e.\xbe\x86W\
|
||||
\x9c\xf5\x12\xee{\xe4[&\x7f\xcb\xf6\x11Bd\xbe\xe9\xd8T\x00H0J\xd9\x90\xac\
|
||||
\xb4)\xc8i\xcd\xd2j*z\xe9\x98\x84.\xdfC\x8f\x8d\x80\x90\x04\xb3\x96\xf0\xf0\
|
||||
\x13\x8f\xf0\xef\xdf\xdf\xc2\xbb_5\x9f\xae\x82!\xeb\xc8\xc5p\xf4\x8a\xd9l}`\
|
||||
\x0b\xd6\xec\x83Pr>\xa3\x83\xfdP\xed\x03;bv.a\xc5\xbc\x0e\xce;\xedX\xce:\xed\
|
||||
\x10fw\x8d\xfb\x10"\xe0W\x8f\xc1\x8d?\xba\x87\xdf?\xfa,\x89r\xa8\x8e\x85($Aq\
|
||||
!\xdb\x06\x87\x19\tA\x97\x14\x85Y \xed<q\xaa\xe9\x9c7\x87\x91\xe1~\x1cGr\xc0\
|
||||
\x8a\x05\xec\xd8\xb6\x96\x81\x1d\xeb9~\xd5R\xde\xf7\xe67\xf3\xab[o\xa2\xbbg\
|
||||
\x11\xaf:\xff(c*jh\x1708\xd0GoOwCqgn`#\xc9\xaa\x85\xe9\xc9\xd4\xea\x1e}\xe8\
|
||||
\xc0\x84\xc4\xce}D\xfc$\xd7\xa1\xb0\xb3\xf4@G\xc3K\x8e_\xc6\xd1+\x97\xf3\xf3\
|
||||
g\x86Q\xb1\x85t\x1c\x1c\xd71\xea*N\x8c\xcf5S\xed\x8d\x0bS;\x8f9\xa4\x04\xd73\
|
||||
\xdd\x80\xaa3\xcb\xf3\xe9\xdf\xb6\x03\x1d\xa7x\x07\x1eL\xad\xd0\xc3\xf7o\xbb\
|
||||
\x8b\xcb/\xbc\x9c\xceLBs\xc0k^~"\xf7<r#\xb5\xea\x16\xaa\xd5\x88y\xf3fs\xf4\
|
||||
\xaaS9\xe9\xa8\x15\x1c\xbb\xd2bI\x0f\x04\x8c\xf7v?\xbfw\x1b?\xfe\xe5\xfd<\
|
||||
\xb6\xae\x9fm%\x8b\xfe\xaa$\xd5>xy\x9c EJA\xe2\xbbHO#=(\xcc\n\x08\x81\x07\
|
||||
\x1e~\x8c\xd9\xbd\x8bY\xbbf\x03\x859\xddx\xae\xe0\xd9\xbb\x7f\xcd\xf2\xa3\
|
||||
\x0f\xe6m\x7f\xfeA\xe6\xb5\xd9|\xea\x13\x1f\xe4\xedW]\xc1Y\xa7\x1d\x86\x0bX\
|
||||
\xda\xa4+\xd9\x1a\xe6u\xf7d\x9eA\x00\x0bK(\x92,\x99\xa1\x91\r\xeb\xd0\xda+7\
|
||||
\x8a\x1a`\xd7D\x81F\xdc`\'Z\xfe\x98\x92\x0e\nG(\x14\ty\xcb\xc6/\xc2\xe5\xaf<\
|
||||
\x87G\xff\xed&\xb6T\x07Qa\x8am\xe5\xb0\x1c\x974\x8e\xd1\x02l\' I\x9b\x01\xbf\
|
||||
\xf1\x8e\xaa\x19\xf1\xc9\x8a\xeetBQ\xc6\x04\x95>:u\x95\x9a\xb4\xa8\x8d\x0e\
|
||||
\xe2\x17\x8b\xf4\x0fo\xe4\xa6[\x9fb\xfe\xcb\x0fd\x9e\x1f\xe2j\xc9\xd9G\x1f\
|
||||
\xc0\x95\xe7\x1c\xc7X\x04\x17\x9dv$\x07-k\xa3\xb38\x9e\xabV\x05\xeez\x10~y\
|
||||
\xf7}\xfc\xea\xb7\x0f\x80\x93g\xb4\x962X\x8a\xc1q(\xf6\xf4\xa0\xb1)\x97J\xc4\
|
||||
\xb6\xe9`\xc3\xea(#NJ\x04F\xda]\xa8\xc51k7nd\xf6\xf2\xd5\xec\xd8\xb4\x16\xab\
|
||||
\x90\xe3o\xae\xfd(K\x0f\x80\x9f|\xffn~w\xe7\xcd|\xf5\x0b\x1fa\xc1,\x1f\x91\
|
||||
\x19\xdd\xae0\xde\xb5\xfah\x15\xdf\x91\xe0\xdb\x99\xa3H\x83L\xb1E:\xa1\x1a\
|
||||
\xc6\x82\xac\x05d\x01a\xd1Z\\\x99\xa59\xa5\xae1\xf02\x9d\xaf[\x98\x17z\xdf\r\
|
||||
\xde\'!]"\xb1HU\x8c+m\x12\r/?\xa5\x8b\x1f\xdd;\x0fwC?[\xfaJ\x08R\x84\xce\xa3\
|
||||
\x89A\xd9\xa4"\x1d\'\xba9\xe4hI\xfe\x97\x02\xa2\x14\xa4\x83\x1b\xe4\x18\xd9\
|
||||
\xb1\x81\xae \xcf\x9cb;\xcf\xec\xd8\x84Wpq\xd3*\xb7\xfc\xe0{\xbc\xf3\xdc\x0f\
|
||||
\x85G\x1aV\xe9\xf4=\xdeu\xe5K(\x16\xc1\xcd\xdc\x97\x03\x11\xdc\xf5\x871~r\
|
||||
\xd7\x03\xfc\xfe\xa9\r\xec\x18\xaaPM!\x16.\xda\xb6I\xed\x0eh\xb3@\xa5\x8c\
|
||||
\x95C\x10%\x84\'\xd1q\x82\xdd\xddER\xaf\xa0\x92~$&\xdf\xac\n\x0c\xf4\xef\xa0\
|
||||
\xa7}\x05\x95\xe1m\xbc\xfd\xea7q\xe1\x05\xf0\xb3\x1f\xc3_\xbf\xfb\xb3\x9c\
|
||||
\xb4j>\xdf\xf8\x97\xeb\x98?\xdb\x1c\xd6\xce\x08\xac\xd7\x14\x05W\xe2\xb7\xe5\
|
||||
ZF+\x13+kdV\x9c\xd4,F\xcd\xde\x13=IT\x92\xf1G\xa8\xb5I\x8e\x10b\xcf,k\xad\
|
||||
\x9b\x99\xbf\x8d\xfd\x1b\x9f\x1b\xdb\xf6\x92t\x07)-\xdc\xacO\xb1\x84\x91\xaa\
|
||||
\xbf\xfd\xcbsx\xc3\xbb>\x8f\x1d\r\xe1\x06s\x88\x1b\xe3M\xaf\x88\x96\x05\xa3\
|
||||
\xe6\xa3(;\x84c:\xb3\xd48lp\x02s*\x1d3\xa8\xa0\xadk\x01\xe5\xb0Dep\x0b\xb3\
|
||||
\xad\x84\xbcR\xac>d1\xe7\x9ev,\x96\x80\x10\xc9`I0\xdb\x87\xf9E\x18\x0ba\xc3\
|
||||
\xa0\xe6\xab\xdf\xbd\x9d\x1f\xde\xb3\x96\xedQ\x11\x95\xef!\xa1\x17\x9cQ\xa4]\
|
||||
G\x08H\xb5@[\x018y\xa8W\xa1:\x08N\x9d|\xb1H\x19\x1b\xe9\x17`\xc7v\xba\xba,\
|
||||
\xbc\x10\xda\x1d\xd8\xbc5&G\xca\xeaUs\xb9\xfa\xbd\xaf`\xf3\x08\xfc\xc5{oc\
|
||||
\xeb\x9aG9xn\x8e\xeb>p)\x07\xb4\x8d\x9755\x0c//\x90M\x12\x1b\xf9i;[\xd9\xa2\
|
||||
\xf5\x01?G\xdf\xfe\xbf\xc1d\r\xa3\xf1Y)\xf5?!\xdd\xa8\xe8V\xd5\xe4\x02\xdd\
|
||||
\x12\xde\xf7\xa7o\xe5\x9a\x0f\xff\x03a\x181T\x1e\x00\x7f\x16\x08\x1bj\x11\
|
||||
\xe4\xf2\xe0{\xc84E\xa5!\x12\x8d\xe5X(\x95\x92\xd6\x86 \x8d\xb0\xf3.V\xbdDyd\
|
||||
\x1b\xbd\x05\xc9KO_\xcd\xb9\xa7\x9f\xc8\xaa\x03\x1d|\x0b\xba\x0b0:\n\xbe\x07\
|
||||
\x1d\xb3\xf3$@R\x8fy\xe4\x91\xb5\xbc\xfd\xfd\x9f\xc5?\xe0\x18\xd6\x0f\x01\
|
||||
\x9d\x9d\xa0\x02\x88k\xa0$\x85\xf6N\xc2J\t)-T\x14\x9a\xc4\xb8\\\x80=g.Vm;\
|
||||
\xe5\x1d\x03P\x9cEt\xff\xfd\xc8\x85]ty\x92.\x17\xa8%T#\xc1G?\xf1i\x96\xac\
|
||||
\xb4\xf8\xd1m\xc3\\\xff\x95o\xe0\xb8\x16\x9d^\xcag\xae\xfd\x13:]c\xa6\xee6\
|
||||
\xe0\xb1oGS/\x08\xf6\xaa\xd1I\xa0\x08\x1c<\xc7\xe7\x03\xef|\x0f\x9f\xfa\xd27\
|
||||
\xb1;\xbb\x19S9\xac\\\x07\xa3\xa5\xbaIF\x93\x1a\xdbQ8D\xa4a\x15\x15W\xf1,(\
|
||||
\xfa)\xbe\x18\xa0\xd7s8\xe9\xd4c8\xef\xec\xd7pp\x16\xc4P\x98\x86\xa5\x81Q`\
|
||||
\xfd\xd0\x18\xbf\xbe\xff).~\xd91$qL\xbb/8\xfa\xd8\x83Xt\xe8\xa9<S\n\x08zSB+D\
|
||||
\t\x05i\x1d\x11\x85DC)\x8e\xe3\x92*\xc0\x89\xc1\x11@\x95\xa4\x1c\x93\xc4\x16\
|
||||
\xf8\xb3\x90\xae\x8b{\xf0"r\xd10\xb5\x91\xed\x0c\x0eV\xe9\xe9\xca1{)\xdc\xf1\
|
||||
k\xf8\xfbk\xbe\xcb\x86\r\x1b\x98\xdb\xddEyp\x0b\xef\x7f\xd7\x9b\xe8\xb4 \x10\
|
||||
{ \xbc\x05i\x9abY\xfb\xce\x81\xf2\xc7\xc4^\x91\xeed\xdd\xc4\xe2N\xc8\x1f\xdb\
|
||||
\xc6\xba\xb5\xa7\xf2\x99\xaf~\x1f\xb7{\x01\xa5r\t\xd7/\xd0\xd6\x9d\xa3V\x1aD\
|
||||
\xc6U\x8a\xae\xc2\xf5\xeb\x14:m\x0e9h9\xc7\x1d\xbe\x84\x0bN_Jo~\xbchO`\xba\
|
||||
\x8d\xe1\x14\x1e{&\xe4\xc1G\x1e\xe7\xe7\xbf\xb8\x83\xca\xe80\xfd\xdb\xd6Q\
|
||||
\xaa\\\xcdU\x17\x9d\xde\xac\xf7z\xef\xfb\xae\xe0\x92\xb7}\x15\xdd\x96G\xd5k`\
|
||||
[XB\xd2Y,P+UH\x13\x81\xf4]p]\xe3\x9fO#\xd0\x02\xcb\xb1\t,(\x97\x07\xc9\x17\
|
||||
\x1d\x866\xaf\xe5\xb4c\x97\xd2\xd9\x9dc,\x86/\xdc\xbc\x85/}\xff\x97\xa8(DhI2\
|
||||
\xb6\x83W\x9f}<\x97\xbfl>\x05\x8c\xd5])W)\x14r\x93?\x9c\x0cS\x8d\xf4=\xd9\
|
||||
\x03{E\xba\x00t\xa5N[\xdeG\xe4\xe0]o:\x14%\xeb|\xf7\'\xbfF\xfb\x8ajT\x82J\
|
||||
\x8c\x9b\x96\x99U\xb09\xea\xf0e\xbc\xf4\xd4c9\xe6\xf0\x85\xcc\xca\x19\x97\
|
||||
\x8e\x93@:\x16\xe2\xe6=\xa4\x84\xa7\xfa\xe0\x87?\xbd\x97_?\xf0$\x83UM\xdfP\
|
||||
\x19\xcb\n\x08\xdc\x1c\xb3\x97\xcc\xe5[\xdf\xbb\x9b\xf3\xcf>\x9d@A\x90\x87Es\
|
||||
`\xd5\x8a\x05<\xf0\xf4:\x8a\xdd\xbd\x94\xab!i\x12\xa3}P\xbe&\xd6\n\xe9\xb8&\
|
||||
\xb9\xa2\x12\x82kS\xec\xca\xe1\xd6G\x18\xda\xbe\x91\xce\xce\x02VX\xe6\xeb_\
|
||||
\xf88g\x1cl\x0c\xe9\xba\x05Oo\xafR.\x0b\xe6,ZLi\xc3\x83\x9c\xba\xfa >\xf6\
|
||||
\xce\xb3\x08\x07\xab\xf8]\x86\xe8B~\xcf\x84\x03\xb8\xee\xeeJ\x0b\xa6\x1e\xf6\
|
||||
\xd2\xa6H\xf0\xac* \xc8I\x8f\x04x\xfb\x95\xc7\xb0f\xcd\x83\xfc\xfe\xf1g\x98\
|
||||
\xd3\xd9\xc51\xc7\x1c\xc5\x19/9\x91c\x0f)\xd0(\xaf\xf70\xaa\xb1\x86\xc9%\xac\
|
||||
[\x1ew\xdc\xb3\x9e[\x7f\xfe\x1b\x1e^\xbb\x9d\x92\xca1\x1c{\x0c\x0e\x878\x9d\
|
||||
\xf3q\x1c\x87\xc1\x91~FD\x9dy\xf96n\xfa\xc9\x1a^\x7f\xd12J5\xf0\x02\xf8\xdb\
|
||||
\xf7\x9c\xc5\x1b\xff\xfcK8Z\x10\n\x8f\xc4\xf1\x19\xacU!\x8e\xf1\xbb\xda\xa8\
|
||||
\x97\xab\xa0\x03hk\x87\xb0\xcc\xd8\xda\xa7\xc8\xbb\x15\x96\xf5\x16Y\xbct\x11\
|
||||
\x7f}\xcd\xd9\x04\xc0wnz\x94KO=\x948\x80{\x1f|\x0c\n\x05\xfa\xd6=\xc3l\'\xe1\
|
||||
-W\\@\x00\xb4w\xb8\x10\x97Mq\xa30\xc9\xc5\xff\xbf`\xefH\x17\x1a|\tz\x8cz\xad\
|
||||
D.7\x0b\xe9\xc0\x97\xaf}+w>\xb8\x9e\x13\x8e\\\xdc\xdcUc\xaaE\x1c\x8c\x1a\xdf\
|
||||
0\x1a\xf3\xe8\xa3\xeb\xb9\xe5\xd6\xfbX\xbba\x98\xbe\x81\x11\xf0\xda\x91\xb9\
|
||||
\xd9Tt\x8e\x98<\xf4\x16\x89\xcb5b7 7\xbb\x8b\xb1\xcdOS\t$_\xfa\xfa\x0fY}\xd8\
|
||||
{9|\xb9)0=a>\x9cv\xc8B~\xfa\xbb\x8d\xa4\xb9y\x88\xf6N\xa8h\xc8\x07\xd4\x85\
|
||||
\x03\xaa\x0eR\xd1i\x01i\r\xe9\xa5\x1c\x7f\xc4R^z\xc6I\x9cs\xc6\\\xb6\x94\xe0\
|
||||
\xc3\x7f\x7f#\xb5\x81\x8d\xbc\xf9\xa2C\xd9T\x02t\x0c\x952\x8b\xe7\x15\xb8\
|
||||
\xf6\x1do\xe1\xa8\xa56n\xac!-\x83cS\x1d\x19!\xd7\xd9\xb3\xcf\x1f\xfc\x8b\x89\
|
||||
\xbd\x94ta\xf4\xa1\xed\x92\x0f\xac,\xc6+\t\xeb1g\x1f\xb9\x98jb\xb2\x98\x1aS`\
|
||||
\x85\x11\xdc\xf1\xc0Fn\xfd\xc5\xafy\xf8\x89\xb5\x94"\x97\xaa\xee@8=\xa8Ys\
|
||||
\x88\x12L$\xca\xce\x83]0\xc1\x89B\x11$TGFi_\xb0\x98\x91\xe1\r\xb4[\x01_\xf9\
|
||||
\xf6\x1d\\\xfbWg\xb2\xc0\x85\x91\x11\xc5\xbb\xdex\x01\x0f<\xfeyv81\xb5$6\xd3\
|
||||
4tuC\xdf&\x9c\x9ev\xfcz\x85\xe15O\xb0pV\x1b\xaf~\xf5\xb9\xbc\xf2\xc2\xe5\xcc\
|
||||
i\x87_\xfcA\xf3\x91\x8f\xff#\x96\x17\xb0\xa0\xab\xc3\x14\x1d>;\xcc\xf6\xf5O0\
|
||||
\xe7\x80\xa5\xbc\xf1\xbc\x938\xfbp;SK\xb1q\x19\xc7)\xb9\xce.j\xf5\x90 \xd8\
|
||||
\xcd\\\x1eS\x14\xa6\x06\x7fr\x7f\xc0^\x92n\x83\xdd\x91\x1dl\xdc\xad\xd8\xe3\
|
||||
\x9b\xa8[\xce2\xdd\xe8\x1f\x1e\xde\xc2\xb7~\xf83\xee{r3e\xab\x8b\xe1\xd4\xa7\
|
||||
"\x0fF\xe5\n\x10V\xc0r\x8c\xcbV\xa6\x99w*\x02Q6\xe3\xdbJ\x05:\xda\xc1\xae0Z\
|
||||
\x1d\xa5\xa7\xbb\xc0\xf6-\xfd\xdc\xbf\xf6\x19\xfe\xfb\xce\x83\xb8\xec\xc8\
|
||||
\xb9\xcc\xee\x94\xd0\x06\xab\x0f\x9f\xc5\x9dkK\xd4\x12\t\x85\x1e(\xa7`\xe7\
|
||||
\xc8\x87\x15D\xe9Y\x8e[\xd5\xce\xdb\xdf>^\xd7\xda\x00\x00 \x00IDATt%/9\xb6@\
|
||||
\x7f\x15\xfe\xe9+O\xf0\xfd\x9bo\xc2o\xefd\xc3\xf6\x11\x0e=\xec\x08"`\xa0o\
|
||||
\x0b\xf9h\x07\x97\x9e|\x0e\x7f~\xd1\x12\xda\x00\xdb\xcf&\x1a\xc0\x03O\xa2\
|
||||
\x85\xc4\xdd\xcf\x08\x070s\xdcLN\xfa^\x8d2\x1b\x89\x90\t&Hf\xf2\xce\xc0R\xe6\
|
||||
e+(H\xf8\xd5m\xbf`\xfd\x9a\xcdD\x91\xc7\xb6AEd-@yK\x81^(\xce1N\x1a!\xc1s\xc1\
|
||||
\xb3L.t}\x04\xc2a\xc8\t,+\x04\x99\x80\x8a\xa9#H\x82\x02\xcf\x0e\x96\xb9\xe1\
|
||||
\xc7?\xc7-Hv\xf4W\xd1\n\xfe\xeeo.G\xd6w\xd0\x11\xc4\xb0c\x1d\xae\x88\tt\rF\
|
||||
\xb6\xf0\x96W\x9f\xcd\x97\xaf\xffSN?\xb6\xc0\xe3\x1b\xe0\xef?\xf3[\xbe\xf3\
|
||||
\xdfw\xa3\xbdN\x06\xcb\t\x9d\xf3\x96!\x83NB\xe0\xee_\xde\xc6\x15\xe7\x9d\xca\
|
||||
\x9b/:\x9ev\xc0V\x15PY\xa2\x88\xb4\xb3\x18\xf8x\x1a\xfa\xfe\x85h\xb7\xdf\xec\
|
||||
\xb5k!my\xa9\xe6h`\xbc\xc4G\xa5\xf0\xa1\x0f\\\xc9Y/;\x83|>\xc7\xac\xd9s\x88\
|
||||
\xb4\x00\xe1A52\x81\xf2j\x19\xc6F\xa1V\xc6K*8I\x05WU\x08D\x84\x1dUp\xc3\xd0x\
|
||||
\xf0\xf0\x08S\x1f\xa7m>8\xb3\xb8\xef\xe9~\xae\xff\xd6]\xf8sr\xd4S\xe8\xb4\
|
||||
\xe1\xdc\x13V\xd3\x9d\x0c\xd0]\xac\xe0\x0e=\xcci+;\xf8\x8fO\xbe\x9b\xb7\\v\
|
||||
\x14\xed\x1e\xdcy\x7f\x85\xbf\xf9\xc4\xd7\xf8\xc9\xef\x9e\xa0\xec\xcfB\xe5\
|
||||
\xbb)G\x92r"\xb0\x1c\x17\x12hs\x15o\xb9\xf4\\\x0e\xea\x06K\x95AU\xcd\x1df^\
|
||||
\xc8\x98\xf1.k\x7fC\x9a\xec\x03\xd2\'B\x81\x88A\x86F\x8d\xc8\x1a\x8eg\xb4\
|
||||
\xe2\x9f\xbe\xf5d^{\xd9\xb9xv\x85\xb6\xa0\x0e\xd5\xcd\xe0\xa7Y\x0c\xde\x04\
|
||||
\x96e\xb5\x8a,W\xc8%\x8a\x82\xb0\xc9i\x0b]OH\xea1\x8e\x95\x03+O\\V\xc4*\xc0n\
|
||||
[\x88,\xce\xe5\xcb?\xf8\x19\x0fo59\xf5I\n\xef\xbb\xfa\xe5\xe8\xadOrX\xaf\xe4\
|
||||
\xcas\x8f\xe6C\xd7\x9c\xc3A\xcb\xa1\xe0\xc2\x7f}\xe7I\xde\xf3\xfe\xeb\xd88\
|
||||
\x10\xa2\xf2\xdd\xd4\xb1\x19\t5^{\x0fq\xa9B{!\xc0Vp\xc5\xc5\xe7q\xd8\xb26\
|
||||
\x920+\xc3\x990\x9b\x83\xc1\xfe\'\xe1\x06\xd2\xde\xfd0s/\xfbt\x85\xd5\xc8\
|
||||
\xf1\xca\x1e\x8a6s\x13fQ#\xb3\x8fR\x82j\xd5\xe3\xaaK\x96\xd2\xb5\xa0\x83\x8f\
|
||||
~\xf6k`\x07DI;I\x1a\xe0{yl\xcb!\xa9\x8c\x81\x8aq\xa5\x8bR\x16\xb5z\x8a\xe7uP\
|
||||
\x8b\x04\xe0\x99. \xac@\xaaIr\x16Z\xe4\x19\xf5\xba\xf8\xc4\x7f\xdc\xc4\xbf|\
|
||||
\xf0"\xf2\xc0\xac\x02\xbc\xeb\xf2\xf3Yr\xf8*\x8e:v\x11!\xd0W\x85\xbf\xfc\xe8\
|
||||
\x0fx\xe0\xa1\xb5\x14{\x0fg0\xc18k\xc6J$qJ\xd0\xdd\x89\xd0\x8a\xde\xbcC^\xc3\
|
||||
\xc9G\xaf\xa2\x02hG\x80\xf4\x8c6B\x820\x81\x92?V\n\xf2\x0b\x81\x88\x80\xddY"\
|
||||
{%\xe9f\x94\xaa\xb2)\xed$f\x1eDS0\xa8\xb3W\n\xb8\x96Ew\xce\xc2\x03.8\xae\x8b\
|
||||
\xaf\\\xf7.\x0e\xed\x8d\xe8T\xdbP\xd5a\xa2Z\x9d8J\xd1\xc2\xc1rrh\xdb\'\xc6\
|
||||
\xa1\xa6$\xd2+\xa2\x95DG\xb1\x89\xca\x15r&e8\xae\x91\x86!i~\x16\xf7<\xbe\x9e\
|
||||
\x1f\xfed\xa3\xb1\'\xca\xf0\xee7\x9d\xcbK\x8f]D\n\xdc\xfd\x84\xe6m\x7f\xf5\r\
|
||||
\xee||\x0b\x03\xa2\x8d-\xa5\x10\xa7\xd8\x8e\xaaW!\x08 \xdf\xc6\xd8H\t_\xa4\
|
||||
\xe4\xa8\x1b\xdf\xbb\x0e\xa9D&6\x14\x11\x80\xcc\x9b\x94m\xad\x10\x848Y\x94l\
|
||||
\x7fDy\x0f\xf2\xbcw\xea]KH\x1dH\x02P\x1eB{h<R\x02"\xf2D\xe4\x19\xaeh\x14\x0e\
|
||||
\x1am\n\xf2\x14\x9c\xb8\xd0\xe6[\x9f|7\xa7\x1d2\x97\x05\x0b\xba\x08\x1d(\x87\
|
||||
e\xca\x16D\x81\xcb\x88\x80\x92\x05\xba\xad@YG\x10X\xe0& \xc6p\xbc\x1aA\xae\
|
||||
\x86\xef\x0c\x82]\'J}\xca\x91\xcbm\xb7\xdf\x8cH\xc0\xf7\xc6 \xae04\x04\xff\
|
||||
\xfe\xcd\x07\xb9\xfa\xff\xfc3\x9b\xc2Nj\x85y\xf8\x0b\x17S\\0\x8b\xd1\xbe\x8d\
|
||||
P)C\xa4p\x82"\x841\x81\x8cY\xb9\xb0\x0b\xa1b\xd01\x910\xe1\xd52P\xc73\x01$RP\
|
||||
!B\x87\xcf1{\xcb\xd4E\xf8\xdc99{\x81F\xdaN\xa6\xf3v.\x7fn\xcb\x17\x10H,e<qm\
|
||||
\xd2\x10\xef\xd7k\xfc\xf3\x87_\xcbY\xc7\x1e\xc0\xb2\xd9 t\x19\xd7J\xd0\x96m2\
|
||||
o\xd2\x04r\x0e$\x15\xc8K\xc8I\x88*\xc4\xe5\x01\xd2\xea\x00"\x19\xa2 +\xf8\
|
||||
\xf1\x18\xc7\x1f\xb8\x84O]\xfb\x0e|\x07T\x14\x83\xeb\xa2\x1d\xf8\xef\x9f\xde\
|
||||
F\xb1\xd0\xc5\xd8H\nv;\xb5\xb1\x1a\xa3\x83\xdb\xa1\xb3\x00\xf9\x0eP\x82\xb8<\
|
||||
L\xbe\xd3f\xe9\xbc6N=\xae\x83\xc6\xfc\xed9g\xdc\xd7f,u\xcbH{\x16&\xb5&\x95\
|
||||
\xf6F\x177n\xdcN\xb5n\xc0\xdf\xc3w{Ozc^\xbdl~L)\xcc(\xd0\xce^\x8d\xff\x1d\
|
||||
\xd9\x98%\xd5\x94\x9b\xcdj\x0f(\x02\xff\xf0\x96\xa3x\xc7Y\x0b9\xa2+\xc1\x1e\
|
||||
\xddN\\\xa9`\xb5\xb5CG\x01\xa2\x12\x144\xd4\x06\xa1V\xc1w\x1c\xe6\xb4u\xa1+U\
|
||||
\\"\xda\x19\xe5\x9a\xf3\x8e\xe4\xcb\x7f\xf9r\xe6\xfa0R\x85\x11\xa7\x8b\x92p\
|
||||
\xf0\x8b\xf0\'\x7fz\x19jp\x03\x8b|\x9bB%\x85\x8a\xc6\xebn\x83\xda\x18\xe4:\
|
||||
\x8d)^\xde\xcc\xc2\xb6\x903NZE\xff\x08\x84\xb6G"\\\n@\x1b&=\xcb\x06blR\xf2 r\
|
||||
\xe6\xaet\x8a\xd0I37\xa45\xd5\xc9d\xfa\x8f[\xf9S\t\xb9\xc6\x0cZ\x93`\xefHo\
|
||||
\xc9\xeal\xfc\xdf\xd8\xd4\xc8\x0c\x11{x\xb9(\xf2*\xe2\xed\x17\xac\xe6\x1f\
|
||||
\xfe\xeaj\xce8r)A<B:\xda\x07\xe1\x88\t\xd8[\xc2$_T\xabx\x96\xa4\x7f\xd3zf\
|
||||
\x05\x16\x0b\x8b\x16\xd7\xfd\xd5\xdb\xb9\xf2\xac#X\xdemB\xf7k\xfb\xe1\xbd\
|
||||
\x1f\xffO\x9e\x1e6\x93\x03\x9d}\xe2b.?\xf74\xca[\xd7\xe0*\x10\xd2&,Ua\xee\\\
|
||||
\x18+A{\x9e\xb6\x0e\x0f\xea\x83\xcc\xed\xca\xd3\xd1n\xc8\nS\x93\xff\xeek\xd3\
|
||||
\x7f7\x885s\xc3I\x9a\xd3\x7f\xb7d\xa34*l\x9a\x1f\x99z\x84\x03\xc8\xe7M\xfa\
|
||||
\xf3\x84\x00<iS\x1a\x1c\xe5\xb8\x95\x0e\x9f\xfb\xbb\x0bx\xfb\xabN\xa6S\x0cBy\
|
||||
\x00\xd7\xb1a\xb4\x0e\x91\xc0\x9b\xbb\x80\xd1\xd2(]m\x16G/\x9f\xcd-\xff\xfan\
|
||||
\xceY\xdd\xc9\xc2y0\x96\xc2-\xf7\x0e\xf1\x86\xbf\xba\x8e[\xef{\x86O|\xee\xbb\
|
||||
\x04@\xbd\x0eW^z*\x9d\xf9\x147\x9fe\x96\xe5\xbba\xa4\x0ev\x82\x15\x0e"\xa3*\
|
||||
\'\x9fx\x02C\x03\xfd\xe4\x84I\xf4\xb1\xa5\x95\xa5\x1c\xa7H\x93\xc3:i\xdd\x01\
|
||||
\xd9\x04\x84\xe3\x9fu#\xe7u\xf2\xfd\xa7\x00\xd4n\xbcq\xf0\x82\xd9(\x92$\x8e\
|
||||
\x99\xd3\xddNA@\x8f\x03\xef~\xfdJ\xaey\xc3\x05\xcc\xcb\xa7Dk\x1f\x07Kc\x17|\
|
||||
\xc2\xd2\x0e<\'\xe4\xca\xcb\xce\xe3s\xd7\xbe\nQ\x86<F\xfa\xfe\xed\xbb\x0f\
|
||||
\xf0\xa1\xeb\xbfB_\xdc\x86\xecY\xcem\xf7<\xce}\x8f\x85\x14}Xz\x00\\\xf4\x8a\
|
||||
\xd3)W\xb6\xe0\xb4\xdbf&\x84\xe1\n\xdd\xed\x01\xe9\xd8v\x1c\x12^{\xf9\t\xfc\
|
||||
\xfe\xfe\xfb\x01c\x93\xb8\x96d\x8f\xae\x97\x9d\x18U\x13\xfeSMM7\x15\r\xbd\
|
||||
\xf8E\']\x83my\x10kl\r\x81\x86 \x86\xab/\\\xc6g\xde\xff\x0eN\\\xb5\x88|\xb5\
|
||||
\x8f\xceh\x07\xf3sU\xae\xfb\xc0\xd5\xbc\xf5\xd5\x07\xa0\x80\xb6\x02\x94\xea\
|
||||
\xf0\xb5\x9b\x1f\xe7\xdfo\xba\x9d~U@t/f t\xf1\xba\x16\xf3w\xff\xf0\x15\xfa\
|
||||
\x86\xcdi.\xbf\xe2H\x82\xa0D\xc1\xab\xc2\x8e~D{\x0f\xb2V"\xa7\xab\x9c\xf9\
|
||||
\x92S\xb0$\x94F\x86M\x97#M\x86:il\xca\xae\xd0M\x1fDv\xc9\x19\xb2\x9c\xb3\xe6\
|
||||
G\x9d}\x99\xcdx\x91\xed\xa1\xd4\xd4R\xf2\xbb,\x1d\xd2\x82\x17\xac\x91F5S\xad\
|
||||
Y+\x8f\x10\x87%\xda\x1d#\xc1\xc7.\xb2\xf8\xd6\'\xaf\xe0\x1d\x17\x9c\xc8\x11\
|
||||
\x1d\x117\\\xff&.\\\r\x8d\xa5q\xaa\xc0\xbf}\xef>>\xf1\x95o\xb3\xa9*Y\xb0\xf2\
|
||||
(F\x9fXKj\xe7\x19\x8b]\xb6\x95|>\xfd\xa5\xbb(\x01\x9dyx\xfdk\xcf\xa6>\xf2\
|
||||
\x0c\x9e+\x08\xc2\x98x\xb8\x9f\xee\xb6\x1cW\xbd\xf6X\xbes\xc3}\x1c|\xe0\x8aq\
|
||||
\xe9\xd4\x8dt\xe4\xd6\x9a\xb1q\x8c\x13\xbf\xf3cjH\xban\xaaxg\x1f\x97\x1e=_\
|
||||
\xa4{\x18O\xbc`Wj;f\xad\x11\xbf\xd8\x86\xeb{\x94+C\xc8$fQ\x0e\xe6\xc6\xf0\
|
||||
\xfeKN\xe0\'\xd7_\xcd\x812\xa4\x07S\xc40\x9a\xc2\xb5\xffz?\x1f\xfe\xd2\x0f\
|
||||
\x18t\xe7"f/a\xfd3\x1bpV\x1e\x86\x9b/\x10)\x8f\x8a\xe8\xe5\xee\xc7w\xf0\xc3_\
|
||||
\x0c1\x00\xbc\xe1\xc2U\x1c\x7fp7\xf3\x83\x145\xd8\x87\'SN9\xe9D\xe6v\xc2\xbd\
|
||||
\xf7\xdc\xc3\xa2E\x8b\x80\xcc6\xd3\x1a3\'\xba!\xbd\xd1\xaf\xef\xf2\x88Z;m\
|
||||
\xdd\xfa\xae\xa6\xec8\xde\xdb\'\xe3\xf4\xe7\tag\x05\nqL\xa8"\x8a\xf9\x00\xdf\
|
||||
V\x888\xc5\x93\xd0\xe1\x87XI\x8d\xd9\xb9\x1a\x05j\x08\r\x1f\xbf\xeek|\xe9\
|
||||
\xff~\x87E\x87\x9fD\x12t\x10\xd6\x12h\xef$V\x9ah\xd36\n]s(\xa7\x01\x9bG\x14\
|
||||
\xd7\xff\xeb\xd7\x19(\x19\xed\xf0\xb6\xd7\xbf\x8a\xda\x8eMty\x82\xae\xc0\xe6\
|
||||
\x95\xe7\x1f\xcd\x86m`9\x81\x99p7+\xb85\xde7\x9aD\x8a]\x94z\x86\ts\xc6\x8b\t\
|
||||
U\xb9\x12\x85T\x8a8\x8e\xff\x88O\xef\x7f\x0e\x97\xdd_\xcf\x0bB\xba\x16\xd9,S\
|
||||
\x12\x1c\xc7\xc3\x95.\xb2\x11\xa1\x93\xcad\xaf\x10\x9by\xc7t\x8cV!?\xff\xe9m\
|
||||
<\xf9\xe4\xe3\xd8\xb6M\xa9T2\x95\xa0(c\xaa\xc7\t\xcc\xea\xa5\\\xae\x83W\x00\
|
||||
\xbf\x00^\x9e/~\xf9\xbf\x18Tp\xf4\x81\x1d\x9cu\xfa\xc9x\xaa\xc6\xb1\x87.\xe3\
|
||||
\xb0\xc5\xf0\xe0\x83\x83l\xeb\xebg\xfe\xc2\xc5(\xc0u \tC\xe3o\xdf\xc3rV{k\
|
||||
\x9a;\x93M\xab\xf6"\xa2^\x19\xd8\xedw/\x98\xa47\xc2\xb1\xa6\x0f43?5EL\nSK\
|
||||
\xec\x14@\x06h\xe9s\xc6\x19g\xf0\xbew\xff\x19\xaf8\xed(j}O\xa1\x867c\xcb\x14\
|
||||
+\xe7\x9b\xf1V\xaa!\xc8\xe3\xe5\x1dR\x15R.Wx\xe4\xd1\xa7\xf9\xf5o\x9e \x01\
|
||||
\xdez\xf5\xc9\xb4\xb7\xb9\xbc\xee\x92\x97\x91\xc6p\xef\xbd\xf7\xa2\x84G\xef\
|
||||
\xfcN,a\xe4\xd4\xf6\xf2 mT\xad\x96]\xa5\x98\\]O\x14\xfb\xf1\xe2\x06hv\x08SM\
|
||||
\xd2\x0b\xf6\xee\xa9}\xc1\xe6\x86m\\\x82\xdd\x9c\x16_e\xb5\xba\xa6\x0e$\x05\
|
||||
\x12\x0b\x12<"\xa0\xcd\x83\xb3\x8fY\xcc\xbc \xcf\xc1\xbd>\xdf\xbc\xedN\x94\
|
||||
\xdb\xce\xa6\xda\x08\xa8"t\xcc\x81\xb1\x12\xe1\xf0\x00\xb3{}\xca\xfduB\x0b\
|
||||
\xbe\xf8\xd5\x9bYu\xf8J\x96\xf5\xc0\x9b\xdf\xf6\x06\x8e]\x01}\xa3\xf0\xe0\
|
||||
\x03\x0fPS6\xdb\xb6\xa7\x1c4\xcf\xa2\xd0\x1c\x8eI\xa3\x8a\xb4\xdc;\xa9n\x96m\
|
||||
\x99\xdfj\x00\xadQj\x8aE\xdd\xe5T\xe8\xd3i\xf8\xb8uK\r\xafefi\xb0\xa0\xa4\
|
||||
\x8d\xa5\x9e\xa51\x00\xc6\x87\x7f\xca!\xb3\xf8\xdb?\xbb\x80\xf7]u!\xc1\xd8V\
|
||||
\x18\xde\x82\xd7\x93\xb9X\xc3*N\xb7O\xa5\xbc\x83 \xc8\x13%\x01\xa3\x95\x80\
|
||||
\xf7\x7f\xe4\x87\xc4\xc09g\xe7q\x81;o\xfb5ZX\x08\xb7\xc0m\xbf\xbc\x8b0\xcb\
|
||||
\xd6\xaaE\x1a\xb0\x90\xb9\xfcs<\x8a\x9d\t5\x8e\xe6\xd6A\x9e\xe7M\xad\x94\xaa\
|
||||
ZR\xdc\xedw/\x98G\xae\xa1\xd6\r\xe1.\x86R\xb7\x99\xa5b\xd9\xe3\x93\xeb[\x8c\
|
||||
\xe7\xca\x0b]\xc3\xd55\xae:\xffT\xde\xf3\xba\x8bX>\'G\xb8\xe1qS\xd1\xd8\xe5\
|
||||
\x12G;PVB\xa8l\x84=\x0b\xd7_\xcc\x93\x0f\xae\xe5\x86\x1f\x0f`\x03C\x031w\xdc\
|
||||
\xfe3\xa4\x9b\xa3\xd09\x8b\x07\x1f~\x92j\x9c\x15]$\x98\xeb\xc1\x9e\xa0\xb2\'\
|
||||
b\'\xc2\x9b\xd5\xa3V6-\xe9\xc4B\xc2\xa9\x02\xb9\x07;\xe5\x05\x92t\x13\x9f\
|
||||
\xceRj1\xe1\x19\x0f\x84\x89\xc3\x0b\x146f\xdc\x9e\xc7\xe4\xdc\xb9\xdaT\xa9"\
|
||||
\x14Im\x8c\x9cT\xbc\xf1\xa2\xd5\xfc\xc5U\xafd^\xb7\x84\x91\x8dP\x1d\x00\xaa\
|
||||
\x90\xf7\xa8\xc9\x02\xb1\xecbxX3{\xc12n\xbe\xe9\xbfP@W\x8f\xc3\x8aU\x873:V\
|
||||
\xa5\x16C\x7f\xa9\xc2\xc3\x8f\xd5I\x01\'\x10\x99\x05\x9fi\x9f=\\\x7f#\x88d\
|
||||
\xd0\x90\xf4,\xc26\x05I\xdfS\xb5\xcd\x0bF\xba\x91c\x93O\x97\xca,\xedI\x98\
|
||||
\xef\\\xaa\xe4T?yJ\xe4SE!\xc2,b\x0cD\xe4!\xd7\x03R\x12\x8d\xc2e\xa7\xcf\xe6\
|
||||
\xb3\x1f|\x0b\xf3;\x81\xda\x00]\x8b\xe7S+WP\xf9\xb9TF-\xda\xf3\xb3\xa9\xf4\
|
||||
\x0f\xb0j\xe9,\x06\x06+\xa4\xc0\x85\x97]\xca\x8aC\x8ff\xb8TCaq\xcb\xad?\xa5\
|
||||
\x9a\xad\xdf\x93*\xcd\x1e\xe7`\x9d\x8cKm\xdc2\x8d\xcc\x9a\xc8q\xa6\\\x9f>\
|
||||
\x05$}\x1c-3\xd3\xb4\xcc\xc3\xa2\xcc?*\x06\x1d\x9a\xb5D]c\xf1\x9b\xc9\xb8$\
|
||||
\x90P\xc8k\\\r\'/\x83\xaf~\xfc\r\x1c\xbf\xa2\x97\xa1{\xee\xa0\xd8\xde\x85.\
|
||||
\x83\xd5>\x8f(L\xb1-X\xbet6\x0b\xba\xf3<\xb5\xb5F\xef\\x\xcd\x15\xe7\xe0\xd9\
|
||||
)\xbeg\xf3\x9b\xdf\xdeK\x98\x18)\x1d\x1e\x8b\xd0\xc2Fc\xd3X\x19a\xbc;\xca\
|
||||
\xd2\xa1[\'\x01\xda\xa9\x814#\x8dS\xa8\x8e\r\xa6\x04\xe9\x12\x13\xd6w\xccR\
|
||||
\xd3\xc2\x14\x96\x9a\x95\xd0$\xc6\xff\xd6\x06\xa2\x90\xe5\xc6\x9b\x9f4\xf2\
|
||||
\xeb]b\xb0\xca\xc4\xaa\x1ft\x8d<p|\x0f|\xe8\x923\xb9\xfc\xd4\xe3\xb1\x9ey\
|
||||
\x96\x0e\x02\xa8*,K\x10tx\xf4,\xe8$\x02n\xfe\xd5]\xfc\xfc\xfe2g\x1f\x03\xc7\
|
||||
\x1d1\x9f\xa8\xda\x8f\xe3\n~\xf7\x87~\xb6\x8fA\xd0\xe1\xed\x12\x13\xb7\xb2Y\
|
||||
\xa4Q1\xa8\x08\xd24K\xa1j\xdc\x8b)\xe5\xce:)s\x1f{\x1a\xebO1\xbc\x80\xa47\
|
||||
\xd2-&\xc6\xda\xc7\xa9\xf5L\xba\xb4\xb0\'\xc4\xec\x9bk\x9a\xa6\x11\x9ek\x13H\
|
||||
IX\xab\x91\xd7p\xceQ]\xbc\xed\x15gr\xce\xd1\xab\x10\xa5\xedt\xe5$c\xa5m\xf4\
|
||||
\xf5\xad\xe5\xf8\xe3V\xa3\x81\xce\xde%\xfc\xed\xb5\x9f\xe2\xa15\xf0\xb67\x9d\
|
||||
\xcb\xbc9\xb3\xf0\x1c\x97\xdb\xee\xf8\x05\xf9\xa2\xe9pF\xab\xe3\xdag\xc2<``\
|
||||
\xaey\x17\xbf\xfa\xb8Fh\xcd\'\x98J\xa8V\xab\xbb\xfdn?i\x9e\x02c\xe2\x05\x80G\
|
||||
!\x08\x8c\xdd%\xe1\xa8\xa3\xe7\xf2\x17\x7f\xfeJ\x96-r\t\xc7\x9ebi\xaf\xcd\
|
||||
\xa2\xde\x02s-\x18N\x14k\xd7\x0e\x90\xaa\x02\xff\xfe\x1f71\x7f\x01\x9cw\xde\
|
||||
\xf9\x8c\x8c\x8e\xf1\xfb\xfb\x7f\x8f\x85I\xa7.\xe6\xc6U\xba\xc9\x8a\xc9\x0c<\
|
||||
\xe9\x19\xa7\x91t\xd8o\x1eU\x86=\x95a\xed\x1fw\xa2m @\x87\x13\x17\xbc\x1f\
|
||||
\xab&\xd8\x16\xac8\x00\xfe\xe6//\xe4\xc8\xe5yF\xb7>\xc8\x81s\x8b8\xc0,[22\
|
||||
\xa8h\xebX\xc4\x1f\x1ez\x86\xcf|\xfe>.\xb9h1\x8b\x96\x1c\x08\xc2\xe2\xde\xfb\
|
||||
\xfbQ\xe9xL\\dG7v\x84m\x82\xa7\x99\x0by\x8f\xc6\xfd\x14\xc4\x9e\xea\xd3\xf7\
|
||||
\x13\xd2\x81T"\xa4\x83\xc4\xcc.\x12+\xc8\xe7l\\\x11"I9\xe1`x\xff;_\xc1\xca\
|
||||
\xb9\x82\xa3W\xcc\xc6\xc5t&]]\x07\xb0~\xf3\x08nn\x16?\xbb\xf3>~z\x17|\xf4\
|
||||
\xef\xff\x84HI~\xff\xc0\xc3\xc6\xed\xae\x1bj:\xcdV;\xd2\x13VWl]\x95q\xbf\x81\
|
||||
~\xd1\r\xb9\xe7\t\x8dYN"{\xf2\x96\x05\xa96\xf2n\x11b\xa9Qr\xc01\xcb\xe1\xba\
|
||||
\xf7_\xcd\xc5g\x1c\x83E\xcah\x05vl\x1f\xa2\xd81\x87\x9av)v\xcf\xe7\xba\xeb\
|
||||
\xff\x85\x91\x1a\\\xf2\x9a\xab\xf8\xcd\xef\x1e\xa4Z3\x06\xfax\xaaD\xd2X\x05\
|
||||
\x06\xd87\xd9\xae:s\xd36^i\x9a6_\r\x84aH\x9a\xa6\xcd1\x7f\xeb\xfe\x90\x90\
|
||||
\x00\xa126H\xe3\x15)\xbdk\xad]\xe3\xc3\x1e\xfc\x06\xfb\x07\xe9`\xae4m1\t-A-2\
|
||||
\xab9\x14\xa5\xc4\'!\x1d+s\xfc\xc1s9b\xc9\x1c\xda\xd1\xcc\xc9\xc3\xe6-\x1b\
|
||||
\xf1\x82\x1ca"\x19\xa8(B+\xcf\xbb\xfe\xfa\xffr\xd6+VP\x8e-\xd6o\xa9\xb5<\x85\
|
||||
F\\ \xc6"\xdeg\xb1\xf2\xc6T_\r\x95\xdb\x98\x15J\x08\x01\xf51\x08\xcbx\x0eX"A\
|
||||
\xc4uD\x1a"E\xb6\x18\xb0NM\xe1\r\x1aK\xea\tF\xb0Nc\x928B\x00a\xbd\x8eNU\xebI\
|
||||
\xf7\xf8(\xa7>\xb2j\'\x04\xd4\xc2\x908\x1b\\\xe5\xdd<\x16.\xa4\x1a\x11W\xe8-\
|
||||
z\xa4\xe5\x11\x02+!\xae\x0fa\x03\xed\x05\xc1Xe\x00\xcb\xcf\x91\x96cd\xd0I\
|
||||
\xea\x16\xf9\xcc\xbf<\xc2\xd5\xef\xfa\x0b~\xfc\x8b{vJa6K\xe9\n\xa2\xac\xa2g\
|
||||
\xdfX\xe7\x96e\x91\xa6)q\x1c7\xbdwJ)3\x8d\xba#\xcc\xf00\x8e\xb24\xf3F\x94\
|
||||
\xc2FH\x07!m\xacl\xe6Y\xadb\xd2$D\xa2\xf0\x1c\x1b\xcf\xb1\x89\xe3\x10\xdf\
|
||||
\xf3\x9b\xc3F\x9d$\xa8=D\xfd\xf6\x0f\xd2\xc1<u[\xe1y`\xb5\xa4)\xa1< \x87#\
|
||||
\x03\xd0\xe0\x05\x01\xc4!\x05\xdfexx\x84\xa5\x0b\x8b\x946=\x8a\xd2\x11\x08\
|
||||
\x9bz\xac\xa9&\x92\x9bo\xbf\x8bu\xdb\xeb\x88\xa0\xab\xb9p}sA\xc0Z\x15#\xed!\
|
||||
\xd5\x91a\xf6\x85\xed\xae\xb5FJ\x89\xe7yMG\x8e\x94\rG\x8f4\xa3\x05\xc76A\x08\
|
||||
\x04\x08\xdbL\xa4,\xc6\xed\t\x81\xc6\x96\x02\xd7\xb6\x18_:[\xe18\x16f\x1dw\
|
||||
\xb3\xa7\xb0m\xe4\x1e\xe2\xfb\xfb\t\xe9\xd9\r\xc9\x18M\x8cl\xa8^\x8d\x99\xd1\
|
||||
By\xd9{f\x87\x0b\x01\xa4t\xb7\xbb\x1c\xb7z1\xe7_|\x06\x1d\x81\xce\x86\xdc\
|
||||
\x02ay\xb4\xcd\x9e\xc7\xa7\xbe\xf0\x15\x0e:j5\x8f\xae\x87\xaa\x86D\x99\xceC\
|
||||
\xd8\xd9\x84\xc7:\xa53\x1f`\xe9\xe7/\xe9\xad}5\x8c{\xccT\xa3`S\xca\xcc\x1f\
|
||||
\x90\x11\xcexN\xfd\xc4\xde\xf9\xf9W\xcb\xef\x1f\xa47:W\xa9\xc8\xca\x14\xc8b1\
|
||||
-\xa5\xa5\x8d\x87\xd6\xa8\xb5\x81\x82\xd4\x9c\xbc\xfa\x00\xde\xf6\xba3\x99\
|
||||
\x93O\xa1>\x80\xaf\xebT\x06w0\xdc?\xc4\xdc\xa5\x07q\xed\xf5_\xc3\xeb\xceb\
|
||||
\x01\xd2\xf8\xff\xb0=\xd3p\xe2\x08a\t\x8c\x1e\xd8w\xf6{\xeb\xd4\x9e\xe6\x9f\
|
||||
\xec\xda\x85\xd5$|\xe7\xb3\x89\tY\xf6\xcd\x072\xfe\xd2r\x8f\x16{+\xf6\x0f\
|
||||
\xd2\x1b\x84\n;+\x97\xce\x86V\xad\x8d\xde2\x81\x1c\xe3\xb4i\xe4\x86\xa4\xf4\
|
||||
\x16\xe0\xb8e\xf0\xe1w\\\xce\x11\x8b\xdah\x17U,\xea89\x9fg\xd7oa\xb8\xa6\xf9\
|
||||
\xc4\xe7\xef\xa0?1\xd3\xcdTb\xcbx\x06\xa5o\xe6\xb3\xddG\xd3PL0\xdev\xda\xa6\
|
||||
\x11\xe8\xac\xd3j%\xbc\xb5\xa8\xa8\xf9\x1cv\x8a\xf7M [0\xf1}7\xd8OH7H1+I\x99\
|
||||
|\xf3\x16CE@$\xcd\xacV\xa1\x04-\xc7\x97\xd2\xc8\xbc\xfa\x9c\xbd\x12>\xf6g\
|
||||
\xaffA>bqO\x0e\x9d\xd6\xb1\x1d\x17\xa7m\x167\xff\xecn\xbeq\xd3\xd3\x0c\xa4\
|
||||
\xa0\x1c\x87\x94\x00\x84\x8f\x92\xbe\xe92\xb4\xb5\xd7R\xb4;\x08!\xcc2\x9e-\
|
||||
\xc47\xc3\xb1\xdaj\xe6\xe26\x08oPkgS\xbdL\xdc\xda\xf2j\x11~\xcd\xc4\xf7\xdda\
|
||||
\xbf \xbd\xb5:\x14\x1aFL\x16\xaa\xcdn\xd8\xd8\xdc\xe3\xce\x140\x99\xae"I\xc9\
|
||||
\xa5\x90\x8b\xe1\xb4\x83\x1d\xfe\xe9\x83o\xa5\xdd\x89\xe9\xca\xfb\xd8\x9eK\
|
||||
\xdf\xb6~f/]\xc9Wo\xb8\x99\xfb\x1e\xad\x9a\x86\x83\x99\xf5^\xfaEcX\xa9\xe7\
|
||||
\xdb\xa3\xef\xe1\xde\xb2\xbe\xbeU\xa14\x15y\xab\x86\xd1\xbbyg\xa22\x9a\xe4\
|
||||
\xeb]\xb0_\x90\x0e\xe3s\xbf\x98\xca\r\x05\x8d\tDE\x0cr<Z\xdfxAf\xd8i\x01i\
|
||||
\x8a\xafJ\xb4i\xc5\x11\x0b\xe1\xf3\xff\xf8&:\n\x0eI\x12\x83\x9fg\xa8\x1c\xd1\
|
||||
7Z\xe7\xc6[~\xc6\x13[\xcc\xb1\xea\xdat\x17\xc0\xf3\x9e7pgg\x8bRj\xd7~\x9d\
|
||||
\x86:\xcff\xfb\xd0\x89y\xa9l\xd5jhf\x9aiZ\xde[\xce\xa3vz\xed\x0e\xfb\r\xe9\
|
||||
\x12\xd3\xf2-\x1c,|\x9a)N\x02\x10\xaa9\x0f\xbb\x85I\x96U\xb1\xa2\x99\xf7)LQC\
|
||||
82@\x0e\x98\x9b\x83\x1b\xbex)\x07\xf6X\x14\x9d\x04[Z\xcc>\xe0`~t\xfb\xef\xf8\
|
||||
\xd1\xdd\x8f3\x02\xd4%D\x8d\xfc\xadf\x9e\xfb$\x8fu_\xf5\xf7{\xdca\xef\x8dH\
|
||||
\xb9\xd3\xfb\x9e\xf6\x99\xd2\x10\x98\xb5tl\x01\x0e\x0e\x16\x05 \xc8\xa2`f\
|
||||
\x98\xe6Ac\xab\x99\xb9\xd9\xf5Ll\xde\x96\xd9\xd87\x8f\xd76\x1b;IY\xe0\xc2\
|
||||
\x81\x12\xbe\xf6\xb7\x97q\xc9\x89+\xa8o\xde\xc8\x8e\x11\x8d\xbb\xe4\x04>\xfd\
|
||||
\xed\x9fs\xe3\x03\xb1I\xd0\x14\x1a\xc6v@2\x04\xba\x86\xd2!Ze\xae\x1c\x9d\x12\
|
||||
Gu\xb3@`\xc3\xa8\xcc\xd0\xe8\x8e\x1a.W\x98h\xc8M\xf6\x1a\x0f\xfa4\xfa\xeal\
|
||||
\x18\'\xadl8G3\xdc\xbc\xbb\x97\xdc\xe9}w\xd8/HG\x98\x11\x94\x91d\x89h\xa4.\
|
||||
\x88\xc6\xd2\x9eF\xa6\x1b\x8b\xceg\xae\x8f\xf1,\x17\x01\xb5\x84\xcc\xf6\xd1P\
|
||||
\x19&\x9f&\x1c\xde\x0b\xaf;\xef\x18\xde\xf0\xda\x97C8J\x14\'\xf8\xdd\x0b\xf9\
|
||||
\xf4\x17\xff\x93G\xb7\x82\xb0\x05\xe4\xf3P\xab\x80\x00)\xe4x\xb2\x84\x108\
|
||||
\xb2\xb1\xd2d\xb6m\xe7~6S\xe1\xad+5\xeci\xc5\x86\x89[[\xc8\xdfK\x9a\xf6\xd2x\
|
||||
\xdfOH\x7f\x9e\xd0\xc2\xcc[\xa8%\xa0ll\xa7\x13\xb4\x8d\xa3\xe1\xa8e\xf0\xce7\
|
||||
\x1e\xc6+_v \x0c?\x85]\x1dcd{\x89/|\xf9G\x8c\x01\xa1\x93G\x15g\xa3\x85G\xd2\
|
||||
\xacv\xcb\xe4\xd2r\xd0\xc2BO\xa2}\x05\xec\x91\xe0\x17\x13\xd3\x82t\x03E=\xa9\
|
||||
\x93&Y>\x9e\x06B\x85\xa7`\xb1\x0f\x7f\xf1\xfa\x97\xf0\xea3\x0e\xc5\xad\xf6\
|
||||
\xd3\x95\xcb\xf1\xe0Ck\xf8\xee\x1dCl\x03F,\x8f\n6\x89\xb2\x88\x12\x88\xb54\
|
||||
\x8e`\x01\xd2\xb6v\x89m4U\xecsH\xf6\x8b\x85iB\xba"%\xc6\xb1m,O\x1a\xc2\xe3\
|
||||
\x10\xcbI)\xc8\nAR\xe6\xb0N\xf8\xec{\xcf\xe3\xb4C\x17\x10\x8f\xf4\xd1\xd3;\
|
||||
\x87\xcf~\xf5F\x1e\x19\x82\x1dd\x0b\x13H\t\x96eV\xf2nt\xe3\xcdj\x97\x0c\xcdb\
|
||||
\xc8\x19\xd2_tX\x8dq\x97P`\xc5&jG\x08:&oC\x1b\x8a\x9c\x86/~\xec2.8c5\x03\xdb\
|
||||
\xd7SKS>\xfc\x0f7Sa\xbc\x10\xa3\x91I\xd5(\xa7\x9b4\xa3f\x1fy\xf1\xfeX\x98&\
|
||||
\xa4K\x046\xf50\xa4R\x1f\x05\x19\x82\x15\x9a\xc9\x7fc\x01\xa9G:Z\xa6M\x80\
|
||||
\x1d\xc2?\xbe\xefB\xce=\xf3p\xfa\xb7\xaf\xa7ZQ|\xeb\x07\xfd\x8cE\xe3\x1exM\
|
||||
\x96\x9e\xfd\\\xe4NQ\xe2\xa7\x05\xe9\x02H\xa2\x84\xbc\x17\xe0\xfb.!\x11\x91\
|
||||
\x8a\xc1\xf1\xc1\xc9\x93\x94\x13\xdc|\x1b\xd5\xe1Q\xba=\x93\xac}\xcd\x9f\x9e\
|
||||
\xcfU\x97\x9cM\xdf\xba\xa7\xf8\xc1\r\xdfah\x08\xc6j\xe3\xf9yM\xe2\x9f+\x7fn\
|
||||
\n\x12?-H\x07\xf0\\\x89@e\x91x\x0f%\x0b\x84\x04\xa4\xc2\xc6.\x06\xe8\x04\xf2\
|
||||
m\xed\x08B\x02\x14s\x1cx\xcf\x1b\xce\xe2\xeaW\xbe\x94\xea\x96g\xf8\xfb\xbf\
|
||||
\xbb\xaeIx\x98dCg\xb1\xc7\xac\xa4qL1\xe2\xa7\t\xe9\r_\xbd\xa9\xa5\xd3\x04\
|
||||
\xa4\x98!X\x8c\t\xd6\xa4\r\xef\x88\x12\xc84&\x07,*\xc0\xe5/;\x92\xf7\xbd\xf3\
|
||||
r\xb6\xac\x7f\x86o|\xf3\x87\xa4\xda\xe4:TjF\x83( \x8e\xf7A\xc0\xfd\x05\xc4\
|
||||
\x0bV\x9f\xfe\xe2"\xc5\x84Q$\x82B\x93\x9f\x863\xd5\xc2\xccLavu\xd1Q\x8a\xed\
|
||||
\x19g\xdeQ\x8b-\x96\xf5\x9e@2\xb6\x99\x9b\x7f|3\x87\x1dr\x10/9q%A\x00c\xd5\
|
||||
\x94\xf6\x9cE\xb5^\xc5u\xf2\x13\xdd\xa5\xcf3*\xf7\xc7\xc44!}\x1c\x96\x1e\x0f\
|
||||
X\x08\xc65\xafB\x91"\xb1$H\xcb2qZKa9u\xba\x02\x87\xab\xdf|)\x96\xedr\xe3\x8d\
|
||||
7\xb0\xfa\x88\x8f\xd0\x96\x83|\xce\x0c\xdf\xf2\xc5|\x16\xe7\xdf\t\xad\'\x98B\
|
||||
\x98\xba\xcdq\x9f\xa2Q\x80db\xec\xb66\x93\x15{\xda\x8c\xdcl\x14)\xa9\x19{\
|
||||
\x9bl\xa5,\x11Sd\xbe\xf5\x08O\xc2[\xde\xf8\n\x0e=t\x15\xd7_\xffO\x84Y\x0e\
|
||||
\xa3\xd2\x8d\xf8\x9f\xca\xca$\xc6O9\x05\xf9\x06\xa6\r\xe9\xa6B\x86\xc6j\xc6:\
|
||||
\x1b\xaek\xb0\xb5\xc2\xc5\x04rD\x16\x97O\x9b\x19\x0c\xc2,C\xa5m\xea\xa1i:oy\
|
||||
\xd3et\xb4\xb7\xf1\xc8#\x0fQ\xadG8V\xebr\x00\xc6\xd4\x9b\x10\xdf\x9e\x82\xd5\
|
||||
1\xd3\x83t\r\xba\x99V\x94`*\'J\xa0\xca\xa6"5\x95\xd8\n\xb3\xc4\xbb0C\xf7\xa4\
|
||||
\xe1bW9H=|\x0f\x12m\xfa\xf9w\xbf\xf3\xadl\xd8\xb0\x0e\xcb\x16\x94\xab\xa5\
|
||||
\x9dO\xd5Dk\x10v*I\xfd\xf4 \x1d&\x96\x80\x88\x14D\xe6j\xc9\xc4R%\xe3\x99*\
|
||||
\xa6+\xce\xe6\\\x94\xa2\x19\xd2lD\xf0\xd2\x04.\xbf\xe4b6\xad_G1W@L)J\x9f\x1b\
|
||||
\xd3\xc3\x90\x13-#*aaT}\xf6Yg\x81\xd8,\xc9f\\\n\xb2\x19\xa2\xb3\xe8\x89\x8b\
|
||||
\xd1\xf6`\x96\x10\x95\xc0\xca\xe5+\x1a\x87\xdf\t\xb2\xe5/\xbb\xd9\xe7\xc5\
|
||||
\xc3\xf4 \x1dZ\x9ezKB\xe1\x84\xed\xbb!F\x8c\xbf\xfdOgq\x99JD\xb7b\xfa\xa8\
|
||||
\xf7\x1941C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\
|
||||
\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\
|
||||
\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1EH\xdf\xbfr\xcc\xf6wL\t\xd2\xe34\
|
||||
d\x86\xf8\x17\x0eS\x82\xf4hJ\xae\x82\xf2\xff/\xa6\x04\xe9\xbe\x9c\x91\xf2\
|
||||
\x17\x12S\x82t-\xfe\xb7\xb3\xf3M\xd5)\x1f\xa6\xe25\x8dcJ\xa4@\xdb\x93\xb5=\
|
||||
\xadI\x84\xc2V\x16J*\xd0\x12\x89&\x15\x02\x89"\xd5\x1a+M\x88\xa5\x8d\x14)\
|
||||
\xb60\xab\xbc\xbdX\xd0\xa9"\x15\x02\x91\xc6\xc4\x96\xc6\x93\xde\xa4W\xb3~\
|
||||
\xfdz\x1c\xc7a\xce\x9c9\x13\xb67\xe6\x8d}!0%$}2\xb2T\xa3\xd2@\x98\xd9^\x04)\
|
||||
\x1a\xcd\xffk\xef\xdc\x83\xa3\xaa\xee\x00\xfc\x9d{\xf6\xbd!\xbby@\x1e\xc4@B\
|
||||
\x91G\x84\x12\x9fT\xd1RPl3\xad\xb4\x96\xf1Q\x18t\xda\xd2Z\xb1\xd3\x8aN\xad:\
|
||||
\xe3L\x9d\xda\x87Z-\xed\xd4>\xa6\xd5"\x91\x82\x03\x96\xfa\xc0X\xa7(T#\x85\
|
||||
\x82$D\xb0\x89\x08I\x0c\xe4\x9d\x05\x93\xecn\xf6\xde{\xfa\xc7n\x96DQ\xab\xd3\
|
||||
Ml\xef\xf9f2\x9b=\xd9\xdc\xf3\xf8rN\xee9;\xfb\xfb\xc9\xd4g\xc5\x84er\xef\xd6\
|
||||
F\xae\xb9\xf7y\xdel\xef?\xed5\xc6\n\x05\xbc\xde;\xc0\xf7\xff\xb0\x93\x1d\x07\
|
||||
;pY\xa7\x17\x0eP]]MMM\r\'N\x9c\xe0\xd1G\x1f\xa5\xb1\xb1\x91G\x1ey\x84\xba\
|
||||
\xba\xba1k\xef\xc7D\xfa;IJN\xcem\x93\x96\x9e(\x1bw\x1de\xd3\xee\xa3\xe9\xb4\
|
||||
\x1b]\t\x17?\xdc\xf2\x1a[_\xf3\xf0\xa7\x1dM\xe3\xbe\xa0>\xb3\xfd ?\xdf.\xb8\
|
||||
\xfb\x99\x06\x94|\xff\xdd\x88\x10\x82p8Lqq1S\xa7N%\x1a\x8d\xd2\xd1\xd11fm\
|
||||
\xcd\xe8\xf2>\x94\xb0pK\x85e\x08\xa4J~TT\x90\n\xa5-\xe0T<\xae\x91\x03\x94\
|
||||
\x9c#B\xd9\x08\x1b,\xe1\xe2\x9fotp\xdd/^%\xe8J\xb0\xf4\xfc2\xfcJ\x91\xebMp\
|
||||
\xe3\xe5\xa5\xec>\x1c\xe1\xf3\x17\xccyG\xcd\n\xc5\xc8x\xab#\xeb\x19\xf98\xfc\
|
||||
\xddp\xfd\x1fm\xb5\x10(\x96]:\x8b!\xeb0\x8b\xcf\x9d\x82aI\xde/i\xfd0\x15\x15\
|
||||
\x15H)Y\xb6l\xd9\xa8\xccM\x99&\xa3\xd2=n\x89\xb2m\xa4\x82\x98ms\xe8\xf8 GZ"\
|
||||
\xc4\xf0p\xd6d?3J\xfc\xf8\x94\x1b%-\x94\xad\x88\x9a\x06\xbb\xdf\xec\xa3\xad;\
|
||||
BQ\xb6\x97\xca\x99\xc5\xf4\xf4D8\xdc\x97\xc06\x14\t\x95M}k\x07><TL\xf6s\xd5\
|
||||
\xa2O\xb0t!L\xce\xf5s\xe8X7\xfdC\x10\xf6IJ\'\xfa\x91\xc2\x83\xcbV\xd4\xb7\
|
||||
\xbf\x8d\x95\x18\xa2(7\x8b\xc2\xa0 nx9~r\x80\xba\xd7\xfbPq\x93Y3\x0b(\x0f\
|
||||
\xbbp{\rL\xdcH;\x81\xc2`\xa0\x7f\x80H$Bnn.>\x9f\x0f\xc30\xd2\xe1>G\x86\xff\
|
||||
\xec\xee\xee&\x18\x0cR\x9a\x93\xc5\xf7\xae\x9e\x9b\\:\x85\xc0\xb6m\x84\x10$\
|
||||
\x12\t:::\x08\x04\x83\x84\xc2\xa1d\xfax\x92\xf9\\JJJ\x00(**\xca\xa4\x86w\x91\
|
||||
\xf1\x1b9\x05\xf4\x0f\xc6\xf9\xea\xda\xbfSS\xd7\x8de\xc0\x90p\x13\x182\xf8\
|
||||
\xe6US\xb8\xe7\xaasp+\x83W\x8e\xf6p\xd3\xaf^\xa6\xfe\x98\x00\x97\xc4P6\xb3\n\
|
||||
\x0f\x92\xe3\x1f\xa2\xf6\x88\x0b\x0bA,\xa1\xb8\xe8\xce\xed\x84d\x90\xa3\x0f/\
|
||||
e\xf9\x8f\x9f\xa2\xa5g\x90_\x7f\xe7\x12ZZ\x8e\xf1\xe3\'\xdb(\tK\xf6\xfe\xe2J\
|
||||
\xbcF\x82\x9e\x98\xe4\xf2;\x9f\xa6\'\xe1\xe1\xe9\xdb?E\xce\xec"\xee\xdf\xba\
|
||||
\x97\x9f<\xf9&\x03\xa6@*APD\xf9\xc1\xf2O\xf2\xed\xcf\xcd\xc1\xad\x12\xf4\x0f\
|
||||
Fyx\xddz\xfeQ[\x0b@ \x10\xe0\x8a+\xae`\xe3\xc6\x8d\xdcr\xcb-TVV\xb2v\xed\xda\
|
||||
t\x1e\xb5\x83\x07\x0f\xb2r\xe5J\x16/^\xccu\xd7]\xc7\xea\xd5\xab\x99?\x7f>\
|
||||
\x00555l\xde\xbc\x99h4\x8a\x90\x06\xf3\xe7\xcf\'\x1e\x8f\x8f{\xae\xf5\x8cK7\
|
||||
\x0c\x83`\xd0O\xc1\x14\x1f_\xcc\x9d\xcc\xf2\x85g\xd1u\xbc\x9b\x1b\xffX\xc7\
|
||||
\xef6\xb7q\xd3\xc2\x99d\x07\x13\\\xff\xc0v\x0e\xf7e1=4\xc8\xf9\xb3\xf2\xd9\
|
||||
\xd3\xd0\xca\xea+?M\x7fg;\x86g\x80\x17\x1bM|\x86\xc9\x17..\xa7\xc0\xb6\xf0\t\
|
||||
E\xdc\x08\x11w\x05\x10\x18\\\xb3\xe4l~\xba\xad\x87\xa3\'\xa0\xb6\xfe-.\x9dW\
|
||||
\xc2\xb6\xbdo\xd0\x13\xf70\xbb\xc4\xcf\xe2Y\x93x\xf8\xa5f\xee\xde|\x84)9n~p\
|
||||
\xd5\\ZNJ~\xb4\xe9\x00\xb7\xafo\xe2\xe2\x8aR\xce)\xf4\xf2\xf0\xba\xc7\xa8\
|
||||
\xab\xdb\xcf\r7\xdc\xc0\xec\xd9\xb3iiia\xdd\xbau\xa3\xfa$\x84\xe0\xc0\x81\
|
||||
\x03,X\xb0\x805k\xd6P\\\\\x9c\xce\xc04\x1c!r\xd7\xae]<\xf6\xd8c,Y\xb2\x84\
|
||||
\xcb.\xbb\x8ch<\xc6\x96-[8r\xe4\x08eee\x99\x1e\xf6\xf7e\x0c\xb6l\n\x03\xc1=_\
|
||||
\xba\x88\xed\rm\x1c<t\x8c\xde\x84"/\xec\xe7\xf8\x90\xc1\x81\xd6n\xbaO(\x8ev{\
|
||||
\xc8\t\x98<{O\x15\x85a7\x83q\x93l\xaf@\x1a\x85\x94\x9c\xd1\xceK\x87^\xc2#\
|
||||
\x03\xfc~\xd5\xd9\xf8p\'\xc3v*\x13C\xc5\x10X\x94\xe5x\xf9\xec\xd9a\xb6\xee\
|
||||
\xe9e\xfd\xae6\x16W\x96\xf0\x97\xdd\xc7\xb1\xe4\x04\xae\xbfx\n\t\xe9\xa6\xfa\
|
||||
o\x87\xb0e\x16\xe7\x9d\x99C\xdc\x90\x14g+\xca\x8b\x0c\xea\x8f\xb9\xa9\xd9\
|
||||
\xd7\xcc\x8c\x85S\xa9\xdd\xb3\x8f\xab\xaf\xacb\xc1\x82\x8bP\n\xc2\xe10+V\xac\
|
||||
\xe0\xc1\x07\x1f\x1c\xd5\xab\xe2\xe2bV\xadZ\x85\x94\xf2\xb43\xf7\x85\x17^\
|
||||
\xa0\xbc\xbc\x9c\xe5\xcb\x97\'\x0b\x84\xe0\xa6\xd5\xab\xf9\xee\xcd7\xff\x7f\
|
||||
\xcf\xf4!\xc0m\xc7\xd9\x7f,\xc65\xf7\xee\xe0H\'\xb8U?\x81,\xc9@\xdc\x83\xe9\
|
||||
\xf6\x10\x8b\xda\xb4\xf7F\xb1\x85\x8b\x8aBIA\xbe\x17\xaf2\xf1\xf9$\t\xe1B*\
|
||||
\x0b\x9f\xa5\x007\xb64\x91J \xb0\x91\x02\xd4p\\8\xe5A!\xf8\xda\xc2)<\xb5\xbb\
|
||||
\x87\xa7_\xe9\xe4_\xcbb\xbcX\xdfF\x96p\xb3\xec\x92R\xb0-\x8e\xf5EQd\xb1\xb5\
|
||||
\xb6\x93-\xbbZ\x91\xb6A\xc2m\xe25\xfd\x9c8\x99\xa0\xab\xfb8\xb6m2m\xea\x0c\
|
||||
\x840Rq\xe2\x14\xd3\xa6M{W\xdfJJJ\x90R\x9eJ\xbe\xf3\x0e\x91]]]\xcc\x9b7/\xbd\
|
||||
\x02\x00\xf8\xbc>\x8a\n\n1\xc6\xf9\xc89\xa3\xd2]\x98\xd8\xb8\xf9\xe5\xb6\xfd\
|
||||
4\xf5x\xa9\xaa\x94\xfc\xe6[K\x08\x05}|\xee\xee\xed\xbc\xf2F\x84!\xe1\xa6p\
|
||||
\x92\x1b0y\xbd\xb5\x9f\xe6\x9e(\xd3s<Db6\xd9~\x13\xd4\x10\x83R"\x94\xc44\x87\
|
||||
\x18\xb4%R\xa6\x02\xfa\x8c\xfa\xec\xb8\xc9EsK\x99^P\xc7\xbf\x8e\x0b\xbe\xf1\
|
||||
\xd0+D\xd4\x04\xbe|n\x1e\x85\xd9~lC2=\xdb\xc5\xe1>\x0f\xd7.\x9e\xc07/=\x13\
|
||||
\x054\xf7\xbd\xcd\xe4\xf0\x04\xf2C\x01\xf2I\xe0\xb6\\tt\xb6\x02\xb3\xd2\x15\
|
||||
\xb4\xb5\xb5}\xe8\xbeggg\xd3\xde\xde\x9e~>\x9c\xd2\xa3\xa7\xa7\'}\x037^d|\
|
||||
\x9fn+\x85e&\x90v\x82\x81\xb8\xcd\xfe\xd6\x08\x0f=\xf9\x1a{\x9b\xdeF\xe1A\n\
|
||||
\x9b/\x9d\x13bj\xbe\x8bn\x95\xc7\xa5w>\xcb\xb2\x07j\xa9\xbc\xf9\x19~\xbb\xa3\
|
||||
\x19Sx\xc8\x91&\xca\x10\x0c\xaa +\xee\xdb\xcew\x7f\xb7sD\n\xdcTG\x0cI\x96\
|
||||
\x01+?3\x15\xa4E\xed\x1bCH\xcbdY\x1f\x03%\x00\x00\x04\xd0IDAT\xe5%e\xb8\x84\
|
||||
\x8d[%\xb8\xfe\xb3sq\xa9A\x9e\xd8\xd5\xc6\xb6=\xcd<U\xd7\xce\xad\xbf\xd9\xcb\
|
||||
\xdam\r\x14\x04\r\xb2\xc2!\xce={.[\x9f\xf83\xfb\xf6\xbdJ4\x1a\xa5\xa9\xa9\
|
||||
\x89\xea\xea\xeaw\xf5\xeb\x83N\xcf.\xbc\xf0B\x1a\x1a\x1ax\xee\xb9\xe70M\x93X\
|
||||
,\xc6\xfa\xf5\xeb\xe9\xed\xed\x1d\xf7\xa8\xd0\x19\x9d\xe9&.\xa4=\xc0\x8d\x97\
|
||||
\xcfb\xfb\xfe\x1d\xbc|\xd0`\xf7k;)\x9c\xe4ez\xa1\x97\xa6\xb7\xfa\xb0\x84 \
|
||||
\x14\xf0\xf0\xc4\xad\xe7\xb3\xea\xa1W\xd9\xff\x96\xcd\xb6\xbd\'q)\xc9\xa6\
|
||||
\x9azV\\0\x95\x0b+\xce\xe0\x82i\r\xec9<\xc0_\xeb\x13\x84}p\xff7@*\x13\xc9\
|
||||
\x10B\xd9\x98H\\\xca\xe4\xdaE\xb3\xb8\xf7\x89\x06N\x0c)\xce\xcc7X4\xa7\x08\
|
||||
\x13\x85\xa1L\xbe\xb0\xa0\x9c\xfb#\x11\xee~\xbc\x99\x1f\xfe\xe5\x18R\xc4\xf0\
|
||||
\xd9\x01\xcas\xb3\xf0\xba<\xc4%|\xed\xeb_\xe1\x0f\xbf\xdf\xc0\xcf~\xf6\x00B\
|
||||
\x80\xcb\xe5b\xe9\xd2\xa5\xb4\xb6\xb6~\xa8\xbe/Z\xb4\x88\xf6\xf6v\xaa\xab\
|
||||
\xab\xd9\xb0a\x03J)\xca\xcb\xcb)--\xcd\xd0h\xff\xe7\x88\xfb\xee\xbbO\xed\xdb\
|
||||
\xb7\x8f\r\x1b6d\xa8\x8a\xe4AIg\x7f\x94\x7f4v"%\xcc\x9f9\x99\x13o\xc7\xb0\
|
||||
\x12\t&\x86\xfc\x84\xfc\x12\x81"\x8a\x87\xfa\xc3]\xb4uE\x99\x98\xebb\xde\'\
|
||||
\x8a\xc8\x92\n0\x184m\xfe\xd9\xf4\x16]\'\xe3\x14\xe5eq^y!\xcd]\'1M\x8b\xe2\
|
||||
\x9c \xa1\x80\x07\x10\xd86\x1c\xef:I\x9fm3\xc1\xe7\xe1\x8c\x9c@*\xdbYre\xb0\
|
||||
\x95\xa2\xaf?N\xed\x9b\x9d\x08s\x889\xe5\xc5\x14\x85\xfdxD\xf2\x88F\xd9\x16\
|
||||
\xb6\xad\xe8\xeb\x8b\x10\x89\xf4QPP@,\x16c\xcd\x9a5\xdcv\xdbmTTT\x10\x89D\
|
||||
\x10B\x10\n\x85\xd2\xe93-\xcb\xa2\xb3\xb3\x93\xec\xecl\x02\x81@z6wvv\xd2\xda\
|
||||
\xdaJ0\x18d\xfa\xf4\xe9\xf4\xf5\xf5!\xa5$\'\'\'C\xe3\xfd\xde\x18\xd2%l\xcbTc\
|
||||
p\xf7\x9e<\x19\x9b\x18p\xf1\xf9O\x16\xa7\x8a\x14\xd9yA\x0c\x14\x86\x12\x88T\
|
||||
\x1e\x14\xbf\xa18\xaf<\x8bs\xa7\x05\xb0U \x95t/9\xa8\x01\x15\xe7\xe2\x99%\
|
||||
\xd8*\xf9\xff\x1baQ61\x94\xec\xcc\x88\xc4|B(\x8a&N\xa00u\xf0f\xa4\xda\x90F)r\
|
||||
\x82^\xaa\xe6\x94\x80R\x18\xc2D\xa88\x08/\x02\xc1\xbeW\xf7STTDaa!\xf9\xf9y(\
|
||||
\xa5x\xfe\xf9\xe7\xf1x<\x94\x95\x95\xa5\x8fP\x93u\x9d\xba\xaea\x18\x14\x14\
|
||||
\x14\xbck\xe9\xce\xcf\xcf\'???\xfd\xfa\xbc\xbc\xbc\xff\xe6\xe0~$\xc6\xec]6e\
|
||||
\xb8\x91*\x991\xcd\x12.\xdc\xe9S\xf4d\xf8\xa6\x84\x91\xcc\xadh\x08\x1f\x86\r\
|
||||
R(\x10F\xfa8U\xb9\xfd(\x92\xe5"\x15\xf2\'\x95\x03\x99tbZ\x14B$\xbfP*\x19\xf1\
|
||||
\x11c\xd4\x91\xec\xf0\xccD\x812\x04\n\x0f\x16"\x99\xed\xcd\xb6\xd9\xb4i\x13\
|
||||
\xbd\xbd\xbdTVV\x92\x97\x97Gss3\r\r\r\xac\\\xb9\x12\xbf\xdf\xff\x9e\x99\x1a\
|
||||
\xde\xab<]\xdf\xc7\x881\x93.\x95\x8d\x9dz\xdf\\*\x1b\x84\x1c\x95\x1e\xd2\x95\
|
||||
\n\xa0;\x1c\xcbMa`\xa5~,\xd5p\x16\xd2\xe1?\x04\x99\x0e\xe4\x0b\xc9\xcc\xab\
|
||||
\xa76F\xc9P}\xb6p3|\xf9\xf7\xbam\x1a.\x97\xa9\xe5\xdf0\x0c\xee\xba\xeb.v\xee\
|
||||
\xdc\xc9\xa1C\x87hlld\xd2\xa4I\xdcq\xc7\x1d\xcc\x981c\xdco\xc0\xfe[dT\xba\
|
||||
\xb2-\x84!1\x01\x97\x10\xa7\xf6\xa7\xa3\x1fF?I\r\xac\x18\xd9\xb8\xf4`\'\x15\
|
||||
\xa6\xc3{\xa5\x8aO\t\x1f\xfe-\xf5\xc1\xdb\x92\x11\xf5\x8c$++\x8b\xaa\xaa*\
|
||||
\xaa\xaa\xaa>\xe8\n\xff\xb3dt\xed\xb1\x85L\x07\xe0\x1d=\xbc\x1fe\xc6\xbc\xdf\
|
||||
\x9c=\xddk?\xec\xb5\x9dCF\xa5\'l\xc5\xe8,\xb1\x9a\x8f\x03\x19]\xde}\xf2t\xeb\
|
||||
\xb8f\xbc\xf9\xf8\xddZj2\x8e\x96\xee@\xb4t\x07\xa2\xa5;\x10-\xdd\x81h\xe9\
|
||||
\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\xa2\xa5;\x10-\xdd\x81h\
|
||||
\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\xa2\xa5;\x10-\xdd\
|
||||
\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\xa2\xa5;\x10-\
|
||||
\xdd\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\xa2\xa5;\
|
||||
\x10-\xdd\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\xa2\
|
||||
\xa5;\x10-\xdd\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\
|
||||
\xa2\xa5;\x10-\xdd\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\
|
||||
\x07\xa2\xa5;\x10-\xdd\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x0b`\xe3\
|
||||
\xa6\xc7\xc5\xc6M\x8f\x8fw[4c\x84PJ\xa9\xf1n\x84fl\xf97\x87\xba&\x9e\x12\xca\
|
||||
GT\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getWizardDataOld():
|
||||
return \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00t\x00\x00\x01\x04\x08\x06\
|
||||
\x00\x00\x00\xf9\xcf\x10R\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
|
||||
\x00\x0f\xdfIDATx\x9c\xed]K\xb6\xe3(\x0cU\xf5\xa9MU\x86\xd9\xd6\xcb\xd0\xd9\
|
||||
@@ -962,6 +288,6 @@ def getWizardBitmap():
|
||||
|
||||
|
||||
def getWizardImage():
|
||||
stream = cStringIO.StringIO(getWizardDataOld()) # NOTE: This reverts us to the bitmap Peter likes.
|
||||
stream = cStringIO.StringIO(getWizardData()) # NOTE: This reverts us to the bitmap Peter likes.
|
||||
return ImageFromStream(stream)
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ class XmlCtrl(CodeEditor.CodeCtrl):
|
||||
# Tag
|
||||
self.StyleSetSpec(wx.stc.STC_H_TAG, "face:%(font)s,fore:#00007F,bold,size:%(size)d" % faces)
|
||||
# Attributes
|
||||
self.StyleSetSpec(wx.stc.STC_H_ATTRIBUTE, "face:%(font)s,fore:#00007F,bold,size:%(size)d" % faces)
|
||||
self.StyleSetSpec(wx.stc.STC_H_ATTRIBUTE, "face:%(font)s,fore:#007F7F,bold,size:%(size)d" % faces)
|
||||
|
||||
|
||||
class XmlOptionsPanel(STCTextEditor.TextOptionsPanel):
|
||||
@@ -118,13 +118,16 @@ class XmlOptionsPanel(STCTextEditor.TextOptionsPanel):
|
||||
STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Xml", label = "XML", hasWordWrap = True, hasTabs = True)
|
||||
|
||||
|
||||
def GetIcon(self):
|
||||
return getXMLIcon()
|
||||
|
||||
|
||||
XMLKEYWORDS = [
|
||||
"ag:connectionstring", "ag:datasource", "ag:editorBounds", "ag:label", "ag:name", "ag:shortLabel", "ag:type",
|
||||
"element", "fractionDigits", "length", "minOccurs", "name", "objtype", "refer", "schema", "type", "xpath", "xmlns",
|
||||
"xs:complexType", "xs:element", "xs:enumeration", "xs:field", "xs:key", "xs:keyref", "xs:schema", "xs:selector"
|
||||
]
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Icon Bitmaps - generated by encode_bitmaps.py
|
||||
#----------------------------------------------------------------------------
|
||||
@@ -136,19 +139,17 @@ def getXMLData():
|
||||
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\x1aIDAT8\x8d\xed\x92?N\xc3P\x0c\xc6\x7fv\xf2\x924\xa8E*7\xe1\n\xbd\
|
||||
\x01G\xa8\xd8\x989\x05S/\xd0\x0110\xf4$\xa0J\xdd\x18\x18XY\x82\xa0\xad\xd2\
|
||||
\xfc\xe9{f\x08-\x02\xc1\xd4\x85\x01/\xb6l\xd9\xdf\xf7\xd9\x16\xd1\x88CL\x0f\
|
||||
\xea\xfe\x13\x03\xc4\xae\xcf\x8d\xb6\x84\xba\x84m\x83e\x03\xa8\x96\x88F`\x86\
|
||||
\xf5\x06\xc8\xba\x80\xf4\x08\xda\x1a\xf2cB04q\xcc\xe7\x0bb\xbb\xbf\x85\xd75\
|
||||
\xf2\xb1K\xc9\x12\xa8\x9aO\x84o\x88\xb6\x0bbxx\x04\xc5e\xe0:%\xe5\xd4\xa0j:\
|
||||
\x0f\xd4\x93\x82\xcd\xe9\x19\xf5\xa4\xd8\xd7\x97\xe2\x904\x82D\x89bA\xa5\xad\
|
||||
!\x85\xb0\x82|,\x94S#\x1fw\xb8\xbe?\xc4\x8d.\xf0\xfd\xe1\x9e\x81\x7fk\x91\
|
||||
\xd6\x83\x05\xcc\x0c\xf5\xea\xf0U@\xfb\xec\x9bw\x0c\x00\xe2\xab\xd1\x17\t\
|
||||
\xd9\xcc \x80o\xc1D\x11\xbb<1^\n\xf0\xbf\xacy\x03\xf4~\xc8g0{R\xe2\x9b\xc5\
|
||||
\x8aM\x03\xd4\xe0=\xb8\xb4;\x88\xc6 \nQ\x1e\xe1W\x1e\x89\xc1W\xe0\xb7\xa0=Hr\
|
||||
\xb8{\x0e\xc8\xff+\x1f>\xe0\x1d~\xafr\x13\x04HY"\x00\x00\x00\x00IEND\xaeB`\
|
||||
\x82'
|
||||
\x00\x01\x08IDAT8\x8dc\xdc{\xf6\xde\x7f\x064p\xfb\xd1K\x06\x06\x06\x06\x86\
|
||||
\xd7o\xbf2\xd4\xa5\xb93\xa2\xcb\xa3\x80\xbdg\xef\xfd\xbf\xff\xed?\x1c_\xf9\
|
||||
\x04\xc13\xd6\x1f\xff\xbf\xeb\xf9\xff\xff\xcds\xf6\xfcgdbf\xc0\x85\x99\xb0\
|
||||
\x19\xfa\xe5\x17\x82m\xee\xed\xcc\x90Z\xb7\x08\xc3\x950\xc0\x82\xcc\xf9\xfa\
|
||||
\x07\xc1~\xfd\xf6+\xc3\xeb\xad{\x19\x1e?y\x89\xd7\x07,\xe8\x1aa\xb6\x9b{;300\
|
||||
00(\xfdb`88\x7f\x19N\x03\x98`\x01\x86\xac\xf9\xd3o\xa8+\xa0\xfc\x07\x0f\x1e\
|
||||
\xe3w\x01\xb2\x9f\xd15\xbf\xfa\x8e\xd7\x07\x0cL\xaf\xdf~%[3\xdc\x050\x8d\xa4\
|
||||
jf````LkX\xfa\x7f\x8a\xcdi\xe2T\xe3r\x01\x03\x03\x03\xc3\xa7#\x13H\xd6|\xea1\
|
||||
\x03jB\x12\xae\xffO\x14\x8d\x0cP\x0cx\xdb\xc8\xc8 \\\xff\x9f\xe1m#"\xf9c\xd3\
|
||||
\x84b\xc0\xec\xa68\xb8j\x98fdM\xc8\x86\xc1\xd4 \xcb32213\xfc\xdc\x95\xfb\x9f\
|
||||
\xdc0`A\xe6\x90\x03\x00\x11\x95\x8b;4e.A\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
|
||||
def getXMLBitmap():
|
||||
|
||||
549
wxPython/samples/ide/activegrid/tool/project.py
Normal file
549
wxPython/samples/ide/activegrid/tool/project.py
Normal file
@@ -0,0 +1,549 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: project.py
|
||||
# Purpose: project model for wx.lib.pydocview
|
||||
#
|
||||
# Author: Morgan Hua
|
||||
#
|
||||
# Created: 8/25/05
|
||||
# CVS-ID: $Id$
|
||||
# Copyright: (c) 2005 ActiveGrid, Inc.
|
||||
# License: wxWindows License
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
import copy
|
||||
import os
|
||||
import os.path
|
||||
import activegrid.util.xmlutils as xmlutils
|
||||
from IDE import ACTIVEGRID_BASE_IDE
|
||||
if not ACTIVEGRID_BASE_IDE:
|
||||
import activegrid.model.basedocmgr as basedocmgr
|
||||
import AppInfo
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Constants
|
||||
#----------------------------------------------------------------------------
|
||||
# Always add new versions, never edit the version number
|
||||
# This allows you to upgrade the file by checking the version number
|
||||
PROJECT_VERSION_050730 = '10'
|
||||
PROJECT_VERSION_050826 = '11'
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# XML Marshalling Methods
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
def load(fileObject):
|
||||
version = xmlutils.getAgVersion(fileObject.name)
|
||||
# most current versions on top
|
||||
if version == PROJECT_VERSION_050826:
|
||||
fileObject.seek(0)
|
||||
if ACTIVEGRID_BASE_IDE:
|
||||
KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile}
|
||||
else:
|
||||
KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo}
|
||||
project = xmlutils.load(fileObject.name, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES)
|
||||
elif version == PROJECT_VERSION_050730:
|
||||
fileObject.seek(0)
|
||||
project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10})
|
||||
project = project.upgradeVersion()
|
||||
else:
|
||||
# assume it is old version without version number
|
||||
fileObject.seek(0)
|
||||
project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10})
|
||||
if project:
|
||||
project = project.upgradeVersion()
|
||||
else:
|
||||
print "Project, unknown version:", version
|
||||
return None
|
||||
|
||||
if project:
|
||||
project._projectDir = os.path.dirname(fileObject.name)
|
||||
project.RelativeToAbsPath()
|
||||
|
||||
return project
|
||||
|
||||
|
||||
def save(fileObject, project, productionDeployment=False):
|
||||
if not project._projectDir:
|
||||
project._projectDir = os.path.dirname(fileObject.name)
|
||||
project.AbsToRelativePath() # temporarily change it to relative paths for saving
|
||||
if ACTIVEGRID_BASE_IDE:
|
||||
KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile}
|
||||
else:
|
||||
KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo}
|
||||
|
||||
savedHomeDir = project.homeDir
|
||||
if productionDeployment:
|
||||
# for deployments, we don't want an abs path in homeDir since that
|
||||
# would tie the app to the current filesystem. So unset it.
|
||||
project.homeDir = None
|
||||
|
||||
xmlutils.save(fileObject.name, project, prettyPrint=True, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES)
|
||||
|
||||
if productionDeployment:
|
||||
project.homeDir = savedHomeDir
|
||||
|
||||
project.RelativeToAbsPath() # swap it back to absolute path
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Classes
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
class BaseProject(object):
|
||||
|
||||
__xmlname__ = "project"
|
||||
__xmlexclude__ = ('fileName', '_projectDir', '_getDocCallback')
|
||||
__xmlattributes__ = ("_homeDir", "version")
|
||||
__xmlrename__ = { "_homeDir":"homeDir", "_appInfo":"appInfo" }
|
||||
__xmlflattensequence__ = { "_files":("file",) }
|
||||
__xmldefaultnamespace__ = xmlutils.AG_NS_URL
|
||||
__xmlattrnamespaces__ = { "ag": ["version", "_homeDir"] }
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.__xmlnamespaces__ = { "ag" : xmlutils.AG_NS_URL }
|
||||
self.version = PROJECT_VERSION_050826
|
||||
self._files = []
|
||||
self._projectDir = None # default for homeDir, set on load
|
||||
self._homeDir = None # user set homeDir for use in calculating relative path
|
||||
if not ACTIVEGRID_BASE_IDE:
|
||||
self._appInfo = AppInfo.AppInfo()
|
||||
|
||||
|
||||
def __copy__(self):
|
||||
clone = Project()
|
||||
clone._files = [copy.copy(file) for file in self._files]
|
||||
clone._projectDir = self._projectDir
|
||||
clone._homeDir = self._homeDir
|
||||
if not ACTIVEGRID_BASE_IDE:
|
||||
clone._appInfo = self._appInfo
|
||||
return clone
|
||||
|
||||
|
||||
def initialize(self):
|
||||
""" Required method for xmlmarshaller """
|
||||
pass
|
||||
|
||||
|
||||
def GetAppInfo(self):
|
||||
return self._appInfo
|
||||
|
||||
|
||||
def AddFile(self, filePath=None, logicalFolder=None, type=None, name=None, file=None):
|
||||
""" Usage: self.AddFile(filePath, logicalFolder, type, name) # used for initial generation of object
|
||||
self.AddFile(file=xyzFile) # normally used for redo/undo
|
||||
Add newly created file object using filePath and logicalFolder or given file object
|
||||
"""
|
||||
if file:
|
||||
self._files.append(file)
|
||||
else:
|
||||
self._files.append(ProjectFile(filePath, logicalFolder, type, name, getDocCallback=self._getDocCallback))
|
||||
|
||||
|
||||
def RemoveFile(self, file):
|
||||
self._files.remove(file)
|
||||
|
||||
|
||||
def FindFile(self, filePath):
|
||||
if filePath:
|
||||
for file in self._files:
|
||||
if file.filePath == filePath:
|
||||
return file
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _GetFilePaths(self):
|
||||
return [file.filePath for file in self._files]
|
||||
|
||||
|
||||
filePaths = property(_GetFilePaths)
|
||||
|
||||
|
||||
def _GetLogicalFolders(self):
|
||||
folders = []
|
||||
for file in self._files:
|
||||
if file.logicalFolder and file.logicalFolder not in folders:
|
||||
folders.append(file.logicalFolder)
|
||||
return folders
|
||||
|
||||
|
||||
logicalFolders = property(_GetLogicalFolders)
|
||||
|
||||
|
||||
def _GetPhysicalFolders(self):
|
||||
physicalFolders = []
|
||||
for file in self._files:
|
||||
physicalFolder = file.physicalFolder
|
||||
if physicalFolder and physicalFolder not in physicalFolders:
|
||||
physicalFolders.append(physicalFolder)
|
||||
return physicalFolders
|
||||
|
||||
|
||||
physicalFolders = property(_GetPhysicalFolders)
|
||||
|
||||
|
||||
def _GetHomeDir(self):
|
||||
if self._homeDir:
|
||||
return self._homeDir
|
||||
else:
|
||||
return self._projectDir
|
||||
|
||||
|
||||
def _SetHomeDir(self, parentPath):
|
||||
self._homeDir = parentPath
|
||||
|
||||
|
||||
def _IsDefaultHomeDir(self):
|
||||
return (self._homeDir == None)
|
||||
|
||||
|
||||
isDefaultHomeDir = property(_IsDefaultHomeDir)
|
||||
|
||||
|
||||
homeDir = property(_GetHomeDir, _SetHomeDir)
|
||||
|
||||
|
||||
def GetRelativeFolders(self):
|
||||
relativeFolders = []
|
||||
for file in self._files:
|
||||
relFolder = file.GetRelativeFolder(self.homeDir)
|
||||
if relFolder and relFolder not in relativeFolders:
|
||||
relativeFolders.append(relFolder)
|
||||
return relativeFolders
|
||||
|
||||
|
||||
def AbsToRelativePath(self):
|
||||
for file in self._files:
|
||||
file.AbsToRelativePath(self.homeDir)
|
||||
|
||||
|
||||
def RelativeToAbsPath(self):
|
||||
for file in self._files:
|
||||
file.RelativeToAbsPath(self.homeDir)
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# BaseDocumentMgr methods
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def fullPath(self, fileName):
|
||||
fileName = super(BaseProject, self).fullPath(fileName)
|
||||
|
||||
if os.path.isabs(fileName):
|
||||
absPath = fileName
|
||||
elif self.homeDir:
|
||||
absPath = os.path.join(self.homeDir, fileName)
|
||||
else:
|
||||
absPath = os.path.abspath(fileName)
|
||||
return os.path.normpath(absPath)
|
||||
|
||||
|
||||
def documentRefFactory(self, name, fileType, filePath):
|
||||
return ProjectFile(filePath=self.fullPath(filePath), type=fileType, name=name, getDocCallback=self._getDocCallback)
|
||||
|
||||
|
||||
def findAllRefs(self):
|
||||
return self._files
|
||||
|
||||
|
||||
def GetXFormsDirectory(self):
|
||||
forms = self.findRefsByFileType(basedocmgr.FILE_TYPE_XFORM)
|
||||
filePaths = map(lambda form: form.filePath, forms)
|
||||
xformdir = os.path.commonprefix(filePaths)
|
||||
if not xformdir:
|
||||
xformdir = self.homeDir
|
||||
return xformdir
|
||||
|
||||
|
||||
def setRefs(self, files):
|
||||
self._files = files
|
||||
|
||||
|
||||
def findRefsByFileType(self, fileType):
|
||||
fileList = []
|
||||
for file in self._files:
|
||||
if fileType == file.type:
|
||||
fileList.append(file)
|
||||
return fileList
|
||||
|
||||
|
||||
def GenerateServiceRefPath(self, wsdlFilePath):
|
||||
# HACK: temporary solution to getting wsdlag path from wsdl path.
|
||||
import wx
|
||||
from WsdlAgEditor import WsdlAgDocument
|
||||
ext = WsdlAgDocument.WSDL_AG_EXT
|
||||
for template in wx.GetApp().GetDocumentManager().GetTemplates():
|
||||
if template.GetDocumentType() == WsdlAgDocument:
|
||||
ext = template.GetDefaultExtension()
|
||||
break;
|
||||
wsdlAgFilePath = os.path.splitext(wsdlFilePath)[0] + ext
|
||||
return wsdlAgFilePath
|
||||
|
||||
|
||||
def SetDocCallback(self, getDocCallback):
|
||||
self._getDocCallback = getDocCallback
|
||||
for file in self._files:
|
||||
file._getDocCallback = getDocCallback
|
||||
|
||||
|
||||
if ACTIVEGRID_BASE_IDE:
|
||||
class Project(BaseProject):
|
||||
pass
|
||||
else:
|
||||
class Project(BaseProject, basedocmgr.BaseDocumentMgr):
|
||||
pass
|
||||
|
||||
|
||||
class ProjectFile(object):
|
||||
__xmlname__ = "file"
|
||||
__xmlexclude__ = ('_getDocCallback', '_docCallbackCacheReturnValue', '_docModelCallbackCacheReturnValue', '_doc',)
|
||||
__xmlattributes__ = ["filePath", "logicalFolder", "type", "name"]
|
||||
__xmldefaultnamespace__ = xmlutils.AG_NS_URL
|
||||
|
||||
|
||||
def __init__(self, filePath=None, logicalFolder=None, type=None, name=None, getDocCallback=None):
|
||||
self.filePath = filePath
|
||||
self.logicalFolder = logicalFolder
|
||||
self.type = type
|
||||
self.name = name
|
||||
self._getDocCallback = getDocCallback
|
||||
self._docCallbackCacheReturnValue = None
|
||||
self._docModelCallbackCacheReturnValue = None
|
||||
self._doc = None
|
||||
|
||||
|
||||
def _GetDocumentModel(self):
|
||||
# possible bug is if document gets replaced outside of IDE, where we'll return previous doc.
|
||||
# originally added a timestamp check but that increased the time again to 4x
|
||||
if self._docModelCallbackCacheReturnValue: # accelerator for caching document, got 4x speed up.
|
||||
return self._docModelCallbackCacheReturnValue
|
||||
|
||||
if self._getDocCallback:
|
||||
self._docCallbackCacheReturnValue, self._docModelCallbackCacheReturnValue = self._getDocCallback(self.filePath)
|
||||
return self._docModelCallbackCacheReturnValue
|
||||
|
||||
return None
|
||||
|
||||
|
||||
document = property(_GetDocumentModel)
|
||||
|
||||
|
||||
def _GetDocument(self):
|
||||
# Hack, just return the IDE document wrapper that corresponds to the runtime document model
|
||||
# callers should have called ".document" before calling ".ideDocument"
|
||||
if self._docCallbackCacheReturnValue: # accelerator for caching document, got 4x speed up.
|
||||
return self._docCallbackCacheReturnValue
|
||||
return None
|
||||
|
||||
|
||||
ideDocument = property(_GetDocument)
|
||||
|
||||
|
||||
def _typeEnumeration(self):
|
||||
return basedocmgr.FILE_TYPE_LIST
|
||||
|
||||
|
||||
def _GetPhysicalFolder(self):
|
||||
dir = None
|
||||
if self.filePath:
|
||||
dir = os.path.dirname(self.filePath)
|
||||
if os.sep != '/':
|
||||
dir = dir.replace(os.sep, '/') # require '/' as delimiter
|
||||
return dir
|
||||
|
||||
|
||||
physicalFolder = property(_GetPhysicalFolder)
|
||||
|
||||
|
||||
def GetRelativeFolder(self, parentPath):
|
||||
parentPathLen = len(parentPath)
|
||||
|
||||
dir = None
|
||||
if self.filePath:
|
||||
dir = os.path.dirname(self.filePath)
|
||||
if dir.startswith(parentPath):
|
||||
dir = "." + dir[parentPathLen:] # convert to relative path
|
||||
if os.sep != '/':
|
||||
dir = dir.replace(os.sep, '/') # always save out with '/' as path separator for cross-platform compatibility.
|
||||
return dir
|
||||
|
||||
|
||||
def AbsToRelativePath(self, parentPath):
|
||||
""" Used to convert path to relative path for saving (disk format) """
|
||||
parentPathLen = len(parentPath)
|
||||
|
||||
if self.filePath.startswith(parentPath):
|
||||
self.filePath = "." + self.filePath[parentPathLen:] # convert to relative path
|
||||
if os.sep != '/':
|
||||
self.filePath = self.filePath.replace(os.sep, '/') # always save out with '/' as path separator for cross-platform compatibility.
|
||||
else:
|
||||
pass # not a decendant of project, use absolute path
|
||||
|
||||
|
||||
def RelativeToAbsPath(self, parentPath):
|
||||
""" Used to convert path to absolute path (for any necessary disk access) """
|
||||
if self.filePath.startswith("."): # relative to project file
|
||||
self.filePath = os.path.normpath(os.path.join(parentPath, self.filePath))
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# BaseDocumentMgr methods
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
def _GetDoc(self):
|
||||
# HACK: temporary solution.
|
||||
import wx
|
||||
import wx.lib.docview
|
||||
if not self._doc:
|
||||
docMgr = wx.GetApp().GetDocumentManager()
|
||||
|
||||
doc = docMgr.CreateDocument(self.filePath, docMgr.GetFlags()|wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE|wx.lib.docview.DOC_NO_VIEW)
|
||||
if (doc == None): # already open
|
||||
docs = docMgr.GetDocuments()
|
||||
for d in docs:
|
||||
if d.GetFilename() == self.filePath:
|
||||
doc = d
|
||||
break
|
||||
self._doc = doc
|
||||
return self._doc
|
||||
|
||||
|
||||
def _GetLocalServiceProcessName(self):
|
||||
# HACK: temporary solution to getting process name from wsdlag file.
|
||||
return self._GetDoc().GetModel().processName
|
||||
|
||||
|
||||
processName = property(_GetLocalServiceProcessName)
|
||||
|
||||
|
||||
def _GetStateful(self):
|
||||
# HACK: temporary solution to getting stateful from wsdlag file.
|
||||
return self._GetDoc().GetModel().stateful
|
||||
|
||||
|
||||
def _SetStateful(self, stateful):
|
||||
# HACK: temporary solution to setting stateful from wsdlag file.
|
||||
self._GetDoc().GetModel().stateful = stateful
|
||||
|
||||
|
||||
stateful = property(_GetStateful, _SetStateful)
|
||||
|
||||
|
||||
def _GetLocalServiceCodeFile(self):
|
||||
# HACK: temporary solution to getting class name from wsdlag file.
|
||||
return self._GetDoc().GetModel().localServiceCodeFile
|
||||
|
||||
|
||||
def _SetLocalServiceCodeFile(self, codefile):
|
||||
# HACK: temporary solution to setting class name from wsdlag file.
|
||||
self._GetDoc().GetModel().localServiceCodeFile = codefile
|
||||
|
||||
|
||||
localServiceCodeFile = property(_GetLocalServiceCodeFile, _SetLocalServiceCodeFile)
|
||||
|
||||
|
||||
def _GetLocalServiceClassName(self):
|
||||
# HACK: temporary solution to getting class name from wsdlag file.
|
||||
return self._GetDoc().GetModel().localServiceClassName
|
||||
|
||||
|
||||
def _SetLocalServiceClassName(self, className):
|
||||
# HACK: temporary solution to setting class name from wsdlag file.
|
||||
self._GetDoc().GetModel().localServiceClassName = className
|
||||
|
||||
|
||||
localServiceClassName = property(_GetLocalServiceClassName, _SetLocalServiceClassName)
|
||||
|
||||
|
||||
|
||||
# only activate this code if we programatically need to access these values
|
||||
## def _GetRssServiceBaseURL(self):
|
||||
## return self._GetDoc().GetModel().rssServiceBaseURL
|
||||
##
|
||||
##
|
||||
## def _SetRssServiceBaseURL(self, baseURL):
|
||||
## self._GetDoc().GetModel().rssServiceBaseURL = baseURL
|
||||
##
|
||||
##
|
||||
## rssServiceBaseURL = property(_GetRssServiceBaseURL, _SetRssServiceBaseURL)
|
||||
##
|
||||
##
|
||||
## def _GetRssServiceRssVersion(self):
|
||||
## return self._GetDoc().GetModel().rssServiceRssVersion
|
||||
##
|
||||
##
|
||||
## def _SetRssServiceRssVersion(self, rssVersion):
|
||||
## self._GetDoc().GetModel().rssServiceRssVersion = rssVersion
|
||||
##
|
||||
##
|
||||
## rssServiceRssVersion = property(_GetRssServiceRssVersion, _SetRssServiceRssVersion)
|
||||
|
||||
|
||||
def _GetServiceRefServiceType(self):
|
||||
# HACK: temporary solution to getting service type from wsdlag file.
|
||||
model = self._GetDoc().GetModel()
|
||||
if hasattr(model, 'serviceType'):
|
||||
return model.serviceType
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _SetServiceRefServiceType(self, serviceType):
|
||||
# HACK: temporary solution to getting service type from wsdlag file.
|
||||
self._GetDoc().GetModel().serviceType = serviceType
|
||||
|
||||
|
||||
serviceType = property(_GetServiceRefServiceType, _SetServiceRefServiceType)
|
||||
|
||||
|
||||
def getExternalPackage(self):
|
||||
# HACK: temporary solution to getting custom code filename from wsdlag file.
|
||||
import activegrid.server.deployment as deploymentlib
|
||||
|
||||
appInfo = self._GetDoc().GetAppInfo()
|
||||
|
||||
if appInfo.language == None:
|
||||
language = deploymentlib.LANGUAGE_DEFAULT
|
||||
else:
|
||||
language = appInfo.language
|
||||
|
||||
if language == deploymentlib.LANGUAGE_PYTHON:
|
||||
suffix = ".py"
|
||||
elif language == deploymentlib.LANGUAGE_PHP:
|
||||
suffix = ".php"
|
||||
pyFilename = self.name + suffix
|
||||
return self._GetDoc().GetAppDocMgr().fullPath(pyFilename)
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Old Classes
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
class Project_10:
|
||||
""" Version 1.0, kept for upgrading to latest version. Over time, this should be deprecated. """
|
||||
__xmlname__ = "project"
|
||||
__xmlrename__ = { "_files":"files"}
|
||||
__xmlexclude__ = ('fileName',)
|
||||
__xmlattributes__ = ["version"]
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.version = PROJECT_VERSION_050730
|
||||
self._files = []
|
||||
|
||||
|
||||
def initialize(self):
|
||||
""" Required method for xmlmarshaller """
|
||||
pass
|
||||
|
||||
|
||||
def upgradeVersion(self):
|
||||
currModel = Project()
|
||||
for file in self._files:
|
||||
currModel._files.append(ProjectFile(file))
|
||||
return currModel
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: __init__.py
|
||||
# Purpose: Utilities
|
||||
#
|
||||
# Author: Joel Hare
|
||||
#
|
||||
# Created: 7/28/04
|
||||
# CVS-ID: $Id$
|
||||
# Copyright: (c) 2004-2005 ActiveGrid, Inc.
|
||||
# License: wxWindows License
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
import traceback
|
||||
import sys
|
||||
import os
|
||||
|
||||
def isWindows():
|
||||
return os.name == 'nt'
|
||||
|
||||
def _generateMainModuleDir():
|
||||
if sys.executable.find('python') != -1:
|
||||
utilModuleDir = os.path.dirname(__file__)
|
||||
if not os.path.isabs(utilModuleDir):
|
||||
utilModuleDir = os.path.join(os.getcwd(), utilModuleDir)
|
||||
mainModuleDir = os.path.normpath(os.path.join(utilModuleDir, os.path.join(os.path.pardir, os.path.pardir)))
|
||||
if mainModuleDir.endswith('.zip'):
|
||||
mainModuleDir = os.path.dirname(mainModuleDir) # Get rid of library.zip
|
||||
else:
|
||||
mainModuleDir = os.path.dirname(sys.executable)
|
||||
return mainModuleDir
|
||||
|
||||
mainModuleDir = _generateMainModuleDir()
|
||||
|
||||
|
||||
def _generatePythonExecPath():
|
||||
if sys.executable.find('python') != -1:
|
||||
pythonExecPath = sys.executable
|
||||
else:
|
||||
pythonExecPath = os.path.join(os.path.dirname(sys.executable), '3rdparty\python2.3\python')
|
||||
return pythonExecPath
|
||||
|
||||
pythonExecPath = _generatePythonExecPath()
|
||||
|
||||
def getCommandNameForExecPath(execPath):
|
||||
if isWindows():
|
||||
return '"%s"' % execPath
|
||||
return execPath
|
||||
|
||||
|
||||
@@ -15,7 +15,10 @@ import os
|
||||
import re
|
||||
import traceback
|
||||
import logging
|
||||
import logging.config
|
||||
from activegrid.util.lang import *
|
||||
import activegrid.util.objutils as objutils
|
||||
import activegrid.util.sysutils as sysutils
|
||||
|
||||
LEVEL_FATAL = logging.FATAL
|
||||
LEVEL_ERROR = logging.ERROR
|
||||
@@ -23,6 +26,90 @@ LEVEL_WARN = logging.WARN
|
||||
LEVEL_INFO = logging.INFO
|
||||
LEVEL_DEBUG = logging.DEBUG
|
||||
|
||||
EXCEPTION_INFO = 'exceptionInfo'
|
||||
|
||||
LOG_MODE_IDE = 1
|
||||
LOG_MODE_TESTRUN = 2
|
||||
LOG_MODE_RUN = 3
|
||||
def initLogging(mode):
|
||||
configFile = None
|
||||
if (mode == LOG_MODE_IDE):
|
||||
configFile = os.getenv("AG_LOGCONFIG_IDE")
|
||||
elif (mode == LOG_MODE_TESTRUN):
|
||||
configFile = os.getenv("AG_LOGCONFIG_TESTRUN")
|
||||
else:
|
||||
configFile = os.getenv("AG_LOGCONFIG_RUN")
|
||||
if ((configFile == None) or not os.path.exists(configFile)):
|
||||
if (mode == LOG_MODE_IDE):
|
||||
configFile = "IDELog"
|
||||
elif (mode == LOG_MODE_TESTRUN):
|
||||
configFile = "TestRunLog"
|
||||
else:
|
||||
configFile = "RunLog"
|
||||
configFile = sysutils.mainModuleDir + "/py" + configFile + ".ini"
|
||||
if (os.path.exists(configFile)):
|
||||
fileConfig(configFile)
|
||||
else:
|
||||
defaultStream = sys.stderr
|
||||
if (mode == LOG_MODE_RUN):
|
||||
defaultStream = sys.stdout
|
||||
handler = logging.StreamHandler(defaultStream)
|
||||
handler.setLevel(logging.INFO)
|
||||
handler.setFormatter(logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s"))
|
||||
logging.getLogger().addHandler(handler)
|
||||
return configFile
|
||||
|
||||
ag_debugLogger = logging.getLogger("activegrid.debug")
|
||||
|
||||
def log(logger, level, msg, *params):
|
||||
if (logger == None):
|
||||
logger = ag_debugLogger
|
||||
apply(logger.log, (level, msg) + params)
|
||||
|
||||
def fatal(logger, msg, *params):
|
||||
apply(logger.fatal, (msg,) + params)
|
||||
|
||||
def error(logger, msg, *params):
|
||||
apply(logger.error, (msg,) + params)
|
||||
|
||||
def warn(logger, msg, *params):
|
||||
apply(logger.warn, (msg,) + params)
|
||||
|
||||
def info(logger, msg, *params):
|
||||
apply(logger.info, (msg,) + params)
|
||||
|
||||
def debug(logger, msg, *params):
|
||||
if (logger == None):
|
||||
logger = ag_debugLogger
|
||||
apply(logger.debug, (msg,) + params)
|
||||
|
||||
def setLevelFatal(logger):
|
||||
logger.setLevel(LEVEL_FATAL)
|
||||
|
||||
def setLevelError(logger):
|
||||
logger.setLevel(LEVEL_ERROR)
|
||||
|
||||
def setLevelWarn(logger):
|
||||
logger.setLevel(LEVEL_WARN)
|
||||
|
||||
def setLevelInfo(logger):
|
||||
logger.setLevel(LEVEL_INFO)
|
||||
|
||||
def setLevelDebug(logger):
|
||||
logger.setLevel(LEVEL_DEBUG)
|
||||
|
||||
def isEnabledForError(logger):
|
||||
return logger.isEnabledFor(LEVEL_ERROR)
|
||||
|
||||
def isEnabledForWarn(logger):
|
||||
return logger.isEnabledFor(LEVEL_WARN)
|
||||
|
||||
def isEnabledForInfo(logger):
|
||||
return logger.isEnabledFor(LEVEL_INFO)
|
||||
|
||||
def isEnabledForDebug(logger):
|
||||
return logger.isEnabledFor(LEVEL_DEBUG)
|
||||
|
||||
TEST_MODE_NONE = 0
|
||||
TEST_MODE_DETERMINISTIC = 1
|
||||
TEST_MODE_NON_DETERMINISTIC = 2
|
||||
@@ -38,8 +125,11 @@ def getTestMode():
|
||||
global agTestMode
|
||||
return agTestMode
|
||||
|
||||
def testMode(normalObj, testObj=None):
|
||||
if getTestMode() > TEST_MODE_NONE:
|
||||
def testMode(normalObj, testObj=None, nonDeterministicObj=None):
|
||||
testMode = getTestMode()
|
||||
if testMode > TEST_MODE_NONE:
|
||||
if ((nonDeterministicObj != None) and (testMode == TEST_MODE_NON_DETERMINISTIC)):
|
||||
return nonDeterministicObj
|
||||
return testObj
|
||||
return normalObj
|
||||
|
||||
@@ -68,18 +158,41 @@ def _fileNameReplacement(match):
|
||||
def _fileNameReplacementPHP(match):
|
||||
return "%s...%s" % (match.group(1), match.group(2).replace(os.sep, "/"))
|
||||
|
||||
def getTraceback():
|
||||
extype, val, tb = sys.exc_info()
|
||||
tbs = "\n"
|
||||
for s in traceback.format_tb(tb):
|
||||
tbs += s
|
||||
def formatTraceback(tb=None):
|
||||
if (tb == None):
|
||||
extype, val, tb = sys.exc_info()
|
||||
tbs = "\n" + "".join(traceback.format_tb(tb))
|
||||
return tbs
|
||||
|
||||
def formatExceptionCause(cause, stacktrace=False):
|
||||
if (cause == None):
|
||||
return ""
|
||||
tbs = ""
|
||||
if (stacktrace):
|
||||
tbs = formatTraceback()
|
||||
return "Caused by %s.%s: %s%s" % (cause.__module__, cause.__class__.__name__, str(cause), tbs)
|
||||
|
||||
def addExceptionInfo(e, key, value):
|
||||
if not hasattr(e, EXCEPTION_INFO):
|
||||
try:
|
||||
setattr(e, EXCEPTION_INFO, {})
|
||||
except:
|
||||
return # Make sure we still report the real exception even if we can't add the extra info
|
||||
if not e.exceptionInfo.has_key(key): # Never overwrite exception info since we assume earlier info is more specific
|
||||
e.exceptionInfo[key] = value
|
||||
|
||||
def reportException(out=None, stacktrace=False, diffable=False, exception=None):
|
||||
if (True): # exception == None):
|
||||
exstr = exceptionToString(exception, stacktrace, diffable)
|
||||
if (out == None):
|
||||
print exstr
|
||||
else:
|
||||
print >> out, exstr
|
||||
|
||||
def exceptionToString(exception=None, stacktrace=False, diffable=False):
|
||||
if (exception == None):
|
||||
extype, val, t = sys.exc_info()
|
||||
else:
|
||||
extype = type(exception)
|
||||
extype = objutils.typeToString(exception)
|
||||
val = exception
|
||||
if (stacktrace):
|
||||
e,v,t = sys.exc_info()
|
||||
@@ -87,17 +200,169 @@ def reportException(out=None, stacktrace=False, diffable=False, exception=None):
|
||||
exstr = removeFileRefs(str(val))
|
||||
else:
|
||||
exstr = str(val)
|
||||
if (out == None):
|
||||
print "Got Exception = %s: %s" % (extype, exstr)
|
||||
else:
|
||||
print >> out, "Got Exception = %s: %s" % (extype, exstr)
|
||||
if hasattr(val, EXCEPTION_INFO):
|
||||
firstTime = True
|
||||
for infoKey, infoValue in getattr(val, EXCEPTION_INFO).items():
|
||||
if firstTime:
|
||||
prefix = " EXTRA INFO:"
|
||||
firstTime = False
|
||||
else:
|
||||
prefix = ","
|
||||
exstr += ("%s %s=%s" % (prefix, infoKey, infoValue))
|
||||
result = "Got Exception = %s: %s" % (extype, exstr)
|
||||
if (stacktrace):
|
||||
fmt = traceback.format_exception(extype, val, t)
|
||||
for s in fmt:
|
||||
if (diffable):
|
||||
s = removeFileRefs(s)
|
||||
if (out == None):
|
||||
print s
|
||||
result = result + "\n" + s
|
||||
return result
|
||||
|
||||
def fileConfig(fname, defaults=None):
|
||||
"""
|
||||
This is copied from logging.config so that we could fix the class lookup of
|
||||
handlers. Previously handlers had to be defined in logging.handlers and we
|
||||
need to be able to define our own.
|
||||
"""
|
||||
import ConfigParser, string
|
||||
|
||||
cp = ConfigParser.ConfigParser(defaults)
|
||||
if hasattr(cp, 'readfp') and hasattr(fname, 'readline'):
|
||||
cp.readfp(fname)
|
||||
else:
|
||||
cp.read(fname)
|
||||
#first, do the formatters...
|
||||
flist = cp.get("formatters", "keys")
|
||||
if len(flist):
|
||||
flist = string.split(flist, ",")
|
||||
formatters = {}
|
||||
for form in flist:
|
||||
sectname = "formatter_%s" % form
|
||||
opts = cp.options(sectname)
|
||||
if "format" in opts:
|
||||
fs = cp.get(sectname, "format", 1)
|
||||
else:
|
||||
print >> out, s
|
||||
|
||||
fs = None
|
||||
if "datefmt" in opts:
|
||||
dfs = cp.get(sectname, "datefmt", 1)
|
||||
else:
|
||||
dfs = None
|
||||
f = logging.Formatter(fs, dfs)
|
||||
formatters[form] = f
|
||||
#next, do the handlers...
|
||||
#critical section...
|
||||
logging._acquireLock()
|
||||
try:
|
||||
## try:
|
||||
#first, lose the existing handlers...
|
||||
logging._handlers.clear()
|
||||
#now set up the new ones...
|
||||
hlist = cp.get("handlers", "keys")
|
||||
if len(hlist):
|
||||
hlist = string.split(hlist, ",")
|
||||
handlers = {}
|
||||
fixups = [] #for inter-handler references
|
||||
for hand in hlist:
|
||||
## try:
|
||||
sectname = "handler_%s" % hand
|
||||
classname = cp.get(sectname, "class")
|
||||
opts = cp.options(sectname)
|
||||
if "formatter" in opts:
|
||||
fmt = cp.get(sectname, "formatter")
|
||||
else:
|
||||
fmt = ""
|
||||
klass = None
|
||||
try:
|
||||
klass = eval(classname, vars(logging))
|
||||
except:
|
||||
pass
|
||||
if (klass == None):
|
||||
klass = objutils.classForName(classname)
|
||||
args = cp.get(sectname, "args")
|
||||
args = eval(args, vars(logging))
|
||||
h = apply(klass, args)
|
||||
if "level" in opts:
|
||||
level = cp.get(sectname, "level")
|
||||
h.setLevel(logging._levelNames[level])
|
||||
if len(fmt):
|
||||
h.setFormatter(formatters[fmt])
|
||||
#temporary hack for FileHandler and MemoryHandler.
|
||||
if klass == logging.handlers.MemoryHandler:
|
||||
if "target" in opts:
|
||||
target = cp.get(sectname,"target")
|
||||
else:
|
||||
target = ""
|
||||
if len(target): #the target handler may not be loaded yet, so keep for later...
|
||||
fixups.append((h, target))
|
||||
handlers[hand] = h
|
||||
## except Exception, e: #if an error occurs when instantiating a handler, too bad
|
||||
## pass #this could happen e.g. because of lack of privileges
|
||||
#now all handlers are loaded, fixup inter-handler references...
|
||||
for fixup in fixups:
|
||||
h = fixup[0]
|
||||
t = fixup[1]
|
||||
h.setTarget(handlers[t])
|
||||
#at last, the loggers...first the root...
|
||||
llist = cp.get("loggers", "keys")
|
||||
llist = string.split(llist, ",")
|
||||
llist.remove("root")
|
||||
sectname = "logger_root"
|
||||
root = logging.root
|
||||
log = root
|
||||
opts = cp.options(sectname)
|
||||
if "level" in opts:
|
||||
level = cp.get(sectname, "level")
|
||||
log.setLevel(logging._levelNames[level])
|
||||
for h in root.handlers[:]:
|
||||
root.removeHandler(h)
|
||||
hlist = cp.get(sectname, "handlers")
|
||||
if len(hlist):
|
||||
hlist = string.split(hlist, ",")
|
||||
for hand in hlist:
|
||||
log.addHandler(handlers[hand])
|
||||
#and now the others...
|
||||
#we don't want to lose the existing loggers,
|
||||
#since other threads may have pointers to them.
|
||||
#existing is set to contain all existing loggers,
|
||||
#and as we go through the new configuration we
|
||||
#remove any which are configured. At the end,
|
||||
#what's left in existing is the set of loggers
|
||||
#which were in the previous configuration but
|
||||
#which are not in the new configuration.
|
||||
existing = root.manager.loggerDict.keys()
|
||||
#now set up the new ones...
|
||||
for log in llist:
|
||||
sectname = "logger_%s" % log
|
||||
qn = cp.get(sectname, "qualname")
|
||||
opts = cp.options(sectname)
|
||||
if "propagate" in opts:
|
||||
propagate = cp.getint(sectname, "propagate")
|
||||
else:
|
||||
propagate = 1
|
||||
logger = logging.getLogger(qn)
|
||||
if qn in existing:
|
||||
existing.remove(qn)
|
||||
if "level" in opts:
|
||||
level = cp.get(sectname, "level")
|
||||
logger.setLevel(logging._levelNames[level])
|
||||
for h in logger.handlers[:]:
|
||||
logger.removeHandler(h)
|
||||
logger.propagate = propagate
|
||||
logger.disabled = 0
|
||||
hlist = cp.get(sectname, "handlers")
|
||||
if len(hlist):
|
||||
hlist = string.split(hlist, ",")
|
||||
for hand in hlist:
|
||||
logger.addHandler(handlers[hand])
|
||||
#Disable any old loggers. There's no point deleting
|
||||
#them as other threads may continue to hold references
|
||||
#and by disabling them, you stop them doing any logging.
|
||||
for log in existing:
|
||||
root.manager.loggerDict[log].disabled = 1
|
||||
## except:
|
||||
## import traceback
|
||||
## ei = sys.exc_info()
|
||||
## traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
|
||||
## del ei
|
||||
finally:
|
||||
logging._releaseLock()
|
||||
|
||||
59
wxPython/samples/ide/activegrid/util/appdirs.py
Normal file
59
wxPython/samples/ide/activegrid/util/appdirs.py
Normal file
@@ -0,0 +1,59 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: appdirs.py
|
||||
# Purpose: Utilities for retrieving special application dirs
|
||||
#
|
||||
# Author: Kevin Ollivier
|
||||
#
|
||||
# Created: 8/27/05
|
||||
# CVS-ID: $Id$
|
||||
# Copyright: (c) 2004-2005 ActiveGrid, Inc.
|
||||
# License: wxWindows License
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
# NOTE: This was made a separate file because it depends upon the
|
||||
# wx.StandardPaths module, and thus, on wxWidgets, unlike other
|
||||
# utils modules. I wanted to ensure this module is never loaded
|
||||
# from the web server, etc.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import string
|
||||
import wx
|
||||
|
||||
def isWindows():
|
||||
return os.name == 'nt'
|
||||
|
||||
def _generateDocumentsDir():
|
||||
path = ""
|
||||
if sys.platform == "win32":
|
||||
from win32com.shell import shell, shellcon
|
||||
path=shell.SHGetFolderPath(0, shellcon.CSIDL_PERSONAL, None, 0)
|
||||
elif sys.platform == "darwin":
|
||||
import macfs, MACFS
|
||||
fsspec_disk, fsspec_desktop = macfs.FindFolder( MACFS.kOnSystemDisk, MACFS.kDocumentsFolderType, 0)
|
||||
path = macfs.FSSpec((fsspec_disk, fsspec_desktop, '')).as_pathname()
|
||||
|
||||
if path == "":
|
||||
path = os.path.expanduser("~")
|
||||
|
||||
return path
|
||||
|
||||
documents_folder = _generateDocumentsDir()
|
||||
|
||||
# NOTE: We don't set this at startup because wxStandardPaths needs a running
|
||||
# application object. This makes sure the wxApp will always be created when
|
||||
# we get the folder.
|
||||
def getAppDataFolder():
|
||||
# wxStandardPaths requires a running app
|
||||
if wx.GetApp() and wx.Platform != "__WXGTK__":
|
||||
data_folder = wx.StandardPaths.Get().GetUserDataDir()
|
||||
if not os.path.exists(data_folder):
|
||||
os.mkdir(data_folder)
|
||||
return data_folder
|
||||
else:
|
||||
# wxBug: on *nix, it wants to point to ~/.appname, but
|
||||
# so does wxConfig... For now, redirect this to ~/.appbuilder
|
||||
# when this is fixed, we'll migrate settings to the correct place
|
||||
return os.path.join(os.path.expanduser("~"), ".appbuilder")
|
||||
|
||||
return ""
|
||||
348
wxPython/samples/ide/activegrid/util/fileutils.py
Normal file
348
wxPython/samples/ide/activegrid/util/fileutils.py
Normal file
@@ -0,0 +1,348 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: fileutils.py
|
||||
# Purpose: Active grid miscellaneous utilities
|
||||
#
|
||||
# Author: Jeff Norton
|
||||
#
|
||||
# Created: 12/10/04
|
||||
# CVS-ID: $Id$
|
||||
# Copyright: (c) 2004-2005 ActiveGrid, Inc.
|
||||
# License: wxWindows License
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
import logging
|
||||
import copy
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
import activegrid.util.aglogging as aglogging
|
||||
import activegrid.util.sysutils as sysutils
|
||||
from activegrid.util.lang import *
|
||||
|
||||
global fileutilsLogger
|
||||
fileutilsLogger = logging.getLogger("activegrid.util.fileutils")
|
||||
# FATAL : No logging
|
||||
# ERROR : No logging
|
||||
# WARN : No logging
|
||||
# INFO : No logging
|
||||
# DEBUG : debugging
|
||||
aglogging.setLevelFatal(fileutilsLogger)
|
||||
#logging.getLogger().addHandler(logging.StreamHandler(sys.stderr))
|
||||
|
||||
|
||||
def makeDirsForFile(filename):
|
||||
d = os.path.dirname(filename)
|
||||
if (not os.path.exists(d)):
|
||||
os.makedirs(d)
|
||||
|
||||
def createFile(filename, mode='w'):
|
||||
f = None
|
||||
if (not os.path.exists(filename)):
|
||||
makeDirsForFile(filename)
|
||||
f = file(filename, mode)
|
||||
return f
|
||||
|
||||
def compareFiles(file1, file2):
|
||||
## result = filecmp.cmp(file1, file2)
|
||||
## if result:
|
||||
## return 0
|
||||
## return -1
|
||||
file1.seek(0)
|
||||
file2.seek(0)
|
||||
while True:
|
||||
line1 = file1.readline()
|
||||
line2 = file2.readline()
|
||||
if (len(line1) == 0):
|
||||
if (len(line2) == 0):
|
||||
return 0
|
||||
else:
|
||||
return -1
|
||||
elif (len(line2) == 0):
|
||||
return -1
|
||||
elif (line1 != line2):
|
||||
line1 = line1.replace(" ", "")
|
||||
line2 = line2.replace(" ", "")
|
||||
if (line1 != line2):
|
||||
len1 = len(line1)
|
||||
len2 = len(line2)
|
||||
if ((abs(len1 - len2) == 1) and (len1 > 0) and (len2 > 0)
|
||||
and (line1[-1] == "\n") and (line2[-1] == "\n")):
|
||||
if (len1 > len2):
|
||||
longer = line1
|
||||
shorter = line2
|
||||
else:
|
||||
shorter = line1
|
||||
longer = line2
|
||||
if ((longer[-2] == "\r") and (longer[:-2] == shorter[:-1])):
|
||||
continue
|
||||
if ((longer[-2:] == shorter[-2:]) and (longer[-3] == "\r") and (longer[:-3] == shorter[:-2])):
|
||||
continue
|
||||
return -1
|
||||
|
||||
def expandVars(value):
|
||||
"""Syntax: ${myvar,default="default value"}"""
|
||||
import activegrid.runtime as runtime
|
||||
sx = value.find("${")
|
||||
if (sx >= 0):
|
||||
result = asString(value[:sx])
|
||||
endx = value.find("}")
|
||||
if (endx > 1):
|
||||
defaultValue = None
|
||||
defsx = value.find(",default=\"")
|
||||
if ((defsx > sx) and (defsx < endx)):
|
||||
varname = value[sx+2:defsx]
|
||||
if (value[endx-1] == '"'):
|
||||
defaultValue = value[defsx+10:endx-1]
|
||||
if (defaultValue == None):
|
||||
varname = value[sx+2:endx]
|
||||
if (varname == "AG_SYSTEM"):
|
||||
varval = runtime.appInfo.getSystemDir()
|
||||
elif (varname == "AG_SYSTEM_STATIC"):
|
||||
varval = runtime.appInfo.getSystemStaticDir()
|
||||
elif (varname == "AG_APP"):
|
||||
varval = runtime.appInfo.getAppDir()
|
||||
elif (varname == "AG_APP_STATIC"):
|
||||
varval = runtime.appInfo.getAppStaticDir()
|
||||
else:
|
||||
varval = os.getenv(varname)
|
||||
if ((varval == None) and (defaultValue != None)):
|
||||
varval = defaultValue
|
||||
if (varval == None):
|
||||
result += value[sx:endx+1]
|
||||
else:
|
||||
result += varval
|
||||
return result + expandVars(value[endx+1:])
|
||||
return value
|
||||
|
||||
def toPHPpath(path, otherdir=None):
|
||||
return convertSourcePath(path, "php", otherdir=otherdir)
|
||||
|
||||
def toPythonpath(path, otherdir=None):
|
||||
return convertSourcePath(path, "python", otherdir=otherdir)
|
||||
|
||||
def toUnixPath(path):
|
||||
if (path != None and os.sep != '/'):
|
||||
path = path.replace(os.sep, '/')
|
||||
return path
|
||||
|
||||
def convertSourcePath(path, to, otherdir=None):
|
||||
fromname = "python"
|
||||
if (to == "python"):
|
||||
fromname = "php"
|
||||
pythonNode = os.sep + fromname + os.sep
|
||||
ix = path.find(pythonNode)
|
||||
if (ix < 0):
|
||||
ix = path.find(fromname) - 1
|
||||
if ((ix < 0) or (len(path) <= ix+7)
|
||||
or (path[ix] not in ("\\", "/")) or (path[ix+7] not in ("\\", "/"))):
|
||||
raise Exception("Not in a %s source tree. Cannot create file name for %s." % (fromname, path))
|
||||
if (otherdir == None):
|
||||
return path[:ix+1] + to + path[ix+7:]
|
||||
else:
|
||||
return otherdir + path[ix+7:]
|
||||
if (otherdir == None):
|
||||
return path.replace(pythonNode, os.sep + to + os.sep)
|
||||
else:
|
||||
return otherdir + path[ix+7:]
|
||||
|
||||
|
||||
def visit(directory, files, extension):
|
||||
testdirs = os.listdir(directory)
|
||||
for thing in testdirs:
|
||||
fullpath = os.path.join(directory, thing)
|
||||
if (os.path.isdir(fullpath)):
|
||||
visit(fullpath, files, extension)
|
||||
elif thing.endswith(extension):
|
||||
fullname = os.path.normpath(os.path.join(directory, thing))
|
||||
if not fullname in files:
|
||||
files.append(fullname)
|
||||
|
||||
def listFilesByExtensionInPath(path=[], extension='.lyt'):
|
||||
#Collect input and output arguments into one bunch
|
||||
retval = []
|
||||
for directory in path:
|
||||
visit(directory, retval, extension)
|
||||
return retval
|
||||
|
||||
def getFileLastModificationTime(fileName):
|
||||
return os.path.getmtime(fileName)
|
||||
|
||||
def findFileLocation(location, fileName):
|
||||
i = fileName.rfind(os.sep)
|
||||
if i > 0:
|
||||
fileName = fileName[:i]
|
||||
while location[0:2] == '..' and location[2:3] == os.sep:
|
||||
location = location[3:]
|
||||
i = fileName.rfind(os.sep)
|
||||
fileName = fileName[:i]
|
||||
absPath = fileName + os.sep + location
|
||||
return absPath
|
||||
|
||||
def getAllExistingFiles(files, basepath=None, forceForwardSlashes=False):
|
||||
"""For each file in files, if it exists, adds its absolute path to the rtn list. If file is a dir, calls this function recursively on all child files in the dir.
|
||||
If basepath is set, and if the file being processed is relative to basedir, adds that relative path to rtn list instead of the abs path.
|
||||
Is this is Windows, and forceForwardSlashes is True, make sure returned paths only have forward slashes."""
|
||||
if isinstance(files, basestring):
|
||||
files = [files]
|
||||
rtn = []
|
||||
for file in files:
|
||||
if os.path.exists(file):
|
||||
if os.path.isfile(file):
|
||||
if basepath and hasAncestorDir(file, basepath):
|
||||
rtn.append(getRelativePath(file, basepath))
|
||||
else:
|
||||
rtn.append(os.path.abspath(str(file)))
|
||||
elif os.path.isdir(file):
|
||||
dircontent = [os.path.join(file, f) for f in os.listdir(file)]
|
||||
rtn.extend(getAllExistingFiles(dircontent, basepath))
|
||||
|
||||
if forceForwardSlashes and sysutils.isWindows():
|
||||
newRtn = []
|
||||
for f in rtn:
|
||||
newRtn.append(f.replace("\\", "/"))
|
||||
rtn = newRtn
|
||||
|
||||
return rtn
|
||||
|
||||
def hasAncestorDir(file, parent):
|
||||
"""Returns true if file has the dir 'parent' as some parent in its path."""
|
||||
return getRelativePath(file, parent) != None
|
||||
|
||||
def getRelativePath(file, basedir):
|
||||
"""Returns relative path from 'basedir' to 'file', assuming 'file' lives beneath 'basedir'. If it doesn't, returns None."""
|
||||
file = os.path.abspath(file)
|
||||
parent = os.path.abspath(basedir)
|
||||
|
||||
if file == parent:
|
||||
return None
|
||||
|
||||
if file.startswith(parent):
|
||||
return file[len(parent)+1:]
|
||||
|
||||
return None
|
||||
|
||||
def isEmptyDir(dir):
|
||||
if not os.path.isdir(dir):
|
||||
return False
|
||||
return len(os.listdir(dir)) == 0
|
||||
|
||||
ifDefPy()
|
||||
def zip(zipfilepath, basedir=None, files=None):
|
||||
"""Zip all files in files and save zip as zipfilepath. If files is None, zip all files in basedir. For all files to be zipped, if they are relative to basedir, include the relative path in the archive."""
|
||||
|
||||
if not files and not basedir:
|
||||
raise AssertionError("Either 'basedir' or 'files' must be set")
|
||||
|
||||
if not files:
|
||||
aglogging.debug(fileutilsLogger,\
|
||||
"Looking for files to zip in %s" % basedir)
|
||||
files = getAllExistingFiles(basedir)
|
||||
else:
|
||||
# removes files that don't exist and gets abs for each
|
||||
files = getAllExistingFiles(files)
|
||||
|
||||
if len(files) == 0:
|
||||
aglogging.debug(fileutilsLogger, "No files to zip, nothing to do")
|
||||
return
|
||||
|
||||
z = zipfile.ZipFile(zipfilepath, mode="w", compression=zipfile.ZIP_DEFLATED)
|
||||
|
||||
try:
|
||||
for file in files:
|
||||
arcname = None
|
||||
if basedir:
|
||||
arcname = getRelativePath(file, basedir)
|
||||
if not arcname:
|
||||
arcname = file
|
||||
aglogging.debug(fileutilsLogger,\
|
||||
"%s: adding %s with arcname %s" %\
|
||||
(zipfilepath, file, arcname))
|
||||
z.write(file, arcname)
|
||||
finally:
|
||||
z.close()
|
||||
endIfDef()
|
||||
|
||||
|
||||
ifDefPy()
|
||||
def unzip(zipfilepath, extractdir):
|
||||
"""Unzip zipfilepath into extractdir."""
|
||||
z = zipfile.ZipFile(zipfilepath, mode="r")
|
||||
for info in z.infolist():
|
||||
filename = os.path.join(extractdir, info.filename)
|
||||
try:
|
||||
dir = os.path.dirname(filename)
|
||||
aglogging.debug(fileutilsLogger, "Creating dir %s" % dir)
|
||||
os.makedirs(dir) # do we have to worry about permissions?
|
||||
except:
|
||||
pass
|
||||
if os.path.isdir(filename):
|
||||
continue
|
||||
aglogging.debug(fileutilsLogger,\
|
||||
("Writing arcfile %s to %s" % (info.filename, filename)))
|
||||
f = open(filename, "w")
|
||||
f.write(z.read(info.filename))
|
||||
f.close()
|
||||
endIfDef()
|
||||
|
||||
ifDefPy()
|
||||
def copyFile(src, dest):
|
||||
"""Copies file src to dest. Creates directories in 'dest' path if necessary."""
|
||||
destdir = os.path.dirname(dest)
|
||||
if not os.path.exists(destdir):
|
||||
os.makedirs(destdir)
|
||||
shutil.copy(src, dest)
|
||||
endIfDef()
|
||||
|
||||
ifDefPy()
|
||||
def copyDir(src, dest):
|
||||
"""Copies dir 'src' into dir 'dest'. Creates 'dest' if it does not exist."""
|
||||
shutil.copytree(src, dest)
|
||||
endIfDef()
|
||||
|
||||
ifDefPy()
|
||||
def remove(file):
|
||||
if not os.path.exists(file):
|
||||
return
|
||||
if os.path.isfile(file):
|
||||
os.remove(file)
|
||||
elif os.path.isdir(file):
|
||||
shutil.rmtree(file)
|
||||
endIfDef()
|
||||
|
||||
ifDefPy()
|
||||
import warnings
|
||||
warnings.filterwarnings("ignore", message="tmpnam is a potential security risk to your program")
|
||||
def getTmpFile():
|
||||
return os.tmpnam()
|
||||
endIfDef()
|
||||
|
||||
ifDefPy()
|
||||
#@accepts str, dict, str, str, boolean
|
||||
def replaceToken(infilepath, tokens={}, outfilepath=None, delim="@@",\
|
||||
useEnv=False):
|
||||
"""Replaces tokens of form 'delim'<tokenname>'delim' in file at 'infilepath', using values in dict 'tokens'. If 'outfilepath' is set, writes output to 'outfilepath', if not set, overwrites original file. If 'useEnv' is True, adds os.environ to 'tokens'. This makes it possible to define an env var FOO=BLAH, and have @@FOO@@ be replaced with BLAH, without explicitly passing FOO=BLAH in 'tokens'. Note that entries in 'tokens' take precedence over entries in os.environ."""
|
||||
|
||||
if useEnv:
|
||||
for key, val in os.environ.items():
|
||||
# passed in tokens take precedence
|
||||
if not tokens.has_key(key):
|
||||
tokens[key] = val
|
||||
|
||||
f = open(infilepath, "r")
|
||||
try:
|
||||
content = f.read()
|
||||
finally:
|
||||
if f: f.close()
|
||||
|
||||
for token, value in tokens.items():
|
||||
content = content.replace("%s%s%s" % (delim, token , delim), str(value))
|
||||
|
||||
if not outfilepath: outfilepath = infilepath
|
||||
f = open(outfilepath, "w")
|
||||
try:
|
||||
f.write(content)
|
||||
finally:
|
||||
if f: f.close()
|
||||
endIfDef()
|
||||
@@ -65,3 +65,9 @@ def ifDefPy(comment=False):
|
||||
|
||||
def endIfDef():
|
||||
pass
|
||||
|
||||
def ag_isPHP():
|
||||
return False
|
||||
|
||||
def ag_isPython():
|
||||
return True
|
||||
|
||||
@@ -14,36 +14,192 @@ import logging
|
||||
import traceback
|
||||
import sys
|
||||
import os
|
||||
import __builtin__
|
||||
import types
|
||||
import xml.sax.saxutils as saxutils
|
||||
from types import *
|
||||
from activegrid.util.lang import *
|
||||
|
||||
FUNCTION_HAS_ATTR = '_hasAttr'
|
||||
FUNCTION_GET_ATTR = '_getAttr'
|
||||
FUNCTION_SET_ATTR = '_setAttr'
|
||||
FUNCTION_DEL_ATTR = '_delAttr'
|
||||
|
||||
def hasRawAttr(obj, name):
|
||||
if obj == None:
|
||||
return False
|
||||
if name != FUNCTION_HAS_ATTR and hasattr(obj, FUNCTION_HAS_ATTR):
|
||||
return obj._hasAttr(name)
|
||||
return obj.__dict__.has_key(name)
|
||||
|
||||
def getRawAttr(obj, name):
|
||||
if name != FUNCTION_GET_ATTR and hasattr(obj, FUNCTION_GET_ATTR):
|
||||
return obj._getAttr(name)
|
||||
return obj.__dict__.get(name)
|
||||
|
||||
def setRawAttr(obj, name, value):
|
||||
if name != FUNCTION_SET_ATTR and hasattr(obj, FUNCTION_SET_ATTR):
|
||||
obj._setAttr(name, value)
|
||||
else:
|
||||
obj.__dict__[name] = value
|
||||
|
||||
def delRawAttr(obj, name):
|
||||
if name != FUNCTION_DEL_ATTR and hasattr(obj, FUNCTION_DEL_ATTR):
|
||||
obj._delAttr(name)
|
||||
else:
|
||||
del obj.__dict__[name]
|
||||
|
||||
def getStaticAttr(obj, attr):
|
||||
if (isinstance(obj, types.TypeType)):
|
||||
classDesc = obj
|
||||
else:
|
||||
classDesc = obj.__class__
|
||||
if (hasattr(classDesc, attr)):
|
||||
return getattr(classDesc, attr)
|
||||
return None
|
||||
|
||||
def setStaticAttr(obj, attr, value):
|
||||
if (isinstance(obj, types.TypeType)):
|
||||
classDesc = obj
|
||||
else:
|
||||
classDesc = obj.__class__
|
||||
setattr(classDesc, attr, value)
|
||||
|
||||
def moduleForName(moduleName):
|
||||
module = None
|
||||
pathList = moduleName.split('.')
|
||||
if (len(moduleName) > 0):
|
||||
module = __import__(moduleName)
|
||||
for name in pathList[1:]:
|
||||
if (name in module.__dict__):
|
||||
module = module.__dict__[name]
|
||||
else:
|
||||
module = None
|
||||
break
|
||||
return module
|
||||
|
||||
def typeForName(typeName):
|
||||
i = typeName.rfind('.')
|
||||
if (i >= 0):
|
||||
module = moduleForName(typeName[:i])
|
||||
if (module != None):
|
||||
name = typeName[i+1:]
|
||||
if (name in module.__dict__):
|
||||
return module.__dict__[name]
|
||||
elif __builtin__.__dict__.has_key(typeName):
|
||||
return __builtin__.__dict__[typeName]
|
||||
return None
|
||||
|
||||
def functionForName(functionName):
|
||||
ftype = typeForName(functionName)
|
||||
if (isinstance(ftype, (types.FunctionType, types.MethodType, types.BuiltinFunctionType, types.BuiltinMethodType))):
|
||||
return ftype
|
||||
return None
|
||||
|
||||
def classForName(className):
|
||||
pathList = className.split('.')
|
||||
moduleName = '.'.join(pathList[:-1])
|
||||
code = __import__(moduleName)
|
||||
for name in pathList[1:]:
|
||||
code = code.__dict__[name]
|
||||
return code
|
||||
ctype = typeForName(className)
|
||||
if (isinstance(ctype, (types.ClassType, types.TypeType))):
|
||||
return ctype
|
||||
return None
|
||||
|
||||
def hasPropertyValue(obj, attr):
|
||||
hasProp = False
|
||||
try:
|
||||
prop = obj.__class__.__dict__[attr]
|
||||
if (isinstance(prop, property)):
|
||||
hasProp = hasattr(obj, attr)
|
||||
if (hasProp):
|
||||
# It's a property and it has a value but sometimes we don't want it.
|
||||
# If there is a _hasattr method execute it and the
|
||||
# result will tell us whether to include this value
|
||||
try:
|
||||
hasProp = obj._hasattr(attr)
|
||||
except:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
return hasProp
|
||||
def newInstance(className, objargs=None):
|
||||
"dynamically create an object based on the className and return it."
|
||||
|
||||
def toDiffableString(value):
|
||||
s = str(value)
|
||||
if not isinstance(objargs, list):
|
||||
objargs = [objargs]
|
||||
|
||||
if className == "None":
|
||||
return None
|
||||
elif className == "bool":
|
||||
if ((len(objargs) < 1) or (objargs[0].lower() == "false") or (not objargs[0])):
|
||||
return False
|
||||
return True
|
||||
if className == "str" or className == "unicode": # don"t strip: blanks are significant
|
||||
if len(objargs) > 0:
|
||||
try:
|
||||
return saxutils.unescape(objargs[0]).encode()
|
||||
except:
|
||||
return "?"
|
||||
else:
|
||||
return ""
|
||||
|
||||
classtype = classForName(className)
|
||||
if (classtype == None):
|
||||
raise Exception("Could not find class %s" % className)
|
||||
|
||||
if (len(objargs) > 0):
|
||||
return classtype(*objargs)
|
||||
else:
|
||||
return classtype()
|
||||
|
||||
def getClassProperty(classType, propertyName):
|
||||
return getattr(classType, propertyName)
|
||||
|
||||
def toDiffableRepr(value, exclude=None):
|
||||
if (value == None):
|
||||
return "None"
|
||||
## elif (isinstance(value, ObjectType) and hasattr(value, "__dict__")):
|
||||
## if (exclude == None):
|
||||
## exclude = []
|
||||
## s = "%s(%s)" % (type(value), toDiffableString(value.__dict__, exclude))
|
||||
elif (not isinstance(value, (BooleanType, ClassType, ComplexType, DictType, DictionaryType,
|
||||
FloatType, IntType, ListType, LongType, StringType, TupleType,
|
||||
UnicodeType, BufferType, BuiltinFunctionType, BuiltinMethodType,
|
||||
CodeType, FrameType, FunctionType, GeneratorType, InstanceType,
|
||||
LambdaType, MethodType, ModuleType, SliceType, TracebackType,
|
||||
TypeType, XRangeType))):
|
||||
if (hasattr(value, "__str__")):
|
||||
s = str(value)
|
||||
elif (hasattr(value, "__dict__")):
|
||||
s = "%s(%s)" % (type(value), toDiffableString(value.__dict__, exclude))
|
||||
else:
|
||||
s = str(type(value))
|
||||
ix2 = s.find(" object at 0x")
|
||||
if (ix2 > 0):
|
||||
ix = s.rfind(".")
|
||||
if (ix > 0):
|
||||
s = "<class %s>" %s[ix+1:ix2]
|
||||
elif (isinstance(value, bool)):
|
||||
if (value):
|
||||
return "True"
|
||||
else:
|
||||
return "False"
|
||||
elif (isinstance(value, (tuple, list))):
|
||||
items = []
|
||||
for v in value:
|
||||
if (isinstance(v, basestring)):
|
||||
if (v.find("'") >= 0):
|
||||
items.append('"%s"' % v)
|
||||
else:
|
||||
items.append("'%s'" % v)
|
||||
else:
|
||||
items.append(toDiffableString(v, exclude))
|
||||
s = "[" + ", ".join(items) + "]"
|
||||
elif (isinstance(value, dict)):
|
||||
if (exclude == None):
|
||||
exclude = []
|
||||
items = []
|
||||
for key, val in value.iteritems():
|
||||
if (isinstance(val, UnicodeType)):
|
||||
items.append("'%s': u'%s'" % (key, toDiffableString(val, exclude)))
|
||||
elif (isinstance(val, basestring)):
|
||||
items.append("'%s': '%s'" % (key, toDiffableString(val, exclude)))
|
||||
else:
|
||||
items.append("'%s': %s" % (key, toDiffableString(val, exclude)))
|
||||
s = "{" + ", ".join(items) + "}"
|
||||
else:
|
||||
s = str(value)
|
||||
return s
|
||||
|
||||
def toDiffableString(value, exclude=None):
|
||||
if (value == None):
|
||||
return "None"
|
||||
if ((exclude != None) and not isinstance(value, (basestring, int))):
|
||||
for v in exclude:
|
||||
if (v is value):
|
||||
return "<recursive reference>"
|
||||
exclude.append(value)
|
||||
s = toDiffableRepr(value)
|
||||
ds = ""
|
||||
i = s.find(" at 0x")
|
||||
start = 0
|
||||
@@ -54,22 +210,43 @@ def toDiffableString(value):
|
||||
ds += s[start:i]
|
||||
start = j
|
||||
i = s.find(" at 0x", start)
|
||||
return ds + s[start:]
|
||||
|
||||
ds = ds + s[start:]
|
||||
i = ds.find("\\src\\")
|
||||
if (i < 0):
|
||||
i = ds.find("/src/")
|
||||
else:
|
||||
ds = ds.replace("\\", "/")
|
||||
if (i > 0):
|
||||
i += 4
|
||||
if (ds[i:i+5] == "\\php\\"):
|
||||
i += 4
|
||||
elif (ds[i:i+8] == "\\python\\"):
|
||||
i += 7
|
||||
ds = "filepath: ..." + ds[i:]
|
||||
return ds
|
||||
|
||||
def toString(value, options=0):
|
||||
if ((options & PRINT_OBJ_DIFFABLE) > 0):
|
||||
return toDiffableString(value)
|
||||
elif (not isinstance(value, basestring)):
|
||||
return str(value)
|
||||
return value
|
||||
|
||||
def toTypeString(obj):
|
||||
def typeToString(obj, options=0):
|
||||
if (isinstance(obj, BooleanType)):
|
||||
return "bool"
|
||||
elif (isinstance(obj, UnicodeType)):
|
||||
if ((options & PRINT_OBJ_DIFFABLE) > 0):
|
||||
return "string"
|
||||
return "unicode"
|
||||
elif (isinstance(obj, basestring)):
|
||||
return "string"
|
||||
elif (isinstance(obj, IntType)):
|
||||
return "int"
|
||||
elif (isinstance(obj, LongType)):
|
||||
if ((options & PRINT_OBJ_DIFFABLE) > 0):
|
||||
return "int"
|
||||
return "long"
|
||||
elif (isinstance(obj, FloatType)):
|
||||
return "float"
|
||||
elif (type(obj) == ListType):
|
||||
@@ -79,18 +256,46 @@ def toTypeString(obj):
|
||||
elif (isinstance(obj, TupleType)):
|
||||
return "tuple"
|
||||
elif (isinstance(obj, InstanceType)):
|
||||
return type(obj)
|
||||
## ds = str(type(obj))
|
||||
ds = "<class %s.%s> " % (obj.__module__, obj.__class__.__name__)
|
||||
else:
|
||||
return type(obj)
|
||||
ds = str(type(obj))
|
||||
if (options == 0):
|
||||
import activegrid.util.aglogging
|
||||
options = activegrid.util.aglogging.testMode(0, PRINT_OBJ_DIFFABLE)
|
||||
if ((options & PRINT_OBJ_DIFFABLE) > 0):
|
||||
if (ds.startswith("<class ")):
|
||||
ix = ds.rfind(".")
|
||||
if (ix < 0):
|
||||
ix = 8
|
||||
ds = "<class %s>" % ds[ix+1:-2]
|
||||
return ds
|
||||
|
||||
def nameToString(name, options=0):
|
||||
if (name.startswith("_v_")):
|
||||
return name[3:]
|
||||
if ((options & PRINT_OBJ_DIFFABLE) > 0):
|
||||
ix = name.find("__")
|
||||
if ((ix > 1) and name.startswith("_")):
|
||||
name = name[ix:]
|
||||
return toDiffableString(name)
|
||||
return name
|
||||
|
||||
PRINT_OBJ_GETATTR = 1
|
||||
PRINT_OBJ_HIDE_INTERNAL = 2
|
||||
PRINT_OBJ_COMPACT = 4
|
||||
PRINT_OBJ_NONONE = 8
|
||||
PRINT_OBJ_DIFFABLE = 16
|
||||
PRINT_OBJ_HIDE_EXCLUDED = 32
|
||||
PRINT_OBJ_INTERNAL = 512
|
||||
|
||||
def printObject(out, object, name="", indent=0, flags=0, exclude=None, maxIndent=30):
|
||||
def printObject(out, object, name=None, indent=0, flags=0, exclude=None, remove=None, maxIndent=30):
|
||||
if (name == None):
|
||||
name = ""
|
||||
## elif (name.endswith("_") and not name.endswith("__")):
|
||||
## name = name[:-1]
|
||||
if ((remove != None) and (name in asDict(remove))):
|
||||
return False
|
||||
if ((maxIndent != None) and (indent > maxIndent)):
|
||||
print >> out, " "*indent, "%s: %s" % (name, toString(str(object), flags)),
|
||||
if ((flags & PRINT_OBJ_INTERNAL) == 0):
|
||||
@@ -98,12 +303,11 @@ def printObject(out, object, name="", indent=0, flags=0, exclude=None, maxIndent
|
||||
return True
|
||||
finalNewLine = False
|
||||
printed = True
|
||||
## if (exclude == None):
|
||||
## exclude = []
|
||||
if ((flags & PRINT_OBJ_COMPACT) > 0):
|
||||
if (exclude and object in exclude):
|
||||
if ((flags & (PRINT_OBJ_COMPACT | PRINT_OBJ_HIDE_EXCLUDED)) > 0):
|
||||
if ((exclude != None) and ((object in exclude) or (name in exclude))):
|
||||
return
|
||||
indent = 0
|
||||
if ((flags & PRINT_OBJ_COMPACT) > 0):
|
||||
indent = 0
|
||||
if ((flags & PRINT_OBJ_INTERNAL) == 0):
|
||||
finalNewLine = True
|
||||
flags |= PRINT_OBJ_INTERNAL
|
||||
@@ -113,23 +317,23 @@ def printObject(out, object, name="", indent=0, flags=0, exclude=None, maxIndent
|
||||
else:
|
||||
finalNewLine = False
|
||||
printed = False
|
||||
elif (name.startswith("_") and ((flags & PRINT_OBJ_HIDE_INTERNAL) > 0)):
|
||||
elif (name.startswith("_") and ((flags & PRINT_OBJ_HIDE_INTERNAL) > 0) and not name.startswith("_v_")):
|
||||
finalNewLine = False
|
||||
printed = False
|
||||
elif (isinstance(object, (list, tuple))):
|
||||
if ((exclude != None) and object in exclude):
|
||||
print >> out, " "*indent, name, " : ", toTypeString(object), " of length = ", len(object), " (already printed)",
|
||||
print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = ", len(object), " (already printed)",
|
||||
elif ((exclude != None) and name in exclude):
|
||||
print >> out, " "*indent, name, " : ", toTypeString(object), " of length = ", len(object), " (excluded)",
|
||||
print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = ", len(object), " (excluded)",
|
||||
else:
|
||||
if ((exclude != None) and (len(object) > 0)): exclude.append(object)
|
||||
print >> out, " "*indent, name, " : ", toTypeString(object), " of length = %d" % len(object),
|
||||
print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = %d" % len(object),
|
||||
for i, o in enumerate(object):
|
||||
print >> out
|
||||
printObject(out, o, name="[%d]" % i, indent=indent+2, flags=flags, exclude=exclude, maxIndent=maxIndent)
|
||||
printObject(out, o, name="[%d]" % i, indent=indent+2, flags=flags, exclude=exclude, remove=remove, maxIndent=maxIndent)
|
||||
elif (isinstance(object, dict)):
|
||||
if ((exclude != None) and object in exclude):
|
||||
print >> out, " "*indent, name, " : ", toTypeString(object), " (already printed)",
|
||||
print >> out, " "*indent, name, " : ", typeToString(object, flags), " (already printed)",
|
||||
else:
|
||||
if ((exclude != None) and (len(object) > 0)): exclude.append(object)
|
||||
if (len(name) > 0):
|
||||
@@ -147,51 +351,62 @@ def printObject(out, object, name="", indent=0, flags=0, exclude=None, maxIndent
|
||||
n = key
|
||||
if (not (isinstance(n, basestring))):
|
||||
n = str(n)
|
||||
else:
|
||||
n = nameToString(n, flags)
|
||||
if ((not n.startswith("_") or ((flags & PRINT_OBJ_HIDE_INTERNAL) == 0))):
|
||||
if printObject(out, object[key], name=n, indent=indent+2, flags=(flags | PRINT_OBJ_INTERNAL), exclude=exclude, maxIndent=maxIndent):
|
||||
if printObject(out, object[key], name=n, indent=indent+2, flags=(flags | PRINT_OBJ_INTERNAL), exclude=exclude, remove=remove, maxIndent=maxIndent):
|
||||
if ((flags & PRINT_OBJ_COMPACT) == 0):
|
||||
print >> out
|
||||
else:
|
||||
print >> out, ",",
|
||||
print >> out, " "*indent, "}",
|
||||
elif (hasattr(object, "__dict__")):
|
||||
if ((exclude != None) and object in exclude):
|
||||
print >> out, " "*indent, name, " : ", toTypeString(object), " (already printed) = ", toDiffableString(object),
|
||||
if (name.startswith("_")): ## and ((flags & PRINT_OBJ_HIDE_INTERNAL) > 0)):
|
||||
print >> out, " "*indent, name, " : ", typeToString(object, flags),
|
||||
elif ((exclude != None) and ((object in exclude) or (object.__dict__ in exclude))):
|
||||
print >> out, " "*indent, name, " : ", typeToString(object, flags), " (already printed)",
|
||||
else:
|
||||
if (exclude != None): exclude.append(object)
|
||||
if (name.startswith("_")): ## and ((flags & PRINT_OBJ_HIDE_INTERNAL) > 0)):
|
||||
print >> out, " "*indent, name, " : ", toTypeString(object),
|
||||
elif ((exclude != None) and object.__dict__ in exclude):
|
||||
print >> out, " "*indent, name, " : ", toTypeString(object), " (already printed)",
|
||||
print >> out, " "*indent, name, " : ", typeToString(object, flags),
|
||||
if ((flags & PRINT_OBJ_GETATTR) == 0):
|
||||
if ((flags & PRINT_OBJ_COMPACT) == 0):
|
||||
print >> out
|
||||
printObject(out, object.__dict__, indent=indent, flags=flags, exclude=exclude, remove=remove, maxIndent=maxIndent)
|
||||
else:
|
||||
print >> out, " "*indent, name, " : ", toTypeString(object),
|
||||
if ((flags & PRINT_OBJ_GETATTR) == 0):
|
||||
if ((flags & PRINT_OBJ_COMPACT) == 0):
|
||||
if ((flags & PRINT_OBJ_COMPACT) == 0):
|
||||
print >> out
|
||||
## indent += 2
|
||||
print >> out, " "*indent, "{",
|
||||
keys = object.__dict__.keys()
|
||||
keys.sort()
|
||||
printed = True
|
||||
for key in keys:
|
||||
if ((exclude != None) and (key in exclude)):
|
||||
continue
|
||||
if (printed and ((flags & PRINT_OBJ_COMPACT) == 0)):
|
||||
print >> out
|
||||
printObject(out, object.__dict__, indent=indent, flags=flags, exclude=exclude, maxIndent=maxIndent)
|
||||
else:
|
||||
keys = object.__dict__.keys()
|
||||
keys.sort()
|
||||
for n in keys:
|
||||
if ((flags & PRINT_OBJ_COMPACT) == 0):
|
||||
print >> out
|
||||
printObject(out, getattr(object, n), name=n, indent=indent+2, flags=flags, exclude=exclude, maxIndent=maxIndent)
|
||||
n = nameToString(key, flags)
|
||||
printed = printObject(out, getattr(object, n), name=n, indent=indent+2, flags=flags, exclude=exclude, remove=remove, maxIndent=maxIndent)
|
||||
if ((flags & PRINT_OBJ_COMPACT) == 0):
|
||||
print >> out
|
||||
print >> out, " "*indent, "}",
|
||||
elif (indent < 0):
|
||||
print >> out, object,
|
||||
elif isinstance(object, basestring):
|
||||
if ((exclude != None) and name in exclude):
|
||||
print >> out, " "*indent, name, " : ", toTypeString(object), " of length = ", len(object), " (excluded)",
|
||||
print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = ", len(object), " (excluded)",
|
||||
elif (len(object) > 100):
|
||||
print >> out, " "*indent, name, ":", toTypeString(object), "[%d] = %s...%s" % (len(object), object[:50], object[-50:]),
|
||||
object = toString(object, flags)
|
||||
print >> out, " "*indent, name, ":", typeToString(object, flags), "[%d] = %s...%s" % (len(object), object[:50], object[-50:]),
|
||||
else:
|
||||
print >> out, " "*indent, name, ":", toTypeString(object), "=", str(object),
|
||||
print >> out, " "*indent, name, ":", typeToString(object, flags), "=", toString(object, flags),
|
||||
## elif (isinstance(object, float)):
|
||||
## val = str(object)
|
||||
## if (len(val) > 17):
|
||||
## val = val[:17]
|
||||
## print >> out, " "*indent, name, ":", type(object), "=", val,
|
||||
else:
|
||||
print >> out, " "*indent, name, ":", toTypeString(object), "=", str(object),
|
||||
print >> out, " "*indent, name, ":", typeToString(object, flags), "=", toString(object, flags),
|
||||
if (finalNewLine):
|
||||
print >> out
|
||||
return printed
|
||||
|
||||
23
wxPython/samples/ide/activegrid/util/strutils.py
Normal file
23
wxPython/samples/ide/activegrid/util/strutils.py
Normal file
@@ -0,0 +1,23 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: strutils.py
|
||||
# Purpose: String Utilities
|
||||
#
|
||||
# Author: Morgan Hua
|
||||
#
|
||||
# Created: 11/3/05
|
||||
# CVS-ID: $Id$
|
||||
# Copyright: (c) 2005 ActiveGrid, Inc.
|
||||
# License: wxWindows License
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def caseInsensitiveCompare(s1, s2):
|
||||
""" Method used by sort() to sort values in case insensitive order """
|
||||
s1L = s1.lower()
|
||||
s2L = s2.lower()
|
||||
if s1L == s2L:
|
||||
return 0
|
||||
elif s1L < s2L:
|
||||
return -1
|
||||
else:
|
||||
return 1
|
||||
87
wxPython/samples/ide/activegrid/util/sysutils.py
Normal file
87
wxPython/samples/ide/activegrid/util/sysutils.py
Normal file
@@ -0,0 +1,87 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: sysutils.py
|
||||
# Purpose: System Utilities
|
||||
#
|
||||
# Author: Joel Hare
|
||||
#
|
||||
# Created: 7/28/04
|
||||
# CVS-ID: $Id$
|
||||
# Copyright: (c) 2004-2005 ActiveGrid, Inc.
|
||||
# License: wxWindows License
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# this will be set to true in IDE.py when we are running release builds.
|
||||
isRelease = False
|
||||
|
||||
# Commented out for now.....
|
||||
# Required for Unicode support with python
|
||||
# Put over here because of py2exe problems
|
||||
# Python suggests modifying site.py
|
||||
#if hasattr(sys,"setdefaultencoding"):
|
||||
# sys.setdefaultencoding("UTF-8")
|
||||
|
||||
|
||||
MAINMODULE_DIR = "AG_MAINMODULE_DIR"
|
||||
IS_RELEASE = "AG_IS_RELEASE"
|
||||
|
||||
def isRelease():
|
||||
return 'true' == (str(os.getenv(IS_RELEASE)).lower())
|
||||
|
||||
def setRelease(value):
|
||||
if value:
|
||||
os.environ[IS_RELEASE]= "TRUE"
|
||||
else:
|
||||
os.environ[IS_RELEASE]= "FALSE"
|
||||
|
||||
def isWindows():
|
||||
return os.name == 'nt'
|
||||
|
||||
|
||||
def _generateMainModuleDir():
|
||||
mainModuleDir = os.getenv(MAINMODULE_DIR)
|
||||
if mainModuleDir: # if environment variable set, return it
|
||||
return mainModuleDir
|
||||
|
||||
# On Mac, the python executable sometimes has a capital "P" so we need to
|
||||
# lower the string first
|
||||
sysExecLower = sys.executable.lower()
|
||||
if sysExecLower == "/" or sysExecLower.find('python') != -1 or sysExecLower.find('apache') != -1:
|
||||
utilModuleDir = os.path.dirname(__file__)
|
||||
if not os.path.isabs(utilModuleDir):
|
||||
utilModuleDir = os.path.join(os.getcwd(), utilModuleDir)
|
||||
mainModuleDir = os.path.normpath(os.path.join(utilModuleDir, os.path.join(os.path.pardir, os.path.pardir)))
|
||||
if mainModuleDir.endswith('.zip'):
|
||||
mainModuleDir = os.path.dirname(mainModuleDir) # Get rid of library.zip
|
||||
else:
|
||||
mainModuleDir = os.path.dirname(sys.executable)
|
||||
|
||||
os.environ[MAINMODULE_DIR] = mainModuleDir # pythonBug: os.putenv doesn't work, set environment variable
|
||||
|
||||
return mainModuleDir
|
||||
|
||||
mainModuleDir = _generateMainModuleDir()
|
||||
|
||||
def _generatePythonExecPath():
|
||||
# On Mac, the python executable sometimes has a capital "P" so we need to
|
||||
# lower the string first
|
||||
sysExecLower = sys.executable.lower()
|
||||
if sysExecLower.find('python') != -1 or sysExecLower.find('apache') != -1:
|
||||
pythonExecPath = sys.executable
|
||||
else:
|
||||
# this is where py2app puts the Python executable
|
||||
if sys.platform == "darwin":
|
||||
pythonExecPath = os.path.join(os.path.dirname(sys.executable), "../Frameworks/Python.Framework/Versions/2.4/Python/bin")
|
||||
else:
|
||||
pythonExecPath = os.path.join(os.path.dirname(sys.executable), '3rdparty\python2.4\python')
|
||||
return pythonExecPath
|
||||
|
||||
pythonExecPath = _generatePythonExecPath()
|
||||
|
||||
def getCommandNameForExecPath(execPath):
|
||||
if isWindows():
|
||||
return '"%s"' % execPath
|
||||
return execPath
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,8 +9,10 @@
|
||||
# Copyright: (c) 2004-2005 ActiveGrid, Inc.
|
||||
# License: wxWindows License
|
||||
#----------------------------------------------------------------------------
|
||||
import xml.sax
|
||||
from activegrid.util.lang import *
|
||||
ifDefPy()
|
||||
import xml.sax
|
||||
endIfDef()
|
||||
|
||||
class XMLPrettyPrinter(xml.sax.ContentHandler):
|
||||
def __init__(self, indentationChar=' ', newlineChar='\n'):
|
||||
|
||||
@@ -10,80 +10,275 @@
|
||||
# License: wxWindows License
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
from activegrid.util.lang import *
|
||||
import os
|
||||
import time
|
||||
import urllib
|
||||
import logging
|
||||
from activegrid.util.lang import *
|
||||
import activegrid.util.objutils as objutils
|
||||
import activegrid.util.xmlmarshaller as xmlmarshaller
|
||||
import activegrid.util.aglogging as aglogging
|
||||
|
||||
agKnownTypes = None
|
||||
|
||||
def defaultLoad(fileObject, knownTypes=None):
|
||||
xml = fileObject.read()
|
||||
loadedObject = unmarshal(xml, knownTypes=knownTypes)
|
||||
if hasattr(fileObject, 'name'):
|
||||
loadedObject.fileName = os.path.abspath(fileObject.name)
|
||||
loadedObject.initialize()
|
||||
xmlLogger = logging.getLogger("activegrid.util.xml")
|
||||
|
||||
def load(fileName, knownTypes=None, knownNamespaces=None):
|
||||
loadedObject = None
|
||||
fileObject = file(fileName)
|
||||
timeStart = time.time()
|
||||
try:
|
||||
xml = fileObject.read()
|
||||
loadedObject = unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=fileName)
|
||||
loadedObject.fileName = os.path.abspath(fileName)
|
||||
if hasattr(loadedObject, 'initialize'):
|
||||
loadedObject.initialize()
|
||||
finally:
|
||||
fileObject.close()
|
||||
timeDone = time.time()
|
||||
aglogging.info(xmlLogger, ('Load statistics for file %s: elapsed time = %f secs' % (fileName, timeDone-timeStart)))
|
||||
return loadedObject
|
||||
|
||||
def unmarshal(xml, knownTypes=None):
|
||||
if not knownTypes: knownTypes = getAgKnownTypes()
|
||||
return xmlmarshaller.unmarshal(xml, knownTypes=knownTypes)
|
||||
def loadURI(uri, knownTypes=None, knownNamespaces=None, xmlSource=None):
|
||||
loadedObject = None
|
||||
xml = urllib.urlopen(uri).read()
|
||||
loadedObject = unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=xmlSource)
|
||||
loadedObject.fileName = uri
|
||||
if hasattr(loadedObject, 'initialize'):
|
||||
loadedObject.initialize()
|
||||
return loadedObject
|
||||
|
||||
def defaultSave(fileObject, objectToSave, prettyPrint=True, knownTypes=None, encoding='utf-8'):
|
||||
xml = marshal(objectToSave, prettyPrint=prettyPrint, knownTypes=knownTypes, encoding=encoding)
|
||||
fileObject.write(xml)
|
||||
fileObject.flush()
|
||||
def unmarshal(xml, knownTypes=None, knownNamespaces=None, xmlSource=None):
|
||||
if (knownTypes == None):
|
||||
knownTypes, knownNamespaces = getAgKnownTypes()
|
||||
return xmlmarshaller.unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=xmlSource)
|
||||
|
||||
def marshal(objectToSave, prettyPrint=True, knownTypes=None, encoding='utf-8'):
|
||||
if not knownTypes: knownTypes = getAgKnownTypes()
|
||||
return xmlmarshaller.marshal(objectToSave, prettyPrint=prettyPrint, knownTypes=knownTypes, encoding=encoding)
|
||||
def save(fileName, objectToSave, prettyPrint=True, marshalType=True, knownTypes=None, knownNamespaces=None, encoding='utf-8'):
|
||||
if hasattr(objectToSave, '_xmlReadOnly') and objectToSave._xmlReadOnly == True:
|
||||
raise xmlmarshaller.MarshallerException('Error marshalling object to file "%s": object is marked "readOnly" and cannot be written' % (fileName))
|
||||
timeStart = time.time()
|
||||
xml = marshal(objectToSave, prettyPrint=prettyPrint, marshalType=marshalType, knownTypes=knownTypes, knownNamespaces=knownNamespaces, encoding=encoding)
|
||||
fileObject = file(fileName, 'w')
|
||||
try:
|
||||
fileObject.write(xml)
|
||||
fileObject.flush()
|
||||
except Exception, errorData:
|
||||
fileObject.close()
|
||||
raise xmlmarshaller.MarshallerException('Error marshalling object to file "%s": %s' % (fileName, str(errorData)))
|
||||
fileObject.close()
|
||||
timeDone = time.time()
|
||||
aglogging.info(xmlLogger, ('Save statistics for file %s: elapsed time = %f secs' % (fileName, timeDone-timeStart)))
|
||||
|
||||
def cloneObject(objectToClone, knownTypes=None, encoding='utf-8'):
|
||||
if not knownTypes: knownTypes = getAgKnownTypes()
|
||||
xml = xmlmarshaller.marshal(objectToClone, prettyPrint=True, knownTypes=knownTypes, encoding=encoding)
|
||||
clonedObject = xmlmarshaller.unmarshal(xml, knownTypes=knownTypes)
|
||||
def marshal(objectToSave, prettyPrint=True, marshalType=True, knownTypes=None, knownNamespaces=None, encoding='utf-8'):
|
||||
if (knownTypes == None):
|
||||
knownTypes, knownNamespaces = getAgKnownTypes()
|
||||
return xmlmarshaller.marshal(objectToSave, prettyPrint=prettyPrint, marshalType=marshalType, knownTypes=knownTypes, knownNamespaces=knownNamespaces, encoding=encoding)
|
||||
|
||||
def addNSAttribute(xmlDoc, shortNamespace, longNamespace):
|
||||
if not hasattr(xmlDoc, "__xmlnamespaces__"):
|
||||
xmlDoc.__xmlnamespaces__ = {shortNamespace:longNamespace}
|
||||
elif shortNamespace not in xmlDoc.__xmlnamespaces__:
|
||||
if (hasattr(xmlDoc.__class__, "__xmlnamespaces__")
|
||||
and (xmlDoc.__xmlnamespaces__ is xmlDoc.__class__.__xmlnamespaces__)):
|
||||
xmlDoc.__xmlnamespaces__ = dict(xmlDoc.__xmlnamespaces__)
|
||||
xmlDoc.__xmlnamespaces__[shortNamespace] = longNamespace
|
||||
|
||||
def genShortNS(xmlDoc, longNamespace=None):
|
||||
if not hasattr(xmlDoc, "__xmlnamespaces__"):
|
||||
return "ns1"
|
||||
elif longNamespace != None and longNamespace in xmlDoc.__xmlnamespaces__.items():
|
||||
for key, value in xmlDoc.__xmlnamespaces__.iteritems():
|
||||
if value == longNamespace:
|
||||
return key
|
||||
i = 1
|
||||
while ("ns%d" % i) in xmlDoc.__xmlnamespaces__:
|
||||
i += 1
|
||||
return ("ns%d" % i)
|
||||
|
||||
def genTargetNS(fileName, applicationName=None, type=None):
|
||||
if (applicationName != None):
|
||||
if (type != None):
|
||||
tns = "urn:%s:%s:%s" % (applicationName, type, fileName)
|
||||
else:
|
||||
tns = "urn:%s:%s" % (applicationName, fileName)
|
||||
else:
|
||||
tns = "urn:%s" % fileName
|
||||
return tns
|
||||
|
||||
def splitType(typeName):
|
||||
index = typeName.rfind(':')
|
||||
if index != -1:
|
||||
ns = typeName[:index]
|
||||
complexTypeName = typeName[index+1:]
|
||||
else:
|
||||
ns = None
|
||||
complexTypeName = typeName
|
||||
return (ns, complexTypeName)
|
||||
|
||||
def cloneObject(objectToClone, knownTypes=None, marshalType=True, knownNamespaces=None, encoding='utf-8'):
|
||||
if (knownTypes == None):
|
||||
knownTypes, knownNamespaces = getAgKnownTypes()
|
||||
xml = xmlmarshaller.marshal(objectToClone, prettyPrint=True, marshalType=marshalType, knownTypes=knownTypes, knownNamespaces=knownNamespaces, encoding=encoding)
|
||||
clonedObject = xmlmarshaller.unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces)
|
||||
if hasattr(objectToClone, 'fileName'):
|
||||
clonedObject.fileName = objectToClone.fileName
|
||||
if hasattr(objectToClone, "_parentDoc"):
|
||||
clonedObject._parentDoc = objectToClone._parentDoc
|
||||
try:
|
||||
clonedObject.initialize()
|
||||
except AttributeError:
|
||||
pass
|
||||
return clonedObject
|
||||
|
||||
def getAgKnownTypes():
|
||||
import activegrid.model.processmodel
|
||||
import activegrid.model.schema
|
||||
import activegrid.data.dataservice
|
||||
import activegrid.server.deployment
|
||||
global agKnownTypes
|
||||
if agKnownTypes == None:
|
||||
tmpAgKnownTypes = {}
|
||||
AG_TYPE_MAPPING = {
|
||||
def getAgVersion(fileName):
|
||||
fileObject = file(fileName)
|
||||
try:
|
||||
xml = fileObject.read()
|
||||
finally:
|
||||
fileObject.close()
|
||||
i = xml.find(' ag:version=')
|
||||
if i >= 0:
|
||||
i += 12
|
||||
else:
|
||||
i2 = xml.find('<ag:')
|
||||
if i2 >= 0:
|
||||
i = xml.find(' version=', i2)
|
||||
if i > 0:
|
||||
i += 9
|
||||
elif xml.find('<project version="10"') >= 0:
|
||||
return "10"
|
||||
else:
|
||||
return None
|
||||
version = None
|
||||
if xml[i:i+1] == '"':
|
||||
j = xml.find('"', i+1)
|
||||
if (j > i+1):
|
||||
version = xml[i+1:j]
|
||||
return version
|
||||
|
||||
def escape(data):
|
||||
"""Escape ', ", &, <, and > in a string of data.
|
||||
|
||||
Basically, everything that saxutils.escape does (and this calls that, at
|
||||
least for now), but with " added as well.
|
||||
|
||||
XXX TODO make this faster; saxutils.escape() is really slow
|
||||
"""
|
||||
|
||||
import xml.sax.saxutils as saxutils
|
||||
|
||||
data=saxutils.escape(data)
|
||||
data=data.replace("\"", """)
|
||||
|
||||
# IE doesn't support '
|
||||
# data=data.replace("\'", "'")
|
||||
data=data.replace("\'", "'")
|
||||
|
||||
return data
|
||||
|
||||
def unescape(data):
|
||||
"""Unescape ', ", &, <, and > in a string of data.
|
||||
|
||||
Basically, everything that saxutils.unescape does (and this calls that, at
|
||||
least for now), but with " added as well.
|
||||
|
||||
XXX TODO make this faster; saxutils.unescape() is really slow
|
||||
"""
|
||||
|
||||
import xml.sax.saxutils as saxutils
|
||||
|
||||
data=data.replace(""", "\"")
|
||||
data=data.replace("'", "\'")
|
||||
return saxutils.unescape(data)
|
||||
|
||||
|
||||
AG_NS_URL = "http://www.activegrid.com/ag.xsd"
|
||||
BPEL_NS_URL = "http://schemas.xmlsoap.org/ws/2003/03/business-process"
|
||||
HTTP_WSDL_NS_URL = "http://schemas.xmlsoap.org/wsdl/http/"
|
||||
MIME_WSDL_NS_URL = "http://schemas.xmlsoap.org/wsdl/mime/"
|
||||
SOAP_NS_URL = "http://schemas.xmlsoap.org/wsdl/soap/"
|
||||
SOAP12_NS_URL = "http://schemas.xmlsoap.org/wsdl/soap12/"
|
||||
WSDL_NS_URL = "http://schemas.xmlsoap.org/wsdl/"
|
||||
XFORMS_NS_URL = "http://www.w3c.org/xform.xsd"
|
||||
XMLSCHEMA_NS_URL = "http://www.w3.org/2001/XMLSchema"
|
||||
XSI_NS_URL = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
XACML_NS_URL = "urn:oasis:names:tc:xacml:2.0:policy:schema:os"
|
||||
|
||||
KNOWN_NAMESPACES = { AG_NS_URL : "ag",
|
||||
BPEL_NS_URL : "bpws",
|
||||
HTTP_WSDL_NS_URL : "http",
|
||||
MIME_WSDL_NS_URL : "mime",
|
||||
SOAP_NS_URL : "soap",
|
||||
SOAP12_NS_URL : "soap12",
|
||||
WSDL_NS_URL : "wsdl",
|
||||
XFORMS_NS_URL : "xforms",
|
||||
XMLSCHEMA_NS_URL : "xs",
|
||||
XACML_NS_URL : "xacml",
|
||||
}
|
||||
|
||||
global agXsdToClassName
|
||||
agXsdToClassName = None
|
||||
def getAgXsdToClassName():
|
||||
global agXsdToClassName
|
||||
if (agXsdToClassName == None):
|
||||
agXsdToClassName = {
|
||||
"ag:append" : "activegrid.model.processmodel.AppendOperation",
|
||||
"ag:attribute" : "activegrid.model.identitymodel.Attribute",
|
||||
"ag:body" : "activegrid.model.processmodel.Body",
|
||||
"ag:category_substitutions" : "activegrid.server.layoutrenderer.CategorySubstitutions",
|
||||
"ag:command" : "activegrid.model.wsdl.Command",
|
||||
"ag:css" : "activegrid.server.layoutrenderer.CSS",
|
||||
"ag:cssRule" : "activegrid.model.processmodel.CssRule",
|
||||
"ag:databaseService" : "activegrid.server.deployment.DatabaseService",
|
||||
"ag:datasource" : "activegrid.data.dataservice.DataSource",
|
||||
"ag:dataObjectList" : "activegrid.data.datalang.DataObjectList",
|
||||
"ag:debug" : "activegrid.model.processmodel.DebugOperation",
|
||||
"ag:deployment" : "activegrid.server.deployment.Deployment",
|
||||
"ag:glue" : "activegrid.model.processmodel.Glue",
|
||||
"ag:generator" : "activegrid.server.layoutrenderer.SerializableGenerator",
|
||||
"ag:head" : "activegrid.server.layoutrenderer.Head",
|
||||
"ag:hr" : "activegrid.model.processmodel.HorizontalRow",
|
||||
"ag:identity" : "activegrid.model.identitymodel.Identity",
|
||||
"ag:identityref" : "activegrid.server.deployment.IdentityRef",
|
||||
"ag:image" : "activegrid.model.processmodel.Image",
|
||||
"ag:inputs" : "activegrid.model.processmodel.Inputs",
|
||||
"ag:label" : "activegrid.model.processmodel.Label",
|
||||
"ag:processmodel" : "activegrid.model.processmodel.ProcessModel",
|
||||
"ag:processmodelref" : "activegrid.server.deployment.ProcessModelRef",
|
||||
"ag:layout" : "activegrid.server.layoutrenderer.Layout",
|
||||
"ag:layouts" : "activegrid.server.layoutrenderer.Layouts",
|
||||
"ag:ldapsource" : "activegrid.model.identitymodel.LDAPSource",
|
||||
"ag:localService" : "activegrid.server.deployment.LocalService",
|
||||
"ag:parameter" : "activegrid.server.layoutrenderer.Parameter",
|
||||
"ag:parameters" : "activegrid.server.layoutrenderer.Parameters",
|
||||
"ag:processref" : "activegrid.server.deployment.ProcessRef",
|
||||
"ag:query" : "activegrid.model.processmodel.Query",
|
||||
"ag:restParameter" : "activegrid.server.deployment.RestParameter",
|
||||
"ag:soapService" : "activegrid.server.deployment.SoapService",
|
||||
"ag:requiredFile" : "activegrid.server.layoutrenderer.RequiredFile",
|
||||
"ag:resource" : "activegrid.model.identitymodel.IDResource",
|
||||
"ag:restService" : "activegrid.server.deployment.RestService",
|
||||
"ag:rewrite" : "activegrid.model.wsdl.Rewrite",
|
||||
"ag:role" : "activegrid.model.identitymodel.IDRole",
|
||||
"ag:roledefn" : "activegrid.model.identitymodel.RoleDefn",
|
||||
"ag:rssService" : "activegrid.server.deployment.RssService",
|
||||
"ag:rule" : "activegrid.model.identitymodel.IDRule",
|
||||
"ag:schemaOptions" : "activegrid.model.schema.SchemaOptions",
|
||||
"ag:schemaref" : "activegrid.server.deployment.SchemaRef",
|
||||
"ag:serviceCache" : "activegrid.server.deployment.ServiceCache",
|
||||
"ag:serviceExtension": "activegrid.model.wsdl.ServiceExtension",
|
||||
"ag:serviceExtensions": "activegrid.model.wsdl.ServiceExtensions",
|
||||
"ag:serviceParameter": "activegrid.server.deployment.ServiceParameter",
|
||||
"ag:serviceref" : "activegrid.server.deployment.ServiceRef",
|
||||
"ag:set" : "activegrid.model.processmodel.SetOperation",
|
||||
"ag:skinref" : "activegrid.server.deployment.SkinRef",
|
||||
"ag:skin" : "activegrid.server.layoutrenderer.Skin",
|
||||
"ag:skin_element_ref": "activegrid.server.layoutrenderer.SkinElementRef",
|
||||
"ag:skin_element" : "activegrid.server.layoutrenderer.SkinElement",
|
||||
"ag:skins" : "activegrid.server.layoutrenderer.Skins",
|
||||
"ag:substitution" : "activegrid.server.layoutrenderer.Substitution",
|
||||
"ag:text" : "activegrid.model.processmodel.Text",
|
||||
"ag:title" : "activegrid.model.processmodel.Title",
|
||||
"ag:view" : "activegrid.model.processmodel.View",
|
||||
"ag:usertemplate" : "activegrid.model.identitymodel.UserTemplate",
|
||||
"ag:xformref" : "activegrid.server.deployment.XFormRef",
|
||||
"bpws:case" : "activegrid.model.processmodel.BPELCase",
|
||||
"bpws:catch" : "activegrid.model.processmodel.BPELCatch",
|
||||
"bpws:faultHandlers" : "activegrid.model.processmodel.BPELFaultHandlers",
|
||||
"bpws:flow" : "activegrid.model.processmodel.BPELFlow",
|
||||
"bpws:invoke" : "activegrid.model.processmodel.BPELInvoke",
|
||||
"bpws:onMessage" : "activegrid.model.processmodel.BPELOnMessage",
|
||||
"bpws:otherwise" : "activegrid.model.processmodel.BPELOtherwise",
|
||||
@@ -98,31 +293,117 @@ def getAgKnownTypes():
|
||||
"bpws:variable" : "activegrid.model.processmodel.BPELVariable",
|
||||
"bpws:variables" : "activegrid.model.processmodel.BPELVariables",
|
||||
"bpws:while" : "activegrid.model.processmodel.BPELWhile",
|
||||
"wsdl:message" : "activegrid.model.processmodel.WSDLMessage",
|
||||
"wsdl:part" : "activegrid.model.processmodel.WSDLPart",
|
||||
"http:address" : "activegrid.model.wsdl.HttpAddress",
|
||||
"http:binding" : "activegrid.model.wsdl.HttpBinding",
|
||||
"http:operation" : "activegrid.model.wsdl.HttpOperation",
|
||||
"http:urlEncoded" : "activegrid.model.wsdl.HttpUrlEncoded",
|
||||
"mime:content" : "activegrid.model.wsdl.MimeContent",
|
||||
"mime:mimeXml" : "activegrid.model.wsdl.MimeMimeXml",
|
||||
"soap:address" : "activegrid.model.wsdl.SoapAddress",
|
||||
"soap:binding" : "activegrid.model.wsdl.SoapBinding",
|
||||
"soap:body" : "activegrid.model.wsdl.SoapBody",
|
||||
"soap:fault" : "activegrid.model.wsdl.SoapFault",
|
||||
"soap:header" : "activegrid.model.wsdl.SoapHeader",
|
||||
"soap:operation" : "activegrid.model.wsdl.SoapOperation",
|
||||
"soap12:address" : "activegrid.model.wsdl.Soap12Address",
|
||||
"soap12:binding" : "activegrid.model.wsdl.Soap12Binding",
|
||||
"soap12:body" : "activegrid.model.wsdl.Soap12Body",
|
||||
"soap12:fault" : "activegrid.model.wsdl.Soap12Fault",
|
||||
"soap12:header" : "activegrid.model.wsdl.Soap12Header",
|
||||
"soap12:operation" : "activegrid.model.wsdl.Soap12Operation",
|
||||
"wsdl:binding" : "activegrid.model.wsdl.WsdlBinding",
|
||||
"wsdl:definitions" : "activegrid.model.wsdl.WsdlDocument",
|
||||
"wsdl:documentation" : "activegrid.model.wsdl.WsdlDocumentation",
|
||||
"wsdl:fault" : "activegrid.model.wsdl.WsdlFault",
|
||||
"wsdl:import" : "activegrid.model.wsdl.WsdlImport",
|
||||
"wsdl:input" : "activegrid.model.wsdl.WsdlInput",
|
||||
"wsdl:message" : "activegrid.model.wsdl.WsdlMessage",
|
||||
"wsdl:operation" : "activegrid.model.wsdl.WsdlOperation",
|
||||
"wsdl:output" : "activegrid.model.wsdl.WsdlOutput",
|
||||
"wsdl:part" : "activegrid.model.wsdl.WsdlPart",
|
||||
"wsdl:port" : "activegrid.model.wsdl.WsdlPort",
|
||||
"wsdl:portType" : "activegrid.model.wsdl.WsdlPortType",
|
||||
"wsdl:service" : "activegrid.model.wsdl.WsdlService",
|
||||
"wsdl:types" : "activegrid.model.wsdl.WsdlTypes",
|
||||
"xacml:Action" : "activegrid.model.identitymodel.XACMLAction",
|
||||
"xacml:ActionAttributeDesignator" : "activegrid.model.identitymodel.XACMLActionAttributeDesignator",
|
||||
"xacml:ActionMatch" : "activegrid.model.identitymodel.XACMLActionMatch",
|
||||
"xacml:Actions" : "activegrid.model.identitymodel.XACMLActions",
|
||||
"xacml:AttributeValue" : "activegrid.model.identitymodel.XACMLAttributeValue",
|
||||
"xacml:Policy" : "activegrid.model.identitymodel.XACMLPolicy",
|
||||
"xacml:Resource" : "activegrid.model.identitymodel.XACMLResource",
|
||||
"xacml:ResourceAttributeDesignator" : "activegrid.model.identitymodel.XACMLResourceAttributeDesignator",
|
||||
"xacml:ResourceMatch" : "activegrid.model.identitymodel.XACMLResourceMatch",
|
||||
"xacml:Resources" : "activegrid.model.identitymodel.XACMLResources",
|
||||
"xacml:Rule" : "activegrid.model.identitymodel.XACMLRule",
|
||||
"xacml:Target" : "activegrid.model.identitymodel.XACMLTarget",
|
||||
"xforms:copy" : "activegrid.model.processmodel.XFormsCopy",
|
||||
"xforms:group" : "activegrid.model.processmodel.XFormsGroup",
|
||||
"xforms:include" : "activegrid.model.processmodel.XFormsInclude",
|
||||
"xforms:input" : "activegrid.model.processmodel.XFormsInput",
|
||||
"xforms:item" : "activegrid.model.processmodel.XFormsItem",
|
||||
"xforms:itemset" : "activegrid.model.processmodel.XFormsItemset",
|
||||
"xforms:label" : "activegrid.model.processmodel.XFormsLabel",
|
||||
"xforms:model" : "activegrid.model.processmodel.XFormsModel",
|
||||
"xforms:output" : "activegrid.model.processmodel.XFormsOutput",
|
||||
"xforms:secret" : "activegrid.model.processmodel.XFormsSecret",
|
||||
"xforms:select1" : "activegrid.model.processmodel.XFormsSelect1",
|
||||
"xforms:submission" : "activegrid.model.processmodel.XFormsSubmission",
|
||||
"xforms:submit" : "activegrid.model.processmodel.XFormsSubmit",
|
||||
"xforms:value" : "activegrid.model.processmodel.XFormsValue",
|
||||
"xforms:xform" : "activegrid.model.processmodel.View",
|
||||
"xforms:xforms" : "activegrid.model.processmodel.XFormsRoot",
|
||||
"xs:all" : "activegrid.model.schema.XsdSequence",
|
||||
"xs:any" : "activegrid.model.schema.XsdAny",
|
||||
"xs:attribute" : "activegrid.model.schema.XsdAttribute",
|
||||
"xs:complexContent" : "activegrid.model.schema.XsdComplexContent",
|
||||
"xs:complexType" : "activegrid.model.schema.XsdComplexType",
|
||||
"xs:element" : "activegrid.model.schema.XsdElement",
|
||||
"xs:enumeration" : "activegrid.model.schema.XsdEnumeration",
|
||||
"xs:extension" : "activegrid.model.schema.XsdExtension",
|
||||
"xs:field" : "activegrid.model.schema.XsdKeyField",
|
||||
"xs:import" : "activegrid.model.schema.XsdInclude",
|
||||
"xs:include" : "activegrid.model.schema.XsdInclude",
|
||||
"xs:key" : "activegrid.model.schema.XsdKey",
|
||||
"xs:keyref" : "activegrid.model.schema.XsdKeyRef",
|
||||
"xs:length" : "activegrid.model.schema.XsdLength",
|
||||
"xs:list" : "activegrid.model.schema.XsdList",
|
||||
"xs:maxLength" : "activegrid.model.schema.XsdMaxLength",
|
||||
"xs:restriction" : "activegrid.model.schema.XsdRestriction",
|
||||
"xs:schema" : "activegrid.model.schema.Schema",
|
||||
"xs:selector" : "activegrid.model.schema.XsdKeySelector",
|
||||
"xs:sequence" : "activegrid.model.schema.XsdSequence",
|
||||
}
|
||||
|
||||
for keyName, className in AG_TYPE_MAPPING.iteritems():
|
||||
try:
|
||||
tmpAgKnownTypes[keyName] = objutils.classForName(className)
|
||||
except KeyError:
|
||||
print "Error mapping knownType", className
|
||||
pass
|
||||
if len(tmpAgKnownTypes) > 0:
|
||||
agKnownTypes = tmpAgKnownTypes
|
||||
return agKnownTypes
|
||||
"xs:simpleContent" : "activegrid.model.schema.XsdSimpleContent",
|
||||
"xs:simpleType" : "activegrid.model.schema.XsdSimpleType",
|
||||
"xs:totalDigits" : "activegrid.model.schema.XsdTotalDigits",
|
||||
}
|
||||
return agXsdToClassName
|
||||
|
||||
global agKnownTypes
|
||||
agKnownTypes = None
|
||||
def getAgKnownTypes():
|
||||
global agKnownTypes
|
||||
if agKnownTypes == None:
|
||||
try:
|
||||
tmpAgKnownTypes = {}
|
||||
import activegrid.model.processmodel
|
||||
import activegrid.model.schema
|
||||
import activegrid.server.deployment
|
||||
import activegrid.model.wsdl
|
||||
ifDefPy()
|
||||
import activegrid.data.dataservice
|
||||
endIfDef()
|
||||
for keyName, className in getAgXsdToClassName().iteritems():
|
||||
classType = objutils.classForName(className)
|
||||
if (classType == None):
|
||||
raise Exception("Cannot get class type for %s" % className)
|
||||
else:
|
||||
tmpAgKnownTypes[keyName] = classType
|
||||
if len(tmpAgKnownTypes) > 0:
|
||||
agKnownTypes = tmpAgKnownTypes
|
||||
except ImportError:
|
||||
agKnownTypes = {}
|
||||
if len(agKnownTypes) == 0: # standalone IDE and XmlMarshaller don't contain known AG types
|
||||
noKnownNamespaces = {}
|
||||
return agKnownTypes, noKnownNamespaces
|
||||
return agKnownTypes, KNOWN_NAMESPACES
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
import wx
|
||||
import wx.lib.docview as docview
|
||||
import wx.lib.pydocview as pydocview
|
||||
import TextEditor
|
||||
import FindService
|
||||
import os.path
|
||||
_ = wx.GetTranslation
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ class TextEditorApplication(pydocview.DocApp):
|
||||
if os.path.exists("tips.txt"):
|
||||
wx.CallAfter(self.ShowTip, wx.GetApp().GetTopWindow(), wx.CreateFileTipProvider("tips.txt", 0))
|
||||
|
||||
wx.UpdateUIEvent.SetUpdateInterval(400) # Overhead of updating menus was too much. Change to update every 400 milliseconds.
|
||||
wx.UpdateUIEvent.SetUpdateInterval(1000) # Overhead of updating menus was too much. Change to update every N milliseconds.
|
||||
|
||||
# Tell the framework that everything is great
|
||||
return True
|
||||
|
||||
@@ -34,8 +34,9 @@ import sys, os
|
||||
# We happen to be doing that here in this script, so make sure to
|
||||
# remove the build_options.py file, so that config.py will recreate it.
|
||||
|
||||
if os.path.exists("build_options.py"):
|
||||
os.remove("build_options.py")
|
||||
for bo_name in ["build_options.py", "build_options.pyc"]:
|
||||
if os.path.exists(bo_name):
|
||||
os.remove(bo_name)
|
||||
|
||||
sys.setup_is_main = __name__ == "__main__" # an icky hack!
|
||||
from config import *
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
%rename(SIZE_AUTO) wxSIZE_AUTO;
|
||||
%rename(SIZE_USE_EXISTING) wxSIZE_USE_EXISTING;
|
||||
%rename(SIZE_ALLOW_MINUS_ONE) wxSIZE_ALLOW_MINUS_ONE;
|
||||
%rename(SIZE_FORCE) wxSIZE_FORCE;
|
||||
%rename(PORTRAIT) wxPORTRAIT;
|
||||
%rename(LANDSCAPE) wxLANDSCAPE;
|
||||
%rename(PRINT_QUALITY_HIGH) wxPRINT_QUALITY_HIGH;
|
||||
@@ -99,6 +100,7 @@
|
||||
%rename(PRINT_QUALITY_DRAFT) wxPRINT_QUALITY_DRAFT;
|
||||
%rename(ID_ANY) wxID_ANY;
|
||||
%rename(ID_SEPARATOR) wxID_SEPARATOR;
|
||||
%rename(ID_NONE) wxID_NONE;
|
||||
%rename(ID_LOWEST) wxID_LOWEST;
|
||||
%rename(ID_OPEN) wxID_OPEN;
|
||||
%rename(ID_CLOSE) wxID_CLOSE;
|
||||
@@ -476,8 +478,12 @@
|
||||
%rename(MOD_NONE) wxMOD_NONE;
|
||||
%rename(MOD_ALT) wxMOD_ALT;
|
||||
%rename(MOD_CONTROL) wxMOD_CONTROL;
|
||||
%rename(MOD_ALTGR) wxMOD_ALTGR;
|
||||
%rename(MOD_SHIFT) wxMOD_SHIFT;
|
||||
%rename(MOD_META) wxMOD_META;
|
||||
%rename(MOD_WIN) wxMOD_WIN;
|
||||
%rename(MOD_CMD) wxMOD_CMD;
|
||||
%rename(MOD_ALL) wxMOD_ALL;
|
||||
%rename(UPDATE_UI_NONE) wxUPDATE_UI_NONE;
|
||||
%rename(UPDATE_UI_RECURSE) wxUPDATE_UI_RECURSE;
|
||||
%rename(UPDATE_UI_FROMIDLE) wxUPDATE_UI_FROMIDLE;
|
||||
@@ -554,6 +560,7 @@
|
||||
%rename(IMAGE_ALPHA_THRESHOLD) wxIMAGE_ALPHA_THRESHOLD;
|
||||
%rename(IMAGE_ALPHA_OPAQUE) wxIMAGE_ALPHA_OPAQUE;
|
||||
%rename(ImageHandler) wxImageHandler;
|
||||
%rename(PyImageHandler) wxPyImageHandler;
|
||||
%rename(ImageHistogram) wxImageHistogram;
|
||||
%rename(Image_RGBValue) wxImage_RGBValue;
|
||||
%rename(Image_HSVValue) wxImage_HSVValue;
|
||||
|
||||
@@ -283,10 +283,13 @@ the ``type`` parameter.", "");
|
||||
|
||||
#ifdef __WXMSW__
|
||||
bool CopyFromCursor(const wxCursor& cursor);
|
||||
|
||||
// WXWIN_COMPATIBILITY_2_4
|
||||
#if 0
|
||||
int GetQuality();
|
||||
void SetQuality(int q);
|
||||
%pythoncode { GetQuality = wx._deprecated(GetQuality) }
|
||||
%pythoncode { SetQuality = wx._deprecated(SetQuality) }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -73,6 +73,15 @@ public:
|
||||
List choices=EmptyList, long style=0, Validator validator=DefaultValidator,
|
||||
String name=ChoiceNameStr) -> bool",
|
||||
"Actually create the GUI Choice control for 2-phase creation", "");
|
||||
|
||||
DocDeclStr(
|
||||
int , GetCurrentSelection() const,
|
||||
"Unlike `GetSelection` which only returns the accepted selection value,
|
||||
i.e. the selection in the control once the user closes the dropdown
|
||||
list, this function returns the current selection. That is, while the
|
||||
dropdown list is shown, it returns the currently selected item in
|
||||
it. When it is not shown, its result is the same as for the other
|
||||
function.", "");
|
||||
|
||||
|
||||
static wxVisualAttributes
|
||||
|
||||
@@ -142,7 +142,8 @@ normal clipboard, if primary is True.", "");
|
||||
self._instance = None
|
||||
def _checkInstance(self):
|
||||
if self._instance is None:
|
||||
self._instance = self._initfunc(*self._args, **self._kwargs)
|
||||
if wx.GetApp():
|
||||
self._instance = self._initfunc(*self._args, **self._kwargs)
|
||||
def __getattr__(self, name):
|
||||
self._checkInstance()
|
||||
return getattr(self._instance, name)
|
||||
|
||||
@@ -166,6 +166,15 @@ the combobox text field.", "",
|
||||
GetMark);
|
||||
#endif
|
||||
|
||||
DocDeclStr(
|
||||
int , GetCurrentSelection() const,
|
||||
"Unlike `GetSelection` which only returns the accepted selection value,
|
||||
i.e. the selection in the control once the user closes the dropdown
|
||||
list, this function returns the current selection. That is, while the
|
||||
dropdown list is shown, it returns the currently selected item in
|
||||
it. When it is not shown, its result is the same as for the other
|
||||
function.", "");
|
||||
|
||||
DocDeclStr(
|
||||
bool , SetStringSelection(const wxString& string),
|
||||
"Select the item with the specifed string", "");
|
||||
|
||||
@@ -122,6 +122,33 @@ PyObject* wxPyMakeSwigPtr(void* ptr, const wxChar* className) {
|
||||
}
|
||||
|
||||
|
||||
// Python's PyInstance_Check does not return True for instances of new-style
|
||||
// classes. This should get close enough for both new and old classes but I
|
||||
// should re-evaluate the need for doing instance checks...
|
||||
bool wxPyInstance_Check(PyObject* obj) {
|
||||
return PyObject_HasAttrString(obj, "__class__") != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This one checks if the object is an instance of a SWIG proxy class (it has
|
||||
// a .this attribute, and the .this attribute is a PySwigObject.)
|
||||
bool wxPySwigInstance_Check(PyObject* obj) {
|
||||
static PyObject* this_str = NULL;
|
||||
if (this_str == NULL)
|
||||
this_str = PyString_FromString("this");
|
||||
|
||||
PyObject* this_attr = PyObject_GetAttr(obj, this_str);
|
||||
if (this_attr) {
|
||||
bool retval = (PySwigObject_Check(this_attr) != 0);
|
||||
Py_DECREF(this_attr);
|
||||
return retval;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Export a C API in a struct. Other modules will be able to load this from
|
||||
|
||||
@@ -248,8 +248,7 @@ in the given direction.", "");
|
||||
for (size_t i=0; i<count; i++) {
|
||||
wxDataFormat* format = new wxDataFormat(formats[i]);
|
||||
PyObject* obj = wxPyConstructObject((void*)format, wxT("wxDataFormat"), true);
|
||||
PyList_Append(list, obj);
|
||||
Py_DECREF(obj);
|
||||
PyList_SET_ITEM(list, i, obj); // PyList_SET_ITEM steals a reference
|
||||
}
|
||||
wxPyEndBlockThreads(blocked);
|
||||
delete [] formats;
|
||||
|
||||
@@ -586,10 +586,22 @@ public:
|
||||
wxDateTime ToTimezone(const wxDateTime::TimeZone& tz, bool noDST = false);
|
||||
wxDateTime& MakeTimezone(const wxDateTime::TimeZone& tz, bool noDST = false);
|
||||
|
||||
// transform to GMT/UTC
|
||||
wxDateTime ToGMT(bool noDST = false);
|
||||
// interpret current value as being in another timezone and transform
|
||||
// it to local one
|
||||
wxDateTime FromTimezone(const wxDateTime::TimeZone& tz, bool noDST = false) const;
|
||||
wxDateTime& MakeFromTimezone(const wxDateTime::TimeZone& tz, bool noDST = false);
|
||||
|
||||
// transform to/from GMT/UTC
|
||||
wxDateTime ToUTC(bool noDST = false) const;
|
||||
wxDateTime& MakeUTC(bool noDST = false);
|
||||
|
||||
wxDateTime ToGMT(bool noDST = false) const;
|
||||
wxDateTime& MakeGMT(bool noDST = false);
|
||||
|
||||
wxDateTime FromUTC(bool noDST = false) const;
|
||||
wxDateTime& MakeFromUTC(bool noDST = false);
|
||||
|
||||
|
||||
// is daylight savings time in effect at this moment according to the
|
||||
// rules of the specified country?
|
||||
//
|
||||
|
||||
@@ -497,6 +497,7 @@ enum {
|
||||
wxSIZE_AUTO,
|
||||
wxSIZE_USE_EXISTING,
|
||||
wxSIZE_ALLOW_MINUS_ONE,
|
||||
wxSIZE_FORCE,
|
||||
wxPORTRAIT,
|
||||
wxLANDSCAPE,
|
||||
wxPRINT_QUALITY_HIGH,
|
||||
@@ -506,6 +507,7 @@ enum {
|
||||
|
||||
wxID_ANY,
|
||||
wxID_SEPARATOR,
|
||||
wxID_NONE,
|
||||
|
||||
wxID_LOWEST,
|
||||
wxID_OPEN,
|
||||
|
||||
@@ -99,8 +99,16 @@ wxEventType wxNewEventType();
|
||||
%constant wxEventType wxEVT_NAVIGATION_KEY;
|
||||
%constant wxEventType wxEVT_KEY_DOWN;
|
||||
%constant wxEventType wxEVT_KEY_UP;
|
||||
|
||||
%{
|
||||
#if ! wxUSE_HOTKEY
|
||||
#define wxEVT_HOTKEY -9999
|
||||
#endif
|
||||
%}
|
||||
|
||||
%constant wxEventType wxEVT_HOTKEY;
|
||||
|
||||
|
||||
|
||||
// Set cursor event
|
||||
%constant wxEventType wxEVT_SET_CURSOR;
|
||||
|
||||
@@ -2234,8 +2242,15 @@ public:
|
||||
|
||||
|
||||
DocStr(wxWindowDestroyEvent,
|
||||
"The EVT_WINDOW_DESTROY event is sent right before the window is
|
||||
destroyed.", "");
|
||||
"The EVT_WINDOW_DESTROY event is sent from the `wx.Window` destructor
|
||||
when the GUI window is destroyed.
|
||||
|
||||
When a class derived from `wx.Window` is destroyed its destructor will
|
||||
have already run by the time this event is sent. Therefore this event
|
||||
will not usually be received at all by the window itself. Since it is
|
||||
received after the destructor has run, an object should not try to
|
||||
handle its own wx.WindowDestroyEvent, but it can be used to get
|
||||
notification of the destruction of another window.", "");
|
||||
class wxWindowDestroyEvent : public wxCommandEvent
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -345,7 +345,7 @@ public:
|
||||
|
||||
// return instance of the wxFontMapper singleton
|
||||
static wxFontMapper *Get();
|
||||
// set the sigleton to 'mapper' instance and return previous one
|
||||
// set the singleton to 'mapper' instance and return previous one
|
||||
static wxFontMapper *Set(wxFontMapper *mapper);
|
||||
|
||||
|
||||
@@ -364,10 +364,13 @@ public:
|
||||
// get the n-th supported encoding
|
||||
static wxFontEncoding GetEncoding(size_t n);
|
||||
|
||||
// return internal string identifier for the encoding (see also
|
||||
// GetEncodingDescription())
|
||||
// return canonical name of this encoding (this is a short string,
|
||||
// GetEncodingDescription() returns a longer one)
|
||||
static wxString GetEncodingName(wxFontEncoding encoding);
|
||||
|
||||
// // return a list of all names of this encoding (see GetEncodingName)
|
||||
// static const wxChar** GetAllEncodingNames(wxFontEncoding encoding);
|
||||
|
||||
// return user-readable string describing the given encoding
|
||||
//
|
||||
// NB: hard-coded now, but might change later (read it from config?)
|
||||
@@ -380,9 +383,6 @@ public:
|
||||
static wxFontEncoding GetEncodingFromName(const wxString& name);
|
||||
|
||||
|
||||
// set the config object to use (may be NULL to use default)
|
||||
void SetConfig(wxConfigBase *config);
|
||||
|
||||
// set the root config path to use (should be an absolute path)
|
||||
void SetConfigPath(const wxString& prefix);
|
||||
|
||||
|
||||
@@ -214,7 +214,9 @@ long wxGetNumberFromUser(const wxString& message,
|
||||
long min = 0, long max = 100,
|
||||
wxWindow *parent = NULL,
|
||||
const wxPoint& pos = wxDefaultPosition);
|
||||
%pythoncode { GetNumberFromUser = wx._deprecated(GetNumberFromUser) }
|
||||
#endif
|
||||
|
||||
// GDI Functions
|
||||
|
||||
MustHaveApp(wxColourDisplay);
|
||||
|
||||
@@ -59,6 +59,43 @@ public:
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
DocStr(wxPyImageHandler,
|
||||
"This is the base class for implementing image file loading/saving, and
|
||||
image creation from data, all written in Python. To create a custom
|
||||
image handler derive a new class from wx.PyImageHandler and provide
|
||||
the following methods::
|
||||
|
||||
def DoCanRead(self, stream) --> bool
|
||||
'''Check if this handler can read the image on the stream'''
|
||||
|
||||
def LoadFile(self, image, stream, verbose, index) --> bool
|
||||
'''Load image data from the stream and load it into image.'''
|
||||
|
||||
def SaveFile(self, image, stream, verbose) --> bool
|
||||
'''Save the iamge data in image to the stream using
|
||||
this handler's image file format.'''
|
||||
|
||||
def GetImageCount(self, stream) --> int
|
||||
'''If this image format can hold more than one image,
|
||||
how many does the image on the stream have?'''
|
||||
|
||||
To activate your handler create an instance of it and pass it to
|
||||
`wx.Image_AddHandler`. Be sure to call `SetName`, `SetType`, and
|
||||
`SetExtension` from your constructor.
|
||||
", "");
|
||||
|
||||
class wxPyImageHandler: public wxImageHandler {
|
||||
public:
|
||||
%pythonAppend wxPyImageHandler() "self._SetSelf(self)"
|
||||
wxPyImageHandler();
|
||||
void _SetSelf(PyObject *self);
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class wxImageHistogram /* : public wxImageHistogramBase */
|
||||
{
|
||||
public:
|
||||
@@ -155,25 +192,41 @@ Unlike RGB data, not all images have an alpha channel and before using
|
||||
with `HasAlpha`. Note that currently only images loaded from PNG files
|
||||
with transparency information will have an alpha channel.", "");
|
||||
|
||||
|
||||
%{
|
||||
// Pull the nested class out to the top level for SWIG's sake
|
||||
#define wxImage_RGBValue wxImage::RGBValue
|
||||
#define wxImage_HSVValue wxImage::HSVValue
|
||||
%}
|
||||
|
||||
|
||||
DocStr(wxImage_RGBValue,
|
||||
"An object that contains values for red, green and blue which represent
|
||||
the value of a color. It is used by `wx.Image.HSVtoRGB` and
|
||||
`wx.Image.RGBtoHSV`, which converts between HSV color space and RGB
|
||||
color space.", "");
|
||||
class wxImage_RGBValue
|
||||
{
|
||||
public:
|
||||
wxImage_RGBValue(byte r=0, byte g=0, byte b=0);
|
||||
DocCtorStr(
|
||||
wxImage_RGBValue(byte r=0, byte g=0, byte b=0),
|
||||
"Constructor.", "");
|
||||
byte red;
|
||||
byte green;
|
||||
byte blue;
|
||||
};
|
||||
|
||||
|
||||
|
||||
DocStr(wxImage_HSVValue,
|
||||
"An object that contains values for hue, saturation and value which
|
||||
represent the value of a color. It is used by `wx.Image.HSVtoRGB` and
|
||||
`wx.Image.RGBtoHSV`, which +converts between HSV color space and RGB
|
||||
color space.", "");
|
||||
class wxImage_HSVValue
|
||||
{
|
||||
public:
|
||||
wxImage_HSVValue(double h=0.0, double s=0.0, double v=0.0);
|
||||
DocCtorStr(
|
||||
wxImage_HSVValue(double h=0.0, double s=0.0, double v=0.0),
|
||||
"Constructor.", "");
|
||||
double hue;
|
||||
double saturation;
|
||||
double value;
|
||||
@@ -919,8 +972,14 @@ MustHaveApp(ConvertToMonoBitmap);
|
||||
"Rotates the hue of each pixel of the image. Hue is a double in the
|
||||
range -1.0..1.0 where -1.0 is -360 degrees and 1.0 is 360 degrees", "");
|
||||
|
||||
static wxImage_HSVValue RGBtoHSV(wxImage_RGBValue rgb);
|
||||
static wxImage_RGBValue HSVtoRGB(wxImage_HSVValue hsv);
|
||||
DocDeclStr(
|
||||
static wxImage_HSVValue , RGBtoHSV(wxImage_RGBValue rgb),
|
||||
"Converts a color in RGB color space to HSV color space.", "");
|
||||
|
||||
DocDeclStr(
|
||||
static wxImage_RGBValue , HSVtoRGB(wxImage_HSVValue hsv),
|
||||
"Converts a color in HSV color space to RGB color space.", "");
|
||||
|
||||
|
||||
%pythoncode { def __nonzero__(self): return self.Ok() }
|
||||
};
|
||||
|
||||
@@ -693,6 +693,9 @@ details in the second return value (see wx.LIST_HITTEST flags.)", "");
|
||||
void SetItemBackgroundColour( long item, const wxColour &col);
|
||||
wxColour GetItemBackgroundColour( long item ) const;
|
||||
|
||||
// Font of an item.
|
||||
void SetItemFont( long item, const wxFont &f);
|
||||
wxFont GetItemFont( long item ) const;
|
||||
|
||||
%pythoncode {
|
||||
%#
|
||||
|
||||
@@ -318,14 +318,14 @@ static wxPySizerItemInfo wxPySizerItemTypeHelper(PyObject* item, bool checkSize,
|
||||
if ( !(info.window || info.sizer || (checkSize && info.gotSize) || (checkIdx && info.gotPos)) ) {
|
||||
// no expected type, figure out what kind of error message to generate
|
||||
if ( !checkSize && !checkIdx )
|
||||
PyErr_SetString(PyExc_TypeError, "wxWindow or wxSizer expected for item");
|
||||
PyErr_SetString(PyExc_TypeError, "wx.Window or wx.Sizer expected for item");
|
||||
else if ( checkSize && !checkIdx )
|
||||
PyErr_SetString(PyExc_TypeError, "wxWindow, wxSizer, wxSize, or (w,h) expected for item");
|
||||
PyErr_SetString(PyExc_TypeError, "wx.Window, wx.Sizer, wx.Size, or (w,h) expected for item");
|
||||
else if ( !checkSize && checkIdx)
|
||||
PyErr_SetString(PyExc_TypeError, "wxWindow, wxSizer or int (position) expected for item");
|
||||
PyErr_SetString(PyExc_TypeError, "wx.Window, wx.Sizer or int (position) expected for item");
|
||||
else
|
||||
// can this one happen?
|
||||
PyErr_SetString(PyExc_TypeError, "wxWindow, wxSizer, wxSize, or (w,h) or int (position) expected for item");
|
||||
PyErr_SetString(PyExc_TypeError, "wx.Window, wx.Sizer, wx.Size, or (w,h) or int (position) expected for item");
|
||||
}
|
||||
|
||||
return info;
|
||||
|
||||
@@ -114,6 +114,14 @@ public:
|
||||
long style = 0,
|
||||
const wxString& name = wxPyStaticTextNameStr);
|
||||
|
||||
DocDeclStr(
|
||||
void , Wrap(int width),
|
||||
"This functions wraps the control's label so that each of its lines
|
||||
becomes at most ``width`` pixels wide if possible (the lines are
|
||||
broken at words boundaries so it might not be the case if words are
|
||||
too long). If ``width`` is negative, no wrapping is done.", "");
|
||||
|
||||
|
||||
static wxVisualAttributes
|
||||
GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
|
||||
};
|
||||
|
||||
@@ -436,13 +436,13 @@ window's *best size* values. Also set's the minsize for use with sizers.", "");
|
||||
|
||||
DocDeclStr(
|
||||
virtual void , Raise(),
|
||||
"Raises the window to the top of the window hierarchy if it is a
|
||||
managed window (dialog or frame).", "");
|
||||
"Raises the window to the top of the window hierarchy. In current
|
||||
version of wxWidgets this works both for manage and child windows.", "");
|
||||
|
||||
DocDeclStr(
|
||||
virtual void , Lower(),
|
||||
"Lowers the window to the bottom of the window hierarchy if it is a
|
||||
managed window (dialog or frame).", "");
|
||||
"Lowers the window to the bottom of the window hierarchy. In current
|
||||
version of wxWidgets this works both for manage and child windows.", "");
|
||||
|
||||
|
||||
|
||||
@@ -2060,7 +2060,8 @@ wxWindow* wxFindWindowByLabel( const wxString& label,
|
||||
WXHWND hWnd = (WXHWND)_hWnd;
|
||||
long id = wxGetWindowId(hWnd);
|
||||
wxWindow* win = new wxWindow;
|
||||
parent->AddChild(win);
|
||||
if (parent)
|
||||
parent->AddChild(win);
|
||||
win->SetEventHandler(win);
|
||||
win->SetHWND(hWnd);
|
||||
win->SetId(id);
|
||||
|
||||
@@ -91,6 +91,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Unload resource from the given XML file (wildcards not allowed)
|
||||
bool Unload(const wxString& filename);
|
||||
|
||||
// Initialize handlers for all supported controls/windows.
|
||||
void InitAllHandlers();
|
||||
|
||||
|
||||
@@ -701,21 +701,6 @@ PyObject* __wxPySetDictionary(PyObject* /* self */, PyObject* args)
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Python's PyInstance_Check does not return True for instances of new-style
|
||||
// classes. This should get close enough for both new and old classes but I
|
||||
// should re-evaluate the need for doing instance checks...
|
||||
bool wxPyInstance_Check(PyObject* obj) {
|
||||
return PyObject_HasAttrString(obj, "__class__") != 0;
|
||||
}
|
||||
|
||||
|
||||
// This one checks if the object is an instance of a SWIG proxy class (it has
|
||||
// a .this attribute)
|
||||
bool wxPySwigInstance_Check(PyObject* obj) {
|
||||
return PyObject_HasAttrString(obj, "this") != 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -2725,6 +2710,145 @@ PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr) {
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// wxPyImageHandler methods
|
||||
//
|
||||
// TODO: Switch these to use wxPython's standard macros and helper classes
|
||||
// for calling callbacks.
|
||||
|
||||
PyObject* wxPyImageHandler::m_DoCanRead_Name = NULL;
|
||||
PyObject* wxPyImageHandler::m_GetImageCount_Name = NULL;
|
||||
PyObject* wxPyImageHandler::m_LoadFile_Name = NULL;
|
||||
PyObject* wxPyImageHandler::m_SaveFile_Name = NULL;
|
||||
|
||||
PyObject* wxPyImageHandler::py_InputStream(wxInputStream* stream) {
|
||||
return wxPyConstructObject(new wxPyInputStream(stream),
|
||||
wxT("wxPyInputStream"), 0);
|
||||
}
|
||||
|
||||
PyObject* wxPyImageHandler::py_Image(wxImage* image) {
|
||||
return wxPyConstructObject(image, wxT("wxImage"), 0);
|
||||
}
|
||||
|
||||
PyObject* wxPyImageHandler::py_OutputStream(wxOutputStream* stream) {
|
||||
return wxPyConstructObject(stream, wxT("wxOutputStream"), 0);
|
||||
}
|
||||
|
||||
wxPyImageHandler::wxPyImageHandler():
|
||||
m_self(NULL)
|
||||
{
|
||||
if (!m_DoCanRead_Name) {
|
||||
m_DoCanRead_Name = PyString_FromString("DoCanRead");
|
||||
m_GetImageCount_Name = PyString_FromString("GetImageCount");
|
||||
m_LoadFile_Name = PyString_FromString("LoadFile");
|
||||
m_SaveFile_Name = PyString_FromString("SaveFile");
|
||||
}
|
||||
}
|
||||
|
||||
wxPyImageHandler::~wxPyImageHandler() {
|
||||
if (m_self) {
|
||||
Py_DECREF(m_self);
|
||||
m_self = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void wxPyImageHandler::_SetSelf(PyObject *self) {
|
||||
// should check here for isinstance(PyImageHandler) ??
|
||||
m_self = self;
|
||||
Py_INCREF(m_self);
|
||||
}
|
||||
|
||||
bool wxPyImageHandler::DoCanRead(wxInputStream& stream) {
|
||||
// check if our object has this method
|
||||
wxPyBlock_t blocked = wxPyBeginBlockThreads();
|
||||
if (!m_self || !PyObject_HasAttr(m_self, m_DoCanRead_Name)) {
|
||||
wxPyEndBlockThreads(blocked);
|
||||
return false;
|
||||
}
|
||||
|
||||
PyObject* res = PyObject_CallMethodObjArgs(m_self, m_DoCanRead_Name,
|
||||
py_InputStream(&stream), NULL);
|
||||
bool retval = false;
|
||||
if (res) {
|
||||
retval = PyInt_AsLong(res);
|
||||
Py_DECREF(res);
|
||||
PyErr_Clear();
|
||||
}
|
||||
else
|
||||
PyErr_Print();
|
||||
wxPyEndBlockThreads(blocked);
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool wxPyImageHandler::LoadFile( wxImage* image, wxInputStream& stream,
|
||||
bool verbose, int index ) {
|
||||
// check if our object has this method
|
||||
wxPyBlock_t blocked = wxPyBeginBlockThreads();
|
||||
if (!m_self || !PyObject_HasAttr(m_self, m_LoadFile_Name)) {
|
||||
wxPyEndBlockThreads(blocked);
|
||||
return false;
|
||||
}
|
||||
PyObject* res = PyObject_CallMethodObjArgs(m_self, m_LoadFile_Name,
|
||||
py_Image(image),
|
||||
py_InputStream(&stream),
|
||||
PyInt_FromLong(verbose),
|
||||
PyInt_FromLong(index),
|
||||
NULL);
|
||||
bool retval = false;
|
||||
if (res) {
|
||||
retval = PyInt_AsLong(res);
|
||||
Py_DECREF(res);
|
||||
PyErr_Clear();
|
||||
} else
|
||||
PyErr_Print();
|
||||
wxPyEndBlockThreads(blocked);
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool wxPyImageHandler::SaveFile( wxImage* image, wxOutputStream& stream,
|
||||
bool verbose ) {
|
||||
wxPyBlock_t blocked = wxPyBeginBlockThreads();
|
||||
if (!m_self || !PyObject_HasAttr(m_self, m_SaveFile_Name)) {
|
||||
wxPyEndBlockThreads(blocked);
|
||||
return false;
|
||||
}
|
||||
PyObject* res = PyObject_CallMethodObjArgs(m_self, m_SaveFile_Name,
|
||||
py_Image(image),
|
||||
py_OutputStream(&stream),
|
||||
PyInt_FromLong(verbose),
|
||||
NULL);
|
||||
bool retval = false;
|
||||
if(res) {
|
||||
retval=PyInt_AsLong(res);
|
||||
Py_DECREF(res);
|
||||
PyErr_Clear();
|
||||
} else
|
||||
PyErr_Print();
|
||||
wxPyEndBlockThreads(blocked);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int wxPyImageHandler::GetImageCount( wxInputStream& stream ) {
|
||||
wxPyBlock_t blocked = wxPyBeginBlockThreads();
|
||||
if (!m_self || !PyObject_HasAttr(m_self, m_GetImageCount_Name)) {
|
||||
wxPyEndBlockThreads(blocked);
|
||||
return 1;
|
||||
}
|
||||
PyObject *res=PyObject_CallMethodObjArgs(m_self, m_GetImageCount_Name,
|
||||
py_InputStream(&stream),
|
||||
NULL);
|
||||
int retval = 1;
|
||||
if(res) {
|
||||
retval=PyInt_AsLong(res);
|
||||
Py_DECREF(res);
|
||||
PyErr_Clear();
|
||||
} else
|
||||
PyErr_Print();
|
||||
wxPyEndBlockThreads(blocked);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -55,7 +55,15 @@ enum wxMediaState
|
||||
wxMEDIASTATE_PLAYING=0
|
||||
};
|
||||
|
||||
enum wxMediaCtrlPlayerControls
|
||||
{
|
||||
wxMEDIACTRLPLAYERCONTROLS_NONE,
|
||||
wxMEDIACTRLPLAYERCONTROLS_STEP,
|
||||
wxMEDIACTRLPLAYERCONTROLS_VOLUME,
|
||||
wxMEDIACTRLPLAYERCONTROLS_DEFAULT
|
||||
};
|
||||
|
||||
|
||||
class wxMediaEvent : public wxNotifyEvent
|
||||
{
|
||||
public:
|
||||
@@ -89,9 +97,6 @@ public:
|
||||
bool Pause() { return false; }
|
||||
bool Stop() { return false; }
|
||||
|
||||
bool Load(const wxString& fileName) { return false; }
|
||||
bool Load(const wxURI& location) { return false; }
|
||||
|
||||
wxMediaState GetState() { return wxMEDIASTATE_STOPPED; }
|
||||
|
||||
double GetPlaybackRate() { return 0.0; }
|
||||
@@ -105,6 +110,14 @@ public:
|
||||
|
||||
double GetVolume() { return 0.0; }
|
||||
bool SetVolume(double dVolume) { return false; }
|
||||
|
||||
bool ShowPlayerControls(
|
||||
wxMediaCtrlPlayerControls flags = wxMEDIACTRLPLAYERCONTROLS_DEFAULT)
|
||||
{ return false; }
|
||||
|
||||
bool Load(const wxString& fileName) { return false; }
|
||||
bool LoadURI(const wxString& fileName) { return false; }
|
||||
bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy) { return false; }
|
||||
};
|
||||
|
||||
const wxEventType wxEVT_MEDIA_FINISHED = 0;
|
||||
@@ -180,16 +193,6 @@ public:
|
||||
bool Pause();
|
||||
bool Stop();
|
||||
|
||||
double GetVolume(); //DirectShow only
|
||||
bool SetVolume(double dVolume); //DirectShow only
|
||||
|
||||
bool Load(const wxString& fileName);
|
||||
%extend {
|
||||
bool LoadFromURI(const wxString& location) {
|
||||
return self->Load(wxURI(location));
|
||||
}
|
||||
}
|
||||
|
||||
wxMediaState GetState();
|
||||
|
||||
double GetPlaybackRate();
|
||||
@@ -198,6 +201,17 @@ public:
|
||||
wxFileOffset Seek(wxFileOffset where, wxSeekMode mode = wxFromStart);
|
||||
wxFileOffset Tell();
|
||||
wxFileOffset Length();
|
||||
|
||||
double GetVolume();
|
||||
bool SetVolume(double dVolume);
|
||||
|
||||
bool ShowPlayerControls(
|
||||
wxMediaCtrlPlayerControls flags = wxMEDIACTRLPLAYERCONTROLS_DEFAULT);
|
||||
|
||||
bool Load(const wxString& fileName);
|
||||
bool LoadURI(const wxString& fileName);
|
||||
bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy);
|
||||
%pythoncode { LoadFromURI = LoadURI }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user