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())
507 painter.clip(rc-sel_clip);
510 int color = PyInt_AsLong(pbackColor);
511 painter.setBackgroundColor(gRGB(color));
512 } // transparent background?
513 // if we have a local background color set, use that.
514 else if (local_style && local_style->m_background_color_set)
515 painter.setBackgroundColor(local_style->m_background_color);
517 style.setStyle(painter, eWindowStyle::styleListboxNormal);
518 if (local_style && local_style->m_transparent_background)
523 painter.clip(rc&sel_clip);
524 style.setStyle(painter, eWindowStyle::styleListboxSelected);
525 if (pbackColorSelected)
527 int color = PyInt_AsLong(pbackColorSelected);
528 painter.setBackgroundColor(gRGB(color));
530 else if (local_style && local_style->m_background_color_selected_set)
531 painter.setBackgroundColor(local_style->m_background_color_selected);
539 style.setStyle(painter, eWindowStyle::styleListboxSelected);
540 if (pbackColorSelected)
542 int color = PyInt_AsLong(pbackColorSelected);
543 painter.setBackgroundColor(gRGB(color));
545 else if (local_style && local_style->m_background_color_selected_set)
546 painter.setBackgroundColor(local_style->m_background_color_selected);
551 style.setStyle(painter, eWindowStyle::styleListboxNormal);
554 int color = PyInt_AsLong(pbackColor);
555 painter.setBackgroundColor(gRGB(color));
556 }/* if we have a local background color set, use that. */
557 else if (local_style && local_style->m_background_color_set)
558 painter.setBackgroundColor(local_style->m_background_color);
559 /* if we have no transparent background */
560 if (local_style && local_style->m_transparent_background)
568 if (pforeColorSelected)
570 int color = PyInt_AsLong(pforeColor);
571 painter.setForegroundColor(gRGB(color));
573 /* if we have a local foreground color set, use that. */
574 else if (local_style && local_style->m_foreground_color_selected_set)
575 painter.setForegroundColor(local_style->m_foreground_color_selected);
581 int color = PyInt_AsLong(pforeColor);
582 painter.setForegroundColor(gRGB(color));
584 /* if we have a local foreground color set, use that. */
585 else if (local_style && local_style->m_foreground_color_set)
586 painter.setForegroundColor(local_style->m_foreground_color);
590 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
592 gRegion itemregion(eRect(offset, m_itemsize));
593 eListboxStyle *local_style = 0;
594 eRect sel_clip(m_selection_clip);
595 if (sel_clip.valid())
596 sel_clip.moveBy(offset);
598 /* get local listbox style, if present */
600 local_style = m_listbox->getLocalStyle();
602 painter.clip(itemregion);
604 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip);
608 if (m_list && cursorValid())
610 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
614 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
616 if (PyTuple_Check(items))
617 items = PyObject_CallObject(m_buildFunc, items);
619 eDebug("items is no tuple");
622 eDebug("buildfunc is not callable");
627 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
631 if (!PyList_Check(items))
633 eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
637 int size = PyList_Size(items);
638 for (int i = 1; i < size; ++i)
640 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
641 bool reset_colors=false;
645 eDebug("eListboxPythonMultiContent: ?");
649 if (!PyTuple_Check(item))
651 eDebug("eListboxPythonMultiContent did not receive a tuple.");
655 int size = PyTuple_Size(item);
659 eDebug("eListboxPythonMultiContent receive empty tuple.");
663 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
667 case TYPE_TEXT: // text
670 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
672 ePyObject px = PyTuple_GET_ITEM(item, 1),
673 py = PyTuple_GET_ITEM(item, 2),
674 pwidth = PyTuple_GET_ITEM(item, 3),
675 pheight = PyTuple_GET_ITEM(item, 4),
676 pfnt = PyTuple_GET_ITEM(item, 5),
677 pflags = PyTuple_GET_ITEM(item, 6),
678 pstring = PyTuple_GET_ITEM(item, 7),
679 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
681 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
683 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
689 pforeColor = PyTuple_GET_ITEM(item, 8);
690 if (pforeColor == Py_None)
691 pforeColor=ePyObject();
695 pforeColorSelected = PyTuple_GET_ITEM(item, 9);
696 if (pforeColorSelected == Py_None)
697 pforeColorSelected=ePyObject();
701 pbackColor = PyTuple_GET_ITEM(item, 10);
702 if (pbackColor == Py_None)
703 pbackColor=ePyObject();
707 pbackColorSelected = PyTuple_GET_ITEM(item, 11);
708 if (pbackColorSelected == Py_None)
709 pbackColorSelected=ePyObject();
713 pborderWidth = PyTuple_GET_ITEM(item, 12);
714 if (pborderWidth == Py_None)
715 pborderWidth=ePyObject();
719 pborderColor = PyTuple_GET_ITEM(item, 13);
720 if (pborderColor == Py_None)
721 pborderColor=ePyObject();
724 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
725 int x = PyInt_AsLong(px) + offset.x();
726 int y = PyInt_AsLong(py) + offset.y();
727 int width = PyInt_AsLong(pwidth);
728 int height = PyInt_AsLong(pheight);
729 int flags = PyInt_AsLong(pflags);
730 int fnt = PyInt_AsLong(pfnt);
731 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
733 if (m_font.find(fnt) == m_font.end())
735 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
739 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
741 if (pbackColor || pbackColorSelected || pforeColor || pforeColorSelected)
744 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
748 painter.setFont(m_font[fnt]);
749 painter.renderText(rect, string, flags);
755 eRect rect(eRect(x, y, width, height));
759 int color = PyInt_AsLong(pborderColor);
760 painter.setForegroundColor(gRGB(color));
762 else if (pforeColor) // reset to normal color
763 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
765 rect.setRect(x, y, width, bwidth);
768 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
771 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
774 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
781 case TYPE_PROGRESS: // Progress
784 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
786 ePyObject px = PyTuple_GET_ITEM(item, 1),
787 py = PyTuple_GET_ITEM(item, 2),
788 pwidth = PyTuple_GET_ITEM(item, 3),
789 pheight = PyTuple_GET_ITEM(item, 4),
790 pfilled_perc = PyTuple_GET_ITEM(item, 5),
791 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
793 if (!(px && py && pwidth && pheight && pfilled_perc))
795 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
801 pborderWidth = PyTuple_GET_ITEM(item, 6);
802 if (pborderWidth == Py_None)
803 pborderWidth = ePyObject();
807 pforeColor = PyTuple_GET_ITEM(item, 7);
808 if (pforeColor == Py_None)
809 pforeColor = ePyObject();
813 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
814 if (pforeColorSelected == Py_None)
815 pforeColorSelected=ePyObject();
819 pbackColor = PyTuple_GET_ITEM(item, 9);
820 if (pbackColor == Py_None)
821 pbackColor=ePyObject();
825 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
826 if (pbackColorSelected == Py_None)
827 pbackColorSelected=ePyObject();
830 int x = PyInt_AsLong(px) + offset.x();
831 int y = PyInt_AsLong(py) + offset.y();
832 int width = PyInt_AsLong(pwidth);
833 int height = PyInt_AsLong(pheight);
834 int filled = PyInt_AsLong(pfilled_perc);
835 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
837 eRect rect(x, y, width, height);
839 if (pbackColor || pbackColorSelected || pforeColor || pforeColorSelected)
842 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
847 rect.setRect(x, y, width, bwidth);
850 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
853 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
856 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
860 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
867 case TYPE_PIXMAP_ALPHATEST:
868 case TYPE_PIXMAP: // pixmap
871 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
874 ePyObject px = PyTuple_GET_ITEM(item, 1),
875 py = PyTuple_GET_ITEM(item, 2),
876 pwidth = PyTuple_GET_ITEM(item, 3),
877 pheight = PyTuple_GET_ITEM(item, 4),
878 ppixmap = PyTuple_GET_ITEM(item, 5),
879 pbackColor, pbackColorSelected;
881 if (!(px && py && pwidth && pheight && ppixmap))
883 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
887 int x = PyInt_AsLong(px) + offset.x();
888 int y = PyInt_AsLong(py) + offset.y();
889 int width = PyInt_AsLong(pwidth);
890 int height = PyInt_AsLong(pheight);
891 ePtr<gPixmap> pixmap;
892 if (SwigFromPython(pixmap, ppixmap))
894 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
900 pbackColor = PyTuple_GET_ITEM(item, 6);
901 if (pbackColor == Py_None)
902 pbackColor=ePyObject();
906 pbackColorSelected = PyTuple_GET_ITEM(item, 7);
907 if (pbackColorSelected == Py_None)
908 pbackColorSelected=ePyObject();
911 eRect rect(x, y, width, height);
913 if (pbackColor || pbackColorSelected)
916 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip);
920 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
925 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
929 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
934 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
937 if (m_buildFunc && PyCallable_Check(m_buildFunc) && items)
943 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
945 Py_XDECREF(m_buildFunc);
947 Py_XINCREF(m_buildFunc);
950 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
952 Py_XDECREF(m_selectableFunc);
954 Py_XINCREF(m_selectableFunc);
957 int eListboxPythonMultiContent::currentCursorSelectable()
959 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
960 if (m_list && cursorValid())
962 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
964 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
965 if (PyTuple_Check(args))
967 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
969 return ret == Py_True;
970 eDebug("call m_selectableFunc failed!!! assume not callable");
973 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
977 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
978 if (PyList_Check(item))
980 item = PyList_GET_ITEM(item, 0);
984 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
991 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
999 void eListboxPythonMultiContent::setItemHeight(int height)
1001 m_itemheight = height;
1003 m_listbox->setItemHeight(height);
1006 void eListboxPythonMultiContent::setList(ePyObject list)
1008 m_old_clip = m_clip = gRegion::invalidRegion();
1009 eListboxPythonStringContent::setList(list);
1012 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1017 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1018 m_clip -= m_old_clip;
1019 m_old_clip = m_clip;
1022 m_old_clip = m_clip = gRegion::invalidRegion();