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();
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 int* int_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 int* temp
= new int[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
] = PyInt_AsLong(o
);
396 long* long_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 long* temp
= new long[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 char** string_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 char** temp
= new char*[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 (! PyString_Check(o
)) {
433 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
436 temp
[x
] = PyString_AsString(o
);
443 wxPoint
* wxPoint_LIST_helper(PyObject
* source
) {
444 if (!PyList_Check(source
)) {
445 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
448 int count
= PyList_Size(source
);
449 wxPoint
* temp
= new wxPoint
[count
];
451 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
454 for (int x
=0; x
<count
; x
++) {
455 PyObject
* o
= PyList_GetItem(source
, x
);
456 if (PyString_Check(o
)) {
457 char* st
= PyString_AsString(o
);
459 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxPoint_p")) {
460 PyErr_SetString(PyExc_TypeError
,"Expected _wxPoint_p.");
465 else if (PyTuple_Check(o
)) {
466 PyObject
* o1
= PyTuple_GetItem(o
, 0);
467 PyObject
* o2
= PyTuple_GetItem(o
, 1);
469 temp
[x
].x
= PyInt_AsLong(o1
);
470 temp
[x
].y
= PyInt_AsLong(o2
);
473 PyErr_SetString(PyExc_TypeError
, "Expected a list of 2-tuples or wxPoints.");
481 wxBitmap
** wxBitmap_LIST_helper(PyObject
* source
) {
482 if (!PyList_Check(source
)) {
483 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
486 int count
= PyList_Size(source
);
487 wxBitmap
** temp
= new wxBitmap
*[count
];
489 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
492 for (int x
=0; x
<count
; x
++) {
493 PyObject
* o
= PyList_GetItem(source
, x
);
494 if (PyString_Check(o
)) {
495 char* st
= PyString_AsString(o
);
497 if (SWIG_GetPtr(st
,(void **) &pt
,"_wxBitmap_p")) {
498 PyErr_SetString(PyExc_TypeError
,"Expected _wxBitmap_p.");
504 PyErr_SetString(PyExc_TypeError
, "Expected a list of wxBitmaps.");
513 wxString
* wxString_LIST_helper(PyObject
* source
) {
514 if (!PyList_Check(source
)) {
515 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
518 int count
= PyList_Size(source
);
519 wxString
* temp
= new wxString
[count
];
521 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
524 for (int x
=0; x
<count
; x
++) {
525 PyObject
* o
= PyList_GetItem(source
, x
);
526 if (! PyString_Check(o
)) {
527 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
530 temp
[x
] = PyString_AsString(o
);
537 wxAcceleratorEntry
* wxAcceleratorEntry_LIST_helper(PyObject
* source
) {
538 if (!PyList_Check(source
)) {
539 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
542 int count
= PyList_Size(source
);
543 wxAcceleratorEntry
* temp
= new wxAcceleratorEntry
[count
];
545 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
548 for (int x
=0; x
<count
; x
++) {
549 PyObject
* o
= PyList_GetItem(source
, x
);
550 if (PyString_Check(o
)) {
551 char* st
= PyString_AsString(o
);
552 wxAcceleratorEntry
* ae
;
553 if (SWIG_GetPtr(st
,(void **) &ae
,"_wxAcceleratorEntry_p")) {
554 PyErr_SetString(PyExc_TypeError
,"Expected _wxAcceleratorEntry_p.");
559 else if (PyTuple_Check(o
)) {
560 PyObject
* o1
= PyTuple_GetItem(o
, 0);
561 PyObject
* o2
= PyTuple_GetItem(o
, 1);
562 PyObject
* o3
= PyTuple_GetItem(o
, 2);
564 temp
[x
].m_flags
= PyInt_AsLong(o1
);
565 temp
[x
].m_keyCode
= PyInt_AsLong(o2
);
566 temp
[x
].m_command
= PyInt_AsLong(o3
);
569 PyErr_SetString(PyExc_TypeError
, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
578 //----------------------------------------------------------------------
579 // A WinMain for when wxWindows and Python are linked together in a single
580 // application, instead of as a dynamic module
583 //#if !defined(WIN_PYD) && defined(WIN32)
585 //extern "C" int Py_Main(int argc, char** argv);
587 //int APIENTRY WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR m_lpCmdLine,
593 // // Initialize wxWindows, but don't start the main loop
594 // wxEntry(hInstance, hPrevInstance, m_lpCmdLine, nCmdShow, FALSE);
597 // PyObject *argvList = PyList_New(0);
599 // char* stderrfilename = "wxpstderr.log";
601 // char* script = NULL;
602 // int argc = wxPythonApp->argc;
603 // char** argv = wxPythonApp->argv;
605 // for (int i = 1; i < argc; i++) {
606 // if (strncmp(argv[i], "wxpstderr=", 10) == 0)
607 // stderrfilename = argv[i]+10;
609 // PyList_Append(argvList, PyString_FromString(argv[i]));
616 // PySys_SetObject("argv", argvList);
620 //// //PyRun_SimpleString("import sys; sys.stdout=open('wxpstdout.log','w')");
621 // sprintf(buf, "import sys; sys.stdout=sys.stderr=open('%s','w')", stderrfilename);
622 // PyRun_SimpleString(buf);
628 // FILE *fp = fopen(script, "r");
630 // PyRun_SimpleFile(fp, script);// This returns after wxpApp constructor
635 // sprintf(msg, "Cannot open %s", script);
636 // wxMessageBox(msg);
640 // PyRun_SimpleString("import wxpide");
648 //----------------------------------------------------------------------
650 /////////////////////////////////////////////////////////////////////////////
653 // Revision 1.12 1998/11/03 09:21:08 RD
656 // Revision 1.11 1998/10/20 06:43:58 RD
657 // New wxTreeCtrl wrappers (untested)
658 // some changes in helpers
661 // Revision 1.10 1998/10/02 06:40:39 RD
663 // Version 0.4 of wxPython for MSW.
665 // Revision 1.9 1998/09/25 13:28:52 VZ
667 // USE_xxx constants renamed to wxUSE_xxx. This is an incompatible change, you
668 // must recompile everything after upgrading!
670 // Revision 1.8 1998/08/27 21:59:08 RD
671 // Some chicken-and-egg problems solved for wxPython on wxGTK
673 // Revision 1.7 1998/08/27 00:00:26 RD
675 // - have discovered some problems but not yet discovered solutions...
677 // Revision 1.6 1998/08/18 21:54:12 RD
679 // ifdef out some wxGTK specific code
681 // Revision 1.5 1998/08/18 19:48:17 RD
682 // more wxGTK compatibility things.
684 // It builds now but there are serious runtime problems...
686 // Revision 1.4 1998/08/16 04:31:06 RD
689 // Revision 1.3 1998/08/15 07:36:36 RD
690 // - Moved the header in the .i files out of the code that gets put into
691 // the .cpp files. It caused CVS conflicts because of the RCS ID being
692 // different each time.
694 // - A few minor fixes.
696 // Revision 1.2 1998/08/14 23:36:36 RD
697 // Beginings of wxGTK compatibility
699 // Revision 1.1 1998/08/09 08:25:51 RD