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();
154 /* if we have a local background color set, use that. */
155 if (local_style->m_background_color_selected_set)
156 painter.setBackgroundColor(local_style->m_background_color_selected);
157 /* same for foreground */
158 if (local_style->m_foreground_color_selected_set)
159 painter.setForegroundColor(local_style->m_foreground_color_selected);
163 /* if we have a local background color set, use that. */
164 if (local_style->m_background_color_set)
165 painter.setBackgroundColor(local_style->m_background_color);
166 /* same for foreground */
167 if (local_style->m_foreground_color_set)
168 painter.setForegroundColor(local_style->m_foreground_color);
172 /* if we have no transparent background */
173 if (!local_style || !local_style->m_transparent_background)
175 /* blit background picture, if available (otherwise, clear only) */
176 if (local_style && local_style->m_background)
177 painter.blit(local_style->m_background, offset, eRect(), 0);
182 if (local_style->m_background)
183 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
184 else if (selected && !local_style->m_selection)
188 if (m_list && cursorValid())
191 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
192 painter.setFont(fnt);
194 /* the user can supply tuples, in this case the first one will be displayed. */
195 if (PyTuple_Check(item))
197 if (PyTuple_Size(item) == 1)
199 item = PyTuple_GET_ITEM(item, 0);
202 if (selected && local_style && local_style->m_selection)
203 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
208 int half_height = m_itemsize.height() / 2;
209 painter.fill(eRect(offset.x() + half_height, offset.y() + half_height - 2, m_itemsize.width() - m_itemsize.height(), 4));
212 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
213 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
215 painter.setForegroundColor(gRGB(0x808080));
216 painter.renderText(eRect(text_offset, m_itemsize), string);
219 if (selected && (!local_style || !local_style->m_selection))
220 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
226 void eListboxPythonStringContent::setList(ePyObject list)
229 if (!PyList_Check(list))
231 m_list = ePyObject();
239 m_listbox->entryReset(false);
242 PyObject *eListboxPythonStringContent::getCurrentSelection()
244 if (!(m_list && cursorValid()))
247 ePyObject r = PyList_GET_ITEM(m_list, m_cursor);
252 void eListboxPythonStringContent::invalidateEntry(int index)
255 m_listbox->entryChanged(index);
258 void eListboxPythonStringContent::invalidate()
264 m_listbox->moveSelectionTo(s?s-1:0);
265 m_listbox->invalidate();
269 //////////////////////////////////////
271 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
273 ePtr<gFont> fnt = new gFont("Regular", 20);
274 ePtr<gFont> fnt2 = new gFont("Regular", 16);
275 eRect itemrect(offset, m_itemsize);
276 eListboxStyle *local_style = 0;
278 painter.clip(itemrect);
279 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
281 /* get local listbox style, if present */
283 local_style = m_listbox->getLocalStyle();
289 /* if we have a local background color set, use that. */
290 if (local_style->m_background_color_selected_set)
291 painter.setBackgroundColor(local_style->m_background_color_selected);
292 /* same for foreground */
293 if (local_style->m_foreground_color_selected_set)
294 painter.setForegroundColor(local_style->m_foreground_color_selected);
298 /* if we have a local background color set, use that. */
299 if (local_style->m_background_color_set)
300 painter.setBackgroundColor(local_style->m_background_color);
301 /* same for foreground */
302 if (local_style->m_foreground_color_set)
303 painter.setForegroundColor(local_style->m_foreground_color);
307 if (!local_style || !local_style->m_transparent_background)
308 /* if we have no transparent background */
310 /* blit background picture, if available (otherwise, clear only) */
311 if (local_style && local_style->m_background)
312 painter.blit(local_style->m_background, offset, eRect(), 0);
317 if (local_style->m_background)
318 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
319 else if (selected && !local_style->m_selection)
323 if (m_list && cursorValid())
325 /* get current list item */
326 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
327 ePyObject text, value;
328 painter.setFont(fnt);
330 if (selected && local_style && local_style->m_selection)
331 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
333 /* the first tuple element is a string for the left side.
334 the second one will be called, and the result shall be an tuple.
337 the first one is the type (string).
338 the second one is the value. */
339 if (PyTuple_Check(item))
341 /* handle left part. get item from tuple, convert to string, display. */
343 text = PyTuple_GET_ITEM(item, 0);
344 text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
345 const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
346 eSize item_left = eSize(m_seperation, m_itemsize.height());
347 eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
348 painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
351 /* when we have no label, align value to the left. (FIXME:
352 don't we want to specifiy this individually?) */
353 int value_alignment_left = !*string;
355 /* now, handle the value. get 2nd part from tuple*/
356 value = PyTuple_GET_ITEM(item, 1);
359 ePyObject args = PyTuple_New(1);
360 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
362 /* CallObject will call __call__ which should return the value tuple */
363 value = PyObject_CallObject(value, args);
365 if (PyErr_Occurred())
369 /* the PyInt was stolen. */
372 /* check if this is really a tuple */
373 if (value && PyTuple_Check(value))
375 /* convert type to string */
376 ePyObject type = PyTuple_GET_ITEM(value, 0);
377 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
381 if (!strcmp(atype, "text"))
383 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
384 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
385 painter.setFont(fnt2);
386 if (value_alignment_left)
387 painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
389 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
391 /* pvalue is borrowed */
392 } else if (!strcmp(atype, "slider"))
394 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
395 ePyObject psize = PyTuple_GET_ITEM(value, 2);
397 /* convert value to Long. fallback to -1 on error. */
398 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
399 int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
401 /* calc. slider length */
402 int width = item_right.width() * value / size;
403 int height = item_right.height();
407 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
408 //hack - make it customizable
409 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
411 /* pvalue is borrowed */
412 } else if (!strcmp(atype, "mtext"))
414 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
415 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
416 int xoffs = value_alignment_left ? 0 : m_seperation;
417 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
419 para->renderString(text, 0);
420 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
421 int glyphs = para->size();
425 if (PyTuple_Size(value) >= 3)
426 plist = PyTuple_GET_ITEM(value, 2);
430 if (plist && PyList_Check(plist))
431 entries = PyList_Size(plist);
433 for (int i = 0; i < entries; ++i)
435 ePyObject entry = PyList_GET_ITEM(plist, i);
436 int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
438 if ((num < 0) || (num >= glyphs))
439 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
442 para->setGlyphFlag(num, GS_INVERT);
444 bbox = para->getGlyphBBox(num);
445 bbox = eRect(bbox.left(), offset.y(), bbox.width(), m_itemsize.height());
448 /* entry is borrowed */
451 painter.renderPara(para, ePoint(0, 0));
452 /* pvalue is borrowed */
453 /* plist is 0 or borrowed */
456 /* type is borrowed */
458 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
459 /* value is borrowed */
462 if (selected && (!local_style || !local_style->m_selection))
463 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
469 int eListboxPythonConfigContent::currentCursorSelectable()
471 return eListboxPythonStringContent::currentCursorSelectable();
474 //////////////////////////////////////
476 /* todo: make a real infrastructure here! */
477 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
479 eListboxPythonMultiContent::eListboxPythonMultiContent()
480 :m_clip(gRegion::invalidRegion()), m_old_clip(gRegion::invalidRegion())
484 eListboxPythonMultiContent::~eListboxPythonMultiContent()
486 Py_XDECREF(m_buildFunc);
487 Py_XDECREF(m_selectableFunc);
490 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
492 m_selection_clip = rect;
494 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
499 if (update && m_listbox)
500 m_listbox->entryChanged(m_cursor);
503 static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *local_style, ePyObject pforeColor, ePyObject pforeColorSelected, ePyObject pbackColor, ePyObject pbackColorSelected, int selected, gRegion &rc, eRect &sel_clip)
505 if (selected && sel_clip.valid())
508 painter.clip(rc-sel_clip);
511 int color = PyInt_AsLong(pbackColor);
512 painter.setBackgroundColor(gRGB(color));
513 } // transparent background?
514 else if (local_style && local_style->m_transparent_background)
516 // if we have a local background color set, use that.
517 else if (local_style && local_style->m_background_color_set)
518 painter.setBackgroundColor(local_style->m_background_color);
520 style.setStyle(painter, eWindowStyle::styleListboxNormal);
524 painter.clip(rc&sel_clip);
525 style.setStyle(painter, eWindowStyle::styleListboxSelected);
526 if (pbackColorSelected)
528 int color = PyInt_AsLong(pbackColorSelected);
529 painter.setBackgroundColor(gRGB(color));
531 else if (local_style && local_style->m_background_color_selected_set)
532 painter.setBackgroundColor(local_style->m_background_color_selected);
540 style.setStyle(painter, eWindowStyle::styleListboxSelected);
541 if (pbackColorSelected)
543 int color = PyInt_AsLong(pbackColorSelected);
544 painter.setBackgroundColor(gRGB(color));
546 else if (local_style && local_style->m_background_color_selected_set)
547 painter.setBackgroundColor(local_style->m_background_color_selected);
553 style.setStyle(painter, eWindowStyle::styleListboxNormal);
556 int color = PyInt_AsLong(pbackColor);
557 painter.setBackgroundColor(gRGB(color));
558 }/* if we have a local background color set, use that. */
559 else if (local_style)
561 if (local_style->m_transparent_background)
563 else if (local_style->m_background_color_set)
564 painter.setBackgroundColor(local_style->m_background_color);
566 /* if we have no transparent background */
573 if (pforeColorSelected)
575 int color = PyInt_AsLong(pforeColor);
576 painter.setForegroundColor(gRGB(color));
578 /* if we have a local foreground color set, use that. */
579 else if (local_style && local_style->m_foreground_color_selected_set)
580 painter.setForegroundColor(local_style->m_foreground_color_selected);
586 int color = PyInt_AsLong(pforeColor);
587 painter.setForegroundColor(gRGB(color));
589 /* if we have a local foreground color set, use that. */
590 else if (local_style && local_style->m_foreground_color_set)
591 painter.setForegroundColor(local_style->m_foreground_color);
595 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
597 gRegion itemregion(eRect(offset, m_itemsize));
598 eListboxStyle *local_style = 0;
599 eRect sel_clip(m_selection_clip);
600 if (sel_clip.valid())
601 sel_clip.moveBy(offset);
603 /* get local listbox style, if present */
605 local_style = m_listbox->getLocalStyle();
607 painter.clip(itemregion);
609 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip);
613 if (m_list && cursorValid())
615 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
619 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
621 if (PyTuple_Check(items))
622 items = PyObject_CallObject(m_buildFunc, items);
624 eDebug("items is no tuple");
627 eDebug("buildfunc is not callable");
632 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
636 if (!PyList_Check(items))
638 eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
642 int size = PyList_Size(items);
643 for (int i = 1; i < size; ++i)
645 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
646 bool reset_colors=false;
650 eDebug("eListboxPythonMultiContent: ?");
654 if (!PyTuple_Check(item))
656 eDebug("eListboxPythonMultiContent did not receive a tuple.");
660 int size = PyTuple_Size(item);
664 eDebug("eListboxPythonMultiContent receive empty tuple.");
668 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
672 case TYPE_TEXT: // text
675 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
677 ePyObject px = PyTuple_GET_ITEM(item, 1),
678 py = PyTuple_GET_ITEM(item, 2),
679 pwidth = PyTuple_GET_ITEM(item, 3),
680 pheight = PyTuple_GET_ITEM(item, 4),
681 pfnt = PyTuple_GET_ITEM(item, 5),
682 pflags = PyTuple_GET_ITEM(item, 6),
683 pstring = PyTuple_GET_ITEM(item, 7),
684 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
686 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
688 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
694 pforeColor = PyTuple_GET_ITEM(item, 8);
695 if (pforeColor == Py_None)
696 pforeColor=ePyObject();
700 pforeColorSelected = PyTuple_GET_ITEM(item, 9);
701 if (pforeColorSelected == Py_None)
702 pforeColorSelected=ePyObject();
706 pbackColor = PyTuple_GET_ITEM(item, 10);
707 if (pbackColor == Py_None)
708 pbackColor=ePyObject();
712 pbackColorSelected = PyTuple_GET_ITEM(item, 11);
713 if (pbackColorSelected == Py_None)
714 pbackColorSelected=ePyObject();
718 pborderWidth = PyTuple_GET_ITEM(item, 12);
719 if (pborderWidth == Py_None)
720 pborderWidth=ePyObject();
724 pborderColor = PyTuple_GET_ITEM(item, 13);
725 if (pborderColor == Py_None)
726 pborderColor=ePyObject();
729 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
730 int x = PyInt_AsLong(px) + offset.x();
731 int y = PyInt_AsLong(py) + offset.y();
732 int width = PyInt_AsLong(pwidth);
733 int height = PyInt_AsLong(pheight);
734 int flags = PyInt_AsLong(pflags);
735 int fnt = PyInt_AsLong(pfnt);
736 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
738 if (m_font.find(fnt) == m_font.end())
740 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
744 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
746 if (pbackColor || pbackColorSelected || pforeColor || pforeColorSelected)
749 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
753 painter.setFont(m_font[fnt]);
754 painter.renderText(rect, string, flags);
760 eRect rect(eRect(x, y, width, height));
764 int color = PyInt_AsLong(pborderColor);
765 painter.setForegroundColor(gRGB(color));
767 else if (pforeColor) // reset to normal color
768 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
770 rect.setRect(x, y, width, bwidth);
773 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
776 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
779 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
786 case TYPE_PROGRESS: // Progress
789 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
791 ePyObject px = PyTuple_GET_ITEM(item, 1),
792 py = PyTuple_GET_ITEM(item, 2),
793 pwidth = PyTuple_GET_ITEM(item, 3),
794 pheight = PyTuple_GET_ITEM(item, 4),
795 pfilled_perc = PyTuple_GET_ITEM(item, 5),
796 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
798 if (!(px && py && pwidth && pheight && pfilled_perc))
800 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
806 pborderWidth = PyTuple_GET_ITEM(item, 6);
807 if (pborderWidth == Py_None)
808 pborderWidth = ePyObject();
812 pforeColor = PyTuple_GET_ITEM(item, 7);
813 if (pforeColor == Py_None)
814 pforeColor = ePyObject();
818 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
819 if (pforeColorSelected == Py_None)
820 pforeColorSelected=ePyObject();
824 pbackColor = PyTuple_GET_ITEM(item, 9);
825 if (pbackColor == Py_None)
826 pbackColor=ePyObject();
830 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
831 if (pbackColorSelected == Py_None)
832 pbackColorSelected=ePyObject();
835 int x = PyInt_AsLong(px) + offset.x();
836 int y = PyInt_AsLong(py) + offset.y();
837 int width = PyInt_AsLong(pwidth);
838 int height = PyInt_AsLong(pheight);
839 int filled = PyInt_AsLong(pfilled_perc);
840 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
842 eRect rect(x, y, width, height);
844 if (pbackColor || pbackColorSelected || pforeColor || pforeColorSelected)
847 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
852 rect.setRect(x, y, width, bwidth);
855 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
858 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
861 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
865 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
872 case TYPE_PIXMAP_ALPHATEST:
873 case TYPE_PIXMAP: // pixmap
876 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
879 ePyObject px = PyTuple_GET_ITEM(item, 1),
880 py = PyTuple_GET_ITEM(item, 2),
881 pwidth = PyTuple_GET_ITEM(item, 3),
882 pheight = PyTuple_GET_ITEM(item, 4),
883 ppixmap = PyTuple_GET_ITEM(item, 5),
884 pbackColor, pbackColorSelected;
886 if (!(px && py && pwidth && pheight && ppixmap))
888 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
892 int x = PyInt_AsLong(px) + offset.x();
893 int y = PyInt_AsLong(py) + offset.y();
894 int width = PyInt_AsLong(pwidth);
895 int height = PyInt_AsLong(pheight);
896 ePtr<gPixmap> pixmap;
897 if (SwigFromPython(pixmap, ppixmap))
899 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
905 pbackColor = PyTuple_GET_ITEM(item, 6);
906 if (pbackColor == Py_None)
907 pbackColor=ePyObject();
911 pbackColorSelected = PyTuple_GET_ITEM(item, 7);
912 if (pbackColorSelected == Py_None)
913 pbackColorSelected=ePyObject();
916 eRect rect(x, y, width, height);
918 if (pbackColor || pbackColorSelected)
921 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip);
925 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
930 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
934 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
939 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
942 if (m_buildFunc && PyCallable_Check(m_buildFunc) && items)
948 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
950 Py_XDECREF(m_buildFunc);
952 Py_XINCREF(m_buildFunc);
955 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
957 Py_XDECREF(m_selectableFunc);
959 Py_XINCREF(m_selectableFunc);
962 int eListboxPythonMultiContent::currentCursorSelectable()
964 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
965 if (m_list && cursorValid())
967 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
969 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
970 if (PyTuple_Check(args))
972 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
974 return ret == Py_True;
975 eDebug("call m_selectableFunc failed!!! assume not callable");
978 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
982 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
983 if (PyList_Check(item))
985 item = PyList_GET_ITEM(item, 0);
989 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
996 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1004 void eListboxPythonMultiContent::setItemHeight(int height)
1006 m_itemheight = height;
1008 m_listbox->setItemHeight(height);
1011 void eListboxPythonMultiContent::setList(ePyObject list)
1013 m_old_clip = m_clip = gRegion::invalidRegion();
1014 eListboxPythonStringContent::setList(list);
1017 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1022 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1023 m_clip -= m_old_clip;
1024 m_old_clip = m_clip;
1027 m_old_clip = m_clip = gRegion::invalidRegion();