]> git.saurik.com Git - wxWidgets.git/blob - utils/wxPython/src/helpers.cpp
Added wxSashWindow, wxSashEvent, wxLayoutAlgorithm, etc.
[wxWidgets.git] / utils / wxPython / src / helpers.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: helpers.cpp
3 // Purpose: Helper functions/classes for the wxPython extension module
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
13 #ifdef __WXMSW__
14 #include <windows.h>
15 #undef FindWindow
16 #undef GetCharWidth
17 #undef LoadAccelerators
18 #endif
19
20 #ifdef __WXGTK__
21 #include "gtk/gtk.h"
22 #endif
23
24 #undef DEBUG
25 #include <Python.h>
26 #include "helpers.h"
27
28 //---------------------------------------------------------------------------
29
30 //wxHashTable* wxPyWindows = NULL;
31
32
33 wxPoint wxPyDefaultPosition; //wxDefaultPosition);
34 wxSize wxPyDefaultSize; //wxDefaultSize);
35 wxString wxPyEmptyStr("");
36
37
38
39 #ifdef __WXMSW__ // If building for win32...
40 extern HINSTANCE wxhInstance;
41
42 //----------------------------------------------------------------------
43 // This gets run when the DLL is loaded. We just need to save a handle.
44 //----------------------------------------------------------------------
45
46 BOOL WINAPI DllMain(
47 HINSTANCE hinstDLL, // handle to DLL module
48 DWORD fdwReason, // reason for calling function
49 LPVOID lpvReserved // reserved
50 )
51 {
52 wxhInstance = hinstDLL;
53 return 1;
54 }
55 #endif
56
57 //----------------------------------------------------------------------
58 // Class for implementing the wxp main application shell.
59 //----------------------------------------------------------------------
60
61 wxPyApp *wxPythonApp = NULL; // Global instance of application object
62
63
64 // This one isn't acutally called... See __wxStart()
65 bool wxPyApp::OnInit(void) {
66 return false;
67 }
68
69 int wxPyApp::MainLoop(void) {
70 int retval = wxApp::MainLoop();
71 AfterMainLoop();
72 return retval;
73 }
74
75 void wxPyApp::AfterMainLoop(void) {
76 // more stuff from wxEntry...
77
78 if (wxPythonApp->GetTopWindow()) {
79 // Forcibly delete the window.
80 if (wxPythonApp->GetTopWindow()->IsKindOf(CLASSINFO(wxFrame)) ||
81 wxPythonApp->GetTopWindow()->IsKindOf(CLASSINFO(wxDialog))) {
82
83 wxPythonApp->GetTopWindow()->Close(TRUE);
84 wxPythonApp->DeletePendingObjects();
85 }
86 else {
87 delete wxPythonApp->GetTopWindow();
88 wxPythonApp->SetTopWindow(NULL);
89 }
90 }
91 #ifdef __WXGTK__
92 wxPythonApp->DeletePendingObjects();
93 #endif
94
95 wxPythonApp->OnExit();
96 wxApp::CleanUp();
97 // delete wxPythonApp;
98 }
99
100
101 //---------------------------------------------------------------------
102 // a few native methods to add to the module
103 //----------------------------------------------------------------------
104
105
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.)
109 void __wxPreStart()
110 {
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)
115 return;
116
117 #ifdef __WXMSW__
118 wxApp::Initialize();
119 #endif
120
121 #ifdef __WXGTK__
122 PyObject* sysargv = PySys_GetObject("argv");
123 int argc = PyList_Size(sysargv);
124 char** argv = new char*[argc+1];
125 int x;
126 for(x=0; x<argc; x++)
127 argv[x] = PyString_AsString(PyList_GetItem(sysargv, x));
128 argv[argc] = NULL;
129
130 gtk_set_locale();
131 gtk_init( &argc, &argv );
132 delete [] argv;
133
134 wxApp::Initialize(); // may return FALSE. Should we check?
135 #endif
136
137 }
138
139
140
141 static char* __nullArgv[1] = { 0 };
142
143 // Start the user application, user App's OnInit method is a parameter here
144 PyObject* __wxStart(PyObject* /* self */, PyObject* args)
145 {
146 PyObject* onInitFunc = NULL;
147 PyObject* arglist;
148 PyObject* result;
149 long bResult;
150
151
152 if (!PyArg_ParseTuple(args, "O", &onInitFunc))
153 return NULL;
154
155 if (wxTopLevelWindows.Number() > 0) {
156 PyErr_SetString(PyExc_TypeError, "Only 1 wxApp per process!");
157 return NULL;
158 }
159
160
161 // This is the next part of the wxEntry functionality...
162 wxPythonApp->argc = 0;
163 wxPythonApp->argv = __nullArgv;
164 wxPythonApp->OnInitGui();
165
166
167 // Call the Python App's OnInit function
168 arglist = PyTuple_New(0);
169 result = PyEval_CallObject(onInitFunc, arglist);
170 if (!result) {
171 PyErr_Print();
172 exit(1);
173 }
174
175 if (! PyInt_Check(result)) {
176 PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value");
177 return NULL;
178 }
179 bResult = PyInt_AS_LONG(result);
180 if (! bResult) {
181 wxPythonApp->DeletePendingObjects();
182 wxPythonApp->OnExit();
183 wxApp::CleanUp();
184 PyErr_SetString(PyExc_SystemExit, "OnInit returned false, exiting...");
185 return NULL;
186 }
187
188 #ifdef __WXGTK__
189 wxTheApp->m_initialized = (wxTopLevelWindows.Number() > 0);
190 #endif
191
192 Py_INCREF(Py_None);
193 return Py_None;
194 }
195
196
197
198
199
200 PyObject* wxPython_dict;
201 PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args)
202 {
203
204 if (!PyArg_ParseTuple(args, "O", &wxPython_dict))
205 return NULL;
206
207 if (!PyDict_Check(wxPython_dict)) {
208 PyErr_SetString(PyExc_TypeError, "_wxSetDictionary must have dictionary object!");
209 return NULL;
210 }
211 #ifdef __WXMOTIF__
212 #define wxPlatform "__WXMOTIF__"
213 #endif
214 #ifdef __WXQT__
215 #define wxPlatform "__WXQT__"
216 #endif
217 #ifdef __WXGTK__
218 #define wxPlatform "__WXGTK__"
219 #endif
220 #if defined(__WIN32__) || defined(__WXMSW__)
221 #define wxPlatform "__WXMSW__"
222 #endif
223 #ifdef __WXMAC__
224 #define wxPlatform "__WXMAC__"
225 #endif
226
227 PyDict_SetItemString(wxPython_dict, "wxPlatform", PyString_FromString(wxPlatform));
228
229 Py_INCREF(Py_None);
230 return Py_None;
231 }
232
233
234 //---------------------------------------------------------------------------
235
236
237 static
238 PyObject* wxPyConstructObject(void* ptr, char* className)
239 {
240 char buff[64]; // should always be big enough...
241 char swigptr[64];
242
243 sprintf(buff, "_%s_p", className);
244 SWIG_MakePtr(swigptr, ptr, buff);
245
246 sprintf(buff, "%sPtr", className);
247 PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
248 if (! classobj) {
249 Py_INCREF(Py_None);
250 return Py_None;
251 }
252
253 PyObject* arg = Py_BuildValue("(s)", swigptr);
254 PyObject* obj = PyInstance_New(classobj, arg, NULL);
255 Py_DECREF(arg);
256
257 return obj;
258 }
259
260
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;
265 PyObject* result;
266 PyObject* arg;
267 PyObject* tuple;
268
269 arg = wxPyConstructObject((void*)&event, event.GetClassInfo()->GetClassName());
270
271 tuple = PyTuple_New(1);
272 PyTuple_SET_ITEM(tuple, 0, arg);
273 result = PyEval_CallObject(func, tuple);
274 Py_DECREF(tuple);
275 if (result) {
276 Py_DECREF(result);
277 PyErr_Clear();
278 } else {
279 PyErr_Print();
280 }
281 }
282
283
284 //---------------------------------------------------------------------------
285
286 wxPyMenu::wxPyMenu(const wxString& title, PyObject* _func)
287 : wxMenu(title, (wxFunction)(func ? MenuCallback : NULL)), func(0) {
288
289 if (_func) {
290 func = _func;
291 Py_INCREF(func);
292 }
293 }
294
295 wxPyMenu::~wxPyMenu() {
296 if (func)
297 Py_DECREF(func);
298 }
299
300
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
306 PyErr_Print();
307 return;
308 }
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);
315 Py_DECREF(args);
316 Py_XDECREF(res); /* In case res is a NULL pointer */
317 }
318
319
320 //---------------------------------------------------------------------------
321
322 wxPyTimer::wxPyTimer(PyObject* callback) {
323 func = callback;
324 Py_INCREF(func);
325 }
326
327 wxPyTimer::~wxPyTimer() {
328 Py_DECREF(func);
329 }
330
331 void wxPyTimer::Notify() {
332 PyObject* result;
333 PyObject* args = Py_BuildValue("()");
334
335 result = PyEval_CallObject(func, args);
336 Py_DECREF(args);
337 if (result) {
338 Py_DECREF(result);
339 PyErr_Clear();
340 } else {
341 PyErr_Print();
342 }
343 }
344
345
346
347 //----------------------------------------------------------------------
348 //----------------------------------------------------------------------
349 // Some helper functions for typemaps in my_typemaps.i, so they won't be
350 // imcluded in every file...
351
352
353 byte* byte_LIST_helper(PyObject* source) {
354 if (!PyList_Check(source)) {
355 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
356 return NULL;
357 }
358 int count = PyList_Size(source);
359 byte* temp = new byte[count];
360 if (! temp) {
361 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
362 return NULL;
363 }
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.");
368 return NULL;
369 }
370 temp[x] = (byte)PyInt_AsLong(o);
371 }
372 return temp;
373 }
374
375
376 int* int_LIST_helper(PyObject* source) {
377 if (!PyList_Check(source)) {
378 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
379 return NULL;
380 }
381 int count = PyList_Size(source);
382 int* temp = new int[count];
383 if (! temp) {
384 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
385 return NULL;
386 }
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.");
391 return NULL;
392 }
393 temp[x] = PyInt_AsLong(o);
394 }
395 return temp;
396 }
397
398
399 long* long_LIST_helper(PyObject* source) {
400 if (!PyList_Check(source)) {
401 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
402 return NULL;
403 }
404 int count = PyList_Size(source);
405 long* temp = new long[count];
406 if (! temp) {
407 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
408 return NULL;
409 }
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.");
414 return NULL;
415 }
416 temp[x] = PyInt_AsLong(o);
417 }
418 return temp;
419 }
420
421
422 char** string_LIST_helper(PyObject* source) {
423 if (!PyList_Check(source)) {
424 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
425 return NULL;
426 }
427 int count = PyList_Size(source);
428 char** temp = new char*[count];
429 if (! temp) {
430 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
431 return NULL;
432 }
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.");
437 return NULL;
438 }
439 temp[x] = PyString_AsString(o);
440 }
441 return temp;
442 }
443
444
445
446 wxPoint* wxPoint_LIST_helper(PyObject* source) {
447 if (!PyList_Check(source)) {
448 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
449 return NULL;
450 }
451 int count = PyList_Size(source);
452 wxPoint* temp = new wxPoint[count];
453 if (! temp) {
454 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
455 return NULL;
456 }
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);
461 wxPoint* pt;
462 if (SWIG_GetPtr(st,(void **) &pt,"_wxPoint_p")) {
463 PyErr_SetString(PyExc_TypeError,"Expected _wxPoint_p.");
464 return NULL;
465 }
466 temp[x] = *pt;
467 }
468 else if (PyTuple_Check(o)) {
469 PyObject* o1 = PyTuple_GetItem(o, 0);
470 PyObject* o2 = PyTuple_GetItem(o, 1);
471
472 temp[x].x = PyInt_AsLong(o1);
473 temp[x].y = PyInt_AsLong(o2);
474 }
475 else {
476 PyErr_SetString(PyExc_TypeError, "Expected a list of 2-tuples or wxPoints.");
477 return NULL;
478 }
479 }
480 return temp;
481 }
482
483
484 wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
485 if (!PyList_Check(source)) {
486 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
487 return NULL;
488 }
489 int count = PyList_Size(source);
490 wxBitmap** temp = new wxBitmap*[count];
491 if (! temp) {
492 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
493 return NULL;
494 }
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);
499 wxBitmap* pt;
500 if (SWIG_GetPtr(st,(void **) &pt,"_wxBitmap_p")) {
501 PyErr_SetString(PyExc_TypeError,"Expected _wxBitmap_p.");
502 return NULL;
503 }
504 temp[x] = pt;
505 }
506 else {
507 PyErr_SetString(PyExc_TypeError, "Expected a list of wxBitmaps.");
508 return NULL;
509 }
510 }
511 return temp;
512 }
513
514
515
516 wxString* wxString_LIST_helper(PyObject* source) {
517 if (!PyList_Check(source)) {
518 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
519 return NULL;
520 }
521 int count = PyList_Size(source);
522 wxString* temp = new wxString[count];
523 if (! temp) {
524 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
525 return NULL;
526 }
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.");
531 return NULL;
532 }
533 temp[x] = PyString_AsString(o);
534 }
535 return temp;
536 }
537
538
539 wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) {
540 if (!PyList_Check(source)) {
541 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
542 return NULL;
543 }
544 int count = PyList_Size(source);
545 wxAcceleratorEntry* temp = new wxAcceleratorEntry[count];
546 if (! temp) {
547 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
548 return NULL;
549 }
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.");
557 return NULL;
558 }
559 temp[x] = *ae;
560 }
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);
565
566 temp[x].m_flags = PyInt_AsLong(o1);
567 temp[x].m_keyCode = PyInt_AsLong(o2);
568 temp[x].m_command = PyInt_AsLong(o3);
569 }
570 else {
571 PyErr_SetString(PyExc_TypeError, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
572 return NULL;
573 }
574 }
575 return temp;
576 }
577
578 //----------------------------------------------------------------------
579
580
581
582 /////////////////////////////////////////////////////////////////////////////
583 //
584 // $Log$
585 // Revision 1.17 1999/01/30 07:30:12 RD
586 // Added wxSashWindow, wxSashEvent, wxLayoutAlgorithm, etc.
587 //
588 // Various cleanup, tweaks, minor additions, etc. to maintain
589 // compatibility with the current wxWindows.
590 //
591 // Revision 1.16 1998/12/17 14:07:39 RR
592 //
593 // Removed minor differences between wxMSW and wxGTK
594 //
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."
600 //
601 // Added wxTaskbarIcon for wxMSW.
602 //
603 // Made the events work for wxGrid.
604 //
605 // Added wxConfig.
606 //
607 // Added wxMiniFrame for wxGTK, (untested.)
608 //
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.
611 //
612 // Other assorted fixes and additions.
613 //
614 // Revision 1.14 1998/11/25 08:45:25 RD
615 //
616 // Added wxPalette, wxRegion, wxRegionIterator, wxTaskbarIcon
617 // Added events for wxGrid
618 // Other various fixes and additions
619 //
620 // Revision 1.13 1998/11/15 23:03:45 RD
621 // Removing some ifdef's for wxGTK
622 //
623 // Revision 1.12 1998/11/03 09:21:08 RD
624 // fixed a typo
625 //
626 // Revision 1.11 1998/10/20 06:43:58 RD
627 // New wxTreeCtrl wrappers (untested)
628 // some changes in helpers
629 // etc.
630 //
631 // Revision 1.10 1998/10/02 06:40:39 RD
632 //
633 // Version 0.4 of wxPython for MSW.
634 //
635 // Revision 1.9 1998/09/25 13:28:52 VZ
636 //
637 // USE_xxx constants renamed to wxUSE_xxx. This is an incompatible change, you
638 // must recompile everything after upgrading!
639 //
640 // Revision 1.8 1998/08/27 21:59:08 RD
641 // Some chicken-and-egg problems solved for wxPython on wxGTK
642 //
643 // Revision 1.7 1998/08/27 00:00:26 RD
644 // - more tweaks
645 // - have discovered some problems but not yet discovered solutions...
646 //
647 // Revision 1.6 1998/08/18 21:54:12 RD
648 //
649 // ifdef out some wxGTK specific code
650 //
651 // Revision 1.5 1998/08/18 19:48:17 RD
652 // more wxGTK compatibility things.
653 //
654 // It builds now but there are serious runtime problems...
655 //
656 // Revision 1.4 1998/08/16 04:31:06 RD
657 // More wxGTK work.
658 //
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.
663 //
664 // - A few minor fixes.
665 //
666 // Revision 1.2 1998/08/14 23:36:36 RD
667 // Beginings of wxGTK compatibility
668 //
669 // Revision 1.1 1998/08/09 08:25:51 RD
670 // Initial version
671 //
672 //