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
25 #ifdef wxUSE_GDK_IMLIB
26 #include "gdk_imlib/gdk_imlib.h"
30 //---------------------------------------------------------------------------
32 //wxHashTable* wxPyWindows = NULL;
35 wxPoint wxPyDefaultPosition
; //wxDefaultPosition);
36 wxSize wxPyDefaultSize
; //wxDefaultSize);
37 wxString
wxPyEmptyStr("");
41 #ifdef __WXMSW__ // If building for win32...
42 extern HINSTANCE wxhInstance
;
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 wxhInstance
= hinstDLL
;
59 //----------------------------------------------------------------------
60 // Class for implementing the wxp main application shell.
61 //----------------------------------------------------------------------
63 wxPyApp
*wxPythonApp
= NULL
; // Global instance of application object
66 // This one isn't acutally called... See __wxStart()
67 bool wxPyApp::OnInit(void) {
71 int wxPyApp::MainLoop(void) {
72 int retval
= wxApp::MainLoop();
77 void wxPyApp::AfterMainLoop(void) {
78 // more stuff from wxEntry...
81 if (wxPythonApp
->GetTopWindow()) {
82 // Forcibly delete the window.
83 if (wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxFrame
)) ||
84 wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxDialog
))) {
86 wxPythonApp
->GetTopWindow()->Close(TRUE
);
87 wxPythonApp
->DeletePendingObjects();
90 delete wxPythonApp
->GetTopWindow();
91 wxPythonApp
->SetTopWindow(NULL
);
96 wxPythonApp
->DeletePendingObjects();
99 wxPythonApp
->OnExit();
104 wxApp::CommonCleanUp();
106 // delete wxPythonApp;
110 //---------------------------------------------------------------------
111 // a few native methods to add to the module
112 //----------------------------------------------------------------------
115 // This is where we pick up the first part of the wxEntry functionality...
116 // The rest is in __wxStart and AfterMainLoop. This function is called when
117 // wxpc is imported. (Before there is a wxApp object.)
120 // Bail out if there is already windows created. This means that the
121 // toolkit has already been initialized, as in embedding wxPython in
122 // a C++ wxWindows app.
123 if (wxTopLevelWindows
.Number() > 0)
130 wxClassInfo::InitializeClasses();
132 PyObject
* sysargv
= PySys_GetObject("argv");
133 int argc
= PyList_Size(sysargv
);
134 char** argv
= new char*[argc
+1];
136 for(x
=0; x
<argc
; x
++)
137 argv
[x
] = PyString_AsString(PyList_GetItem(sysargv
, x
));
140 gtk_init( &argc
, &argv
);
143 #ifdef wxUSE_GDK_IMLIB
145 gtk_widget_push_visual(gdk_imlib_get_visual());
146 gtk_widget_push_colormap(gdk_imlib_get_colormap());
156 static char* __nullArgv
[1] = { 0 };
158 // Start the user application, user App's OnInit method is a parameter here
159 PyObject
* __wxStart(PyObject
* /* self */, PyObject
* args
)
161 PyObject
* onInitFunc
= NULL
;
167 if (!PyArg_ParseTuple(args
, "O", &onInitFunc
))
170 if (wxTopLevelWindows
.Number() > 0) {
171 PyErr_SetString(PyExc_TypeError
, "Only 1 wxApp per process!");
176 // This is the next part of the wxEntry functionality...
177 wxPythonApp
->argc
= 0;
178 wxPythonApp
->argv
= __nullArgv
;
179 wxPythonApp
->OnInitGui();
182 // Call the Python App's OnInit function
183 arglist
= PyTuple_New(0);
184 result
= PyEval_CallObject(onInitFunc
, arglist
);
190 if (! PyInt_Check(result
)) {
191 PyErr_SetString(PyExc_TypeError
, "OnInit should return a boolean value");
194 bResult
= PyInt_AS_LONG(result
);
196 wxPythonApp
->DeletePendingObjects();
197 wxPythonApp
->OnExit();
202 wxApp::CommonCleanUp();
204 PyErr_SetString(PyExc_SystemExit
, "OnInit returned false, exiting...");
209 wxTheApp
->m_initialized
= (wxTopLevelWindows
.Number() > 0);
220 PyObject
* wxPython_dict
;
221 PyObject
* __wxSetDictionary(PyObject
* /* self */, PyObject
* args
)
224 if (!PyArg_ParseTuple(args
, "O", &wxPython_dict
))
227 if (!PyDict_Check(wxPython_dict
)) {
228 PyErr_SetString(PyExc_TypeError
, "_wxSetDictionary must have dictionary object!");
232 #define wxPlatform "__WXMOTIF__"
235 #define wxPlatform "__WXQT__"
238 #define wxPlatform "__WXGTK__"
240 #if defined(__WIN32__) || defined(__WXMSW__)
241 #define wxPlatform "__WXMSW__"
244 #define wxPlatform "__WXMAC__"
247 PyDict_SetItemString(wxPython_dict
, "wxPlatform", PyString_FromString(wxPlatform
));
254 //---------------------------------------------------------------------------
258 PyObject
* wxPyConstructObject(void* ptr
, char* className
)
260 char buff
[64]; // should always be big enough...
263 sprintf(buff
, "_%s_p", className
);
264 SWIG_MakePtr(swigptr
, ptr
, buff
);
266 sprintf(buff
, "%sPtr", className
);
267 PyObject
* classobj
= PyDict_GetItemString(wxPython_dict
, buff
);
273 PyObject
* arg
= Py_BuildValue("(s)", swigptr
);
274 PyObject
* obj
= PyInstance_New(classobj
, arg
, NULL
);
281 // This function is used for all events destined for Python event handlers.
282 void wxPyCallback::EventThunker(wxEvent
& event
) {
283 wxPyCallback
* cb
= (wxPyCallback
*)event
.m_callbackUserData
;
284 PyObject
* func
= cb
->m_func
;
289 arg
= wxPyConstructObject((void*)&event
, event
.GetClassInfo()->GetClassName());
291 tuple
= PyTuple_New(1);
292 PyTuple_SET_ITEM(tuple
, 0, arg
);
293 result
= PyEval_CallObject(func
, tuple
);
304 //---------------------------------------------------------------------------
306 wxPyMenu::wxPyMenu(const wxString
& title
, PyObject
* _func
)
307 : wxMenu(title
, (wxFunction
)(func
? MenuCallback
: NULL
)), func(0) {
315 wxPyMenu::~wxPyMenu() {
321 void wxPyMenu::MenuCallback(wxMenu
& menu
, wxCommandEvent
& evt
) {
322 PyObject
* evtobj
= wxPyConstructObject((void*)&evt
, "wxCommandEvent");
323 PyObject
* menuobj
= wxPyConstructObject((void*)&menu
, "wxMenu");
324 if (PyErr_Occurred()) {
325 // bail out if a problem
329 // Now call the callback...
330 PyObject
* func
= ((wxPyMenu
*)&menu
)->func
;
331 PyObject
* args
= PyTuple_New(2);
332 PyTuple_SET_ITEM(args
, 0, menuobj
);
333 PyTuple_SET_ITEM(args
, 1, evtobj
);
334 PyObject
* res
= PyEval_CallObject(func
, args
);
336 Py_XDECREF(res
); /* In case res is a NULL pointer */
340 //---------------------------------------------------------------------------
342 wxPyTimer::wxPyTimer(PyObject
* callback
) {
347 wxPyTimer::~wxPyTimer() {
351 void wxPyTimer::Notify() {
353 PyObject
* args
= Py_BuildValue("()");
355 result
= PyEval_CallObject(func
, args
);
367 //----------------------------------------------------------------------
368 //----------------------------------------------------------------------
369 // Some helper functions for typemaps in my_typemaps.i, so they won't be
370 // imcluded in every file...
373 byte
* byte_LIST_helper(PyObject
* source
) {
374 if (!PyList_Check(source
)) {
375 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
378 int count
= PyList_Size(source
);
379 byte
* temp
= new byte
[count
];
381 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
384 for (int x
=0; x
<count
; x
++) {
385 PyObject
* o
= PyList_GetItem(source
, x
);
386 if (! PyInt_Check(o
)) {
387 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
390 temp
[x
] = (byte
)PyInt_AsLong(o
);
396 int* int_LIST_helper(PyObject
* source
) {
397 if (!PyList_Check(source
)) {
398 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
401 int count
= PyList_Size(source
);
402 int* temp
= new int[count
];
404 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
407 for (int x
=0; x
<count
; x
++) {
408 PyObject
* o
= PyList_GetItem(source
, x
);
409 if (! PyInt_Check(o
)) {
410 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
413 temp
[x
] = PyInt_AsLong(o
);
419 long* long_LIST_helper(PyObject
* source
) {
420 if (!PyList_Check(source
)) {
421 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
424 int count
= PyList_Size(source
);
425 long* temp
= new long[count
];
427 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
430 for (int x
=0; x
<count
; x
++) {
431 PyObject
* o
= PyList_GetItem(source
, x
);
432 if (! PyInt_Check(o
)) {
433 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
436 temp
[x
] = PyInt_AsLong(o
);
442 char** string_LIST_helper(PyObject
* source
) {
443 if (!PyList_Check(source
)) {
444 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
447 int count
= PyList_Size(source
);
448 char** temp
= new char*[count
];
450 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
453 for (int x
=0; x
<count
; x
++) {
454 PyObject
* o
= PyList_GetItem(source
, x
);
455 if (! PyString_Check(o
)) {
456 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
459 temp
[x
] = PyString_AsString(o
);
466 wxPoint
* wxPoint_LIST_helper(PyObject
* source
) {
467 if (!PyList_Check(source
)) {
468 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
471 int count
= PyList_Size(source
);
472 wxPoint
* temp
= new wxPoint
[count
];
474 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
477 for (int x
=0; x
<count
; x
++) {
478 PyObject
* o
= PyList_GetItem(source
, x
);
479 if (PyString_Check(o
)) {
480 char* st
= PyString_AsString(o
);
482 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxPoint_p")) {
483 PyErr_SetString(PyExc_TypeError
,"Expected _wxPoint_p.");
488 else if (PyTuple_Check(o
)) {
489 PyObject
* o1
= PyTuple_GetItem(o
, 0);
490 PyObject
* o2
= PyTuple_GetItem(o
, 1);
492 temp
[x
].x
= PyInt_AsLong(o1
);
493 temp
[x
].y
= PyInt_AsLong(o2
);
496 PyErr_SetString(PyExc_TypeError
, "Expected a list of 2-tuples or wxPoints.");
504 wxBitmap
** wxBitmap_LIST_helper(PyObject
* source
) {
505 if (!PyList_Check(source
)) {
506 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
509 int count
= PyList_Size(source
);
510 wxBitmap
** temp
= new wxBitmap
*[count
];
512 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
515 for (int x
=0; x
<count
; x
++) {
516 PyObject
* o
= PyList_GetItem(source
, x
);
517 if (PyString_Check(o
)) {
518 char* st
= PyString_AsString(o
);
520 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxBitmap_p")) {
521 PyErr_SetString(PyExc_TypeError
,"Expected _wxBitmap_p.");
527 PyErr_SetString(PyExc_TypeError
, "Expected a list of wxBitmaps.");
536 wxString
* wxString_LIST_helper(PyObject
* source
) {
537 if (!PyList_Check(source
)) {
538 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
541 int count
= PyList_Size(source
);
542 wxString
* temp
= new wxString
[count
];
544 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
547 for (int x
=0; x
<count
; x
++) {
548 PyObject
* o
= PyList_GetItem(source
, x
);
549 if (! PyString_Check(o
)) {
550 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
553 temp
[x
] = PyString_AsString(o
);
559 wxAcceleratorEntry
* wxAcceleratorEntry_LIST_helper(PyObject
* source
) {
560 if (!PyList_Check(source
)) {
561 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
564 int count
= PyList_Size(source
);
565 wxAcceleratorEntry
* temp
= new wxAcceleratorEntry
[count
];
567 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
570 for (int x
=0; x
<count
; x
++) {
571 PyObject
* o
= PyList_GetItem(source
, x
);
572 if (PyString_Check(o
)) {
573 char* st
= PyString_AsString(o
);
574 wxAcceleratorEntry
* ae
;
575 if (SWIG_GetPtr(st
,(void **) &ae
,"_wxAcceleratorEntry_p")) {
576 PyErr_SetString(PyExc_TypeError
,"Expected _wxAcceleratorEntry_p.");
581 else if (PyTuple_Check(o
)) {
582 PyObject
* o1
= PyTuple_GetItem(o
, 0);
583 PyObject
* o2
= PyTuple_GetItem(o
, 1);
584 PyObject
* o3
= PyTuple_GetItem(o
, 2);
586 temp
[x
].m_flags
= PyInt_AsLong(o1
);
587 temp
[x
].m_keyCode
= PyInt_AsLong(o2
);
588 temp
[x
].m_command
= PyInt_AsLong(o3
);
591 PyErr_SetString(PyExc_TypeError
, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
598 //----------------------------------------------------------------------
602 /////////////////////////////////////////////////////////////////////////////
605 // Revision 1.15 1998/12/15 20:41:19 RD
606 // Changed the import semantics from "from wxPython import *" to "from
607 // wxPython.wx import *" This is for people who are worried about
608 // namespace pollution, they can use "from wxPython import wx" and then
609 // prefix all the wxPython identifiers with "wx."
611 // Added wxTaskbarIcon for wxMSW.
613 // Made the events work for wxGrid.
617 // Added wxMiniFrame for wxGTK, (untested.)
619 // Changed many of the args and return values that were pointers to gdi
620 // objects to references to reflect changes in the wxWindows API.
622 // Other assorted fixes and additions.
624 // Revision 1.14 1998/11/25 08:45:25 RD
626 // Added wxPalette, wxRegion, wxRegionIterator, wxTaskbarIcon
627 // Added events for wxGrid
628 // Other various fixes and additions
630 // Revision 1.13 1998/11/15 23:03:45 RD
631 // Removing some ifdef's for wxGTK
633 // Revision 1.12 1998/11/03 09:21:08 RD
636 // Revision 1.11 1998/10/20 06:43:58 RD
637 // New wxTreeCtrl wrappers (untested)
638 // some changes in helpers
641 // Revision 1.10 1998/10/02 06:40:39 RD
643 // Version 0.4 of wxPython for MSW.
645 // Revision 1.9 1998/09/25 13:28:52 VZ
647 // USE_xxx constants renamed to wxUSE_xxx. This is an incompatible change, you
648 // must recompile everything after upgrading!
650 // Revision 1.8 1998/08/27 21:59:08 RD
651 // Some chicken-and-egg problems solved for wxPython on wxGTK
653 // Revision 1.7 1998/08/27 00:00:26 RD
655 // - have discovered some problems but not yet discovered solutions...
657 // Revision 1.6 1998/08/18 21:54:12 RD
659 // ifdef out some wxGTK specific code
661 // Revision 1.5 1998/08/18 19:48:17 RD
662 // more wxGTK compatibility things.
664 // It builds now but there are serious runtime problems...
666 // Revision 1.4 1998/08/16 04:31:06 RD
669 // Revision 1.3 1998/08/15 07:36:36 RD
670 // - Moved the header in the .i files out of the code that gets put into
671 // the .cpp files. It caused CVS conflicts because of the RCS ID being
672 // different each time.
674 // - A few minor fixes.
676 // Revision 1.2 1998/08/14 23:36:36 RD
677 // Beginings of wxGTK compatibility
679 // Revision 1.1 1998/08/09 08:25:51 RD