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>
31 //---------------------------------------------------------------------------
33 //wxHashTable* wxPyWindows = NULL;
36 wxPoint wxPyDefaultPosition
; //wxDefaultPosition);
37 wxSize wxPyDefaultSize
; //wxDefaultSize);
38 wxString
wxPyEmptyStr("");
42 #ifdef __WXMSW__ // If building for win32...
43 //----------------------------------------------------------------------
44 // This gets run when the DLL is loaded. We just need to save a handle.
45 //----------------------------------------------------------------------
48 HINSTANCE hinstDLL
, // handle to DLL module
49 DWORD fdwReason
, // reason for calling function
50 LPVOID lpvReserved
// reserved
53 wxSetInstance(hinstDLL
);
58 //----------------------------------------------------------------------
59 // Class for implementing the wxp main application shell.
60 //----------------------------------------------------------------------
62 wxPyApp
*wxPythonApp
= NULL
; // Global instance of application object
65 // This one isn't acutally called... See __wxStart()
66 bool wxPyApp::OnInit(void) {
70 int wxPyApp::MainLoop(void) {
71 int retval
= wxApp::MainLoop();
77 void wxPyApp::AfterMainLoop(void) {
78 // more stuff from wxEntry...
80 if (wxPythonApp
->GetTopWindow()) {
81 // Forcibly delete the window.
82 if (wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxFrame
)) ||
83 wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxDialog
))) {
85 wxPythonApp
->GetTopWindow()->Close(TRUE
);
86 wxPythonApp
->DeletePendingObjects();
89 delete wxPythonApp
->GetTopWindow();
90 wxPythonApp
->SetTopWindow(NULL
);
94 wxPythonApp
->DeletePendingObjects();
97 wxPythonApp
->OnExit();
99 // delete wxPythonApp;
103 //---------------------------------------------------------------------
104 // a few native methods to add to the module
105 //----------------------------------------------------------------------
108 // This is where we pick up the first part of the wxEntry functionality...
109 // The rest is in __wxStart and AfterMainLoop. This function is called when
110 // wxpc is imported. (Before there is a wxApp object.)
113 // Bail out if there is already windows created. This means that the
114 // toolkit has already been initialized, as in embedding wxPython in
115 // a C++ wxWindows app.
116 if (wxTopLevelWindows
.Number() > 0)
124 PyObject
* sysargv
= PySys_GetObject("argv");
125 int argc
= PyList_Size(sysargv
);
126 char** argv
= new char*[argc
+1];
128 for(x
=0; x
<argc
; x
++)
129 argv
[x
] = PyString_AsString(PyList_GetItem(sysargv
, x
));
133 gtk_init( &argc
, &argv
);
136 wxApp::Initialize(); // may return FALSE. Should we check?
143 static char* __nullArgv
[1] = { 0 };
145 // Start the user application, user App's OnInit method is a parameter here
146 PyObject
* __wxStart(PyObject
* /* self */, PyObject
* args
)
148 PyObject
* onInitFunc
= NULL
;
154 if (!PyArg_ParseTuple(args
, "O", &onInitFunc
))
157 if (wxTopLevelWindows
.Number() > 0) {
158 PyErr_SetString(PyExc_TypeError
, "Only 1 wxApp per process!");
163 // This is the next part of the wxEntry functionality...
164 wxPythonApp
->argc
= 0;
165 wxPythonApp
->argv
= __nullArgv
;
166 wxPythonApp
->OnInitGui();
169 // Call the Python App's OnInit function
170 arglist
= PyTuple_New(0);
171 result
= PyEval_CallObject(onInitFunc
, arglist
);
177 if (! PyInt_Check(result
)) {
178 PyErr_SetString(PyExc_TypeError
, "OnInit should return a boolean value");
181 bResult
= PyInt_AS_LONG(result
);
183 wxPythonApp
->DeletePendingObjects();
184 wxPythonApp
->OnExit();
186 PyErr_SetString(PyExc_SystemExit
, "OnInit returned false, exiting...");
191 wxTheApp
->m_initialized
= (wxTopLevelWindows
.Number() > 0);
202 PyObject
* wxPython_dict
;
203 PyObject
* __wxSetDictionary(PyObject
* /* self */, PyObject
* args
)
206 if (!PyArg_ParseTuple(args
, "O", &wxPython_dict
))
209 if (!PyDict_Check(wxPython_dict
)) {
210 PyErr_SetString(PyExc_TypeError
, "_wxSetDictionary must have dictionary object!");
214 #define wxPlatform "__WXMOTIF__"
217 #define wxPlatform "__WXQT__"
220 #define wxPlatform "__WXGTK__"
222 #if defined(__WIN32__) || defined(__WXMSW__)
223 #define wxPlatform "__WXMSW__"
226 #define wxPlatform "__WXMAC__"
229 PyDict_SetItemString(wxPython_dict
, "wxPlatform", PyString_FromString(wxPlatform
));
236 //---------------------------------------------------------------------------
240 PyObject
* wxPyConstructObject(void* ptr
, char* className
)
242 char buff
[64]; // should always be big enough...
245 sprintf(buff
, "_%s_p", className
);
246 SWIG_MakePtr(swigptr
, ptr
, buff
);
248 sprintf(buff
, "%sPtr", className
);
249 PyObject
* classobj
= PyDict_GetItemString(wxPython_dict
, buff
);
255 PyObject
* arg
= Py_BuildValue("(s)", swigptr
);
256 PyObject
* obj
= PyInstance_New(classobj
, arg
, NULL
);
263 // This function is used for all events destined for Python event handlers.
264 void wxPyCallback::EventThunker(wxEvent
& event
) {
265 wxPyCallback
* cb
= (wxPyCallback
*)event
.m_callbackUserData
;
266 PyObject
* func
= cb
->m_func
;
271 arg
= wxPyConstructObject((void*)&event
, event
.GetClassInfo()->GetClassName());
273 tuple
= PyTuple_New(1);
274 PyTuple_SET_ITEM(tuple
, 0, arg
);
275 result
= PyEval_CallObject(func
, tuple
);
286 //---------------------------------------------------------------------------
288 wxPyMenu::wxPyMenu(const wxString
& title
, PyObject
* _func
)
289 : wxMenu(title
, (wxFunction
)(func
? MenuCallback
: NULL
)), func(0) {
297 wxPyMenu::~wxPyMenu() {
303 void wxPyMenu::MenuCallback(wxMenu
& menu
, wxCommandEvent
& evt
) {
304 PyObject
* evtobj
= wxPyConstructObject((void*)&evt
, "wxCommandEvent");
305 PyObject
* menuobj
= wxPyConstructObject((void*)&menu
, "wxMenu");
306 if (PyErr_Occurred()) {
307 // bail out if a problem
311 // Now call the callback...
312 PyObject
* func
= ((wxPyMenu
*)&menu
)->func
;
313 PyObject
* args
= PyTuple_New(2);
314 PyTuple_SET_ITEM(args
, 0, menuobj
);
315 PyTuple_SET_ITEM(args
, 1, evtobj
);
316 PyObject
* res
= PyEval_CallObject(func
, args
);
318 Py_XDECREF(res
); /* In case res is a NULL pointer */
322 //---------------------------------------------------------------------------
324 wxPyTimer::wxPyTimer(PyObject
* callback
) {
329 wxPyTimer::~wxPyTimer() {
333 void wxPyTimer::Notify() {
335 PyObject
* args
= Py_BuildValue("()");
337 result
= PyEval_CallObject(func
, args
);
349 //----------------------------------------------------------------------
350 //----------------------------------------------------------------------
351 // Some helper functions for typemaps in my_typemaps.i, so they won't be
352 // imcluded in every file...
355 byte
* byte_LIST_helper(PyObject
* source
) {
356 if (!PyList_Check(source
)) {
357 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
360 int count
= PyList_Size(source
);
361 byte
* temp
= new byte
[count
];
363 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
366 for (int x
=0; x
<count
; x
++) {
367 PyObject
* o
= PyList_GetItem(source
, x
);
368 if (! PyInt_Check(o
)) {
369 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
372 temp
[x
] = (byte
)PyInt_AsLong(o
);
378 int* int_LIST_helper(PyObject
* source
) {
379 if (!PyList_Check(source
)) {
380 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
383 int count
= PyList_Size(source
);
384 int* temp
= new int[count
];
386 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
389 for (int x
=0; x
<count
; x
++) {
390 PyObject
* o
= PyList_GetItem(source
, x
);
391 if (! PyInt_Check(o
)) {
392 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
395 temp
[x
] = PyInt_AsLong(o
);
401 long* long_LIST_helper(PyObject
* source
) {
402 if (!PyList_Check(source
)) {
403 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
406 int count
= PyList_Size(source
);
407 long* temp
= new long[count
];
409 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
412 for (int x
=0; x
<count
; x
++) {
413 PyObject
* o
= PyList_GetItem(source
, x
);
414 if (! PyInt_Check(o
)) {
415 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
418 temp
[x
] = PyInt_AsLong(o
);
424 char** string_LIST_helper(PyObject
* source
) {
425 if (!PyList_Check(source
)) {
426 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
429 int count
= PyList_Size(source
);
430 char** temp
= new char*[count
];
432 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
435 for (int x
=0; x
<count
; x
++) {
436 PyObject
* o
= PyList_GetItem(source
, x
);
437 if (! PyString_Check(o
)) {
438 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
441 temp
[x
] = PyString_AsString(o
);
448 wxPoint
* wxPoint_LIST_helper(PyObject
* source
) {
449 if (!PyList_Check(source
)) {
450 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
453 int count
= PyList_Size(source
);
454 wxPoint
* temp
= new wxPoint
[count
];
456 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
459 for (int x
=0; x
<count
; x
++) {
460 PyObject
* o
= PyList_GetItem(source
, x
);
461 if (PyString_Check(o
)) {
462 char* st
= PyString_AsString(o
);
464 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxPoint_p")) {
465 PyErr_SetString(PyExc_TypeError
,"Expected _wxPoint_p.");
470 else if (PyTuple_Check(o
)) {
471 PyObject
* o1
= PyTuple_GetItem(o
, 0);
472 PyObject
* o2
= PyTuple_GetItem(o
, 1);
474 temp
[x
].x
= PyInt_AsLong(o1
);
475 temp
[x
].y
= PyInt_AsLong(o2
);
478 PyErr_SetString(PyExc_TypeError
, "Expected a list of 2-tuples or wxPoints.");
486 wxBitmap
** wxBitmap_LIST_helper(PyObject
* source
) {
487 if (!PyList_Check(source
)) {
488 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
491 int count
= PyList_Size(source
);
492 wxBitmap
** temp
= new wxBitmap
*[count
];
494 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
497 for (int x
=0; x
<count
; x
++) {
498 PyObject
* o
= PyList_GetItem(source
, x
);
499 if (PyString_Check(o
)) {
500 char* st
= PyString_AsString(o
);
502 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxBitmap_p")) {
503 PyErr_SetString(PyExc_TypeError
,"Expected _wxBitmap_p.");
509 PyErr_SetString(PyExc_TypeError
, "Expected a list of wxBitmaps.");
518 wxString
* wxString_LIST_helper(PyObject
* source
) {
519 if (!PyList_Check(source
)) {
520 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
523 int count
= PyList_Size(source
);
524 wxString
* temp
= new wxString
[count
];
526 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
529 for (int x
=0; x
<count
; x
++) {
530 PyObject
* o
= PyList_GetItem(source
, x
);
531 if (! PyString_Check(o
)) {
532 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
535 temp
[x
] = PyString_AsString(o
);
541 wxAcceleratorEntry
* wxAcceleratorEntry_LIST_helper(PyObject
* source
) {
542 if (!PyList_Check(source
)) {
543 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
546 int count
= PyList_Size(source
);
547 wxAcceleratorEntry
* temp
= new wxAcceleratorEntry
[count
];
549 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
552 for (int x
=0; x
<count
; x
++) {
553 PyObject
* o
= PyList_GetItem(source
, x
);
554 if (PyString_Check(o
)) {
555 char* st
= PyString_AsString(o
);
556 wxAcceleratorEntry
* ae
;
557 if (SWIG_GetPtr(st
,(void **) &ae
,"_wxAcceleratorEntry_p")) {
558 PyErr_SetString(PyExc_TypeError
,"Expected _wxAcceleratorEntry_p.");
563 else if (PyTuple_Check(o
)) {
564 PyObject
* o1
= PyTuple_GetItem(o
, 0);
565 PyObject
* o2
= PyTuple_GetItem(o
, 1);
566 PyObject
* o3
= PyTuple_GetItem(o
, 2);
568 temp
[x
].m_flags
= PyInt_AsLong(o1
);
569 temp
[x
].m_keyCode
= PyInt_AsLong(o2
);
570 temp
[x
].m_command
= PyInt_AsLong(o3
);
573 PyErr_SetString(PyExc_TypeError
, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
580 //----------------------------------------------------------------------
584 /////////////////////////////////////////////////////////////////////////////
587 // Revision 1.19 1999/02/20 09:02:59 RD
588 // Added wxWindow_FromHWND(hWnd) for wxMSW to construct a wxWindow from a
589 // window handle. If you can get the window handle into the python code,
590 // it should just work... More news on this later.
592 // Added wxImageList, wxToolTip.
594 // Re-enabled wxConfig.DeleteAll() since it is reportedly fixed for the
595 // wxRegConfig class.
597 // As usual, some bug fixes, tweaks, etc.
599 // Revision 1.18 1999/01/30 08:17:27 RD
601 // Added wxSashWindow, wxSashEvent, wxLayoutAlgorithm, etc.
603 // Various cleanup, tweaks, minor additions, etc. to maintain
604 // compatibility with the current wxWindows.
606 // Revision 1.17 1999/01/30 07:30:12 RD
608 // Added wxSashWindow, wxSashEvent, wxLayoutAlgorithm, etc.
610 // Various cleanup, tweaks, minor additions, etc. to maintain
611 // compatibility with the current wxWindows.
613 // Revision 1.16 1998/12/17 14:07:39 RR
615 // Removed minor differences between wxMSW and wxGTK
617 // Revision 1.15 1998/12/15 20:41:19 RD
618 // Changed the import semantics from "from wxPython import *" to "from
619 // wxPython.wx import *" This is for people who are worried about
620 // namespace pollution, they can use "from wxPython import wx" and then
621 // prefix all the wxPython identifiers with "wx."
623 // Added wxTaskbarIcon for wxMSW.
625 // Made the events work for wxGrid.
629 // Added wxMiniFrame for wxGTK, (untested.)
631 // Changed many of the args and return values that were pointers to gdi
632 // objects to references to reflect changes in the wxWindows API.
634 // Other assorted fixes and additions.
636 // Revision 1.14 1998/11/25 08:45:25 RD
638 // Added wxPalette, wxRegion, wxRegionIterator, wxTaskbarIcon
639 // Added events for wxGrid
640 // Other various fixes and additions
642 // Revision 1.13 1998/11/15 23:03:45 RD
643 // Removing some ifdef's for wxGTK
645 // Revision 1.12 1998/11/03 09:21:08 RD
648 // Revision 1.11 1998/10/20 06:43:58 RD
649 // New wxTreeCtrl wrappers (untested)
650 // some changes in helpers
653 // Revision 1.10 1998/10/02 06:40:39 RD
655 // Version 0.4 of wxPython for MSW.
657 // Revision 1.9 1998/09/25 13:28:52 VZ
659 // USE_xxx constants renamed to wxUSE_xxx. This is an incompatible change, you
660 // must recompile everything after upgrading!
662 // Revision 1.8 1998/08/27 21:59:08 RD
663 // Some chicken-and-egg problems solved for wxPython on wxGTK
665 // Revision 1.7 1998/08/27 00:00:26 RD
667 // - have discovered some problems but not yet discovered solutions...
669 // Revision 1.6 1998/08/18 21:54:12 RD
671 // ifdef out some wxGTK specific code
673 // Revision 1.5 1998/08/18 19:48:17 RD
674 // more wxGTK compatibility things.
676 // It builds now but there are serious runtime problems...
678 // Revision 1.4 1998/08/16 04:31:06 RD
681 // Revision 1.3 1998/08/15 07:36:36 RD
682 // - Moved the header in the .i files out of the code that gets put into
683 // the .cpp files. It caused CVS conflicts because of the RCS ID being
684 // different each time.
686 // - A few minor fixes.
688 // Revision 1.2 1998/08/14 23:36:36 RD
689 // Beginings of wxGTK compatibility
691 // Revision 1.1 1998/08/09 08:25:51 RD