- Added a python wrapper module for WINGs
[wmaker-crm.git] / WINGs / python / WINGs.i
blob255f68afe5867ea0aa61d3d7b57e48e3bb32202f
1 %module wings
2 %{
3 #include "WINGs/WINGsP.h"
4 %}
6 %include typemaps.i
8 // This tells SWIG to treat char ** as a special case
9 %typemap(python, in) char ** {
10 /* Check if is a list */
11 if (PyList_Check($input)) {
12 int size = PyList_Size($input);
13 int i = 0;
14 $1 = (char **) wmalloc((size+1)*sizeof(char *));
15 for (i = 0; i < size; i++) {
16 PyObject *o = PyList_GetItem($input, i);
17 if (PyString_Check(o))
18 $1[i] = PyString_AsString(PyList_GetItem($input, i));
19 else {
20 PyErr_SetString(PyExc_TypeError, "list must contain strings");
21 wfree($1);
22 return NULL;
25 $1[i] = 0;
26 } else {
27 PyErr_SetString(PyExc_TypeError, "not a list");
28 return NULL;
31 // This cleans up the char ** array we malloc\x19d before the function call
32 %typemap(python, freearg) char ** {
33 wfree($1);
35 // This allows a C function to return a char ** as a Python list
36 %typemap(python, out) char ** {
37 int len,i;
38 len = 0;
39 while ($1[len]) len++;
40 $result = PyList_New(len);
41 for (i = 0; i < len; i++) {
42 PyList_SetItem($result, i, PyString_FromString($1[i]));
46 // Now for some callbacks
47 %typemap(python, in) PyObject *pyacArgs {
48 if (PyTuple_Check($input)) {
49 if (PyTuple_Size($input) != 3) {
50 PyErr_SetString(PyExc_ValueError,
51 "wrong number of parameters in tuple. should be 3.");
52 return NULL;
53 } else {
54 PyObject *func = PyTuple_GetItem($input, 1);
55 if (func!=Py_None && !PyCallable_Check(func)) {
56 PyErr_SetString(PyExc_TypeError,
57 "'action' needs to be a callable object!");
58 return NULL;
61 } else {
62 PyErr_SetString(PyExc_TypeError, "2nd argument not a tuple!");
63 return NULL;
65 $1 = $input;
68 %typemap(python, in) PyObject *pycArgs {
69 if (PyTuple_Check($input)) {
70 if (PyTuple_Size($input) != 2) {
71 PyErr_SetString(PyExc_ValueError,
72 "wrong number of parameters in tuple. should be 2.");
73 return NULL;
74 } else {
75 PyObject *func = PyTuple_GetItem($input, 0);
76 if (func!=Py_None && !PyCallable_Check(func)) {
77 PyErr_SetString(PyExc_TypeError,
78 "'action' needs to be a callable object!");
79 return NULL;
82 } else {
83 PyErr_SetString(PyExc_TypeError, "2nd argument not a tuple!");
84 return NULL;
86 $1 = $input;
89 // Type mapping for grabbing a FILE * from Python
90 %typemap(python, in) FILE * {
91 if (!PyFile_Check($input)) {
92 PyErr_SetString(PyExc_TypeError, "Need a file!");
93 return NULL;
95 $1 = PyFile_AsFile($input);
98 /* These are for freeing the return of functions that need to be freed
99 * before returning control to python. */
100 %typemap(python, ret) char* WMGetTextFieldText { wfree($1); };
103 %include exception.i
105 %exception pyWMScreenMainLoop {
106 $function
107 if (PyErr_Occurred())
108 return NULL;
111 %exception pyWMRunModalLoop {
112 $function
113 if (PyErr_Occurred())
114 return NULL;
118 static int mainLoopDone = 0;
122 %inline %{
123 WMScreen *pyWMOpenScreen(const char *display, int simpleapp)
125 Display *dpy = XOpenDisplay(display);
127 if (!dpy) {
128 wwarning("WINGs: could not open display %s", XDisplayName(display));
129 return NULL;
132 if (simpleapp) {
133 return WMCreateSimpleApplicationScreen(dpy);
134 } else {
135 return WMCreateScreen(dpy, DefaultScreen(dpy));
139 void pyWMScreenMainLoop(WMScreen *scr)
141 XEvent event;
143 while (!PyErr_Occurred() && !mainLoopDone) {
144 WMNextEvent(((W_Screen*)scr)->display, &event);
145 WMHandleEvent(&event);
149 void pyWMBreakScreenMainLoop(WMScreen *scr)
151 mainLoopDone = 1;
154 void pyWMRunModalLoop(WMScreen *scr, WMView *view)
156 int oldModalLoop = scr->modalLoop;
157 WMView *oldModalView = scr->modalView;
159 scr->modalView = view;
161 scr->modalLoop = 1;
162 while (!PyErr_Occurred() && scr->modalLoop) {
163 XEvent event;
165 WMNextEvent(scr->display, &event);
166 WMHandleEvent(&event);
169 scr->modalView = oldModalView;
170 scr->modalLoop = oldModalLoop;
175 //%rename WMScreenMainLoop _WMScreenMainLoop;
176 //%rename WMRunModalLoop _WMRunModalLoop;
180 /* These functions match the prototypes of the normal C callback
181 * functions. However, we use the clientdata pointer for holding a
182 * reference to a Python tuple containing (object, funct, clientData).
184 static void PythonWMActionCallback(WMWidget *widget, void *cdata)
186 PyObject *pyobj, *func, *pydata, *arglist, *tuple, *result;
188 tuple = (PyObject*) cdata;
189 pyobj = PyTuple_GetItem(tuple, 0);
190 func = PyTuple_GetItem(tuple, 1);
191 if (func && func!=Py_None) {
192 pydata = PyTuple_GetItem(tuple, 2);
193 arglist = Py_BuildValue("(OO)", pyobj, pydata);
194 result = PyEval_CallObject(func, arglist);
195 Py_DECREF(arglist);
196 Py_XDECREF(result);
200 static void PythonWMCallback(void *data)
202 PyObject *func, *pydata, *arglist, *tuple, *result;
204 tuple = (PyObject*) data;
205 func = PyTuple_GetItem(tuple, 0);
206 if (func && func!=Py_None) {
207 pydata = PyTuple_GetItem(tuple, 1);
208 arglist = Py_BuildValue("(O)", pydata);
209 result = PyEval_CallObject(func, arglist);
210 Py_DECREF(arglist);
211 Py_XDECREF(result);
215 static void
216 pyTextFieldDidBeginEditing(WMTextFieldDelegate *self, WMNotification *notif)
218 PyObject *pyobj, *delegate, *func, *pydata, *arglist, *tuple, *result;
219 int action;
221 tuple = (PyObject*) self->data;
222 pyobj = PyTuple_GetItem(tuple, 0);
223 delegate = PyTuple_GetItem(tuple, 1);
224 if (delegate != Py_None) {
225 // should we call PyObject_HasAttrString()?? rather not and let
226 // python raise an exception because the object doesn't has the
227 // attribute
228 func = PyObject_GetAttrString(delegate, "didBeginEditing");
229 if (func!=NULL && func!=Py_None) {
230 pydata = PyObject_GetAttrString(delegate, "data");
231 if (!pydata) {
232 Py_INCREF(Py_None);
233 pydata = Py_None;
235 action = (int)WMGetNotificationClientData(notif);
236 arglist = Py_BuildValue("(OOi)", pyobj, pydata, action);
237 result = PyEval_CallObject(func, arglist);
238 Py_DECREF(pydata);
239 Py_DECREF(arglist);
240 Py_XDECREF(result);
242 Py_XDECREF(func);
246 static void
247 pyTextFieldDidChange(WMTextFieldDelegate *self, WMNotification *notif)
249 PyObject *pyobj, *delegate, *func, *pydata, *arglist, *tuple, *result;
250 int action;
252 tuple = (PyObject*) self->data;
253 pyobj = PyTuple_GetItem(tuple, 0);
254 delegate = PyTuple_GetItem(tuple, 1);
255 if (delegate != Py_None) {
256 func = PyObject_GetAttrString(delegate, "didChange");
257 if (func!=NULL && func!=Py_None) {
258 pydata = PyObject_GetAttrString(delegate, "data");
259 if (!pydata) {
260 Py_INCREF(Py_None);
261 pydata = Py_None;
263 action = (int)WMGetNotificationClientData(notif);
264 arglist = Py_BuildValue("(OOi)", pyobj, pydata, action);
265 result = PyEval_CallObject(func, arglist);
266 Py_DECREF(pydata);
267 Py_DECREF(arglist);
268 Py_XDECREF(result);
270 Py_XDECREF(func);
274 static void
275 pyTextFieldDidEndEditing(WMTextFieldDelegate *self, WMNotification *notif)
277 PyObject *pyobj, *delegate, *func, *pydata, *arglist, *tuple, *result;
278 int action;
280 tuple = (PyObject*) self->data;
281 pyobj = PyTuple_GetItem(tuple, 0);
282 delegate = PyTuple_GetItem(tuple, 1);
283 if (delegate != Py_None) {
284 func = PyObject_GetAttrString(delegate, "didEndEditing");
285 if (func!=NULL && func!=Py_None) {
286 pydata = PyObject_GetAttrString(delegate, "data");
287 if (!pydata) {
288 Py_INCREF(Py_None);
289 pydata = Py_None;
291 action = (int)WMGetNotificationClientData(notif);
292 arglist = Py_BuildValue("(OOi)", pyobj, pydata, action);
293 result = PyEval_CallObject(func, arglist);
294 Py_DECREF(pydata);
295 Py_DECREF(arglist);
296 Py_XDECREF(result);
298 Py_XDECREF(func);
302 static Bool
303 pyTextFieldShouldBeginEditing(WMTextFieldDelegate *self, WMTextField *tPtr)
305 PyObject *pyobj, *delegate, *func, *pydata, *arglist, *tuple, *result;
306 Bool retval = False;
308 tuple = (PyObject*) self->data;
309 pyobj = PyTuple_GetItem(tuple, 0);
310 delegate = PyTuple_GetItem(tuple, 1);
311 if (delegate != Py_None) {
312 func = PyObject_GetAttrString(delegate, "shouldBeginEditing");
313 if (func!=NULL && func!=Py_None) {
314 pydata = PyObject_GetAttrString(delegate, "data");
315 if (!pydata) {
316 Py_INCREF(Py_None);
317 pydata = Py_None;
319 arglist = Py_BuildValue("(OO)", pyobj, pydata);
320 result = PyEval_CallObject(func, arglist);
321 if (result!=Py_None && PyInt_AsLong(result)!=0) {
322 retval = True;
324 Py_DECREF(pydata);
325 Py_DECREF(arglist);
326 Py_XDECREF(result);
328 Py_XDECREF(func);
331 return retval;
334 static Bool
335 pyTextFieldShouldEndEditing(WMTextFieldDelegate *self, WMTextField *tPtr)
337 PyObject *pyobj, *delegate, *func, *pydata, *arglist, *tuple, *result;
338 Bool retval = False;
340 tuple = (PyObject*) self->data;
341 pyobj = PyTuple_GetItem(tuple, 0);
342 delegate = PyTuple_GetItem(tuple, 1);
343 if (delegate != Py_None) {
344 func = PyObject_GetAttrString(delegate, "shouldEndEditing");
345 if (func!=NULL && func!=Py_None) {
346 pydata = PyObject_GetAttrString(delegate, "data");
347 if (!pydata) {
348 Py_INCREF(Py_None);
349 pydata = Py_None;
351 arglist = Py_BuildValue("(OO)", pyobj, pydata);
352 result = PyEval_CallObject(func, arglist);
353 if (result!=Py_None && PyInt_AsLong(result)!=0) {
354 retval = True;
356 Py_DECREF(pydata);
357 Py_DECREF(arglist);
358 Py_XDECREF(result);
360 Py_XDECREF(func);
363 return retval;
367 %inline %{
368 void pyWMSetWindowCloseAction(WMWindow *win, PyObject *pyacArgs) {
369 WMSetWindowCloseAction(win, PythonWMActionCallback, (void*)pyacArgs);
370 Py_INCREF(pyacArgs);
373 void pyWMSetButtonAction(WMButton *bPtr, PyObject *pyacArgs) {
374 WMSetButtonAction(bPtr, PythonWMActionCallback, (void*)pyacArgs);
375 Py_INCREF(pyacArgs);
378 void pyWMSetScrollerAction(WMScroller *sPtr, PyObject *pyacArgs) {
379 WMSetScrollerAction(sPtr, PythonWMActionCallback, (void*)pyacArgs);
380 Py_INCREF(pyacArgs);
383 void pyWMSetListAction(WMList *lPtr, PyObject *pyacArgs) {
384 WMSetListAction(lPtr, PythonWMActionCallback, (void*)pyacArgs);
385 Py_INCREF(pyacArgs);
388 void pyWMSetListDoubleAction(WMList *lPtr, PyObject *pyacArgs) {
389 WMSetListDoubleAction(lPtr, PythonWMActionCallback, (void*)pyacArgs);
390 Py_INCREF(pyacArgs);
393 void pyWMSetBrowserAction(WMBrowser *bPtr, PyObject *pyacArgs) {
394 WMSetBrowserAction(bPtr, PythonWMActionCallback, (void*)pyacArgs);
395 Py_INCREF(pyacArgs);
398 void pyWMSetBrowserDoubleAction(WMBrowser *bPtr, PyObject *pyacArgs) {
399 WMSetBrowserDoubleAction(bPtr, PythonWMActionCallback, (void*)pyacArgs);
400 Py_INCREF(pyacArgs);
403 void pyWMSetMenuItemAction(WMMenuItem *miPtr, PyObject *pyacArgs) {
404 WMSetMenuItemAction(miPtr, PythonWMActionCallback, (void*)pyacArgs);
405 Py_INCREF(pyacArgs);
408 void pyWMSetPopUpButtonAction(WMPopUpButton *pPtr, PyObject *pyacArgs) {
409 WMSetPopUpButtonAction(pPtr, PythonWMActionCallback, (void*)pyacArgs);
410 Py_INCREF(pyacArgs);
413 void pyWMSetSliderAction(WMSlider *sPtr, PyObject *pyacArgs) {
414 WMSetSliderAction(sPtr, PythonWMActionCallback, (void*)pyacArgs);
415 Py_INCREF(pyacArgs);
418 void pyWMSetRulerMoveAction(WMRuler *rPtr, PyObject *pyacArgs) {
419 WMSetRulerMoveAction(rPtr, PythonWMActionCallback, (void*)pyacArgs);
420 Py_INCREF(pyacArgs);
423 void pyWMSetRulerReleaseAction(WMRuler *rPtr, PyObject *pyacArgs) {
424 WMSetRulerReleaseAction(rPtr, PythonWMActionCallback, (void*)pyacArgs);
425 Py_INCREF(pyacArgs);
428 void pyWMSetColorPanelAction(WMColorPanel *panel, PyObject *pyacArgs) {
429 WMSetColorPanelAction(panel, (WMAction2*)PythonWMActionCallback, (void*)pyacArgs);
430 Py_INCREF(pyacArgs);
433 void* pyWMAddTimerHandler(int miliseconds, PyObject *pycArgs) {
434 Py_INCREF(pycArgs);
435 return (void*)WMAddTimerHandler(miliseconds, PythonWMCallback,
436 (void*)pycArgs);
439 void* pyWMAddPersistentTimerHandler(int miliseconds, PyObject *pycArgs) {
440 Py_INCREF(pycArgs);
441 return (void*)WMAddPersistentTimerHandler(miliseconds, PythonWMCallback,
442 (void*)pycArgs);
445 /* this doesn't work. we pass (func, data) as cdata at creation time, but
446 * only data at destruction, so it won't find it unless we change
447 * WMDeleteTimerWithClientData() to extract data from the tuple, and this
448 * requires access to the internals of WINGs
449 void pyWMDeleteTimerWithClientData(PyObject *pycData) {
450 WMDeleteTimerWithClientData((void*)pycData);
453 void pyWMDeleteTimerHandler(void *handlerID) {
454 WMDeleteTimerHandler((WMHandlerID)handlerID);
457 void* pyWMAddIdleHandler(PyObject *pycArgs) {
458 Py_INCREF(pycArgs);
459 return (void*)WMAddIdleHandler(PythonWMCallback, (void*)pycArgs);
462 void pyWMDeleteIdleHandler(void *handlerID) {
463 WMDeleteIdleHandler((WMHandlerID)handlerID);
469 %exception pyWMSetTextFieldDelegate {
470 $function
471 if (PyErr_Occurred()) {
472 return NULL;
476 %inline %{
477 void pyWMSetTextFieldDelegate(WMTextField *tPtr, PyObject *txtArgs) {
478 WMTextFieldDelegate *td;
480 if (!txtArgs || !PyTuple_Check(txtArgs) || PyTuple_Size(txtArgs)!=2) {
481 PyErr_SetString(PyExc_TypeError, "invalid setting of WMTextField "
482 "delegate. Should be '(self, delegate)'");
483 return;
485 // how do I check if txtArgs[1] is an instance of WMTextFieldDelegate?
486 td = WMGetTextFieldDelegate(tPtr);
487 if (!td) {
488 td = (WMTextFieldDelegate*)wmalloc(sizeof(WMTextFieldDelegate));
489 td->didBeginEditing = pyTextFieldDidBeginEditing;
490 td->didChange = pyTextFieldDidChange;
491 td->didEndEditing = pyTextFieldDidEndEditing;
492 td->shouldBeginEditing = pyTextFieldShouldBeginEditing;
493 td->shouldEndEditing = pyTextFieldShouldEndEditing;
494 } else {
495 Py_XDECREF((PyObject*)td->data);
497 Py_INCREF(txtArgs);
498 td->data = txtArgs;
499 WMSetTextFieldDelegate(tPtr, td);
504 %inline %{
505 PyObject* pyWMGetTextFieldDelegate(WMTextField *tPtr) {
506 WMTextFieldDelegate *td;
507 PyObject *result, *tuple;
509 td = WMGetTextFieldDelegate(tPtr);
510 if (!td) {
511 Py_INCREF(Py_None);
512 return Py_None;
515 tuple = (PyObject*)td->data;
516 if (!tuple || !PyTuple_Check(tuple) || PyTuple_Size(tuple)!=2) {
517 PyErr_SetString(PyExc_TypeError, "invalid TextField delegate");
518 return NULL;
521 result = PyTuple_GetItem(tuple, 1);
522 if (!result)
523 result = Py_None;
525 Py_INCREF(result);
527 return result;
532 %apply int *INPUT { int *argc };
534 #define Bool int
536 %include "WINGs/WUtil.h"
538 %include "WINGs/WINGs.h"
541 void
542 WHandleEvents()
544 /* Check any expired timers */
545 W_CheckTimerHandlers();
547 /* Do idle and timer stuff while there are no input events */
548 /* Do not wait for input here. just peek to se if input is available */
549 while (!W_HandleInputEvents(False, -1) && W_CheckIdleHandlers()) {
550 /* dispatch timer events */
551 W_CheckTimerHandlers();
554 W_HandleInputEvents(True, -1);
556 /* Check any expired timers */
557 W_CheckTimerHandlers();
561 /* rewrite functions originally defined as macros */
562 %inline %{
563 #undef WMDuplicateArray
564 WMArray* WMDuplicateArray(WMArray* array) {
565 return WMCreateArrayWithArray(array);
568 #undef WMPushInArray
569 void WMPushInArray(WMArray *array, void *item) {
570 WMAddToArray(array, item);
573 #undef WMSetInArray
574 void* WMSetInArray(WMArray *array, int index, void *item) {
575 return WMReplaceInArray(array, index, item);
578 #undef WMRemoveFromArray
579 int WMRemoveFromArray(WMArray *array, void *item) {
580 return WMRemoveFromArrayMatching(array, NULL, item);
583 #undef WMGetFirstInArray
584 int WMGetFirstInArray(WMArray *array, void *item) {
585 return WMFindInArray(array, NULL, item);
588 #undef WMCreateBag
589 WMBag* WMCreateBag(int size) {
590 return WMCreateTreeBag();
593 #undef WMCreateBagWithDestructor
594 WMBag* WMCreateBagWithDestructor(int size, WMFreeDataProc *destructor) {
595 return WMCreateTreeBagWithDestructor(destructor);
598 #undef WMSetInBag
599 void* WMSetInBag(WMBag *bag, int index, void *item) {
600 return WMReplaceInBag(bag, index, item);
603 #undef WMAddItemToTree
604 WMTreeNode* WMAddItemToTree(WMTreeNode *parent, void *item) {
605 return WMInsertItemInTree(parent, -1, item);
608 #undef WMAddNodeToTree
609 WMTreeNode* WMAddNodeToTree(WMTreeNode *parent, WMTreeNode *aNode) {
610 return WMInsertNodeInTree(parent, -1, aNode);
613 #undef WMGetFirstInTree
614 /* Returns first tree node that has data == cdata */
615 WMTreeNode* WMGetFirstInTree(WMTreeNode *aTree, void *cdata) {
616 return WMFindInTree(aTree, NULL, cdata);
619 #undef WMFlushConnection
620 int WMFlushConnection(WMConnection *cPtr) {
621 return WMSendConnectionData(cPtr, NULL);
624 #undef WMGetConnectionQueuedData
625 WMArray* WMGetConnectionQueuedData(WMConnection *cPtr) {
626 return WMGetConnectionUnsentData(cPtr);
629 #undef WMWidgetClass
630 W_Class WMWidgetClass(WMWidget *widget) {
631 return (((W_WidgetType*)(widget))->widgetClass);
634 #undef WMWidgetView
635 WMView* WMWidgetView(WMWidget *widget) {
636 return (((W_WidgetType*)(widget))->view);
639 #undef WMCreateCommandButton
640 WMButton* WMCreateCommandButton(WMWidget *parent) {
641 return WMCreateCustomButton(parent, WBBSpringLoadedMask|WBBPushInMask
642 |WBBPushLightMask|WBBPushChangeMask);
645 #undef WMCreateRadioButton
646 WMButton* WMCreateRadioButton(WMWidget *parent) {
647 return WMCreateButton(parent, WBTRadio);
650 #undef WMCreateSwitchButton
651 WMButton* WMCreateSwitchButton(WMWidget *parent) {
652 return WMCreateButton(parent, WBTSwitch);
655 #undef WMAddListItem
656 WMListItem* WMAddListItem(WMList *lPtr, char *text)
658 return WMInsertListItem(lPtr, -1, text);
661 #undef WMCreateText
662 WMText* WMCreateText(WMWidget *parent) {
663 return WMCreateTextForDocumentType(parent, NULL, NULL);
666 #undef WMRefreshText
667 void WMRefreshText(WMText *tPtr) {
668 return WMThawText(tPtr);
671 #undef WMClearText
672 void WMClearText(WMText *tPtr) {
673 return WMAppendTextStream(tPtr, NULL);