This commit was manufactured by cvs2svn to create tag 'wxPy_2_3_3_1'.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/tags/wxPy_2_3_3_1@17271 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Bryan Petty
2002-09-19 06:10:53 +00:00
parent bf4a027ddb
commit fe0c95d0ba
103 changed files with 6418 additions and 11559 deletions

View File

@@ -1,11 +1,11 @@
Building wxPython on Mac OS X
-----------------------------
NOTE: OS X support is HIGHLY EXPERIMENTAL at this time. Most things
are working now, but a few still don't. I know about most of
them and am addressing them as I have time. If you have any
ideas about a fix for the stuff that's still broken then
please persue them and send the fixes to me.
NOTE: OS X support is EXPERIMENTAL at this time. Most things are
working now, but a few still don't. I know about most of them
and am addressing them as I have time. If you have any ideas
about a fix for the stuff that's still broken then please
persue them and send the fixes to me.
These are the steps I have used for building wxPython on Mac OS X 10.1
@@ -14,13 +14,14 @@ that you know your way around a command line and that you know how to
get things from various CVS repositories as needed.
1. Python 2.2 is required. There is a disk image with an installer
package in the wxPython Sourceforge download area, in this group:
1. "MachoPython" 2.2 is required. There is a disk image with an
installer package in the wxPython Sourceforge download area, in
this group:
http://sourceforge.net/project/showfiles.php?group_id=10718&release_id=84730
If, for some reason you need to build your own Python, get the
source from www.python.org and follow theinstructions in the
source from www.python.org and follow the instructions in the
Mac/OSX/README file to build and install Python.app and the
Python.framework.
@@ -33,8 +34,8 @@ get things from various CVS repositories as needed.
sudo ln -s python2.2 python
Also, if you create a /usr/local/bin/pythonw script like the
following then you can run Python GUI apps (like wxPython) directly
from the command line:
following then you can run Python GUI apps (like wxPython apps)
directly from the command line:
#!/bin/sh
exec /Applications/Python.app/Contents/MacOS/python $@
@@ -45,13 +46,15 @@ get things from various CVS repositories as needed.
If you would like to make a MachoPython installer from what you
built then you may want to look at the scripts I use to do it
located in wxPython/distrib/mac/buildPython.
located in wxPython/distrib/mac/buildPython in CVS.
One last thing, make sure that /usr/local/bin is in your PATH
environment variable.
2. In a wxWindows CVS tree make a build directory.
2. In a wxWindows CVS tree make a build directory. (You can also use
a CVS snapshot located in http://wxwindows.org/snapshots/ or the
released wxPythonSrc-*.tr.gz archive.)
cd ~/proj/wxWindows # or wherever you put it
mkdir build

View File

@@ -249,7 +249,9 @@ C. Change to the root wxPython directory and look at the setup.py
and shadow python files.
IN_CVS_TREE If you are using the CVS version of the
wxWindows and wxPython sources then you will
wxWindows and wxPython sources, or a combined
source archive from the CVS snapshots or the
distributed wxPythonSrc-*.tar.gz then you will
need to set this flag to non-zero. This is
needed because some source files from the
wxWindows tree are copied to be under the
@@ -257,9 +259,6 @@ C. Change to the root wxPython directory and look at the setup.py
With this flag set then setup.py will
automatically keep these copied sources up to
date if the original version is ever updated.
If you are using the tar.gz version of the
Python sources then these copied sources are
already present in your source tree.
D. To build and install wxPython you simply need to execute the

View File

@@ -246,18 +246,17 @@ B. Change to the root wxPython directory and look at the setup.py
will be executed to regenerate the wrapper C++
and shadow python files.
IN_CVS_TREE If you are using the CVS version of the
wxWindows and wxPython sources then you will
need to set this flag to non-zero. This is
needed because some source files from the
wxWindows tree are copied to be under the
wxPython tree in order to keep Distutils happy.
With this flag set then setup.py will
automatically keep these copied sources up to
date if the original version is ever updated.
If you are using the tar.gz version of the
Python sources then these copied sources are
already present in your source tree.
IN_CVS_TREE If you are using the CVS version of the
wxWindows and wxPython sources, or a combined
source archive from the CVS snapshots or the
distributed wxPythonSrc-*.tar.gz then you will
need to set this flag to non-zero. This is
needed because some source files from the
wxWindows tree are copied to be under the
wxPython tree in order to keep Distutils happy.
With this flag set then setup.py will
automatically keep these copied sources up to
date if the original version is ever updated.
C. To build and install wxPython you simply need to execute the

View File

@@ -174,6 +174,9 @@ Added wxXmlResourceHandler which allows you to create custom handlers
for nonstandard class types in XRC resources. See the demo for an
example.
Added wxPython.lib.mixins.rubberband module from Robb Shecter.
Added wxTimeCtrl from Will Sadkin.

View File

@@ -3,5 +3,5 @@
wx.wxStyledTextEventPtr = wxStyledTextEventPtr
wx.wxStyledTextCtrlPtr = wxStyledTextCtrlPtr
wxSTC_CARET_CENTER = wxSTC_CARET_STRICT
# This constant no longer exists in Scintilla, but I'll put it here for a while to avoid disrupting user code...
wxSTC_CARET_CENTER = 0

View File

@@ -1819,5 +1819,5 @@ wxEVT_STC_ZOOM = stc_c.wxEVT_STC_ZOOM
wx.wxStyledTextEventPtr = wxStyledTextEventPtr
wx.wxStyledTextCtrlPtr = wxStyledTextCtrlPtr
wxSTC_CARET_CENTER = wxSTC_CARET_STRICT
# This constant no longer exists in Scintilla, but I'll put it here for a while to avoid disrupting user code...
wxSTC_CARET_CENTER = 0

View File

@@ -1819,5 +1819,5 @@ wxEVT_STC_ZOOM = stc_c.wxEVT_STC_ZOOM
wx.wxStyledTextEventPtr = wxStyledTextEventPtr
wx.wxStyledTextCtrlPtr = wxStyledTextCtrlPtr
wxSTC_CARET_CENTER = wxSTC_CARET_STRICT
# This constant no longer exists in Scintilla, but I'll put it here for a while to avoid disrupting user code...
wxSTC_CARET_CENTER = 0

View File

@@ -1819,5 +1819,5 @@ wxEVT_STC_ZOOM = stc_c.wxEVT_STC_ZOOM
wx.wxStyledTextEventPtr = wxStyledTextEventPtr
wx.wxStyledTextCtrlPtr = wxStyledTextCtrlPtr
wxSTC_CARET_CENTER = wxSTC_CARET_STRICT
# This constant no longer exists in Scintilla, but I'll put it here for a while to avoid disrupting user code...
wxSTC_CARET_CENTER = 0

View File

@@ -45,7 +45,10 @@ class CustomDataTable(wxPyGridTableBase):
return len(self.data[0])
def IsEmptyCell(self, row, col):
return not self.data[row][col]
try:
return not self.data[row][col]
except IndexError:
return true
# Get/Set values in the table. The Python version of these
# methods can handle any data-type, (as long as the Editor and
@@ -138,8 +141,22 @@ class CustTableGrid(wxGrid):
class TestFrame(wxFrame):
def __init__(self, parent, log):
wxFrame.__init__(self, parent, -1, "Custom Table, data driven Grid Demo", size=(640,480))
grid = CustTableGrid(self, log)
p = wxPanel(self, -1, style=0)
grid = CustTableGrid(p, log)
b = wxButton(p, -1, "Another Control...")
b.SetDefault()
EVT_BUTTON(self, b.GetId(), self.OnButton)
EVT_SET_FOCUS(b, self.OnButtonFocus)
bs = wxBoxSizer(wxVERTICAL)
bs.Add(grid, 1, wxGROW|wxALL, 5)
bs.Add(b)
p.SetSizer(bs)
def OnButton(self, evt):
print "button selected"
def OnButtonFocus(self, evt):
print "button focus"
#---------------------------------------------------------------------------

View File

@@ -37,6 +37,7 @@ _treeList = [
'wxKeyEvents',
'wxWizard',
'wxXmlResourceHandler',
'wxTimeCtrl',
]),
# managed windows == things with a caption you can close
@@ -129,6 +130,7 @@ _treeList = [
'wxRightTextCtrl',
'wxStyledTextCtrl_1',
'wxStyledTextCtrl_2',
'wxTimeCtrl',
]),
# How to lay out the controls in a frame/dialog

View File

@@ -223,7 +223,8 @@ class TestListCtrlPanel(wxPanel, wxColumnSorterMixin):
def OnItemActivated(self, event):
self.currentItem = event.m_itemIndex
self.log.WriteText("OnItemActivated: %s\n" % self.list.GetItemText(self.currentItem))
self.log.WriteText("OnItemActivated: %s\nTopItem: %s" %
(self.list.GetItemText(self.currentItem), self.list.GetTopItem()))
def OnItemDelete(self, event):
self.log.WriteText("OnItemDelete\n")

View File

@@ -45,7 +45,8 @@ class TestVirtualList(wxListCtrl):
def OnItemActivated(self, event):
self.currentItem = event.m_itemIndex
self.log.WriteText("OnItemActivated: %s\n" % self.GetItemText(self.currentItem))
self.log.WriteText("OnItemActivated: %s\nTopItem: %s\n" %
(self.GetItemText(self.currentItem), self.GetTopItem()))
def getColumnText(self, index, col):
item = self.GetItem(index, col)

View File

@@ -149,6 +149,7 @@ class MyCanvas(wxScrolledWindow):
def OnLeftButtonEvent(self, event):
if event.LeftDown():
self.SetFocus()
self.SetXY(event)
self.curLine = []
self.CaptureMouse()

