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 int left=0, right=0, last=-1;
436 for (int i = 0; i < entries; ++i)
438 ePyObject entry = PyList_GET_ITEM(plist, i);
439 int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
441 if ((num < 0) || (num >= glyphs))
442 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
445 if (last+1 != num && last != -1) {
446 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
449 para->setGlyphFlag(num, GS_INVERT);
450 bbox = para->getGlyphBBox(num);
451 if (last+1 != num || last == -1)
453 right = bbox.left() + bbox.width();
456 /* entry is borrowed */
459 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
462 painter.renderPara(para, ePoint(0, 0));
463 /* pvalue is borrowed */
464 /* plist is 0 or borrowed */
467 /* type is borrowed */
469 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
474 if (selected && (!local_style || !local_style->m_selection))
475 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
481 int eListboxPythonConfigContent::currentCursorSelectable()
483 return eListboxPythonStringContent::currentCursorSelectable();
486 //////////////////////////////////////
488 /* todo: make a real infrastructure here! */
489 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
491 eListboxPythonMultiContent::eListboxPythonMultiContent()
492 :m_clip(gRegion::invalidRegion()), m_old_clip(gRegion::invalidRegion())
496 eListboxPythonMultiContent::~eListboxPythonMultiContent()
498 Py_XDECREF(m_buildFunc);
499 Py_XDECREF(m_selectableFunc);
502 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
504 m_selection_clip = rect;
506 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
511 if (update && m_listbox)
512 m_listbox->entryChanged(m_cursor);
515 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)
517 if (selected && sel_clip.valid())
519 gRegion part = rc - sel_clip;
523 style.setStyle(painter, eWindowStyle::styleListboxNormal);
526 int color = PyInt_AsLong(pbackColor);
527 painter.setBackgroundColor(gRGB(color));
528 } // transparent background?
529 // if we have a local background color set, use that.
530 else if (local_style && local_style->m_background_color_set)
531 painter.setBackgroundColor(local_style->m_background_color);
532 if (!pbackColor && local_style && local_style->m_transparent_background)
539 part = rc & sel_clip;
543 style.setStyle(painter, eWindowStyle::styleListboxSelected);
544 if (pbackColorSelected)
546 int color = PyInt_AsLong(pbackColorSelected);
547 painter.setBackgroundColor(gRGB(color));
549 else if (local_style && local_style->m_background_color_selected_set)
550 painter.setBackgroundColor(local_style->m_background_color_selected);
560 style.setStyle(painter, eWindowStyle::styleListboxSelected);
561 if (pbackColorSelected)
563 int color = PyInt_AsLong(pbackColorSelected);
564 painter.setBackgroundColor(gRGB(color));
566 else if (local_style && local_style->m_background_color_selected_set)
567 painter.setBackgroundColor(local_style->m_background_color_selected);
572 style.setStyle(painter, eWindowStyle::styleListboxNormal);
575 int color = PyInt_AsLong(pbackColor);
576 painter.setBackgroundColor(gRGB(color));
577 }/* if we have a local background color set, use that. */
578 else if (local_style && local_style->m_background_color_set)
579 painter.setBackgroundColor(local_style->m_background_color);
580 /* if we have no transparent background */
581 if (!pbackColor && local_style && local_style->m_transparent_background)
589 if (pforeColorSelected)
591 int color = PyInt_AsLong(pforeColorSelected);
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_selected_set)
596 painter.setForegroundColor(local_style->m_foreground_color_selected);
602 int color = PyInt_AsLong(pforeColor);
603 painter.setForegroundColor(gRGB(color));
605 /* if we have a local foreground color set, use that. */
606 else if (local_style && local_style->m_foreground_color_set)
607 painter.setForegroundColor(local_style->m_foreground_color);
611 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
613 gRegion itemregion(eRect(offset, m_itemsize));
614 eListboxStyle *local_style = 0;
615 eRect sel_clip(m_selection_clip);
616 if (sel_clip.valid())
617 sel_clip.moveBy(offset);
619 /* get local listbox style, if present */
621 local_style = m_listbox->getLocalStyle();
623 painter.clip(itemregion);
624 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip);
626 ePyObject items, buildfunc_ret;
628 if (m_list && cursorValid())
630 /* a multicontent list can be used in two ways:
631 either each item is a list of (TYPE,...)-tuples,
632 or there is a template defined, which is a list of (TYPE,...)-tuples,
633 and the list is an unformatted tuple. The template then references items from the list.
635 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
639 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
641 if (PyTuple_Check(items))
642 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
644 eDebug("items is no tuple");
647 eDebug("buildfunc is not callable");
652 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
658 if (!PyList_Check(items))
660 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
665 if (!PyTuple_Check(items))
667 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
674 /* if we have a template, use the template for the actual formatting.
675 we will later detect that "data" is present, and refer to that, instead
676 of the immediate value. */
685 int size = PyList_Size(items);
686 for (int i = start; i < size; ++i)
688 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
692 eDebug("eListboxPythonMultiContent: ?");
696 if (!PyTuple_Check(item))
698 eDebug("eListboxPythonMultiContent did not receive a tuple.");
702 int size = PyTuple_Size(item);
706 eDebug("eListboxPythonMultiContent receive empty tuple.");
710 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
714 case TYPE_TEXT: // text
717 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
719 ePyObject px = PyTuple_GET_ITEM(item, 1),
720 py = PyTuple_GET_ITEM(item, 2),
721 pwidth = PyTuple_GET_ITEM(item, 3),
722 pheight = PyTuple_GET_ITEM(item, 4),
723 pfnt = PyTuple_GET_ITEM(item, 5),
724 pflags = PyTuple_GET_ITEM(item, 6),
725 pstring = PyTuple_GET_ITEM(item, 7),
726 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
728 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
730 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
736 pforeColor = PyTuple_GET_ITEM(item, 8);
737 if (pforeColor == Py_None)
738 pforeColor=ePyObject();
742 pforeColorSelected = PyTuple_GET_ITEM(item, 9);
743 if (pforeColorSelected == Py_None)
744 pforeColorSelected=ePyObject();
748 pbackColor = PyTuple_GET_ITEM(item, 10);
749 if (pbackColor == Py_None)
750 pbackColor=ePyObject();
754 pbackColorSelected = PyTuple_GET_ITEM(item, 11);
755 if (pbackColorSelected == Py_None)
756 pbackColorSelected=ePyObject();
760 pborderWidth = PyTuple_GET_ITEM(item, 12);
761 if (pborderWidth == Py_None)
762 pborderWidth=ePyObject();
766 pborderColor = PyTuple_GET_ITEM(item, 13);
767 if (pborderColor == Py_None)
768 pborderColor=ePyObject();
771 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
772 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
774 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
775 int x = PyInt_AsLong(px) + offset.x();
776 int y = PyInt_AsLong(py) + offset.y();
777 int width = PyInt_AsLong(pwidth);
778 int height = PyInt_AsLong(pheight);
779 int flags = PyInt_AsLong(pflags);
780 int fnt = PyInt_AsLong(pfnt);
781 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
783 if (m_font.find(fnt) == m_font.end())
785 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
789 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
794 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
797 painter.setFont(m_font[fnt]);
798 painter.renderText(rect, string, flags);
804 eRect rect(eRect(x, y, width, height));
808 int color = PyInt_AsLong(pborderColor);
809 painter.setForegroundColor(gRGB(color));
812 rect.setRect(x, y, width, bwidth);
815 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
818 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
821 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
828 case TYPE_PROGRESS: // Progress
831 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
833 ePyObject px = PyTuple_GET_ITEM(item, 1),
834 py = PyTuple_GET_ITEM(item, 2),
835 pwidth = PyTuple_GET_ITEM(item, 3),
836 pheight = PyTuple_GET_ITEM(item, 4),
837 pfilled_perc = PyTuple_GET_ITEM(item, 5),
838 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
840 if (!(px && py && pwidth && pheight && pfilled_perc))
842 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
848 pborderWidth = PyTuple_GET_ITEM(item, 6);
849 if (pborderWidth == Py_None)
850 pborderWidth = ePyObject();
854 pforeColor = PyTuple_GET_ITEM(item, 7);
855 if (pforeColor == Py_None)
856 pforeColor = ePyObject();
860 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
861 if (pforeColorSelected == Py_None)
862 pforeColorSelected=ePyObject();
866 pbackColor = PyTuple_GET_ITEM(item, 9);
867 if (pbackColor == Py_None)
868 pbackColor=ePyObject();
872 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
873 if (pbackColorSelected == Py_None)
874 pbackColorSelected=ePyObject();
877 int x = PyInt_AsLong(px) + offset.x();
878 int y = PyInt_AsLong(py) + offset.y();
879 int width = PyInt_AsLong(pwidth);
880 int height = PyInt_AsLong(pheight);
881 int filled = PyInt_AsLong(pfilled_perc);
883 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
884 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
886 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
888 eRect rect(x, y, width, height);
893 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
897 rect.setRect(x, y, width, bwidth);
900 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
903 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
906 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
910 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
917 case TYPE_PIXMAP_ALPHATEST:
918 case TYPE_PIXMAP: // pixmap
921 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
924 ePyObject px = PyTuple_GET_ITEM(item, 1),
925 py = PyTuple_GET_ITEM(item, 2),
926 pwidth = PyTuple_GET_ITEM(item, 3),
927 pheight = PyTuple_GET_ITEM(item, 4),
928 ppixmap = PyTuple_GET_ITEM(item, 5),
929 pbackColor, pbackColorSelected;
931 if (!(px && py && pwidth && pheight && ppixmap))
933 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
937 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
938 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
940 int x = PyInt_AsLong(px) + offset.x();
941 int y = PyInt_AsLong(py) + offset.y();
942 int width = PyInt_AsLong(pwidth);
943 int height = PyInt_AsLong(pheight);
944 ePtr<gPixmap> pixmap;
945 if (SwigFromPython(pixmap, ppixmap))
947 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
953 pbackColor = PyTuple_GET_ITEM(item, 6);
954 if (pbackColor == Py_None)
955 pbackColor=ePyObject();
959 pbackColorSelected = PyTuple_GET_ITEM(item, 7);
960 if (pbackColorSelected == Py_None)
961 pbackColorSelected=ePyObject();
964 eRect rect(x, y, width, height);
969 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip);
972 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
977 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
984 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
988 Py_DECREF(buildfunc_ret);
993 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
995 Py_XDECREF(m_buildFunc);
997 Py_XINCREF(m_buildFunc);
1000 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1002 Py_XDECREF(m_selectableFunc);
1003 m_selectableFunc=cb;
1004 Py_XINCREF(m_selectableFunc);
1007 int eListboxPythonMultiContent::currentCursorSelectable()
1009 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1010 if (m_list && cursorValid())
1012 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1014 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1015 if (PyTuple_Check(args))
1017 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1020 bool retval = ret == Py_True;
1024 eDebug("call m_selectableFunc failed!!! assume not callable");
1027 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1031 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1032 if (PyList_Check(item))
1034 item = PyList_GET_ITEM(item, 0);
1035 if (item != Py_None)
1037 } else if (PyTuple_Check(item))
1039 item = PyTuple_GET_ITEM(item, 0);
1040 if (item != Py_None)
1043 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1050 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1058 void eListboxPythonMultiContent::setItemHeight(int height)
1060 m_itemheight = height;
1062 m_listbox->setItemHeight(height);
1065 void eListboxPythonMultiContent::setList(ePyObject list)
1067 m_old_clip = m_clip = gRegion::invalidRegion();
1068 eListboxPythonStringContent::setList(list);
1071 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1076 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1077 m_clip -= m_old_clip;
1078 m_old_clip = m_clip;
1081 m_old_clip = m_clip = gRegion::invalidRegion();
1084 void eListboxPythonMultiContent::entryRemoved(int idx)
1087 m_listbox->entryRemoved(idx);
1090 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1092 m_template = tmplate;