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_clip(gRegion::invalidRegion()), m_old_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 m_selection_clip = rect;
462 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
467 if (update && m_listbox)
468 m_listbox->entryChanged(m_cursor);
471 static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *local_style, ePyObject pforeColor, ePyObject pbackColor, ePyObject pbackColorSelected, int selected, gRegion &rc, eRect &sel_clip)
473 if (selected && sel_clip.valid())
476 painter.clip(rc-sel_clip);
479 int color = PyInt_AsLong(pbackColor);
480 painter.setBackgroundColor(gRGB(color));
482 else if (local_style)
484 // transparent background?
485 if (local_style->m_transparent_background)
487 // if we have a local background color set, use that.
488 else if (local_style->m_background_color_set)
489 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));
521 style.setStyle(painter, eWindowStyle::styleListboxNormal);
524 int color = PyInt_AsLong(pbackColor);
525 painter.setBackgroundColor(gRGB(color));
526 }/* if we have a local background color set, use that. */
527 else if (local_style)
529 if (local_style->m_transparent_background)
531 else if (local_style->m_background_color_set)
532 painter.setBackgroundColor(local_style->m_background_color);
534 /* if we have no transparent background */
541 int color = PyInt_AsLong(pforeColor);
542 painter.setForegroundColor(gRGB(color));
543 }/* if we have a local foreground color set, use that. */
544 else if (local_style && local_style->m_foreground_color_set)
545 painter.setBackgroundColor(local_style->m_foreground_color);
548 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
550 gRegion itemregion(eRect(offset, m_itemsize));
551 eListboxStyle *local_style = 0;
552 eRect sel_clip(m_selection_clip);
553 if (sel_clip.valid())
554 sel_clip.moveBy(offset);
556 /* get local listbox style, if present */
558 local_style = m_listbox->getLocalStyle();
560 painter.clip(itemregion);
562 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip);
566 if (m_list && cursorValid())
568 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
572 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
574 if (PyTuple_Check(items))
575 items = PyObject_CallObject(m_buildFunc, items);
577 eDebug("items is no tuple");
580 eDebug("buildfunc is not callable");
585 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
589 if (!PyList_Check(items))
591 eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
595 int size = PyList_Size(items);
596 for (int i = 1; i < size; ++i)
598 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
599 bool reset_colors=false;
603 eDebug("eListboxPythonMultiContent: ?");
607 if (!PyTuple_Check(item))
609 eDebug("eListboxPythonMultiContent did not receive a tuple.");
613 int size = PyTuple_Size(item);
617 eDebug("eListboxPythonMultiContent receive empty tuple.");
621 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
625 case TYPE_TEXT: // text
628 (0, x, y, width, height, fnt, flags, "bla" [, color, backColor, backColorSelected, borderWidth, borderColor] )
630 ePyObject px = PyTuple_GET_ITEM(item, 1),
631 py = PyTuple_GET_ITEM(item, 2),
632 pwidth = PyTuple_GET_ITEM(item, 3),
633 pheight = PyTuple_GET_ITEM(item, 4),
634 pfnt = PyTuple_GET_ITEM(item, 5),
635 pflags = PyTuple_GET_ITEM(item, 6),
636 pstring = PyTuple_GET_ITEM(item, 7),
637 pforeColor, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
639 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
641 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
647 pforeColor = PyTuple_GET_ITEM(item, 8);
648 if (pforeColor == Py_None)
649 pforeColor=ePyObject();
653 pbackColor = PyTuple_GET_ITEM(item, 9);
654 if (pbackColor == Py_None)
655 pbackColor=ePyObject();
659 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
660 if (pbackColorSelected == Py_None)
661 pbackColorSelected=ePyObject();
664 pborderWidth = PyTuple_GET_ITEM(item, 11);
666 pborderColor = PyTuple_GET_ITEM(item, 12);
668 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
669 int x = PyInt_AsLong(px) + offset.x();
670 int y = PyInt_AsLong(py) + offset.y();
671 int width = PyInt_AsLong(pwidth);
672 int height = PyInt_AsLong(pheight);
673 int flags = PyInt_AsLong(pflags);
674 int fnt = PyInt_AsLong(pfnt);
675 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
677 if (m_font.find(fnt) == m_font.end())
679 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
683 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
685 if (pbackColor || pbackColorSelected || pforeColor)
688 clearRegion(painter, style, local_style, pforeColor, pbackColor, pbackColorSelected, selected, rc, sel_clip);
692 painter.setFont(m_font[fnt]);
693 painter.renderText(rect, string, flags);
699 eRect rect(eRect(x, y, width, height));
703 int color = PyInt_AsLong(pborderColor);
704 painter.setForegroundColor(gRGB(color));
706 else if (pforeColor) // reset to normal color
707 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
709 rect.setRect(x, y, width, bwidth);
712 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
715 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
718 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
725 case TYPE_PROGRESS: // Progress
728 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
730 ePyObject px = PyTuple_GET_ITEM(item, 1),
731 py = PyTuple_GET_ITEM(item, 2),
732 pwidth = PyTuple_GET_ITEM(item, 3),
733 pheight = PyTuple_GET_ITEM(item, 4),
734 pfilled_perc = PyTuple_GET_ITEM(item, 5),
735 pborderWidth, pforeColor, pbackColor, pbackColorSelected;
737 if (!(px && py && pwidth && pheight && pfilled_perc))
739 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
744 pborderWidth = PyTuple_GET_ITEM(item, 6);
746 pforeColor = PyTuple_GET_ITEM(item, 7);
749 pbackColor = PyTuple_GET_ITEM(item, 8);
750 if (pbackColor == Py_None)
751 pbackColor=ePyObject();
755 pbackColorSelected = PyTuple_GET_ITEM(item, 9);
756 if (pbackColorSelected == Py_None)
757 pbackColorSelected=ePyObject();
760 int x = PyInt_AsLong(px) + offset.x();
761 int y = PyInt_AsLong(py) + offset.y();
762 int width = PyInt_AsLong(pwidth);
763 int height = PyInt_AsLong(pheight);
764 int filled = PyInt_AsLong(pfilled_perc);
765 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
767 eRect rect(x, y, width, height);
769 if (pbackColor || pbackColorSelected || pforeColor)
772 clearRegion(painter, style, local_style, pforeColor, pbackColor, pbackColorSelected, selected, rc, sel_clip);
777 rect.setRect(x, y, width, bwidth);
780 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
783 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
786 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
790 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
797 case TYPE_PIXMAP_ALPHATEST:
798 case TYPE_PIXMAP: // pixmap
801 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
804 ePyObject px = PyTuple_GET_ITEM(item, 1),
805 py = PyTuple_GET_ITEM(item, 2),
806 pwidth = PyTuple_GET_ITEM(item, 3),
807 pheight = PyTuple_GET_ITEM(item, 4),
808 ppixmap = PyTuple_GET_ITEM(item, 5),
809 pbackColor, pbackColorSelected;
811 if (!(px && py && pwidth && pheight && ppixmap))
813 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
817 int x = PyInt_AsLong(px) + offset.x();
818 int y = PyInt_AsLong(py) + offset.y();
819 int width = PyInt_AsLong(pwidth);
820 int height = PyInt_AsLong(pheight);
821 ePtr<gPixmap> pixmap;
822 if (SwigFromPython(pixmap, ppixmap))
824 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
830 pbackColor = PyTuple_GET_ITEM(item, 6);
831 if (pbackColor == Py_None)
832 pbackColor=ePyObject();
836 pbackColorSelected = PyTuple_GET_ITEM(item, 7);
837 if (pbackColorSelected == Py_None)
838 pbackColorSelected=ePyObject();
841 eRect rect(x, y, width, height);
843 if (pbackColor || pbackColorSelected)
846 clearRegion(painter, style, local_style, ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip);
850 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
855 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
859 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
864 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
867 if (m_buildFunc && PyCallable_Check(m_buildFunc) && items)
873 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
875 Py_XDECREF(m_buildFunc);
877 Py_XINCREF(m_buildFunc);
880 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
882 Py_XDECREF(m_selectableFunc);
884 Py_XINCREF(m_selectableFunc);
887 int eListboxPythonMultiContent::currentCursorSelectable()
889 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
890 if (m_list && cursorValid())
892 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
894 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
895 if (PyTuple_Check(args))
897 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
899 return ret == Py_True;
900 eDebug("call m_selectableFunc failed!!! assume not callable");
903 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
907 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
908 if (PyList_Check(item))
910 item = PyList_GET_ITEM(item, 0);
914 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
921 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
929 void eListboxPythonMultiContent::setItemHeight(int height)
931 m_itemheight = height;
933 m_listbox->setItemHeight(height);
936 void eListboxPythonMultiContent::setList(ePyObject list)
938 m_old_clip = m_clip = gRegion::invalidRegion();
939 eListboxPythonStringContent::setList(list);
942 void eListboxPythonMultiContent::updateClip(gRegion &clip)
947 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
948 m_clip -= m_old_clip;
952 m_old_clip = m_clip = gRegion::invalidRegion();