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);
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);
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);
540 static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColorSelected, bool cursorValid)
542 if (pbackColorSelected)
544 unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
545 painter.setBackgroundColor(gRGB(color));
547 else if (local_style)
549 if (local_style && local_style->m_background_color_selected_set)
550 painter.setBackgroundColor(local_style->m_background_color_selected);
551 if (local_style->m_background && cursorValid)
553 if (local_style->m_transparent_background)
554 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
556 painter.blit(local_style->m_background, offset, eRect(), 0);
563 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)
565 if (selected && sel_clip.valid())
567 gRegion part = rc - sel_clip;
571 style.setStyle(painter, eWindowStyle::styleListboxNormal);
572 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
576 part = rc & sel_clip;
580 style.setStyle(painter, eWindowStyle::styleListboxSelected);
581 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
588 style.setStyle(painter, eWindowStyle::styleListboxSelected);
589 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
590 if (local_style && local_style->m_selection)
591 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
595 style.setStyle(painter, eWindowStyle::styleListboxNormal);
596 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
601 if (pforeColorSelected)
603 unsigned int color = PyInt_AsUnsignedLongMask(pforeColorSelected);
604 painter.setForegroundColor(gRGB(color));
606 /* if we have a local foreground color set, use that. */
607 else if (local_style && local_style->m_foreground_color_selected_set)
608 painter.setForegroundColor(local_style->m_foreground_color_selected);
614 unsigned int color = PyInt_AsUnsignedLongMask(pforeColor);
615 painter.setForegroundColor(gRGB(color));
617 /* if we have a local foreground color set, use that. */
618 else if (local_style && local_style->m_foreground_color_set)
619 painter.setForegroundColor(local_style->m_foreground_color);
623 static ePyObject lookupColor(ePyObject color, ePyObject data)
625 if (color == Py_None)
628 if ((!color) && (!data))
631 unsigned int icolor = PyInt_AsUnsignedLongMask(color);
633 /* check if we have the "magic" template color */
634 if ((icolor & 0xFF000000) == 0xFF000000)
636 int index = icolor & 0xFFFFFF;
637 eDebug("[eListboxPythonMultiContent] template color index: %d", index);
638 return PyTuple_GetItem(data, index);
641 if (color == Py_None)
647 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
649 gRegion itemregion(eRect(offset, m_itemsize));
650 eListboxStyle *local_style = 0;
651 eRect sel_clip(m_selection_clip);
652 bool cursorValid = this->cursorValid();
653 if (sel_clip.valid())
654 sel_clip.moveBy(offset);
656 /* get local listbox style, if present */
658 local_style = m_listbox->getLocalStyle();
660 painter.clip(itemregion);
661 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, cursorValid);
663 ePyObject items, buildfunc_ret;
665 if (m_list && cursorValid)
667 /* a multicontent list can be used in two ways:
668 either each item is a list of (TYPE,...)-tuples,
669 or there is a template defined, which is a list of (TYPE,...)-tuples,
670 and the list is an unformatted tuple. The template then references items from the list.
672 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
676 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
678 if (PyTuple_Check(items))
679 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
681 eDebug("items is no tuple");
684 eDebug("buildfunc is not callable");
689 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
695 if (!PyList_Check(items))
697 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
702 if (!PyTuple_Check(items))
704 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
711 /* if we have a template, use the template for the actual formatting.
712 we will later detect that "data" is present, and refer to that, instead
713 of the immediate value. */
722 int size = PyList_Size(items);
723 for (int i = start; i < size; ++i)
725 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
729 eDebug("eListboxPythonMultiContent: ?");
733 if (!PyTuple_Check(item))
735 eDebug("eListboxPythonMultiContent did not receive a tuple.");
739 int size = PyTuple_Size(item);
743 eDebug("eListboxPythonMultiContent receive empty tuple.");
747 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
751 case TYPE_TEXT: // text
754 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
756 ePyObject px = PyTuple_GET_ITEM(item, 1),
757 py = PyTuple_GET_ITEM(item, 2),
758 pwidth = PyTuple_GET_ITEM(item, 3),
759 pheight = PyTuple_GET_ITEM(item, 4),
760 pfnt = PyTuple_GET_ITEM(item, 5),
761 pflags = PyTuple_GET_ITEM(item, 6),
762 pstring = PyTuple_GET_ITEM(item, 7),
763 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
765 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
767 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
772 pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data);
775 pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data);
778 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data);
781 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data);
785 pborderWidth = PyTuple_GET_ITEM(item, 12);
786 if (pborderWidth == Py_None)
787 pborderWidth=ePyObject();
790 pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data);
792 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
793 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
795 /* don't do anything if we have 'None' as string */
796 if (pstring == Py_None)
799 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
800 int x = PyInt_AsLong(px) + offset.x();
801 int y = PyInt_AsLong(py) + offset.y();
802 int width = PyInt_AsLong(pwidth);
803 int height = PyInt_AsLong(pheight);
804 int flags = PyInt_AsLong(pflags);
805 int fnt = PyInt_AsLong(pfnt);
806 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
808 if (m_font.find(fnt) == m_font.end())
810 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
814 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
819 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
822 painter.setFont(m_font[fnt]);
823 painter.renderText(rect, string, flags);
829 eRect rect(eRect(x, y, width, height));
833 unsigned int color = PyInt_AsUnsignedLongMask(pborderColor);
834 painter.setForegroundColor(gRGB(color));
837 rect.setRect(x, y, width, bwidth);
840 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
843 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
846 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
853 case TYPE_PROGRESS: // Progress
856 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
858 ePyObject px = PyTuple_GET_ITEM(item, 1),
859 py = PyTuple_GET_ITEM(item, 2),
860 pwidth = PyTuple_GET_ITEM(item, 3),
861 pheight = PyTuple_GET_ITEM(item, 4),
862 pfilled_perc = PyTuple_GET_ITEM(item, 5),
863 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
865 if (!(px && py && pwidth && pheight && pfilled_perc))
867 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
873 pborderWidth = PyTuple_GET_ITEM(item, 6);
874 if (pborderWidth == Py_None)
875 pborderWidth = ePyObject();
879 pforeColor = PyTuple_GET_ITEM(item, 7);
880 if (pforeColor == Py_None)
881 pforeColor = ePyObject();
885 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
886 if (pforeColorSelected == Py_None)
887 pforeColorSelected=ePyObject();
891 pbackColor = PyTuple_GET_ITEM(item, 9);
892 if (pbackColor == Py_None)
893 pbackColor=ePyObject();
897 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
898 if (pbackColorSelected == Py_None)
899 pbackColorSelected=ePyObject();
902 int x = PyInt_AsLong(px) + offset.x();
903 int y = PyInt_AsLong(py) + offset.y();
904 int width = PyInt_AsLong(pwidth);
905 int height = PyInt_AsLong(pheight);
906 int filled = PyInt_AsLong(pfilled_perc);
908 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
909 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
911 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
913 eRect rect(x, y, width, height);
918 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
922 rect.setRect(x, y, width, bwidth);
925 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
928 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
931 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
935 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
942 case TYPE_PIXMAP_ALPHATEST:
943 case TYPE_PIXMAP: // pixmap
946 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
949 ePyObject px = PyTuple_GET_ITEM(item, 1),
950 py = PyTuple_GET_ITEM(item, 2),
951 pwidth = PyTuple_GET_ITEM(item, 3),
952 pheight = PyTuple_GET_ITEM(item, 4),
953 ppixmap = PyTuple_GET_ITEM(item, 5),
954 pbackColor, pbackColorSelected;
956 if (!(px && py && pwidth && pheight && ppixmap))
958 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
962 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
963 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
965 /* don't do anything if we have 'None' as pixmap */
966 if (ppixmap == Py_None)
969 int x = PyInt_AsLong(px) + offset.x();
970 int y = PyInt_AsLong(py) + offset.y();
971 int width = PyInt_AsLong(pwidth);
972 int height = PyInt_AsLong(pheight);
973 ePtr<gPixmap> pixmap;
974 if (SwigFromPython(pixmap, ppixmap))
976 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
981 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
984 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
986 eRect rect(x, y, width, height);
991 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
994 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
999 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1005 if (selected && (!local_style || !local_style->m_selection))
1006 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1010 Py_DECREF(buildfunc_ret);
1015 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1017 Py_XDECREF(m_buildFunc);
1019 Py_XINCREF(m_buildFunc);
1022 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1024 Py_XDECREF(m_selectableFunc);
1025 m_selectableFunc=cb;
1026 Py_XINCREF(m_selectableFunc);
1029 int eListboxPythonMultiContent::currentCursorSelectable()
1031 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1032 if (m_list && cursorValid())
1034 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1036 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1037 if (PyTuple_Check(args))
1039 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1042 bool retval = ret == Py_True;
1046 eDebug("call m_selectableFunc failed!!! assume not callable");
1049 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1053 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1054 if (PyList_Check(item))
1056 item = PyList_GET_ITEM(item, 0);
1057 if (item != Py_None)
1059 } else if (PyTuple_Check(item))
1061 item = PyTuple_GET_ITEM(item, 0);
1062 if (item != Py_None)
1065 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1072 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1080 void eListboxPythonMultiContent::setItemHeight(int height)
1082 m_itemheight = height;
1084 m_listbox->setItemHeight(height);
1087 void eListboxPythonMultiContent::setList(ePyObject list)
1089 m_old_clip = m_clip = gRegion::invalidRegion();
1090 eListboxPythonStringContent::setList(list);
1093 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1098 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1099 m_clip -= m_old_clip;
1100 m_old_clip = m_clip;
1103 m_old_clip = m_clip = gRegion::invalidRegion();
1106 void eListboxPythonMultiContent::entryRemoved(int idx)
1109 m_listbox->entryRemoved(idx);
1112 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1114 m_template = tmplate;