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.setForegroundColor(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->m_background)
169 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
170 else if (selected && !local_style->m_selection)
174 if (m_list && cursorValid())
177 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
178 painter.setFont(fnt);
180 /* the user can supply tuples, in this case the first one will be displayed. */
181 if (PyTuple_Check(item))
183 if (PyTuple_Size(item) == 1)
185 item = PyTuple_GET_ITEM(item, 0);
188 if (selected && local_style && local_style->m_selection)
189 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
194 int half_height = m_itemsize.height() / 2;
195 painter.fill(eRect(offset.x() + half_height, offset.y() + half_height - 2, m_itemsize.width() - m_itemsize.height(), 4));
198 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
199 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
201 painter.setForegroundColor(gRGB(0x808080));
202 painter.renderText(eRect(text_offset, m_itemsize), string);
205 if (selected && (!local_style || !local_style->m_selection))
206 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
212 void eListboxPythonStringContent::setList(ePyObject list)
215 if (!PyList_Check(list))
217 m_list = ePyObject();
225 m_listbox->entryReset(false);
228 PyObject *eListboxPythonStringContent::getCurrentSelection()
230 if (!(m_list && cursorValid()))
233 ePyObject r = PyList_GET_ITEM(m_list, m_cursor);
238 void eListboxPythonStringContent::invalidateEntry(int index)
241 m_listbox->entryChanged(index);
244 void eListboxPythonStringContent::invalidate()
250 m_listbox->moveSelectionTo(s?s-1:0);
251 m_listbox->invalidate();
255 //////////////////////////////////////
257 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
259 ePtr<gFont> fnt = new gFont("Regular", 20);
260 ePtr<gFont> fnt2 = new gFont("Regular", 16);
261 eRect itemrect(offset, m_itemsize);
262 eListboxStyle *local_style = 0;
264 painter.clip(itemrect);
265 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
267 /* get local listbox style, if present */
269 local_style = m_listbox->getLocalStyle();
271 /* if we have a local background color set, use that. */
272 if (local_style && local_style->m_background_color_set)
273 painter.setBackgroundColor(local_style->m_background_color);
275 /* same for foreground */
276 if (local_style && local_style->m_foreground_color_set)
277 painter.setForegroundColor(local_style->m_foreground_color);
279 if (!local_style || !local_style->m_transparent_background)
280 /* if we have no transparent background */
282 /* blit background picture, if available (otherwise, clear only) */
283 if (local_style && local_style->m_background)
284 painter.blit(local_style->m_background, offset, eRect(), 0);
289 if (local_style->m_background)
290 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
291 else if (selected && !local_style->m_selection)
295 if (m_list && cursorValid())
297 /* get current list item */
298 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
299 ePyObject text, value;
300 painter.setFont(fnt);
302 if (selected && local_style && local_style->m_selection)
303 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
305 /* the first tuple element is a string for the left side.
306 the second one will be called, and the result shall be an tuple.
309 the first one is the type (string).
310 the second one is the value. */
311 if (PyTuple_Check(item))
313 /* handle left part. get item from tuple, convert to string, display. */
315 text = PyTuple_GET_ITEM(item, 0);
316 text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
317 const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
318 eSize item_left = eSize(m_seperation, m_itemsize.height());
319 eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
320 painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
323 /* when we have no label, align value to the left. (FIXME:
324 don't we want to specifiy this individually?) */
325 int value_alignment_left = !*string;
327 /* now, handle the value. get 2nd part from tuple*/
328 value = PyTuple_GET_ITEM(item, 1);
331 ePyObject args = PyTuple_New(1);
332 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
334 /* CallObject will call __call__ which should return the value tuple */
335 value = PyObject_CallObject(value, args);
337 if (PyErr_Occurred())
341 /* the PyInt was stolen. */
344 /* check if this is really a tuple */
345 if (value && PyTuple_Check(value))
347 /* convert type to string */
348 ePyObject type = PyTuple_GET_ITEM(value, 0);
349 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
353 if (!strcmp(atype, "text"))
355 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
356 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
357 painter.setFont(fnt2);
358 if (value_alignment_left)
359 painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
361 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
363 /* pvalue is borrowed */
364 } else if (!strcmp(atype, "slider"))
366 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
367 ePyObject psize = PyTuple_GET_ITEM(value, 2);
369 /* convert value to Long. fallback to -1 on error. */
370 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
371 int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
373 /* calc. slider length */
374 int width = item_right.width() * value / size;
375 int height = item_right.height();
379 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
380 //hack - make it customizable
381 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
383 /* pvalue is borrowed */
384 } else if (!strcmp(atype, "mtext"))
386 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
387 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
388 int xoffs = value_alignment_left ? 0 : m_seperation;
389 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
391 para->renderString(text, 0);
392 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
393 int glyphs = para->size();
397 if (PyTuple_Size(value) >= 3)
398 plist = PyTuple_GET_ITEM(value, 2);
402 if (plist && PyList_Check(plist))
403 entries = PyList_Size(plist);
405 for (int i = 0; i < entries; ++i)
407 ePyObject entry = PyList_GET_ITEM(plist, i);
408 int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
410 if ((num < 0) || (num >= glyphs))
411 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
414 para->setGlyphFlag(num, GS_INVERT);
416 bbox = para->getGlyphBBox(num);
417 bbox = eRect(bbox.left(), offset.y(), bbox.width(), m_itemsize.height());
420 /* entry is borrowed */
423 painter.renderPara(para, ePoint(0, 0));
424 /* pvalue is borrowed */
425 /* plist is 0 or borrowed */
428 /* type is borrowed */
430 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
431 /* value is borrowed */
434 if (selected && (!local_style || !local_style->m_selection))
435 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
441 int eListboxPythonConfigContent::currentCursorSelectable()
443 return eListboxPythonStringContent::currentCursorSelectable();
446 //////////////////////////////////////
448 /* todo: make a real infrastructure here! */
449 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
451 eListboxPythonMultiContent::eListboxPythonMultiContent()
452 :m_clip(gRegion::invalidRegion()), m_old_clip(gRegion::invalidRegion())
456 eListboxPythonMultiContent::~eListboxPythonMultiContent()
458 Py_XDECREF(m_buildFunc);
459 Py_XDECREF(m_selectableFunc);
462 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
464 m_selection_clip = rect;
466 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
471 if (update && m_listbox)
472 m_listbox->entryChanged(m_cursor);
475 static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *local_style, ePyObject pforeColor, ePyObject pbackColor, ePyObject pbackColorSelected, int selected, gRegion &rc, eRect &sel_clip)
477 if (selected && sel_clip.valid())
480 painter.clip(rc-sel_clip);
483 int color = PyInt_AsLong(pbackColor);
484 painter.setBackgroundColor(gRGB(color));
485 } // transparent background?
486 else if (local_style && local_style->m_transparent_background)
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));
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.setForegroundColor(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();