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 clearRegionHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColor)
519 unsigned int color = PyInt_AsUnsignedLongMask(pbackColor);
520 painter.setBackgroundColor(gRGB(color));
523 else if (local_style)
525 if (local_style && local_style->m_background_color_set)
526 painter.setBackgroundColor(local_style->m_background_color);
527 if (local_style->m_background)
529 if (local_style->m_transparent_background)
530 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
532 painter.blit(local_style->m_background, offset, eRect(), 0);
534 else if (local_style->m_transparent_background)
543 static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColorSelected)
545 if (pbackColorSelected)
547 unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
548 painter.setBackgroundColor(gRGB(color));
551 else if (local_style)
553 if (local_style && local_style->m_background_color_selected_set)
554 painter.setBackgroundColor(local_style->m_background_color_selected);
555 if (local_style->m_background)
557 if (local_style->m_transparent_background)
558 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
560 painter.blit(local_style->m_background, offset, eRect(), 0);
562 else if (local_style->m_transparent_background)
571 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, const ePoint &offset)
573 if (selected && sel_clip.valid())
575 gRegion part = rc - sel_clip;
579 style.setStyle(painter, eWindowStyle::styleListboxNormal);
580 clearRegionHelper(painter, local_style, offset, pbackColor);
584 part = rc & sel_clip;
588 style.setStyle(painter, eWindowStyle::styleListboxSelected);
589 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected);
596 style.setStyle(painter, eWindowStyle::styleListboxSelected);
597 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected);
598 if (local_style && local_style->m_selection)
599 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
603 style.setStyle(painter, eWindowStyle::styleListboxNormal);
604 clearRegionHelper(painter, local_style, offset, pbackColor);
609 if (pforeColorSelected)
611 unsigned int color = PyInt_AsUnsignedLongMask(pforeColorSelected);
612 painter.setForegroundColor(gRGB(color));
614 /* if we have a local foreground color set, use that. */
615 else if (local_style && local_style->m_foreground_color_selected_set)
616 painter.setForegroundColor(local_style->m_foreground_color_selected);
622 unsigned int color = PyInt_AsUnsignedLongMask(pforeColor);
623 painter.setForegroundColor(gRGB(color));
625 /* if we have a local foreground color set, use that. */
626 else if (local_style && local_style->m_foreground_color_set)
627 painter.setForegroundColor(local_style->m_foreground_color);
631 static ePyObject lookupColor(ePyObject color, ePyObject data)
633 if (color == Py_None)
636 if ((!color) && (!data))
639 unsigned int icolor = PyInt_AsUnsignedLongMask(color);
641 /* check if we have the "magic" template color */
642 if ((icolor & 0xFF000000) == 0xFF000000)
644 int index = icolor & 0xFFFFFF;
645 eDebug("[eListboxPythonMultiContent] template color index: %d", index);
646 return PyTuple_GetItem(data, index);
649 if (color == Py_None)
655 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
657 gRegion itemregion(eRect(offset, m_itemsize));
658 eListboxStyle *local_style = 0;
659 eRect sel_clip(m_selection_clip);
660 if (sel_clip.valid())
661 sel_clip.moveBy(offset);
663 /* get local listbox style, if present */
665 local_style = m_listbox->getLocalStyle();
667 painter.clip(itemregion);
668 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset);
670 ePyObject items, buildfunc_ret;
672 if (m_list && cursorValid())
674 /* a multicontent list can be used in two ways:
675 either each item is a list of (TYPE,...)-tuples,
676 or there is a template defined, which is a list of (TYPE,...)-tuples,
677 and the list is an unformatted tuple. The template then references items from the list.
679 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
683 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
685 if (PyTuple_Check(items))
686 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
688 eDebug("items is no tuple");
691 eDebug("buildfunc is not callable");
696 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
702 if (!PyList_Check(items))
704 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
709 if (!PyTuple_Check(items))
711 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
718 /* if we have a template, use the template for the actual formatting.
719 we will later detect that "data" is present, and refer to that, instead
720 of the immediate value. */
729 int size = PyList_Size(items);
730 for (int i = start; i < size; ++i)
732 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
736 eDebug("eListboxPythonMultiContent: ?");
740 if (!PyTuple_Check(item))
742 eDebug("eListboxPythonMultiContent did not receive a tuple.");
746 int size = PyTuple_Size(item);
750 eDebug("eListboxPythonMultiContent receive empty tuple.");
754 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
758 case TYPE_TEXT: // text
761 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
763 ePyObject px = PyTuple_GET_ITEM(item, 1),
764 py = PyTuple_GET_ITEM(item, 2),
765 pwidth = PyTuple_GET_ITEM(item, 3),
766 pheight = PyTuple_GET_ITEM(item, 4),
767 pfnt = PyTuple_GET_ITEM(item, 5),
768 pflags = PyTuple_GET_ITEM(item, 6),
769 pstring = PyTuple_GET_ITEM(item, 7),
770 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
772 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
774 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
779 pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data);
782 pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data);
785 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data);
788 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data);
792 pborderWidth = PyTuple_GET_ITEM(item, 12);
793 if (pborderWidth == Py_None)
794 pborderWidth=ePyObject();
797 pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data);
799 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
800 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
802 /* don't do anything if we have 'None' as string */
803 if (pstring == Py_None)
806 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
807 int x = PyInt_AsLong(px) + offset.x();
808 int y = PyInt_AsLong(py) + offset.y();
809 int width = PyInt_AsLong(pwidth);
810 int height = PyInt_AsLong(pheight);
811 int flags = PyInt_AsLong(pflags);
812 int fnt = PyInt_AsLong(pfnt);
813 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
815 if (m_font.find(fnt) == m_font.end())
817 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
821 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
826 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset);
829 painter.setFont(m_font[fnt]);
830 painter.renderText(rect, string, flags);
836 eRect rect(eRect(x, y, width, height));
840 unsigned int color = PyInt_AsUnsignedLongMask(pborderColor);
841 painter.setForegroundColor(gRGB(color));
844 rect.setRect(x, y, width, bwidth);
847 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
850 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
853 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
860 case TYPE_PROGRESS: // Progress
863 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
865 ePyObject px = PyTuple_GET_ITEM(item, 1),
866 py = PyTuple_GET_ITEM(item, 2),
867 pwidth = PyTuple_GET_ITEM(item, 3),
868 pheight = PyTuple_GET_ITEM(item, 4),
869 pfilled_perc = PyTuple_GET_ITEM(item, 5),
870 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
872 if (!(px && py && pwidth && pheight && pfilled_perc))
874 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
880 pborderWidth = PyTuple_GET_ITEM(item, 6);
881 if (pborderWidth == Py_None)
882 pborderWidth = ePyObject();
886 pforeColor = PyTuple_GET_ITEM(item, 7);
887 if (pforeColor == Py_None)
888 pforeColor = ePyObject();
892 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
893 if (pforeColorSelected == Py_None)
894 pforeColorSelected=ePyObject();
898 pbackColor = PyTuple_GET_ITEM(item, 9);
899 if (pbackColor == Py_None)
900 pbackColor=ePyObject();
904 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
905 if (pbackColorSelected == Py_None)
906 pbackColorSelected=ePyObject();
909 int x = PyInt_AsLong(px) + offset.x();
910 int y = PyInt_AsLong(py) + offset.y();
911 int width = PyInt_AsLong(pwidth);
912 int height = PyInt_AsLong(pheight);
913 int filled = PyInt_AsLong(pfilled_perc);
915 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
916 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
918 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
920 eRect rect(x, y, width, height);
925 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset);
929 rect.setRect(x, y, width, bwidth);
932 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
935 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
938 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
942 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
949 case TYPE_PIXMAP_ALPHATEST:
950 case TYPE_PIXMAP: // pixmap
953 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
956 ePyObject px = PyTuple_GET_ITEM(item, 1),
957 py = PyTuple_GET_ITEM(item, 2),
958 pwidth = PyTuple_GET_ITEM(item, 3),
959 pheight = PyTuple_GET_ITEM(item, 4),
960 ppixmap = PyTuple_GET_ITEM(item, 5),
961 pbackColor, pbackColorSelected;
963 if (!(px && py && pwidth && pheight && ppixmap))
965 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
969 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
970 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
972 /* don't do anything if we have 'None' as pixmap */
973 if (ppixmap == Py_None)
976 int x = PyInt_AsLong(px) + offset.x();
977 int y = PyInt_AsLong(py) + offset.y();
978 int width = PyInt_AsLong(pwidth);
979 int height = PyInt_AsLong(pheight);
980 ePtr<gPixmap> pixmap;
981 if (SwigFromPython(pixmap, ppixmap))
983 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
988 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
991 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
993 eRect rect(x, y, width, height);
998 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset);
1001 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
1006 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1012 if (selected && (sel_clip.valid() || (!local_style || !local_style->m_selection)))
1013 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1017 Py_DECREF(buildfunc_ret);
1022 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1024 Py_XDECREF(m_buildFunc);
1026 Py_XINCREF(m_buildFunc);
1029 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1031 Py_XDECREF(m_selectableFunc);
1032 m_selectableFunc=cb;
1033 Py_XINCREF(m_selectableFunc);
1036 int eListboxPythonMultiContent::currentCursorSelectable()
1038 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1039 if (m_list && cursorValid())
1041 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1043 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1044 if (PyTuple_Check(args))
1046 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1049 bool retval = ret == Py_True;
1053 eDebug("call m_selectableFunc failed!!! assume not callable");
1056 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1060 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1061 if (PyList_Check(item))
1063 item = PyList_GET_ITEM(item, 0);
1064 if (item != Py_None)
1066 } else if (PyTuple_Check(item))
1068 item = PyTuple_GET_ITEM(item, 0);
1069 if (item != Py_None)
1072 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1079 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1087 void eListboxPythonMultiContent::setItemHeight(int height)
1089 m_itemheight = height;
1091 m_listbox->setItemHeight(height);
1094 void eListboxPythonMultiContent::setList(ePyObject list)
1096 m_old_clip = m_clip = gRegion::invalidRegion();
1097 eListboxPythonStringContent::setList(list);
1100 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1105 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1106 m_clip -= m_old_clip;
1107 m_old_clip = m_clip;
1110 m_old_clip = m_clip = gRegion::invalidRegion();
1113 void eListboxPythonMultiContent::entryRemoved(int idx)
1116 m_listbox->entryRemoved(idx);
1119 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1121 m_template = tmplate;