Merge recent wxPython changes from 2.8 branch to HEAD

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@46675 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2007-06-23 20:50:39 +00:00
parent e31f4da5f0
commit fe45b493dc
50 changed files with 7989 additions and 2997 deletions

View File

@@ -200,6 +200,10 @@ WXDLLVER = '%d%d' % (VER_MAJOR, VER_MINOR)
WXPY_SRC = '.' # Assume we're in the source tree already, but allow the WXPY_SRC = '.' # Assume we're in the source tree already, but allow the
# user to change it, particularly for extension building. # user to change it, particularly for extension building.
ARCH = '' # If this is set, add an -arch XXX flag to cflags
# Only tested (and presumably, needed) for OS X universal
# binary builds created using lipo.
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@@ -271,7 +275,7 @@ for flag in [ 'BUILD_ACTIVEX', 'BUILD_DLLWIDGET',
# String options # String options
for option in ['WX_CONFIG', 'SYS_WX_CONFIG', 'WXDLLVER', 'BUILD_BASE', for option in ['WX_CONFIG', 'SYS_WX_CONFIG', 'WXDLLVER', 'BUILD_BASE',
'WXPORT', 'SWIG', 'CONTRIBS_INC', 'WXPY_SRC', 'FLAVOUR', 'WXPORT', 'SWIG', 'CONTRIBS_INC', 'WXPY_SRC', 'FLAVOUR',
'VER_FLAGS', 'VER_FLAGS', 'ARCH',
]: ]:
for x in range(len(sys.argv)): for x in range(len(sys.argv)):
if sys.argv[x].find(option) == 0: if sys.argv[x].find(option) == 0:
@@ -483,7 +487,10 @@ class wx_install_headers(distutils.command.install_headers.install_headers):
return return
root = self.root root = self.root
if root is None or WXPREFIX.startswith(root): #print "WXPREFIX is %s, root is %s" % (WXPREFIX, root)
# hack for universal builds, which append i386/ppc
# to the root
if root is None or WXPREFIX.startswith(os.path.dirname(root)):
root = '' root = ''
for header, location in headers: for header, location in headers:
install_dir = os.path.normpath(root + install_dir = os.path.normpath(root +
@@ -600,9 +607,9 @@ def adjustLFLAGS(lflags, libdirs, libs):
# remove any flags for universal binaries, we'll get those from # remove any flags for universal binaries, we'll get those from
# distutils instead # distutils instead
return [flag for flag in newLFLAGS return newLFLAGS #[flag for flag in newLFLAGS
if flag not in ['-isysroot', '-arch', 'ppc', 'i386'] and # if flag not in ['-isysroot', '-arch', 'ppc', 'i386'] and
not flag.startswith('/Developer') ] # not flag.startswith('/Developer') ]
@@ -789,6 +796,14 @@ elif os.name == 'posix':
GENDIR = 'mac' GENDIR = 'mac'
libs = ['stdc++'] libs = ['stdc++']
NO_SCRIPTS = 1 NO_SCRIPTS = 1
if not ARCH == "":
cflags.append("-arch")
cflags.append(ARCH)
lflags.append("-arch")
lflags.append(ARCH)
#if ARCH == "ppc":
# cflags.append("-isysroot")
# cflags.append("/Developer/SDKs/MacOSX10.3.9.sdk")
else: else:

View File

@@ -1442,7 +1442,10 @@ class wxPythonDemo(wx.Frame):
menu = wx.Menu() menu = wx.Menu()
findItem = wx.MenuItem(menu, -1, '&Find\tCtrl-F', 'Find in the Demo Code') findItem = wx.MenuItem(menu, -1, '&Find\tCtrl-F', 'Find in the Demo Code')
findItem.SetBitmap(images.catalog['find'].getBitmap()) findItem.SetBitmap(images.catalog['find'].getBitmap())
findNextItem = wx.MenuItem(menu, -1, 'Find &Next\tF3', 'Find Next') if 'wxMac' not in wx.PlatformInfo:
findNextItem = wx.MenuItem(menu, -1, 'Find &Next\tF3', 'Find Next')
else:
findNextItem = wx.MenuItem(menu, -1, 'Find &Next\tCtrl-G', 'Find Next')
findNextItem.SetBitmap(images.catalog['findnext'].getBitmap()) findNextItem.SetBitmap(images.catalog['findnext'].getBitmap())
menu.AppendItem(findItem) menu.AppendItem(findItem)
menu.AppendItem(findNextItem) menu.AppendItem(findNextItem)
@@ -1456,7 +1459,8 @@ class wxPythonDemo(wx.Frame):
'A tool that lets you browse the live widgets and sizers in an application') 'A tool that lets you browse the live widgets and sizers in an application')
inspToolItem.SetBitmap(images.catalog['inspect'].getBitmap()) inspToolItem.SetBitmap(images.catalog['inspect'].getBitmap())
menu.AppendItem(inspToolItem) menu.AppendItem(inspToolItem)
menu.AppendSeparator() if 'wxMac' not in wx.PlatformInfo:
menu.AppendSeparator()
helpItem = menu.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!') helpItem = menu.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
wx.App.SetMacAboutMenuItemId(helpItem.GetId()) wx.App.SetMacAboutMenuItemId(helpItem.GetId())

View File

@@ -176,15 +176,17 @@ class RichTextFrame(wx.Frame):
def OnFileOpen(self, evt): def OnFileOpen(self, evt):
# TODO: Use RichTextBuffer.GetExtWildcard to get the wildcard string # This gives us a string suitable for the file dialog based on
# the file handlers that are loaded
wildcard, types = rt.RichTextBuffer.GetExtWildcard(save=False)
dlg = wx.FileDialog(self, "Choose a filename", dlg = wx.FileDialog(self, "Choose a filename",
wildcard="All files (*.*)|*.*", wildcard=wildcard,
style=wx.OPEN) style=wx.OPEN)
if dlg.ShowModal() == wx.ID_OK: if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath() path = dlg.GetPath()
if path: if path:
# TODO: use the filter index to determine what file type to use fileType = types[dlg.GetFilterIndex()]
self.rtc.LoadFile(path, rt.RICHTEXT_TYPE_TEXT) self.rtc.LoadFile(path, fileType)
dlg.Destroy() dlg.Destroy()
@@ -194,19 +196,52 @@ class RichTextFrame(wx.Frame):
return return
self.rtc.SaveFile() self.rtc.SaveFile()
def OnFileSaveAs(self, evt): def OnFileSaveAs(self, evt):
# TODO: Use RichTextBuffer.GetExtWildcard to get the wildcard string wildcard, types = rt.RichTextBuffer.GetExtWildcard(save=True)
dlg = wx.FileDialog(self, "Choose a filename", dlg = wx.FileDialog(self, "Choose a filename",
wildcard="All files (*.*)|*.*", wildcard=wildcard,
style=wx.SAVE) style=wx.SAVE)
if dlg.ShowModal() == wx.ID_OK: if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath() path = dlg.GetPath()
if path: if path:
self.rtc.SaveFile(path) fileType = types[dlg.GetFilterIndex()]
ext = rt.RichTextBuffer.FindHandlerByType(fileType).GetExtension()
if not path.endswith(ext):
path += '.' + ext
self.rtc.SaveFile(path, fileType)
dlg.Destroy() dlg.Destroy()
def OnFileViewHTML(self, evt): pass def OnFileViewHTML(self, evt):
# Get an instance of the html file handler, use it to save the
# document to a StringIO stream, and then display the
# resulting html text in a dialog with a HtmlWindow.
handler = rt.RichTextHTMLHandler()
handler.SetFlags(rt.RICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY)
handler.SetFontSizeMapping([7,9,11,12,14,22,100])
import cStringIO
stream = cStringIO.StringIO()
if not handler.SaveStream(self.rtc.GetBuffer(), stream):
return
import wx.html
dlg = wx.Dialog(self, title="HTML", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
html = wx.html.HtmlWindow(dlg, size=(500,400), style=wx.BORDER_SUNKEN)
html.SetPage(stream.getvalue())
btn = wx.Button(dlg, wx.ID_CANCEL)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(html, 1, wx.ALL|wx.EXPAND, 5)
sizer.Add(btn, 0, wx.ALL|wx.CENTER, 10)
dlg.SetSizer(sizer)
sizer.Fit(dlg)
dlg.ShowModal()
handler.DeleteTemporaryImages()
def OnFileExit(self, evt): def OnFileExit(self, evt):
@@ -533,6 +568,7 @@ class RichTextFrame(wx.Frame):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
class TestPanel(wx.Panel): class TestPanel(wx.Panel):
def __init__(self, parent, log): def __init__(self, parent, log):
self.log = log self.log = log
@@ -541,6 +577,30 @@ class TestPanel(wx.Panel):
b = wx.Button(self, -1, "Show the RichTextCtrl sample", (50,50)) b = wx.Button(self, -1, "Show the RichTextCtrl sample", (50,50))
self.Bind(wx.EVT_BUTTON, self.OnButton, b) self.Bind(wx.EVT_BUTTON, self.OnButton, b)
self.AddRTCHandlers()
def AddRTCHandlers(self):
# make sure we haven't already added them.
if rt.RichTextBuffer.FindHandlerByType(rt.RICHTEXT_TYPE_HTML) is not None:
return
# This would normally go in your app's OnInit method. I'm
# not sure why these file handlers are not loaded by
# default by the C++ richtext code, I guess it's so you
# can change the name or extension if you wanted...
rt.RichTextBuffer.AddHandler(rt.RichTextHTMLHandler())
rt.RichTextBuffer.AddHandler(rt.RichTextXMLHandler())
# ...like this
rt.RichTextBuffer.AddHandler(rt.RichTextXMLHandler(name="Other XML",
ext="ox",
type=99))
# This is needed for the view as HTML option since we tell it
# to store the images in the memory file system.
wx.FileSystem.AddHandler(wx.MemoryFSHandler())
def OnButton(self, evt): def OnButton(self, evt):
win = RichTextFrame(self, -1, "wx.richtext.RichTextCtrl", win = RichTextFrame(self, -1, "wx.richtext.RichTextCtrl",
@@ -548,10 +608,12 @@ class TestPanel(wx.Panel):
style = wx.DEFAULT_FRAME_STYLE) style = wx.DEFAULT_FRAME_STYLE)
win.Show(True) win.Show(True)
# give easy access to PyShell if it's running # give easy access to the demo's PyShell if it's running
self.rtfrm = win self.rtfrm = win
self.rtc = win.rtc self.rtc = win.rtc
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def runTest(frame, nb, log): def runTest(frame, nb, log):

View File

@@ -9,6 +9,7 @@ class TestPanel(wx.Panel):
wx.Panel.__init__(self, parent, -1) wx.Panel.__init__(self, parent, -1)
sizer = wx.FlexGridSizer(0, 3, 5, 5) sizer = wx.FlexGridSizer(0, 3, 5, 5)
sizer.AddGrowableCol(1)
box = wx.BoxSizer(wx.VERTICAL) box = wx.BoxSizer(wx.VERTICAL)
fs = self.GetFont().GetPointSize() fs = self.GetFont().GetPointSize()
bf = wx.Font(fs+4, wx.SWISS, wx.NORMAL, wx.BOLD) bf = wx.Font(fs+4, wx.SWISS, wx.NORMAL, wx.BOLD)
@@ -38,7 +39,7 @@ class TestPanel(wx.Panel):
0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL) 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
sizer.Add(wx.TextCtrl(self, -1, func(*args), sizer.Add(wx.TextCtrl(self, -1, func(*args),
size=(275,-1), style=wx.TE_READONLY), size=(275,-1), style=wx.TE_READONLY),
0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL) 0, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL)
btn = wx.Button(self, wx.ID_HELP) btn = wx.Button(self, wx.ID_HELP)
sizer.Add(btn) sizer.Add(btn)
@@ -64,7 +65,8 @@ class TestPanel(wx.Panel):
wx.StandardPaths.ResourceCat_Messages ) wx.StandardPaths.ResourceCat_Messages )
self.Bind(wx.EVT_BUTTON, self.OnShowDoc, id=wx.ID_HELP) self.Bind(wx.EVT_BUTTON, self.OnShowDoc, id=wx.ID_HELP)
box.Add(sizer, 0, wx.CENTER|wx.ALL, 10)
box.Add(sizer, 0, wx.CENTER|wx.EXPAND|wx.ALL, 20)
self.SetSizer(box) self.SetSizer(box)

View File

@@ -211,10 +211,13 @@ class TestPanel(wx.Panel):
def OnButton(self, evt): def OnButton(self, evt):
win = TestFrame(self, self.log) self.win = TestFrame(self, self.log)
win.Show(True) self.win.Show(True)
def ShutdownDemo(self):
self.win.Close()
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View File

@@ -5,7 +5,7 @@ debug=no
reswig=no reswig=no
all=no all=no
if [ "$1" = "all" ]; then if [ "$1" = all ]; then
all=yes all=yes
else else
PY_VERSION=$1 PY_VERSION=$1
@@ -99,7 +99,7 @@ if [ "$OSTYPE" = "cygwin" ]; then
$WXWIN/wxPython/distrib/makedemo $WXWIN/wxPython/distrib/makedemo
$TOOLS/Python$PY_VERSION/python `cygpath -d $WXWIN/wxPython/distrib/make_installer_inno4.py` $UNICODE_FLAG $TOOLS/Python$PY_VERSION/python `cygpath -d $WXWIN/wxPython/distrib/make_installer_inno4.py` $UNICODE_FLAG
elif [ "$OSTYPE" = "darwin" ]; then elif [ "${OSTYPE:0:6}" = "darwin" ]; then
OSX_VERSION=`sw_vers -productVersion` OSX_VERSION=`sw_vers -productVersion`
echo "OS X Version: ${OSX_VERSION:0:4}" echo "OS X Version: ${OSX_VERSION:0:4}"
cd $WXWIN/wxPython cd $WXWIN/wxPython

View File

@@ -276,7 +276,10 @@ if [ $skipbuild != yes ]; then
export WXROOT export WXROOT
export BUILDPREFIX=$PREFIX export BUILDPREFIX=$PREFIX
export INSTALLDIR=$INSTALLROOT$PREFIX export INSTALLDIR=$INSTALLROOT$PREFIX
$WXDIR/distrib/scripts/mac/macbuild wxpython universal $CHARTYPE $WXDIR/distrib/scripts/mac/macbuild-lipo wxpython $CHARTYPE
if [ $? != 0 ]; then
exit $?
fi
else else
make $MAKEJOBS make $MAKEJOBS
make $MAKEJOBS -C contrib/src/gizmos make $MAKEJOBS -C contrib/src/gizmos
@@ -289,20 +292,60 @@ if [ $skipbuild != yes ]; then
fi fi
# Build wxPython # Build wxPython
if [ $universal = yes ]; then
# build ppc, then i386, then lipo them together
ARCH=ppc
export CXX="g++-3.3 -DMAC_OS_X_VERSION_MAX_ALLOWED=1030"
export CC="gcc-3.3 -DMAC_OS_X_VERSION_MAX_ALLOWED=1030"
export MACOSX_DEPLOYMENT_TARGET=10.3
mkdir -p $INSTALLROOT/$ARCH
mkdir -p $WXBLD/$ARCH
echo "Building wxPython for PPC..."
cd $WXROOT/wxPython
$PYTHON setup.py \
UNICODE=$PYUNICODEOPT \
NO_SCRIPTS=1 \
EP_ADD_OPTS=1 \
WX_CONFIG="$INSTALLROOT/$PREFIX/bin/wx-config --prefix=$INSTALLROOT$PREFIX" \
BUILD_BASE=$WXBLD/$ARCH/wxPython \
ARCH="$ARCH" \
build
ARCH=i386
export CXX="g++-4.0 -arch i386"
export CC="gcc-4.0 -arch i386"
export MACOSX_DEPLOYMENT_TARGET=10.4
mkdir -p $INSTALLROOT/$ARCH
mkdir -p $WXBLD/$ARCH
echo "Building wxPython for Intel..."
cd $WXROOT/wxPython cd $WXROOT/wxPython
$PYTHON setup.py \ $PYTHON setup.py \
UNICODE=$PYUNICODEOPT \ UNICODE=$PYUNICODEOPT \
NO_SCRIPTS=1 \ NO_SCRIPTS=1 \
EP_ADD_OPTS=1 \ EP_ADD_OPTS=1 \
WX_CONFIG="$INSTALLROOT/$PREFIX/bin/wx-config --prefix=$INSTALLROOT$PREFIX" \
BUILD_BASE=$WXBLD/$ARCH/wxPython \
ARCH="$ARCH" \
build
else
cd $WXROOT/wxPython
$PYTHON setup.py \
UNICODE=$PYUNICODEOPT \
NO_SCRIPTS=1 \
EP_ADD_OPTS=1 \
WX_CONFIG="$WXBLD_CONFIG --inplace" \ WX_CONFIG="$WXBLD_CONFIG --inplace" \
BUILD_BASE=$WXBLD/wxPython \ BUILD_BASE=$WXBLD/wxPython \
SWIG=$SWIGBIN \ SWIG=$SWIGBIN \
USE_SWIG=$SWIGIT \ USE_SWIG=$SWIGIT \
build build
fi
fi fi
#---------------------------------------------------------------------- #----------------------------------------------------------------------
if [ $skipinstall != yes ]; then if [ $skipinstall != yes ]; then
# Install wxWidgets # Install wxWidgets
cd $WXBLD cd $WXBLD
@@ -317,17 +360,51 @@ if [ $skipinstall != yes ]; then
rm wx-config rm wx-config
ln -s ../lib/wx/config/* wx-config ln -s ../lib/wx/config/* wx-config
# and wxPython if [ $universal == yes ]; then
ARCH=ppc
export CXX="g++-3.3 -DMAC_OS_X_VERSION_MAX_ALLOWED=1030"
export CC="gcc-3.3 -DMAC_OS_X_VERSION_MAX_ALLOWED=1030"
export MACOSX_DEPLOYMENT_TARGET=10.3
cd $WXROOT/wxPython cd $WXROOT/wxPython
$PYTHON setup.py \ $PYTHON setup.py \
UNICODE=$PYUNICODEOPT \ UNICODE=$PYUNICODEOPT \
NO_SCRIPTS=1 \ NO_SCRIPTS=1 \
EP_ADD_OPTS=1 \ EP_ADD_OPTS=1 \
WX_CONFIG="$INSTALLROOT$PREFIX/bin/wx-config --prefix=$INSTALLROOT$PREFIX" \ WX_CONFIG="$INSTALLROOT$PREFIX/bin/wx-config --prefix=$INSTALLROOT$PREFIX" \
BUILD_BASE=$WXBLD/$ARCH/wxPython \
install \
--root=$INSTALLROOT/$ARCH
ARCH=i386
export CXX="g++-4.0 -arch i386"
export CC="gcc-4.0 -arch i386"
export MACOSX_DEPLOYMENT_TARGET=10.4
cd $WXROOT/wxPython
$PYTHON setup.py \
UNICODE=$PYUNICODEOPT \
NO_SCRIPTS=1 \
EP_ADD_OPTS=1 \
WX_CONFIG="$INSTALLROOT$PREFIX/bin/wx-config --prefix=$INSTALLROOT$PREFIX" \
BUILD_BASE=$WXBLD/$ARCH/wxPython \
install \
--root=$INSTALLROOT/$ARCH
echo "Lipoing $INSTALLROOT/ppc and $INSTALLROOT/i386..."
$PYTHON $WXROOT/distrib/scripts/mac/lipo-dir.py $INSTALLROOT/ppc $INSTALLROOT/i386 $INSTALLROOT
rm -rf $INSTALLROOT/ppc $INSTALLROOT/i386
else
cd $WXROOT/wxPython
$PYTHON setup.py \
UNICODE=$PYUNICODEOPT \
NO_SCRIPTS=1 \
EP_ADD_OPTS=1 \
WX_CONFIG="$INSTALLROOT$PREFIX/bin/wx-config --prefix=$INSTALLROOT$PREFIX" \
BUILD_BASE=$WXBLD/wxPython \ BUILD_BASE=$WXBLD/wxPython \
install \ install \
--root=$INSTALLROOT --root=$INSTALLROOT
fi
# Apple's Python Framework (such as what comes with Panther) # Apple's Python Framework (such as what comes with Panther)
# sym-links the site-packages dir in the framework to # sym-links the site-packages dir in the framework to

View File

@@ -14,7 +14,7 @@
#define __PYISTREAM__ #define __PYISTREAM__
//---------------------------------------------------------------------- //---------------------------------------------------------------------------
// Handling of wxInputStreams by Joerg Baumann // Handling of wxInputStreams by Joerg Baumann
// See stream.i for implementations // See stream.i for implementations
@@ -34,19 +34,22 @@ public:
void close(); void close();
void flush(); void flush();
bool eof(); bool eof();
PyObject* read(int size=-1);
PyObject* readline(int size=-1);
PyObject* readlines(int sizehint=-1);
void seek(int offset, int whence=0); void seek(int offset, int whence=0);
int tell(); int tell();
/* do these later? PyObject* read(int size=-1);
bool isatty(); PyObject* readline(int size=-1);
int fileno(); PyObject* readlines(int sizehint=-1);
void truncate(int size=-1);
void write(wxString data); // do these later?
void writelines(wxStringPtrList); //bool isatty();
*/ //int fileno();
//void truncate(int size=-1);
//PyObject* next();
// It's an input stream, can't write to it.
//void write(wxString data);
//void writelines(wxStringPtrList);
// wxInputStream methods that may come in handy... // wxInputStream methods that may come in handy...
@@ -86,14 +89,82 @@ protected:
virtual wxFileOffset OnSysSeek(wxFileOffset off, wxSeekMode mode); virtual wxFileOffset OnSysSeek(wxFileOffset off, wxSeekMode mode);
virtual wxFileOffset OnSysTell() const; virtual wxFileOffset OnSysTell() const;
// helper
static PyObject* getMethod(PyObject* py, char* name);
PyObject* m_read; PyObject* m_read;
PyObject* m_seek; PyObject* m_seek;
PyObject* m_tell; PyObject* m_tell;
bool m_block; bool m_block;
}; };
//---------------------------------------------------------------------- //---------------------------------------------------------------------------
// C++ class wxPyOutputStream to act as base for python class wxOutputStream
// You can use it in python like a python file object.
class wxPyOutputStream {
public:
// underlying wxOutputStream
wxOutputStream* m_wxos;
public:
wxPyOutputStream(wxOutputStream* wxos) : m_wxos(wxos) {}
~wxPyOutputStream();
void close();
void flush();
bool eof();
void seek(int offset, int whence=0);
int tell();
// it's an output stream, can't read from it.
//PyObject* read(int size=-1);
//PyObject* readline(int size=-1);
//PyObject* readlines(int sizehint=-1);
// do these later?
//bool isatty();
//int fileno();
//void truncate(int size=-1);
void write(PyObject* data);
//void writelines(wxStringArray& arr);
// wxOutputStream methods that may come in handy...
void PutC(char c) { if (m_wxos) m_wxos->PutC(c); }
size_t LastWrite() { if (m_wxos) return m_wxos->LastWrite(); }
unsigned long SeekO(unsigned long pos, wxSeekMode mode = wxFromStart)
{ if (m_wxos) return m_wxos->SeekO(pos, mode); else return 0; }
unsigned long TellO() { if (m_wxos) return m_wxos->TellO(); else return 0; }
};
// This is a wxOutputStream that wraps a Python file-like
// object and calls the Python methods as needed.
class wxPyCBOutputStream : public wxOutputStream {
public:
~wxPyCBOutputStream();
virtual wxFileOffset GetLength() const;
// factory function
static wxPyCBOutputStream* create(PyObject *py, bool block=true);
wxPyCBOutputStream(const wxPyCBOutputStream& other);
protected:
// can only be created via the factory
wxPyCBOutputStream(PyObject *w, PyObject *s, PyObject *t, bool block);
// wxStreamBase methods
virtual size_t OnSysRead(void *buffer, size_t bufsize);
virtual size_t OnSysWrite(const void *buffer, size_t bufsize);
virtual wxFileOffset OnSysSeek(wxFileOffset off, wxSeekMode mode);
virtual wxFileOffset OnSysTell() const;
PyObject* m_write;
PyObject* m_seek;
PyObject* m_tell;
bool m_block;
};
//---------------------------------------------------------------------------
#endif #endif

