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 gRegion part = rc - sel_clip;
511 style.setStyle(painter, eWindowStyle::styleListboxNormal);
514 int color = PyInt_AsLong(pbackColor);
515 painter.setBackgroundColor(gRGB(color));
516 } // transparent background?
517 // if we have a local background color set, use that.
518 else if (local_style && local_style->m_background_color_set)
519 painter.setBackgroundColor(local_style->m_background_color);
520 if (!pbackColor && local_style && local_style->m_transparent_background)
527 part = rc & sel_clip;
531 style.setStyle(painter, eWindowStyle::styleListboxSelected);
532 if (pbackColorSelected)
534 int color = PyInt_AsLong(pbackColorSelected);
535 painter.setBackgroundColor(gRGB(color));
537 else if (local_style && local_style->m_background_color_selected_set)
538 painter.setBackgroundColor(local_style->m_background_color_selected);
548 style.setStyle(painter, eWindowStyle::styleListboxSelected);
549 if (pbackColorSelected)
551 int color = PyInt_AsLong(pbackColorSelected);
552 painter.setBackgroundColor(gRGB(color));
554 else if (local_style && local_style->m_background_color_selected_set)
555 painter.setBackgroundColor(local_style->m_background_color_selected);
560 style.setStyle(painter, eWindowStyle::styleListboxNormal);
563 int color = PyInt_AsLong(pbackColor);
564 painter.setBackgroundColor(gRGB(color));
565 }/* if we have a local background color set, use that. */
566 else if (local_style && local_style->m_background_color_set)
567 painter.setBackgroundColor(local_style->m_background_color);
568 /* if we have no transparent background */
569 if (!pbackColor && local_style && local_style->m_transparent_background)
577 if (pforeColorSelected)
579 int color = PyInt_AsLong(pforeColor);
580 painter.setForegroundColor(gRGB(color));
582 /* if we have a local foreground color set, use that. */
583 else if (local_style && local_style->m_foreground_color_selected_set)
584 painter.setForegroundColor(local_style->m_foreground_color_selected);
590 int color = PyInt_AsLong(pforeColor);
591 painter.setForegroundColor(gRGB(color));
593 /* if we have a local foreground color set, use that. */
594 else if (local_style && local_style->m_foreground_color_set)
595 painter.setForegroundColor(local_style->m_foreground_color);
599 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
601 gRegion itemregion(eRect(offset, m_itemsize));
602 eListboxStyle *local_style = 0;
603 eRect sel_clip(m_selection_clip);
604 if (sel_clip.valid())
605 sel_clip.moveBy(offset);
607 /* get local listbox style, if present */
609 local_style = m_listbox->getLocalStyle();
611 painter.clip(itemregion);
612 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip);
616 if (m_list && cursorValid())
618 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
622 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
624 if (PyTuple_Check(items))
625 items = PyObject_CallObject(m_buildFunc, items);
627 eDebug("items is no tuple");
630 eDebug("buildfunc is not callable");
635 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
639 if (!PyList_Check(items))
641 eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
645 int size = PyList_Size(items);
646 for (int i = 1; i < size; ++i)
648 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
652 eDebug("eListboxPythonMultiContent: ?");
656 if (!PyTuple_Check(item))
658 eDebug("eListboxPythonMultiContent did not receive a tuple.");
662 int size = PyTuple_Size(item);
666 eDebug("eListboxPythonMultiContent receive empty tuple.");
670 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
674 case TYPE_TEXT: // text
677 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
679 ePyObject px = PyTuple_GET_ITEM(item, 1),
680 py = PyTuple_GET_ITEM(item, 2),
681 pwidth = PyTuple_GET_ITEM(item, 3),
682 pheight = PyTuple_GET_ITEM(item, 4),
683 pfnt = PyTuple_GET_ITEM(item, 5),
684 pflags = PyTuple_GET_ITEM(item, 6),
685 pstring = PyTuple_GET_ITEM(item, 7),
686 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
688 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
690 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
696 pforeColor = PyTuple_GET_ITEM(item, 8);
697 if (pforeColor == Py_None)
698 pforeColor=ePyObject();
702 pforeColorSelected = PyTuple_GET_ITEM(item, 9);
703 if (pforeColorSelected == Py_None)
704 pforeColorSelected=ePyObject();
708 pbackColor = PyTuple_GET_ITEM(item, 10);
709 if (pbackColor == Py_None)
710 pbackColor=ePyObject();
714 pbackColorSelected = PyTuple_GET_ITEM(item, 11);
715 if (pbackColorSelected == Py_None)
716 pbackColorSelected=ePyObject();
720 pborderWidth = PyTuple_GET_ITEM(item, 12);
721 if (pborderWidth == Py_None)
722 pborderWidth=ePyObject();
726 pborderColor = PyTuple_GET_ITEM(item, 13);
727 if (pborderColor == Py_None)
728 pborderColor=ePyObject();
731 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
732 int x = PyInt_AsLong(px) + offset.x();
733 int y = PyInt_AsLong(py) + offset.y();
734 int width = PyInt_AsLong(pwidth);
735 int height = PyInt_AsLong(pheight);
736 int flags = PyInt_AsLong(pflags);
737 int fnt = PyInt_AsLong(pfnt);
738 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
740 if (m_font.find(fnt) == m_font.end())
742 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
746 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
751 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
754 painter.setFont(m_font[fnt]);
755 painter.renderText(rect, string, flags);
761 eRect rect(eRect(x, y, width, height));
765 int color = PyInt_AsLong(pborderColor);
766 painter.setForegroundColor(gRGB(color));
768 else if (pforeColor) // reset to normal color
769 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
771 rect.setRect(x, y, width, bwidth);
774 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
777 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
780 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
787 case TYPE_PROGRESS: // Progress
790 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
792 ePyObject px = PyTuple_GET_ITEM(item, 1),
793 py = PyTuple_GET_ITEM(item, 2),
794 pwidth = PyTuple_GET_ITEM(item, 3),
795 pheight = PyTuple_GET_ITEM(item, 4),
796 pfilled_perc = PyTuple_GET_ITEM(item, 5),
797 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
799 if (!(px && py && pwidth && pheight && pfilled_perc))
801 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
807 pborderWidth = PyTuple_GET_ITEM(item, 6);
808 if (pborderWidth == Py_None)
809 pborderWidth = ePyObject();
813 pforeColor = PyTuple_GET_ITEM(item, 7);
814 if (pforeColor == Py_None)
815 pforeColor = ePyObject();
819 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
820 if (pforeColorSelected == Py_None)
821 pforeColorSelected=ePyObject();
825 pbackColor = PyTuple_GET_ITEM(item, 9);
826 if (pbackColor == Py_None)
827 pbackColor=ePyObject();
831 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
832 if (pbackColorSelected == Py_None)
833 pbackColorSelected=ePyObject();
836 int x = PyInt_AsLong(px) + offset.x();
837 int y = PyInt_AsLong(py) + offset.y();
838 int width = PyInt_AsLong(pwidth);
839 int height = PyInt_AsLong(pheight);
840 int filled = PyInt_AsLong(pfilled_perc);
841 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
843 eRect rect(x, y, width, height);
848 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);
921 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip);
924 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
929 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
936 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
939 if (m_buildFunc && PyCallable_Check(m_buildFunc) && items)
945 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
947 Py_XDECREF(m_buildFunc);
949 Py_XINCREF(m_buildFunc);
952 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
954 Py_XDECREF(m_selectableFunc);
956 Py_XINCREF(m_selectableFunc);
959 int eListboxPythonMultiContent::currentCursorSelectable()
961 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
962 if (m_list && cursorValid())
964 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
966 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
967 if (PyTuple_Check(args))
969 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
971 return ret == Py_True;
972 eDebug("call m_selectableFunc failed!!! assume not callable");
975 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
979 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
980 if (PyList_Check(item))
982 item = PyList_GET_ITEM(item, 0);
986 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
993 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1001 void eListboxPythonMultiContent::setItemHeight(int height)
1003 m_itemheight = height;
1005 m_listbox->setItemHeight(height);
1008 void eListboxPythonMultiContent::setList(ePyObject list)
1010 m_old_clip = m_clip = gRegion::invalidRegion();
1011 eListboxPythonStringContent::setList(list);
1014 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1019 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1020 m_clip -= m_old_clip;
1021 m_old_clip = m_clip;
1024 m_old_clip = m_clip = gRegion::invalidRegion();