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;
145 bool cursorValid = this->cursorValid();
147 /* get local listbox style, if present */
149 local_style = m_listbox->getLocalStyle();
155 /* if we have a local background color set, use that. */
156 if (local_style->m_background_color_selected_set)
157 painter.setBackgroundColor(local_style->m_background_color_selected);
158 /* same for foreground */
159 if (local_style->m_foreground_color_selected_set)
160 painter.setForegroundColor(local_style->m_foreground_color_selected);
164 /* if we have a local background color set, use that. */
165 if (local_style->m_background_color_set)
166 painter.setBackgroundColor(local_style->m_background_color);
167 /* same for foreground */
168 if (local_style->m_foreground_color_set)
169 painter.setForegroundColor(local_style->m_foreground_color);
173 /* if we have no transparent background */
174 if (!local_style || !local_style->m_transparent_background)
176 /* blit background picture, if available (otherwise, clear only) */
177 if (local_style && local_style->m_background && cursorValid)
178 painter.blit(local_style->m_background, offset, eRect(), 0);
183 if (local_style->m_background && cursorValid)
184 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
185 else if (selected && !local_style->m_selection)
189 if (m_list && cursorValid)
192 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
193 painter.setFont(fnt);
195 /* the user can supply tuples, in this case the first one will be displayed. */
196 if (PyTuple_Check(item))
198 if (PyTuple_Size(item) == 1)
200 item = PyTuple_GET_ITEM(item, 0);
203 if (selected && local_style && local_style->m_selection)
204 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
209 int half_height = m_itemsize.height() / 2;
210 painter.fill(eRect(offset.x() + half_height, offset.y() + half_height - 2, m_itemsize.width() - m_itemsize.height(), 4));
213 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
214 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
216 painter.setForegroundColor(gRGB(0x808080));
217 painter.renderText(eRect(text_offset, m_itemsize), string);
220 if (selected && (!local_style || !local_style->m_selection))
221 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
227 void eListboxPythonStringContent::setList(ePyObject list)
230 if (!PyList_Check(list))
232 m_list = ePyObject();
240 m_listbox->entryReset(false);
243 PyObject *eListboxPythonStringContent::getCurrentSelection()
245 if (!(m_list && cursorValid()))
248 ePyObject r = PyList_GET_ITEM(m_list, m_cursor);
253 void eListboxPythonStringContent::invalidateEntry(int index)
256 m_listbox->entryChanged(index);
259 void eListboxPythonStringContent::invalidate()
265 m_listbox->moveSelectionTo(s?s-1:0);
267 m_listbox->invalidate();
271 //////////////////////////////////////
273 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
275 ePtr<gFont> fnt = new gFont("Regular", 20);
276 ePtr<gFont> fnt2 = new gFont("Regular", 16);
277 eRect itemrect(offset, m_itemsize);
278 eListboxStyle *local_style = 0;
279 bool cursorValid = this->cursorValid();
281 painter.clip(itemrect);
282 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
284 /* get local listbox style, if present */
286 local_style = m_listbox->getLocalStyle();
292 /* if we have a local background color set, use that. */
293 if (local_style->m_background_color_selected_set)
294 painter.setBackgroundColor(local_style->m_background_color_selected);
295 /* same for foreground */
296 if (local_style->m_foreground_color_selected_set)
297 painter.setForegroundColor(local_style->m_foreground_color_selected);
301 /* if we have a local background color set, use that. */
302 if (local_style->m_background_color_set)
303 painter.setBackgroundColor(local_style->m_background_color);
304 /* same for foreground */
305 if (local_style->m_foreground_color_set)
306 painter.setForegroundColor(local_style->m_foreground_color);
310 if (!local_style || !local_style->m_transparent_background)
311 /* if we have no transparent background */
313 /* blit background picture, if available (otherwise, clear only) */
314 if (local_style && local_style->m_background && cursorValid)
315 painter.blit(local_style->m_background, offset, eRect(), 0);
320 if (local_style->m_background && cursorValid)
321 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
322 else if (selected && !local_style->m_selection)
326 if (m_list && cursorValid)
328 /* get current list item */
329 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
330 ePyObject text, value;
331 painter.setFont(fnt);
333 if (selected && local_style && local_style->m_selection)
334 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
336 /* the first tuple element is a string for the left side.
337 the second one will be called, and the result shall be an tuple.
340 the first one is the type (string).
341 the second one is the value. */
342 if (PyTuple_Check(item))
344 /* handle left part. get item from tuple, convert to string, display. */
346 text = PyTuple_GET_ITEM(item, 0);
347 text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
348 const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
349 eSize item_left = eSize(m_seperation, m_itemsize.height());
350 eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
351 painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
354 /* when we have no label, align value to the left. (FIXME:
355 don't we want to specifiy this individually?) */
356 int value_alignment_left = !*string;
358 /* now, handle the value. get 2nd part from tuple*/
359 value = PyTuple_GET_ITEM(item, 1);
362 ePyObject args = PyTuple_New(1);
363 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
365 /* CallObject will call __call__ which should return the value tuple */
366 value = PyObject_CallObject(value, args);
368 if (PyErr_Occurred())
372 /* the PyInt was stolen. */
375 /* check if this is really a tuple */
376 if (value && PyTuple_Check(value))
378 /* convert type to string */
379 ePyObject type = PyTuple_GET_ITEM(value, 0);
380 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
384 if (!strcmp(atype, "text"))
386 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
387 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
388 painter.setFont(fnt2);
389 if (value_alignment_left)
390 painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
392 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
394 /* pvalue is borrowed */
395 } else if (!strcmp(atype, "slider"))
397 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
398 ePyObject psize = PyTuple_GET_ITEM(value, 2);
400 /* convert value to Long. fallback to -1 on error. */
401 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
402 int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
404 /* calc. slider length */
405 int width = item_right.width() * value / size;
406 int height = item_right.height();
410 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
411 //hack - make it customizable
412 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
414 /* pvalue is borrowed */
415 } else if (!strcmp(atype, "mtext"))
417 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
418 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
419 int xoffs = value_alignment_left ? 0 : m_seperation;
420 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
422 para->renderString(text, 0);
423 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
424 int glyphs = para->size();
428 if (PyTuple_Size(value) >= 3)
429 plist = PyTuple_GET_ITEM(value, 2);
433 if (plist && PyList_Check(plist))
434 entries = PyList_Size(plist);
436 int left=0, right=0, last=-1;
438 for (int i = 0; i < entries; ++i)
440 ePyObject entry = PyList_GET_ITEM(plist, i);
441 int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
443 if ((num < 0) || (num >= glyphs))
444 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
447 if (last+1 != num && last != -1) {
448 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
451 para->setGlyphFlag(num, GS_INVERT);
452 bbox = para->getGlyphBBox(num);
453 if (last+1 != num || last == -1)
455 right = bbox.left() + bbox.width();
458 /* entry is borrowed */
461 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
464 painter.renderPara(para, ePoint(0, 0));
465 /* pvalue is borrowed */
466 /* plist is 0 or borrowed */
469 /* type is borrowed */
471 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
476 if (selected && (!local_style || !local_style->m_selection))
477 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
483 int eListboxPythonConfigContent::currentCursorSelectable()
485 return eListboxPythonStringContent::currentCursorSelectable();
488 //////////////////////////////////////
490 /* todo: make a real infrastructure here! */
491 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
493 eListboxPythonMultiContent::eListboxPythonMultiContent()
494 :m_clip(gRegion::invalidRegion()), m_old_clip(gRegion::invalidRegion())
498 eListboxPythonMultiContent::~eListboxPythonMultiContent()
500 Py_XDECREF(m_buildFunc);
501 Py_XDECREF(m_selectableFunc);
504 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
506 m_selection_clip = rect;
508 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
513 if (update && m_listbox)
514 m_listbox->entryChanged(m_cursor);
517 static void clearRegionHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColor, bool cursorValid)
521 unsigned int color = PyInt_AsUnsignedLongMask(pbackColor);
522 painter.setBackgroundColor(gRGB(color));
524 else if (local_style)
526 if (local_style && local_style->m_background_color_set)
527 painter.setBackgroundColor(local_style->m_background_color);
528 if (local_style->m_background && cursorValid)
530 if (local_style->m_transparent_background)
531 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
533 painter.blit(local_style->m_background, offset, eRect(), 0);
536 else if (local_style->m_transparent_background)
542 static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColorSelected, bool cursorValid)
544 if (pbackColorSelected)
546 unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
547 painter.setBackgroundColor(gRGB(color));
549 else if (local_style)
551 if (local_style && local_style->m_background_color_selected_set)
552 painter.setBackgroundColor(local_style->m_background_color_selected);
553 if (local_style->m_background && cursorValid)
555 if (local_style->m_transparent_background)
556 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
558 painter.blit(local_style->m_background, offset, eRect(), 0);
561 else if (local_style->m_transparent_background)
567 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, bool cursorValid)
569 if (selected && sel_clip.valid())
571 gRegion part = rc - sel_clip;
575 style.setStyle(painter, eWindowStyle::styleListboxNormal);
576 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
580 part = rc & sel_clip;
584 style.setStyle(painter, eWindowStyle::styleListboxSelected);
585 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
592 style.setStyle(painter, eWindowStyle::styleListboxSelected);
593 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
594 if (local_style && local_style->m_selection)
595 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
599 style.setStyle(painter, eWindowStyle::styleListboxNormal);
600 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
605 if (pforeColorSelected)
607 unsigned int color = PyInt_AsUnsignedLongMask(pforeColorSelected);
608 painter.setForegroundColor(gRGB(color));
610 /* if we have a local foreground color set, use that. */
611 else if (local_style && local_style->m_foreground_color_selected_set)
612 painter.setForegroundColor(local_style->m_foreground_color_selected);
618 unsigned int color = PyInt_AsUnsignedLongMask(pforeColor);
619 painter.setForegroundColor(gRGB(color));
621 /* if we have a local foreground color set, use that. */
622 else if (local_style && local_style->m_foreground_color_set)
623 painter.setForegroundColor(local_style->m_foreground_color);
627 static ePyObject lookupColor(ePyObject color, ePyObject data)
629 if (color == Py_None)
632 if ((!color) && (!data))
635 unsigned int icolor = PyInt_AsUnsignedLongMask(color);
637 /* check if we have the "magic" template color */
638 if ((icolor & 0xFF000000) == 0xFF000000)
640 int index = icolor & 0xFFFFFF;
641 eDebug("[eListboxPythonMultiContent] template color index: %d", index);
642 return PyTuple_GetItem(data, index);
645 if (color == Py_None)
651 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
653 gRegion itemregion(eRect(offset, m_itemsize));
654 eListboxStyle *local_style = 0;
655 eRect sel_clip(m_selection_clip);
656 bool cursorValid = this->cursorValid();
657 if (sel_clip.valid())
658 sel_clip.moveBy(offset);
660 /* get local listbox style, if present */
662 local_style = m_listbox->getLocalStyle();
664 painter.clip(itemregion);
665 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, cursorValid);
667 ePyObject items, buildfunc_ret;
669 if (m_list && cursorValid)
671 /* a multicontent list can be used in two ways:
672 either each item is a list of (TYPE,...)-tuples,
673 or there is a template defined, which is a list of (TYPE,...)-tuples,
674 and the list is an unformatted tuple. The template then references items from the list.
676 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
680 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
682 if (PyTuple_Check(items))
683 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
685 eDebug("items is no tuple");
688 eDebug("buildfunc is not callable");
693 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
699 if (!PyList_Check(items))
701 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
706 if (!PyTuple_Check(items))
708 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
715 /* if we have a template, use the template for the actual formatting.
716 we will later detect that "data" is present, and refer to that, instead
717 of the immediate value. */
726 int size = PyList_Size(items);
727 for (int i = start; i < size; ++i)
729 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
733 eDebug("eListboxPythonMultiContent: ?");
737 if (!PyTuple_Check(item))
739 eDebug("eListboxPythonMultiContent did not receive a tuple.");
743 int size = PyTuple_Size(item);
747 eDebug("eListboxPythonMultiContent receive empty tuple.");
751 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
755 case TYPE_TEXT: // text
758 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
760 ePyObject px = PyTuple_GET_ITEM(item, 1),
761 py = PyTuple_GET_ITEM(item, 2),
762 pwidth = PyTuple_GET_ITEM(item, 3),
763 pheight = PyTuple_GET_ITEM(item, 4),
764 pfnt = PyTuple_GET_ITEM(item, 5),
765 pflags = PyTuple_GET_ITEM(item, 6),
766 pstring = PyTuple_GET_ITEM(item, 7),
767 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
769 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
771 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
776 pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data);
779 pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data);
782 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data);
785 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data);
789 pborderWidth = PyTuple_GET_ITEM(item, 12);
790 if (pborderWidth == Py_None)
791 pborderWidth=ePyObject();
794 pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data);
796 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
797 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
799 /* don't do anything if we have 'None' as string */
800 if (pstring == Py_None)
803 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
804 int x = PyInt_AsLong(px) + offset.x();
805 int y = PyInt_AsLong(py) + offset.y();
806 int width = PyInt_AsLong(pwidth);
807 int height = PyInt_AsLong(pheight);
808 int flags = PyInt_AsLong(pflags);
809 int fnt = PyInt_AsLong(pfnt);
810 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
812 if (m_font.find(fnt) == m_font.end())
814 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
818 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
823 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
826 painter.setFont(m_font[fnt]);
827 painter.renderText(rect, string, flags);
833 eRect rect(eRect(x, y, width, height));
837 unsigned int color = PyInt_AsUnsignedLongMask(pborderColor);
838 painter.setForegroundColor(gRGB(color));
841 rect.setRect(x, y, width, bwidth);
844 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
847 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
850 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
857 case TYPE_PROGRESS: // Progress
860 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
862 ePyObject px = PyTuple_GET_ITEM(item, 1),
863 py = PyTuple_GET_ITEM(item, 2),
864 pwidth = PyTuple_GET_ITEM(item, 3),
865 pheight = PyTuple_GET_ITEM(item, 4),
866 pfilled_perc = PyTuple_GET_ITEM(item, 5),
867 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
869 if (!(px && py && pwidth && pheight && pfilled_perc))
871 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
877 pborderWidth = PyTuple_GET_ITEM(item, 6);
878 if (pborderWidth == Py_None)
879 pborderWidth = ePyObject();
883 pforeColor = PyTuple_GET_ITEM(item, 7);
884 if (pforeColor == Py_None)
885 pforeColor = ePyObject();
889 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
890 if (pforeColorSelected == Py_None)
891 pforeColorSelected=ePyObject();
895 pbackColor = PyTuple_GET_ITEM(item, 9);
896 if (pbackColor == Py_None)
897 pbackColor=ePyObject();
901 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
902 if (pbackColorSelected == Py_None)
903 pbackColorSelected=ePyObject();
906 int x = PyInt_AsLong(px) + offset.x();
907 int y = PyInt_AsLong(py) + offset.y();
908 int width = PyInt_AsLong(pwidth);
909 int height = PyInt_AsLong(pheight);
910 int filled = PyInt_AsLong(pfilled_perc);
912 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
913 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
915 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
917 eRect rect(x, y, width, height);
922 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
926 rect.setRect(x, y, width, bwidth);
929 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
932 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
935 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
939 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
946 case TYPE_PIXMAP_ALPHATEST:
947 case TYPE_PIXMAP: // pixmap
950 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
953 ePyObject px = PyTuple_GET_ITEM(item, 1),
954 py = PyTuple_GET_ITEM(item, 2),
955 pwidth = PyTuple_GET_ITEM(item, 3),
956 pheight = PyTuple_GET_ITEM(item, 4),
957 ppixmap = PyTuple_GET_ITEM(item, 5),
958 pbackColor, pbackColorSelected;
960 if (!(px && py && pwidth && pheight && ppixmap))
962 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
966 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
967 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
969 /* don't do anything if we have 'None' as pixmap */
970 if (ppixmap == Py_None)
973 int x = PyInt_AsLong(px) + offset.x();
974 int y = PyInt_AsLong(py) + offset.y();
975 int width = PyInt_AsLong(pwidth);
976 int height = PyInt_AsLong(pheight);
977 ePtr<gPixmap> pixmap;
978 if (SwigFromPython(pixmap, ppixmap))
980 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
985 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
988 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
990 eRect rect(x, y, width, height);
995 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
998 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
1003 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1009 if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection))
1010 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1014 Py_DECREF(buildfunc_ret);
1019 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1021 Py_XDECREF(m_buildFunc);
1023 Py_XINCREF(m_buildFunc);
1026 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1028 Py_XDECREF(m_selectableFunc);
1029 m_selectableFunc=cb;
1030 Py_XINCREF(m_selectableFunc);
1033 int eListboxPythonMultiContent::currentCursorSelectable()
1035 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1036 if (m_list && cursorValid())
1038 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1040 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1041 if (PyTuple_Check(args))
1043 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1046 bool retval = ret == Py_True;
1050 eDebug("call m_selectableFunc failed!!! assume not callable");
1053 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1057 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1058 if (PyList_Check(item))
1060 item = PyList_GET_ITEM(item, 0);
1061 if (item != Py_None)
1063 } else if (PyTuple_Check(item))
1065 item = PyTuple_GET_ITEM(item, 0);
1066 if (item != Py_None)
1069 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1076 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1084 void eListboxPythonMultiContent::setItemHeight(int height)
1086 m_itemheight = height;
1088 m_listbox->setItemHeight(height);
1091 void eListboxPythonMultiContent::setList(ePyObject list)
1093 m_old_clip = m_clip = gRegion::invalidRegion();
1094 eListboxPythonStringContent::setList(list);
1097 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1102 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1103 m_clip -= m_old_clip;
1104 m_old_clip = m_clip;
1107 m_old_clip = m_clip = gRegion::invalidRegion();
1110 void eListboxPythonMultiContent::entryRemoved(int idx)
1113 m_listbox->entryRemoved(idx);
1116 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1118 m_template = tmplate;