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(pforeColorSelected);
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));
769 rect.setRect(x, y, width, bwidth);
772 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
775 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
778 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
785 case TYPE_PROGRESS: // Progress
788 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
790 ePyObject px = PyTuple_GET_ITEM(item, 1),
791 py = PyTuple_GET_ITEM(item, 2),
792 pwidth = PyTuple_GET_ITEM(item, 3),
793 pheight = PyTuple_GET_ITEM(item, 4),
794 pfilled_perc = PyTuple_GET_ITEM(item, 5),
795 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
797 if (!(px && py && pwidth && pheight && pfilled_perc))
799 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
805 pborderWidth = PyTuple_GET_ITEM(item, 6);
806 if (pborderWidth == Py_None)
807 pborderWidth = ePyObject();
811 pforeColor = PyTuple_GET_ITEM(item, 7);
812 if (pforeColor == Py_None)
813 pforeColor = ePyObject();
817 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
818 if (pforeColorSelected == Py_None)
819 pforeColorSelected=ePyObject();
823 pbackColor = PyTuple_GET_ITEM(item, 9);
824 if (pbackColor == Py_None)
825 pbackColor=ePyObject();
829 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
830 if (pbackColorSelected == Py_None)
831 pbackColorSelected=ePyObject();
834 int x = PyInt_AsLong(px) + offset.x();
835 int y = PyInt_AsLong(py) + offset.y();
836 int width = PyInt_AsLong(pwidth);
837 int height = PyInt_AsLong(pheight);
838 int filled = PyInt_AsLong(pfilled_perc);
839 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
841 eRect rect(x, y, width, height);
846 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
850 rect.setRect(x, y, width, bwidth);
853 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
856 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
859 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
863 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
870 case TYPE_PIXMAP_ALPHATEST:
871 case TYPE_PIXMAP: // pixmap
874 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
877 ePyObject px = PyTuple_GET_ITEM(item, 1),
878 py = PyTuple_GET_ITEM(item, 2),
879 pwidth = PyTuple_GET_ITEM(item, 3),
880 pheight = PyTuple_GET_ITEM(item, 4),
881 ppixmap = PyTuple_GET_ITEM(item, 5),
882 pbackColor, pbackColorSelected;
884 if (!(px && py && pwidth && pheight && ppixmap))
886 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
890 int x = PyInt_AsLong(px) + offset.x();
891 int y = PyInt_AsLong(py) + offset.y();
892 int width = PyInt_AsLong(pwidth);
893 int height = PyInt_AsLong(pheight);
894 ePtr<gPixmap> pixmap;
895 if (SwigFromPython(pixmap, ppixmap))
897 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
903 pbackColor = PyTuple_GET_ITEM(item, 6);
904 if (pbackColor == Py_None)
905 pbackColor=ePyObject();
909 pbackColorSelected = PyTuple_GET_ITEM(item, 7);
910 if (pbackColorSelected == Py_None)
911 pbackColorSelected=ePyObject();
914 eRect rect(x, y, width, height);
919 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip);
922 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
927 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
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();