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
28 //---------------------------------------------------------------------------
30 //wxHashTable* wxPyWindows = NULL;
33 wxPoint wxPyDefaultPosition
; //wxDefaultPosition);
34 wxSize wxPyDefaultSize
; //wxDefaultSize);
35 wxString
wxPyEmptyStr("");
39 #ifdef __WXMSW__ // If building for win32...
40 extern HINSTANCE wxhInstance
;
42 //----------------------------------------------------------------------
43 // This gets run when the DLL is loaded. We just need to save a handle.
44 //----------------------------------------------------------------------
47 HINSTANCE hinstDLL
, // handle to DLL module
48 DWORD fdwReason
, // reason for calling function
49 LPVOID lpvReserved
// reserved
52 wxhInstance
= hinstDLL
;
57 //----------------------------------------------------------------------
58 // Class for implementing the wxp main application shell.
59 //----------------------------------------------------------------------
61 wxPyApp
*wxPythonApp
= NULL
; // Global instance of application object
64 // This one isn't acutally called... See __wxStart()
65 bool wxPyApp::OnInit(void) {
69 int wxPyApp::MainLoop(void) {
70 int retval
= wxApp::MainLoop();
75 void wxPyApp::AfterMainLoop(void) {
76 // more stuff from wxEntry...
78 if (wxPythonApp
->GetTopWindow()) {
79 // Forcibly delete the window.
80 if (wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxFrame
)) ||
81 wxPythonApp
->GetTopWindow()->IsKindOf(CLASSINFO(wxDialog
))) {
83 wxPythonApp
->GetTopWindow()->Close(TRUE
);
84 wxPythonApp
->DeletePendingObjects();
87 delete wxPythonApp
->GetTopWindow();
88 wxPythonApp
->SetTopWindow(NULL
);
92 wxPythonApp
->DeletePendingObjects();
95 wxPythonApp
->OnExit();
97 // delete wxPythonApp;
101 //---------------------------------------------------------------------
102 // a few native methods to add to the module
103 //----------------------------------------------------------------------
106 // This is where we pick up the first part of the wxEntry functionality...
107 // The rest is in __wxStart and AfterMainLoop. This function is called when
108 // wxpc is imported. (Before there is a wxApp object.)
111 // Bail out if there is already windows created. This means that the
112 // toolkit has already been initialized, as in embedding wxPython in
113 // a C++ wxWindows app.
114 if (wxTopLevelWindows
.Number() > 0)
122 PyObject
* sysargv
= PySys_GetObject("argv");
123 int argc
= PyList_Size(sysargv
);
124 char** argv
= new char*[argc
+1];
126 for(x
=0; x
<argc
; x
++)
127 argv
[x
] = PyString_AsString(PyList_GetItem(sysargv
, x
));
131 gtk_init( &argc
, &argv
);
134 wxApp::Initialize(); // may return FALSE. Should we check?
141 static char* __nullArgv
[1] = { 0 };
143 // Start the user application, user App's OnInit method is a parameter here
144 PyObject
* __wxStart(PyObject
* /* self */, PyObject
* args
)
146 PyObject
* onInitFunc
= NULL
;
152 if (!PyArg_ParseTuple(args
, "O", &onInitFunc
))
155 if (wxTopLevelWindows
.Number() > 0) {
156 PyErr_SetString(PyExc_TypeError
, "Only 1 wxApp per process!");
161 // This is the next part of the wxEntry functionality...
162 wxPythonApp
->argc
= 0;
163 wxPythonApp
->argv
= __nullArgv
;
164 wxPythonApp
->OnInitGui();
167 // Call the Python App's OnInit function
168 arglist
= PyTuple_New(0);
169 result
= PyEval_CallObject(onInitFunc
, arglist
);
175 if (! PyInt_Check(result
)) {
176 PyErr_SetString(PyExc_TypeError
, "OnInit should return a boolean value");
179 bResult
= PyInt_AS_LONG(result
);
181 wxPythonApp
->DeletePendingObjects();
182 wxPythonApp
->OnExit();
184 PyErr_SetString(PyExc_SystemExit
, "OnInit returned false, exiting...");
189 wxTheApp
->m_initialized
= (wxTopLevelWindows
.Number() > 0);
200 PyObject
* wxPython_dict
;
201 PyObject
* __wxSetDictionary(PyObject
* /* self */, PyObject
* args
)
204 if (!PyArg_ParseTuple(args
, "O", &wxPython_dict
))
207 if (!PyDict_Check(wxPython_dict
)) {
208 PyErr_SetString(PyExc_TypeError
, "_wxSetDictionary must have dictionary object!");
212 #define wxPlatform "__WXMOTIF__"
215 #define wxPlatform "__WXQT__"
218 #define wxPlatform "__WXGTK__"
220 #if defined(__WIN32__) || defined(__WXMSW__)
221 #define wxPlatform "__WXMSW__"
224 #define wxPlatform "__WXMAC__"
227 PyDict_SetItemString(wxPython_dict
, "wxPlatform", PyString_FromString(wxPlatform
));
234 //---------------------------------------------------------------------------
238 PyObject
* wxPyConstructObject(void* ptr
, char* className
)
240 char buff
[64]; // should always be big enough...
243 sprintf(buff
, "_%s_p", className
);
244 SWIG_MakePtr(swigptr
, ptr
, buff
);
246 sprintf(buff
, "%sPtr", className
);
247 PyObject
* classobj
= PyDict_GetItemString(wxPython_dict
, buff
);
253 PyObject
* arg
= Py_BuildValue("(s)", swigptr
);
254 PyObject
* obj
= PyInstance_New(classobj
, arg
, NULL
);
261 // This function is used for all events destined for Python event handlers.
262 void wxPyCallback::EventThunker(wxEvent
& event
) {
263 wxPyCallback
* cb
= (wxPyCallback
*)event
.m_callbackUserData
;
264 PyObject
* func
= cb
->m_func
;
269 arg
= wxPyConstructObject((void*)&event
, event
.GetClassInfo()->GetClassName());
271 tuple
= PyTuple_New(1);
272 PyTuple_SET_ITEM(tuple
, 0, arg
);
273 result
= PyEval_CallObject(func
, tuple
);
284 //---------------------------------------------------------------------------
286 wxPyMenu::wxPyMenu(const wxString
& title
, PyObject
* _func
)
287 : wxMenu(title
, (wxFunction
)(func
? MenuCallback
: NULL
)), func(0) {
295 wxPyMenu::~wxPyMenu() {
301 void wxPyMenu::MenuCallback(wxMenu
& menu
, wxCommandEvent
& evt
) {
302 PyObject
* evtobj
= wxPyConstructObject((void*)&evt
, "wxCommandEvent");
303 PyObject
* menuobj
= wxPyConstructObject((void*)&menu
, "wxMenu");
304 if (PyErr_Occurred()) {
305 // bail out if a problem
309 // Now call the callback...
310 PyObject
* func
= ((wxPyMenu
*)&menu
)->func
;
311 PyObject
* args
= PyTuple_New(2);
312 PyTuple_SET_ITEM(args
, 0, menuobj
);
313 PyTuple_SET_ITEM(args
, 1, evtobj
);
314 PyObject
* res
= PyEval_CallObject(func
, args
);
316 Py_XDECREF(res
); /* In case res is a NULL pointer */
320 //---------------------------------------------------------------------------
322 wxPyTimer::wxPyTimer(PyObject
* callback
) {
327 wxPyTimer::~wxPyTimer() {
331 void wxPyTimer::Notify() {
333 PyObject
* args
= Py_BuildValue("()");
335 result
= PyEval_CallObject(func
, args
);
347 //----------------------------------------------------------------------
348 //----------------------------------------------------------------------
349 // Some helper functions for typemaps in my_typemaps.i, so they won't be
350 // imcluded in every file...
353 byte
* byte_LIST_helper(PyObject
* source
) {
354 if (!PyList_Check(source
)) {
355 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
358 int count
= PyList_Size(source
);
359 byte
* temp
= new byte
[count
];
361 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
364 for (int x
=0; x
<count
; x
++) {
365 PyObject
* o
= PyList_GetItem(source
, x
);
366 if (! PyInt_Check(o
)) {
367 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
370 temp
[x
] = (byte
)PyInt_AsLong(o
);
376 int* int_LIST_helper(PyObject
* source
) {
377 if (!PyList_Check(source
)) {
378 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
381 int count
= PyList_Size(source
);
382 int* temp
= new int[count
];
384 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
387 for (int x
=0; x
<count
; x
++) {
388 PyObject
* o
= PyList_GetItem(source
, x
);
389 if (! PyInt_Check(o
)) {
390 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
393 temp
[x
] = PyInt_AsLong(o
);
399 long* long_LIST_helper(PyObject
* source
) {
400 if (!PyList_Check(source
)) {
401 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
404 int count
= PyList_Size(source
);
405 long* temp
= new long[count
];
407 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
410 for (int x
=0; x
<count
; x
++) {
411 PyObject
* o
= PyList_GetItem(source
, x
);
412 if (! PyInt_Check(o
)) {
413 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
416 temp
[x
] = PyInt_AsLong(o
);
422 char** string_LIST_helper(PyObject
* source
) {
423 if (!PyList_Check(source
)) {
424 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
427 int count
= PyList_Size(source
);
428 char** temp
= new char*[count
];
430 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
433 for (int x
=0; x
<count
; x
++) {
434 PyObject
* o
= PyList_GetItem(source
, x
);
435 if (! PyString_Check(o
)) {
436 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
439 temp
[x
] = PyString_AsString(o
);
446 wxPoint
* wxPoint_LIST_helper(PyObject
* source
) {
447 if (!PyList_Check(source
)) {
448 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
451 int count
= PyList_Size(source
);
452 wxPoint
* temp
= new wxPoint
[count
];
454 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
457 for (int x
=0; x
<count
; x
++) {
458 PyObject
* o
= PyList_GetItem(source
, x
);
459 if (PyString_Check(o
)) {
460 char* st
= PyString_AsString(o
);
462 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxPoint_p")) {
463 PyErr_SetString(PyExc_TypeError
,"Expected _wxPoint_p.");
468 else if (PyTuple_Check(o
)) {
469 PyObject
* o1
= PyTuple_GetItem(o
, 0);
470 PyObject
* o2
= PyTuple_GetItem(o
, 1);
472 temp
[x
].x
= PyInt_AsLong(o1
);
473 temp
[x
].y
= PyInt_AsLong(o2
);
476 PyErr_SetString(PyExc_TypeError
, "Expected a list of 2-tuples or wxPoints.");
484 wxBitmap
** wxBitmap_LIST_helper(PyObject
* source
) {
485 if (!PyList_Check(source
)) {
486 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
489 int count
= PyList_Size(source
);
490 wxBitmap
** temp
= new wxBitmap
*[count
];
492 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
495 for (int x
=0; x
<count
; x
++) {
496 PyObject
* o
= PyList_GetItem(source
, x
);
497 if (PyString_Check(o
)) {
498 char* st
= PyString_AsString(o
);
500 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxBitmap_p")) {
501 PyErr_SetString(PyExc_TypeError
,"Expected _wxBitmap_p.");
507 PyErr_SetString(PyExc_TypeError
, "Expected a list of wxBitmaps.");
516 wxString
* wxString_LIST_helper(PyObject
* source
) {
517 if (!PyList_Check(source
)) {
518 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
521 int count
= PyList_Size(source
);
522 wxString
* temp
= new wxString
[count
];
524 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
527 for (int x
=0; x
<count
; x
++) {
528 PyObject
* o
= PyList_GetItem(source
, x
);
529 if (! PyString_Check(o
)) {
530 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
533 temp
[x
] = PyString_AsString(o
);
539 wxAcceleratorEntry
* wxAcceleratorEntry_LIST_helper(PyObject
* source
) {
540 if (!PyList_Check(source
)) {
541 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
544 int count
= PyList_Size(source
);
545 wxAcceleratorEntry
* temp
= new wxAcceleratorEntry
[count
];
547 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
550 for (int x
=0; x
<count
; x
++) {
551 PyObject
* o
= PyList_GetItem(source
, x
);
552 if (PyString_Check(o
)) {
553 char* st
= PyString_AsString(o
);
554 wxAcceleratorEntry
* ae
;
555 if (SWIG_GetPtr(st
,(void **) &ae
,"_wxAcceleratorEntry_p")) {
556 PyErr_SetString(PyExc_TypeError
,"Expected _wxAcceleratorEntry_p.");
561 else if (PyTuple_Check(o
)) {
562 PyObject
* o1
= PyTuple_GetItem(o
, 0);
563 PyObject
* o2
= PyTuple_GetItem(o
, 1);
564 PyObject
* o3
= PyTuple_GetItem(o
, 2);
566 temp
[x
].m_flags
= PyInt_AsLong(o1
);
567 temp
[x
].m_keyCode
= PyInt_AsLong(o2
);
568 temp
[x
].m_command
= PyInt_AsLong(o3
);
571 PyErr_SetString(PyExc_TypeError
, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
578 //----------------------------------------------------------------------
582 /////////////////////////////////////////////////////////////////////////////
585 // Revision 1.17 1999/01/30 07:30:12 RD
586 // Added wxSashWindow, wxSashEvent, wxLayoutAlgorithm, etc.
588 // Various cleanup, tweaks, minor additions, etc. to maintain
589 // compatibility with the current wxWindows.
591 // Revision 1.16 1998/12/17 14:07:39 RR
593 // Removed minor differences between wxMSW and wxGTK
595 // Revision 1.15 1998/12/15 20:41:19 RD
596 // Changed the import semantics from "from wxPython import *" to "from
597 // wxPython.wx import *" This is for people who are worried about
598 // namespace pollution, they can use "from wxPython import wx" and then
599 // prefix all the wxPython identifiers with "wx."
601 // Added wxTaskbarIcon for wxMSW.
603 // Made the events work for wxGrid.
607 // Added wxMiniFrame for wxGTK, (untested.)
609 // Changed many of the args and return values that were pointers to gdi
610 // objects to references to reflect changes in the wxWindows API.
612 // Other assorted fixes and additions.
614 // Revision 1.14 1998/11/25 08:45:25 RD
616 // Added wxPalette, wxRegion, wxRegionIterator, wxTaskbarIcon
617 // Added events for wxGrid
618 // Other various fixes and additions
620 // Revision 1.13 1998/11/15 23:03:45 RD
621 // Removing some ifdef's for wxGTK
623 // Revision 1.12 1998/11/03 09:21:08 RD
626 // Revision 1.11 1998/10/20 06:43:58 RD
627 // New wxTreeCtrl wrappers (untested)
628 // some changes in helpers
631 // Revision 1.10 1998/10/02 06:40:39 RD
633 // Version 0.4 of wxPython for MSW.
635 // Revision 1.9 1998/09/25 13:28:52 VZ
637 // USE_xxx constants renamed to wxUSE_xxx. This is an incompatible change, you
638 // must recompile everything after upgrading!
640 // Revision 1.8 1998/08/27 21:59:08 RD
641 // Some chicken-and-egg problems solved for wxPython on wxGTK
643 // Revision 1.7 1998/08/27 00:00:26 RD
645 // - have discovered some problems but not yet discovered solutions...
647 // Revision 1.6 1998/08/18 21:54:12 RD
649 // ifdef out some wxGTK specific code
651 // Revision 1.5 1998/08/18 19:48:17 RD
652 // more wxGTK compatibility things.
654 // It builds now but there are serious runtime problems...
656 // Revision 1.4 1998/08/16 04:31:06 RD
659 // Revision 1.3 1998/08/15 07:36:36 RD
660 // - Moved the header in the .i files out of the code that gets put into
661 // the .cpp files. It caused CVS conflicts because of the RCS ID being
662 // different each time.
664 // - A few minor fixes.
666 // Revision 1.2 1998/08/14 23:36:36 RD
667 // Beginings of wxGTK compatibility
669 // Revision 1.1 1998/08/09 08:25:51 RD