1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Helper functions/classes for the wxPython extension module
9 // Copyright: (c) 1998 by Total Control Software
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
17 #undef LoadAccelerators
27 #include <wx/module.h>
29 //---------------------------------------------------------------------------
31 //wxHashTable* wxPyWindows = NULL;
34 wxPoint wxPyDefaultPosition
; //wxDefaultPosition);
35 wxSize wxPyDefaultSize
; //wxDefaultSize);
36 wxString
wxPyEmptyStr("");
40 #ifdef __WXMSW__ // If building for win32...
41 extern HINSTANCE wxhInstance
;
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 wxhInstance
= 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();
76 void wxPyApp::AfterMainLoop(void) {
77 // more stuff from wxEntry...
79 if (wxPythonApp
->GetTopWindow()) {
80 // Forcibly delete the window.
81 if (wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxFrame
)) ||
82 wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxDialog
))) {
84 wxPythonApp
->GetTopWindow()->Close(TRUE
);
85 wxPythonApp
->DeletePendingObjects();
88 delete wxPythonApp
->GetTopWindow();
89 wxPythonApp
->SetTopWindow(NULL
);
93 wxPythonApp
->DeletePendingObjects();
96 wxPythonApp
->OnExit();
98 // delete wxPythonApp;
102 //---------------------------------------------------------------------
103 // a few native methods to add to the module
104 //----------------------------------------------------------------------
107 // This is where we pick up the first part of the wxEntry functionality...
108 // The rest is in __wxStart and AfterMainLoop. This function is called when
109 // wxpc is imported. (Before there is a wxApp object.)
112 // Bail out if there is already windows created. This means that the
113 // toolkit has already been initialized, as in embedding wxPython in
114 // a C++ wxWindows app.
115 if (wxTopLevelWindows
.Number() > 0)
123 PyObject
* sysargv
= PySys_GetObject("argv");
124 int argc
= PyList_Size(sysargv
);
125 char** argv
= new char*[argc
+1];
127 for(x
=0; x
<argc
; x
++)
128 argv
[x
] = PyString_AsString(PyList_GetItem(sysargv
, x
));
132 gtk_init( &argc
, &argv
);
135 wxApp::Initialize(); // may return FALSE. Should we check?
142 static char* __nullArgv
[1] = { 0 };
144 // Start the user application, user App's OnInit method is a parameter here
145 PyObject
* __wxStart(PyObject
* /* self */, PyObject
* args
)
147 PyObject
* onInitFunc
= NULL
;
153 if (!PyArg_ParseTuple(args
, "O", &onInitFunc
))
156 if (wxTopLevelWindows
.Number() > 0) {
157 PyErr_SetString(PyExc_TypeError
, "Only 1 wxApp per process!");
162 // This is the next part of the wxEntry functionality...
163 wxPythonApp
->argc
= 0;
164 wxPythonApp
->argv
= __nullArgv
;
165 wxPythonApp
->OnInitGui();
168 // Call the Python App's OnInit function
169 arglist
= PyTuple_New(0);
170 result
= PyEval_CallObject(onInitFunc
, arglist
);
176 if (! PyInt_Check(result
)) {
177 PyErr_SetString(PyExc_TypeError
, "OnInit should return a boolean value");
180 bResult
= PyInt_AS_LONG(result
);
182 wxPythonApp
->DeletePendingObjects();
183 wxPythonApp
->OnExit();
185 PyErr_SetString(PyExc_SystemExit
, "OnInit returned false, exiting...");
190 wxTheApp
->m_initialized
= (wxTopLevelWindows
.Number() > 0);
201 PyObject
* wxPython_dict
;
202 PyObject
* __wxSetDictionary(PyObject
* /* self */, PyObject
* args
)
205 if (!PyArg_ParseTuple(args
, "O", &wxPython_dict
))
208 if (!PyDict_Check(wxPython_dict
)) {
209 PyErr_SetString(PyExc_TypeError
, "_wxSetDictionary must have dictionary object!");
213 #define wxPlatform "__WXMOTIF__"
216 #define wxPlatform "__WXQT__"
219 #define wxPlatform "__WXGTK__"
221 #if defined(__WIN32__) || defined(__WXMSW__)
222 #define wxPlatform "__WXMSW__"
225 #define wxPlatform "__WXMAC__"
228 PyDict_SetItemString(wxPython_dict
, "wxPlatform", PyString_FromString(wxPlatform
));
235 //---------------------------------------------------------------------------
239 PyObject
* wxPyConstructObject(void* ptr
, char* className
)
241 char buff
[64]; // should always be big enough...
244 sprintf(buff
, "_%s_p", className
);
245 SWIG_MakePtr(swigptr
, ptr
, buff
);
247 sprintf(buff
, "%sPtr", className
);
248 PyObject
* classobj
= PyDict_GetItemString(wxPython_dict
, buff
);
254 PyObject
* arg
= Py_BuildValue("(s)", swigptr
);
255 PyObject
* obj
= PyInstance_New(classobj
, arg
, NULL
);
262 // This function is used for all events destined for Python event handlers.
263 void wxPyCallback::EventThunker(wxEvent
& event
) {
264 wxPyCallback
* cb
= (wxPyCallback
*)event
.m_callbackUserData
;
265 PyObject
* func
= cb
->m_func
;
270 arg
= wxPyConstructObject((void*)&event
, event
.GetClassInfo()->GetClassName());
272 tuple
= PyTuple_New(1);
273 PyTuple_SET_ITEM(tuple
, 0, arg
);
274 result
= PyEval_CallObject(func
, tuple
);
285 //---------------------------------------------------------------------------
287 wxPyMenu::wxPyMenu(const wxString
& title
, PyObject
* _func
)
288 : wxMenu(title
, (wxFunction
)(func
? MenuCallback
: NULL
)), func(0) {
296 wxPyMenu::~wxPyMenu() {
302 void wxPyMenu::MenuCallback(wxMenu
& menu
, wxCommandEvent
& evt
) {
303 PyObject
* evtobj
= wxPyConstructObject((void*)&evt
, "wxCommandEvent");
304 PyObject
* menuobj
= wxPyConstructObject((void*)&menu
, "wxMenu");
305 if (PyErr_Occurred()) {
306 // bail out if a problem
310 // Now call the callback...
311 PyObject
* func
= ((wxPyMenu
*)&menu
)->func
;
312 PyObject
* args
= PyTuple_New(2);
313 PyTuple_SET_ITEM(args
, 0, menuobj
);
314 PyTuple_SET_ITEM(args
, 1, evtobj
);
315 PyObject
* res
= PyEval_CallObject(func
, args
);
317 Py_XDECREF(res
); /* In case res is a NULL pointer */
321 //---------------------------------------------------------------------------
323 wxPyTimer::wxPyTimer(PyObject
* callback
) {
328 wxPyTimer::~wxPyTimer() {
332 void wxPyTimer::Notify() {
334 PyObject
* args
= Py_BuildValue("()");
336 result
= PyEval_CallObject(func
, args
);
348 //----------------------------------------------------------------------
349 //----------------------------------------------------------------------
350 // Some helper functions for typemaps in my_typemaps.i, so they won't be
351 // imcluded in every file...
354 byte
* byte_LIST_helper(PyObject
* source
) {
355 if (!PyList_Check(source
)) {
356 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
359 int count
= PyList_Size(source
);
360 byte
* temp
= new byte
[count
];
362 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
365 for (int x
=0; x
<count
; x
++) {
366 PyObject
* o
= PyList_GetItem(source
, x
);
367 if (! PyInt_Check(o
)) {
368 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
371 temp
[x
] = (byte
)PyInt_AsLong(o
);
377 int* int_LIST_helper(PyObject
* source
) {
378 if (!PyList_Check(source
)) {
379 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
382 int count
= PyList_Size(source
);
383 int* temp
= new int[count
];
385 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
388 for (int x
=0; x
<count
; x
++) {
389 PyObject
* o
= PyList_GetItem(source
, x
);
390 if (! PyInt_Check(o
)) {
391 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
394 temp
[x
] = PyInt_AsLong(o
);
400 long* long_LIST_helper(PyObject
* source
) {
401 if (!PyList_Check(source
)) {
402 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
405 int count
= PyList_Size(source
);
406 long* temp
= new long[count
];
408 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
411 for (int x
=0; x
<count
; x
++) {
412 PyObject
* o
= PyList_GetItem(source
, x
);
413 if (! PyInt_Check(o
)) {
414 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
417 temp
[x
] = PyInt_AsLong(o
);
423 char** string_LIST_helper(PyObject
* source
) {
424 if (!PyList_Check(source
)) {
425 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
428 int count
= PyList_Size(source
);
429 char** temp
= new char*[count
];
431 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
434 for (int x
=0; x
<count
; x
++) {
435 PyObject
* o
= PyList_GetItem(source
, x
);
436 if (! PyString_Check(o
)) {
437 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
440 temp
[x
] = PyString_AsString(o
);
447 wxPoint
* wxPoint_LIST_helper(PyObject
* source
) {
448 if (!PyList_Check(source
)) {
449 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
452 int count
= PyList_Size(source
);
453 wxPoint
* temp
= new wxPoint
[count
];
455 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
458 for (int x
=0; x
<count
; x
++) {
459 PyObject
* o
= PyList_GetItem(source
, x
);
460 if (PyString_Check(o
)) {
461 char* st
= PyString_AsString(o
);
463 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxPoint_p")) {
464 PyErr_SetString(PyExc_TypeError
,"Expected _wxPoint_p.");
469 else if (PyTuple_Check(o
)) {
470 PyObject
* o1
= PyTuple_GetItem(o
, 0);
471 PyObject
* o2
= PyTuple_GetItem(o
, 1);
473 temp
[x
].x
= PyInt_AsLong(o1
);
474 temp
[x
].y
= PyInt_AsLong(o2
);
477 PyErr_SetString(PyExc_TypeError
, "Expected a list of 2-tuples or wxPoints.");
485 wxBitmap
** wxBitmap_LIST_helper(PyObject
* source
) {
486 if (!PyList_Check(source
)) {
487 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
490 int count
= PyList_Size(source
);
491 wxBitmap
** temp
= new wxBitmap
*[count
];
493 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
496 for (int x
=0; x
<count
; x
++) {
497 PyObject
* o
= PyList_GetItem(source
, x
);
498 if (PyString_Check(o
)) {
499 char* st
= PyString_AsString(o
);
501 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxBitmap_p")) {
502 PyErr_SetString(PyExc_TypeError
,"Expected _wxBitmap_p.");
508 PyErr_SetString(PyExc_TypeError
, "Expected a list of wxBitmaps.");
517 wxString
* wxString_LIST_helper(PyObject
* source
) {
518 if (!PyList_Check(source
)) {
519 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
522 int count
= PyList_Size(source
);
523 wxString
* temp
= new wxString
[count
];
525 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
528 for (int x
=0; x
<count
; x
++) {
529 PyObject
* o
= PyList_GetItem(source
, x
);
530 if (! PyString_Check(o
)) {
531 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
534 temp
[x
] = PyString_AsString(o
);
540 wxAcceleratorEntry
* wxAcceleratorEntry_LIST_helper(PyObject
* source
) {
541 if (!PyList_Check(source
)) {
542 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
545 int count
= PyList_Size(source
);
546 wxAcceleratorEntry
* temp
= new wxAcceleratorEntry
[count
];
548 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
551 for (int x
=0; x
<count
; x
++) {
552 PyObject
* o
= PyList_GetItem(source
, x
);
553 if (PyString_Check(o
)) {
554 char* st
= PyString_AsString(o
);
555 wxAcceleratorEntry
* ae
;
556 if (SWIG_GetPtr(st
,(void **) &ae
,"_wxAcceleratorEntry_p")) {
557 PyErr_SetString(PyExc_TypeError
,"Expected _wxAcceleratorEntry_p.");
562 else if (PyTuple_Check(o
)) {
563 PyObject
* o1
= PyTuple_GetItem(o
, 0);
564 PyObject
* o2
= PyTuple_GetItem(o
, 1);
565 PyObject
* o3
= PyTuple_GetItem(o
, 2);
567 temp
[x
].m_flags
= PyInt_AsLong(o1
);
568 temp
[x
].m_keyCode
= PyInt_AsLong(o2
);
569 temp
[x
].m_command
= PyInt_AsLong(o3
);
572 PyErr_SetString(PyExc_TypeError
, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
579 //----------------------------------------------------------------------
583 /////////////////////////////////////////////////////////////////////////////
586 // Revision 1.18 1999/01/30 08:17:27 RD
587 // Added wxSashWindow, wxSashEvent, wxLayoutAlgorithm, etc.
589 // Various cleanup, tweaks, minor additions, etc. to maintain
590 // compatibility with the current wxWindows.
592 // Revision 1.17 1999/01/30 07:30:12 RD
594 // Added wxSashWindow, wxSashEvent, wxLayoutAlgorithm, etc.
596 // Various cleanup, tweaks, minor additions, etc. to maintain
597 // compatibility with the current wxWindows.
599 // Revision 1.16 1998/12/17 14:07:39 RR
601 // Removed minor differences between wxMSW and wxGTK
603 // Revision 1.15 1998/12/15 20:41:19 RD
604 // Changed the import semantics from "from wxPython import *" to "from
605 // wxPython.wx import *" This is for people who are worried about
606 // namespace pollution, they can use "from wxPython import wx" and then
607 // prefix all the wxPython identifiers with "wx."
609 // Added wxTaskbarIcon for wxMSW.
611 // Made the events work for wxGrid.
615 // Added wxMiniFrame for wxGTK, (untested.)
617 // Changed many of the args and return values that were pointers to gdi
618 // objects to references to reflect changes in the wxWindows API.
620 // Other assorted fixes and additions.
622 // Revision 1.14 1998/11/25 08:45:25 RD
624 // Added wxPalette, wxRegion, wxRegionIterator, wxTaskbarIcon
625 // Added events for wxGrid
626 // Other various fixes and additions
628 // Revision 1.13 1998/11/15 23:03:45 RD
629 // Removing some ifdef's for wxGTK
631 // Revision 1.12 1998/11/03 09:21:08 RD
634 // Revision 1.11 1998/10/20 06:43:58 RD
635 // New wxTreeCtrl wrappers (untested)
636 // some changes in helpers
639 // Revision 1.10 1998/10/02 06:40:39 RD
641 // Version 0.4 of wxPython for MSW.
643 // Revision 1.9 1998/09/25 13:28:52 VZ
645 // USE_xxx constants renamed to wxUSE_xxx. This is an incompatible change, you
646 // must recompile everything after upgrading!
648 // Revision 1.8 1998/08/27 21:59:08 RD
649 // Some chicken-and-egg problems solved for wxPython on wxGTK
651 // Revision 1.7 1998/08/27 00:00:26 RD
653 // - have discovered some problems but not yet discovered solutions...
655 // Revision 1.6 1998/08/18 21:54:12 RD
657 // ifdef out some wxGTK specific code
659 // Revision 1.5 1998/08/18 19:48:17 RD
660 // more wxGTK compatibility things.
662 // It builds now but there are serious runtime problems...
664 // Revision 1.4 1998/08/16 04:31:06 RD
667 // Revision 1.3 1998/08/15 07:36:36 RD
668 // - Moved the header in the .i files out of the code that gets put into
669 // the .cpp files. It caused CVS conflicts because of the RCS ID being
670 // different each time.
672 // - A few minor fixes.
674 // Revision 1.2 1998/08/14 23:36:36 RD
675 // Beginings of wxGTK compatibility
677 // Revision 1.1 1998/08/09 08:25:51 RD