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), m_cursor(0)
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 ((unsigned int)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);
565 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)
567 if (selected && sel_clip.valid())
569 gRegion part = rc - sel_clip;
573 style.setStyle(painter, eWindowStyle::styleListboxNormal);
574 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
578 part = rc & sel_clip;
582 style.setStyle(painter, eWindowStyle::styleListboxSelected);
583 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
590 style.setStyle(painter, eWindowStyle::styleListboxSelected);
591 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
592 if (local_style && local_style->m_selection)
593 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
597 style.setStyle(painter, eWindowStyle::styleListboxNormal);
598 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
603 if (pforeColorSelected)
605 unsigned int color = PyInt_AsUnsignedLongMask(pforeColorSelected);
606 painter.setForegroundColor(gRGB(color));
608 /* if we have a local foreground color set, use that. */
609 else if (local_style && local_style->m_foreground_color_selected_set)
610 painter.setForegroundColor(local_style->m_foreground_color_selected);
616 unsigned int color = PyInt_AsUnsignedLongMask(pforeColor);
617 painter.setForegroundColor(gRGB(color));
619 /* if we have a local foreground color set, use that. */
620 else if (local_style && local_style->m_foreground_color_set)
621 painter.setForegroundColor(local_style->m_foreground_color);
625 static ePyObject lookupColor(ePyObject color, ePyObject data)
627 if (color == Py_None)
630 if ((!color) && (!data))
633 unsigned int icolor = PyInt_AsUnsignedLongMask(color);
635 /* check if we have the "magic" template color */
636 if ((icolor & 0xFF000000) == 0xFF000000)
638 int index = icolor & 0xFFFFFF;
639 eDebug("[eListboxPythonMultiContent] template color index: %d", index);
640 return PyTuple_GetItem(data, index);
643 if (color == Py_None)
649 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
651 gRegion itemregion(eRect(offset, m_itemsize));
652 eListboxStyle *local_style = 0;
653 eRect sel_clip(m_selection_clip);
654 bool cursorValid = this->cursorValid();
655 if (sel_clip.valid())
656 sel_clip.moveBy(offset);
658 /* get local listbox style, if present */
660 local_style = m_listbox->getLocalStyle();
662 painter.clip(itemregion);
663 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, cursorValid);
665 ePyObject items, buildfunc_ret;
667 if (m_list && cursorValid)
669 /* a multicontent list can be used in two ways:
670 either each item is a list of (TYPE,...)-tuples,
671 or there is a template defined, which is a list of (TYPE,...)-tuples,
672 and the list is an unformatted tuple. The template then references items from the list.
674 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
678 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
680 if (PyTuple_Check(items))
681 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
683 eDebug("items is no tuple");
686 eDebug("buildfunc is not callable");
691 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
697 if (!PyList_Check(items))
699 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
704 if (!PyTuple_Check(items))
706 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
713 /* if we have a template, use the template for the actual formatting.
714 we will later detect that "data" is present, and refer to that, instead
715 of the immediate value. */
724 int size = PyList_Size(items);
725 for (int i = start; i < size; ++i)
727 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
731 eDebug("eListboxPythonMultiContent: ?");
735 if (!PyTuple_Check(item))
737 eDebug("eListboxPythonMultiContent did not receive a tuple.");
741 int size = PyTuple_Size(item);
745 eDebug("eListboxPythonMultiContent receive empty tuple.");
749 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
753 case TYPE_TEXT: // text
756 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
758 ePyObject px = PyTuple_GET_ITEM(item, 1),
759 py = PyTuple_GET_ITEM(item, 2),
760 pwidth = PyTuple_GET_ITEM(item, 3),
761 pheight = PyTuple_GET_ITEM(item, 4),
762 pfnt = PyTuple_GET_ITEM(item, 5),
763 pflags = PyTuple_GET_ITEM(item, 6),
764 pstring = PyTuple_GET_ITEM(item, 7),
765 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
767 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
769 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
774 pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data);
777 pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data);
780 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data);
783 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data);
787 pborderWidth = PyTuple_GET_ITEM(item, 12);
788 if (pborderWidth == Py_None)
789 pborderWidth=ePyObject();
792 pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data);
794 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
795 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
797 /* don't do anything if we have 'None' as string */
798 if (pstring == Py_None)
801 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
802 int x = PyInt_AsLong(px) + offset.x();
803 int y = PyInt_AsLong(py) + offset.y();
804 int width = PyInt_AsLong(pwidth);
805 int height = PyInt_AsLong(pheight);
806 int flags = PyInt_AsLong(pflags);
807 int fnt = PyInt_AsLong(pfnt);
808 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
810 if (m_font.find(fnt) == m_font.end())
812 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
816 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
821 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
824 painter.setFont(m_font[fnt]);
825 painter.renderText(rect, string, flags);
831 eRect rect(eRect(x, y, width, height));
835 unsigned int color = PyInt_AsUnsignedLongMask(pborderColor);
836 painter.setForegroundColor(gRGB(color));
839 rect.setRect(x, y, width, bwidth);
842 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
845 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
848 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
855 case TYPE_PROGRESS: // Progress
858 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
860 ePyObject px = PyTuple_GET_ITEM(item, 1),
861 py = PyTuple_GET_ITEM(item, 2),
862 pwidth = PyTuple_GET_ITEM(item, 3),
863 pheight = PyTuple_GET_ITEM(item, 4),
864 pfilled_perc = PyTuple_GET_ITEM(item, 5),
865 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
867 if (!(px && py && pwidth && pheight && pfilled_perc))
869 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
875 pborderWidth = PyTuple_GET_ITEM(item, 6);
876 if (pborderWidth == Py_None)
877 pborderWidth = ePyObject();
881 pforeColor = PyTuple_GET_ITEM(item, 7);
882 if (pforeColor == Py_None)
883 pforeColor = ePyObject();
887 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
888 if (pforeColorSelected == Py_None)
889 pforeColorSelected=ePyObject();
893 pbackColor = PyTuple_GET_ITEM(item, 9);
894 if (pbackColor == Py_None)
895 pbackColor=ePyObject();
899 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
900 if (pbackColorSelected == Py_None)
901 pbackColorSelected=ePyObject();
904 int x = PyInt_AsLong(px) + offset.x();
905 int y = PyInt_AsLong(py) + offset.y();
906 int width = PyInt_AsLong(pwidth);
907 int height = PyInt_AsLong(pheight);
908 int filled = PyInt_AsLong(pfilled_perc);
910 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
911 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
913 /* don't do anything if percent out of range */
914 if ((filled < 0) || (filled > 100))
917 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
919 eRect rect(x, y, width, height);
924 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
928 rect.setRect(x, y, width, bwidth);
931 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
934 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
937 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
941 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
948 case TYPE_PIXMAP_ALPHATEST:
949 case TYPE_PIXMAP: // pixmap
952 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
955 ePyObject px = PyTuple_GET_ITEM(item, 1),
956 py = PyTuple_GET_ITEM(item, 2),
957 pwidth = PyTuple_GET_ITEM(item, 3),
958 pheight = PyTuple_GET_ITEM(item, 4),
959 ppixmap = PyTuple_GET_ITEM(item, 5),
960 pbackColor, pbackColorSelected;
962 if (!(px && py && pwidth && pheight && ppixmap))
964 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
968 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
969 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
971 /* don't do anything if we have 'None' as pixmap */
972 if (ppixmap == Py_None)
975 int x = PyInt_AsLong(px) + offset.x();
976 int y = PyInt_AsLong(py) + offset.y();
977 int width = PyInt_AsLong(pwidth);
978 int height = PyInt_AsLong(pheight);
979 ePtr<gPixmap> pixmap;
980 if (SwigFromPython(pixmap, ppixmap))
982 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
987 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
990 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
992 eRect rect(x, y, width, height);
997 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
1000 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
1005 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1011 if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection))
1012 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1016 Py_DECREF(buildfunc_ret);
1021 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1023 Py_XDECREF(m_buildFunc);
1025 Py_XINCREF(m_buildFunc);
1028 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1030 Py_XDECREF(m_selectableFunc);
1031 m_selectableFunc=cb;
1032 Py_XINCREF(m_selectableFunc);
1035 int eListboxPythonMultiContent::currentCursorSelectable()
1037 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1038 if (m_list && cursorValid())
1040 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1042 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1043 if (PyTuple_Check(args))
1045 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1048 bool retval = ret == Py_True;
1052 eDebug("call m_selectableFunc failed!!! assume not callable");
1055 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1059 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1060 if (PyList_Check(item))
1062 item = PyList_GET_ITEM(item, 0);
1063 if (item != Py_None)
1065 } else if (PyTuple_Check(item))
1067 item = PyTuple_GET_ITEM(item, 0);
1068 if (item != Py_None)
1071 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1078 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1086 void eListboxPythonMultiContent::setItemHeight(int height)
1088 m_itemheight = height;
1090 m_listbox->setItemHeight(height);
1093 void eListboxPythonMultiContent::setList(ePyObject list)
1095 m_old_clip = m_clip = gRegion::invalidRegion();
1096 eListboxPythonStringContent::setList(list);
1099 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1104 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1105 m_clip -= m_old_clip;
1106 m_old_clip = m_clip;
1109 m_old_clip = m_clip = gRegion::invalidRegion();
1112 void eListboxPythonMultiContent::entryRemoved(int idx)
1115 m_listbox->entryRemoved(idx);
1118 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1120 m_template = tmplate;