View File

@@ -124,6 +124,8 @@ inline wxPyCoreAPI* wxPyGetCoreAPIPtr()
#define wxRect2D_helper(a,b) (wxPyGetCoreAPIPtr()->p_wxRect2D_helper(a,b)) #define wxRect2D_helper(a,b) (wxPyGetCoreAPIPtr()->p_wxRect2D_helper(a,b))
#define wxPosition_helper(a,b) (wxPyGetCoreAPIPtr()->p_wxPosition_helper(a,b)) #define wxPosition_helper(a,b) (wxPyGetCoreAPIPtr()->p_wxPosition_helper(a,b))
#define wxPyCBOutputStream_create(a, b) (wxPyGetCoreAPIPtr()->p_wxPyCBOutputStream_create(a, b))
#define wxPyCBOutputStream_copy(a) (wxPyGetCoreAPIPtr()->p_wxPyCBOutputStream_copy(a))
//---------------------------------------------------------------------- //----------------------------------------------------------------------
#endif #endif

View File

@@ -353,6 +353,7 @@ class wxPyClientData;
class wxPyUserData; class wxPyUserData;
class wxPyOORClientData; class wxPyOORClientData;
class wxPyCBInputStream; class wxPyCBInputStream;
class wxPyCBOutputStream;
void wxPyClientData_dtor(wxPyClientData* self); void wxPyClientData_dtor(wxPyClientData* self);
void wxPyUserData_dtor(wxPyUserData* self); void wxPyUserData_dtor(wxPyUserData* self);
@@ -360,6 +361,9 @@ void wxPyOORClientData_dtor(wxPyOORClientData* self);
wxPyCBInputStream* wxPyCBInputStream_create(PyObject *py, bool block); wxPyCBInputStream* wxPyCBInputStream_create(PyObject *py, bool block);
wxPyCBInputStream* wxPyCBInputStream_copy(wxPyCBInputStream* other); wxPyCBInputStream* wxPyCBInputStream_copy(wxPyCBInputStream* other);
wxPyCBOutputStream* wxPyCBOutputStream_create(PyObject *py, bool block);
wxPyCBOutputStream* wxPyCBOutputStream_copy(wxPyCBOutputStream* other);
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Export a C API in a struct. Other modules will be able to load this from // Export a C API in a struct. Other modules will be able to load this from
// the wx.core module and will then have safe access to these functions, even if // the wx.core module and will then have safe access to these functions, even if
@@ -437,6 +441,8 @@ struct wxPyCoreAPI {
bool (*p_wxRect2D_helper)(PyObject* source, wxRect2D** obj); bool (*p_wxRect2D_helper)(PyObject* source, wxRect2D** obj);
bool (*p_wxPosition_helper)(PyObject* source, wxPosition** obj); bool (*p_wxPosition_helper)(PyObject* source, wxPosition** obj);
wxPyCBOutputStream* (*p_wxPyCBOutputStream_create)(PyObject *py, bool block);
wxPyCBOutputStream* (*p_wxPyCBOutputStream_copy)(wxPyCBOutputStream* other);
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -25,13 +25,18 @@ class TextDocument(wx.lib.docview.Document):
def SaveObject(self, fileObject): def SaveObject(self, fileObject):
view = self.GetFirstView() view = self.GetFirstView()
fileObject.write(view.GetTextCtrl().GetValue()) val = view.GetTextCtrl().GetValue()
if wx.USE_UNICODE:
val = val.encode('utf-8')
fileObject.write(val)
return True return True
def LoadObject(self, fileObject): def LoadObject(self, fileObject):
view = self.GetFirstView() view = self.GetFirstView()
data = fileObject.read() data = fileObject.read()
if wx.USE_UNICODE:
data = data.decode('utf-8')
view.GetTextCtrl().SetValue(data) view.GetTextCtrl().SetValue(data)
return True return True
@@ -93,7 +98,7 @@ class TextView(wx.lib.docview.View):
wordWrapStyle = wx.TE_WORDWRAP wordWrapStyle = wx.TE_WORDWRAP
else: else:
wordWrapStyle = wx.TE_DONTWRAP wordWrapStyle = wx.TE_DONTWRAP
textCtrl = wx.TextCtrl(parent, -1, pos = wx.DefaultPosition, size = parent.GetClientSize(), style = wx.TE_MULTILINE | wordWrapStyle) textCtrl = wx.TextCtrl(parent, -1, pos = wx.DefaultPosition, size = parent.GetClientSize(), style = wx.TE_MULTILINE | wx.TE_RICH | wordWrapStyle)
textCtrl.SetFont(font) textCtrl.SetFont(font)
textCtrl.SetForegroundColour(color) textCtrl.SetForegroundColour(color)
textCtrl.SetValue(value) textCtrl.SetValue(value)
@@ -521,7 +526,7 @@ class TextOptionsPanel(wx.Panel):
nativeFont.FromString(self._textFont.GetNativeFontInfoDesc()) nativeFont.FromString(self._textFont.GetNativeFontInfoDesc())
font = wx.NullFont font = wx.NullFont
font.SetNativeFontInfo(nativeFont) font.SetNativeFontInfo(nativeFont)
font.SetPointSize(self._sampleTextCtrl.GetFont().GetPointSize()) # Use the standard point size #font.SetPointSize(self._sampleTextCtrl.GetFont().GetPointSize()) # Use the standard point size
self._sampleTextCtrl.SetFont(font) self._sampleTextCtrl.SetFont(font)
self._sampleTextCtrl.SetForegroundColour(self._textColor) self._sampleTextCtrl.SetForegroundColour(self._textColor)
self._sampleTextCtrl.SetValue(_("%d pt. %s") % (self._textFont.GetPointSize(), self._textFont.GetFaceName())) self._sampleTextCtrl.SetValue(_("%d pt. %s") % (self._textFont.GetPointSize(), self._textFont.GetFaceName()))

View File

@@ -0,0 +1,372 @@
#----------------------------------------------------------------------------
# Name: clroses.py
# Purpose: Class definitions for Roses interactive display programs.
#
# Author: Ric Werme
# WWW: http://WermeNH.com/roses
#
# Created: June 2007
# CVS-ID: $Id$
# Copyright: Public Domain, please give credit where credit is due.
# License: Sorry, no EULA.
#----------------------------------------------------------------------------
# This is yet another incarnation of an old graphics hack based around
# misdrawing an analytic geometry curve called a rose. The basic form is
# simply the polar coordinate function r = cos(a * theta). "a" is the
# "order" of the rose, a zero value degenerates to r = 1, a circle. While
# this program is happy to draw that, much more interesting things happen when
# one or more of the following is in effect:
# 1) The "delta theta" between points is large enough to distort the curve,
# e.g. 90 degrees will draw a square, slightly less will be interesting.
# 2) The order of the rose is too large to draw it accurately.
# 3) Vectors are drawn at less than full speed.
# 4) The program is stepping through different patterns on its own.
# While you will be able to predict some aspects of the generated patterns,
# a lot of what there is to be found is found at random!
# The rose class has all the knowledge to implement generating vector data for
# roses and handles all the timing issues. It does not have the user interface
# for changing all the drawing parameters. It offers a "vision" of what an
# ideal Roses program should be, however, callers are welcome to assert their
# independence, override defaults, ignore features, etc.
from math import sin, cos, pi
# Rose class knows about:
# > Generating points and vectors (returning data as a list of points)
# > Starting a new rose (e.g. telling user to erase old vectors)
# > Stepping from one pattern to the next.
class rose:
"Defines everything needed for drawing a rose with timers."
# The following data is accessible by callers, but there are set
# methods for most everything and various method calls to client methods
# to display current values.
style = 100 # Angular distance along curve between points
sincr = -1 # Amount to increment style by in auto mode
petals = 2 # Lobes on the rose (even values have 2X lobes)
pincr = 1 # Amount to increment petals by in auto mode
nvec = 399 # Number of vectors to draw the rose
minvec = 0 # Minimum number acceptable in automatic mode
maxvec = 3600 # Maximum number acceptable in automatic mode
skipvec = 0 # Don't draw this many at the start (cheap animations)
drawvec = 3600 # Draw only this many (cheap animations)
step = 20 # Number of vectors to draw each clock tick
draw_delay = 50 # Time between roselet calls to watch pattern draw
wait_delay = 2000 # Time between roses in automatic mode
# Other variables that the application shouldn't access.
verbose = 0 # No good way to set this at the moment.
nextpt = 0 # Next position to draw on next clock tick
# Internal states:
INT_IDLE, INT_DRAW, INT_SEARCH, INT_WAIT, INT_RESIZE = range(5)
int_state = INT_IDLE
# Command states
CMD_STOP, CMD_GO = range(2)
cmd_state = CMD_STOP
# Return full rose line (a tuple of (x, y) tuples). Not used by interactive
# clients but still useful for command line and batch clients.
# This is the "purest" code and doesn't require the App* methods defined
# by the caller.
def rose(self, style, petals, vectors):
self.nvec = vectors
self.make_tables(vectors)
line = [(1.0, 0.0)]
for i in range (1, vectors):
theta = (style * i) % vectors
r = self.cos_table[(petals * theta) % vectors]
line.append((r * self.cos_table[theta], r * self.sin_table[theta]))
line.append((1.0, 0.0))
return line
# Generate vectors for the next chunk of rose.
# This is not meant to be called from an external module, as it is closely
# coupled to parameters set up within the class and limits set up by
# restart(). Restart() initializes all data this needs to start drawing a
# pattern, and clock() calls this to compute the next batch of points and
# hear if that is the last batch. We maintain all data we need to draw each
# batch after the first. theta should be 2.0*pi * style*i/self.nvec
# radians, but we deal in terms of the lookup table so it's just the index
# that refers to the same spot.
def roselet(self):
line = []
stop = self.nextpt + self.step
keep_running = True
if stop >= self.endpt:
stop = self.endpt
keep_running = False
for i in range (self.nextpt, stop + 1):
theta = (self.style * i) % self.nvec
r = self.cos_table[(self.petals * theta) % self.nvec]
line.append((r * self.cos_table[theta], r * self.sin_table[theta]))
self.nextpt = stop
return line, keep_running
# Generate sine and cosine lookup tables. We could create data for just
# 1/4 of a circle, at least if vectors was a multiple of 4, and share a
# table for both sine and cosine, but memory is cheaper than it was in
# PDP-11 days. OTOH, small, shared tables would be more cache friendly,
# but if we were that concerned, this would be in C.
def make_tables(self, vectors):
self.sin_table = [sin(2.0 * pi * i / vectors) for i in range(vectors)]
self.cos_table = [cos(2.0 * pi * i / vectors) for i in range(vectors)]
# Rescale (x,y) data to match our window. Note the negative scaling in the
# Y direction, this compensates for Y moving down the screen, but up on
# graph paper.
def rescale(self, line, offset, scale):
for i in range(len(line)):
line[i] = (line[i][0] * scale + offset[0],
line[i][1] * (-scale) + offset[1])
return line
# Euler's Method for computing the greatest common divisor. Knuth's
# "The Art of Computer Programming" vol.2 is the standard reference,
# but the web has several good ones too. Basically this sheds factors
# that aren't in the GCD and returns when there's nothing left to shed.
# N.B. Call with a >= b.
def gcd(self, a, b):
while b != 0:
a, b = b, a % b
return a
# Erase any old vectors and start drawing a new rose. When the program
# starts, the sine and cosine tables don't exist, build them here. (Of
# course, if an __init__() method is added, move the call there.
# If we're in automatic mode, check to see if the new pattern has neither
# too few or too many vectors and skip it if so. Skip by setting up for
# a one tick wait to let us get back to the main loop so the user can
# update parameters or stop.
def restart(self):
if self.verbose:
print 'restart: int_state', self.int_state, 'cmd_state', self.cmd_state
try:
tmp = self.sin_table[0]
except:
self.make_tables(self.nvec)
new_state = self.INT_DRAW
self.takesvec = self.nvec / self.gcd(self.nvec, self.style)
if not self.takesvec & 1 and self.petals & 1:
self.takesvec /= 2
if self.cmd_state == self.CMD_GO:
if self.minvec > self.takesvec or self.maxvec < self.takesvec:
new_state = self.INT_SEARCH
self.AppSetTakesVec(self.takesvec)
self.AppClear()
self.nextpt = self.skipvec
self.endpt = min(self.takesvec, self.skipvec + self.drawvec)
old_state, self.int_state = self.int_state, new_state
if old_state == self.INT_IDLE: # Clock not running
self.clock()
elif old_state == self.INT_WAIT: # May be long delay, restart
self.AppCancelTimer()
self.clock()
else:
return 1 # If called by clock(), return and start clock
return 0 # We're in INT_IDLE or INT_WAIT, clock running
# Called from App. Recompute the center and scale values for the subsequent pattern.
# Force us into INT_RESIZE state if not already there so that in 100 ms we'll start
# to draw something to give an idea of the new size.
def resize(self, size, delay):
xsize, ysize = size
self.center = (xsize / 2, ysize / 2)
self.scale = min(xsize, ysize) / 2.1
self.repaint(delay)
# Called from App or above. From App, called with small delay because
# some window managers will produce a flood of expose events or call us
# before initialization is done.
def repaint(self, delay):
if self.int_state != self.INT_RESIZE:
# print 'repaint after', delay
self.int_state = self.INT_RESIZE
self.AppCancelTimer()
self.AppAfter(delay, self.clock)
# Method that returns the next style and petal values for automatic
# mode and remembers them internally. Keep things scaled in the
# range [0:nvec) because there's little reason to exceed that.
def next(self):
self.style += self.sincr
self.petals += self.pincr
if self.style <= 0 or self.petals < 0:
self.style, self.petals = \
abs(self.petals) + 1, abs(self.style)
if self.style >= self.nvec:
self.style %= self.nvec # Don't bother defending against 0
if self.petals >= self.nvec:
self.petals %= self.nvec
self.AppSetParam(self.style, self.petals, self.nvec)
# Resume pattern drawing with the next one to display.
def resume(self):
self.next()
return self.restart()
# Go/Stop button.
def cmd_go_stop(self):
if self.cmd_state == self.CMD_STOP:
self.cmd_state = self.CMD_GO
self.resume() # Draw next pattern
elif self.cmd_state == self.CMD_GO:
self.cmd_state = self.CMD_STOP
self.update_labels()
# Centralize button naming to share with initialization.
# Leave colors to the application (assuming it cares), we can't guess
# what's available.
def update_labels(self):
if self.cmd_state == self.CMD_STOP:
self.AppCmdLabels(('Go', 'Redraw', 'Backward', 'Forward'))
else: # Must be in state CMD_GO
self.AppCmdLabels(('Stop', 'Redraw', 'Reverse', 'Skip'))
# Redraw/Redraw button
def cmd_redraw(self):
self.restart() # Redraw current pattern
# Backward/Reverse button
# Useful for when you see an interesting pattern and want
# to go back to it. If running, just change direction. If stopped, back
# up one step. The resume code handles the step, then we change the
# incrementers back to what they were. (Unless resume changed them too.)
def cmd_backward(self):
self.sincr = -self.sincr
self.pincr = -self.pincr
if self.cmd_state == self.CMD_STOP:
self.resume();
self.sincr = -self.sincr # Go forward again
self.pincr = -self.pincr
else:
self.AppSetIncrs(self.sincr, self.pincr)
# Forward/Skip button. CMD_STOP & CMD_GO both just call resume.
def cmd_step(self):
self.resume() # Draw next pattern
# Handler called on each timer event. This handles the metered drawing
# of a rose and the delays between them. It also registers for the next
# timer event unless we're idle (rose is done and the delay between
# roses is 0.)
def clock(self):
if self.int_state == self.INT_IDLE:
# print 'clock called in idle state'
delay = 0
elif self.int_state == self.INT_DRAW:
line, run = self.roselet()
self.AppCreateLine(self.rescale(line, self.center, self.scale))
if run:
delay = self.draw_delay
else:
if self.cmd_state == self.CMD_GO:
self.int_state = self.INT_WAIT
delay = self.wait_delay
else:
self.int_state = self.INT_IDLE
delay = 0
elif self.int_state == self.INT_SEARCH:
delay = self.resume() # May call us to start drawing
if self.int_state == self.INT_SEARCH:
delay = self.draw_delay # but not if searching.
elif self.int_state == self.INT_WAIT:
if self.cmd_state == self.CMD_GO:
delay = self.resume() # Calls us to start drawing
else:
self.int_state = self.INT_IDLE
delay = 0
elif self.int_state == self.INT_RESIZE: # Waiting for resize event stream to settle
self.AppSetParam(self.style, self.petals, self.nvec)
self.AppSetIncrs(self.sincr, self.pincr)
delay = self.restart() # Calls us to start drawing
if delay == 0:
if self.verbose:
print 'clock: going idle from state', self.int_state
else:
self.AppAfter(delay, self.clock)
# Methods to allow App to change the parameters on the screen.
# These expect to be called when the associated paramenter changes,
# but work reasonably well if several are called at once. (E.g.
# tkroses.py groups them into things that affect the visual display
# and warrant a new start, and things that just change and don't affect
# the ultimate pattern. All parameters within a group are updated
# at once even if the value hasn't changed.
# We restrict the style and petals parameters to the range [0: nvec)
# since numbers outside of that range aren't interesting. We don't
# immediately update the value in the application, we probably should.
# NW control window - key parameters
def SetStyle(self, value):
self.style = value % self.nvec
self.restart()
def SetSincr(self, value):
self.sincr = value
def SetPetals(self, value):
self.petals = value % self.nvec
self.restart()
def SetPincr(self, value):
self.pincr = value
# SW control window - vectors
def SetVectors(self, value):
self.nvec = value
self.style %= value
self.petals %= value
self.AppSetParam(self.style, self.petals, self.nvec)
self.make_tables(value)
self.restart()
def SetMinVec(self, value):
if self.maxvec >= value and self.nvec >= value:
self.minvec = value
def SetMaxVec(self, value):
if self.minvec < value:
self.maxvec = value
def SetSkipFirst(self, value):
self.skipvec = value
self.restart()
def SetDrawOnly(self, value):
self.drawvec = value
self.restart()
# SE control window - timings
def SetStep(self, value):
self.step = value
def SetDrawDelay(self, value):
self.draw_delay = value
def SetWaitDelay(self, value):
self.wait_delay = value
# Method for client to use to have us supply our defaults.
def SupplyControlValues(self):
self.update_labels()
self.AppSetParam(self.style, self.petals, self.nvec)
self.AppSetIncrs(self.sincr, self.pincr)
self.AppSetVectors(self.nvec, self.minvec, self.maxvec,
self.skipvec, self.drawvec)
self.AppSetTiming(self.step, self.draw_delay, self.wait_delay)

View File

@@ -0,0 +1,544 @@
#----------------------------------------------------------------------------
# Name: wxroses.py
# Purpose: wxPython GUI using clroses.py to display a classic graphics
# hack.
#
# Author: Ric Werme, Robin Dunn.
# WWW: http://WermeNH.com/roses
#
# Created: June 2007
# CVS-ID: $Id$
# Copyright: Public Domain, please give credit where credit is due.
# License: Sorry, no EULA.
#----------------------------------------------------------------------------
# This module is responsible for everything involving GUI usage
# as clroses knows nothing about wxpython, tkintr, etc.
# There are some notes about how the Roses algorithm works in clroses.py,
# but the best reference should be at http://WermeNH.com/roses/index.html .
# There are a number of enhancements that could be done to wxRoses, and
# contributions are welcome as long as you don't destory the general
# structure, flavor, and all that. The following list is in the order
# I'd like to see done. Some are easy, some aren't, some are easy if
# you have experience in the right parts of external code.
# Brighter crossing points.
# Where many vectors cross, the display becomes washed out as a solid shape
# of light. On (antique) refresh vector graphics systems, crossing points
# are brighter because the electron beam paints the pixels multiple times.
# This gives complex patterns a lacy feel to some, and a 3-D sense to
# fluted shapes where vectors lie tangent to some curve. It would be
# nice to do the same in a bitmap buffer, the code to draw a vector is
# pretty simple, adding something that adds brightness to it via math or
# a lookup table ought to be a simple addition.
# Monochrome is so 20th century.
# There are a number of things that could be done with color. The simplest
# is to step through colors in a color list, better things to do would be
# for clroses.py to determine the length of an interesting "generator pattern,"
# e.g. the square in the opening display. Then it could change colors either
# every four vectors or cycle through the first four colors in the list.
# Bookmark that Rose!
# As you play with wxRoses, you'll come across some patterns that are
# "keepers." A bookmark mechanism would be handy.
# Save that Rose!
# It would be nice to have a Menu-bar/File/Save-as dialog to save a pattern
# as a jpg/png/gif file.
# Themes
# A pulldown option to select various themes is worthwhile. E.g.:
# Start an interesting animation,
# Select complex, lacy Roses,
# Select the author's favorites,
# Return to the initial Rose.
# Actually, all that's necessary are some pre-loaded bookmarks.
# Help text
# Standard fare, or:
# Slide show
# At CMU I created an interactive slide show that walked people through
# all the options and made suggestions about how to choose Style and Petal.
# I forget exactly what I said and may not have listings for it. At any rate,
# making the help mechanism start one of several "lessons" where it could
# control the display (without blocking the user's control) would be pretty
# straightforward.
import wx
import clroses
import wx.lib.colourselect as cs
# Class SpinPanel creates a control that includes both a StaticText widget
# which holds the the name of a parameter and a SpinCtrl widget which
# displays the current value. Values are set at initialization and can
# change via the SpinCtrl widget or by the program. So that the program
# can easily access the SpinCtrl, the SpinPanel handles are saved in the
# spin_panels dictionary.
class SpinPanel(wx.Panel):
def __init__(self, parent, name, min_value, value, max_value, callback):
wx.Panel.__init__(self, parent, -1)
if "wxMac" in wx.PlatformInfo:
self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
self.st = wx.StaticText(self, -1, name)
self.sc = wx.SpinCtrl(self, -1, "", size = (70, -1))
self.sc.SetRange(min_value, max_value)
self.sc.SetValue(value)
self.sc.Bind(wx.EVT_SPINCTRL, self.OnSpin)
self.callback = callback
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.st, 0, wx.ALIGN_CENTER_VERTICAL)
sizer.Add((1,1), 1)
sizer.Add(self.sc)
self.SetSizer(sizer)
global spin_panels
spin_panels[name] = self
# Called (generally through spin_panels{}) to set the SpinCtrl value.
def SetValue(self, value):
self.sc.SetValue(value)
# Called when user changes the SpinCtrl value.
def OnSpin(self, event):
name = self.st.GetLabel()
value = self.sc.GetValue()
if verbose:
print 'OnSpin', name, '=', value
self.callback(name, value) # Call MyFrame.OnSpinback to call clroses
# This class is used to display the current rose diagram. It keeps a
# buffer bitmap of the current display, which it uses to refresh the
# screen with when needed. When it is told to draw some lines it does
# so to the buffer in order for it to always be up to date.
class RosePanel(wx.Panel):
def __init__(self, *args, **kw):
wx.Panel.__init__(self, *args, **kw)
self.InitBuffer()
self.resizeNeeded = False
self.useGCDC = False
self.useBuffer = True
# set default colors
self.SetBackgroundColour((51, 51, 51)) # gray20
self.SetForegroundColour((164, 211, 238)) # lightskyblue2
# connect the size and paint events to handlers
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_IDLE, self.OnIdle)
def InitBuffer(self):
size = self.GetClientSize()
self.buffer = wx.EmptyBitmap(max(1, size.width),
max(1, size.height))
def Clear(self):
dc = self.useBuffer and wx.MemoryDC(self.buffer) or wx.ClientDC(self)
dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
dc.Clear()
if self.useBuffer:
self.Refresh(False)
def DrawLines(self, lines):
if len(lines) <= 1:
return
dc = self.useBuffer and wx.MemoryDC(self.buffer) or wx.ClientDC(self)
if self.useGCDC:
dc = wx.GCDC(dc)
dc.SetPen(wx.Pen(self.GetForegroundColour(), 1))
dc.DrawLines(lines)
if self.useBuffer:
self.Refresh(False)
def TriggerResize(self):
self.GetParent().TriggerResize(self.buffer.GetSize())
def TriggerRedraw(self):
self.GetParent().TriggerRedraw()
def OnSize(self, evt):
self.resizeNeeded = True
def OnIdle(self, evt):
if self.resizeNeeded:
self.InitBuffer()
self.TriggerResize()
if self.useBuffer:
self.Refresh()
self.resizeNeeded = False
def OnPaint(self, evt):
dc = wx.PaintDC(self)
if self.useBuffer:
dc.DrawBitmap(self.buffer, 0,0)
else:
self.TriggerRedraw()
# A panel used to collect options on how the rose is drawn
class OptionsPanel(wx.Panel):
def __init__(self, parent, rose):
wx.Panel.__init__(self, parent)
self.rose = rose
sizer = wx.StaticBoxSizer(wx.StaticBox(self, label='Options'),
wx.VERTICAL)
self.useGCDC = wx.CheckBox(self, label="Use GCDC")
sizer.Add(self.useGCDC, 0, wx.BOTTOM|wx.LEFT, 2)
self.useBuffer = wx.CheckBox(self, label="Use buffering")
sizer.Add(self.useBuffer, 0, wx.BOTTOM|wx.LEFT, 2)
def makeCButton(label):
btn = cs.ColourSelect(self, size=(20,22))
lbl = wx.StaticText(self, -1, label)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(btn)
sizer.Add((4,4))
sizer.Add(lbl, 0, wx.ALIGN_CENTER_VERTICAL)
return sizer, btn
s, self.fg = makeCButton('Foreground')
sizer.Add(s)
s, self.bg = makeCButton('Background')
sizer.Add(s)
self.SetSizer(sizer)
self.Bind(wx.EVT_CHECKBOX, self.OnUseGCDC, self.useGCDC)
self.Bind(wx.EVT_CHECKBOX, self.OnUseBuffer, self.useBuffer)
self.Bind(wx.EVT_IDLE, self.OnIdle)
self.Bind(cs.EVT_COLOURSELECT, self.OnSetFG, self.fg)
self.Bind(cs.EVT_COLOURSELECT, self.OnSetBG, self.bg)
def OnIdle(self, evt):
if self.useGCDC.GetValue() != self.rose.useGCDC:
self.useGCDC.SetValue(self.rose.useGCDC)
if self.useBuffer.GetValue() != self.rose.useBuffer:
self.useBuffer.SetValue(self.rose.useBuffer)
if self.fg.GetValue() != self.rose.GetForegroundColour():
self.fg.SetValue(self.rose.GetForegroundColour())
if self.bg.GetValue() != self.rose.GetBackgroundColour():
self.bg.SetValue(self.rose.GetBackgroundColour())
def OnUseGCDC(self, evt):
self.rose.useGCDC = evt.IsChecked()
self.rose.TriggerRedraw()
def OnUseBuffer(self, evt):
self.rose.useBuffer = evt.IsChecked()
self.rose.TriggerRedraw()
def OnSetFG(self, evt):
self.rose.SetForegroundColour(evt.GetValue())
self.rose.TriggerRedraw()
def OnSetBG(self, evt):
self.rose.SetBackgroundColour(evt.GetValue())
self.rose.TriggerRedraw()
# MyFrame is the traditional class name to create and populate the
# application's frame. The general GUI has control/status panels on
# the right side and a panel on the left side that draws the rose
#
# This class also derives from clroses.rose so it can implement the
# required interfaces to connect the GUI to the rose engine.
class MyFrame(wx.Frame, clroses.rose):
# Color matching dictionary, convert label name to color:
# Stop and Go ala traffic lights,
# Skip and Forward look ahead to the purple mountain majesties (really bluish),
# Reverse and Backward look morosely behind to maroon memories,
# Redraw looks at the brown earth right below your feet.
# Yeah, so it's lame. All I really wanted was to color Stop and Go.
labelColours = {
'Go': 'dark green', 'Stop': 'red',
'Redraw': 'brown', 'Skip': 'dark slate blue',
'Backward': 'maroon', 'Forward': 'dark slate blue', 'Reverse': 'maroon'
}
def __init__(self):
def makeSP(name, labels, statictexts = None):
panel = wx.Panel(self.side_panel, -1)
box = wx.StaticBox(panel, -1, name)
sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
for name, min_value, value, max_value in labels:
sp = SpinPanel(panel, name, min_value, value, max_value, self.OnSpinback)
sizer.Add(sp, 0, wx.EXPAND)
if statictexts:
for name, text in statictexts:
st = wx.StaticText(panel, -1, text)
spin_panels[name] = st # Supposed to be a SpinPanel....
sizer.Add(st, 0, wx.EXPAND)
panel.SetSizer(sizer)
return panel
wx.Frame.__init__(self, None, title="Roses in wxPython")
self.rose_panel = RosePanel(self)
self.side_panel = wx.Panel(self)
# The cmd panel is four buttons whose names and foreground colors
# change. Plop them in a StaticBox like the SpinPanels. Use
# a 2x2 grid, but StaticBoxSizer can't handle that. Therefore,
# create a sub panel, layout the buttons there, then give that to
# a higher panel that has the static box stuff.
self.cmd_panel = wx.Panel(self.side_panel, -1)
self.sub_panel = wx.Panel(self.cmd_panel, -1)
sizer = wx.GridSizer(rows = 2, cols = 2)
global ctrl_buttons
border = 'wxMac' in wx.PlatformInfo and 3 or 1
for name, handler in (
('Go', self.OnGoStop),
('Redraw', self.OnRedraw),
('Backward', self.OnBackward),
('Forward', self.OnForward)):
button = wx.Button(self.sub_panel, -1, name)
button.SetForegroundColour(self.labelColours[name])
ctrl_buttons[name] = button
button.Bind(wx.EVT_BUTTON, handler)
sizer.Add(button, 0, wx.EXPAND|wx.ALL, border)
self.sub_panel.SetSizer(sizer)
# Set up cmd_panel with StaticBox stuff
box = wx.StaticBox(self.cmd_panel, -1, 'Command')
sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
sizer.Add(self.sub_panel)
self.cmd_panel.SetSizer(sizer)
# Now make the rest of the control panels...
# The order of creation of SpinCtrls and Buttons is the order that
# the tab key will step through, so the order of panel creation is
# important.
# In the SpinPanel data (name, min, value, max), value will be
# overridden by clroses.py defaults.
self.coe_panel = makeSP('Coefficient',
(('Style', 0, 100, 3600),
('Sincr', -3600, -1, 3600),
('Petal', 0, 2, 3600),
('Pincr', -3600, 1, 3600)))
self.vec_panel = makeSP('Vector',
(('Vectors' , 1, 399, 3600),
('Minimum' , 1, 1, 3600),
('Maximum' , 1, 3600, 3600),
('Skip first', 0, 0, 3600),
('Draw only' , 1, 3600, 3600)),
(('Takes', 'Takes 0000 vectors'), ))
self.tim_panel = makeSP('Timing',
(('Vec/tick' , 1, 20, 3600),
('msec/tick', 1, 50, 1000),
('Delay' , 1, 2000, 9999)))
self.opt_panel = OptionsPanel(self.side_panel, self.rose_panel)
# put them all on in a sizer attached to the side_panel
panelSizer = wx.BoxSizer(wx.VERTICAL)
panelSizer.Add(self.cmd_panel, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)
panelSizer.Add(self.coe_panel, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)
panelSizer.Add(self.vec_panel, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)
panelSizer.Add(self.tim_panel, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)
panelSizer.Add(self.opt_panel, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)
self.side_panel.SetSizer(panelSizer)
# and now arrange the two main panels in another sizer for the frame
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
mainSizer.Add(self.rose_panel, 1, wx.EXPAND)
mainSizer.Add(self.side_panel, 0, wx.EXPAND)
self.SetSizer(mainSizer)
# bind event handlers
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
# Determine appropriate image size.
# At this point, the rose_panel and side_panel will both report
# size (20, 20). After mainSizer.Fit(self) they will report the
# same, but the Frame size, self.GetSize(), will report the desired
# side panel dimensions plus an extra 20 on the width. That lets
# us determine the frame size that will display the side panel and
# a square space for the diagram. Only after Show() will the two
# panels report the accurate sizes.
mainSizer.Fit(self)
rw, rh = self.rose_panel.GetSize()
sw, sh = self.side_panel.GetSize()
fw, fh = self.GetSize()
h = max(600, fh) # Change 600 to desired minimum size
w = h + fw - rw
if verbose:
print 'rose panel size', (rw, rh)
print 'side panel size', (sw, sh)
print ' frame size', (fw, fh)
print 'Want size', (w,h)
self.SetSize((w, h))
self.SupplyControlValues() # Ask clroses to tell us all the defaults
self.Show()
# Command button event handlers. These are relabled when changing between auto
# and manual modes. They simply reflect the call to a method in the base class.
#
# Go/Stop button
def OnGoStop(self, event):
if verbose:
print 'OnGoStop'
self.cmd_go_stop()
# Redraw/Redraw
def OnRedraw(self, event):
if verbose:
print 'OnRedraw'
self.cmd_redraw()
# Backward/Reverse
def OnBackward(self, event):
if verbose:
print 'OnBackward'
self.cmd_backward()
# Forward/Skip
def OnForward(self, event):
if verbose:
print 'OnForward'
self.cmd_step()
# The clroses.roses class expects to have methods available that
# implement the missing parts of the functionality needed to do
# the actual work of getting the diagram to the screen and etc.
# Those are implemented here as the App* methods.
def AppClear(self):
if verbose:
print 'AppClear: clear screen'
self.rose_panel.Clear()
def AppCreateLine(self, line):
# print 'AppCreateLine, len', len(line), 'next', self.nextpt
self.rose_panel.DrawLines(line)
# Here when clroses has set a new style and/or petal value, update
# strings on display.
def AppSetParam(self, style, petals, vectors):
spin_panels['Style'].SetValue(style)
spin_panels['Petal'].SetValue(petals)
spin_panels['Vectors'].SetValue(vectors)
def AppSetIncrs(self, sincr, pincr):
spin_panels['Sincr'].SetValue(sincr)
spin_panels['Pincr'].SetValue(pincr)
def AppSetVectors(self, vectors, minvec, maxvec, skipvec, drawvec):
spin_panels['Vectors'].SetValue(vectors)
spin_panels['Minimum'].SetValue(minvec)
spin_panels['Maximum'].SetValue(maxvec)
spin_panels['Skip first'].SetValue(skipvec)
spin_panels['Draw only'].SetValue(drawvec)
def AppSetTakesVec(self, takes):
spin_panels['Takes'].SetLabel('Takes %d vectors' % takes)
# clroses doesn't change this data, so it's not telling us something
# we don't already know.
def AppSetTiming(self, vecPtick, msecPtick, delay):
spin_panels['Vec/tick'].SetValue(vecPtick)
spin_panels['msec/tick'].SetValue(msecPtick)
spin_panels['Delay'].SetValue(delay)
# Command buttons change their names based on the whether we're in auto
# or manual mode.
def AppCmdLabels(self, labels):
for name, label in map(None, ('Go', 'Redraw', 'Backward', 'Forward'), labels):
ctrl_buttons[name].SetLabel(label)
ctrl_buttons[name].SetForegroundColour(self.labelColours[label])
# Timer methods. The paranoia about checking up on the callers is
# primarily because it's easier to check here. We expect that calls to
# AppAfter and OnTimer alternate, but don't verify that AppCancelTimer()
# is canceling anything as callers of that may be uncertain about what's
# happening.
# Method to provide a single callback after some amount of time.
def AppAfter(self, msec, callback):
if self.timer_callback:
print 'AppAfter: timer_callback already set!',
# print 'AppAfter:', callback
self.timer_callback = callback
self.timer.Start(msec, True)
# Method to cancel something we might be waiting for but have lost
# interest in.
def AppCancelTimer(self):
self.timer.Stop()
# print 'AppCancelTimer'
self.timer_callback = None
# When the timer happens, we come here and jump off to clroses internal code.
def OnTimer(self, evt):
callback = self.timer_callback
self.timer_callback = None
# print 'OnTimer,', callback
if callback:
callback() # Often calls AppAfter() and sets the callback
else:
print 'OnTimer: no callback!'
resize_delay = 300
def TriggerResize(self, size):
self.resize(size, self.resize_delay)
self.resize_delay = 100
def TriggerRedraw(self):
self.repaint(10)
# Called when data in spin boxes changes.
def OnSpinback(self, name, value):
if verbose:
print 'OnSpinback', name, value
if name == 'Style':
self.SetStyle(value)
elif name == 'Sincr':
self.SetSincr(value)
elif name == 'Petal':
self.SetPetals(value)
elif name == 'Pincr':
self.SetPincr(value)
elif name == 'Vectors':
self.SetVectors(value)
elif name == 'Minimum':
self.SetMinVec(value)
elif name == 'Maximum':
self.SetMaxVec(value)
elif name == 'Skip first':
self.SetSkipFirst(value)
elif name == 'Draw only':
self.SetDrawOnly(value)
elif name == 'Vec/tick':
self.SetStep(value)
elif name == 'msec/tick':
self.SetDrawDelay(value)
elif name == 'Delay':
self.SetWaitDelay(value)
else:
print 'OnSpinback: Don\'t recognize', name
verbose = 0 # Need some command line options...
spin_panels = {} # Hooks to get from rose to panel labels
ctrl_buttons = {} # Button widgets for command (NE) panel
app = wx.App(False)
MyFrame()
if verbose:
print 'spin_panels', spin_panels.keys()
print 'ctrl_buttons', ctrl_buttons.keys()
app.MainLoop()