View File

@@ -22,6 +22,7 @@ class TestPanel(wxPanel):
l1 = wxStaticText(self, -1, "wxTextCtrl")
t1 = wxTextCtrl(self, 10, "Test it out and see", size=(125, -1))
t1.SetInsertionPoint(0)
self.tc1 = t1
EVT_TEXT(self, 10, self.EvtText)
EVT_CHAR(t1, self.EvtChar)
EVT_SET_FOCUS(t1, self.OnSetFocus)
@@ -43,6 +44,8 @@ class TestPanel(wxPanel):
EVT_BUTTON(self, b.GetId(), self.OnTestReplace)
b2 = wxButton(self, -1, "Test GetSelection")
EVT_BUTTON(self, b2.GetId(), self.OnTestGetSelection)
b3 = wxButton(self, -1, "Test WriteText")
EVT_BUTTON(self, b3.GetId(), self.OnTestWriteText)
self.tc = t3
l4 = wxStaticText(self, -1, "Rich Text")
@@ -58,6 +61,7 @@ class TestPanel(wxPanel):
bsizer = wxBoxSizer(wxVERTICAL)
bsizer.Add(b, 0, wxGROW)
bsizer.Add(b2, 0, wxGROW)
bsizer.Add(b3, 0, wxGROW)
sizer = wxFlexGridSizer(cols=3, hgap=6, vgap=6)
sizer.AddMany([ l1, t1, (0,0),
@@ -84,6 +88,9 @@ class TestPanel(wxPanel):
self.tc.Replace(5, 9, "IS A")
#self.tc.Remove(5, 9)
def OnTestWriteText(self, evt):
self.tc.WriteText("TEXT")
def OnTestGetSelection(self, evt):
start, end = self.tc.GetSelection()
text = self.tc.GetValue()

117
wxPython/demo/wxTimeCtrl.py Normal file
View File

@@ -0,0 +1,117 @@
from wxPython.wx import *
from wxPython.lib.timectrl import *
import string
#----------------------------------------------------------------------
class TestPanel(wxPanel):
def __init__(self, parent, log):
wxPanel.__init__(self, parent, -1)
self.log = log
panel = wxPanel(self, -1)
grid = wxFlexGridSizer( 0, 2, 20, 0 )
text1 = wxStaticText( panel, 10, "A 12-hour format wxTimeCtrl:", wxDefaultPosition, wxDefaultSize, 0 )
grid.AddWindow( text1, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 )
hsizer1 = wxBoxSizer( wxHORIZONTAL )
self.time12 = wxTimeCtrl(panel, 20, name="12 hour time")
hsizer1.AddWindow( self.time12, 0, wxALIGN_CENTRE, 5 )
spin1 = wxSpinButton( panel, 30, wxDefaultPosition, wxSize(-1,20), 0 )
self.time12.BindSpinButton(spin1)
hsizer1.AddWindow( spin1, 0, wxALIGN_CENTRE, 5 )
grid.AddSizer( hsizer1, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 )
text2 = wxStaticText( panel, 40, "A 24-hour format wxTimeCtrl:", wxDefaultPosition, wxDefaultSize, 0 )
grid.AddWindow( text2, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxTOP|wxBOTTOM, 5 )
hsizer2 = wxBoxSizer( wxHORIZONTAL )
self.time24 = wxTimeCtrl(panel, 50, fmt24hr=true, name="24 hour time")
hsizer2.AddWindow( self.time24, 0, wxALIGN_CENTRE, 5 )
spin2 = wxSpinButton( panel, 60, wxDefaultPosition, wxSize(-1,20), 0 )
self.time24.BindSpinButton(spin2)
hsizer2.AddWindow( spin2, 0, wxALIGN_CENTRE, 5 )
grid.AddSizer( hsizer2, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 )
panel.SetAutoLayout(true)
panel.SetSizer(grid)
grid.Fit(panel)
panel.Move((50,50))
self.panel = panel
EVT_TIMEUPDATE(self, self.time12.GetId(), self.OnTimeChange)
EVT_TIMEUPDATE(self, self.time24.GetId(), self.OnTimeChange)
def OnTimeChange(self, event):
timectrl = self.panel.FindWindowById(event.GetId())
self.log.write('%s = %s\n' % (
timectrl.GetName(), timectrl.GetValue() ) )
#----------------------------------------------------------------------
def runTest(frame, nb, log):
win = TestPanel(nb, log)
return win
#----------------------------------------------------------------------
# It's nice to be able to use HTML here, but line breaks in the triple quoted string
# cause the resulting output to look funny, as they seem to be interpreted by the
# parser...
overview = """<html><body>
<P>
<B>wxTimeCtrl</B> provides a multi-cell control that allows manipulation of a time value. It supports 12 or 24 hour format, and you can use wxDateTime or mxDateTimet o get/set values from the control.
<P>
Left/right/tab keys to switch cells within a wxTimeCtrl, and the up/down arrows act like a spin control. wxTimeCtrl also allows for an actual spin button to be attached to the control, so that it acts like the up/down arrow keys.
<P>
Here's the interface for wxTimeCtrl:
<DL>
<PRE>
<B>wxTimeCtrl</B>(parent, id = -1,
<B>value</B> = '12:00:00 AM',
pos = wxDefaultPosition,
size = wxDefaultSize,
<B>fmt24hr</B> = false,
<B>spinButton</B> = None,
<B>style</B> = wxTE_PROCESS_TAB,
name = "time")
</PRE>
<UL>
<DT><B>value</B><DD>If no initial value is set, the default will be midnight; if an illegal string is specified, a ValueError will result. (You can always later set the initial time with SetValue() after instantiation of the control.)
<DL><B>size</B><DD>The size of the control will be automatically adjusted for 12/24 hour format if wxDefaultSize is specified.
<DT><B>fmt24hr</B><DD>If true, control will display time in 24 hour time format; if false, it will use 12 hour AM/PM format. SetValue() will adjust values accordingly for the control, based on the format specified.
<DT><B>spinButton</B><DD>If specified, this button's events will be bound to the behavior of the wxTimeCtrl, working like up/down cursor key events. (See BindSpinButton.)
<DT><B>style</B><DD>By default, wxTimeCtrl will process TAB events, by allowing tab to the different cells within the control.
</DL>
</UL>
<DT><B>SetValue(time_string)</B><DD>Sets the value of the control to a particular time, given a valid time string; raises ValueError on invalid value
<DT><B>GetValue()</B><DD>Retrieves the string value of the time from the control
<BR>
<DT><B>SetWxDateTime(wxDateTime)</B><DD>Uses the time portion of a wxDateTime to construct a value for the control.
<DT><B>GetWxDateTime()</B><DD>Retrieves the value of the control, and applies it to the wxDateTimeFromHMS() constructor, and returns the resulting value. (This returns the date portion as "today".)
<BR>
<DT><B>SetMxDateTime(mxDateTime)</B><DD>Uses the time portion of an mxDateTime to construct a value for the control. <EM>NOTE:</EM> This imports mx.DateTime at runtime only if this or the Get function is called.
<DT><B>GetMxDateTime()</B><DD>Retrieves the value of the control and applies it to the DateTime.Time() constructor, and returns the resulting value. (mxDateTime is smart enough to know this is just a time value.)
<BR>
<DT><B>BindSpinButton(wxSpinBtton)</B><DD>Binds an externally created spin button to the control, so that up/down spin events change the active cell or selection in the control (in addition to the up/down cursor keys.) (This is primarily to allow you to create a "standard" interface to time controls, as seen in Windows.)
<BR>
<DT><B>EVT_TIMEUPDATE(win, id, func)</B><DD>func is fired whenever the value of the control changes.
</DL>
</body></html>
"""
if __name__ == '__main__':
import sys,os
import run
run.main(['', os.path.basename(sys.argv[0])])

View File

@@ -0,0 +1,83 @@
README for wxPythonSrc-*.tar.gz
-------------------------------
Prior to version 2.3.3 of wxPython I had always made my Linux/Unix
binaries based on the released binary of wxGTK and wxGTK-gl. This
imposed a few restrictions and so starting with 2.3.3 I have decided
to do a combined binary that inlcudes wxGTK as well as wxPython. This
allows me a bit more flexibility and is consistent with how the
Windows and Mac OS X binaries are built.
If you are reading this file then you are probably interested in
building your own copy of wxPython from the sources contained in this
file. If you wish to use the released wxGTK binary as has been done
in the past then you can still follow the old build directions in
wxPython/BUILD.unix.txt. If you are building for Windows or Mac OS X
then you should look at BUILD.win32.txt or BUILD.osx.txt respectivly.
In all these cases you should use the IN_CVS_TREE=1 flag since this
archive is really just a modified CVS snapshot.
If, on the other hand, you would like to build Linux/Unix binaries
with a private copy of wxGTK like what I am now distributing then
you'll want to follow the instructions in this file.
Clear as mud? Good. Let's get started.
1. We'll be making a private copy of wxGTK so it doesn't conflict with
one used by wxGTK C++ apps that expect to have the default binary
installed from RPM or whatever. I put it in /usr/lib/wxPython, but
you can use whatever you like. I'll just set a variable to our wx
prefix to reference later:
export WXPREF=/usr/lib/wxPython
2. Make a build directory and configure wxGTK.
cd wxPythonGTK-2.3.3 # or whatever the top-level dir is
mkdir build
cd build
../configure --with-gtk \
--prefix=$WXPREF \
--enable-rpath=$WXPREF/lib \
--with-opengl \
--enable-optimise \
--enable-debug_flag \
-with-libjpeg=builtin \
--with-libpng=builtin \
--with-libtiff=builtin \
--with-zlib=builtin
You may want to use --enable-debug instead of --enable-optimise if
you need to run though a debugger and want full debugging symbols.
3. Build and install wxGTK. (You may need to be root for the last
step, depending on where your WXPREF is.)
make
cd ../locale
make allmo
cd ../build
make install
4. Build and install wxPython. If you want to use a different version
of Python than is found by default on the PATH then specify the
whole pathname in these steps. The version of Python that runs
setup.py is the version wxPython will be built and installed for.
(You will need to be root for the install step unless your Python
is not in a system location.)
cd ../wxPython
python setup.py \
IN_CVS_TREE=1 WX_CONFIG=$WXPREF/bin/wx-config \
build install
5. That's all!
--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

View File

@@ -172,6 +172,7 @@ cp ${distdir}/wxPython${port}.spec ${builddir}/${tarver}/wxPython${port}.spec
if [ -z "${skiptar}" ]; then
echo "*** Creating tarball..."
cp distrib/README.1st.txt ${builddir}/${tarver}
pushd ${builddir} > /dev/null
tar cvf ${distdir}/${tarver}.tar ${tarver} > /dev/null
echo "*** Compressing..."

View File

@@ -13,7 +13,7 @@ from my_distutils import run_swig, contrib_copy_tree
# flags and values that affect this script
#----------------------------------------------------------------------
VERSION = "2.3.3pre8"
VERSION = "2.3.3.1"
DESCRIPTION = "Cross platform GUI toolkit for Python"
AUTHOR = "Robin Dunn"
AUTHOR_EMAIL = "Robin Dunn <robin@alldunn.com>"

View File

@@ -1 +1 @@
ver = '2.3.3pre8'
ver = '2.3.3.1'

View File

@@ -765,10 +765,14 @@ class wxApp(wxPyApp):
error = 'wxApp.error'
outputWindowClass = wxPyOnDemandOutputWindow
def __init__(self, redirect=_defRedirect, filename=None):
def __init__(self, redirect=_defRedirect, filename=None, useBestVisual=true):
wxPyApp.__init__(self)
self.stdioWin = None
self.saveStdio = (sys.stdout, sys.stderr)
# This has to be done before OnInit
self.SetUseBestVisual(useBestVisual)
if redirect:
self.RedirectStdio(filename)
# this initializes wxWindows and then calls our OnInit

View File

@@ -9978,6 +9978,35 @@ static PyObject *_wrap_wxMenuBar_EnableTop(PyObject *self, PyObject *args, PyObj
return _resultobj;
}
#define wxMenuBar_IsEnabledTop(_swigobj,_swigarg0) (_swigobj->IsEnabledTop(_swigarg0))
static PyObject *_wrap_wxMenuBar_IsEnabledTop(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
bool _result;
wxMenuBar * _arg0;
size_t _arg1;
PyObject * _argo0 = 0;
char *_kwnames[] = { "self","pos", NULL };
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,"Oi:wxMenuBar_IsEnabledTop",_kwnames,&_argo0,&_arg1))
return NULL;
if (_argo0) {
if (_argo0 == Py_None) { _arg0 = NULL; }
else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxMenuBar_p")) {
PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxMenuBar_IsEnabledTop. Expected _wxMenuBar_p.");
return NULL;
}
}
{
PyThreadState* __tstate = wxPyBeginAllowThreads();
_result = (bool )wxMenuBar_IsEnabledTop(_arg0,_arg1);
wxPyEndAllowThreads(__tstate);
if (PyErr_Occurred()) return NULL;
} _resultobj = Py_BuildValue("i",_result);
return _resultobj;
}
#define wxMenuBar_SetLabelTop(_swigobj,_swigarg0,_swigarg1) (_swigobj->SetLabelTop(_swigarg0,_swigarg1))
static PyObject *_wrap_wxMenuBar_SetLabelTop(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
@@ -11377,6 +11406,7 @@ static PyMethodDef windowscMethods[] = {
{ "wxMenuBar_FindMenu", (PyCFunction) _wrap_wxMenuBar_FindMenu, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_GetLabelTop", (PyCFunction) _wrap_wxMenuBar_GetLabelTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_SetLabelTop", (PyCFunction) _wrap_wxMenuBar_SetLabelTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_IsEnabledTop", (PyCFunction) _wrap_wxMenuBar_IsEnabledTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_EnableTop", (PyCFunction) _wrap_wxMenuBar_EnableTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_Remove", (PyCFunction) _wrap_wxMenuBar_Remove, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_Replace", (PyCFunction) _wrap_wxMenuBar_Replace, METH_VARARGS | METH_KEYWORDS },

View File

@@ -977,6 +977,9 @@ class wxMenuBarPtr(wxWindowPtr):
def EnableTop(self, *_args, **_kwargs):
val = apply(windowsc.wxMenuBar_EnableTop,(self,) + _args, _kwargs)
return val
def IsEnabledTop(self, *_args, **_kwargs):
val = apply(windowsc.wxMenuBar_IsEnabledTop,(self,) + _args, _kwargs)
return val
def SetLabelTop(self, *_args, **_kwargs):
val = apply(windowsc.wxMenuBar_SetLabelTop,(self,) + _args, _kwargs)
return val

View File

@@ -1691,10 +1691,14 @@ class wxApp(wxPyApp):
error = 'wxApp.error'
outputWindowClass = wxPyOnDemandOutputWindow
def __init__(self, redirect=_defRedirect, filename=None):
def __init__(self, redirect=_defRedirect, filename=None, useBestVisual=true):
wxPyApp.__init__(self)
self.stdioWin = None
self.saveStdio = (sys.stdout, sys.stderr)
# This has to be done before OnInit
self.SetUseBestVisual(useBestVisual)
if redirect:
self.RedirectStdio(filename)
# this initializes wxWindows and then calls our OnInit

View File

@@ -92,7 +92,6 @@ BOOL WINAPI DllMain(
wxPyApp::wxPyApp() {
SetUseBestVisual(TRUE);
}
wxPyApp::~wxPyApp() {
@@ -889,7 +888,6 @@ size_t wxPyCBInputStream::OnSysRead(void *buffer, size_t bufsize) {
else
m_lasterror = wxSTREAM_READ_ERROR;
wxPyEndBlockThreads();
m_lastcount = o;
return o;
}

View File

@@ -9978,6 +9978,35 @@ static PyObject *_wrap_wxMenuBar_EnableTop(PyObject *self, PyObject *args, PyObj
return _resultobj;
}
#define wxMenuBar_IsEnabledTop(_swigobj,_swigarg0) (_swigobj->IsEnabledTop(_swigarg0))
static PyObject *_wrap_wxMenuBar_IsEnabledTop(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
bool _result;
wxMenuBar * _arg0;
size_t _arg1;
PyObject * _argo0 = 0;
char *_kwnames[] = { "self","pos", NULL };
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,"Oi:wxMenuBar_IsEnabledTop",_kwnames,&_argo0,&_arg1))
return NULL;
if (_argo0) {
if (_argo0 == Py_None) { _arg0 = NULL; }
else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxMenuBar_p")) {
PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxMenuBar_IsEnabledTop. Expected _wxMenuBar_p.");
return NULL;
}
}
{
PyThreadState* __tstate = wxPyBeginAllowThreads();
_result = (bool )wxMenuBar_IsEnabledTop(_arg0,_arg1);
wxPyEndAllowThreads(__tstate);
if (PyErr_Occurred()) return NULL;
} _resultobj = Py_BuildValue("i",_result);
return _resultobj;
}
#define wxMenuBar_SetLabelTop(_swigobj,_swigarg0,_swigarg1) (_swigobj->SetLabelTop(_swigarg0,_swigarg1))
static PyObject *_wrap_wxMenuBar_SetLabelTop(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
@@ -11377,6 +11406,7 @@ static PyMethodDef windowscMethods[] = {
{ "wxMenuBar_FindMenu", (PyCFunction) _wrap_wxMenuBar_FindMenu, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_GetLabelTop", (PyCFunction) _wrap_wxMenuBar_GetLabelTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_SetLabelTop", (PyCFunction) _wrap_wxMenuBar_SetLabelTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_IsEnabledTop", (PyCFunction) _wrap_wxMenuBar_IsEnabledTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_EnableTop", (PyCFunction) _wrap_wxMenuBar_EnableTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_Remove", (PyCFunction) _wrap_wxMenuBar_Remove, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_Replace", (PyCFunction) _wrap_wxMenuBar_Replace, METH_VARARGS | METH_KEYWORDS },

View File

@@ -977,6 +977,9 @@ class wxMenuBarPtr(wxWindowPtr):
def EnableTop(self, *_args, **_kwargs):
val = apply(windowsc.wxMenuBar_EnableTop,(self,) + _args, _kwargs)
return val
def IsEnabledTop(self, *_args, **_kwargs):
val = apply(windowsc.wxMenuBar_IsEnabledTop,(self,) + _args, _kwargs)
return val
def SetLabelTop(self, *_args, **_kwargs):
val = apply(windowsc.wxMenuBar_SetLabelTop,(self,) + _args, _kwargs)
return val

View File

@@ -1691,10 +1691,14 @@ class wxApp(wxPyApp):
error = 'wxApp.error'
outputWindowClass = wxPyOnDemandOutputWindow
def __init__(self, redirect=_defRedirect, filename=None):
def __init__(self, redirect=_defRedirect, filename=None, useBestVisual=true):
wxPyApp.__init__(self)
self.stdioWin = None
self.saveStdio = (sys.stdout, sys.stderr)
# This has to be done before OnInit
self.SetUseBestVisual(useBestVisual)
if redirect:
self.RedirectStdio(filename)
# this initializes wxWindows and then calls our OnInit

View File

@@ -10072,6 +10072,35 @@ static PyObject *_wrap_wxMenuBar_EnableTop(PyObject *self, PyObject *args, PyObj
return _resultobj;
}
#define wxMenuBar_IsEnabledTop(_swigobj,_swigarg0) (_swigobj->IsEnabledTop(_swigarg0))
static PyObject *_wrap_wxMenuBar_IsEnabledTop(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
bool _result;
wxMenuBar * _arg0;
size_t _arg1;
PyObject * _argo0 = 0;
char *_kwnames[] = { "self","pos", NULL };
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,"Oi:wxMenuBar_IsEnabledTop",_kwnames,&_argo0,&_arg1))
return NULL;
if (_argo0) {
if (_argo0 == Py_None) { _arg0 = NULL; }
else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxMenuBar_p")) {
PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxMenuBar_IsEnabledTop. Expected _wxMenuBar_p.");
return NULL;
}
}
{
PyThreadState* __tstate = wxPyBeginAllowThreads();
_result = (bool )wxMenuBar_IsEnabledTop(_arg0,_arg1);
wxPyEndAllowThreads(__tstate);
if (PyErr_Occurred()) return NULL;
} _resultobj = Py_BuildValue("i",_result);
return _resultobj;
}
#define wxMenuBar_SetLabelTop(_swigobj,_swigarg0,_swigarg1) (_swigobj->SetLabelTop(_swigarg0,_swigarg1))
static PyObject *_wrap_wxMenuBar_SetLabelTop(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
@@ -11859,6 +11888,7 @@ static PyMethodDef windowscMethods[] = {
{ "wxMenuBar_FindMenu", (PyCFunction) _wrap_wxMenuBar_FindMenu, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_GetLabelTop", (PyCFunction) _wrap_wxMenuBar_GetLabelTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_SetLabelTop", (PyCFunction) _wrap_wxMenuBar_SetLabelTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_IsEnabledTop", (PyCFunction) _wrap_wxMenuBar_IsEnabledTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_EnableTop", (PyCFunction) _wrap_wxMenuBar_EnableTop, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_Remove", (PyCFunction) _wrap_wxMenuBar_Remove, METH_VARARGS | METH_KEYWORDS },
{ "wxMenuBar_Replace", (PyCFunction) _wrap_wxMenuBar_Replace, METH_VARARGS | METH_KEYWORDS },

View File

@@ -983,6 +983,9 @@ class wxMenuBarPtr(wxWindowPtr):
def EnableTop(self, *_args, **_kwargs):
val = apply(windowsc.wxMenuBar_EnableTop,(self,) + _args, _kwargs)
return val
def IsEnabledTop(self, *_args, **_kwargs):
val = apply(windowsc.wxMenuBar_IsEnabledTop,(self,) + _args, _kwargs)
return val
def SetLabelTop(self, *_args, **_kwargs):
val = apply(windowsc.wxMenuBar_SetLabelTop,(self,) + _args, _kwargs)
return val

View File

@@ -1697,10 +1697,14 @@ class wxApp(wxPyApp):
error = 'wxApp.error'
outputWindowClass = wxPyOnDemandOutputWindow
def __init__(self, redirect=_defRedirect, filename=None):
def __init__(self, redirect=_defRedirect, filename=None, useBestVisual=true):
wxPyApp.__init__(self)
self.stdioWin = None
self.saveStdio = (sys.stdout, sys.stderr)
# This has to be done before OnInit
self.SetUseBestVisual(useBestVisual)
if redirect:
self.RedirectStdio(filename)
# this initializes wxWindows and then calls our OnInit

View File

@@ -761,6 +761,7 @@ public:
wxMenu *Replace(size_t pos, wxMenu *menu, const wxString& title);
wxMenu *Remove(size_t pos);
void EnableTop(size_t pos, bool enable);
bool IsEnabledTop(size_t pos);
void SetLabelTop(size_t pos, const wxString& label);
wxString GetLabelTop(size_t pos);
int FindMenu(const wxString& title);

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python
"""PyCrustApp is a python shell and namespace browser application."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python
"""PyFillingApp is a python namespace inspection application."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python
"""PyShellApp is a python shell application."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"

View File

@@ -132,137 +132,102 @@ class wxColumnSorterMixin:
class wxListCtrlAutoWidthMixin:
""" A mix-in class that automatically resizes the last column to take up
the remaining width of the wxListCtrl.
the remaining width of the wxListCtrl.
This causes the wxListCtrl to automatically take up the full width of
the list, without either a horizontal scroll bar (unless absolutely
necessary) or empty space to the right of the last column.
This causes the wxListCtrl to automatically take up the full width of
the list, without either a horizontal scroll bar (unless absolutely
necessary) or empty space to the right of the last column.
NOTE: This only works for report-style lists.
NOTE: This only works for report-style lists.
WARNING: If you override the EVT_SIZE event in your wxListCtrl, make
sure you call event.Skip() to ensure that the mixin's
_OnResize method is called.
WARNING: If you override the EVT_SIZE event in your wxListCtrl, make
sure you call event.Skip() to ensure that the mixin's
_OnResize method is called.
This mix-in class was written by Erik Westra <ewestra@wave.co.nz>
This mix-in class was written by Erik Westra <ewestra@wave.co.nz>
"""
def __init__(self):
""" Standard initialiser.
"""
self._needResize = false
self._lastColMinWidth = None
""" Standard initialiser.
"""
self._lastColMinWidth = None
EVT_SIZE(self, self._onResize)
EVT_LIST_COL_END_DRAG(self, self.GetId(), self._onEndColDrag)
EVT_IDLE(self, self._onIdle)
EVT_SIZE(self, self._onResize)
EVT_LIST_COL_END_DRAG(self, self.GetId(), self._onResize)
def resizeLastColumn(self, minWidth):
""" Resize the last column appropriately.
""" Resize the last column appropriately.
If the list's columns are too wide to fit within the window, we use
a horizontal scrollbar. Otherwise, we expand the right-most column
to take up the remaining free space in the list.
If the list's columns are too wide to fit within the window, we use
a horizontal scrollbar. Otherwise, we expand the right-most column
to take up the remaining free space in the list.
This method is called automatically when the wxListCtrl is resized;
you can also call it yourself whenever you want the last column to
be resized appropriately (eg, when adding, removing or resizing
columns).
This method is called automatically when the wxListCtrl is resized;
you can also call it yourself whenever you want the last column to
be resized appropriately (eg, when adding, removing or resizing
columns).
'minWidth' is the preferred minimum width for the last column.
"""
self._lastColMinWidth = minWidth
self._doResize()
'minWidth' is the preferred minimum width for the last column.
"""
self._lastColMinWidth = minWidth
self._doResize()
# =====================
# == Private Methods ==
# =====================
def _onResize(self, event):
""" Respond to the wxListCtrl being resized.
""" Respond to the wxListCtrl being resized.
We automatically resize the last column in the list.
"""
self._doResize()
event.Skip()
def _onEndColDrag(self, event):
""" Respond to the user resizing one of our columns.
We resize the last column in the list to match. Note that, because
of a quirk in the way columns are resized under MS Windows, we
actually have to do the column resize in idle time.
"""
self._needResize = true
event.Skip()
def _onIdle(self, event):
""" Respond to an idle event.
We resize the last column, if we've been asked to do so.
"""
if self._needResize:
self._doResize()
self.Refresh() # Fixes redraw problem under MS Windows.
self._needResize = false
We automatically resize the last column in the list.
"""
wxCallAfter(self._doResize)
event.Skip()
def _doResize(self):
""" Resize the last column as appropriate.
""" Resize the last column as appropriate.
If the list's columns are too wide to fit within the window, we use
a horizontal scrollbar. Otherwise, we expand the right-most column
to take up the remaining free space in the list.
If the list's columns are too wide to fit within the window, we use
a horizontal scrollbar. Otherwise, we expand the right-most column
to take up the remaining free space in the list.
We remember the current size of the last column, before resizing,
as the preferred minimum width if we haven't previously been given
or calculated a minimum width. This ensure that repeated calls to
_doResize() don't cause the last column to size itself too large.
"""
numCols = self.GetColumnCount()
if numCols == 0: return # Nothing to resize.
We remember the current size of the last column, before resizing,
as the preferred minimum width if we haven't previously been given
or calculated a minimum width. This ensure that repeated calls to
_doResize() don't cause the last column to size itself too large.
"""
numCols = self.GetColumnCount()
if numCols == 0: return # Nothing to resize.
if self._lastColMinWidth == None:
self._lastColMinWidth = self.GetColumnWidth(numCols - 1)
if self._lastColMinWidth == None:
self._lastColMinWidth = self.GetColumnWidth(numCols - 1)
listWidth = self.GetSize().width
if self.GetItemCount() > self.GetCountPerPage():
# We're showing the vertical scrollbar -> allow for scrollbar width
scrollWidth = wxSystemSettings_GetSystemMetric(wxSYS_VSCROLL_X)
listWidth = listWidth - scrollWidth
# We're showing the vertical scrollbar -> allow for scrollbar width
# NOTE: on GTK, the scrollbar is included in the client size, but on
# Windows it is not included
listWidth = self.GetClientSize().width
if wxPlatform != '__WXMSW__':
if self.GetItemCount() > self.GetCountPerPage():
scrollWidth = wxSystemSettings_GetSystemMetric(wxSYS_VSCROLL_X)
listWidth = listWidth - scrollWidth
totColWidth = 0 # Width of all columns except last one.
for col in range(numCols-1):
totColWidth = totColWidth + self.GetColumnWidth(col)
totColWidth = 0 # Width of all columns except last one.
for col in range(numCols-1):
totColWidth = totColWidth + self.GetColumnWidth(col)
lastColWidth = self.GetColumnWidth(numCols - 1)
lastColWidth = self.GetColumnWidth(numCols - 1)
# NOTE: This is the extra number of pixels required to make the
# wxListCtrl size correctly, at least under Windows 2000.
# Unfortunately, different OSs and even different versions of the
# same OS may implement the wxListCtrl differently, so different
# margins may be needed to get the columns resized correctly. No
# doubt the margin could be calculated in a more intelligent
# manner...
if wxPlatform == '__WXMSW__':
margin = 6
elif wxPlatform == '__WXGTK__':
margin = 8
else:
margin = 0
if totColWidth + self._lastColMinWidth > listWidth:
# We haven't got the width to show the last column at its minimum
# width -> set it to its minimum width and allow the horizontal
# scrollbar to show.
self.SetColumnWidth(numCols-1, self._lastColMinWidth)
return
if totColWidth + self._lastColMinWidth > listWidth - margin:
# We haven't got the width to show the last column at its minimum
# width -> set it to its minimum width and allow the horizontal
# scrollbar to show.
self.SetColumnWidth(numCols-1, self._lastColMinWidth)
return
# Resize the last column to take up the remaining available space.
# Resize the last column to take up the remaining available space.
self.SetColumnWidth(numCols-1, listWidth - totColWidth - margin)
self.SetColumnWidth(numCols-1, listWidth - totColWidth)

View File

@@ -0,0 +1,389 @@
"""
A mixin class for doing "RubberBand"-ing on a window.
by "Robb Shecter" <rs@onsitetech.com>
$Id$
"""
from wxPython.wx import *
import Image
#
# Some miscellaneous mathematical and geometrical functions
#
def isNegative(aNumber):
"""
x < 0: 1
else: 0
"""
return aNumber < 0
def normalizeBox(box):
"""
Convert any negative measurements in the current
box to positive, and adjust the origin.
"""
x, y, w, h = box
if w < 0:
x += (w+1)
w *= -1
if h < 0:
y += (h+1)
h *= -1
return (x, y, w, h)
def boxToExtent(box):
"""
Convert a box specification to an extent specification.
I put this into a seperate function after I realized that
I had been implementing it wrong in several places.
"""
b = normalizeBox(box)
return (b[0], b[1], b[0]+b[2]-1, b[1]+b[3]-1)
def pointInBox(x, y, box):
"""
Return true if the given point is contained in the box.
"""
e = boxToExtent(box)
return x >= e[0] and x <= e[2] and y >= e[1] and y <= e[3]
def pointOnBox(x, y, box, thickness=1):
"""
Return true if the point is on the outside edge
of the box. The thickness defines how thick the
edge should be. This is necessary for HCI reasons:
For example, it's normally very difficult for a user
to manuever the mouse onto a one pixel border.
"""
outerBox = box
innerBox = (box[0]+thickness, box[1]+thickness, box[2]-(thickness*2), box[3]-(thickness*2))
return pointInBox(x, y, outerBox) and not pointInBox(x, y, innerBox)
def getCursorPosition(x, y, box, thickness=1):
"""
Return a position number in the range 0 .. 7 to indicate
where on the box border the point is. The layout is:
0 1 2
7 3
6 5 4
"""
x0, y0, x1, y1 = boxToExtent(box)
w, h = box[2], box[3]
delta = thickness - 1
p = None
if pointInBox(x, y, (x0, y0, thickness, thickness)):
p = 0
elif pointInBox(x, y, (x1-delta, y0, thickness, thickness)):
p = 2
elif pointInBox(x, y, (x1-delta, y1-delta, thickness, thickness)):
p = 4
elif pointInBox(x, y, (x0, y1-delta, thickness, thickness)):
p = 6
elif pointInBox(x, y, (x0+thickness, y0, w-(thickness*2), thickness)):
p = 1
elif pointInBox(x, y, (x1-delta, y0+thickness, thickness, h-(thickness*2))):
p = 3
elif pointInBox(x, y, (x0+thickness, y1-delta, w-(thickness*2), thickness)):
p = 5
elif pointInBox(x, y, (x0, y0+thickness, thickness, h-(thickness*2))):
p = 7
return p
class RubberBand:
"""
A stretchable border which is drawn on top of an
image to define an area.
"""
def __init__(self, drawingSurface, aspectRatio=None):
self.__THICKNESS = 5
self.drawingSurface = drawingSurface
self.aspectRatio = aspectRatio
self.hasLetUp = 0
self.currentlyMoving = None
self.currentBox = None
self.__enabled = 1
self.__currentCursor = None
EVT_MOUSE_EVENTS(drawingSurface, self.__handleMouseEvents)
EVT_PAINT(drawingSurface, self.__handleOnPaint)
def __setEnabled(self, enabled):
self.__enabled = enabled
def __isEnabled(self):
return self.__enabled
def __handleOnPaint(self, event):
#print 'paint'
event.Skip()
def __isMovingCursor(self):
"""
Return true if the current cursor is one used to
mean moving the rubberband.
"""
return self.__currentCursor == wxCURSOR_HAND
def __isSizingCursor(self):
"""
Return true if the current cursor is one of the ones
I may use to signify sizing.
"""
sizingCursors = [wxCURSOR_SIZENESW,
wxCURSOR_SIZENS,
wxCURSOR_SIZENWSE,
wxCURSOR_SIZEWE,
wxCURSOR_SIZING,
wxCURSOR_CROSS]
try:
sizingCursors.index(self.__currentCursor)
return 1
except ValueError:
return 0
def __handleMouseEvents(self, event):
"""
React according to the new event. This is the main
entry point into the class. This method contains the
logic for the class's behavior.
"""
if not self.enabled:
return
x, y = event.GetPosition()
# First make sure we have started a box.
if self.currentBox == None and not event.LeftDown():
# No box started yet. Set cursor to the initial kind.
self.__setCursor(wxCURSOR_CROSS)
return
if event.LeftDown():
if self.currentBox == None:
# No RB Box, so start a new one.
self.currentBox = (x, y, 0, 0)
self.hasLetUp = 0
elif self.__isSizingCursor():
# Starting a sizing operation. Change the origin.
position = getCursorPosition(x, y, self.currentBox, thickness=self.__THICKNESS)
self.currentBox = self.__denormalizeBox(position, self.currentBox)
elif event.Dragging() and event.LeftIsDown():
# Use the cursor type to determine operation
if self.__isMovingCursor():
if self.currentlyMoving or pointInBox(x, y, self.currentBox):
if not self.currentlyMoving:
self.currentlyMoving = (x - self.currentBox[0], y - self.currentBox[1])
self.__moveTo(x - self.currentlyMoving[0], y - self.currentlyMoving[1])
elif self.__isSizingCursor():
self.__resizeBox(x, y)
elif event.LeftUp():
self.hasLetUp = 1
self.currentlyMoving = None
self.__normalizeBox()
elif event.Moving() and not event.Dragging():
# Simple mouse movement event
self.__mouseMoved(x,y)
def __denormalizeBox(self, position, box):
x, y, w, h = box
b = box
if position == 2 or position == 3:
b = (x, y + (h-1), w, h * -1)
elif position == 0 or position == 1 or position == 7:
b = (x + (w-1), y + (h-1), w * -1, h * -1)
elif position == 6:
b = (x + (w-1), y, w * -1, h)
return b
def __resizeBox(self, x, y):
"""
Resize and repaint the box based on the given mouse
coordinates.
"""
# Implement the correct behavior for dragging a side
# of the box: Only change one dimension.
if not self.aspectRatio:
if self.__currentCursor == wxCURSOR_SIZENS:
x = None
elif self.__currentCursor == wxCURSOR_SIZEWE:
y = None
x0,y0,w0,h0 = self.currentBox
currentExtent = boxToExtent(self.currentBox)
if x == None:
if w0 < 1:
w0 += 1
else:
w0 -= 1
x = x0 + w0
if y == None:
if h0 < 1:
h0 += 1
else:
h0 -= 1
y = y0 + h0
x1,y1 = x, y
w, h = abs(x1-x0)+1, abs(y1-y0)+1
if self.aspectRatio:
w = max(w, int(h * self.aspectRatio))
h = int(w / self.aspectRatio)
w *= [1,-1][isNegative(x1-x0)]
h *= [1,-1][isNegative(y1-y0)]
newbox = (x0, y0, w, h)
self.__drawAndErase(boxToDraw=normalizeBox(newbox), boxToErase=normalizeBox(self.currentBox))
self.currentBox = (x0, y0, w, h)
def __normalizeBox(self):
"""
Convert any negative measurements in the current
box to positive, and adjust the origin.
"""
self.currentBox = normalizeBox(self.currentBox)
def __mouseMoved(self, x, y):
"""
Called when the mouse moved without any buttons pressed
or dragging being done.
"""
# Are we on the bounding box?
if pointOnBox(x, y, self.currentBox, thickness=self.__THICKNESS):
position = getCursorPosition(x, y, self.currentBox, thickness=self.__THICKNESS)
cursor = [
wxCURSOR_SIZENWSE,
wxCURSOR_SIZENS,
wxCURSOR_SIZENESW,
wxCURSOR_SIZEWE,
wxCURSOR_SIZENWSE,
wxCURSOR_SIZENS,
wxCURSOR_SIZENESW,
wxCURSOR_SIZEWE
] [position]
self.__setCursor(cursor)
elif pointInBox(x, y, self.currentBox):
self.__setCursor(wxCURSOR_HAND)
else:
self.__setCursor()
def __setCursor(self, id=None):
"""
Set the mouse cursor to the given id.
"""
if self.__currentCursor != id: # Avoid redundant calls
if id:
self.drawingSurface.SetCursor(wxStockCursor(id))
else:
self.drawingSurface.SetCursor(wxNullCursor)
self.__currentCursor = id
def __moveCenterTo(self, x, y):
"""
Move the rubber band so that its center is at (x,y).
"""
x0, y0, w, h = self.currentBox
x2, y2 = x - (w/2), y - (h/2)
self.__moveTo(x2, y2)
def __moveTo(self, x, y):
"""
Move the rubber band so that its origin is at (x,y).
"""
newbox = (x, y, self.currentBox[2], self.currentBox[3])
self.__drawAndErase(boxToDraw=newbox, boxToErase=self.currentBox)
self.currentBox = newbox
def __drawAndErase(self, boxToDraw, boxToErase=None):
"""
Draw one box shape and possibly erase another.
"""
dc = wxClientDC(self.drawingSurface)
dc.BeginDrawing()
dc.SetPen(wxPen(wxWHITE, 1, wxDOT))
dc.SetBrush(wxTRANSPARENT_BRUSH)
dc.SetLogicalFunction(wxXOR)
if boxToErase:
dc.DrawRectangle(*boxToErase)
dc.DrawRectangle(*boxToDraw)
dc.EndDrawing()
def __dumpMouseEvent(self, event):
print 'Moving: ',event.Moving()
print 'Dragging: ',event.Dragging()
print 'LeftDown: ',event.LeftDown()
print 'LeftisDown: ',event.LeftIsDown()
print 'LeftUp: ',event.LeftUp()
print 'Position: ',event.GetPosition()
print 'x,y: ',event.GetX(),event.GetY()
print
#
# The public API:
#
def reset(self, aspectRatio=None):
"""
Clear the existing rubberband
"""
self.currentBox = None
self.aspectRatio = aspectRatio
self.drawingSurface.Refresh()
def getCurrentExtent(self):
"""
Return (x0, y0, x1, y1) or None if
no drawing has yet been done.
"""
if not self.currentBox:
extent = None
else:
extent = boxToExtent(self.currentBox)
return extent
enabled = property(__isEnabled, __setEnabled, None, 'True if I am responding to mouse events')
if __name__ == '__main__':
app = wxPySimpleApp()
frame = wxFrame(None, -1, title='RubberBand Test', size=(300,300))
# Add a panel that the rubberband will work on.
panel = wxPanel(frame, -1)
panel.SetBackgroundColour(wxBLUE)
# Create the rubberband
frame.rubberBand = RubberBand(drawingSurface=panel)
frame.rubberBand.reset(aspectRatio=0.5)
# Add a button that creates a new rubberband
def __newRubberBand(event):
frame.rubberBand.reset()
button = wxButton(frame, 100, 'Reset Rubberband')
EVT_BUTTON(frame, 100, __newRubberBand)
# Layout the frame
sizer = wxBoxSizer(wxVERTICAL)
sizer.Add(panel, 1, wxEXPAND | wxALL, 5)
sizer.Add(button, 0, wxALIGN_CENTER | wxALL, 5)
frame.SetAutoLayout(1)
frame.SetSizer(sizer)
frame.Show(1)
app.MainLoop()

View File

@@ -0,0 +1,701 @@
#----------------------------------------------------------------------------
# Name: wxTimeCtrl.py
# Author: Will Sadkin
# Created: 09/19/2002
# Copyright: (c) 2002 by Will Sadkin, 2002
# License: wxWindows license
#----------------------------------------------------------------------------
# NOTE:
# This was written way it is because of the lack of masked edit controls
# in wxWindows/wxPython. I would also have preferred to derive this
# control from a wxSpinCtrl rather than wxTextCtrl, but the wxTextCtrl
# component of that control is inaccessible through the interface exposed in
# wxPython.
#
# wxTimeCtrl does not use validators, because it does careful manipulation
# of the cursor in the text window on each keystroke, and validation is
# cursor-position specific, so the control intercepts the key codes before the
# validator would fire.
#
from wxPython.wx import *
import string
# The following bit of function is for debugging the subsequent code.
# To turn on debugging output, set _debug to 1
_debug = 0
_indent = 0
def _dbg(*args, **kwargs):
global _indent
if _debug:
if len(args):
if _indent: print ' ' * 3 * _indent,
for arg in args: print arg,
print
# else do nothing
# post process args:
for kwarg, value in kwargs.items():
if kwarg == 'indent' and value: _indent = _indent + 1
elif kwarg == 'indent' and value == 0: _indent = _indent - 1
if _indent < 0: _indent = 0
# This class of event fires whenever the value of the time changes in the control:
wxEVT_TIMEVAL_UPDATED = wxNewId()
def EVT_TIMEUPDATE(win, id, func):
"""Used to trap events indicating that the current time has been changed."""
win.Connect(id, -1, wxEVT_TIMEVAL_UPDATED, func)
class TimeUpdatedEvent(wxPyCommandEvent):
def __init__(self, id, value ='12:00:00 AM'):
wxPyCommandEvent.__init__(self, wxEVT_TIMEVAL_UPDATED, id)
self.value = value
def GetValue(self):
"""Retrieve the value of the float control at the time this event was generated"""
return self.value
class wxTimeCtrl(wxTextCtrl):
def __init__ (
self, parent, id=-1, value = '12:00:00 AM',
pos = wxDefaultPosition, size = wxDefaultSize,
fmt24hr=0,
spinButton = None,
style = wxTE_PROCESS_TAB, name = "time"
):
wxTextCtrl.__init__(self, parent, id, value='',
pos=pos, size=size, style=style, name=name)
self.__fmt24hr = fmt24hr
if size == wxDefaultSize:
# set appropriate default sizes depending on format:
if self.__fmt24hr:
testText = '00:00:00 '
else:
testText = '00:00:00 XXX'
w, h = self.GetTextExtent(testText)
self.SetClientSize( (w+4, self.GetClientSize().height) )
# Set up all the positions of the cells in the wxTimeCtrl (once):
# Format of control is:
# hh:mm:ss xM
# 1
# positions: 01234567890
self.__listCells = ['hour', 'minute', 'second', 'am_pm']
self.__listCellRange = [(0,1,2), (3,4,5), (6,7,8), (9,10,11)]
self.__listDelimPos = [2,5,8]
# Create dictionary of cell ranges, indexed by name or position in the range:
self.__dictCellRange = {}
for i in range(4):
self.__dictCellRange[self.__listCells[i]] = self.__listCellRange[i]
for cell in self.__listCells:
for i in self.__dictCellRange[cell]:
self.__dictCellRange[i] = self.__dictCellRange[cell]
# Create lists of starting and ending positions for each range, and a dictionary of starting
# positions indexed by name
self.__listStartCellPos = []
self.__listEndCellPos = []
for tup in self.__listCellRange:
self.__listStartCellPos.append(tup[0]) # 1st char of cell
self.__listEndCellPos.append(tup[1]) # last char of cell (not including delimiter)
self.__dictStartCellPos = {}
for i in range(4):
self.__dictStartCellPos[self.__listCells[i]] = self.__listStartCellPos[i]
if self.__fmt24hr: self.__lastCell = 'second'
else: self.__lastCell = 'am_pm'
# Validate initial value and set if appropriate
try:
self.SetValue(value)
except ValueError:
self.SetValue('12:00:00 AM')
# set initial position and selection state
self.__SetCurrentCell(self.__dictStartCellPos['hour'])
self.__bSelection = false
EVT_TEXT(self, self.GetId(), self.__OnTextChange)
EVT_SET_FOCUS(self, self.__OnFocus)
EVT_CHAR(self, self.__OnChar)
if spinButton:
self.BindSpinbutton(spinButton) # bind spin button up/down events to this control
def __repr__(self):
return "<wxTimeCtrl: %s>" % self.GetValue()
def SetValue(self, value):
"""
Validating SetValue function for time strings, doing 12/24 format conversion as appropriate.
"""
_dbg('wxTimeCtrl::SetValue', indent=1)
dict_range = self.__dictCellRange
dict_start = self.__dictStartCellPos
fmt12len = dict_range['am_pm'][-1]
fmt24len = dict_range['second'][-1]
try:
separators_correct = value[2] == ':' and value[5] == ':'
len_ok = len(value) in (fmt12len, fmt24len)
if len(value) > fmt24len:
separators_correct = separators_correct and value[8] == ' '
hour = int(value[dict_range['hour'][0]:dict_range['hour'][-1]])
hour_ok = ((hour in range(0,24) and len(value) == fmt24len)
or (hour in range(1,13) and len(value) == fmt12len
and value[dict_start['am_pm']:] in ('AM', 'PM')))
minute = int(value[dict_range['minute'][0]:dict_range['minute'][-1]])
min_ok = minute in range(60)
second = int(value[dict_range['second'][0]:dict_range['second'][-1]])
sec_ok = second in range(60)
_dbg('len_ok =', len_ok, 'separators_correct =', separators_correct)
_dbg('hour =', hour, 'hour_ok =', hour_ok, 'min_ok =', min_ok, 'sec_ok =', sec_ok)
if len_ok and hour_ok and min_ok and sec_ok and separators_correct:
_dbg('valid time string')
self.__hour = hour
if len(value) == fmt12len: # handle 12 hour format conversion for actual hour:
am = value[dict_start['am_pm']:] == 'AM'
if hour != 12 and not am:
self.__hour = hour = (hour+12) % 24
elif hour == 12:
if am: self.__hour = hour = 0
self.__minute = minute
self.__second = second
# valid time
need_to_convert = ((self.__fmt24hr and len(value) == fmt12len)
or (not self.__fmt24hr and len(value) == fmt24len))
_dbg('need_to_convert =', need_to_convert)
if need_to_convert: #convert to 12/24 hour format as specified:
dict_start = self.__dictStartCellPos
if self.__fmt24hr and len(value) == fmt12len:
text = '%.2d:%.2d:%.2d' % (hour, minute, second)
else:
if hour > 12:
hour = hour - 12
am_pm = 'PM'
elif hour == 12:
am_pm = 'PM'
else:
if hour == 0: hour = 12
am_pm = 'AM'
text = '%2d:%.2d:%.2d %s' % (hour, minute, second, am_pm)
else:
text = value
_dbg('text=', text)
wxTextCtrl.SetValue(self, text)
_dbg('firing TimeUpdatedEvent...')
evt = TimeUpdatedEvent(self.GetId(), text)
evt.SetEventObject(self)
self.GetEventHandler().ProcessEvent(evt)
else:
_dbg('len_ok:', len_ok, 'separators_correct =', separators_correct)
_dbg('hour_ok:', hour_ok, 'min_ok:', min_ok, 'sec_ok:', sec_ok, indent=0)
raise ValueError, 'value is not a valid time string'
except (TypeError, ValueError):
_dbg(indent=0)
raise ValueError, 'value is not a valid time string'
_dbg(indent=0)
def SetFromWxDateTime(self, wxdt):
value = '%2d:%.2d:%.2d' % (wxdt.GetHour(), wxdt.GetMinute(), wxdt.GetSecond())
self.SetValue(value)
def GetWxDateTime(self):
t = wxDateTimeFromHMS(self.__hour, self.__minute, self.__second)
return t
def SetMxDateTime(self, mxdt):
from mx import DateTime
value = '%2d:%.2d:%.2d' % (mxdt.hour, mxdt.minute, mxdt.second)
self.SetValue(value)
def GetMxDateTime(self):
from mx import DateTime
t = DateTime.Time(self.__hour, self.__minute, self.__second)
return t
def BindSpinButton(self, sb):
"""
This function binds an externally created spin button to the control, so that
up/down events from the button automatically change the control.
"""
_dbg('wxTimeCtrl::BindSpinButton')
self.__spinButton = sb
if self.__spinButton:
EVT_SPIN_UP(self.__spinButton, self.__spinButton.GetId(), self.__OnSpinUp) # bind event handler to spin ctrl
EVT_SPIN_DOWN(self.__spinButton, self.__spinButton.GetId(), self.__OnSpinDown) # bind event handler to spin ctrl
#-------------------------------------------------------------------------------------------------------------
# these are private functions and overrides:
def __SetCurrentCell(self, pos):
"""
Sets state variables that indicate the current cell and position within the control.
"""
self.__posCurrent = pos
self.__cellStart, self.__cellEnd = self.__dictCellRange[pos][0], self.__dictCellRange[pos][-1]
def SetInsertionPoint(self, pos):
"""
Records the specified position and associated cell before calling base class' function.
"""
self.__SetCurrentCell(pos)
wxTextCtrl.SetInsertionPoint(self, pos) # (causes EVT_TEXT event to fire)
def __OnTextChange(self, event):
"""
This private event handler is required to retain the current position information of the cursor
after update to the underlying text control is done.
"""
_dbg('wxTimeCtrl::OnTextChange', indent=1)
self.__SetCurrentCell(self.__posCurrent) # ensure cell range vars are set
# Note: must call self.SetSelection here to preserve insertion point cursor after update!
# (I don't know why, but this does the trick!)
if self.__bSelection:
_dbg('reselecting from ', self.__posCurrent, 'to', self.__posSelectTo)
self.SetSelection(self.__posCurrent, self.__posSelectTo)
else:
self.SetSelection(self.__posCurrent, self.__posCurrent)
event.Skip()
_dbg(indent=0)
def __OnFocus(self, event):
"""
This internal event handler ensures legal setting of input cursor on (re)focus to the control.
"""
_dbg('wxTimeCtrl::OnFocus; ctrl id=', event.GetId())
self.__SetCurrentCell(0)
self.__bSelection = false
self.__posSelectTo = self.__posCurrent
self.SetInsertionPoint(self.__posCurrent)
event.Skip()
def __OnSpinUp(self, event):
"""
Event handler for any bound spin button on EVT_SPIN_UP;
causes control to behave as if up arrow was pressed.
"""
_dbg('wxTimeCtrl::OnSpinUp')
pos = self.GetInsertionPoint()
self.IncrementValue(WXK_UP, pos)
self.SetInsertionPoint(pos)
def __OnSpinDown(self, event):
"""
Event handler for any bound spin button on EVT_SPIN_DOWN;
causes control to behave as if down arrow was pressed.
"""
_dbg('wxTimeCtrl::OnSpinDown')
pos = self.GetInsertionPoint()
self.IncrementValue(WXK_DOWN, pos)
self.SetInsertionPoint(pos)
def __OnChar(self, event):
"""
This private event handler is the main control point for the wxTimeCtrl.
It governs whether input characters are accepted and if so, handles them
so as to provide appropriate cursor and selection behavior for the control.
"""
_dbg('wxTimeCtrl::OnChar', indent=1)
# NOTE: Returning without calling event.Skip() eats the event before it
# gets to the text control...
key = event.GetKeyCode()
text = self.GetValue()
pos = self.GetInsertionPoint()
if pos != self.__posCurrent:
_dbg("insertion point has moved; resetting current cell")
self.__SetCurrentCell(pos)
self.SetSelection(self.__posCurrent, self.__posCurrent)
sel_start, sel_to = self.GetSelection()
selection = sel_start != sel_to
if not selection:
self.__bSelection = false # predict unselection of entire region
_dbg('keycode = ', key)
_dbg('pos = ', pos)
if key in (WXK_DELETE, WXK_BACK): # don't allow deletion
_dbg(indent=0)
return
elif key == WXK_TAB: # skip to next field if applicable:
_dbg('key == WXK_TAB')
dict_range = self.__dictCellRange
dict_start = self.__dictStartCellPos
if event.ShiftDown(): # tabbing backwords
###(NOTE: doesn't work; wxTE_PROCESS_TAB doesn't appear to send us this event!)
_dbg('event.ShiftDown()')
if pos in dict_range['hour']: # already in 1st field
self.__SetCurrentCell(dict_start['hour']) # ensure we have our member vars set
event.Skip() #then do normal tab processing for the form
elif pos in dict_range['minute']: # skip to hours field
new_pos = dict_start['hour']
elif pos in dict_range['second']: # skip to minutes field
new_pos = dict_start['minute']
elif pos in dict_range['am_pm']: # skip to seconds field
new_pos = dict_start['second']
self.__bSelection = true
self.__posSelectTo = new_pos+2
self.SetInsertionPoint(new_pos) # force insert point to jump to next cell (swallowing TAB)
else:
if pos in dict_range[self.__lastCell]: # already in last field; ensure we have our members set
self.__SetCurrentCell(dict_start[self.__lastCell])
_dbg('tab in last cell')
event.Skip() # then do normal tab processing for the form
_dbg(indent=0)
return
if pos in dict_range['second']: # skip to AM/PM field (if not last cell)
new_pos = dict_start['am_pm']
elif pos in dict_range['minute']: # skip to seconds field
new_pos = dict_start['second']
elif pos in dict_range['hour']: # skip to minutes field
new_pos = dict_start['minute']
self.__bSelection = true
self.__posSelectTo = new_pos+2
self.SetInsertionPoint(new_pos) # force insert point to jump to next cell (swallowing TAB)
elif key == WXK_LEFT: # move left; set insertion point as appropriate:
_dbg('key == WXK_LEFT')
if event.ShiftDown(): # selecting a range...
_dbg('event.ShiftDown()')
if sel_to != pos:
if sel_to - 1 == pos: # allow unselection of position
self.__bSelection = false # predict unselection of entire region
event.Skip()
if pos in self.__listStartCellPos: # can't select pass delimiters
_dbg(indent=0)
return
elif pos in self.__listEndCellPos: # can't use normal selection, because position ends up
# at delimeter
_dbg('set selection from', pos-1, 'to', self.__posCurrent)
self.__bSelection = true
self.__posSelectTo = pos
self.__posCurrent = pos-1
self.SetSelection(self.__posCurrent, self.__posSelectTo)
_dbg(indent=0)
return
else: event.Skip() # allow selection
# else... not selecting
if selection:
_dbg('sel_start=', sel_start, 'sel_to=', sel_to, '(Clearing selection)')
self.SetSelection(pos,pos) # clear selection
self.__bSelection = false
if pos == 0: # let base ctrl handle left bound case
event.Skip()
elif pos in self.__listStartCellPos: # skip (left) OVER the colon/space:
self.SetInsertionPoint(pos-1) # (this causes a EVT_TEXT)
self.__SetCurrentCell(pos-2) # set resulting position as "current"
else:
self.__SetCurrentCell(pos-1) # record the new cell position after the event is finishedI
# and update spinbutton as necessary
event.Skip() # let base control handle event
elif key == WXK_RIGHT: # move right
_dbg('key == WXK_RIGHT')
if event.ShiftDown():
_dbg('event.ShiftDown()')
if sel_to in self.__listDelimPos: # can't select pass delimiters
_dbg(indent=0)
return
elif pos in self.__listEndCellPos: # can't use normal selection, because position ends up
# at delimeter
_dbg('set selection from', self.__posCurrent, 'to', pos+1)
self.__bSelection = true
self.__posSelectTo = pos+1
self.SetSelection(self.__posCurrent, self.__posSelectTo)
_dbg(indent=0)
return
else: event.Skip()
else:
if selection:
_dbg('sel_start=', sel_start, 'sel_to=', sel_to, '(Clearing selection)')
pos = sel_start
self.SetSelection(pos,pos) # clear selection
self.__bSelection = false
if pos == self.__dictStartCellPos[self.__lastCell]+1:
_dbg(indent=0)
return # don't allow cursor past last cell
if pos in self.__listEndCellPos: # skip (right) OVER the colon/space:
self.SetInsertionPoint(pos+1) # (this causes a EVT_TEXT)
self.__SetCurrentCell(pos+2) # set resulting position
else:
self.__SetCurrentCell(pos+1) # record the new cell position after the event is finished
self.__bSelection = false
event.Skip()
elif key in (WXK_UP, WXK_DOWN):
_dbg('key in (WXK_UP, WXK_DOWN)')
self.IncrementValue(key, pos) # increment/decrement as appropriate
self.SetInsertionPoint(pos)
elif key < WXK_SPACE or key == WXK_DELETE or key > 255:
event.Skip() # non alphanumeric; process normally (Right thing to do?)
elif chr(key) in string.digits: # let ChangeValue validate and update current position
self.ChangeValue(chr(key), pos) # handle event (and swallow it)
elif chr(key) in ('A', 'P', 'M', ' '): # let ChangeValue validate and update current position
self.ChangeValue(chr(key), pos) # handle event (and swallow it)
else: # disallowed char; swallow event
_dbg(indent=0)
return
_dbg(indent=0)
def IncrementValue(self, key, pos):
_dbg('wxTimeCtrl::IncrementValue', key, pos)
text = self.GetValue()
sel_start, sel_to = self.GetSelection()
selection = sel_start != sel_to
cell_selected = selection and sel_to -1 != pos
dict_start = self.__dictStartCellPos
# Determine whether we should change the entire cell or just a portion of it:
if( not selection
or cell_selected
or text[pos] == ' '
or text[pos] == '9' and text[pos-1] == ' ' and key == WXK_UP
or text[pos] == '1' and text[pos-1] == ' ' and key == WXK_DOWN
or pos >= dict_start['am_pm']):
_dbg(indent=1)
self.IncrementCell(key, pos)
_dbg(indent=0)
else:
if key == WXK_UP: inc = 1
else: inc = -1
if pos == dict_start['hour'] and not self.__fmt24hr:
if text[pos] == ' ': digit = '1' # allow ' ' or 1 for 1st digit in 12hr format
else: digit = ' '
else:
if pos == dict_start['hour']:
if int(text[pos + 1]) >3: mod = 2 # allow for 20-23
else: mod = 3 # allow 00-19
elif pos == dict_start['hour'] + 1:
if self.__fmt24hr:
if text[pos - 1] == '2': mod = 4 # allow hours 20-23
else: mod = 10 # allow hours 00-19
else:
if text[pos - 1] == '1': mod = 3 # allow hours 10-12
else: mod = 10 # allow 0-9
elif pos in (dict_start['minute'],
dict_start['second']): mod = 6 # allow minutes/seconds 00-59
else: mod = 10
digit = '%d' % ((int(text[pos]) + inc) % mod)
_dbg(indent=1)
_dbg("new digit = \'%s\'" % digit)
self.ChangeValue(digit, pos)
_dbg(indent=0)
def IncrementCell(self, key, pos):
_dbg('wxTimeCtrl::IncrementCell', key, pos)
self.__SetCurrentCell(pos) # determine current cell
hour, minute, second = self.__hour, self.__minute, self.__second
text = self.GetValue()
dict_start = self.__dictStartCellPos
if key == WXK_UP: inc = 1
else: inc = -1
if self.__cellStart == dict_start['am_pm']:
am = text[dict_start['am_pm']:] == 'AM'
if am: hour = hour + 12
else: hour = hour - 12
else:
if self.__cellStart == dict_start['hour']:
hour = (hour + inc) % 24
elif self.__cellStart == dict_start['minute']:
minute = (minute + inc) % 60
elif self.__cellStart == dict_start['second']:
second = (second + inc) % 60
newvalue = '%.2d:%.2d:%.2d' % (hour, minute, second)
self.__posCurrent = self.__cellStart
self.__posSelectTo = self.__cellEnd
self.__bSelection = true
_dbg(indent=1)
self.SetValue(newvalue)
_dbg(indent=0)
def ChangeValue(self, char, pos):
_dbg('wxTimeCtrl::ChangeValue', "\'" + char + "\'", pos)
text = self.GetValue()
self.__SetCurrentCell(pos)
sel_start, sel_to = self.GetSelection()
self.__posSelectTo = sel_to
self.__bSelection = selection = sel_start != sel_to
cell_selected = selection and sel_to -1 != pos
dict_start = self.__dictStartCellPos
if pos in self.__listDelimPos: return # don't allow change of punctuation
elif( 0 < pos < dict_start['am_pm'] and char not in string.digits):
return # AM/PM not allowed in this position
# See if we're changing the hour cell, and validate/update appropriately:
#
hour_start = dict_start['hour'] # (ie. 0)
if pos == hour_start: # if at 1st position,
if self.__fmt24hr: # and using 24 hour format
if char not in ('0', '1', '2'): # return if digit not 0,1, or 2
return
if cell_selected: # replace cell contents
newtext = '%.2d' % int(char) + text[hour_start+2:]
else: # relace current position
newtext = char + text[pos+1:]
else: # (12 hour format)
if char not in ('1', ' '): # can only type a 1 or space
return
if text[pos+1] not in ('0', '1', '2'): # and then, only if other column is 0,1, or 2
return
if( char == ' ' # and char isn't space and
and (cell_selected or text[pos+1] == '0')): # 2nd column is 0 or cell isn't selected
return
# else... ok
if cell_selected: # replace cell contents
newtext = '%2d' % int(char) + text[hour_start+2:]
else: # relace current position
newtext = char + text[pos+1:]
if char == ' ': self.SetInsertionPoint(pos+1) # move insert point to legal position
elif pos == hour_start+1: # if editing 2nd position of hour
if( not self.__fmt24hr # and using 12 hour format
and text[hour_start] == '1' # if 1st char is 1,
and char not in ('0', '1', '2')): # disallow anything bug 0,1, or 2
return
newtext = text[hour_start] + char + text[hour_start+2:] # else any digit ok
# Do the same sort of validation for minute and second cells
elif pos in (dict_start['minute'], dict_start['second']):
if cell_selected: # if cell selected, replace value
newtext = text[:pos] + '%.2d' % int(char) + text[pos+2:]
elif int(char) > 5: return # else disallow > 59 for minute and second fields
else:
newtext = text[:pos] + char + text[pos+1:] # else ok
elif pos in (dict_start['minute']+1, dict_start['second']+1):
newtext = text[:pos] + char + text[pos+1:] # all digits ok for 2nd digit of minute/second
# Process AM/PM cell
elif pos == dict_start['am_pm']:
if char not in ('A','P'): return # disallow all but A or P as 1st char of column
newtext = text[:pos] + char + text[pos+1:]
else: return # not a valid position
# update member position vars and set selection to character changed
self.__posCurrent = pos+1
self.__SetCurrentCell(self.__posCurrent)
_dbg(indent=1)
_dbg('newtext=', newtext)
_dbg(indent=0)
self.SetValue(newtext)
self.SetInsertionPoint(pos+1)
#----------------------------------------------------------------------------
if __name__ == '__main__':
import traceback
class TestPanel(wxPanel):
def __init__(self, parent, id,
pos = wxPyDefaultPosition, size = wxPyDefaultSize,
fmt24hr = 0, test_mx = 0,
style = wxTAB_TRAVERSAL ):
self.test_mx = test_mx
wxPanel.__init__(self, parent, id, pos, size, style)
sizer = wxBoxSizer( wxHORIZONTAL )
self.tc = wxTimeCtrl(self, 10, fmt24hr = fmt24hr)
sizer.AddWindow( self.tc, 0, wxALIGN_CENTRE|wxLEFT|wxTOP|wxBOTTOM, 5 )
sb = wxSpinButton( self, 20, wxDefaultPosition, wxSize(-1,20), 0 )
self.tc.BindSpinButton(sb)
sizer.AddWindow( sb, 0, wxALIGN_CENTRE|wxRIGHT|wxTOP|wxBOTTOM, 5 )
self.SetAutoLayout( true )
self.SetSizer( sizer )
sizer.Fit( self )
sizer.SetSizeHints( self )
EVT_TIMEUPDATE(self, self.tc.GetId(), self.OnTimeChange)
def OnTimeChange(self, event):
_dbg('OnTimeChange: value = ', event.GetValue())
wxdt = self.tc.GetWxDateTime()
_dbg('wxdt =', wxdt.GetHour(), wxdt.GetMinute(), wxdt.GetSecond())
if self.test_mx:
mxdt = self.tc.GetMxDateTime()
_dbg('mxdt =', mxdt.hour, mxdt.minute, mxdt.second)
class MyApp(wxApp):
def OnInit(self):
import sys
fmt24hr = '24' in sys.argv
test_mx = 'mx' in sys.argv
try:
frame = wxFrame(NULL, -1, "Junk", wxPoint(20,20), wxSize(100,100) )
panel = TestPanel(frame, -1, wxPoint(-1,-1), fmt24hr=fmt24hr, test_mx = test_mx)
frame.Show(true)
except:
traceback.print_exc()
return false
return true
try:
app = MyApp(0)
app.MainLoop()
except:
traceback.print_exc()

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python
"""
img2png.py -- convert several image formats to PNG format

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python
"""
img2py.py -- Convert an image to PNG format and embed it in a Python
module with appropriate code so it can be loaded into

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env python
"""
img2xpm.py -- convert several image formats to XPM