From 4a61305d364dcf229395fb223daec31e2d6efcb4 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Thu, 6 Dec 2001 19:59:37 +0000 Subject: [PATCH] Added wxDllWidget from Vaclav Slavik which allows wx widgets derived from wxWindow to be loaded from a C++ .dll (or .so) and be used in a wxPython program, without the widget having to be SWIGged first. Various updates for distribs git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@12890 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- wxPython/CHANGES.txt | 8 + wxPython/MANIFEST.in | 14 + wxPython/contrib/dllwidget/dllwidget.cpp | 128 ++++++ wxPython/contrib/dllwidget/dllwidget.h | 143 ++++++ wxPython/contrib/dllwidget/dllwidget.py | 6 + wxPython/contrib/dllwidget/dllwidget_.cpp | 501 ++++++++++++++++++++++ wxPython/contrib/dllwidget/dllwidget_.i | 111 +++++ wxPython/contrib/dllwidget/dllwidget_.py | 76 ++++ wxPython/demo/dllwidget/Makefile | 19 + wxPython/demo/dllwidget/makefile.vc | 32 ++ wxPython/demo/dllwidget/test_dll.cpp | 54 +++ wxPython/demo/dllwidget/test_prog.py | 82 ++++ wxPython/distrib/make_installer.py | 9 +- wxPython/setup.py | 40 +- 14 files changed, 1218 insertions(+), 5 deletions(-) create mode 100644 wxPython/contrib/dllwidget/dllwidget.cpp create mode 100644 wxPython/contrib/dllwidget/dllwidget.h create mode 100644 wxPython/contrib/dllwidget/dllwidget.py create mode 100644 wxPython/contrib/dllwidget/dllwidget_.cpp create mode 100644 wxPython/contrib/dllwidget/dllwidget_.i create mode 100644 wxPython/contrib/dllwidget/dllwidget_.py create mode 100644 wxPython/demo/dllwidget/Makefile create mode 100644 wxPython/demo/dllwidget/makefile.vc create mode 100644 wxPython/demo/dllwidget/test_dll.cpp create mode 100644 wxPython/demo/dllwidget/test_prog.py diff --git a/wxPython/CHANGES.txt b/wxPython/CHANGES.txt index c3afe48498..6285dc385f 100644 --- a/wxPython/CHANGES.txt +++ b/wxPython/CHANGES.txt @@ -105,6 +105,14 @@ wxRemotelyScrolledTreeCtrl, wxTreeCompanionWindow, wxThinSplitterWindow, and wxSplitterScrolledWindow, some of which may also be useful by themselves. +Added wxDllWidget from Vaclav Slavik which allows wx widgets derived +from wxWindow to be loaded from a C++ .dll (or .so) and be used in a +wxPython program, without the widget having to be SWIGged first. The +visible API of the widget is limited to wxWindow methods plus a +SendCommand method, but it is still quite powerful. See +wxPython/contrib/dllwidget and wxPython/demo/dllwidget for more +details. + diff --git a/wxPython/MANIFEST.in b/wxPython/MANIFEST.in index 60183f925c..c9eb040343 100644 --- a/wxPython/MANIFEST.in +++ b/wxPython/MANIFEST.in @@ -166,3 +166,17 @@ include contrib/gizmos/*.c include contrib/gizmos/*.h include contrib/gizmos/contrib/include/wx/gizmos/*.h include contrib/gizmos/contrib/src/gizmos/*.cpp + +include contrib/dllwidget/*.txt +include contrib/dllwidget/*.i +include contrib/dllwidget/*.py +include contrib/dllwidget/*.cpp +include contrib/dllwidget/*.c +include contrib/dllwidget/*.h + +include demo/dllwidget/*.h +include demo/dllwidget/*.cpp +include demo/dllwidget/*.py +include demo/dllwidget/Makefile +include demo/dllwidget/makefile.* + diff --git a/wxPython/contrib/dllwidget/dllwidget.cpp b/wxPython/contrib/dllwidget/dllwidget.cpp new file mode 100644 index 0000000000..7e39d634fd --- /dev/null +++ b/wxPython/contrib/dllwidget/dllwidget.cpp @@ -0,0 +1,128 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: dllwidget.cpp +// Purpose: Dynamically loadable C++ widget for wxPython +// Author: Vaclav Slavik +// Created: 2001/12/03 +// RCS-ID: $Id$ +// Copyright: (c) 2001 Vaclav Slavik +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation "dllwidget.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#include "wx/defs.h" +#include "wx/dynlib.h" +#include "wx/sizer.h" + +#include "dllwidget.h" + + +IMPLEMENT_ABSTRACT_CLASS(wxDllWidget, wxPanel) + +wxDllWidget::wxDllWidget(wxWindow *parent, + wxWindowID id, + const wxString& dllName, const wxString& className, + const wxPoint& pos, const wxSize& size, + long style) + : wxPanel(parent, id, pos, size, wxTAB_TRAVERSAL | wxNO_BORDER, + className + wxT("_container")), + m_widget(NULL), m_lib(NULL), m_controlAdded(FALSE) +{ + SetBackgroundColour(wxColour(255, 0, 255)); + if ( !!className ) + LoadWidget(dllName, className, style); +} + +wxDllWidget::~wxDllWidget() +{ + UnloadWidget(); +} + +void wxDllWidget::AddChild(wxWindowBase *child) +{ + wxASSERT_MSG( !m_controlAdded, wxT("Couldn't load two widgets into one container!") ) + + wxPanel::AddChild(child); + + m_controlAdded = TRUE; + wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add((wxWindow*)child, 1, wxEXPAND); + SetSizer(sizer); + SetAutoLayout(TRUE); + Layout(); +} + + +wxString wxDllWidget::GetDllExt() +{ + return wxDllLoader::GetDllExt(); +} + + +typedef WXDLLEXPORT bool (*DLL_WidgetFactory_t)(const wxString& className, + wxWindow *parent, + long style, + wxWindow **classInst, + wxSendCommandFunc *cmdFunc); + +bool wxDllWidget::LoadWidget(const wxString& dll, const wxString& className, + long style) +{ + UnloadWidget(); + + // Load the dynamic library + m_lib = new wxDynamicLibrary(dll); + if ( !m_lib->IsLoaded() ) + { + delete m_lib; + m_lib = NULL; + return FALSE; + } + + DLL_WidgetFactory_t factory; + factory = (DLL_WidgetFactory_t) m_lib->GetSymbol(wxT("DLL_WidgetFactory")); + if ( factory == NULL) + { + delete m_lib; + m_lib = NULL; + return FALSE; + } + + if ( !factory(className, this, style, &m_widget, &m_cmdFunc) ) + { + delete m_widget; + delete m_lib; + m_lib = NULL; + m_widget = NULL; + return FALSE; + } + + return TRUE; +} + +void wxDllWidget::UnloadWidget() +{ + if ( m_widget ) + { + DestroyChildren(); + m_widget = NULL; + delete m_lib; + m_lib = NULL; + } +} + +int wxDllWidget::SendCommand(int cmd, const wxString& param) +{ + wxASSERT_MSG( m_widget && m_cmdFunc, wxT("Sending command to not loaded widget!")); + + return m_cmdFunc(m_widget, cmd, param); +} diff --git a/wxPython/contrib/dllwidget/dllwidget.h b/wxPython/contrib/dllwidget/dllwidget.h new file mode 100644 index 0000000000..daf209c82d --- /dev/null +++ b/wxPython/contrib/dllwidget/dllwidget.h @@ -0,0 +1,143 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: dllwidget.h +// Purpose: Dynamically loadable C++ widget for wxPython +// Author: Vaclav Slavik +// Created: 2001/12/03 +// RCS-ID: $Id$ +// Copyright: (c) 2001 Vaclav Slavik +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma interface "dllwidget.h" +#endif + +#ifndef __DLLWIDGET_H__ +#define __DLLWIDGET_H__ + +#include "wx/panel.h" + +/* + +wxDllWidget can be used to embed a wxWindow implemented in C++ in your +wxPython application without the need to write a SWIG interface. Widget's code +is stored in shared library or DLL that exports DLL_WidgetFactory symbol +and loaded at runtime. All you have to do is to pass the name of DLL and the class +to create to wxDllWidget's ctor. + +Runtime-loadable widget must have HandleCommand method (see the example) that is +used to communicate with Python app. You call wxDllWidget.SendCommand(cmd,param) from +Python and it in turn calls HandleCommand of the loaded widget. + +You must use DECLARE_DLL_WIDGET, BEGIN_WIDGET_LIBRARY, END_WIDGET_LIBRARY and +REGISTER_WIDGET macros in your C++ module in order to provide all the meat +wxDllWidget needs. + +Example of use: + + #define CMD_MAKEWHITE 1 + + class MyWindow : public wxWindow + { + public: + MyWindow(wxWindow *parent, long style) + : wxWindow(parent, -1) {} + + int HandleCommand(int cmd, const wxString& param) + { + if (cmd == CMD_MAKEWHITE) + SetBackgroundColour(*wxWHITE); + return 0; + } + }; + DECLARE_DLL_WIDGET(MyWindow) + + class MyCanvasWindow : public wxScrolledWindow + { + ... + }; + DECLARE_DLL_WIDGET(MyCanvasWindow) + + BEGIN_WIDGET_LIBRARY() + REGISTER_WIDGET(MyWindow) + REGISTER_WIDGET(MyCanvasWindow) + END_WIDGET_LIBRARY() + +*/ + + + +class WXDLLEXPORT wxDynamicLibrary; + +typedef int (*wxSendCommandFunc)(wxWindow *wnd, int cmd, const wxString& param); + +class wxDllWidget : public wxPanel +{ +public: + wxDllWidget(wxWindow *parent, + wxWindowID id = -1, + const wxString& dllName = wxEmptyString, + const wxString& className = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0); + virtual ~wxDllWidget(); + + bool Ok() { return m_widget != NULL; } + + virtual int SendCommand(int cmd, const wxString& param = wxEmptyString); + virtual wxWindow* GetEmbeddedWindow() { return m_widget; } + + virtual void AddChild(wxWindowBase *child); + + static wxString GetDllExt(); + + +protected: + bool LoadWidget(const wxString& dll, const wxString& className, long style); + void UnloadWidget(); + +protected: + wxWindow* m_widget; + wxSendCommandFunc m_cmdFunc; + wxDynamicLibrary* m_lib; + bool m_controlAdded; + +private: + DECLARE_ABSTRACT_CLASS(wxDllWidget) +}; + + +#define DECLARE_DLL_WIDGET(widget) \ + static int SendCommandTo##widget(wxWindow *wnd, int cmd, const wxString& param) \ + { \ + return wxStaticCast(wnd, widget)->HandleCommand(cmd, param); \ + } + + +#define BEGIN_WIDGET_LIBRARY() \ + extern "C" WXEXPORT bool DLL_WidgetFactory( \ + const wxString& className, \ + wxWindow *parent, \ + long style, \ + wxWindow **classInst, \ + wxSendCommandFunc *cmdFunc) \ + { \ + wxClassInfo::CleanUpClasses(); \ + wxClassInfo::InitializeClasses(); + + +#define REGISTER_WIDGET(widget) \ + if ( className == wxT(#widget) ) \ + { \ + *classInst = new widget(parent, style); \ + *cmdFunc = SendCommandTo##widget; \ + return TRUE; \ + } + + +#define END_WIDGET_LIBRARY() \ + return FALSE; \ + } + +#endif // __DLLWIDGET_H__ diff --git a/wxPython/contrib/dllwidget/dllwidget.py b/wxPython/contrib/dllwidget/dllwidget.py new file mode 100644 index 0000000000..63b7609f9c --- /dev/null +++ b/wxPython/contrib/dllwidget/dllwidget.py @@ -0,0 +1,6 @@ +# The SWIG module is named dllwidget_ to avoid name clashes, so +# this stub just imports everything in it so the firendly module +# name can be used elsewhere. + +from dllwidget_ import * + diff --git a/wxPython/contrib/dllwidget/dllwidget_.cpp b/wxPython/contrib/dllwidget/dllwidget_.cpp new file mode 100644 index 0000000000..b34a06a273 --- /dev/null +++ b/wxPython/contrib/dllwidget/dllwidget_.cpp @@ -0,0 +1,501 @@ +/* + * FILE : contrib/dllwidget/dllwidget_.cpp + * + * This file was automatically generated by : + * Simplified Wrapper and Interface Generator (SWIG) + * Version 1.1 (Build 883) + * + * Portions Copyright (c) 1995-1998 + * The University of Utah and The Regents of the University of California. + * Permission is granted to distribute this file in any manner provided + * this notice remains intact. + * + * Do not make changes to this file--changes will be lost! + * + */ + + +#define SWIGCODE +/* Implementation : PYTHON */ + +#define SWIGPYTHON +#include +#include +/* Definitions for Windows/Unix exporting */ +#if defined(__WIN32__) +# if defined(_MSC_VER) +# define SWIGEXPORT(a) __declspec(dllexport) a +# else +# if defined(__BORLANDC__) +# define SWIGEXPORT(a) a _export +# else +# define SWIGEXPORT(a) a +# endif +# endif +#else +# define SWIGEXPORT(a) a +#endif + +#include "Python.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void SWIG_MakePtr(char *, void *, char *); +extern void SWIG_RegisterMapping(char *, char *, void *(*)(void *)); +extern char *SWIG_GetPtr(char *, void **, char *); +extern char *SWIG_GetPtrObj(PyObject *, void **, char *); +extern void SWIG_addvarlink(PyObject *, char *, PyObject *(*)(void), int (*)(PyObject *)); +extern PyObject *SWIG_newvarlink(void); +#ifdef __cplusplus +} +#endif +#define SWIG_init initdllwidget_c + +#define SWIG_name "dllwidget_c" + +#include "export.h" +#include "dllwidget.h" + + +static PyObject* t_output_helper(PyObject* target, PyObject* o) { + PyObject* o2; + PyObject* o3; + + if (!target) { + target = o; + } else if (target == Py_None) { + Py_DECREF(Py_None); + target = o; + } else { + if (!PyTuple_Check(target)) { + o2 = target; + target = PyTuple_New(1); + PyTuple_SetItem(target, 0, o2); + } + o3 = PyTuple_New(1); + PyTuple_SetItem(o3, 0, o); + + o2 = target; + target = PySequence_Concat(o2, o3); + Py_DECREF(o2); + Py_DECREF(o3); + } + return target; +} + +#if PYTHON_API_VERSION >= 1009 + static char* wxStringErrorMsg = "String or Unicode type required"; +#else + static char* wxStringErrorMsg = "String type required"; +#endif +#ifdef __cplusplus +extern "C" { +#endif +static void *SwigwxDllWidgetTowxPanel(void *ptr) { + wxDllWidget *src; + wxPanel *dest; + src = (wxDllWidget *) ptr; + dest = (wxPanel *) src; + return (void *) dest; +} + +static void *SwigwxDllWidgetTowxWindow(void *ptr) { + wxDllWidget *src; + wxWindow *dest; + src = (wxDllWidget *) ptr; + dest = (wxWindow *) src; + return (void *) dest; +} + +static void *SwigwxDllWidgetTowxEvtHandler(void *ptr) { + wxDllWidget *src; + wxEvtHandler *dest; + src = (wxDllWidget *) ptr; + dest = (wxEvtHandler *) src; + return (void *) dest; +} + +static void *SwigwxDllWidgetTowxObject(void *ptr) { + wxDllWidget *src; + wxObject *dest; + src = (wxDllWidget *) ptr; + dest = (wxObject *) src; + return (void *) dest; +} + +#define new_wxDllWidget(_swigarg0,_swigarg1,_swigarg2,_swigarg3,_swigarg4,_swigarg5,_swigarg6) (new wxDllWidget(_swigarg0,_swigarg1,_swigarg2,_swigarg3,_swigarg4,_swigarg5,_swigarg6)) +static PyObject *_wrap_new_wxDllWidget(PyObject *self, PyObject *args, PyObject *kwargs) { + PyObject * _resultobj; + wxDllWidget * _result; + wxWindow * _arg0; + wxWindowID _arg1 = (wxWindowID ) -1; + wxString * _arg2 = (wxString *) &wxEmptyString; + wxString * _arg3 = (wxString *) &wxEmptyString; + wxPoint * _arg4 = (wxPoint *) &wxDefaultPosition; + wxSize * _arg5 = (wxSize *) &wxDefaultSize; + long _arg6 = (long ) 0; + PyObject * _argo0 = 0; + PyObject * _obj2 = 0; + PyObject * _obj3 = 0; + wxPoint temp; + PyObject * _obj4 = 0; + wxSize temp0; + PyObject * _obj5 = 0; + char *_kwnames[] = { "parent","id","dllName","className","pos","size","style", NULL }; + char _ptemp[128]; + + self = self; + if(!PyArg_ParseTupleAndKeywords(args,kwargs,"O|iOOOOl:new_wxDllWidget",_kwnames,&_argo0,&_arg1,&_obj2,&_obj3,&_obj4,&_obj5,&_arg6)) + return NULL; + if (_argo0) { + if (_argo0 == Py_None) { _arg0 = NULL; } + else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxWindow_p")) { + PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of new_wxDllWidget. Expected _wxWindow_p."); + return NULL; + } + } + if (_obj2) +{ +#if PYTHON_API_VERSION >= 1009 + char* tmpPtr; int tmpSize; + if (!PyString_Check(_obj2) && !PyUnicode_Check(_obj2)) { + PyErr_SetString(PyExc_TypeError, wxStringErrorMsg); + return NULL; + } + if (PyString_AsStringAndSize(_obj2, &tmpPtr, &tmpSize) == -1) + return NULL; + _arg2 = new wxString(tmpPtr, tmpSize); +#else + if (!PyString_Check(_obj2)) { + PyErr_SetString(PyExc_TypeError, wxStringErrorMsg); + return NULL; + } + _arg2 = new wxString(PyString_AS_STRING(_obj2), PyString_GET_SIZE(_obj2)); +#endif +} + if (_obj3) +{ +#if PYTHON_API_VERSION >= 1009 + char* tmpPtr; int tmpSize; + if (!PyString_Check(_obj3) && !PyUnicode_Check(_obj3)) { + PyErr_SetString(PyExc_TypeError, wxStringErrorMsg); + return NULL; + } + if (PyString_AsStringAndSize(_obj3, &tmpPtr, &tmpSize) == -1) + return NULL; + _arg3 = new wxString(tmpPtr, tmpSize); +#else + if (!PyString_Check(_obj3)) { + PyErr_SetString(PyExc_TypeError, wxStringErrorMsg); + return NULL; + } + _arg3 = new wxString(PyString_AS_STRING(_obj3), PyString_GET_SIZE(_obj3)); +#endif +} + if (_obj4) +{ + _arg4 = &temp; + if (! wxPoint_helper(_obj4, &_arg4)) + return NULL; +} + if (_obj5) +{ + _arg5 = &temp0; + if (! wxSize_helper(_obj5, &_arg5)) + return NULL; +} +{ + wxPy_BEGIN_ALLOW_THREADS; + _result = (wxDllWidget *)new_wxDllWidget(_arg0,_arg1,*_arg2,*_arg3,*_arg4,*_arg5,_arg6); + + wxPy_END_ALLOW_THREADS; +} if (_result) { + SWIG_MakePtr(_ptemp, (char *) _result,"_wxDllWidget_p"); + _resultobj = Py_BuildValue("s",_ptemp); + } else { + Py_INCREF(Py_None); + _resultobj = Py_None; + } +{ + if (_obj2) + delete _arg2; +} +{ + if (_obj3) + delete _arg3; +} + return _resultobj; +} + +#define wxDllWidget_Ok(_swigobj) (_swigobj->Ok()) +static PyObject *_wrap_wxDllWidget_Ok(PyObject *self, PyObject *args, PyObject *kwargs) { + PyObject * _resultobj; + bool _result; + wxDllWidget * _arg0; + PyObject * _argo0 = 0; + char *_kwnames[] = { "self", NULL }; + + self = self; + if(!PyArg_ParseTupleAndKeywords(args,kwargs,"O:wxDllWidget_Ok",_kwnames,&_argo0)) + return NULL; + if (_argo0) { + if (_argo0 == Py_None) { _arg0 = NULL; } + else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxDllWidget_p")) { + PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxDllWidget_Ok. Expected _wxDllWidget_p."); + return NULL; + } + } +{ + wxPy_BEGIN_ALLOW_THREADS; + _result = (bool )wxDllWidget_Ok(_arg0); + + wxPy_END_ALLOW_THREADS; +} _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +#define wxDllWidget_SendCommand(_swigobj,_swigarg0,_swigarg1) (_swigobj->SendCommand(_swigarg0,_swigarg1)) +static PyObject *_wrap_wxDllWidget_SendCommand(PyObject *self, PyObject *args, PyObject *kwargs) { + PyObject * _resultobj; + int _result; + wxDllWidget * _arg0; + int _arg1; + wxString * _arg2 = (wxString *) &wxEmptyString; + PyObject * _argo0 = 0; + PyObject * _obj2 = 0; + char *_kwnames[] = { "self","cmd","param", NULL }; + + self = self; + if(!PyArg_ParseTupleAndKeywords(args,kwargs,"Oi|O:wxDllWidget_SendCommand",_kwnames,&_argo0,&_arg1,&_obj2)) + return NULL; + if (_argo0) { + if (_argo0 == Py_None) { _arg0 = NULL; } + else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxDllWidget_p")) { + PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxDllWidget_SendCommand. Expected _wxDllWidget_p."); + return NULL; + } + } + if (_obj2) +{ +#if PYTHON_API_VERSION >= 1009 + char* tmpPtr; int tmpSize; + if (!PyString_Check(_obj2) && !PyUnicode_Check(_obj2)) { + PyErr_SetString(PyExc_TypeError, wxStringErrorMsg); + return NULL; + } + if (PyString_AsStringAndSize(_obj2, &tmpPtr, &tmpSize) == -1) + return NULL; + _arg2 = new wxString(tmpPtr, tmpSize); +#else + if (!PyString_Check(_obj2)) { + PyErr_SetString(PyExc_TypeError, wxStringErrorMsg); + return NULL; + } + _arg2 = new wxString(PyString_AS_STRING(_obj2), PyString_GET_SIZE(_obj2)); +#endif +} +{ + wxPy_BEGIN_ALLOW_THREADS; + _result = (int )wxDllWidget_SendCommand(_arg0,_arg1,*_arg2); + + wxPy_END_ALLOW_THREADS; +} _resultobj = Py_BuildValue("i",_result); +{ + if (_obj2) + delete _arg2; +} + return _resultobj; +} + +#define wxDllWidget_GetEmbeddedWindow(_swigobj) (_swigobj->GetEmbeddedWindow()) +static PyObject *_wrap_wxDllWidget_GetEmbeddedWindow(PyObject *self, PyObject *args, PyObject *kwargs) { + PyObject * _resultobj; + wxWindow * _result; + wxDllWidget * _arg0; + PyObject * _argo0 = 0; + char *_kwnames[] = { "self", NULL }; + + self = self; + if(!PyArg_ParseTupleAndKeywords(args,kwargs,"O:wxDllWidget_GetEmbeddedWindow",_kwnames,&_argo0)) + return NULL; + if (_argo0) { + if (_argo0 == Py_None) { _arg0 = NULL; } + else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxDllWidget_p")) { + PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxDllWidget_GetEmbeddedWindow. Expected _wxDllWidget_p."); + return NULL; + } + } +{ + wxPy_BEGIN_ALLOW_THREADS; + _result = (wxWindow *)wxDllWidget_GetEmbeddedWindow(_arg0); + + wxPy_END_ALLOW_THREADS; +}{ _resultobj = wxPyMake_wxObject(_result); } + return _resultobj; +} + +static PyObject *_wrap_wxDllWidget_GetDllExt(PyObject *self, PyObject *args, PyObject *kwargs) { + PyObject * _resultobj; + wxString * _result; + char *_kwnames[] = { NULL }; + + self = self; + if(!PyArg_ParseTupleAndKeywords(args,kwargs,":wxDllWidget_GetDllExt",_kwnames)) + return NULL; +{ + wxPy_BEGIN_ALLOW_THREADS; + _result = new wxString (wxDllWidget::GetDllExt()); + + wxPy_END_ALLOW_THREADS; +}{ + _resultobj = PyString_FromStringAndSize(_result->c_str(), _result->Len()); +} +{ + delete _result; +} + return _resultobj; +} + +static PyMethodDef dllwidget_cMethods[] = { + { "wxDllWidget_GetDllExt", (PyCFunction) _wrap_wxDllWidget_GetDllExt, METH_VARARGS | METH_KEYWORDS }, + { "wxDllWidget_GetEmbeddedWindow", (PyCFunction) _wrap_wxDllWidget_GetEmbeddedWindow, METH_VARARGS | METH_KEYWORDS }, + { "wxDllWidget_SendCommand", (PyCFunction) _wrap_wxDllWidget_SendCommand, METH_VARARGS | METH_KEYWORDS }, + { "wxDllWidget_Ok", (PyCFunction) _wrap_wxDllWidget_Ok, METH_VARARGS | METH_KEYWORDS }, + { "new_wxDllWidget", (PyCFunction) _wrap_new_wxDllWidget, METH_VARARGS | METH_KEYWORDS }, + { NULL, NULL } +}; +#ifdef __cplusplus +} +#endif +/* + * This table is used by the pointer type-checker + */ +static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = { + { "_signed_long","_long",0}, + { "_wxPrintQuality","_wxCoord",0}, + { "_wxPrintQuality","_int",0}, + { "_wxPrintQuality","_signed_int",0}, + { "_wxPrintQuality","_unsigned_int",0}, + { "_wxPrintQuality","_wxWindowID",0}, + { "_wxPrintQuality","_uint",0}, + { "_wxPrintQuality","_EBool",0}, + { "_wxPrintQuality","_size_t",0}, + { "_wxPrintQuality","_time_t",0}, + { "_byte","_unsigned_char",0}, + { "_long","_unsigned_long",0}, + { "_long","_signed_long",0}, + { "_size_t","_wxCoord",0}, + { "_size_t","_wxPrintQuality",0}, + { "_size_t","_time_t",0}, + { "_size_t","_unsigned_int",0}, + { "_size_t","_int",0}, + { "_size_t","_wxWindowID",0}, + { "_size_t","_uint",0}, + { "_wxPanel","_wxDllWidget",SwigwxDllWidgetTowxPanel}, + { "_uint","_wxCoord",0}, + { "_uint","_wxPrintQuality",0}, + { "_uint","_time_t",0}, + { "_uint","_size_t",0}, + { "_uint","_unsigned_int",0}, + { "_uint","_int",0}, + { "_uint","_wxWindowID",0}, + { "_wxChar","_char",0}, + { "_char","_wxChar",0}, + { "_struct_wxNativeFontInfo","_wxNativeFontInfo",0}, + { "_EBool","_wxCoord",0}, + { "_EBool","_wxPrintQuality",0}, + { "_EBool","_signed_int",0}, + { "_EBool","_int",0}, + { "_EBool","_wxWindowID",0}, + { "_unsigned_long","_long",0}, + { "_wxNativeFontInfo","_struct_wxNativeFontInfo",0}, + { "_signed_int","_wxCoord",0}, + { "_signed_int","_wxPrintQuality",0}, + { "_signed_int","_EBool",0}, + { "_signed_int","_wxWindowID",0}, + { "_signed_int","_int",0}, + { "_WXTYPE","_wxDateTime_t",0}, + { "_WXTYPE","_short",0}, + { "_WXTYPE","_signed_short",0}, + { "_WXTYPE","_unsigned_short",0}, + { "_unsigned_short","_wxDateTime_t",0}, + { "_unsigned_short","_WXTYPE",0}, + { "_unsigned_short","_short",0}, + { "_wxObject","_wxDllWidget",SwigwxDllWidgetTowxObject}, + { "_signed_short","_WXTYPE",0}, + { "_signed_short","_short",0}, + { "_unsigned_char","_byte",0}, + { "_unsigned_int","_wxCoord",0}, + { "_unsigned_int","_wxPrintQuality",0}, + { "_unsigned_int","_time_t",0}, + { "_unsigned_int","_size_t",0}, + { "_unsigned_int","_uint",0}, + { "_unsigned_int","_wxWindowID",0}, + { "_unsigned_int","_int",0}, + { "_short","_wxDateTime_t",0}, + { "_short","_WXTYPE",0}, + { "_short","_unsigned_short",0}, + { "_short","_signed_short",0}, + { "_wxWindowID","_wxCoord",0}, + { "_wxWindowID","_wxPrintQuality",0}, + { "_wxWindowID","_time_t",0}, + { "_wxWindowID","_size_t",0}, + { "_wxWindowID","_EBool",0}, + { "_wxWindowID","_uint",0}, + { "_wxWindowID","_int",0}, + { "_wxWindowID","_signed_int",0}, + { "_wxWindowID","_unsigned_int",0}, + { "_int","_wxCoord",0}, + { "_int","_wxPrintQuality",0}, + { "_int","_time_t",0}, + { "_int","_size_t",0}, + { "_int","_EBool",0}, + { "_int","_uint",0}, + { "_int","_wxWindowID",0}, + { "_int","_unsigned_int",0}, + { "_int","_signed_int",0}, + { "_wxDateTime_t","_unsigned_short",0}, + { "_wxDateTime_t","_short",0}, + { "_wxDateTime_t","_WXTYPE",0}, + { "_time_t","_wxCoord",0}, + { "_time_t","_wxPrintQuality",0}, + { "_time_t","_unsigned_int",0}, + { "_time_t","_int",0}, + { "_time_t","_wxWindowID",0}, + { "_time_t","_uint",0}, + { "_time_t","_size_t",0}, + { "_wxCoord","_int",0}, + { "_wxCoord","_signed_int",0}, + { "_wxCoord","_unsigned_int",0}, + { "_wxCoord","_wxWindowID",0}, + { "_wxCoord","_uint",0}, + { "_wxCoord","_EBool",0}, + { "_wxCoord","_size_t",0}, + { "_wxCoord","_time_t",0}, + { "_wxCoord","_wxPrintQuality",0}, + { "_wxEvtHandler","_wxDllWidget",SwigwxDllWidgetTowxEvtHandler}, + { "_wxWindow","_wxDllWidget",SwigwxDllWidgetTowxWindow}, +{0,0,0}}; + +static PyObject *SWIG_globals; +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT(void) initdllwidget_c() { + PyObject *m, *d; + SWIG_globals = SWIG_newvarlink(); + m = Py_InitModule("dllwidget_c", dllwidget_cMethods); + d = PyModule_GetDict(m); + + + wxClassInfo::CleanUpClasses(); + wxClassInfo::InitializeClasses(); + +{ + int i; + for (i = 0; _swig_mapping[i].n1; i++) + SWIG_RegisterMapping(_swig_mapping[i].n1,_swig_mapping[i].n2,_swig_mapping[i].pcnv); +} +} diff --git a/wxPython/contrib/dllwidget/dllwidget_.i b/wxPython/contrib/dllwidget/dllwidget_.i new file mode 100644 index 0000000000..37aa1781db --- /dev/null +++ b/wxPython/contrib/dllwidget/dllwidget_.i @@ -0,0 +1,111 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: dllwidget_.i +// Purpose: Load wx widgets from external DLLs +// +// Author: Robin Dunn +// +// Created: 04-Dec-2001 +// RCS-ID: $Id$ +// Copyright: (c) 2001 by Total Control Software +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +%module dllwidget_ + + +%{ +#include "export.h" +#include "dllwidget.h" +%} + +//--------------------------------------------------------------------------- + +%include typemaps.i +%include my_typemaps.i + +%extern wx.i +%extern windows.i +%extern _defs.i + +//--------------------------------------------------------------------------- + +/* + +wxDllWidget can be used to embed a wxWindow implemented in C++ in your +wxPython application without the need to write a SWIG interface. Widget's code +is stored in shared library or DLL that exports DLL_WidgetFactory symbol +and loaded at runtime. All you have to do is to pass the name of DLL and the class +to create to wxDllWidget's ctor. + +Runtime-loadable widget must have HandleCommand method (see the example) that is +used to communicate with Python app. You call wxDllWidget.SendCommand(cmd,param) from +Python and it in turn calls HandleCommand of the loaded widget. + +You must use DECLARE_DLL_WIDGET, BEGIN_WIDGET_LIBRARY, END_WIDGET_LIBRARY and +REGISTER_WIDGET macros in your C++ module in order to provide all the meat +wxDllWidget needs. + +Example of use: + + #define CMD_MAKEWHITE 1 + + class MyWindow : public wxWindow + { + public: + MyWindow(wxWindow *parent, long style) + : wxWindow(parent, -1) {} + + int HandleCommand(int cmd, const wxString& param) + { + if (cmd == CMD_MAKEWHITE) + SetBackgroundColour(*wxWHITE); + return 0; + } + }; + DECLARE_DLL_WIDGET(MyWindow) + + class MyCanvasWindow : public wxScrolledWindow + { + ... + }; + DECLARE_DLL_WIDGET(MyCanvasWindow) + + BEGIN_WIDGET_LIBRARY() + REGISTER_WIDGET(MyWindow) + REGISTER_WIDGET(MyCanvasWindow) + END_WIDGET_LIBRARY() + +*/ + +class wxDllWidget : public wxPanel +{ +public: + wxDllWidget(wxWindow *parent, + wxWindowID id = -1, + const wxString& dllName = wxEmptyString, + const wxString& className = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0); + + %pragma(python) addtomethod = "__init__:self._setOORInfo(self)" + + bool Ok(); + + int SendCommand(int cmd, const wxString& param = wxEmptyString); + wxWindow* GetEmbeddedWindow(); + + static wxString GetDllExt(); +}; + +//--------------------------------------------------------------------------- + +%init %{ + + wxClassInfo::CleanUpClasses(); + wxClassInfo::InitializeClasses(); + +%} + + +//--------------------------------------------------------------------------- diff --git a/wxPython/contrib/dllwidget/dllwidget_.py b/wxPython/contrib/dllwidget/dllwidget_.py new file mode 100644 index 0000000000..377dbf404d --- /dev/null +++ b/wxPython/contrib/dllwidget/dllwidget_.py @@ -0,0 +1,76 @@ +# This file was created automatically by SWIG. +import dllwidget_c + +from misc import * + +from misc2 import * + +from windows import * + +from gdi import * + +from clip_dnd import * + +from events import * + +from streams import * + +from utils import * + +from mdi import * + +from frames import * + +from stattool import * + +from controls import * + +from controls2 import * + +from windows2 import * + +from cmndlgs import * + +from windows3 import * + +from image import * + +from printfw import * + +from sizers import * + +from filesys import * +class wxDllWidgetPtr(wxPanelPtr): + def __init__(self,this): + self.this = this + self.thisown = 0 + def Ok(self, *_args, **_kwargs): + val = apply(dllwidget_c.wxDllWidget_Ok,(self,) + _args, _kwargs) + return val + def SendCommand(self, *_args, **_kwargs): + val = apply(dllwidget_c.wxDllWidget_SendCommand,(self,) + _args, _kwargs) + return val + def GetEmbeddedWindow(self, *_args, **_kwargs): + val = apply(dllwidget_c.wxDllWidget_GetEmbeddedWindow,(self,) + _args, _kwargs) + return val + def __repr__(self): + return "" % (self.this,) +class wxDllWidget(wxDllWidgetPtr): + def __init__(self,*_args,**_kwargs): + self.this = apply(dllwidget_c.new_wxDllWidget,_args,_kwargs) + self.thisown = 1 + self._setOORInfo(self) + + + + + + +#-------------- FUNCTION WRAPPERS ------------------ + +wxDllWidget_GetDllExt = dllwidget_c.wxDllWidget_GetDllExt + + + +#-------------- VARIABLE WRAPPERS ------------------ + diff --git a/wxPython/demo/dllwidget/Makefile b/wxPython/demo/dllwidget/Makefile new file mode 100644 index 0000000000..71065ea605 --- /dev/null +++ b/wxPython/demo/dllwidget/Makefile @@ -0,0 +1,19 @@ + +CXX = c++ +CXXFLAGS = `wx-config --cxxflags` -fPIC -I. +LDFLAGS = `wx-config --libs` + + +all: test_prg test_dll.so + +test_prg: dllwidget.o test_prg.o + $(CXX) $(LDFLAGS) -o $@ dllwidget.o test_prg.o + +test_dll.so: test_dll.o + $(CXX) $(LDFLAGS) -shared -o $@ $< + +%.o : %.cpp + $(CXX) -c $(CXXFLAGS) -o $@ $< + +clean: + rm -f *.o *.so test_prg diff --git a/wxPython/demo/dllwidget/makefile.vc b/wxPython/demo/dllwidget/makefile.vc new file mode 100644 index 0000000000..e12c0d34ec --- /dev/null +++ b/wxPython/demo/dllwidget/makefile.vc @@ -0,0 +1,32 @@ + +WXDIR = $(WXWIN) +WXUSINGDLL = 1 + +PROGRAM = test_dll +OBJECTS = test_dll.obj + +!include $(WXDIR)\src\makevc.env + + +$(PROGRAM).dll : $(OBJECTS) + $(link) @<< +-out:$(PROGRAM).dll +-dll $(LINK_DEBUG_FLAGS) $(WINLINKFLAGS) +$(OBJECTS) +$(WXLIB) +<< + + +clean: + del $(OBJECTS) + del $(PROGRAM).dll + del $(PROGRAM).exp + del $(PROGRAM).lib + del $(PROGRAM).pdb + +test: + @echo -out:$(PROGRAM).dll + @echo -dll $(LINK_DEBUG_FLAGS) $(WINLINKFLAGS) + @echo $(OBJECTS) + @echo $(WXLIB) + diff --git a/wxPython/demo/dllwidget/test_dll.cpp b/wxPython/demo/dllwidget/test_dll.cpp new file mode 100644 index 0000000000..605d787a36 --- /dev/null +++ b/wxPython/demo/dllwidget/test_dll.cpp @@ -0,0 +1,54 @@ + +#include +#include +#include + +#include "../dllwidget.h" + +class TestWindow : public wxWindow +{ +public: + TestWindow(wxWindow *parent, long style) + : wxWindow(parent, -1) + { + SetBackgroundColour(wxColour("white")); + } + + int HandleCommand(int cmd, const wxString& param) + { + if (cmd == 1) + { + SetBackgroundColour(wxColour("red")); + Refresh(); + } + + if (cmd == 2) + { + SetBackgroundColour(wxColour(param)); + Refresh(); + } + + else if (cmd == 3) + { + wxMessageBox("Message from embedded widget:\n\n" + param); + } + + return 0; + } +private: + DECLARE_ABSTRACT_CLASS(TestWindow) +}; + +IMPLEMENT_ABSTRACT_CLASS(TestWindow, wxWindow) + + +//DECLARE_DLL_WIDGET(TestWindow) +static int SendCommandToTestWindow(wxWindow *wnd, int cmd, const wxString& param) +{ + return wxStaticCast(wnd, TestWindow)->HandleCommand(cmd, param); +} + + +BEGIN_WIDGET_LIBRARY() + REGISTER_WIDGET(TestWindow) +END_WIDGET_LIBRARY() diff --git a/wxPython/demo/dllwidget/test_prog.py b/wxPython/demo/dllwidget/test_prog.py new file mode 100644 index 0000000000..42991bd8fc --- /dev/null +++ b/wxPython/demo/dllwidget/test_prog.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python + +from wxPython.wx import * +from wxPython.dllwidget import wxDllWidget, wxDllWidget_GetDllExt + +#---------------------------------------------------------------------- + +class TestFrame(wxFrame): + def __init__(self): + wxFrame.__init__(self, None, -1, "Test wxDllWidget") + + menu = wxMenu() + menu.Append(101, "Send command &1") + menu.Append(102, "Send command &2") + menu.Append(103, "Send command &3") + menu.AppendSeparator() + menu.Append(110, "E&xit") + + mb = wxMenuBar() + mb.Append(menu, "&Test") + self.SetMenuBar(mb) + + EVT_MENU_RANGE(self, 101, 109, self.OnSendCommand) + EVT_MENU(self, 110, self.OnExit) + + panel = wxPanel(self, -1) + panel.SetFont(wxFont(12, wxSWISS, wxNORMAL, wxBOLD)) + + st = wxStaticText(panel, -1, + "The widget below was dynamically imported from\n" + "test_dll.dll or test_dll.so with no prior knowledge\n" + "of it's contents or structure by wxPython.") + + self.dw = dw = wxDllWidget(panel, -1, + "test_dll" + wxDllWidget_GetDllExt(), + "TestWindow", + size=(250, 150)) + + # The embedded window is the one exported from the DLL + print dw.GetEmbeddedWindow().GetClassName() + + # This shows that we can give it a child from this side of things. + # You can also call any wxWindow methods on it too. + wxStaticText(dw.GetEmbeddedWindow(), -1, + "Loaded from test_dll...", pos=(10,10)) + + + sizer = wxBoxSizer(wxVERTICAL) + sizer.Add(wxStaticLine(panel, -1), 0, wxGROW) + sizer.Add(st, 0, wxGROW|wxALL, 5) + sizer.Add(dw, 1, wxGROW|wxALL, 5) + + panel.SetSizer(sizer) + panel.SetAutoLayout(true) + sizer.Fit(self) + sizer.SetSizeHints(self) + + + def OnExit(self, evt): + self.Close() + + + def OnSendCommand(self, evt): + ID = evt.GetId() - 100 # use the menu ID as the command + param = "" + if ID == 2: + dlg = wxTextEntryDialog(self, "Enter a colour name to pass to the embedded widget:") + if dlg.ShowModal() == wxID_OK: + param = dlg.GetValue() + dlg.Destroy() + self.dw.SendCommand(ID, param) + + + +#---------------------------------------------------------------------- + + +if __name__ == "__main__": + app = wxPySimpleApp() + frame = TestFrame() + frame.Show(true) + app.MainLoop() diff --git a/wxPython/distrib/make_installer.py b/wxPython/distrib/make_installer.py index 08e1aba4e2..487526e220 100644 --- a/wxPython/distrib/make_installer.py +++ b/wxPython/distrib/make_installer.py @@ -79,6 +79,7 @@ Source: "wxPython\oglc.pyd"; DestDir: "{app}\wxPython"; Component Source: "wxPython\stc_c.pyd"; DestDir: "{app}\wxPython"; Components: core Source: "wxPython\xrcc.pyd"; DestDir: "{app}\wxPython"; Components: core Source: "wxPython\gizmosc.pyd"; DestDir: "{app}\wxPython"; Components: core +Source: "wxPython\dllwidget.pyd"; DestDir: "{app}\wxPython"; Components: core Source: "wxPython\*.py"; DestDir: "{app}\wxPython"; Components: core Source: "wxPython\lib\*.py"; DestDir: "{app}\wxPython\lib"; Components: core @@ -117,6 +118,11 @@ Source: "demo\data\*.wav"; DestDir: "{app}\wxPython\demo\data"; Source: "demo\data\*.wdr"; DestDir: "{app}\wxPython\demo\data"; Components: demo Source: "demo\data\*.xrc"; DestDir: "{app}\wxPython\demo\data"; Components: demo +Source: "demo\dllwidget\*.cpp"; DestDir: "{app}\wxPython\demo\dllwidget"; Components: demo +Source: "demo\dllwidget\*.py"; DestDir: "{app}\wxPython\demo\dllwidget"; Components: demo +Source: "demo\dllwidget\Makefile"; DestDir: "{app}\wxPython\demo\dllwidget"; Components: demo +Source: "demo\dllwidget\makefile.*"; DestDir: "{app}\wxPython\demo\dllwidget"; Components: demo + Source: "README.txt"; DestDir: "{app}\wxPython\docs"; Flags: isreadme; Components: core Source: "CHANGES.txt"; DestDir: "{app}\wxPython\docs"; Components: core Source: "licence\*.txt"; DestDir: "{app}\wxPython\docs\licence"; Components: core @@ -201,9 +207,6 @@ Type: files; Name: "{app}\wxPython\samples\frogedit\*.pyo"; #---------------------------------------------------------------------- -## TODO: For Python 2.2 wxPython should go into -# os.path.join(sys.prefix, 'Lib', 'site-packages') - IFS_Template = r""" program Setup; diff --git a/wxPython/setup.py b/wxPython/setup.py index 96ecf34550..abcae25aa6 100755 --- a/wxPython/setup.py +++ b/wxPython/setup.py @@ -33,11 +33,13 @@ BUILD_OGL = 1 # If true, build the contrib/ogl extension module BUILD_STC = 1 # If true, build the contrib/stc extension module BUILD_XRC = 1 # XML based resource system BUILD_GIZMOS = 1 # Build a module for the gizmos contrib library +BUILD_DLLWIDGET = 1# Build a module for the gizmos contrib library BUILD_IEWIN = 0 # Internet Explorer wrapper (experimental) - CORE_ONLY = 0 # if true, don't build any of the above + + GL_ONLY = 0 # Only used when making the -gl RPM. See the "b" script # for the ugly details @@ -113,6 +115,7 @@ if bcpp_compiling: #---------------------------------------------------------------------- for flag in ['BUILD_GLCANVAS', 'BUILD_OGL', 'BUILD_STC', 'BUILD_XRC', + 'BUILD_GIZMOS', 'BUILD_DLLWIDGET', 'CORE_ONLY', 'USE_SWIG', 'IN_CVS_TREE', 'FINAL', 'HYBRID', ]: for x in range(len(sys.argv)): @@ -554,7 +557,7 @@ if not GL_ONLY and BUILD_STC: swig_args + ['-I'+STC_H, '-I'+location], [opj(STC_H, 'stc.h')]) - # copy a project specific py module to the main package dir + # copy a contrib project specific py module to the main package dir copy_file(opj(location, 'stc.py'), PKGDIR, update=1, verbose=0) # add some include dirs to the standard set @@ -793,6 +796,39 @@ if not GL_ONLY and BUILD_GIZMOS: +#---------------------------------------------------------------------- +# Define the DLLWIDGET extension module +#---------------------------------------------------------------------- + +if not GL_ONLY and BUILD_DLLWIDGET: + msg('Preparing DLLWIDGET...') + location = 'contrib/dllwidget' + swig_files = ['dllwidget_.i'] + + swig_sources = run_swig(swig_files, location, '', PKGDIR, + USE_SWIG, swig_force, swig_args) + + # copy a contrib project specific py module to the main package dir + copy_file(opj(location, 'dllwidget.py'), PKGDIR, update=1, verbose=0) + + ext = Extension('dllwidget_c', [ + '%s/dllwidget.cpp' % location, + ] + swig_sources, + + include_dirs = includes, + define_macros = defines, + + library_dirs = libdirs, + libraries = libs, + + extra_compile_args = cflags, + extra_link_args = lflags, + ) + + wxpExtensions.append(ext) + + + #---------------------------------------------------------------------- # Do the Setup/Build/Install/Whatever -- 2.47.2