1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Helper functions/classes for the wxPython extension module
9 // Copyright: (c) 1998 by Total Control Software
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
22 #include <wx/msw/private.h>
25 #undef LoadAccelerators
29 #include <wx/module.h>
32 //---------------------------------------------------------------------------
34 //wxHashTable* wxPyWindows = NULL;
37 wxPoint wxPyDefaultPosition
; //wxDefaultPosition);
38 wxSize wxPyDefaultSize
; //wxDefaultSize);
39 wxString
wxPyEmptyStr("");
43 #ifdef __WXMSW__ // If building for win32...
44 //----------------------------------------------------------------------
45 // This gets run when the DLL is loaded. We just need to save a handle.
46 //----------------------------------------------------------------------
49 HINSTANCE hinstDLL
, // handle to DLL module
50 DWORD fdwReason
, // reason for calling function
51 LPVOID lpvReserved
// reserved
54 wxSetInstance(hinstDLL
);
59 //----------------------------------------------------------------------
60 // Class for implementing the wxp main application shell.
61 //----------------------------------------------------------------------
63 wxPyApp
*wxPythonApp
= NULL
; // Global instance of application object
67 // printf("**** ctor\n");
71 // printf("**** dtor\n");
75 // This one isn't acutally called... See __wxStart()
76 bool wxPyApp::OnInit(void) {
80 int wxPyApp::MainLoop(void) {
81 int retval
= wxApp::MainLoop();
87 void wxPyApp::AfterMainLoop(void) {
88 // more stuff from wxEntry...
90 if (wxPythonApp
->GetTopWindow()) {
91 // Forcibly delete the window.
92 if (wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxFrame
)) ||
93 wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxDialog
))) {
95 wxPythonApp
->GetTopWindow()->Close(TRUE
);
96 wxPythonApp
->DeletePendingObjects();
99 delete wxPythonApp
->GetTopWindow();
100 wxPythonApp
->SetTopWindow(NULL
);
104 wxPythonApp
->DeletePendingObjects();
107 wxPythonApp
->OnExit();
109 // delete wxPythonApp;
113 //---------------------------------------------------------------------
114 // a few native methods to add to the module
115 //----------------------------------------------------------------------
118 // This is where we pick up the first part of the wxEntry functionality...
119 // The rest is in __wxStart and AfterMainLoop. This function is called when
120 // wxpc is imported. (Before there is a wxApp object.)
123 // Bail out if there is already windows created. This means that the
124 // toolkit has already been initialized, as in embedding wxPython in
125 // a C++ wxWindows app.
126 if (wxTopLevelWindows
.Number() > 0)
134 PyObject
* sysargv
= PySys_GetObject("argv");
135 int argc
= PyList_Size(sysargv
);
136 char** argv
= new char*[argc
+1];
138 for(x
=0; x
<argc
; x
++)
139 argv
[x
] = PyString_AsString(PyList_GetItem(sysargv
, x
));
143 gtk_init( &argc
, &argv
);
146 wxApp::Initialize(); // may return FALSE. Should we check?
152 #ifdef WXP_WITH_THREAD
153 static PyThreadState
*event_tstate
= NULL
;
155 static char* __nullArgv
[1] = { 0 };
157 // Start the user application, user App's OnInit method is a parameter here
158 PyObject
* __wxStart(PyObject
* /* self */, PyObject
* args
)
160 PyObject
* onInitFunc
= NULL
;
165 #ifdef WXP_WITH_THREAD
166 event_tstate
= PyThreadState_Get();
169 if (!PyArg_ParseTuple(args
, "O", &onInitFunc
))
172 if (wxTopLevelWindows
.Number() > 0) {
173 PyErr_SetString(PyExc_TypeError
, "Only 1 wxApp per process!");
178 // This is the next part of the wxEntry functionality...
179 wxPythonApp
->argc
= 0;
180 wxPythonApp
->argv
= NULL
;
181 wxPythonApp
->OnInitGui();
184 // Call the Python App's OnInit function
185 arglist
= PyTuple_New(0);
187 // Py_END_ALLOW_THREADS; **** __wxStart was called from Python,
188 // should already have the lock
189 result
= PyEval_CallObject(onInitFunc
, arglist
);
190 // Py_BEGIN_ALLOW_THREADS;
197 if (! PyInt_Check(result
)) {
198 PyErr_SetString(PyExc_TypeError
, "OnInit should return a boolean value");
201 bResult
= PyInt_AS_LONG(result
);
203 wxPythonApp
->DeletePendingObjects();
204 wxPythonApp
->OnExit();
206 PyErr_SetString(PyExc_SystemExit
, "OnInit returned false, exiting...");
211 wxTheApp
->m_initialized
= (wxTopLevelWindows
.Number() > 0);
222 PyObject
* wxPython_dict
;
223 PyObject
* __wxSetDictionary(PyObject
* /* self */, PyObject
* args
)
226 if (!PyArg_ParseTuple(args
, "O", &wxPython_dict
))
229 if (!PyDict_Check(wxPython_dict
)) {
230 PyErr_SetString(PyExc_TypeError
, "_wxSetDictionary must have dictionary object!");
234 #define wxPlatform "__WXMOTIF__"
237 #define wxPlatform "__WXQT__"
240 #define wxPlatform "__WXGTK__"
242 #if defined(__WIN32__) || defined(__WXMSW__)
243 #define wxPlatform "__WXMSW__"
246 #define wxPlatform "__WXMAC__"
249 PyDict_SetItemString(wxPython_dict
, "wxPlatform", PyString_FromString(wxPlatform
));
256 //---------------------------------------------------------------------------
260 PyObject
* wxPyConstructObject(void* ptr
, char* className
)
262 char buff
[64]; // should always be big enough...
265 sprintf(buff
, "_%s_p", className
);
266 SWIG_MakePtr(swigptr
, ptr
, buff
);
268 sprintf(buff
, "%sPtr", className
);
269 PyObject
* classobj
= PyDict_GetItemString(wxPython_dict
, buff
);
275 PyObject
* arg
= Py_BuildValue("(s)", swigptr
);
276 PyObject
* obj
= PyInstance_New(classobj
, arg
, NULL
);
284 wxPyCallback::wxPyCallback(PyObject
* func
) {
289 wxPyCallback::~wxPyCallback() {
290 #ifdef WXP_WITH_THREAD
291 PyEval_RestoreThread(event_tstate
);
296 #ifdef WXP_WITH_THREAD
304 // This function is used for all events destined for Python event handlers.
305 void wxPyCallback::EventThunker(wxEvent
& event
) {
306 wxPyCallback
* cb
= (wxPyCallback
*)event
.m_callbackUserData
;
307 PyObject
* func
= cb
->m_func
;
313 #ifdef WXP_WITH_THREAD
314 PyEval_RestoreThread(event_tstate
);
316 arg
= wxPyConstructObject((void*)&event
, event
.GetClassInfo()->GetClassName());
318 tuple
= PyTuple_New(1);
319 PyTuple_SET_ITEM(tuple
, 0, arg
);
320 result
= PyEval_CallObject(func
, tuple
);
328 #ifdef WXP_WITH_THREAD
334 //---------------------------------------------------------------------------
336 wxPyMenu::wxPyMenu(const wxString
& title
, PyObject
* _func
)
337 : wxMenu(title
, (wxFunction
)(func
? MenuCallback
: NULL
)), func(0) {
345 wxPyMenu::~wxPyMenu() {
351 void wxPyMenu::MenuCallback(wxMenu
& menu
, wxCommandEvent
& evt
) {
352 #ifdef WXP_WITH_THREAD
353 PyEval_RestoreThread(event_tstate
);
355 PyObject
* evtobj
= wxPyConstructObject((void*)&evt
, "wxCommandEvent");
356 PyObject
* menuobj
= wxPyConstructObject((void*)&menu
, "wxMenu");
357 if (PyErr_Occurred()) {
358 // bail out if a problem
362 // Now call the callback...
363 PyObject
* func
= ((wxPyMenu
*)&menu
)->func
;
364 PyObject
* args
= PyTuple_New(2);
365 PyTuple_SET_ITEM(args
, 0, menuobj
);
366 PyTuple_SET_ITEM(args
, 1, evtobj
);
367 PyObject
* res
= PyEval_CallObject(func
, args
);
369 Py_XDECREF(res
); /* In case res is a NULL pointer */
370 #ifdef WXP_WITH_THREAD
376 //---------------------------------------------------------------------------
378 wxPyTimer::wxPyTimer(PyObject
* callback
) {
383 wxPyTimer::~wxPyTimer() {
387 void wxPyTimer::Notify() {
388 #ifdef WXP_WITH_THREAD
389 PyEval_RestoreThread(event_tstate
);
392 PyObject
* args
= Py_BuildValue("()");
394 result
= PyEval_CallObject(func
, args
);
402 #ifdef WXP_WITH_THREAD
408 //----------------------------------------------------------------------
410 IMPLEMENT_DYNAMIC_CLASS(wxPyEvent
, wxCommandEvent
)
412 wxPyEvent::wxPyEvent(wxEventType commandType
, PyObject
* userData
)
413 : wxCommandEvent(commandType
), m_userData(Py_None
)
415 m_userData
= userData
;
416 if (m_userData
!= Py_None
) {
417 Py_INCREF(m_userData
);
422 wxPyEvent::~wxPyEvent() {
423 if (m_userData
!= Py_None
) {
424 Py_DECREF(m_userData
);
425 m_userData
= Py_None
;
430 void wxPyEvent::SetUserData(PyObject
* userData
) {
431 if (m_userData
!= Py_None
) {
432 Py_DECREF(m_userData
);
433 m_userData
= Py_None
;
435 m_userData
= userData
;
436 if (m_userData
!= Py_None
) {
437 Py_INCREF(m_userData
);
442 PyObject
* wxPyEvent::GetUserData() {
446 //----------------------------------------------------------------------
447 //----------------------------------------------------------------------
448 // Some helper functions for typemaps in my_typemaps.i, so they won't be
449 // imcluded in every file...
452 byte
* byte_LIST_helper(PyObject
* source
) {
453 if (!PyList_Check(source
)) {
454 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
457 int count
= PyList_Size(source
);
458 byte
* temp
= new byte
[count
];
460 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
463 for (int x
=0; x
<count
; x
++) {
464 PyObject
* o
= PyList_GetItem(source
, x
);
465 if (! PyInt_Check(o
)) {
466 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
469 temp
[x
] = (byte
)PyInt_AsLong(o
);
475 int* int_LIST_helper(PyObject
* source
) {
476 if (!PyList_Check(source
)) {
477 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
480 int count
= PyList_Size(source
);
481 int* temp
= new int[count
];
483 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
486 for (int x
=0; x
<count
; x
++) {
487 PyObject
* o
= PyList_GetItem(source
, x
);
488 if (! PyInt_Check(o
)) {
489 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
492 temp
[x
] = PyInt_AsLong(o
);
498 long* long_LIST_helper(PyObject
* source
) {
499 if (!PyList_Check(source
)) {
500 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
503 int count
= PyList_Size(source
);
504 long* temp
= new long[count
];
506 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
509 for (int x
=0; x
<count
; x
++) {
510 PyObject
* o
= PyList_GetItem(source
, x
);
511 if (! PyInt_Check(o
)) {
512 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
515 temp
[x
] = PyInt_AsLong(o
);
521 char** string_LIST_helper(PyObject
* source
) {
522 if (!PyList_Check(source
)) {
523 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
526 int count
= PyList_Size(source
);
527 char** temp
= new char*[count
];
529 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
532 for (int x
=0; x
<count
; x
++) {
533 PyObject
* o
= PyList_GetItem(source
, x
);
534 if (! PyString_Check(o
)) {
535 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
538 temp
[x
] = PyString_AsString(o
);
545 wxPoint
* wxPoint_LIST_helper(PyObject
* source
) {
546 if (!PyList_Check(source
)) {
547 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
550 int count
= PyList_Size(source
);
551 wxPoint
* temp
= new wxPoint
[count
];
553 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
556 for (int x
=0; x
<count
; x
++) {
557 PyObject
* o
= PyList_GetItem(source
, x
);
558 if (PyString_Check(o
)) {
559 char* st
= PyString_AsString(o
);
561 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxPoint_p")) {
562 PyErr_SetString(PyExc_TypeError
,"Expected _wxPoint_p.");
567 else if (PyTuple_Check(o
)) {
568 PyObject
* o1
= PyTuple_GetItem(o
, 0);
569 PyObject
* o2
= PyTuple_GetItem(o
, 1);
571 temp
[x
].x
= PyInt_AsLong(o1
);
572 temp
[x
].y
= PyInt_AsLong(o2
);
575 PyErr_SetString(PyExc_TypeError
, "Expected a list of 2-tuples or wxPoints.");
583 wxBitmap
** wxBitmap_LIST_helper(PyObject
* source
) {
584 if (!PyList_Check(source
)) {
585 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
588 int count
= PyList_Size(source
);
589 wxBitmap
** temp
= new wxBitmap
*[count
];
591 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
594 for (int x
=0; x
<count
; x
++) {
595 PyObject
* o
= PyList_GetItem(source
, x
);
596 if (PyString_Check(o
)) {
597 char* st
= PyString_AsString(o
);
599 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxBitmap_p")) {
600 PyErr_SetString(PyExc_TypeError
,"Expected _wxBitmap_p.");
606 PyErr_SetString(PyExc_TypeError
, "Expected a list of wxBitmaps.");
615 wxString
* wxString_LIST_helper(PyObject
* source
) {
616 if (!PyList_Check(source
)) {
617 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
620 int count
= PyList_Size(source
);
621 wxString
* temp
= new wxString
[count
];
623 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
626 for (int x
=0; x
<count
; x
++) {
627 PyObject
* o
= PyList_GetItem(source
, x
);
628 if (! PyString_Check(o
)) {
629 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
632 temp
[x
] = PyString_AsString(o
);
638 wxAcceleratorEntry
* wxAcceleratorEntry_LIST_helper(PyObject
* source
) {
639 if (!PyList_Check(source
)) {
640 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
643 int count
= PyList_Size(source
);
644 wxAcceleratorEntry
* temp
= new wxAcceleratorEntry
[count
];
646 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
649 for (int x
=0; x
<count
; x
++) {
650 PyObject
* o
= PyList_GetItem(source
, x
);
651 if (PyString_Check(o
)) {
652 char* st
= PyString_AsString(o
);
653 wxAcceleratorEntry
* ae
;
654 if (SWIG_GetPtr(st
,(void **) &ae
,"_wxAcceleratorEntry_p")) {
655 PyErr_SetString(PyExc_TypeError
,"Expected _wxAcceleratorEntry_p.");
660 else if (PyTuple_Check(o
)) {
661 PyObject
* o1
= PyTuple_GetItem(o
, 0);
662 PyObject
* o2
= PyTuple_GetItem(o
, 1);
663 PyObject
* o3
= PyTuple_GetItem(o
, 2);
665 temp
[x
].m_flags
= PyInt_AsLong(o1
);
666 temp
[x
].m_keyCode
= PyInt_AsLong(o2
);
667 temp
[x
].m_command
= PyInt_AsLong(o3
);
670 PyErr_SetString(PyExc_TypeError
, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
677 //----------------------------------------------------------------------
681 /////////////////////////////////////////////////////////////////////////////
684 // Revision 1.20 1999/04/30 03:29:18 RD
685 // wxPython 2.0b9, first phase (win32)
686 // Added gobs of stuff, see wxPython/README.txt for details
688 // Revision 1.19.4.1 1999/03/27 23:29:14 RD
691 // Python thread support
692 // various minor additions
693 // various minor fixes
695 // Revision 1.19 1999/02/20 09:02:59 RD
696 // Added wxWindow_FromHWND(hWnd) for wxMSW to construct a wxWindow from a
697 // window handle. If you can get the window handle into the python code,
698 // it should just work... More news on this later.
700 // Added wxImageList, wxToolTip.
702 // Re-enabled wxConfig.DeleteAll() since it is reportedly fixed for the
703 // wxRegConfig class.
705 // As usual, some bug fixes, tweaks, etc.
707 // Revision 1.18 1999/01/30 08:17:27 RD
709 // Added wxSashWindow, wxSashEvent, wxLayoutAlgorithm, etc.
711 // Various cleanup, tweaks, minor additions, etc. to maintain
712 // compatibility with the current wxWindows.
714 // Revision 1.17 1999/01/30 07:30:12 RD
716 // Added wxSashWindow, wxSashEvent, wxLayoutAlgorithm, etc.
718 // Various cleanup, tweaks, minor additions, etc. to maintain
719 // compatibility with the current wxWindows.
721 // Revision 1.16 1998/12/17 14:07:39 RR
723 // Removed minor differences between wxMSW and wxGTK
725 // Revision 1.15 1998/12/15 20:41:19 RD
726 // Changed the import semantics from "from wxPython import *" to "from
727 // wxPython.wx import *" This is for people who are worried about
728 // namespace pollution, they can use "from wxPython import wx" and then
729 // prefix all the wxPython identifiers with "wx."
731 // Added wxTaskbarIcon for wxMSW.
733 // Made the events work for wxGrid.
737 // Added wxMiniFrame for wxGTK, (untested.)
739 // Changed many of the args and return values that were pointers to gdi
740 // objects to references to reflect changes in the wxWindows API.
742 // Other assorted fixes and additions.
744 // Revision 1.14 1998/11/25 08:45:25 RD
746 // Added wxPalette, wxRegion, wxRegionIterator, wxTaskbarIcon
747 // Added events for wxGrid
748 // Other various fixes and additions
750 // Revision 1.13 1998/11/15 23:03:45 RD
751 // Removing some ifdef's for wxGTK
753 // Revision 1.12 1998/11/03 09:21:08 RD
756 // Revision 1.11 1998/10/20 06:43:58 RD
757 // New wxTreeCtrl wrappers (untested)
758 // some changes in helpers
761 // Revision 1.10 1998/10/02 06:40:39 RD
763 // Version 0.4 of wxPython for MSW.
765 // Revision 1.9 1998/09/25 13:28:52 VZ
767 // USE_xxx constants renamed to wxUSE_xxx. This is an incompatible change, you
768 // must recompile everything after upgrading!
770 // Revision 1.8 1998/08/27 21:59:08 RD
771 // Some chicken-and-egg problems solved for wxPython on wxGTK
773 // Revision 1.7 1998/08/27 00:00:26 RD
775 // - have discovered some problems but not yet discovered solutions...
777 // Revision 1.6 1998/08/18 21:54:12 RD
779 // ifdef out some wxGTK specific code
781 // Revision 1.5 1998/08/18 19:48:17 RD
782 // more wxGTK compatibility things.
784 // It builds now but there are serious runtime problems...
786 // Revision 1.4 1998/08/16 04:31:06 RD
789 // Revision 1.3 1998/08/15 07:36:36 RD
790 // - Moved the header in the .i files out of the code that gets put into
791 // the .cpp files. It caused CVS conflicts because of the RCS ID being
792 // different each time.
794 // - A few minor fixes.
796 // Revision 1.2 1998/08/14 23:36:36 RD
797 // Beginings of wxGTK compatibility
799 // Revision 1.1 1998/08/09 08:25:51 RD