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);
266 m_listbox->invalidate();
270 //////////////////////////////////////
272 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
274 ePtr<gFont> fnt = new gFont("Regular", 20);
275 ePtr<gFont> fnt2 = new gFont("Regular", 16);
276 eRect itemrect(offset, m_itemsize);
277 eListboxStyle *local_style = 0;
279 painter.clip(itemrect);
280 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
282 /* get local listbox style, if present */
284 local_style = m_listbox->getLocalStyle();
290 /* if we have a local background color set, use that. */
291 if (local_style->m_background_color_selected_set)
292 painter.setBackgroundColor(local_style->m_background_color_selected);
293 /* same for foreground */
294 if (local_style->m_foreground_color_selected_set)
295 painter.setForegroundColor(local_style->m_foreground_color_selected);
299 /* if we have a local background color set, use that. */
300 if (local_style->m_background_color_set)
301 painter.setBackgroundColor(local_style->m_background_color);
302 /* same for foreground */
303 if (local_style->m_foreground_color_set)
304 painter.setForegroundColor(local_style->m_foreground_color);
308 if (!local_style || !local_style->m_transparent_background)
309 /* if we have no transparent background */
311 /* blit background picture, if available (otherwise, clear only) */
312 if (local_style && local_style->m_background)
313 painter.blit(local_style->m_background, offset, eRect(), 0);
318 if (local_style->m_background)
319 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
320 else if (selected && !local_style->m_selection)
324 if (m_list && cursorValid())
326 /* get current list item */
327 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
328 ePyObject text, value;
329 painter.setFont(fnt);
331 if (selected && local_style && local_style->m_selection)
332 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
334 /* the first tuple element is a string for the left side.
335 the second one will be called, and the result shall be an tuple.
338 the first one is the type (string).
339 the second one is the value. */
340 if (PyTuple_Check(item))
342 /* handle left part. get item from tuple, convert to string, display. */
344 text = PyTuple_GET_ITEM(item, 0);
345 text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
346 const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
347 eSize item_left = eSize(m_seperation, m_itemsize.height());
348 eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
349 painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
352 /* when we have no label, align value to the left. (FIXME:
353 don't we want to specifiy this individually?) */
354 int value_alignment_left = !*string;
356 /* now, handle the value. get 2nd part from tuple*/
357 value = PyTuple_GET_ITEM(item, 1);
360 ePyObject args = PyTuple_New(1);
361 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
363 /* CallObject will call __call__ which should return the value tuple */
364 value = PyObject_CallObject(value, args);
366 if (PyErr_Occurred())
370 /* the PyInt was stolen. */
373 /* check if this is really a tuple */
374 if (value && PyTuple_Check(value))
376 /* convert type to string */
377 ePyObject type = PyTuple_GET_ITEM(value, 0);
378 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
382 if (!strcmp(atype, "text"))
384 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
385 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
386 painter.setFont(fnt2);
387 if (value_alignment_left)
388 painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
390 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
392 /* pvalue is borrowed */
393 } else if (!strcmp(atype, "slider"))
395 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
396 ePyObject psize = PyTuple_GET_ITEM(value, 2);
398 /* convert value to Long. fallback to -1 on error. */
399 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
400 int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
402 /* calc. slider length */
403 int width = item_right.width() * value / size;
404 int height = item_right.height();
408 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
409 //hack - make it customizable
410 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
412 /* pvalue is borrowed */
413 } else if (!strcmp(atype, "mtext"))
415 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
416 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
417 int xoffs = value_alignment_left ? 0 : m_seperation;
418 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
420 para->renderString(text, 0);
421 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
422 int glyphs = para->size();
426 if (PyTuple_Size(value) >= 3)
427 plist = PyTuple_GET_ITEM(value, 2);
431 if (plist && PyList_Check(plist))
432 entries = PyList_Size(plist);
434 for (int i = 0; i < entries; ++i)
436 ePyObject entry = PyList_GET_ITEM(plist, i);
437 int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
439 if ((num < 0) || (num >= glyphs))
440 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
443 para->setGlyphFlag(num, GS_INVERT);
445 bbox = para->getGlyphBBox(num);
446 bbox = eRect(bbox.left(), offset.y(), bbox.width(), m_itemsize.height());
449 /* entry is borrowed */
452 painter.renderPara(para, ePoint(0, 0));
453 /* pvalue is borrowed */
454 /* plist is 0 or borrowed */
457 /* type is borrowed */
459 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
460 /* value is borrowed */
463 if (selected && (!local_style || !local_style->m_selection))
464 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
470 int eListboxPythonConfigContent::currentCursorSelectable()
472 return eListboxPythonStringContent::currentCursorSelectable();
475 //////////////////////////////////////
477 /* todo: make a real infrastructure here! */
478 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
480 eListboxPythonMultiContent::eListboxPythonMultiContent()
481 :m_clip(gRegion::invalidRegion()), m_old_clip(gRegion::invalidRegion())
485 eListboxPythonMultiContent::~eListboxPythonMultiContent()
487 Py_XDECREF(m_buildFunc);
488 Py_XDECREF(m_selectableFunc);
491 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
493 m_selection_clip = rect;
495 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
500 if (update && m_listbox)
501 m_listbox->entryChanged(m_cursor);
504 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)
506 if (selected && sel_clip.valid())
508 gRegion part = rc - sel_clip;
512 style.setStyle(painter, eWindowStyle::styleListboxNormal);
515 int color = PyInt_AsLong(pbackColor);
516 painter.setBackgroundColor(gRGB(color));
517 } // transparent background?
518 // if we have a local background color set, use that.
519 else if (local_style && local_style->m_background_color_set)
520 painter.setBackgroundColor(local_style->m_background_color);
521 if (!pbackColor && local_style && local_style->m_transparent_background)
528 part = rc & sel_clip;
532 style.setStyle(painter, eWindowStyle::styleListboxSelected);
533 if (pbackColorSelected)
535 int color = PyInt_AsLong(pbackColorSelected);
536 painter.setBackgroundColor(gRGB(color));
538 else if (local_style && local_style->m_background_color_selected_set)
539 painter.setBackgroundColor(local_style->m_background_color_selected);
549 style.setStyle(painter, eWindowStyle::styleListboxSelected);
550 if (pbackColorSelected)
552 int color = PyInt_AsLong(pbackColorSelected);
553 painter.setBackgroundColor(gRGB(color));
555 else if (local_style && local_style->m_background_color_selected_set)
556 painter.setBackgroundColor(local_style->m_background_color_selected);
561 style.setStyle(painter, eWindowStyle::styleListboxNormal);
564 int color = PyInt_AsLong(pbackColor);
565 painter.setBackgroundColor(gRGB(color));
566 }/* if we have a local background color set, use that. */
567 else if (local_style && local_style->m_background_color_set)
568 painter.setBackgroundColor(local_style->m_background_color);
569 /* if we have no transparent background */
570 if (!pbackColor && local_style && local_style->m_transparent_background)
578 if (pforeColorSelected)
580 int color = PyInt_AsLong(pforeColorSelected);
581 painter.setForegroundColor(gRGB(color));
583 /* if we have a local foreground color set, use that. */
584 else if (local_style && local_style->m_foreground_color_selected_set)
585 painter.setForegroundColor(local_style->m_foreground_color_selected);
591 int color = PyInt_AsLong(pforeColor);
592 painter.setForegroundColor(gRGB(color));
594 /* if we have a local foreground color set, use that. */
595 else if (local_style && local_style->m_foreground_color_set)
596 painter.setForegroundColor(local_style->m_foreground_color);
600 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
602 gRegion itemregion(eRect(offset, m_itemsize));
603 eListboxStyle *local_style = 0;
604 eRect sel_clip(m_selection_clip);
605 if (sel_clip.valid())
606 sel_clip.moveBy(offset);
608 /* get local listbox style, if present */
610 local_style = m_listbox->getLocalStyle();
612 painter.clip(itemregion);
613 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip);
617 if (m_list && cursorValid())
619 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
623 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
625 if (PyTuple_Check(items))
626 items = PyObject_CallObject(m_buildFunc, items);
628 eDebug("items is no tuple");
631 eDebug("buildfunc is not callable");
636 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
640 if (!PyList_Check(items))
642 eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
646 int size = PyList_Size(items);
647 for (int i = 1; i < size; ++i)
649 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
653 eDebug("eListboxPythonMultiContent: ?");
657 if (!PyTuple_Check(item))
659 eDebug("eListboxPythonMultiContent did not receive a tuple.");
663 int size = PyTuple_Size(item);
667 eDebug("eListboxPythonMultiContent receive empty tuple.");
671 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
675 case TYPE_TEXT: // text
678 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
680 ePyObject px = PyTuple_GET_ITEM(item, 1),
681 py = PyTuple_GET_ITEM(item, 2),
682 pwidth = PyTuple_GET_ITEM(item, 3),
683 pheight = PyTuple_GET_ITEM(item, 4),
684 pfnt = PyTuple_GET_ITEM(item, 5),
685 pflags = PyTuple_GET_ITEM(item, 6),
686 pstring = PyTuple_GET_ITEM(item, 7),
687 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
689 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
691 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
697 pforeColor = PyTuple_GET_ITEM(item, 8);
698 if (pforeColor == Py_None)
699 pforeColor=ePyObject();
703 pforeColorSelected = PyTuple_GET_ITEM(item, 9);
704 if (pforeColorSelected == Py_None)
705 pforeColorSelected=ePyObject();
709 pbackColor = PyTuple_GET_ITEM(item, 10);
710 if (pbackColor == Py_None)
711 pbackColor=ePyObject();
715 pbackColorSelected = PyTuple_GET_ITEM(item, 11);
716 if (pbackColorSelected == Py_None)
717 pbackColorSelected=ePyObject();
721 pborderWidth = PyTuple_GET_ITEM(item, 12);
722 if (pborderWidth == Py_None)
723 pborderWidth=ePyObject();
727 pborderColor = PyTuple_GET_ITEM(item, 13);
728 if (pborderColor == Py_None)
729 pborderColor=ePyObject();
732 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
733 int x = PyInt_AsLong(px) + offset.x();
734 int y = PyInt_AsLong(py) + offset.y();
735 int width = PyInt_AsLong(pwidth);
736 int height = PyInt_AsLong(pheight);
737 int flags = PyInt_AsLong(pflags);
738 int fnt = PyInt_AsLong(pfnt);
739 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
741 if (m_font.find(fnt) == m_font.end())
743 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
747 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
752 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
755 painter.setFont(m_font[fnt]);
756 painter.renderText(rect, string, flags);
762 eRect rect(eRect(x, y, width, height));
766 int color = PyInt_AsLong(pborderColor);
767 painter.setForegroundColor(gRGB(color));
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);
847 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
851 rect.setRect(x, y, width, bwidth);
854 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
857 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
860 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
864 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
871 case TYPE_PIXMAP_ALPHATEST:
872 case TYPE_PIXMAP: // pixmap
875 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
878 ePyObject px = PyTuple_GET_ITEM(item, 1),
879 py = PyTuple_GET_ITEM(item, 2),
880 pwidth = PyTuple_GET_ITEM(item, 3),
881 pheight = PyTuple_GET_ITEM(item, 4),
882 ppixmap = PyTuple_GET_ITEM(item, 5),
883 pbackColor, pbackColorSelected;
885 if (!(px && py && pwidth && pheight && ppixmap))
887 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
891 int x = PyInt_AsLong(px) + offset.x();
892 int y = PyInt_AsLong(py) + offset.y();
893 int width = PyInt_AsLong(pwidth);
894 int height = PyInt_AsLong(pheight);
895 ePtr<gPixmap> pixmap;
896 if (SwigFromPython(pixmap, ppixmap))
898 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
904 pbackColor = PyTuple_GET_ITEM(item, 6);
905 if (pbackColor == Py_None)
906 pbackColor=ePyObject();
910 pbackColorSelected = PyTuple_GET_ITEM(item, 7);
911 if (pbackColorSelected == Py_None)
912 pbackColorSelected=ePyObject();
915 eRect rect(x, y, width, height);
920 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip);
923 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
928 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
935 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
938 if (m_buildFunc && PyCallable_Check(m_buildFunc) && items)
944 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
946 Py_XDECREF(m_buildFunc);
948 Py_XINCREF(m_buildFunc);
951 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
953 Py_XDECREF(m_selectableFunc);
955 Py_XINCREF(m_selectableFunc);
958 int eListboxPythonMultiContent::currentCursorSelectable()
960 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
961 if (m_list && cursorValid())
963 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
965 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
966 if (PyTuple_Check(args))
968 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
970 return ret == Py_True;
971 eDebug("call m_selectableFunc failed!!! assume not callable");
974 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
978 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
979 if (PyList_Check(item))
981 item = PyList_GET_ITEM(item, 0);
985 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
992 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1000 void eListboxPythonMultiContent::setItemHeight(int height)
1002 m_itemheight = height;
1004 m_listbox->setItemHeight(height);
1007 void eListboxPythonMultiContent::setList(ePyObject list)
1009 m_old_clip = m_clip = gRegion::invalidRegion();
1010 eListboxPythonStringContent::setList(list);
1013 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1018 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1019 m_clip -= m_old_clip;
1020 m_old_clip = m_clip;
1023 m_old_clip = m_clip = gRegion::invalidRegion();
1026 void eListboxPythonMultiContent::entryRemoved(int idx)
1029 m_listbox->entryRemoved(idx);