1 #include <lib/gui/elistbox.h>
2 #include <lib/gui/elistboxcontent.h>
3 #include <lib/gdi/font.h>
4 #include <lib/python/python.h>
7 The basic idea is to have an interface which gives all relevant list
8 processing functions, and can be used by the listbox to browse trough
11 The listbox directly uses the implemented cursor. It tries hard to avoid
12 iterating trough the (possibly very large) list, so it should be O(1),
13 i.e. the performance should not be influenced by the size of the list.
15 The list interface knows how to draw the current entry to a specified
16 offset. Different interfaces can be used to adapt different lists,
17 pre-filter lists on the fly etc.
19 cursorSave/Restore is used to avoid re-iterating the list on redraw.
20 The current selection is always selected as cursor position, the
21 cursor is then positioned to the start, and then iterated. This gives
22 at most 2x m_items_per_page cursor movements per redraw, indepenent
23 of the size of the list.
25 Although cursorSet is provided, it should be only used when there is no
26 other way, as it involves iterating trough the list.
29 iListboxContent::~iListboxContent()
33 iListboxContent::iListboxContent(): m_listbox(0)
37 void iListboxContent::setListbox(eListbox *lb)
40 m_listbox->setItemHeight(getItemHeight());
43 int iListboxContent::currentCursorSelectable()
48 //////////////////////////////////////
50 DEFINE_REF(eListboxPythonStringContent);
52 eListboxPythonStringContent::eListboxPythonStringContent(): m_itemheight(25)
56 eListboxPythonStringContent::~eListboxPythonStringContent()
61 void eListboxPythonStringContent::cursorHome()
66 void eListboxPythonStringContent::cursorEnd()
71 int eListboxPythonStringContent::cursorMove(int count)
77 else if (m_cursor > size())
82 int eListboxPythonStringContent::cursorValid()
84 return m_cursor < size();
87 int eListboxPythonStringContent::cursorSet(int n)
93 else if (m_cursor > size())
98 int eListboxPythonStringContent::cursorGet()
103 int eListboxPythonStringContent::currentCursorSelectable()
105 if (m_list && cursorValid())
107 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
108 if (!PyTuple_Check(item))
110 if (PyTuple_Size(item) >= 2)
116 void eListboxPythonStringContent::cursorSave()
118 m_saved_cursor = m_cursor;
121 void eListboxPythonStringContent::cursorRestore()
123 m_cursor = m_saved_cursor;
126 int eListboxPythonStringContent::size()
130 return PyList_Size(m_list);
133 void eListboxPythonStringContent::setSize(const eSize &size)
138 void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
140 ePtr<gFont> fnt = new gFont("Regular", 20);
141 painter.clip(eRect(offset, m_itemsize));
142 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
144 eListboxStyle *local_style = 0;
146 /* get local listbox style, if present */
148 local_style = m_listbox->getLocalStyle();
150 /* if we have a local background color set, use that. */
151 if (local_style && local_style->m_background_color_set)
152 painter.setBackgroundColor(local_style->m_background_color);
154 /* same for foreground */
155 if (local_style && local_style->m_foreground_color_set)
156 painter.setBackgroundColor(local_style->m_foreground_color);
158 /* if we have no transparent background */
159 if (!local_style || !local_style->m_transparent_background)
161 /* blit background picture, if available (otherwise, clear only) */
162 if (local_style && local_style->m_background)
163 painter.blit(local_style->m_background, offset, eRect(), 0);
168 if (local_style && local_style->m_background)
169 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
172 if (m_list && cursorValid())
175 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
176 painter.setFont(fnt);
178 /* the user can supply tuples, in this case the first one will be displayed. */
179 if (PyTuple_Check(item))
181 if (PyTuple_Size(item) == 1)
183 item = PyTuple_GET_ITEM(item, 0);
186 if (selected && local_style && local_style->m_selection)
187 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
192 int half_height = m_itemsize.height() / 2;
193 painter.fill(eRect(offset.x() + half_height, offset.y() + half_height - 2, m_itemsize.width() - m_itemsize.height(), 4));
196 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
197 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
199 painter.setForegroundColor(gRGB(0x808080));
200 painter.renderText(eRect(text_offset, m_itemsize), string);
203 if (selected && (!local_style || !local_style->m_selection))
204 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
210 void eListboxPythonStringContent::setList(ePyObject list)
213 if (!PyList_Check(list))
215 m_list = ePyObject();
223 m_listbox->entryReset(false);
226 PyObject *eListboxPythonStringContent::getCurrentSelection()
228 if (!(m_list && cursorValid()))
231 ePyObject r = PyList_GET_ITEM(m_list, m_cursor);
236 void eListboxPythonStringContent::invalidateEntry(int index)
239 m_listbox->entryChanged(index);
242 void eListboxPythonStringContent::invalidate()
248 m_listbox->moveSelectionTo(s?s-1:0);
249 m_listbox->invalidate();
253 //////////////////////////////////////
255 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
257 ePtr<gFont> fnt = new gFont("Regular", 20);
258 ePtr<gFont> fnt2 = new gFont("Regular", 16);
259 eRect itemrect(offset, m_itemsize);
260 eListboxStyle *local_style = 0;
262 painter.clip(itemrect);
263 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
265 /* get local listbox style, if present */
267 local_style = m_listbox->getLocalStyle();
269 /* if we have a local background color set, use that. */
270 if (local_style && local_style->m_background_color_set)
271 painter.setBackgroundColor(local_style->m_background_color);
273 /* same for foreground */
274 if (local_style && local_style->m_foreground_color_set)
275 painter.setBackgroundColor(local_style->m_foreground_color);
277 if (!local_style || !local_style->m_transparent_background)
278 /* if we have no transparent background */
280 /* blit background picture, if available (otherwise, clear only) */
281 if (local_style && local_style->m_background)
282 painter.blit(local_style->m_background, offset, eRect(), 0);
287 if (local_style && local_style->m_background)
288 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
291 if (m_list && cursorValid())
293 /* get current list item */
294 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
295 ePyObject text, value;
296 painter.setFont(fnt);
298 if (selected && local_style && local_style->m_selection)
299 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
301 /* the first tuple element is a string for the left side.
302 the second one will be called, and the result shall be an tuple.
305 the first one is the type (string).
306 the second one is the value. */
307 if (PyTuple_Check(item))
309 /* handle left part. get item from tuple, convert to string, display. */
311 text = PyTuple_GET_ITEM(item, 0);
312 text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
313 const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
314 eSize item_left = eSize(m_seperation, m_itemsize.height());
315 eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
316 painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
319 /* when we have no label, align value to the left. (FIXME:
320 don't we want to specifiy this individually?) */
321 int value_alignment_left = !*string;
323 /* now, handle the value. get 2nd part from tuple*/
324 value = PyTuple_GET_ITEM(item, 1);
327 ePyObject args = PyTuple_New(1);
328 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
330 /* CallObject will call __call__ which should return the value tuple */
331 value = PyObject_CallObject(value, args);
333 if (PyErr_Occurred())
337 /* the PyInt was stolen. */
340 /* check if this is really a tuple */
341 if (value && PyTuple_Check(value))
343 /* convert type to string */
344 ePyObject type = PyTuple_GET_ITEM(value, 0);
345 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
349 if (!strcmp(atype, "text"))
351 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
352 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
353 painter.setFont(fnt2);
354 if (value_alignment_left)
355 painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
357 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
359 /* pvalue is borrowed */
360 } else if (!strcmp(atype, "slider"))
362 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
363 ePyObject psize = PyTuple_GET_ITEM(value, 2);
365 /* convert value to Long. fallback to -1 on error. */
366 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
367 int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
369 /* calc. slider length */
370 int width = item_right.width() * value / size;
371 int height = item_right.height();
375 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
376 //hack - make it customizable
377 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
379 /* pvalue is borrowed */
380 } else if (!strcmp(atype, "mtext"))
382 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
383 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
384 int xoffs = value_alignment_left ? 0 : m_seperation;
385 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
387 para->renderString(text, 0);
388 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
389 int glyphs = para->size();
393 if (PyTuple_Size(value) >= 3)
394 plist = PyTuple_GET_ITEM(value, 2);
398 if (plist && PyList_Check(plist))
399 entries = PyList_Size(plist);
401 for (int i = 0; i < entries; ++i)
403 ePyObject entry = PyList_GET_ITEM(plist, i);
404 int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
406 if ((num < 0) || (num >= glyphs))
407 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
410 para->setGlyphFlag(num, GS_INVERT);
412 bbox = para->getGlyphBBox(num);
413 bbox = eRect(bbox.left(), offset.y(), bbox.width(), m_itemsize.height());
416 /* entry is borrowed */
419 painter.renderPara(para, ePoint(0, 0));
420 /* pvalue is borrowed */
421 /* plist is 0 or borrowed */
424 /* type is borrowed */
426 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
427 /* value is borrowed */
430 if (selected && (!local_style || !local_style->m_selection))
431 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
437 int eListboxPythonConfigContent::currentCursorSelectable()
439 return eListboxPythonStringContent::currentCursorSelectable();
442 //////////////////////////////////////
444 /* todo: make a real infrastructure here! */
445 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
447 eListboxPythonMultiContent::eListboxPythonMultiContent()
448 :m_temp_clip(gRegion::invalidRegion())
452 eListboxPythonMultiContent::~eListboxPythonMultiContent()
454 Py_XDECREF(m_buildFunc);
455 Py_XDECREF(m_selectableFunc);
458 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
460 if (update && m_selection_clip.valid())
462 m_temp_clip = m_selection_clip;
464 m_selection_clip = rect;
466 m_listbox->entryChanged(m_cursor);
469 m_selection_clip = rect;
472 static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *local_style, ePyObject pforeColor, ePyObject pbackColor, ePyObject pbackColorSelected, int selected, gRegion &rc, eRect &sel_clip)
474 /* if we have a local background color set, use that. */
475 if (local_style && local_style->m_background_color_set)
476 painter.setBackgroundColor(local_style->m_background_color);
478 if (selected && sel_clip.valid())
480 /* if we have no transparent background */
481 if (!local_style || !local_style->m_transparent_background)
483 painter.clip(rc-sel_clip);
486 int color = PyInt_AsLong(pbackColor);
487 painter.setBackgroundColor(gRGB(color));
488 }/* if we have a local background color set, use that. */
489 else if (local_style && local_style->m_background_color_set)
490 painter.setBackgroundColor(local_style->m_background_color);
492 style.setStyle(painter, eWindowStyle::styleListboxNormal);
496 painter.clip(rc&sel_clip);
497 style.setStyle(painter, eWindowStyle::styleListboxSelected);
498 if (pbackColorSelected)
500 int color = PyInt_AsLong(pbackColorSelected);
501 painter.setBackgroundColor(gRGB(color));
510 style.setStyle(painter, eWindowStyle::styleListboxSelected);
511 if (pbackColorSelected)
513 int color = PyInt_AsLong(pbackColorSelected);
514 painter.setBackgroundColor(gRGB(color));
520 style.setStyle(painter, eWindowStyle::styleListboxNormal);
523 int color = PyInt_AsLong(pbackColor);
524 painter.setBackgroundColor(gRGB(color));
525 }/* if we have a local background color set, use that. */
526 else if (local_style && local_style->m_background_color_set)
527 painter.setBackgroundColor(local_style->m_background_color);
528 /* if we have no transparent background */
529 if (!local_style || !local_style->m_transparent_background)
535 int color = PyInt_AsLong(pforeColor);
536 painter.setForegroundColor(gRGB(color));
537 }/* if we have a local foreground color set, use that. */
538 else if (local_style && local_style->m_foreground_color_set)
539 painter.setBackgroundColor(local_style->m_foreground_color);
542 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
544 gRegion itemregion(eRect(offset, m_itemsize));
545 eListboxStyle *local_style = 0;
546 eRect sel_clip(m_selection_clip);
547 if (sel_clip.valid())
548 sel_clip.moveBy(offset);
550 if (m_temp_clip.valid())
552 m_temp_clip.moveBy(offset);
553 itemregion &= m_temp_clip;
554 m_temp_clip = eRect();
557 /* get local listbox style, if present */
559 local_style = m_listbox->getLocalStyle();
561 painter.clip(itemregion);
563 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip);
567 if (m_list && cursorValid())
569 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
573 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
575 if (PyTuple_Check(items))
576 items = PyObject_CallObject(m_buildFunc, items);
578 eDebug("items is no tuple");
581 eDebug("buildfunc is not callable");
586 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
590 if (!PyList_Check(items))
592 eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
596 int size = PyList_Size(items);
597 for (int i = 1; i < size; ++i)
599 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
600 bool reset_colors=false;
604 eDebug("eListboxPythonMultiContent: ?");
608 if (!PyTuple_Check(item))
610 eDebug("eListboxPythonMultiContent did not receive a tuple.");
614 int size = PyTuple_Size(item);
618 eDebug("eListboxPythonMultiContent receive empty tuple.");
622 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
626 case TYPE_TEXT: // text
629 (0, x, y, width, height, fnt, flags, "bla" [, color, backColor, backColorSelected, borderWidth, borderColor] )
631 ePyObject px = PyTuple_GET_ITEM(item, 1),
632 py = PyTuple_GET_ITEM(item, 2),
633 pwidth = PyTuple_GET_ITEM(item, 3),
634 pheight = PyTuple_GET_ITEM(item, 4),
635 pfnt = PyTuple_GET_ITEM(item, 5),
636 pflags = PyTuple_GET_ITEM(item, 6),
637 pstring = PyTuple_GET_ITEM(item, 7),
638 pforeColor, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
640 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
642 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
648 pforeColor = PyTuple_GET_ITEM(item, 8);
649 if (pforeColor == Py_None)
650 pforeColor=ePyObject();
654 pbackColor = PyTuple_GET_ITEM(item, 9);
655 if (pbackColor == Py_None)
656 pbackColor=ePyObject();
660 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
661 if (pbackColorSelected == Py_None)
662 pbackColorSelected=ePyObject();
665 pborderWidth = PyTuple_GET_ITEM(item, 11);
667 pborderColor = PyTuple_GET_ITEM(item, 12);
669 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
670 int x = PyInt_AsLong(px) + offset.x();
671 int y = PyInt_AsLong(py) + offset.y();
672 int width = PyInt_AsLong(pwidth);
673 int height = PyInt_AsLong(pheight);
674 int flags = PyInt_AsLong(pflags);
675 int fnt = PyInt_AsLong(pfnt);
676 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
678 if (m_font.find(fnt) == m_font.end())
680 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
684 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
686 if (pbackColor || pbackColorSelected || pforeColor)
689 clearRegion(painter, style, local_style, pforeColor, pbackColor, pbackColorSelected, selected, rc, sel_clip);
693 painter.setFont(m_font[fnt]);
694 painter.renderText(rect, string, flags);
700 eRect rect(eRect(x, y, width, height));
704 int color = PyInt_AsLong(pborderColor);
705 painter.setForegroundColor(gRGB(color));
707 else if (pforeColor) // reset to normal color
708 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
710 rect.setRect(x, y, width, bwidth);
713 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
716 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
719 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
726 case TYPE_PROGRESS: // Progress
729 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
731 ePyObject px = PyTuple_GET_ITEM(item, 1),
732 py = PyTuple_GET_ITEM(item, 2),
733 pwidth = PyTuple_GET_ITEM(item, 3),
734 pheight = PyTuple_GET_ITEM(item, 4),
735 pfilled_perc = PyTuple_GET_ITEM(item, 5),
736 pborderWidth, pforeColor, pbackColor, pbackColorSelected;
738 if (!(px && py && pwidth && pheight && pfilled_perc))
740 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
745 pborderWidth = PyTuple_GET_ITEM(item, 6);
747 pforeColor = PyTuple_GET_ITEM(item, 7);
750 pbackColor = PyTuple_GET_ITEM(item, 8);
751 if (pbackColor == Py_None)
752 pbackColor=ePyObject();
756 pbackColorSelected = PyTuple_GET_ITEM(item, 9);
757 if (pbackColorSelected == Py_None)
758 pbackColorSelected=ePyObject();
761 int x = PyInt_AsLong(px) + offset.x();
762 int y = PyInt_AsLong(py) + offset.y();
763 int width = PyInt_AsLong(pwidth);
764 int height = PyInt_AsLong(pheight);
765 int filled = PyInt_AsLong(pfilled_perc);
766 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
768 eRect rect(x, y, width, height);
770 if (pbackColor || pbackColorSelected || pforeColor)
773 clearRegion(painter, style, local_style, pforeColor, pbackColor, pbackColorSelected, selected, rc, sel_clip);
778 rect.setRect(x, y, width, bwidth);
781 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
784 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
787 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
791 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
798 case TYPE_PIXMAP_ALPHATEST:
799 case TYPE_PIXMAP: // pixmap
802 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
805 ePyObject px = PyTuple_GET_ITEM(item, 1),
806 py = PyTuple_GET_ITEM(item, 2),
807 pwidth = PyTuple_GET_ITEM(item, 3),
808 pheight = PyTuple_GET_ITEM(item, 4),
809 ppixmap = PyTuple_GET_ITEM(item, 5),
810 pbackColor, pbackColorSelected;
812 if (!(px && py && pwidth && pheight && ppixmap))
814 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
818 int x = PyInt_AsLong(px) + offset.x();
819 int y = PyInt_AsLong(py) + offset.y();
820 int width = PyInt_AsLong(pwidth);
821 int height = PyInt_AsLong(pheight);
822 ePtr<gPixmap> pixmap;
823 if (SwigFromPython(pixmap, ppixmap))
825 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
831 pbackColor = PyTuple_GET_ITEM(item, 6);
832 if (pbackColor == Py_None)
833 pbackColor=ePyObject();
837 pbackColorSelected = PyTuple_GET_ITEM(item, 7);
838 if (pbackColorSelected == Py_None)
839 pbackColorSelected=ePyObject();
842 eRect rect(x, y, width, height);
844 if (pbackColor || pbackColorSelected)
847 clearRegion(painter, style, local_style, ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip);
851 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
856 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
860 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
865 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
868 if (m_buildFunc && PyCallable_Check(m_buildFunc) && items)
874 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
876 Py_XDECREF(m_buildFunc);
878 Py_XINCREF(m_buildFunc);
881 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
883 Py_XDECREF(m_selectableFunc);
885 Py_XINCREF(m_selectableFunc);
888 int eListboxPythonMultiContent::currentCursorSelectable()
890 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
891 if (m_list && cursorValid())
893 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
895 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
896 if (PyTuple_Check(args))
898 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
900 return ret == Py_True;
901 eDebug("call m_selectableFunc failed!!! assume not callable");
904 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
908 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
909 if (PyList_Check(item))
911 item = PyList_GET_ITEM(item, 0);
915 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
922 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
930 void eListboxPythonMultiContent::setItemHeight(int height)
932 m_itemheight = height;
934 m_listbox->setItemHeight(height);