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
24 //---------------------------------------------------------------------------
26 //wxHashTable* wxPyWindows = NULL;
29 wxPoint wxPyDefaultPosition
; //wxDefaultPosition);
30 wxSize wxPyDefaultSize
; //wxDefaultSize);
31 wxString
wxPyEmptyStr("");
35 #ifdef __WXMSW__ // If building for win32...
36 extern HINSTANCE wxhInstance
;
38 //----------------------------------------------------------------------
39 // This gets run when the DLL is loaded. We just need to save a handle.
40 //----------------------------------------------------------------------
43 HINSTANCE hinstDLL
, // handle to DLL module
44 DWORD fdwReason
, // reason for calling function
45 LPVOID lpvReserved
// reserved
48 wxhInstance
= hinstDLL
;
53 //----------------------------------------------------------------------
54 // Class for implementing the wxp main application shell.
55 //----------------------------------------------------------------------
57 wxPyApp
*wxPythonApp
= NULL
; // Global instance of application object
60 // This one isn't acutally called... See __wxStart()
61 bool wxPyApp::OnInit(void) {
65 int wxPyApp::MainLoop(void) {
66 int retval
= wxApp::MainLoop();
71 void wxPyApp::AfterMainLoop(void) {
72 // more stuff from wxEntry...
75 if (wxPythonApp
->GetTopWindow()) {
76 // Forcibly delete the window.
77 if (wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxFrame
)) ||
78 wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxDialog
))) {
80 wxPythonApp
->GetTopWindow()->Close(TRUE
);
81 wxPythonApp
->DeletePendingObjects();
84 delete wxPythonApp
->GetTopWindow();
85 wxPythonApp
->SetTopWindow(NULL
);
90 wxPythonApp
->DeletePendingObjects();
93 wxPythonApp
->OnExit();
98 wxApp::CommonCleanUp();
100 // delete wxPythonApp;
104 //---------------------------------------------------------------------
105 // a few native methods to add to the module
106 //----------------------------------------------------------------------
109 // This is where we pick up the first part of the wxEntry functionality...
110 // The rest is in __wxStart and AfterMainLoop. This function is called when
111 // wxpc is imported. (Before there is a wxApp object.)
114 // Bail out if there is already windows created. This means that the
115 // toolkit has already been initialized, as in embedding wxPython in
116 // a C++ wxWindows app.
117 if (wxTopLevelWindows
.Number() > 0)
124 wxClassInfo::InitializeClasses();
126 PyObject
* sysargv
= PySys_GetObject("argv");
127 int argc
= PyList_Size(sysargv
);
128 char** argv
= new char*[argc
+1];
130 for(x
=0; x
<argc
; x
++)
131 argv
[x
] = PyString_AsString(PyList_GetItem(sysargv
, x
));
134 gtk_init( &argc
, &argv
);
144 static char* __nullArgv
[1] = { 0 };
146 // Start the user application, user App's OnInit method is a parameter here
147 PyObject
* __wxStart(PyObject
* /* self */, PyObject
* args
)
149 PyObject
* onInitFunc
= NULL
;
155 if (!PyArg_ParseTuple(args
, "O", &onInitFunc
))
158 if (wxTopLevelWindows
.Number() > 0) {
159 PyErr_SetString(PyExc_TypeError
, "Only 1 wxApp per process!");
164 // This is the next part of the wxEntry functionality...
165 wxPythonApp
->argc
= 0;
166 wxPythonApp
->argv
= __nullArgv
;
167 wxPythonApp
->OnInitGui();
170 // Call the Python App's OnInit function
171 arglist
= PyTuple_New(0);
172 result
= PyEval_CallObject(onInitFunc
, arglist
);
178 if (! PyInt_Check(result
)) {
179 PyErr_SetString(PyExc_TypeError
, "OnInit should return a boolean value");
182 bResult
= PyInt_AS_LONG(result
);
184 wxPythonApp
->DeletePendingObjects();
185 wxPythonApp
->OnExit();
190 wxApp::CommonCleanUp();
192 PyErr_SetString(PyExc_SystemExit
, "OnInit returned false, exiting...");
197 wxTheApp
->m_initialized
= (wxTopLevelWindows
.Number() > 0);
208 PyObject
* wxPython_dict
;
209 PyObject
* __wxSetDictionary(PyObject
* /* self */, PyObject
* args
)
212 if (!PyArg_ParseTuple(args
, "O", &wxPython_dict
))
215 if (!PyDict_Check(wxPython_dict
)) {
216 PyErr_SetString(PyExc_TypeError
, "_wxSetDictionary must have dictionary object!");
220 #define wxPlatform "__WXMOTIF__"
223 #define wxPlatform "__WXQT__"
226 #define wxPlatform "__WXGTK__"
228 #if defined(__WIN32__) || defined(__WXMSW__)
229 #define wxPlatform "__WXMSW__"
232 #define wxPlatform "__WXMAC__"
235 PyDict_SetItemString(wxPython_dict
, "wxPlatform", PyString_FromString(wxPlatform
));
242 //---------------------------------------------------------------------------
246 PyObject
* wxPyConstructObject(void* ptr
, char* className
)
248 char buff
[64]; // should always be big enough...
251 sprintf(buff
, "_%s_p", className
);
252 SWIG_MakePtr(swigptr
, ptr
, buff
);
254 sprintf(buff
, "%sPtr", className
);
255 PyObject
* classobj
= PyDict_GetItemString(wxPython_dict
, buff
);
261 PyObject
* arg
= Py_BuildValue("(s)", swigptr
);
262 PyObject
* obj
= PyInstance_New(classobj
, arg
, NULL
);
269 // This function is used for all events destined for Python event handlers.
270 void wxPyCallback::EventThunker(wxEvent
& event
) {
271 wxPyCallback
* cb
= (wxPyCallback
*)event
.m_callbackUserData
;
272 PyObject
* func
= cb
->m_func
;
277 arg
= wxPyConstructObject((void*)&event
, event
.GetClassInfo()->GetClassName());
279 tuple
= PyTuple_New(1);
280 PyTuple_SET_ITEM(tuple
, 0, arg
);
281 result
= PyEval_CallObject(func
, tuple
);
292 //---------------------------------------------------------------------------
294 wxPyMenu::wxPyMenu(const wxString
& title
, PyObject
* _func
)
295 : wxMenu(title
, (wxFunction
)(func
? MenuCallback
: NULL
)), func(0) {
303 wxPyMenu::~wxPyMenu() {
309 void wxPyMenu::MenuCallback(wxMenu
& menu
, wxCommandEvent
& evt
) {
310 PyObject
* evtobj
= wxPyConstructObject((void*)&evt
, "wxCommandEvent");
311 PyObject
* menuobj
= wxPyConstructObject((void*)&menu
, "wxMenu");
312 if (PyErr_Occurred()) {
313 // bail out if a problem
317 // Now call the callback...
318 PyObject
* func
= ((wxPyMenu
*)&menu
)->func
;
319 PyObject
* args
= PyTuple_New(2);
320 PyTuple_SET_ITEM(args
, 0, menuobj
);
321 PyTuple_SET_ITEM(args
, 1, evtobj
);
322 PyObject
* res
= PyEval_CallObject(func
, args
);
324 Py_XDECREF(res
); /* In case res is a NULL pointer */
328 //---------------------------------------------------------------------------
330 wxPyTimer::wxPyTimer(PyObject
* callback
) {
335 wxPyTimer::~wxPyTimer() {
339 void wxPyTimer::Notify() {
341 PyObject
* args
= Py_BuildValue("()");
343 result
= PyEval_CallObject(func
, args
);
355 //----------------------------------------------------------------------
356 //----------------------------------------------------------------------
357 // Some helper functions for typemaps in my_typemaps.i, so they won't be
358 // imcluded in every file...
361 byte
* byte_LIST_helper(PyObject
* source
) {
362 if (!PyList_Check(source
)) {
363 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
366 int count
= PyList_Size(source
);
367 byte
* temp
= new byte
[count
];
369 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
372 for (int x
=0; x
<count
; x
++) {
373 PyObject
* o
= PyList_GetItem(source
, x
);
374 if (! PyInt_Check(o
)) {
375 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
378 temp
[x
] = (byte
)PyInt_AsLong(o
);
384 int* int_LIST_helper(PyObject
* source
) {
385 if (!PyList_Check(source
)) {
386 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
389 int count
= PyList_Size(source
);
390 int* temp
= new int[count
];
392 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
395 for (int x
=0; x
<count
; x
++) {
396 PyObject
* o
= PyList_GetItem(source
, x
);
397 if (! PyInt_Check(o
)) {
398 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
401 temp
[x
] = PyInt_AsLong(o
);
407 long* long_LIST_helper(PyObject
* source
) {
408 if (!PyList_Check(source
)) {
409 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
412 int count
= PyList_Size(source
);
413 long* temp
= new long[count
];
415 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
418 for (int x
=0; x
<count
; x
++) {
419 PyObject
* o
= PyList_GetItem(source
, x
);
420 if (! PyInt_Check(o
)) {
421 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
424 temp
[x
] = PyInt_AsLong(o
);
430 char** string_LIST_helper(PyObject
* source
) {
431 if (!PyList_Check(source
)) {
432 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
435 int count
= PyList_Size(source
);
436 char** temp
= new char*[count
];
438 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
441 for (int x
=0; x
<count
; x
++) {
442 PyObject
* o
= PyList_GetItem(source
, x
);
443 if (! PyString_Check(o
)) {
444 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
447 temp
[x
] = PyString_AsString(o
);
454 wxPoint
* wxPoint_LIST_helper(PyObject
* source
) {
455 if (!PyList_Check(source
)) {
456 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
459 int count
= PyList_Size(source
);
460 wxPoint
* temp
= new wxPoint
[count
];
462 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
465 for (int x
=0; x
<count
; x
++) {
466 PyObject
* o
= PyList_GetItem(source
, x
);
467 if (PyString_Check(o
)) {
468 char* st
= PyString_AsString(o
);
470 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxPoint_p")) {
471 PyErr_SetString(PyExc_TypeError
,"Expected _wxPoint_p.");
476 else if (PyTuple_Check(o
)) {
477 PyObject
* o1
= PyTuple_GetItem(o
, 0);
478 PyObject
* o2
= PyTuple_GetItem(o
, 1);
480 temp
[x
].x
= PyInt_AsLong(o1
);
481 temp
[x
].y
= PyInt_AsLong(o2
);
484 PyErr_SetString(PyExc_TypeError
, "Expected a list of 2-tuples or wxPoints.");
492 wxBitmap
** wxBitmap_LIST_helper(PyObject
* source
) {
493 if (!PyList_Check(source
)) {
494 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
497 int count
= PyList_Size(source
);
498 wxBitmap
** temp
= new wxBitmap
*[count
];
500 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
503 for (int x
=0; x
<count
; x
++) {
504 PyObject
* o
= PyList_GetItem(source
, x
);
505 if (PyString_Check(o
)) {
506 char* st
= PyString_AsString(o
);
508 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxBitmap_p")) {
509 PyErr_SetString(PyExc_TypeError
,"Expected _wxBitmap_p.");
515 PyErr_SetString(PyExc_TypeError
, "Expected a list of wxBitmaps.");
524 wxString
* wxString_LIST_helper(PyObject
* source
) {
525 if (!PyList_Check(source
)) {
526 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
529 int count
= PyList_Size(source
);
530 wxString
* temp
= new wxString
[count
];
532 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
535 for (int x
=0; x
<count
; x
++) {
536 PyObject
* o
= PyList_GetItem(source
, x
);
537 if (! PyString_Check(o
)) {
538 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
541 temp
[x
] = PyString_AsString(o
);
547 wxAcceleratorEntry
* wxAcceleratorEntry_LIST_helper(PyObject
* source
) {
548 if (!PyList_Check(source
)) {
549 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
552 int count
= PyList_Size(source
);
553 wxAcceleratorEntry
* temp
= new wxAcceleratorEntry
[count
];
555 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
558 for (int x
=0; x
<count
; x
++) {
559 PyObject
* o
= PyList_GetItem(source
, x
);
560 if (PyString_Check(o
)) {
561 char* st
= PyString_AsString(o
);
562 wxAcceleratorEntry
* ae
;
563 if (SWIG_GetPtr(st
,(void **) &ae
,"_wxAcceleratorEntry_p")) {
564 PyErr_SetString(PyExc_TypeError
,"Expected _wxAcceleratorEntry_p.");
569 else if (PyTuple_Check(o
)) {
570 PyObject
* o1
= PyTuple_GetItem(o
, 0);
571 PyObject
* o2
= PyTuple_GetItem(o
, 1);
572 PyObject
* o3
= PyTuple_GetItem(o
, 2);
574 temp
[x
].m_flags
= PyInt_AsLong(o1
);
575 temp
[x
].m_keyCode
= PyInt_AsLong(o2
);
576 temp
[x
].m_command
= PyInt_AsLong(o3
);
579 PyErr_SetString(PyExc_TypeError
, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
586 //----------------------------------------------------------------------
590 /////////////////////////////////////////////////////////////////////////////
593 // Revision 1.16 1998/12/17 14:07:39 RR
594 // Removed minor differences between wxMSW and wxGTK
596 // Revision 1.15 1998/12/15 20:41:19 RD
597 // Changed the import semantics from "from wxPython import *" to "from
598 // wxPython.wx import *" This is for people who are worried about
599 // namespace pollution, they can use "from wxPython import wx" and then
600 // prefix all the wxPython identifiers with "wx."
602 // Added wxTaskbarIcon for wxMSW.
604 // Made the events work for wxGrid.
608 // Added wxMiniFrame for wxGTK, (untested.)
610 // Changed many of the args and return values that were pointers to gdi
611 // objects to references to reflect changes in the wxWindows API.
613 // Other assorted fixes and additions.
615 // Revision 1.14 1998/11/25 08:45:25 RD
617 // Added wxPalette, wxRegion, wxRegionIterator, wxTaskbarIcon
618 // Added events for wxGrid
619 // Other various fixes and additions
621 // Revision 1.13 1998/11/15 23:03:45 RD
622 // Removing some ifdef's for wxGTK
624 // Revision 1.12 1998/11/03 09:21:08 RD
627 // Revision 1.11 1998/10/20 06:43:58 RD
628 // New wxTreeCtrl wrappers (untested)
629 // some changes in helpers
632 // Revision 1.10 1998/10/02 06:40:39 RD
634 // Version 0.4 of wxPython for MSW.
636 // Revision 1.9 1998/09/25 13:28:52 VZ
638 // USE_xxx constants renamed to wxUSE_xxx. This is an incompatible change, you
639 // must recompile everything after upgrading!
641 // Revision 1.8 1998/08/27 21:59:08 RD
642 // Some chicken-and-egg problems solved for wxPython on wxGTK
644 // Revision 1.7 1998/08/27 00:00:26 RD
646 // - have discovered some problems but not yet discovered solutions...
648 // Revision 1.6 1998/08/18 21:54:12 RD
650 // ifdef out some wxGTK specific code
652 // Revision 1.5 1998/08/18 19:48:17 RD
653 // more wxGTK compatibility things.
655 // It builds now but there are serious runtime problems...
657 // Revision 1.4 1998/08/16 04:31:06 RD
660 // Revision 1.3 1998/08/15 07:36:36 RD
661 // - Moved the header in the .i files out of the code that gets put into
662 // the .cpp files. It caused CVS conflicts because of the RCS ID being
663 // different each time.
665 // - A few minor fixes.
667 // Revision 1.2 1998/08/14 23:36:36 RD
668 // Beginings of wxGTK compatibility
670 // Revision 1.1 1998/08/09 08:25:51 RD