]> git.saurik.com Git - wxWidgets.git/blame - utils/wxPython/src/helpers.cpp
const added to GetBitmap it was my fault.
[wxWidgets.git] / utils / wxPython / src / helpers.cpp
CommitLineData
7bf85405
RD
1/////////////////////////////////////////////////////////////////////////////
2// Name: helpers.cpp
03e9bead 3// Purpose: Helper functions/classes for the wxPython extension module
7bf85405
RD
4//
5// Author: Robin Dunn
6//
7// Created: 7/1/97
8// RCS-ID: $Id$
9// Copyright: (c) 1998 by Total Control Software
10// Licence: wxWindows license
11/////////////////////////////////////////////////////////////////////////////
12
21f4bf45
RD
13#ifdef __WXMSW__
14#include <windows.h>
15#undef FindWindow
16#undef GetCharWidth
17#undef LoadAccelerators
18#endif
19
7bf85405
RD
20#undef DEBUG
21#include <Python.h>
22#include "helpers.h"
23
853b255a
RD
24#ifdef __WXGTK__
25#ifdef USE_GDK_IMLIB
26#include "gdk_imlib/gdk_imlib.h"
27#endif
28#endif
7bf85405
RD
29
30//---------------------------------------------------------------------------
31
32//wxHashTable* wxPyWindows = NULL;
33
34
35wxPoint wxPyDefaultPosition; //wxDefaultPosition);
36wxSize wxPyDefaultSize; //wxDefaultSize);
37wxString wxPyEmptyStr("");
38
39
40
21f4bf45
RD
41#ifdef __WXMSW__ // If building for win32...
42extern HINSTANCE wxhInstance;
43
44//----------------------------------------------------------------------
45// This gets run when the DLL is loaded. We just need to save a handle.
46//----------------------------------------------------------------------
47BOOL WINAPI DllMain(
48 HINSTANCE hinstDLL, // handle to DLL module
49 DWORD fdwReason, // reason for calling function
50 LPVOID lpvReserved // reserved
51 )
52{
53 wxhInstance = hinstDLL;
54 return 1;
55}
56#endif
57
7bf85405
RD
58//----------------------------------------------------------------------
59// Class for implementing the wxp main application shell.
60//----------------------------------------------------------------------
61
62wxPyApp *wxPythonApp = NULL; // Global instance of application object
63
64
65// This one isn't acutally called... See __wxStart()
66bool wxPyApp::OnInit(void) {
67 return false;
68}
69
70int wxPyApp::MainLoop(void) {
71 int retval = wxApp::MainLoop();
72 AfterMainLoop();
73 return retval;
74}
75
76void wxPyApp::AfterMainLoop(void) {
77 // more stuff from wxEntry...
0d6f9504
RD
78
79#ifdef __WXMSW__
7bf85405
RD
80 if (wxPythonApp->GetTopWindow()) {
81 // Forcibly delete the window.
82 if (wxPythonApp->GetTopWindow()->IsKindOf(CLASSINFO(wxFrame)) ||
83 wxPythonApp->GetTopWindow()->IsKindOf(CLASSINFO(wxDialog))) {
84
85 wxPythonApp->GetTopWindow()->Close(TRUE);
86 wxPythonApp->DeletePendingObjects();
87 }
88 else {
89 delete wxPythonApp->GetTopWindow();
90 wxPythonApp->SetTopWindow(NULL);
91 }
92 }
0d6f9504
RD
93#endif
94#ifdef __WXGTK__
95 wxPythonApp->DeletePendingObjects();
96#endif
7bf85405
RD
97
98 wxPythonApp->OnExit();
99#ifdef __WXMSW__
100 wxApp::CleanUp();
101#endif
102#ifdef __WXGTK__
853b255a 103 wxApp::CommonCleanUp();
7bf85405
RD
104#endif
105 delete wxPythonApp;
106}
107
108
fb5e0af0 109//---------------------------------------------------------------------
7bf85405
RD
110// a few native methods to add to the module
111//----------------------------------------------------------------------
112
113
0d6f9504
RD
114// This is where we pick up the first part of the wxEntry functionality...
115// The rest is in __wxStart and AfterMainLoop. Thi function is called when
116// wxpc is imported. (Before there is a wxApp object.)
117void __wxPreStart()
7bf85405 118{
0d6f9504
RD
119 // Bail out if there is already windows created. This means that the
120 // toolkit has already been initialized, as in embedding wxPython in
121 // a C++ wxWindows app.
122 if (wxTopLevelWindows.Number() > 0)
123 return;
7bf85405 124
7bf85405 125#ifdef __WXMSW__
21f4bf45 126 wxApp::Initialize((WXHINSTANCE)wxhInstance);
7bf85405
RD
127#endif
128#ifdef __WXGTK__
fb5e0af0 129 wxClassInfo::InitializeClasses();
21f4bf45 130
fb5e0af0
RD
131 PyObject* sysargv = PySys_GetObject("argv");
132 int argc = PyList_Size(sysargv);
133 char** argv = new char*[argc+1];
134 int x;
135 for(x=0; x<argc; x++)
136 argv[x] = PyString_AsString(PyList_GetItem(sysargv, x));
137 argv[argc] = NULL;
138
0d6f9504
RD
139 gtk_init( &argc, &argv );
140 delete [] argv;
7bf85405
RD
141
142#ifdef USE_GDK_IMLIB
7bf85405 143 gdk_imlib_init();
7bf85405 144 gtk_widget_push_visual(gdk_imlib_get_visual());
7bf85405 145 gtk_widget_push_colormap(gdk_imlib_get_colormap());
7bf85405
RD
146#endif
147
148 wxApp::CommonInit();
7bf85405
RD
149#endif
150
0d6f9504
RD
151}
152
153
154
155static char* __nullArgv[1] = { 0 };
156
157// Start the user application, user App's OnInit method is a parameter here
158PyObject* __wxStart(PyObject* /* self */, PyObject* args)
159{
160 PyObject* onInitFunc = NULL;
161 PyObject* arglist;
162 PyObject* result;
163 long bResult;
164
165
166 if (!PyArg_ParseTuple(args, "O", &onInitFunc))
167 return NULL;
168
169 if (wxTopLevelWindows.Number() > 0) {
170 PyErr_SetString(PyExc_TypeError, "Only 1 wxApp per process!");
171 return NULL;
172 }
173
174
175 // This is the next part of the wxEntry functionality...
176 wxPythonApp->argc = 0;
177 wxPythonApp->argv = __nullArgv;
178 wxPythonApp->OnInitGui();
179
7bf85405
RD
180
181 // Call the Python App's OnInit function
182 arglist = PyTuple_New(0);
183 result = PyEval_CallObject(onInitFunc, arglist);
184 if (!result) {
185 PyErr_Print();
186 exit(1);
187 }
188
189 if (! PyInt_Check(result)) {
190 PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value");
191 return NULL;
192 }
193 bResult = PyInt_AS_LONG(result);
194 if (! bResult) {
195 wxPythonApp->DeletePendingObjects();
196 wxPythonApp->OnExit();
197#ifdef __WXMSW__
fb5e0af0 198 wxApp::CleanUp();
7bf85405
RD
199#endif
200#ifdef __WXGTK__
fb5e0af0 201 wxApp::CommonCleanUp();
7bf85405
RD
202#endif
203 PyErr_SetString(PyExc_SystemExit, "OnInit returned false, exiting...");
204 return NULL;
205 }
206
13dfc243 207#ifdef __WXGTK__
fb5e0af0 208 wxTheApp->m_initialized = (wxTopLevelWindows.Number() > 0);
13dfc243 209#endif
fb5e0af0 210
7bf85405
RD
211 Py_INCREF(Py_None);
212 return Py_None;
213}
214
215
7bf85405
RD
216
217
218
219PyObject* wxPython_dict;
220PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args)
221{
222
223 if (!PyArg_ParseTuple(args, "O", &wxPython_dict))
224 return NULL;
225
226 if (!PyDict_Check(wxPython_dict)) {
227 PyErr_SetString(PyExc_TypeError, "_wxSetDictionary must have dictionary object!");
228 return NULL;
229 }
230#ifdef __WXMOTIF__
21f4bf45
RD
231#define wxPlatform "__WXMOTIF__"
232#endif
233#ifdef __WXQT__
234#define wxPlatform "__WXQT__"
7bf85405
RD
235#endif
236#ifdef __WXGTK__
21f4bf45 237#define wxPlatform "__WXGTK__"
7bf85405
RD
238#endif
239#if defined(__WIN32__) || defined(__WXMSW__)
fb5e0af0 240#define wxPlatform "__WXMSW__"
7bf85405
RD
241#endif
242#ifdef __WXMAC__
21f4bf45 243#define wxPlatform "__WXMAC__"
7bf85405
RD
244#endif
245
246 PyDict_SetItemString(wxPython_dict, "wxPlatform", PyString_FromString(wxPlatform));
247
248 Py_INCREF(Py_None);
249 return Py_None;
250}
251
252
253//---------------------------------------------------------------------------
254
255
256static
257PyObject* wxPyConstructObject(void* ptr, char* className)
258{
259 char buff[64]; // should be big enough...
260 char swigptr[64];
261
262 sprintf(buff, "_%s_p", className);
263 SWIG_MakePtr(swigptr, ptr, buff);
264
265 sprintf(buff, "%sPtr", className);
266 PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
267 if (! classobj) {
268 Py_INCREF(Py_None);
269 return Py_None;
270 }
271
272 PyObject* arg = Py_BuildValue("(s)", swigptr);
273 PyObject* obj = PyInstance_New(classobj, arg, NULL);
274 Py_DECREF(arg);
275
276 return obj;
277}
278
279
280// This function is used for all events destined for Python event handlers.
281void wxPyCallback::EventThunker(wxEvent& event) {
282 wxPyCallback* cb = (wxPyCallback*)event.m_callbackUserData;
283 PyObject* func = cb->m_func;
284 PyObject* result;
285 PyObject* arg;
286 PyObject* tuple;
287
288 arg = wxPyConstructObject((void*)&event, event.GetClassInfo()->GetClassName());
289
290 tuple = PyTuple_New(1);
291 PyTuple_SET_ITEM(tuple, 0, arg);
292 result = PyEval_CallObject(func, tuple);
293 Py_DECREF(arg);
294 Py_DECREF(tuple);
295 if (result) {
296 Py_DECREF(result);
297 PyErr_Clear();
298 } else {
299 PyErr_Print();
300 }
301}
302
303
304//---------------------------------------------------------------------------
305
306wxPyMenu::wxPyMenu(const wxString& title, PyObject* _func)
307 : wxMenu(title, (wxFunction)(func ? MenuCallback : NULL)), func(0) {
308
309 if (_func) {
310 func = _func;
311 Py_INCREF(func);
312 }
313}
314
315wxPyMenu::~wxPyMenu() {
316 if (func)
317 Py_DECREF(func);
318}
319
320
321void 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
326 PyErr_Print();
327 return;
328 }
329 // Now call the callback...
330 PyObject* func = ((wxPyMenu*)&menu)->func;
331 PyObject* args = Py_BuildValue("(OO)", menuobj, evtobj);
332 PyObject* res = PyEval_CallObject(func, args);
333 Py_DECREF(args);
334 Py_DECREF(res);
335 Py_DECREF(evtobj);
336 Py_DECREF(menuobj);
337}
714e6a9e 338
7bf85405
RD
339
340//---------------------------------------------------------------------------
341
342wxPyTimer::wxPyTimer(PyObject* callback) {
343 func = callback;
344 Py_INCREF(func);
345}
346
347wxPyTimer::~wxPyTimer() {
348 Py_DECREF(func);
349}
350
351void wxPyTimer::Notify() {
352 PyObject* result;
353 PyObject* args = Py_BuildValue("()");
354
355 result = PyEval_CallObject(func, args);
356 Py_DECREF(args);
357 if (result) {
358 Py_DECREF(result);
359 PyErr_Clear();
360 } else {
361 PyErr_Print();
362 }
363}
364
365
366
7bf85405
RD
367
368//----------------------------------------------------------------------
369//----------------------------------------------------------------------
370// Some helper functions for typemaps in my_typemaps.i, so they won't be
371// imcluded in every file...
372
373
374int* int_LIST_helper(PyObject* source) {
375 if (!PyList_Check(source)) {
376 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
377 return NULL;
378 }
379 int count = PyList_Size(source);
380 int* temp = new int[count];
381 if (! temp) {
382 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
383 return NULL;
384 }
385 for (int x=0; x<count; x++) {
386 PyObject* o = PyList_GetItem(source, x);
387 if (! PyInt_Check(o)) {
388 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
389 return NULL;
390 }
391 temp[x] = PyInt_AsLong(o);
392 }
393 return temp;
394}
395
396
397long* long_LIST_helper(PyObject* source) {
398 if (!PyList_Check(source)) {
399 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
400 return NULL;
401 }
402 int count = PyList_Size(source);
403 long* temp = new long[count];
404 if (! temp) {
405 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
406 return NULL;
407 }
408 for (int x=0; x<count; x++) {
409 PyObject* o = PyList_GetItem(source, x);
410 if (! PyInt_Check(o)) {
411 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
412 return NULL;
413 }
414 temp[x] = PyInt_AsLong(o);
415 }
416 return temp;
417}
418
419
420char** string_LIST_helper(PyObject* source) {
421 if (!PyList_Check(source)) {
422 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
423 return NULL;
424 }
425 int count = PyList_Size(source);
426 char** temp = new char*[count];
427 if (! temp) {
428 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
429 return NULL;
430 }
431 for (int x=0; x<count; x++) {
432 PyObject* o = PyList_GetItem(source, x);
433 if (! PyString_Check(o)) {
434 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
435 return NULL;
436 }
437 temp[x] = PyString_AsString(o);
438 }
439 return temp;
440}
441
442
443
444wxPoint* wxPoint_LIST_helper(PyObject* source) {
445 if (!PyList_Check(source)) {
446 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
447 return NULL;
448 }
449 int count = PyList_Size(source);
450 wxPoint* temp = new wxPoint[count];
451 if (! temp) {
452 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
453 return NULL;
454 }
455 for (int x=0; x<count; x++) {
456 PyObject* o = PyList_GetItem(source, x);
457 if (PyString_Check(o)) {
458 char* st = PyString_AsString(o);
459 wxPoint* pt;
460 if (SWIG_GetPtr(st,(void **) &pt,"_wxPoint_p")) {
461 PyErr_SetString(PyExc_TypeError,"Expected _wxPoint_p.");
462 return NULL;
463 }
464 temp[x] = *pt;
465 }
466 else if (PyTuple_Check(o)) {
467 PyObject* o1 = PyTuple_GetItem(o, 0);
468 PyObject* o2 = PyTuple_GetItem(o, 1);
469
470 temp[x].x = PyInt_AsLong(o1);
471 temp[x].y = PyInt_AsLong(o2);
472 }
473 else {
474 PyErr_SetString(PyExc_TypeError, "Expected a list of 2-tuples or wxPoints.");
475 return NULL;
476 }
477 }
478 return temp;
479}
480
481
482wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
483 if (!PyList_Check(source)) {
484 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
485 return NULL;
486 }
487 int count = PyList_Size(source);
488 wxBitmap** temp = new wxBitmap*[count];
489 if (! temp) {
490 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
491 return NULL;
492 }
493 for (int x=0; x<count; x++) {
494 PyObject* o = PyList_GetItem(source, x);
495 if (PyString_Check(o)) {
496 char* st = PyString_AsString(o);
497 wxBitmap* pt;
498 if (SWIG_GetPtr(st,(void **) &pt,"_wxBitmap_p")) {
499 PyErr_SetString(PyExc_TypeError,"Expected _wxBitmap_p.");
500 return NULL;
501 }
502 temp[x] = pt;
503 }
504 else {
505 PyErr_SetString(PyExc_TypeError, "Expected a list of wxBitmaps.");
506 return NULL;
507 }
508 }
509 return temp;
510}
511
512
513
514wxString* wxString_LIST_helper(PyObject* source) {
515 if (!PyList_Check(source)) {
516 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
517 return NULL;
518 }
519 int count = PyList_Size(source);
520 wxString* temp = new wxString[count];
521 if (! temp) {
522 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
523 return NULL;
524 }
525 for (int x=0; x<count; x++) {
526 PyObject* o = PyList_GetItem(source, x);
527 if (! PyString_Check(o)) {
528 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
529 return NULL;
530 }
531 temp[x] = PyString_AsString(o);
532 }
533 return temp;
534}
535
536
853b255a 537#ifdef __WXMSW__
7bf85405
RD
538wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) {
539 if (!PyList_Check(source)) {
540 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
541 return NULL;
542 }
543 int count = PyList_Size(source);
544 wxAcceleratorEntry* temp = new wxAcceleratorEntry[count];
545 if (! temp) {
546 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
547 return NULL;
548 }
549 for (int x=0; x<count; x++) {
550 PyObject* o = PyList_GetItem(source, x);
551 if (PyString_Check(o)) {
552 char* st = PyString_AsString(o);
553 wxAcceleratorEntry* ae;
554 if (SWIG_GetPtr(st,(void **) &ae,"_wxAcceleratorEntry_p")) {
555 PyErr_SetString(PyExc_TypeError,"Expected _wxAcceleratorEntry_p.");
556 return NULL;
557 }
558 temp[x] = *ae;
559 }
560 else if (PyTuple_Check(o)) {
561 PyObject* o1 = PyTuple_GetItem(o, 0);
562 PyObject* o2 = PyTuple_GetItem(o, 1);
563 PyObject* o3 = PyTuple_GetItem(o, 2);
564
565 temp[x].m_flags = PyInt_AsLong(o1);
566 temp[x].m_keyCode = PyInt_AsLong(o2);
567 temp[x].m_command = PyInt_AsLong(o3);
568 }
569 else {
570 PyErr_SetString(PyExc_TypeError, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
571 return NULL;
572 }
573 }
574 return temp;
575}
576
853b255a 577#endif
7bf85405
RD
578
579//----------------------------------------------------------------------
580// A WinMain for when wxWindows and Python are linked together in a single
581// application, instead of as a dynamic module
582
583
584//#if !defined(WIN_PYD) && defined(WIN32)
585
586//extern "C" int Py_Main(int argc, char** argv);
587
588//int APIENTRY WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR m_lpCmdLine,
589// int nCmdShow )
590//{
591
592// wxpCreateApp();
593
594// // Initialize wxWindows, but don't start the main loop
595// wxEntry(hInstance, hPrevInstance, m_lpCmdLine, nCmdShow, FALSE);
596
597// Py_Initialize();
598// PyObject *argvList = PyList_New(0);
599
600// char* stderrfilename = "wxpstderr.log";
601// int pyargc = 1;
602// char* script = NULL;
603// int argc = wxPythonApp->argc;
604// char** argv = wxPythonApp->argv;
605
606// for (int i = 1; i < argc; i++) {
607// if (strncmp(argv[i], "wxpstderr=", 10) == 0)
608// stderrfilename = argv[i]+10;
609// else {
610// PyList_Append(argvList, PyString_FromString(argv[i]));
611// if (!script)
612// script = argv[i];
613// pyargc++;
614// }
615// }
616
617// PySys_SetObject("argv", argvList);
618
619//#if 1
620// char buf[256];
621//// //PyRun_SimpleString("import sys; sys.stdout=open('wxpstdout.log','w')");
622// sprintf(buf, "import sys; sys.stdout=sys.stderr=open('%s','w')", stderrfilename);
623// PyRun_SimpleString(buf);
624//#endif
625
626// initwxPythonc();
627
628// if (script) {
629// FILE *fp = fopen(script, "r");
630// if (fp) {
631// PyRun_SimpleFile(fp, script);// This returns after wxpApp constructor
632// fclose(fp);
633// }
634// else {
635// char msg[256];
636// sprintf(msg, "Cannot open %s", script);
637// wxMessageBox(msg);
638// }
639// }
640// else
641// PyRun_SimpleString("import wxpide");
642
643// return 0;
644//}
645
646
647//#endif
648
649//----------------------------------------------------------------------
650
651/////////////////////////////////////////////////////////////////////////////
652//
653// $Log$
0d6f9504
RD
654// Revision 1.8 1998/08/27 21:59:08 RD
655// Some chicken-and-egg problems solved for wxPython on wxGTK
656//
21f4bf45
RD
657// Revision 1.7 1998/08/27 00:00:26 RD
658// - more tweaks
659// - have discovered some problems but not yet discovered solutions...
660//
13dfc243 661// Revision 1.6 1998/08/18 21:54:12 RD
21f4bf45 662//
13dfc243
RD
663// ifdef out some wxGTK specific code
664//
fb5e0af0
RD
665// Revision 1.5 1998/08/18 19:48:17 RD
666// more wxGTK compatibility things.
667//
668// It builds now but there are serious runtime problems...
669//
714e6a9e
RD
670// Revision 1.4 1998/08/16 04:31:06 RD
671// More wxGTK work.
672//
03e9bead
RD
673// Revision 1.3 1998/08/15 07:36:36 RD
674// - Moved the header in the .i files out of the code that gets put into
675// the .cpp files. It caused CVS conflicts because of the RCS ID being
676// different each time.
677//
678// - A few minor fixes.
679//
853b255a
RD
680// Revision 1.2 1998/08/14 23:36:36 RD
681// Beginings of wxGTK compatibility
682//
7bf85405
RD
683// Revision 1.1 1998/08/09 08:25:51 RD
684// Initial version
685//
686//