View File

@@ -482,7 +482,12 @@ wxpExtensions.append(ext)
swig_sources = run_swig(['richtext.i'], 'src', GENDIR, PKGDIR, swig_sources = run_swig(['richtext.i'], 'src', GENDIR, PKGDIR,
USE_SWIG, swig_force, swig_args, swig_deps) USE_SWIG, swig_force, swig_args,
swig_deps + [ 'src/_richtextbuffer.i',
'src/_richtextctrl.i',
'src/_richtexthtml.i',
'src/_richtextxml.i',
])
if not MONOLITHIC and findLib('richtext', libdirs): if not MONOLITHIC and findLib('richtext', libdirs):
richLib = makeLibName('richtext') richLib = makeLibName('richtext')
else: else:
@@ -569,6 +574,11 @@ if BUILD_GLCANVAS:
gl_libs = libs + ['opengl32', 'glu32'] + makeLibName('gl') gl_libs = libs + ['opengl32', 'glu32'] + makeLibName('gl')
gl_lflags = lflags gl_lflags = lflags
if sys.platform[:6] == "darwin" and WXPORT == 'mac':
if not ARCH == "":
gl_lflags.append("-arch")
gl_lflags.append(ARCH)
ext = Extension('_glcanvas', ext = Extension('_glcanvas',
swig_sources, swig_sources,

View File

@@ -24,10 +24,10 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
%{ %{
// See http://tinyurl.com/e5adr for what premultiplying alpha means. It // See http://tinyurl.com/e5adr for what premultiplying alpha means. wxMSW and
// appears to me that the other platforms are already doing it, so I'll just // wxMac want to have the values premultiplied by the alpha value, but the
// automatically do it for wxMSW here. // other platforms don't. These macros help keep the code clean.
#ifdef __WXMSW__ #if defined(__WXMSW__) || (defined(__WXMAC__) && wxMAC_USE_CORE_GRAPHICS)
#define wxPy_premultiply(p, a) ((p) * (a) / 0xff) #define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
#define wxPy_unpremultiply(p, a) ((a) ? ((p) * 0xff / (a)) : (p)) #define wxPy_unpremultiply(p, a) ((a) ? ((p) * 0xff / (a)) : (p))
#else #else
@@ -500,8 +500,8 @@ def BitmapFromBuffer(width, height, dataBuffer, alphaBuffer=None):
expected to contain a series of RGB bytes and be width*height*3 expected to contain a series of RGB bytes and be width*height*3
bytes long. A buffer object can optionally be supplied for the bytes long. A buffer object can optionally be supplied for the
image's alpha channel data, and it is expected to be width*height image's alpha channel data, and it is expected to be width*height
bytes long. On Windows the RGB values are 'premultiplied' by the bytes long. On Windows and Mac the RGB values are 'premultiplied'
alpha values. (The other platforms do the multiplication by the alpha values. (The other platforms do the multiplication
themselves.) themselves.)
Unlike `wx.ImageFromBuffer` the bitmap created with this function Unlike `wx.ImageFromBuffer` the bitmap created with this function
@@ -567,8 +567,8 @@ def BitmapFromBufferRGBA(width, height, dataBuffer):
parameter must be a Python object that implements the buffer parameter must be a Python object that implements the buffer
interface, such as a string, array, etc. The dataBuffer object is interface, such as a string, array, etc. The dataBuffer object is
expected to contain a series of RGBA bytes (red, green, blue and expected to contain a series of RGBA bytes (red, green, blue and
alpha) and be width*height*4 bytes long. On Windows the RGB alpha) and be width*height*4 bytes long. On Windows and Mac the
values are 'premultiplied' by the alpha values. (The other RGB values are 'premultiplied' by the alpha values. (The other
platforms do the multiplication themselves.) platforms do the multiplication themselves.)
Unlike `wx.ImageFromBuffer` the bitmap created with this function Unlike `wx.ImageFromBuffer` the bitmap created with this function

View File

@@ -35,7 +35,7 @@ Blue (RGB) intensity values, and is used to determine drawing colours,
window colours, etc. Valid RGB values are in the range 0 to 255. window colours, etc. Valid RGB values are in the range 0 to 255.
In wxPython there are typemaps that will automatically convert from a In wxPython there are typemaps that will automatically convert from a
colour name, from a '#RRGGBB' colour hex value string, or from a 3 colour name, from a '#RRGGBB' colour hex value string, or from a 3 or 4
integer tuple to a wx.Colour object when calling C++ methods that integer tuple to a wx.Colour object when calling C++ methods that
expect a wxColour. This means that the following are all expect a wxColour. This means that the following are all
equivallent:: equivallent::
@@ -59,7 +59,7 @@ public:
DocCtorStr( DocCtorStr(
wxColour(byte red=0, byte green=0, byte blue=0, byte alpha=wxALPHA_OPAQUE), wxColour(byte red=0, byte green=0, byte blue=0, byte alpha=wxALPHA_OPAQUE),
"Constructs a colour from red, green and blue values. "Constructs a colour from red, green, blue and alpha values.
:see: Alternate constructors `wx.NamedColour` and `wx.ColourRGB`. :see: Alternate constructors `wx.NamedColour` and `wx.ColourRGB`.
", ""); ", "");
@@ -165,8 +165,8 @@ is returned if the pixel is invalid (on X, unallocated).", "");
%extend { %extend {
KeepGIL(Get); KeepGIL(Get);
DocAStr(Get, DocAStr(Get,
"Get() -> (r, g, b)", "Get(self, bool includeAlpha=False) -> (r,g,b) or (r,g,b,a)",
"Returns the RGB intensity values as a tuple.", ""); "Returns the RGB intensity values as a tuple, optionally the alpha value as well.", "");
PyObject* Get(bool includeAlpha=false) { PyObject* Get(bool includeAlpha=false) {
PyObject* rv = PyTuple_New(includeAlpha ? 4 : 3); PyObject* rv = PyTuple_New(includeAlpha ? 4 : 3);
int red = -1; int red = -1;

View File

@@ -242,6 +242,8 @@ static wxPyCoreAPI API = {
wxRect2D_helper, wxRect2D_helper,
wxPosition_helper, wxPosition_helper,
wxPyCBOutputStream_create,
wxPyCBOutputStream_copy,
}; };
#endif #endif

View File

@@ -93,6 +93,7 @@ typedef unsigned int size_t;
typedef unsigned int time_t; typedef unsigned int time_t;
typedef unsigned char byte; typedef unsigned char byte;
typedef unsigned long wxUIntPtr; typedef unsigned long wxUIntPtr;
typedef double wxDouble;
#define wxWindowID int #define wxWindowID int
#define wxCoord int #define wxCoord int
@@ -408,6 +409,19 @@ typedef unsigned long wxUIntPtr;
%enddef %enddef
#endif #endif
#ifdef _DO_FULL_DOCS
%define %RenameDocStr(newname, docstr, details, type, decl)
%feature("docstring") decl docstr;
%rename(newname) decl;
type decl
%enddef
#else
%define %RenameDocStr(newname, docstr, details, type, decl)
%feature("docstring") decl docstr details;
%rename(newname) decl;
type decl
%enddef
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Generates a base_On* method that just wraps a call to the On*, and mark it // Generates a base_On* method that just wraps a call to the On*, and mark it
@@ -459,6 +473,204 @@ FORWARD_DECLARE(wxIcon, Icon);
FORWARD_DECLARE(wxStaticBox, StaticBox); FORWARD_DECLARE(wxStaticBox, StaticBox);
//---------------------------------------------------------------------------
// This macro makes a class to wrap a type specific class derived from wxList,
// and make it look like a Python sequence, including with iterator support
%define wxLIST_WRAPPER(ListClass, ItemClass)
// first a bit of C++ code...
%{
class ListClass##_iterator
{
public:
ListClass##_iterator(ListClass::compatibility_iterator start)
: m_node(start) {}
ItemClass* next() {
ItemClass* obj = NULL;
if (m_node) {
obj = m_node->GetData();
m_node = m_node->GetNext();
}
else PyErr_SetString(PyExc_StopIteration, "");
return obj;
}
private:
ListClass::compatibility_iterator m_node;
};
%}
// Now declare the classes for SWIG
DocStr(ListClass##_iterator,
"This class serves as an iterator for a ListClass object.", "");
class ListClass##_iterator
{
public:
//ListClass##_iterator();
~ListClass_iterator();
KeepGIL(next);
ItemClass* next();
};
DocStr(ListClass,
"This class wraps a wxList-based class and gives it a Python
sequence-like interface. Sequence operations supported are length,
index access and iteration.", "");
class ListClass
{
public:
//ListClass(); This will always be created by some C++ function
~ListClass();
%extend {
KeepGIL(__len__);
size_t __len__() {
return self->size();
}
KeepGIL(__getitem__);
ItemClass* __getitem__(size_t index) {
if (index < self->size()) {
ListClass::compatibility_iterator node = self->Item(index);
if (node) return node->GetData();
}
PyErr_SetString(PyExc_IndexError, "Invalid list index");
return NULL;
}
KeepGIL(__contains__);
bool __contains__(const ItemClass* obj) {
return self->Find(obj) != NULL;
}
KeepGIL(__iter__);
%newobject __iter__;
ListClass##_iterator* __iter__() {
return new ListClass##_iterator(self->GetFirst());
}
}
%pythoncode {
def __repr__(self):
return "ListClass: " + repr(list(self))
}
};
%enddef
// This macro is similar to the above, but it is to be used when there isn't a
// type-specific C++ list class to use. In other words the C++ code is using
// a plain wxList and typecasting the node values, so we'll do the same.
%define wxUNTYPED_LIST_WRAPPER(ListClass, ItemClass)
// first a bit of C++ code...
%{
class ListClass
{
public:
ListClass(wxList* theList)
: m_list(theList) {}
~ListClass() {}
public:
wxList* m_list;
};
class ListClass##_iterator
{
public:
ListClass##_iterator(wxList::compatibility_iterator start)
: m_node(start) {}
ItemClass* next() {
ItemClass* obj = NULL;
if (m_node) {
obj = (ItemClass*)m_node->GetData();
m_node = m_node->GetNext();
}
else PyErr_SetString(PyExc_StopIteration, "");
return obj;
}
private:
wxList::compatibility_iterator m_node;
};
%}
// Now declare the classes for SWIG
DocStr(ListClass##_iterator,
"This class serves as an iterator for a ListClass object.", "");
class ListClass##_iterator
{
public:
//ListClass##_iterator();
~ListClass_iterator();
KeepGIL(next);
ItemClass* next();
};
DocStr(ListClass,
"This class wraps a wxList-based class and gives it a Python
sequence-like interface. Sequence operations supported are length,
index access and iteration.", "");
class ListClass
{
public:
//ListClass(); This will always be created by some C++ function
~ListClass();
%extend {
KeepGIL(__len__);
size_t __len__() {
return self->m_list->size();
}
KeepGIL(__getitem__);
ItemClass* __getitem__(size_t index) {
if (index < self->m_list->size()) {
wxList::compatibility_iterator node = self->m_list->Item(index);
if (node) return (ItemClass*)node->GetData();
}
PyErr_SetString(PyExc_IndexError, "Invalid list index");
return NULL;
}
KeepGIL(__contains__);
bool __contains__(const ItemClass* obj) {
return self->m_list->Find(obj) != NULL;
}
KeepGIL(__iter__);
%newobject __iter__;
ListClass##_iterator* __iter__() {
return new ListClass##_iterator(self->m_list->GetFirst());
}
}
%pythoncode {
def __repr__(self):
return "ListClass: " + repr(list(self))
}
};
// A typemap to handle converting a wxList& return value to this new list
// type. To use this just change the return value type in the class
// definition to this typedef instead of wxList, then SWIG will use the
// typemap.
%{
typedef wxList ListClass##_t;
%}
%typemap(out) ListClass##_t& {
ListClass* mylist = new ListClass($1);
$result = SWIG_NewPointerObj(SWIG_as_voidptr(mylist), SWIGTYPE_p_##ListClass, SWIG_POINTER_OWN );
}
%enddef
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
%{ %{

View File

@@ -280,6 +280,26 @@ public:
// Add a file to the memory FS // Add a file to the memory FS
%pythoncode { AddFile = staticmethod(MemoryFSHandler_AddFile) } %pythoncode { AddFile = staticmethod(MemoryFSHandler_AddFile) }
%extend {
static void AddFileWithMimeType(const wxString& filename,
PyObject* data,
const wxString& mimetype)
{
if (! PyString_Check(data)) {
wxPyBLOCK_THREADS(PyErr_SetString(PyExc_TypeError,
"Expected string object"));
return;
}
wxPyBlock_t blocked = wxPyBeginBlockThreads();
void* ptr = (void*)PyString_AsString(data);
size_t size = PyString_Size(data);
wxPyEndBlockThreads(blocked);
wxMemoryFSHandler::AddFileWithMimeType(filename, ptr, size, mimetype);
}
}
bool CanOpen(const wxString& location); bool CanOpen(const wxString& location);
%newobject OpenFile; %newobject OpenFile;
wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location); wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location);

View File

@@ -451,7 +451,7 @@ public:
}; };
MustHaveApp(wxThread); MustHaveApp(wxThread_IsMain);
%inline %{ %inline %{
bool wxThread_IsMain() { bool wxThread_IsMain() {
#ifdef WXP_WITH_THREAD #ifdef WXP_WITH_THREAD

View File

@@ -488,6 +488,9 @@ DocStr(wxRect,
width and height properties. In wxPython most palces that expect a width and height properties. In wxPython most palces that expect a
wx.Rect can also accept a (x,y,width,height) tuple.", ""); wx.Rect can also accept a (x,y,width,height) tuple.", "");
%typemap(in) wxRect*;
class wxRect class wxRect
{ {
public: public:
@@ -777,6 +780,9 @@ usually, but not necessarily, the larger one.", "");
%property(Empty, IsEmpty, doc="See `IsEmpty`"); %property(Empty, IsEmpty, doc="See `IsEmpty`");
}; };
%apply wxRect& { wxRect* };
MustHaveApp(wxIntersectRect); MustHaveApp(wxIntersectRect);

View File

@@ -350,9 +350,6 @@ MustHaveApp(wxGraphicsPath);
MustHaveApp(wxGraphicsContext); MustHaveApp(wxGraphicsContext);
MustHaveApp(wxGCDC); MustHaveApp(wxGCDC);
typedef double wxDouble;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -643,6 +643,17 @@ string.", "",
"Saves an image in the named file.", "", "Saves an image in the named file.", "",
SaveMimeFile); SaveMimeFile);
DocDeclStrName(
bool , SaveFile( wxOutputStream& stream, int type ),
"Saves an image in the named file.", "",
SaveStream);
DocDeclStrName(
bool , SaveFile( wxOutputStream& stream, const wxString& mimetype ),
"Saves an image in the named file.", "",
SaveMimeStream);
DocDeclStrName( DocDeclStrName(
static bool , CanRead( wxInputStream& stream ), static bool , CanRead( wxInputStream& stream ),

View File

@@ -214,6 +214,7 @@ public:
void PassMessages(bool bDoPass); void PassMessages(bool bDoPass);
bool IsPassingMessages(); bool IsPassingMessages();
wxLog *GetOldLog(); wxLog *GetOldLog();
void DetachOldLog();
%property(OldLog, GetOldLog, doc="See `GetOldLog`"); %property(OldLog, GetOldLog, doc="See `GetOldLog`");
}; };

View File

@@ -16,6 +16,9 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
%newgroup %newgroup
wxLIST_WRAPPER(wxMenuItemList, wxMenuItem);
MustHaveApp(wxMenu); MustHaveApp(wxMenu);
@@ -169,12 +172,7 @@ public:
// get the items // get the items
size_t GetMenuItemCount() const; size_t GetMenuItemCount() const;
%extend { wxMenuItemList& GetMenuItems();
PyObject* GetMenuItems() {
wxMenuItemList& list = self->GetMenuItems();
return wxPy_ConvertList(&list);
}
}
// search // search
int FindItem(const wxString& item) const; int FindItem(const wxString& item) const;

View File

@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Name: _window.i // Name: _panel.i
// Purpose: SWIG interface for wxPanel and wxScrolledWindow // Purpose: SWIG interface for wxPanel and wxScrolledWindow
// //
// Author: Robin Dunn // Author: Robin Dunn

File diff suppressed because it is too large Load Diff

1237
wxPython/src/_richtextctrl.i Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,102 @@
/////////////////////////////////////////////////////////////////////////////
// Name: _richtexthtml
// Purpose: wxRichTextHTMLHandler
//
// Author: Robin Dunn
//
// Created: 18-May-2007
// RCS-ID: $Id$
// Copyright: (c) 2007 by Total Control Software
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
// Not a %module
//---------------------------------------------------------------------------
%{
#include <wx/richtext/richtexthtml.h>
%}
//---------------------------------------------------------------------------
%newgroup
MAKE_CONST_WXSTRING2(HtmlName, wxT("HTML"));
MAKE_CONST_WXSTRING2(HtmlExt, wxT("html"));
class wxRichTextHTMLHandler: public wxRichTextFileHandler
{
public:
wxRichTextHTMLHandler(const wxString& name = wxPyHtmlName,
const wxString& ext = wxPyHtmlExt,
int type = wxRICHTEXT_TYPE_HTML);
DocDeclStr(
virtual bool , CanSave() const,
"Can we save using this handler?", "");
DocDeclStr(
virtual bool , CanLoad() const,
"Can we load using this handler?", "");
DocDeclStr(
virtual bool , CanHandle(const wxString& filename) const,
"Can we handle this filename (if using files)? By default, checks the
extension.", "");
DocDeclStr(
void , SetTemporaryImageLocations(const wxArrayString& locations),
"Set the list of image locations generated by the last operation", "");
DocDeclStr(
const wxArrayString& , GetTemporaryImageLocations() const,
"Get the list of image locations generated by the last operation", "");
%property(TemporaryImageLocations, GetTemporaryImageLocations, SetTemporaryImageLocations);
DocDeclStr(
void , ClearTemporaryImageLocations(),
"Clear the image locations generated by the last operation", "");
DocDeclStr(
bool , DeleteTemporaryImages(),
"Delete the in-memory or temporary files generated by the last operation", "");
// DocDeclStr(
// static bool , DeleteTemporaryImages(int flags, const wxArrayString& imageLocations),
// "Delete the in-memory or temporary files generated by the last operation. This
// is a static function that can be used to delete the saved locations from an
// earlier operation, for example after the user has viewed the HTML file.", "");
DocDeclStr(
static void , SetFileCounter(int counter),
"Reset the file counter, in case, for example, the same names are required each
time", "");
DocDeclStr(
void , SetTempDir(const wxString& tempDir),
"Set the directory for storing temporary files. If empty, the system temporary
directory will be used.", "");
DocDeclStr(
const wxString& , GetTempDir() const,
"Get the directory for storing temporary files. If empty, the system temporary
directory will be used.", "");
%property(TempDir, GetTempDir, SetTempDir);
DocDeclStr(
void , SetFontSizeMapping(const wxArrayInt& fontSizeMapping),
"Set mapping from point size to HTML font size. There should be 7 elements, one
for each HTML font size, each element specifying the maximum point size for
that HTML font size. E.g. 8, 10, 13, 17, 22, 29, 100
", "");
DocDeclStr(
wxArrayInt , GetFontSizeMapping() const,
"Get mapping deom point size to HTML font size.", "");
%property(FontSizeMapping, GetFontSizeMapping, SetFontSizeMapping);
};
//---------------------------------------------------------------------------

View File

@@ -0,0 +1,67 @@
/////////////////////////////////////////////////////////////////////////////
// Name: _richtextxml
// Purpose: wxRichTextXMLHandler
//
// Author: Robin Dunn
//
// Created: 18-May-2007
// RCS-ID: $Id$
// Copyright: (c) 2007 by Total Control Software
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
// Not a %module
//---------------------------------------------------------------------------
%{
#include <wx/richtext/richtextxml.h>
%}
//---------------------------------------------------------------------------
%newgroup
MAKE_CONST_WXSTRING2(XmlName, wxT("XML"));
MAKE_CONST_WXSTRING2(XmlExt, wxT("xml"));
class wxRichTextXMLHandler: public wxRichTextFileHandler
{
public:
wxRichTextXMLHandler(const wxString& name = wxPyXmlName,
const wxString& ext = wxPyXmlExt,
int type = wxRICHTEXT_TYPE_XML);
// #if wxUSE_STREAMS
// /// Recursively export an object
// bool ExportXML(wxOutputStream& stream, wxMBConv* convMem, wxMBConv* convFile, wxRichTextObject& obj, int level);
// bool ExportStyleDefinition(wxOutputStream& stream, wxMBConv* convMem, wxMBConv* convFile, wxRichTextStyleDefinition* def, int level);
// /// Recursively import an object
// bool ImportXML(wxRichTextBuffer* buffer, wxXmlNode* node);
// bool ImportStyleDefinition(wxRichTextStyleSheet* sheet, wxXmlNode* node);
// /// Create style parameters
// wxString CreateStyle(const wxTextAttrEx& attr, bool isPara = false);
// /// Get style parameters
// bool GetStyle(wxTextAttrEx& attr, wxXmlNode* node, bool isPara = false);
// #endif
/// Can we save using this handler?
virtual bool CanSave() const;
/// Can we load using this handler?
virtual bool CanLoad() const;
// bool HasParam(wxXmlNode* node, const wxString& param);
// wxXmlNode *GetParamNode(wxXmlNode* node, const wxString& param);
// wxString GetNodeContent(wxXmlNode *node);
// wxString GetParamValue(wxXmlNode *node, const wxString& param);
// wxString GetText(wxXmlNode *node, const wxString& param = wxEmptyString, bool translate = false);
};
//---------------------------------------------------------------------------

View File

@@ -169,6 +169,11 @@ border size.", "");
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
%newgroup
wxLIST_WRAPPER( wxSizerItemList, wxSizerItem );
DocStr(wxSizerItem, DocStr(wxSizerItem,
"The wx.SizerItem class is used to track the position, size and other "The wx.SizerItem class is used to track the position, size and other
@@ -1247,21 +1252,12 @@ as well.", "");
// wxList& GetChildren(); DocStr(GetChildren,
%extend { "Returns all of the `wx.SizerItem` objects managed by the sizer in a
DocAStr(GetChildren, list-like object.", "");
"GetChildren(self) -> list", wxSizerItemList& GetChildren();
"Returns a list of all the `wx.SizerItem` objects managed by the sizer.", "");
PyObject* GetChildren() {
wxSizerItemList& list = self->GetChildren();
return wxPy_ConvertList(&list);
}
}
// Manage whether individual windows or subsizers are considered
// in the layout calculations or not.
%extend { %extend {
DocAStr(Show, DocAStr(Show,
"Show(self, item, bool show=True, bool recursive=false) -> bool", "Show(self, item, bool show=True, bool recursive=false) -> bool",

View File

@@ -32,7 +32,7 @@ given for the Unix, Windows and Mac OS X systems, however please note
that these are just examples and the actual values may differ. For that these are just examples and the actual values may differ. For
example, under Windows the system administrator may change the example, under Windows the system administrator may change the
standard directories locations, i.e. the Windows directory may be standard directories locations, i.e. the Windows directory may be
named W:\Win2003 instead of the default C:\Windows. named W:/Win2003 instead of the default C:/Windows.
The strings appname and username should be replaced with the value The strings appname and username should be replaced with the value
returned by `wx.App.GetAppName` and the name of the currently logged returned by `wx.App.GetAppName` and the name of the currently logged
@@ -85,14 +85,14 @@ absolute path whenever possible.", "");
DocDeclStr( DocDeclStr(
virtual wxString , GetConfigDir() const, virtual wxString , GetConfigDir() const,
"Return the directory with system config files: /etc under Unix, "Return the directory with system config files: /etc under Unix,
'c:\\Documents and Settings\\All Users\\Application Data' under Windows, 'c:/Documents and Settings/All Users/Application Data' under Windows,
/Library/Preferences for Mac", ""); /Library/Preferences for Mac", "");
DocDeclStr( DocDeclStr(
virtual wxString , GetUserConfigDir() const, virtual wxString , GetUserConfigDir() const,
"Return the directory for the user config files: $HOME under Unix, "Return the directory for the user config files: $HOME under Unix,
'c:\\Documents and Settings\\username' under Windows, and 'c:/Documents and Settings/username' under Windows, and
~/Library/Preferences under Mac ~/Library/Preferences under Mac
Only use this if you have a single file to put there, otherwise Only use this if you have a single file to put there, otherwise
@@ -103,7 +103,7 @@ Only use this if you have a single file to put there, otherwise
virtual wxString , GetDataDir() const, virtual wxString , GetDataDir() const,
"Return the location of the application's global, (i.e. not "Return the location of the application's global, (i.e. not
user-specific,) data files: prefix/share/appname under Unix, user-specific,) data files: prefix/share/appname under Unix,
'c:\\Program Files\\appname' under Windows, 'c:/Program Files/appname' under Windows,
appname.app/Contents/SharedSupport app bundle directory under Mac.", ""); appname.app/Contents/SharedSupport app bundle directory under Mac.", "");
@@ -117,8 +117,8 @@ host-specific. Same as `GetDataDir` except under Unix where it is
DocDeclStr( DocDeclStr(
virtual wxString , GetUserDataDir() const, virtual wxString , GetUserDataDir() const,
"Return the directory for the user-dependent application data files: "Return the directory for the user-dependent application data files:
$HOME/.appname under Unix, c:\\Documents and $HOME/.appname under Unix, c:/Documents and
Settings\\username\\Application Data\\appname under Windows and Settings/username/Application Data/appname under Windows and
~/Library/Application Support/appname under Mac", ""); ~/Library/Application Support/appname under Mac", "");
@@ -128,7 +128,7 @@ Settings\\username\\Application Data\\appname under Windows and
with the other machines with the other machines
Same as `GetUserDataDir` for all platforms except Windows where it is Same as `GetUserDataDir` for all platforms except Windows where it is
the 'Local Settings\\Application Data\\appname' directory.", ""); the 'Local Settings/Application Data/appname' directory.", "");
DocDeclStr( DocDeclStr(
@@ -168,7 +168,7 @@ standard prefix/share/locale/lang/LC_MESSAGES.)", "");
virtual wxString , GetDocumentsDir() const, virtual wxString , GetDocumentsDir() const,
"Return the Documents directory for the current user. "Return the Documents directory for the current user.
C:\Documents and Settings\username\Documents under Windows, C:/Documents and Settings/username/Documents under Windows,
$HOME under Unix and ~/Documents under Mac", ""); $HOME under Unix and ~/Documents under Mac", "");
DocDeclStr( DocDeclStr(

View File

@@ -61,18 +61,43 @@
} }
} }
%typemap(out) wxInputStream* { %typemap(out) wxInputStream* {
wxPyInputStream * _ptr = NULL; wxPyInputStream * _ptr = NULL;
if ($1)
if ($1) {
_ptr = new wxPyInputStream($1); _ptr = new wxPyInputStream($1);
}
$result = wxPyConstructObject(_ptr, wxT("wxPyInputStream"), $owner); $result = wxPyConstructObject(_ptr, wxT("wxPyInputStream"), $owner);
} }
//---------------------------------------------------------------------------
// Typemaps for wxOutputStream. We only need in by reference and out by
// pointer in this one.
%typemap(in) wxOutputStream& (wxPyOutputStream* temp, bool created) {
if (wxPyConvertSwigPtr($input, (void **)&temp, wxT("wxPyOutputStream"))) {
$1 = temp->m_wxos;
created = false;
} else {
PyErr_Clear(); // clear the failure of the wxPyConvert above
$1 = wxPyCBOutputStream_create($input, false);
if ($1 == NULL) {
PyErr_SetString(PyExc_TypeError, "Expected wx.OutputStream or Python file-like object.");
SWIG_fail;
}
created = true;
}
}
%typemap(freearg) wxOutputStream& { if (created$argnum) delete $1; }
%typemap(out) wxOutputStream* {
wxPyOutputStream * _ptr = NULL;
if ($1)
_ptr = new wxPyOutputStream($1);
$result = wxPyConstructObject(_ptr, wxT("wxPyOutputStream"), $owner);
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
enum wxSeekMode enum wxSeekMode
@@ -107,14 +132,6 @@ public:
void seek(int offset, int whence=0); void seek(int offset, int whence=0);
int tell(); int tell();
/*
bool isatty();
int fileno();
void truncate(int size=-1);
void write(wxString data);
void writelines(wxStringPtrList);
*/
char Peek(); char Peek();
char GetC(); char GetC();
size_t LastRead(); size_t LastRead();
@@ -128,43 +145,41 @@ public:
// TODO: make a more fully implemented file interface...
class wxOutputStream {
public:
/*
void close();
void flush();
wxString* read(int size=-1);
wxString* readline(int size=-1);
wxStringPtrList* readlines(int sizehint=-1);
void seek(int offset, int whence=0);
int tell();
bool isatty();
int fileno();
void truncate(int size=-1);
void write(wxString data);
void writelines(wxStringPtrList);
*/
%rename(OutputStream) wxPyOutputStream;
class wxPyOutputStream
{
public:
%extend { %extend {
void write(PyObject* obj) { wxPyOutputStream(PyObject* p) {
// We use only strings for the streams, not unicode wxOutputStream* wxis = wxPyCBOutputStream::create(p);
PyObject* str = PyObject_Str(obj); if (wxis)
if (! str) { return new wxPyOutputStream(wxis);
PyErr_SetString(PyExc_TypeError, "Unable to convert to string"); else
return; return NULL;
}
self->Write(PyString_AS_STRING(str),
PyString_GET_SIZE(str));
Py_DECREF(str);
} }
} }
size_t LastWrite() const; ~wxPyOutputStream();
void close();
void flush();
bool eof();
void seek(int offset, int whence=0);
int tell();
void write(PyObject* data);
//void writelines(wxStringArray& arr);
void PutC(char c);
size_t LastWrite();
unsigned long SeekO(unsigned long pos, wxSeekMode mode = wxFromStart);
unsigned long TellO();
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
%init %{ %init %{
wxPyPtrTypeMap_Add("wxInputStream", "wxPyInputStream"); wxPyPtrTypeMap_Add("wxInputStream", "wxPyInputStream");
wxPyPtrTypeMap_Add("wxOutputStream", "wxPyOutputStream");
%} %}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -24,6 +24,9 @@ MAKE_CONST_WXSTRING(PanelNameStr);
%newgroup %newgroup
wxLIST_WRAPPER(wxWindowList, wxWindow);
DocStr(wxVisualAttributes, DocStr(wxVisualAttributes,
"struct containing all the visual attributes of a control", ""); "struct containing all the visual attributes of a control", "");
@@ -124,8 +127,13 @@ Styles
deactivate it. deactivate it.
wx.VSCROLL Use this style to enable a vertical scrollbar. wx.VSCROLL Use this style to enable a vertical scrollbar.
Notice that this style cannot be used with
native controls which don't support scrollbars
nor with top-level windows in most ports.
wx.HSCROLL Use this style to enable a horizontal scrollbar. wx.HSCROLL Use this style to enable a horizontal scrollbar.
The same limitations as for wx.VSCROLL apply to
this style.
wx.ALWAYS_SHOW_SB If a window has scrollbars, disable them wx.ALWAYS_SHOW_SB If a window has scrollbars, disable them
instead of hiding them when they are instead of hiding them when they are
@@ -990,26 +998,16 @@ before win instead of putting it right after it.", "");
// parent/children relations // parent/children relations
// ------------------------- // -------------------------
//wxWindowList& GetChildren(); // TODO: Do a typemap or a wrapper for wxWindowList
%extend {
DocStr(GetChildren, DocStr(GetChildren,
"Returns a list of the window's children. NOTE: Currently this is a "Returns an object containing a list of the window's children. The
copy of the child window list maintained by the window, so the return object provides a Python sequence-like interface over the internal
value of this function is only valid as long as the window's children list maintained by the window..", "");
do not change.", ""); wxWindowList& GetChildren();
PyObject* GetChildren() {
wxWindowList& list = self->GetChildren();
return wxPy_ConvertList(&list);
}
}
DocDeclStr( DocDeclStr(
wxWindow *, GetParent() const, wxWindow *, GetParent() const,
@@ -2318,14 +2316,11 @@ MustHaveApp(wxWindow_FromHWND);
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
DocStr(GetTopLevelWindows, DocStr(GetTopLevelWindows,
"Returns a list of the the application's top-level windows, (frames, "Returns a list-like object of the the application's top-level windows, (frames,
dialogs, etc.) NOTE: Currently this is a copy of the list maintained dialogs, etc.)", "");
by wxWidgets, and so it is only valid as long as no top-level windows
are closed or new top-level windows are created.
", "");
%inline %{ %inline %{
PyObject* GetTopLevelWindows() { wxWindowList& GetTopLevelWindows() {
return wxPy_ConvertList(&wxTopLevelWindows); return wxTopLevelWindows;
} }
%} %}

View File

@@ -11,7 +11,7 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
%define DOCSTRING %define DOCSTRING
"The wx.aui moduleis an Advanced User Interface library that aims to "The wx.aui module is an Advanced User Interface library that aims to
implement \"cutting-edge\" interface usability and design features so implement \"cutting-edge\" interface usability and design features so
developers can quickly and easily create beautiful and usable developers can quickly and easily create beautiful and usable
application interfaces. application interfaces.

View File

@@ -712,6 +712,7 @@ Nearly all of the methods of this class are overridable in Python.", "");
MustHaveApp(wxPyComboPopup); MustHaveApp(wxPyComboPopup);
%rename(ComboPopup) wxPyComboPopup; %rename(ComboPopup) wxPyComboPopup;
%typemap(out) wxPyComboCtrl* { $result = wxPyMake_wxObject($1, (bool)$owner); }
class wxPyComboPopup class wxPyComboPopup
{ {
@@ -851,7 +852,6 @@ is associated with.", "");
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
%newgroup %newgroup

View File

@@ -1090,6 +1090,21 @@ void wxPyEndBlockThreads(wxPyBlock_t blocked) {
// wxPyInputStream and wxPyCBInputStream methods // wxPyInputStream and wxPyCBInputStream methods
static PyObject* wxPyGetMethod(PyObject* py, char* name)
{
if (!PyObject_HasAttrString(py, name))
return NULL;
PyObject* o = PyObject_GetAttrString(py, name);
if (!PyMethod_Check(o) && !PyCFunction_Check(o)) {
Py_DECREF(o);
return NULL;
}
return o;
}
void wxPyInputStream::close() { void wxPyInputStream::close() {
/* do nothing for now */ /* do nothing for now */
} }
@@ -1246,7 +1261,7 @@ void wxPyInputStream::seek(int offset, int whence) {
m_wxis->SeekI(offset, wxSeekMode(whence)); m_wxis->SeekI(offset, wxSeekMode(whence));
} }
int wxPyInputStream::tell(){ int wxPyInputStream::tell() {
if (m_wxis) if (m_wxis)
return m_wxis->TellI(); return m_wxis->TellI();
else return 0; else return 0;
@@ -1285,9 +1300,9 @@ wxPyCBInputStream* wxPyCBInputStream::create(PyObject *py, bool block) {
wxPyBlock_t blocked = wxPyBlock_t_default; wxPyBlock_t blocked = wxPyBlock_t_default;
if (block) blocked = wxPyBeginBlockThreads(); if (block) blocked = wxPyBeginBlockThreads();
PyObject* read = getMethod(py, "read"); PyObject* read = wxPyGetMethod(py, "read");
PyObject* seek = getMethod(py, "seek"); PyObject* seek = wxPyGetMethod(py, "seek");
PyObject* tell = getMethod(py, "tell"); PyObject* tell = wxPyGetMethod(py, "tell");
if (!read) { if (!read) {
PyErr_SetString(PyExc_TypeError, "Not a file-like object"); PyErr_SetString(PyExc_TypeError, "Not a file-like object");
@@ -1311,17 +1326,6 @@ wxPyCBInputStream* wxPyCBInputStream_copy(wxPyCBInputStream* other) {
return new wxPyCBInputStream(*other); return new wxPyCBInputStream(*other);
} }
PyObject* wxPyCBInputStream::getMethod(PyObject* py, char* name) {
if (!PyObject_HasAttrString(py, name))
return NULL;
PyObject* o = PyObject_GetAttrString(py, name);
if (!PyMethod_Check(o) && !PyCFunction_Check(o)) {
Py_DECREF(o);
return NULL;
}
return o;
}
wxFileOffset wxPyCBInputStream::GetLength() const { wxFileOffset wxPyCBInputStream::GetLength() const {
wxPyCBInputStream* self = (wxPyCBInputStream*)this; // cast off const wxPyCBInputStream* self = (wxPyCBInputStream*)this; // cast off const
@@ -1406,6 +1410,196 @@ wxFileOffset wxPyCBInputStream::OnSysTell() const {
return o; return o;
} }
//----------------------------------------------------------------------
// Output stream
wxPyOutputStream::~wxPyOutputStream()
{
if (m_wxos)
delete m_wxos;
}
void wxPyOutputStream::close()
{
}
void wxPyOutputStream::flush()
{
}
bool wxPyOutputStream::eof()
{
return false;
}
void wxPyOutputStream::seek(int offset, int whence)
{
if (m_wxos)
m_wxos->SeekO(offset, wxSeekMode(whence));
}
int wxPyOutputStream::tell()
{
if (m_wxos)
return m_wxos->TellO();
else return 0;
}
void wxPyOutputStream::write(PyObject* data)
{
if (!m_wxos)
return;
// We use only strings for the streams, not unicode
PyObject* str = PyObject_Str(data);
if (! str) {
PyErr_SetString(PyExc_TypeError, "Unable to convert to string");
return;
}
m_wxos->Write(PyString_AS_STRING(str), PyString_GET_SIZE(str));
Py_DECREF(str);
}
wxPyCBOutputStream::wxPyCBOutputStream(PyObject *w, PyObject *s, PyObject *t, bool block)
: wxOutputStream(), m_write(w), m_seek(s), m_tell(t), m_block(block)
{}
wxPyCBOutputStream::wxPyCBOutputStream(const wxPyCBOutputStream& other)
{
m_write = other.m_write;
m_seek = other.m_seek;
m_tell = other.m_tell;
m_block = other.m_block;
Py_INCREF(m_write);
Py_INCREF(m_seek);
Py_INCREF(m_tell);
}
wxPyCBOutputStream::~wxPyCBOutputStream() {
wxPyBlock_t blocked = wxPyBlock_t_default;
if (m_block) blocked = wxPyBeginBlockThreads();
Py_XDECREF(m_write);
Py_XDECREF(m_seek);
Py_XDECREF(m_tell);
if (m_block) wxPyEndBlockThreads(blocked);
}
wxPyCBOutputStream* wxPyCBOutputStream::create(PyObject *py, bool block) {
wxPyBlock_t blocked = wxPyBlock_t_default;
if (block) blocked = wxPyBeginBlockThreads();
PyObject* write = wxPyGetMethod(py, "write");
PyObject* seek = wxPyGetMethod(py, "seek");
PyObject* tell = wxPyGetMethod(py, "tell");
if (!write) {
PyErr_SetString(PyExc_TypeError, "Not a file-like object");
Py_XDECREF(write);
Py_XDECREF(seek);
Py_XDECREF(tell);
if (block) wxPyEndBlockThreads(blocked);
return NULL;
}
if (block) wxPyEndBlockThreads(blocked);
return new wxPyCBOutputStream(write, seek, tell, block);
}
wxPyCBOutputStream* wxPyCBOutputStream_create(PyObject *py, bool block) {
return wxPyCBOutputStream::create(py, block);
}
wxPyCBOutputStream* wxPyCBOutputStream_copy(wxPyCBOutputStream* other) {
return new wxPyCBOutputStream(*other);
}
wxFileOffset wxPyCBOutputStream::GetLength() const {
wxPyCBOutputStream* self = (wxPyCBOutputStream*)this; // cast off const
if (m_seek && m_tell) {
wxFileOffset temp = self->OnSysTell();
wxFileOffset ret = self->OnSysSeek(0, wxFromEnd);
self->OnSysSeek(temp, wxFromStart);
return ret;
}
else
return wxInvalidOffset;
}
size_t wxPyCBOutputStream::OnSysRead(void *buffer, size_t bufsize) {
m_lasterror = wxSTREAM_READ_ERROR;
return 0;
}
size_t wxPyCBOutputStream::OnSysWrite(const void *buffer, size_t bufsize) {
if (bufsize == 0)
return 0;
wxPyBlock_t blocked = wxPyBeginBlockThreads();
PyObject* arglist = PyTuple_New(1);
PyTuple_SET_ITEM(arglist, 0, PyString_FromStringAndSize((char*)buffer, bufsize));
PyObject* result = PyEval_CallObject(m_write, arglist);
Py_DECREF(arglist);
if (result != NULL)
Py_DECREF(result);
else
m_lasterror = wxSTREAM_WRITE_ERROR;
wxPyEndBlockThreads(blocked);
return bufsize;
}
wxFileOffset wxPyCBOutputStream::OnSysSeek(wxFileOffset off, wxSeekMode mode) {
wxPyBlock_t blocked = wxPyBeginBlockThreads();
PyObject* arglist = PyTuple_New(2);
if (sizeof(wxFileOffset) > sizeof(long))
// wxFileOffset is a 64-bit value...
PyTuple_SET_ITEM(arglist, 0, PyLong_FromLongLong(off));
else
PyTuple_SET_ITEM(arglist, 0, PyInt_FromLong(off));
PyTuple_SET_ITEM(arglist, 1, PyInt_FromLong(mode));
PyObject* result = PyEval_CallObject(m_seek, arglist);
Py_DECREF(arglist);
Py_XDECREF(result);
wxPyEndBlockThreads(blocked);
return OnSysTell();
}
wxFileOffset wxPyCBOutputStream::OnSysTell() const {
wxPyBlock_t blocked = wxPyBeginBlockThreads();
PyObject* arglist = Py_BuildValue("()");
PyObject* result = PyEval_CallObject(m_tell, arglist);
Py_DECREF(arglist);
wxFileOffset o = 0;
if (result != NULL) {
if (PyLong_Check(result))
o = PyLong_AsLongLong(result);
else
o = PyInt_AsLong(result);
Py_DECREF(result);
};
wxPyEndBlockThreads(blocked);
return o;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject); IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject);

View File

@@ -173,6 +173,10 @@ MAKE_INT_ARRAY_TYPEMAPS(styles, styles_field)
} }
%apply wxRect& { wxRect* };
%typemap(in) wxPoint2D& (wxPoint2D temp) { %typemap(in) wxPoint2D& (wxPoint2D temp) {
$1 = &temp; $1 = &temp;
if ( ! wxPoint2D_helper($input, &$1)) SWIG_fail; if ( ! wxPoint2D_helper($input, &$1)) SWIG_fail;

File diff suppressed because it is too large Load Diff

View File

@@ -974,7 +974,10 @@ class ButtonInfo(Control):
self._shortHelp = shortHelp self._shortHelp = shortHelp
self._longHelp = longHelp self._longHelp = longHelp
disabledbmp = GrayOut(bmp) if bmp:
disabledbmp = GrayOut(bmp)
else:
disabledbmp = wx.NullBitmap
self._bitmaps = {"Normal": bmp, "Toggled": None, "Disabled": disabledbmp, self._bitmaps = {"Normal": bmp, "Toggled": None, "Disabled": disabledbmp,
"Hover": None, "Pressed": None} "Hover": None, "Pressed": None}

View File

@@ -140,10 +140,10 @@ class ColourSelect(wx.BitmapButton):
def SetBitmap(self, bmp): def SetBitmap(self, bmp):
self.SetBitmapLabel(bmp) self.SetBitmapLabel(bmp)
self.SetBitmapSelected(bmp) #self.SetBitmapSelected(bmp)
self.SetBitmapDisabled(bmp) #self.SetBitmapDisabled(bmp)
self.SetBitmapFocus(bmp) #self.SetBitmapFocus(bmp)
self.SetBitmapSelected(bmp) #self.SetBitmapSelected(bmp)
self.Refresh() self.Refresh()

View File

@@ -1459,7 +1459,7 @@ class FNBRenderer:
# erase old bitmap # erase old bitmap
posx = self.GetDropArrowButtonPos(pc) posx = self.GetDropArrowButtonPos(pc)
dc.DrawBitmap(self._xBgBmp, posx, 6) dc.DrawBitmap(self._rightBgBmp, posx, 6)
# Draw the new bitmap # Draw the new bitmap
dc.DrawBitmap(downBmp, posx, 6, True) dc.DrawBitmap(downBmp, posx, 6, True)
@@ -3353,6 +3353,7 @@ class FlatNotebook(wx.Panel):
self._pages.DoDeletePage(page) self._pages.DoDeletePage(page)
self.Refresh() self.Refresh()
self.Update()
# Fire a closed event # Fire a closed event
closedEvent = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, self.GetId()) closedEvent = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, self.GetId())
@@ -4733,12 +4734,13 @@ class PageContainer(wx.Panel):
for i in xrange(len(self._pagesInfoVec)): for i in xrange(len(self._pagesInfoVec)):
pi = self._pagesInfoVec[i] pi = self._pagesInfoVec[i]
item = wx.MenuItem(popupMenu, i, pi.GetCaption(), pi.GetCaption(), wx.ITEM_NORMAL) item = wx.MenuItem(popupMenu, i+1, pi.GetCaption(), pi.GetCaption(), wx.ITEM_NORMAL)
self.Bind(wx.EVT_MENU, self.OnTabMenuSelection, item) self.Bind(wx.EVT_MENU, self.OnTabMenuSelection, item)
# This code is commented, since there is an alignment problem with wx2.6.3 & Menus # There is an alignment problem with wx2.6.3 & Menus so only use
# if self.TabHasImage(ii): # images for versions above 2.6.3
# item.SetBitmaps( (*m_ImageList)[pi.GetImageIndex()] ); if wx.VERSION > (2, 6, 3, 0) and self.TabHasImage(i):
item.SetBitmap(self.GetImageList().GetBitmap(pi.GetImageIndex()))
popupMenu.AppendItem(item) popupMenu.AppendItem(item)
item.Enable(pi.GetEnabled()) item.Enable(pi.GetEnabled())
@@ -4749,7 +4751,7 @@ class PageContainer(wx.Panel):
def OnTabMenuSelection(self, event): def OnTabMenuSelection(self, event):
""" Handles the wx.EVT_MENU event for L{PageContainer}. """ """ Handles the wx.EVT_MENU event for L{PageContainer}. """
selection = event.GetId() selection = event.GetId() - 1
self.FireEvent(selection) self.FireEvent(selection)

View File

@@ -2,17 +2,27 @@
# Name: BrowseImage.py # Name: BrowseImage.py
# Purpose: Display and Select Image Files # Purpose: Display and Select Image Files
# #
# Author: Lorne White # Original Author: Lorne White
# #
# Version: 1.0 # Version: 2.0
# Date: January 29, 2002 # Date: June 16, 2007
# Licence: wxWindows license # Licence: wxWindows license
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# 1.0 Release # 2.0 Release - Bill Baxter (wbaxter@gmail.com)
# Create list of all available image file types # Date: June 16, 2007
# View "All Image" File Types as default filter # o Changed to use sizers instead of fixed placement.
# Sort the file list # o Made dialog resizeable
# Use newer "re" function for patterns # o Added a splitter between file list and view pane
# o Made directory path editable
# o Added an "up" button" to go to the parent dir
# o Changed to show directories in file list
# o Don't select images on double click any more
# o Added a 'broken image' display for files that wx fails to identify
# o Redesigned appearance -- using bitmap buttons now, and rearranged things
# o Fixed display of masked gifs
# o Fixed zooming logic to show shrunken images at correct aspect ratio
# o Added different background modes for preview (white/grey/dark/checkered)
# o Added framing modes for preview (no frame/box frame/tinted border)
# #
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# #
@@ -22,18 +32,32 @@
# o Corrected a nasty bug or two - see comments below. # o Corrected a nasty bug or two - see comments below.
# o There was a duplicate ImageView.DrawImage() method. Que? # o There was a duplicate ImageView.DrawImage() method. Que?
# #
#----------------------------------------------------------------------------
# 1.0 Release - Lorne White
# Date: January 29, 2002
# Create list of all available image file types
# View "All Image" File Types as default filter
# Sort the file list
# Use newer "re" function for patterns
#
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
import os import os
import sys import sys
import wx import wx
dir_path = os.getcwd()
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
BAD_IMAGE = -1
ID_WHITE_BG = wx.NewId()
ID_BLACK_BG = wx.NewId()
ID_GREY_BG = wx.NewId()
ID_CHECK_BG = wx.NewId()
ID_NO_FRAME = wx.NewId()
ID_BOX_FRAME = wx.NewId()
ID_CROP_FRAME = wx.NewId()
def ConvertBMP(file_nm): def ConvertBMP(file_nm):
if file_nm is None: if file_nm is None:
return None return None
@@ -42,35 +66,68 @@ def ConvertBMP(file_nm):
ext = fl_fld[1] ext = fl_fld[1]
ext = ext[1:].lower() ext = ext[1:].lower()
image = wx.Image(file_nm, wx.BITMAP_TYPE_ANY) # Don't try to create it directly because wx throws up
return image # an annoying messasge dialog if the type isn't supported.
if wx.Image.CanRead(file_nm):
image = wx.Image(file_nm, wx.BITMAP_TYPE_ANY)
return image
# BAD_IMAGE means a bad image, None just means no image (i.e. directory)
return BAD_IMAGE
def GetSize(file_nm): # for scaling image values def GetCheckeredBitmap(blocksize=8,ntiles=4,rgb0='\xFF', rgb1='\xCC'):
image = ConvertBMP(file_nm) """Creates a square RGB checkered bitmap using the two specified colors.
bmp = image.ConvertToBitmap()
size = bmp.GetWidth(), bmp.GetHeight() Inputs:
return size - blocksize: the number of pixels in each solid color square
- ntiles: the number of tiles along width and height. Each tile is 2x2 blocks.
- rbg0,rgb1: the first and second colors, as 3-byte strings.
If only 1 byte is provided, it is treated as a grey value.
The bitmap returned will have width = height = blocksize*ntiles*2
"""
size = blocksize*ntiles*2
if len(rgb0)==1:
rgb0 = rgb0 * 3
if len(rgb1)==1:
rgb1 = rgb1 * 3
strip0 = (rgb0*blocksize + rgb1*blocksize)*(ntiles*blocksize)
strip1 = (rgb1*blocksize + rgb0*blocksize)*(ntiles*blocksize)
band = strip0 + strip1
data = band * ntiles
return wx.BitmapFromBuffer(size, size, data)
def GetNamedBitmap(name):
return IMG_CATALOG[name].getBitmap()
class ImageView(wx.Window): class ImageView(wx.Window):
def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize): def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
wx.Window.__init__(self, parent, id, pos, size) style=wx.BORDER_SUNKEN
self.win = parent ):
wx.Window.__init__(self, parent, id, pos, size, style=style)
self.image = None self.image = None
self.back_color = 'WHITE'
self.border_color = 'BLACK' self.check_bmp = None
self.check_dim_bmp = None
# dark_bg is the brush/bitmap to use for painting in the whole background
# lite_bg is the brush/bitmap/pen to use for painting the image rectangle
self.dark_bg = None
self.lite_bg = None
self.border_mode = ID_CROP_FRAME
self.SetBackgroundMode( ID_WHITE_BG )
self.SetBorderMode( ID_NO_FRAME )
# Changed API of wx uses tuples for size and pos now. # Changed API of wx uses tuples for size and pos now.
self.image_sizex = size[0]
self.image_sizey = size[1]
self.image_posx = pos[0]
self.image_posy = pos[1]
self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
def OnPaint(self, event): self.Bind(wx.EVT_SIZE, self.OnSize)
dc = wx.PaintDC(self)
self.DrawImage(dc)
def SetValue(self, file_nm): # display the selected file in the panel def SetValue(self, file_nm): # display the selected file in the panel
@@ -78,56 +135,257 @@ class ImageView(wx.Window):
self.image = image self.image = image
self.Refresh() self.Refresh()
def DrawBorder(self, dc): def SetBackgroundMode(self, mode):
brush = wx.Brush(wx.NamedColour(self.back_color), wx.SOLID) self.bg_mode = mode
dc.SetBrush(brush) self._updateBGInfo()
dc.SetPen(wx.Pen(wx.NamedColour(self.border_color), 1))
dc.DrawRectangle(0, 0, self.image_sizex, self.image_sizey) def _updateBGInfo(self):
bg = self.bg_mode
border = self.border_mode
self.dark_bg = None
self.lite_bg = None
if border == ID_BOX_FRAME:
self.lite_bg = wx.BLACK_PEN
if bg == ID_WHITE_BG:
if border == ID_CROP_FRAME:
self.SetBackgroundColour('LIGHT GREY')
self.lite_bg = wx.WHITE_BRUSH
else:
self.SetBackgroundColour('WHITE')
elif bg == ID_GREY_BG:
if border == ID_CROP_FRAME:
self.SetBackgroundColour('GREY')
self.lite_bg = wx.LIGHT_GREY_BRUSH
else:
self.SetBackgroundColour('LIGHT GREY')
elif bg == ID_BLACK_BG:
if border == ID_BOX_FRAME:
self.lite_bg = wx.WHITE_PEN
if border == ID_CROP_FRAME:
self.SetBackgroundColour('GREY')
self.lite_bg = wx.BLACK_BRUSH
else:
self.SetBackgroundColour('BLACK')
else:
if self.check_bmp is None:
self.check_bmp = GetCheckeredBitmap()
self.check_dim_bmp = GetCheckeredBitmap(rgb0='\x7F', rgb1='\x66')
if border == ID_CROP_FRAME:
self.dark_bg = self.check_dim_bmp
self.lite_bg = self.check_bmp
else:
self.dark_bg = self.check_bmp
self.Refresh()
def SetBorderMode(self, mode):
self.border_mode = mode
self._updateBGInfo()
def OnSize(self, event):
event.Skip()
self.Refresh()
def OnPaint(self, event):
dc = wx.PaintDC(self)
self.DrawImage(dc)
def OnEraseBackground(self, evt):
if self.bg_mode != ID_CHECK_BG:
evt.Skip()
return
dc = evt.GetDC()
if not dc:
dc = wx.ClientDC(self)
rect = self.GetUpdateRegion().GetBox()
dc.SetClippingRect(rect)
self.PaintBackground(dc, self.dark_bg)
def PaintBackground(self, dc, painter, rect=None):
if painter is None:
return
if rect is None:
pos = self.GetPosition()
sz = self.GetSize()
else:
pos = rect.Position
sz = rect.Size
if type(painter)==wx.Brush:
dc.SetPen(wx.TRANSPARENT_PEN)
dc.SetBrush(painter)
dc.DrawRectangle(pos.x,pos.y,sz.width,sz.height)
elif type(painter)==wx.Pen:
dc.SetPen(painter)
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawRectangle(pos.x-1,pos.y-1,sz.width+2,sz.height+2)
else:
self.TileBackground(dc, painter, pos.x,pos.y,sz.width,sz.height)
def TileBackground(self, dc, bmp, x,y,w,h):
"""Tile bmp into the specified rectangle"""
bw = bmp.GetWidth()
bh = bmp.GetHeight()
dc.SetClippingRegion(x,y,w,h)
# adjust so 0,0 so we always match with a tiling starting at 0,0
dx = x % bw
x = x - dx
w = w + dx
dy = y % bh
y = y - dy
h = h + dy
tx = x
x2 = x+w
y2 = y+h
while tx < x2:
ty = y
while ty < y2:
dc.DrawBitmap(bmp, tx, ty)
ty += bh
tx += bw
def DrawImage(self, dc): def DrawImage(self, dc):
try:
image = self.image if not hasattr(self,'image') or self.image is None:
except:
return return
self.DrawBorder(dc) wwidth,wheight = self.GetSize()
image = self.image
bmp = None
if image != BAD_IMAGE and image.IsOk():
iwidth = image.GetWidth() # dimensions of image file
iheight = image.GetHeight()
else:
bmp = wx.ArtProvider.GetBitmap(wx.ART_MISSING_IMAGE, wx.ART_MESSAGE_BOX, (64,64))
iwidth = bmp.GetWidth()
iheight = bmp.GetHeight()
if image is None: # squeeze iwidth x iheight image into window, preserving aspect ratio
return
try: xfactor = float(wwidth) / iwidth
bmp = image.ConvertToBitmap() yfactor = float(wheight) / iheight
except:
return
iwidth = bmp.GetWidth() # dimensions of image file if xfactor < 1.0 and xfactor < yfactor:
iheight = bmp.GetHeight() scale = xfactor
elif yfactor < 1.0 and yfactor < xfactor:
scale = yfactor
else:
scale = 1.0
diffx = (self.image_sizex - iwidth)/2 # center calc owidth = int(scale*iwidth)
if iwidth >= self.image_sizex -10: # if image width fits in window adjust oheight = int(scale*iheight)
diffx = 5
iwidth = self.image_sizex - 10
diffy = (self.image_sizey - iheight)/2 # center calc diffx = (wwidth - owidth)/2 # center calc
if iheight >= self.image_sizey - 10: # if image height fits in window adjust diffy = (wheight - oheight)/2 # center calc
diffy = 5
iheight = self.image_sizey - 10 if not bmp:
if owidth!=iwidth or oheight!=iheight:
sc_image = sc_image = image.Scale(owidth,oheight)
else:
sc_image = image
bmp = sc_image.ConvertToBitmap()
if image != BAD_IMAGE and image.IsOk():
self.PaintBackground(dc, self.lite_bg, wx.Rect(diffx,diffy,owidth,oheight))
dc.DrawBitmap(bmp, diffx, diffy, useMask=True) # draw the image to window
class ImagePanel(wx.Panel):
def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
style=wx.NO_BORDER
):
wx.Panel.__init__(self, parent, id, pos, size, style=style)
vbox = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(vbox)
self.view = ImageView(self)
vbox.Add(self.view, 1, wx.GROW|wx.ALL, 0)
hbox_ctrls = wx.BoxSizer(wx.HORIZONTAL)
vbox.Add(hbox_ctrls, 0, wx.ALIGN_RIGHT|wx.TOP, 4)
bmp = GetNamedBitmap('White')
btn = wx.BitmapButton(self, ID_WHITE_BG, bmp, style=wx.BU_EXACTFIT)
self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
btn.SetToolTipString("Set background to white")
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
bmp = GetNamedBitmap('Grey')
btn = wx.BitmapButton(self, ID_GREY_BG, bmp, style=wx.BU_EXACTFIT)
self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
btn.SetToolTipString("Set background to grey")
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
bmp = GetNamedBitmap('Black')
btn = wx.BitmapButton(self, ID_BLACK_BG, bmp, style=wx.BU_EXACTFIT)
self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
btn.SetToolTipString("Set background to black")
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
bmp = GetNamedBitmap('Checked')
btn = wx.BitmapButton(self, ID_CHECK_BG, bmp, style=wx.BU_EXACTFIT)
self.Bind(wx.EVT_BUTTON, self.OnSetImgBackground, btn)
btn.SetToolTipString("Set background to chekered pattern")
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
hbox_ctrls.AddSpacer(7)
bmp = GetNamedBitmap('NoFrame')
btn = wx.BitmapButton(self, ID_NO_FRAME, bmp, style=wx.BU_EXACTFIT)
self.Bind(wx.EVT_BUTTON, self.OnSetBorderMode, btn)
btn.SetToolTipString("No framing around image")
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
bmp = GetNamedBitmap('BoxFrame')
btn = wx.BitmapButton(self, ID_BOX_FRAME, bmp, style=wx.BU_EXACTFIT)
self.Bind(wx.EVT_BUTTON, self.OnSetBorderMode, btn)
btn.SetToolTipString("Frame image with a box")
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
bmp = GetNamedBitmap('CropFrame')
btn = wx.BitmapButton(self, ID_CROP_FRAME, bmp, style=wx.BU_EXACTFIT|wx.BORDER_SIMPLE)
self.Bind(wx.EVT_BUTTON, self.OnSetBorderMode, btn)
btn.SetToolTipString("Frame image with a dimmed background")
hbox_ctrls.Add(btn, 0, wx.ALIGN_LEFT|wx.LEFT, 4)
def SetValue(self, file_nm): # display the selected file in the panel
self.view.SetValue(file_nm)
def SetBackgroundMode(self, mode):
self.view.SetBackgroundMode(mode)
def SetBorderMode(self, mode):
self.view.SetBorderMode(mode)
def OnSetImgBackground(self, event):
mode = event.GetId()
self.SetBackgroundMode(mode)
def OnSetBorderMode(self, event):
mode = event.GetId()
self.SetBorderMode(mode)
image.Rescale(iwidth, iheight) # rescale to fit the window
image.ConvertToBitmap()
bmp = image.ConvertToBitmap()
dc.DrawBitmap(bmp, diffx, diffy) # draw the image to window
class ImageDialog(wx.Dialog): class ImageDialog(wx.Dialog):
def __init__(self, parent, set_dir = None): def __init__(self, parent, set_dir = None):
wx.Dialog.__init__(self, parent, -1, "Image Browser", wx.DefaultPosition, (400, 400)) wx.Dialog.__init__(self, parent, -1, "Image Browser", wx.DefaultPosition, (400, 400),style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
self.x_pos = 30 # initial display positions
self.y_pos = 20
self.delta = 20
size = wx.Size(80, -1)
self.set_dir = os.getcwd() self.set_dir = os.getcwd()
self.set_file = None self.set_file = None
@@ -136,77 +394,110 @@ class ImageDialog(wx.Dialog):
if os.path.exists(set_dir): # set to working directory if nothing set if os.path.exists(set_dir): # set to working directory if nothing set
self.set_dir = set_dir self.set_dir = set_dir
self.dir_x = self.x_pos vbox_top = wx.BoxSizer(wx.VERTICAL)
self.dir_y = self.y_pos self.SetSizer(vbox_top)
self.dir = wx.StaticText(self, -1, self.set_dir, (self.dir_x, self.dir_y), (250, -1))
self.y_pos = self.y_pos + self.delta hbox_loc = wx.BoxSizer(wx.HORIZONTAL)
vbox_top.Add(hbox_loc, 0, wx.GROW|wx.ALIGN_LEFT|wx.ALL, 0)
btn = wx.Button(self, 12331, ' Set Directory ', (self.x_pos, self.y_pos)) loc_label = wx.StaticText( self, -1, "Folder:")
self.Bind(wx.EVT_BUTTON, self.SetDirect, btn) hbox_loc.Add(loc_label, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.ADJUST_MINSIZE, 5)
self.type_posy = self.y_pos # save the y position for the image type combo self.dir = wx.TextCtrl( self, -1, self.set_dir, style=wx.TE_RICH|wx.TE_PROCESS_ENTER)
self.Bind(wx.EVT_TEXT_ENTER, self.OnDirectoryTextSet, self.dir)
hbox_loc.Add(self.dir, 1, wx.GROW|wx.ALIGN_LEFT|wx.ALL, 5)
up_bmp = wx.ArtProvider.GetBitmap(wx.ART_GO_DIR_UP, wx.ART_BUTTON, (16,16))
btn = wx.BitmapButton(self, -1, up_bmp)
btn.SetHelpText("Up one level")
btn.SetToolTipString("Up one level")
self.Bind(wx.EVT_BUTTON, self.OnUpDirectory, btn)
hbox_loc.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 2)
folder_bmp = wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN, wx.ART_BUTTON, (16,16))
btn = wx.BitmapButton(self, -1, folder_bmp)
btn.SetHelpText("Browse for a &folder...")
btn.SetToolTipString("Browse for a folder...")
self.Bind(wx.EVT_BUTTON, self.OnChooseDirectory, btn)
hbox_loc.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
hbox_nav = wx.BoxSizer(wx.HORIZONTAL)
vbox_top.Add(hbox_nav, 0, wx.ALIGN_LEFT|wx.ALL, 0)
label = wx.StaticText( self, -1, "Files of type:")
hbox_nav.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
self.fl_ext = '*.bmp' # initial setting for file filtering self.fl_ext = '*.bmp' # initial setting for file filtering
self.GetFiles() # get the file list self.GetFiles() # get the file list
self.y_pos = self.y_pos + self.delta + 10 self.fl_ext_types = (
self.list_height = 150 # display, filter
("All supported formats", "All"),
("BMP (*.bmp)", "*.bmp"),
("GIF (*.gif)", "*.gif"),
("PNG (*.png)", "*.png"),
("JPEG (*.jpg)", "*.jpg"),
("ICO (*.ico)", "*.ico"),
("PNM (*.pnm)", "*.pnm"),
("PCX (*.pcx)", "*.pcx"),
("TIFF (*.tif)", "*.tif"),
("All Files", "*.*"),
)
self.set_type,self.fl_ext = self.fl_ext_types[0] # initial file filter setting
self.fl_types = [ x[0] for x in self.fl_ext_types ]
self.sel_type = wx.ComboBox( self, -1, self.set_type,
wx.DefaultPosition, wx.DefaultSize, self.fl_types,
wx.CB_DROPDOWN )
# after this we don't care about the order any more
self.fl_ext_types = dict(self.fl_ext_types)
# List of Labels self.Bind(wx.EVT_COMBOBOX, self.OnSetType, self.sel_type)
self.tb = tb = wx.ListBox(self, -1, (self.x_pos, self.y_pos), hbox_nav.Add(self.sel_type, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
(160, self.list_height), self.fl_list,
wx.LB_SINGLE ) splitter = wx.SplitterWindow( self, -1, wx.DefaultPosition, wx.Size(100, 100), 0 )
splitter.SetMinimumPaneSize(100)
split_left = wx.Panel( splitter, -1, wx.DefaultPosition, wx.DefaultSize,
wx.NO_BORDER|wx.TAB_TRAVERSAL )
vbox_left = wx.BoxSizer(wx.VERTICAL)
split_left.SetSizer(vbox_left)
self.tb = tb = wx.ListBox( split_left, -1, wx.DefaultPosition, wx.DefaultSize,
self.fl_list, wx.LB_SINGLE )
self.Bind(wx.EVT_LISTBOX, self.OnListClick, tb) self.Bind(wx.EVT_LISTBOX, self.OnListClick, tb)
self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnListDClick, tb) self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnListDClick, tb)
vbox_left.Add(self.tb, 1, wx.GROW|wx.ALL, 0)
width, height = self.tb.GetSize() width, height = self.tb.GetSize()
image_posx = self.x_pos + width + 20 # positions for setting the image window
image_posy = self.y_pos
image_sizex = 150
image_sizey = self.list_height
self.fl_types = [ split_right = wx.Panel( splitter, -1, wx.DefaultPosition, wx.DefaultSize,
"All Images", "Bmp", "Gif", "Png", "Jpg", "Ico", "Pnm", wx.NO_BORDER|wx.TAB_TRAVERSAL )
"Pcx", "Tif", "All Files" vbox_right = wx.BoxSizer(wx.VERTICAL)
] split_right.SetSizer(vbox_right)
self.fl_ext_types = { self.image_view = ImagePanel( split_right )
"All Images": "All", vbox_right.Add(self.image_view, 1, wx.GROW|wx.ALL, 0)
"Bmp": "*.bmp",
"Gif": "*.gif",
"Png": "*.png",
"Jpg": "*.jpg",
"Ico": "*.ico",
"Pnm": "*.pnm",
"Pcx": "*.pcx",
"Tif": "*.tif",
"All Files": "*.*"
}
self.set_type = self.fl_types[0] # initial file filter setting splitter.SplitVertically(split_left, split_right, 150)
self.fl_ext = self.fl_ext_types[self.set_type] vbox_top.Add(splitter, 1, wx.GROW|wx.ALL, 5)
self.sel_type = wx.ComboBox(self, -1, self.set_type, (image_posx , self.type_posy), hbox_btns = wx.BoxSizer(wx.HORIZONTAL)
(150, -1), self.fl_types, wx.CB_DROPDOWN) vbox_top.Add(hbox_btns, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
self.Bind(wx.EVT_COMBOBOX, self.OnSetType, self.sel_type)
self.image_view = ImageView( self, pos=(image_posx, image_posy), ok_btn = wx.Button( self, wx.ID_OPEN, "", wx.DefaultPosition, wx.DefaultSize, 0 )
size=(image_sizex, image_sizey)) self.Bind(wx.EVT_BUTTON, self.OnOk, ok_btn)
#ok_btn.SetDefault()
hbox_btns.Add(ok_btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
self.y_pos = self.y_pos + height + 20 cancel_btn = wx.Button( self, wx.ID_CANCEL, "",
wx.DefaultPosition, wx.DefaultSize, 0 )
btn = wx.Button(self, -1, ' Select ', (100, self.y_pos), size) hbox_btns.Add(cancel_btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
self.Bind(wx.EVT_BUTTON, self.OnOk, btn)
wx.Button(self, wx.ID_CANCEL, 'Cancel', (250, self.y_pos), size)
self.y_pos = self.y_pos + self.delta
fsize = (400, self.y_pos + 50) # resize dialog for final vertical position
self.SetSize(fsize)
self.ResetFiles() self.ResetFiles()
def GetFiles(self): # get the file list using directory and extension values def GetFiles(self): # get the file list using directory and extension values
if self.fl_ext == "All": if self.fl_ext == "All":
all_files = [] all_files = []
@@ -222,11 +513,17 @@ class ImageDialog(wx.Dialog):
self.fl_val = FindFiles(self, self.set_dir, self.fl_ext) self.fl_val = FindFiles(self, self.set_dir, self.fl_ext)
self.fl_list = self.fl_val.files self.fl_list = self.fl_val.files
self.fl_list.sort() # sort the file list self.fl_list.sort() # sort the file list
# prepend the directories
self.fl_ndirs = len(self.fl_val.dirs)
self.fl_list = sorted(self.fl_val.dirs) + self.fl_list
def DisplayDir(self): # display the working directory def DisplayDir(self): # display the working directory
if self.dir: if self.dir:
self.dir.SetLabel(self.set_dir) ipt = self.dir.GetInsertionPoint()
self.dir.SetValue(self.set_dir)
self.dir.SetInsertionPoint(ipt)
def OnSetType(self, event): def OnSetType(self, event):
val = event.GetString() # get file type value val = event.GetString() # get file type value
@@ -234,7 +531,7 @@ class ImageDialog(wx.Dialog):
self.ResetFiles() self.ResetFiles()
def OnListDClick(self, event): def OnListDClick(self, event):
self.OnOk(0) self.OnOk('dclick')
def OnListClick(self, event): def OnListClick(self, event):
val = event.GetSelection() val = event.GetSelection()
@@ -243,9 +540,40 @@ class ImageDialog(wx.Dialog):
def SetListValue(self, val): def SetListValue(self, val):
file_nm = self.fl_list[val] file_nm = self.fl_list[val]
self.set_file = file_val = os.path.join(self.set_dir, file_nm) self.set_file = file_val = os.path.join(self.set_dir, file_nm)
self.image_view.SetValue(file_val) if val>=self.fl_ndirs:
self.image_view.SetValue(file_val)
else:
self.image_view.SetValue(None)
def SetDirect(self, event): # set the new directory def OnDirectoryTextSet(self,event):
event.Skip()
path = event.GetString()
if os.path.isdir(path):
self.set_dir = path
self.ResetFiles()
return
if os.path.isfile(path):
dname,fname = os.path.split(path)
if os.path.isdir(dname):
self.ResetFiles()
# try to select fname in list
try:
idx = self.fl_list.index(fname)
self.tb.SetSelection(idx)
self.SetListValue(idx)
return
except ValueError:
pass
wx.Bell()
def OnUpDirectory(self, event):
sdir = os.path.split(self.set_dir)[0]
self.set_dir = sdir
self.ResetFiles()
def OnChooseDirectory(self, event): # set the new directory
dlg = wx.DirDialog(self) dlg = wx.DirDialog(self)
dlg.SetPath(self.set_dir) dlg.SetPath(self.set_dir)
@@ -278,6 +606,12 @@ class ImageDialog(wx.Dialog):
if len(self.fl_list): if len(self.fl_list):
self.tb.Set(self.fl_list) self.tb.Set(self.fl_list)
for idir in xrange(self.fl_ndirs):
d = self.fl_list[idir]
# mark directories as 'True' with client data
self.tb.SetClientData(idir, True)
self.tb.SetString(idir,'['+d+']')
try: try:
self.tb.SetSelection(0) self.tb.SetSelection(0)
self.SetListValue(0) self.SetListValue(0)
@@ -297,24 +631,24 @@ class ImageDialog(wx.Dialog):
self.EndModal(wx.ID_CANCEL) self.EndModal(wx.ID_CANCEL)
def OnOk(self, event): def OnOk(self, event):
self.result = self.set_file if os.path.isdir(self.set_file):
self.EndModal(wx.ID_OK) sdir = os.path.split(self.set_file)
#os.path.normapth?
if sdir and sdir[-1]=='..':
sdir = os.path.split(sdir[0])[0]
sdir = os.path.split(sdir)
self.set_dir = os.path.join(*sdir)
self.set_file = None
self.ResetFiles()
elif event != 'dclick':
self.result = self.set_file
self.EndModal(wx.ID_OK)
def OnFileDlg(self):
dlg = wx.FileDialog(self, "Choose an Image File", ".", "",
"Bmp (*.bmp)|*.bmp|JPEG (*.jpg)|*.jpg", wx.OPEN)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
else:
path = None
dlg.Destroy()
return path
class FindFiles: class FindFiles:
def __init__(self, parent, dir, mask): def __init__(self, parent, dir, mask, with_dirs=True):
filelist = [] filelist = []
dirlist = [".."] dirlist = [".."]
self.dir = dir self.dir = dir
@@ -327,13 +661,21 @@ class FindFiles:
continue continue
path = os.path.join(dir, i) path = os.path.join(dir, i)
if os.path.isdir(path):
dirlist.append(i)
continue
path = path.upper() path = path.upper()
value = i.upper() value = i.upper()
if pattern.match(value) != None: if pattern.match(value) != None:
filelist.append(i) filelist.append(i)
self.files = filelist self.files = filelist
if with_dirs:
self.dirs = dirlist
def MakeRegex(self, pattern): def MakeRegex(self, pattern):
import re import re
@@ -356,3 +698,166 @@ class FindFiles:
fl_name = fl_fld[0] fl_name = fl_fld[0]
ext = fl_fld[1] ext = fl_fld[1]
return ext[1:] return ext[1:]
#----------------------------------------------------------------------
# This part of the file was generated by C:\Python25\Scripts\img2py
# then edited slightly.
import cStringIO, zlib
IMG_CATALOG = {}
class ImageClass: pass
def getWhiteData():
return zlib.decompress(
'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2< \xcc\xc1\x04$\
o\x8a\x9f\xde\x00\xa4\x98\x8b\x9d<C888n?\xf4\x7f\x00\xe4*z\xba8\x86HLMNP`202\
0\xf8\xf3\xff\xbf\xfc|.77\xb5$\x1f\xa9P\x979J\x8b\x18\x18N\\d\x16\t\xfd\xfc\
\xce\x07\xa8\x98\xc1\xd3\xd5\xcfe\x9dSB\x13\x00\xcc1\x1b\xb3' )
def getWhiteBitmap():
return wx.BitmapFromImage(getWhiteImage())
def getWhiteImage():
stream = cStringIO.StringIO(getWhiteData())
return wx.ImageFromStream(stream)
IMG_CATALOG['White'] = ImageClass()
IMG_CATALOG['White'].getData = getWhiteData
IMG_CATALOG['White'].getImage = getWhiteImage
IMG_CATALOG['White'].getBitmap = getWhiteBitmap
#----------------------------------------------------------------------
def getGreyData():
return zlib.decompress(
'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2< \xcc\xc1\x04$\
o\x8a\x9f\xde\x00\xa4\x98\x8b\x9d<C888n?\xf4\x7f\x00\xe4*y\xba8\x86HLMNP`202\
0\x98cY\xcc\xd6\xcf%,,\xac\x96\xe4#\x15\xea2Gi\x11\x03\xc3\xb6\xc7\xcc":A7%\
\x80\xaa\x19<]\xfd\\\xd69%4\x01\x00{m\x18s' )
def getGreyBitmap():
return wx.BitmapFromImage(getGreyImage())
def getGreyImage():
stream = cStringIO.StringIO(getGreyData())
return wx.ImageFromStream(stream)
IMG_CATALOG['Grey'] = ImageClass()
IMG_CATALOG['Grey'].getData = getGreyData
IMG_CATALOG['Grey'].getImage = getGreyImage
IMG_CATALOG['Grey'].getBitmap = getGreyBitmap
#----------------------------------------------------------------------
def getBlackData():
return zlib.decompress(
'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2< \xcc\xc1\x04$\
o\x8a\x9f\xde\x00\xa4\x98\x8b\x9d<C888n?\xf4\x7f\x00\xe4\xf2y\xba8\x86HLMN\
\x90`u\x16e``\xdc\xc3\xc0h\\3\xdb\x0c(\xc3\xe0\xe9\xea\xe7\xb2\xce)\xa1\t\
\x00\xb6`\x12\x08' )
def getBlackBitmap():
return wx.BitmapFromImage(getBlackImage())
def getBlackImage():
stream = cStringIO.StringIO(getBlackData())
return wx.ImageFromStream(stream)
IMG_CATALOG['Black'] = ImageClass()
IMG_CATALOG['Black'].getData = getBlackData
IMG_CATALOG['Black'].getImage = getBlackImage
IMG_CATALOG['Black'].getBitmap = getBlackBitmap
#----------------------------------------------------------------------
def getCheckedData():
return zlib.decompress(
'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2< \xcc\xc1\x04$\
o\x8a\x9f\xde\x00\xa4\x98\x8b\x9d<C888n?\xf4\x7f\x00\xe4\x1az\xba8\x86HLMNP`\
2020\x98cY\xcc\x16y\xe2\xc6\r\tWVeeaC\xb5\x8b\x91\x82\xdc\xccm\xde\xe7\xe7\
\xd9Zo\xc8S\xf2\x12\x0cd`\xd0\xd8\xc5&\xf6\xeb\xd5\xe5t\xa0f\x06OW?\x97uN\tM\
\x00qL\x1f\x94' )
def getCheckedBitmap():
return wx.BitmapFromImage(getCheckedImage())
def getCheckedImage():
stream = cStringIO.StringIO(getCheckedData())
return wx.ImageFromStream(stream)
IMG_CATALOG['Checked'] = ImageClass()
IMG_CATALOG['Checked'].getData = getCheckedData
IMG_CATALOG['Checked'].getImage = getCheckedImage
IMG_CATALOG['Checked'].getBitmap = getCheckedBitmap
#----------------------------------------------------------------------
def getNoFrameData():
return zlib.decompress(
"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2< \xcc\xc1\x04$\
o\x8a\x9f\xde\x00\xa4\x98\x8b\x9d<C888n?\xf4\x7f\x00\xe4\x9ay\xba8\x86HL]\
\xdb\xef\xc8\xc5\xa0 \xc04\xf7\xc5\xff\xf8m\xd1\x01.\xba\x93\x9e'\x86\xac\
\x14P\xb9\xb9O\xf0\x82\xd62\x0e\xa6\x06\xf9e\x8f;Yg\xc5F'\xd7g]\xf2\xadd;=\
\x87S\xfe\xf3\xc7\x15\x8f\x80&0x\xba\xfa\xb9\xacsJh\x02\x00\x07\xac't" )
def getNoFrameBitmap():
return wx.BitmapFromImage(getNoFrameImage())
def getNoFrameImage():
stream = cStringIO.StringIO(getNoFrameData())
return wx.ImageFromStream(stream)
IMG_CATALOG['NoFrame'] = ImageClass()
IMG_CATALOG['NoFrame'].getData = getNoFrameData
IMG_CATALOG['NoFrame'].getImage = getNoFrameImage
IMG_CATALOG['NoFrame'].getBitmap = getNoFrameBitmap
#----------------------------------------------------------------------
def getBoxFrameData():
return zlib.decompress(
"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2< \xcc\xc1\x04$\
o\x8a\x9f\xde\x00\xa4\x98\x8b\x9d<C888n?\xf4\x7f\x00\xe4:{\xba8\x86HL\x9d\
\xdbw\x91\x8bA\x81\x83\xb9\xfc\xd2\xff\xff\x9bl9\x02\x15\xd5\xdefnJ\xf6\xcb\
\xe2\xf0|\x17'\x980W\xed\xaa\xaf\xe0\xcd:\xfd\xaa\xef\xec!/\xda.]ggaH\xfcT\
\xbaRI\xca_\xef\xe6\x97\xf5\x9c;\xa2\x15\xfe\xbe^S\xbe\th\x1c\x83\xa7\xab\
\x9f\xcb:\xa7\x84&\x00k\xdd.\x08" )
def getBoxFrameBitmap():
return wx.BitmapFromImage(getBoxFrameImage())
def getBoxFrameImage():
stream = cStringIO.StringIO(getBoxFrameData())
return wx.ImageFromStream(stream)
IMG_CATALOG['BoxFrame'] = ImageClass()
IMG_CATALOG['BoxFrame'].getData = getBoxFrameData
IMG_CATALOG['BoxFrame'].getImage = getBoxFrameImage
IMG_CATALOG['BoxFrame'].getBitmap = getBoxFrameBitmap
#----------------------------------------------------------------------
def getCropFrameData():
return zlib.decompress(
"x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2< \xcc\xc1\x04$\
o\x8a\x9f\xde\x00\xa4\x98\x8b\x9d<C888n?\xf4\x7f\x00\xe4zz\xba8\x86HL\xdd;\
\xc1\x90\xeb\x80\x03\x07K\xba\xf3\xbf\xd5\xfe\x17\xc5g;\xedh\x16i\xcf\xdc\
\xd4z\xc2\xa8G\x81GIA\x89\xafew\xbc\xf0e\x8e]\xd7\xd3\xd2\x1aT\x16\xacj8\xf3\
'\xa1\xca\xf9\xad\x85\xe3\xa4_1\xe7\xef~~\xcd\xedV\xc9\xf0\x7f#\xbftm\xb5\
\x8d\t\x03\xc8TW?\x97uN\tM\x00\x9c@0\x82" )
def getCropFrameBitmap():
return wx.BitmapFromImage(getCropFrameImage())
def getCropFrameImage():
stream = cStringIO.StringIO(getCropFrameData())
return wx.ImageFromStream(stream)
IMG_CATALOG['CropFrame'] = ImageClass()
IMG_CATALOG['CropFrame'].getData = getCropFrameData
IMG_CATALOG['CropFrame'].getImage = getCropFrameImage
IMG_CATALOG['CropFrame'].getBitmap = getCropFrameBitmap

View File

@@ -511,6 +511,8 @@ class InspectionInfoPanel(wx.stc.StyledTextCtrl):
st.append(self.Fmt('name', obj.GetName())) st.append(self.Fmt('name', obj.GetName()))
st.append(self.Fmt('class', obj.__class__)) st.append(self.Fmt('class', obj.__class__))
st.append(self.Fmt('bases', obj.__class__.__bases__)) st.append(self.Fmt('bases', obj.__class__.__bases__))
if hasattr(obj, 'this'):
st.append(self.Fmt('this', repr(obj.this)))
st.append(self.Fmt('id', obj.GetId())) st.append(self.Fmt('id', obj.GetId()))
st.append(self.Fmt('style', obj.GetWindowStyle())) st.append(self.Fmt('style', obj.GetWindowStyle()))
st.append(self.Fmt('pos', obj.GetPosition())) st.append(self.Fmt('pos', obj.GetPosition()))
@@ -561,6 +563,8 @@ class InspectionInfoPanel(wx.stc.StyledTextCtrl):
def FmtSizer(self, obj): def FmtSizer(self, obj):
st = ['Sizer:'] st = ['Sizer:']
st.append(self.Fmt('class', obj.__class__)) st.append(self.Fmt('class', obj.__class__))
if hasattr(obj, 'this'):
st.append(self.Fmt('this', repr(obj.this)))
st.append(self.Fmt('pos', obj.GetPosition())) st.append(self.Fmt('pos', obj.GetPosition()))
st.append(self.Fmt('size', obj.GetSize())) st.append(self.Fmt('size', obj.GetSize()))
st.append(self.Fmt('minsize', obj.GetMinSize())) st.append(self.Fmt('minsize', obj.GetMinSize()))

View File

@@ -22,20 +22,25 @@ def get_acroversion():
global _acroversion global _acroversion
if _acroversion == None: if _acroversion == None:
import _winreg import _winreg
acrosoft = [r'SOFTWARE\Adobe\Acrobat Reader\%version%\InstallPath', adobesoft = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r'Software\Adobe')
r'SOFTWARE\Adobe\Adobe Acrobat\%version%\InstallPath',] acrokeys, acroversions = [], []
for index in range(_winreg.QueryInfoKey(adobesoft)[0]):
for regkey in acrosoft: key = _winreg.EnumKey(adobesoft, index)
for version in ('7.0', '6.0', '5.0', '4.0'): if "acrobat" in key.lower():
acrokeys.append(_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'Software\\Adobe\\%s' % key))
for acrokey in acrokeys:
for index in range(_winreg.QueryInfoKey(acrokey)[0]):
key = _winreg.EnumKey(acrokey, index)
try: try:
path = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE, acroversions.append(float(key))
regkey.replace('%version%', version))
_acroversion = version
break
except: except:
continue pass
acroversions.sort(reverse=True)
if acroversions:
_acroversion = acroversions[0]
return _acroversion return _acroversion
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# The ActiveX module from Acrobat 7.0 has changed and it seems to now # The ActiveX module from Acrobat 7.0 has changed and it seems to now
@@ -54,7 +59,7 @@ def get_acroversion():
# Co-ordinates passed as parameters are in points (1/72 inch). # Co-ordinates passed as parameters are in points (1/72 inch).
if get_acroversion() >= '7.0': if get_acroversion() >= 7.0:
from wx.lib.activexwrapper import MakeActiveXClass from wx.lib.activexwrapper import MakeActiveXClass
import win32com.client.gencache import win32com.client.gencache

View File

@@ -292,6 +292,22 @@ class Shell(editwindow.EditWindow):
self.Bind(wx.EVT_CHAR, self.OnChar) self.Bind(wx.EVT_CHAR, self.OnChar)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
# Assign handler for the context menu
self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI)
# Assign handlers for edit events
self.Bind(wx.EVT_MENU, lambda evt: self.Cut(), id=wx.ID_CUT)
self.Bind(wx.EVT_MENU, lambda evt: self.Copy(), id=wx.ID_COPY)
self.Bind(wx.EVT_MENU, lambda evt: self.CopyWithPrompts(), id=frame.ID_COPY_PLUS)
self.Bind(wx.EVT_MENU, lambda evt: self.Paste(), id=wx.ID_PASTE)
self.Bind(wx.EVT_MENU, lambda evt: self.PasteAndRun(), id=frame.ID_PASTE_PLUS)
self.Bind(wx.EVT_MENU, lambda evt: self.SelectAll(), id=wx.ID_SELECTALL)
self.Bind(wx.EVT_MENU, lambda evt: self.Clear(), id=wx.ID_CLEAR)
self.Bind(wx.EVT_MENU, lambda evt: self.Undo(), id=wx.ID_UNDO)
self.Bind(wx.EVT_MENU, lambda evt: self.Redo(), id=wx.ID_REDO)
# Assign handler for idle time. # Assign handler for idle time.
self.waiting = False self.waiting = False
self.Bind(wx.EVT_IDLE, self.OnIdle) self.Bind(wx.EVT_IDLE, self.OnIdle)
@@ -1367,6 +1383,48 @@ Platform: %s""" % \
config.WriteBool('View/ShowLineNumbers', self.lineNumbers) config.WriteBool('View/ShowLineNumbers', self.lineNumbers)
config.WriteInt('View/Zoom/Shell', self.GetZoom()) config.WriteInt('View/Zoom/Shell', self.GetZoom())
def GetContextMenu(self):
"""
Create and return a context menu for the shell.
This is used instead of the scintilla default menu
in order to correctly respect our immutable buffer.
"""
menu = wx.Menu()
menu.Append(wx.ID_UNDO, "Undo")
menu.Append(wx.ID_REDO, "Redo")
menu.AppendSeparator()
menu.Append(wx.ID_CUT, "Cut")
menu.Append(wx.ID_COPY, "Copy")
menu.Append(frame.ID_COPY_PLUS, "Copy Plus")
menu.Append(wx.ID_PASTE, "Paste")
menu.Append(frame.ID_PASTE_PLUS, "Paste Plus")
menu.Append(wx.ID_CLEAR, "Clear")
menu.AppendSeparator()
menu.Append(wx.ID_SELECTALL, "Select All")
return menu
def OnContextMenu(self, evt):
menu = self.GetContextMenu()
self.PopupMenu(menu)
def OnUpdateUI(self, evt):
id = evt.Id
if id in (wx.ID_CUT, wx.ID_CLEAR):
evt.Enable(self.CanCut())
elif id in (wx.ID_COPY, frame.ID_COPY_PLUS):
evt.Enable(self.CanCopy())
elif id in (wx.ID_PASTE, frame.ID_PASTE_PLUS):
evt.Enable(self.CanPaste())
elif id == wx.ID_UNDO:
evt.Enable(self.CanUndo())
elif id == wx.ID_REDO:
evt.Enable(self.CanRedo())
## NOTE: The DnD of file names is disabled until I can figure out how ## NOTE: The DnD of file names is disabled until I can figure out how

View File

@@ -304,7 +304,7 @@ class ParamFont(PPanel):
except KeyError: error = True; wx.LogError('Invalid style specification') except KeyError: error = True; wx.LogError('Invalid style specification')
try: weight = fontWeightsXml2wx[self.value[3]] try: weight = fontWeightsXml2wx[self.value[3]]
except KeyError: error = True; wx.LogError('Invalid weight specification') except KeyError: error = True; wx.LogError('Invalid weight specification')
try: underlined = bool(self.value[4]) try: underlined = bool(int(self.value[4]))
except ValueError: error = True; wx.LogError('Invalid underlined flag specification') except ValueError: error = True; wx.LogError('Invalid underlined flag specification')
face = self.value[5] face = self.value[5]
except IndexError: except IndexError:

View File

@@ -197,7 +197,7 @@ class xxxObject:
# Special parameters # Special parameters
specials = [] specials = []
# Bitmap tags # Bitmap tags
bitmapTags = ['bitmap', 'bitmap2', 'icon'] bitmapTags = ['bitmap', 'bitmap2', 'icon', 'selected', 'focus', 'disabled']
# Required paremeters: none by default # Required paremeters: none by default
required = [] required = []
# Default parameters with default values # Default parameters with default values

View File

@@ -148,7 +148,8 @@ wxID_HTML_SEARCHCHOICE = wx.html.ID_HTML_SEARCHCHOICE
wxID_HTML_COUNTINFO = wx.html.ID_HTML_COUNTINFO wxID_HTML_COUNTINFO = wx.html.ID_HTML_COUNTINFO
wxHtmlHelpWindow = wx.html.HtmlHelpWindow wxHtmlHelpWindow = wx.html.HtmlHelpWindow
wxPreHtmlHelpWindow = wx.html.PreHtmlHelpWindow wxPreHtmlHelpWindow = wx.html.PreHtmlHelpWindow
wxHtmlWindowEvent = wx.html.HtmlWindowEvent wxHtmlCellEvent = wx.html.HtmlCellEvent
wxHtmlLinkEvent = wx.html.HtmlLinkEvent
wxHtmlHelpFrame = wx.html.HtmlHelpFrame wxHtmlHelpFrame = wx.html.HtmlHelpFrame
wxPreHtmlHelpFrame = wx.html.PreHtmlHelpFrame wxPreHtmlHelpFrame = wx.html.PreHtmlHelpFrame
wxHtmlHelpDialog = wx.html.HtmlHelpDialog wxHtmlHelpDialog = wx.html.HtmlHelpDialog