1 #include <lib/gui/elistbox.h>
2 #include <lib/gui/elistboxcontent.h>
3 #include <lib/gdi/font.h>
4 #include <lib/python/python.h>
7 The basic idea is to have an interface which gives all relevant list
8 processing functions, and can be used by the listbox to browse trough
11 The listbox directly uses the implemented cursor. It tries hard to avoid
12 iterating trough the (possibly very large) list, so it should be O(1),
13 i.e. the performance should not be influenced by the size of the list.
15 The list interface knows how to draw the current entry to a specified
16 offset. Different interfaces can be used to adapt different lists,
17 pre-filter lists on the fly etc.
19 cursorSave/Restore is used to avoid re-iterating the list on redraw.
20 The current selection is always selected as cursor position, the
21 cursor is then positioned to the start, and then iterated. This gives
22 at most 2x m_items_per_page cursor movements per redraw, indepenent
23 of the size of the list.
25 Although cursorSet is provided, it should be only used when there is no
26 other way, as it involves iterating trough the list.
29 iListboxContent::~iListboxContent()
33 iListboxContent::iListboxContent(): m_listbox(0)
37 void iListboxContent::setListbox(eListbox *lb)
40 m_listbox->setItemHeight(getItemHeight());
43 int iListboxContent::currentCursorSelectable()
48 //////////////////////////////////////
50 DEFINE_REF(eListboxPythonStringContent);
52 eListboxPythonStringContent::eListboxPythonStringContent(): m_itemheight(25)
56 eListboxPythonStringContent::~eListboxPythonStringContent()
61 void eListboxPythonStringContent::cursorHome()
66 void eListboxPythonStringContent::cursorEnd()
71 int eListboxPythonStringContent::cursorMove(int count)
77 else if (m_cursor > size())
82 int eListboxPythonStringContent::cursorValid()
84 return m_cursor < size();
87 int eListboxPythonStringContent::cursorSet(int n)
93 else if (m_cursor > size())
98 int eListboxPythonStringContent::cursorGet()
103 int eListboxPythonStringContent::currentCursorSelectable()
105 if (m_list && cursorValid())
107 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
108 if (!PyTuple_Check(item))
110 if (PyTuple_Size(item) >= 2)
116 void eListboxPythonStringContent::cursorSave()
118 m_saved_cursor = m_cursor;
121 void eListboxPythonStringContent::cursorRestore()
123 m_cursor = m_saved_cursor;
126 int eListboxPythonStringContent::size()
130 return PyList_Size(m_list);
133 void eListboxPythonStringContent::setSize(const eSize &size)
138 void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
140 ePtr<gFont> fnt = new gFont("Regular", 20);
141 painter.clip(eRect(offset, m_itemsize));
142 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
144 eListboxStyle *local_style = 0;
146 /* get local listbox style, if present */
148 local_style = m_listbox->getLocalStyle();
154 /* if we have a local background color set, use that. */
155 if (local_style->m_background_color_selected_set)
156 painter.setBackgroundColor(local_style->m_background_color_selected);
157 /* same for foreground */
158 if (local_style->m_foreground_color_selected_set)
159 painter.setForegroundColor(local_style->m_foreground_color_selected);
163 /* if we have a local background color set, use that. */
164 if (local_style->m_background_color_set)
165 painter.setBackgroundColor(local_style->m_background_color);
166 /* same for foreground */
167 if (local_style->m_foreground_color_set)
168 painter.setForegroundColor(local_style->m_foreground_color);
172 /* if we have no transparent background */
173 if (!local_style || !local_style->m_transparent_background)
175 /* blit background picture, if available (otherwise, clear only) */
176 if (local_style && local_style->m_background)
177 painter.blit(local_style->m_background, offset, eRect(), 0);
182 if (local_style->m_background)
183 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
184 else if (selected && !local_style->m_selection)
188 if (m_list && cursorValid())
191 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
192 painter.setFont(fnt);
194 /* the user can supply tuples, in this case the first one will be displayed. */
195 if (PyTuple_Check(item))
197 if (PyTuple_Size(item) == 1)
199 item = PyTuple_GET_ITEM(item, 0);
202 if (selected && local_style && local_style->m_selection)
203 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
208 int half_height = m_itemsize.height() / 2;
209 painter.fill(eRect(offset.x() + half_height, offset.y() + half_height - 2, m_itemsize.width() - m_itemsize.height(), 4));
212 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
213 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
215 painter.setForegroundColor(gRGB(0x808080));
216 painter.renderText(eRect(text_offset, m_itemsize), string);
219 if (selected && (!local_style || !local_style->m_selection))
220 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
226 void eListboxPythonStringContent::setList(ePyObject list)
229 if (!PyList_Check(list))
231 m_list = ePyObject();
239 m_listbox->entryReset(false);
242 PyObject *eListboxPythonStringContent::getCurrentSelection()
244 if (!(m_list && cursorValid()))
247 ePyObject r = PyList_GET_ITEM(m_list, m_cursor);
252 void eListboxPythonStringContent::invalidateEntry(int index)
255 m_listbox->entryChanged(index);
258 void eListboxPythonStringContent::invalidate()
264 m_listbox->moveSelectionTo(s?s-1:0);
266 m_listbox->invalidate();
270 //////////////////////////////////////
272 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
274 ePtr<gFont> fnt = new gFont("Regular", 20);
275 ePtr<gFont> fnt2 = new gFont("Regular", 16);
276 eRect itemrect(offset, m_itemsize);
277 eListboxStyle *local_style = 0;
279 painter.clip(itemrect);
280 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
282 /* get local listbox style, if present */
284 local_style = m_listbox->getLocalStyle();
290 /* if we have a local background color set, use that. */
291 if (local_style->m_background_color_selected_set)
292 painter.setBackgroundColor(local_style->m_background_color_selected);
293 /* same for foreground */
294 if (local_style->m_foreground_color_selected_set)
295 painter.setForegroundColor(local_style->m_foreground_color_selected);
299 /* if we have a local background color set, use that. */
300 if (local_style->m_background_color_set)
301 painter.setBackgroundColor(local_style->m_background_color);
302 /* same for foreground */
303 if (local_style->m_foreground_color_set)
304 painter.setForegroundColor(local_style->m_foreground_color);
308 if (!local_style || !local_style->m_transparent_background)
309 /* if we have no transparent background */
311 /* blit background picture, if available (otherwise, clear only) */
312 if (local_style && local_style->m_background)
313 painter.blit(local_style->m_background, offset, eRect(), 0);
318 if (local_style->m_background)
319 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
320 else if (selected && !local_style->m_selection)
324 if (m_list && cursorValid())
326 /* get current list item */
327 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
328 ePyObject text, value;
329 painter.setFont(fnt);
331 if (selected && local_style && local_style->m_selection)
332 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
334 /* the first tuple element is a string for the left side.
335 the second one will be called, and the result shall be an tuple.
338 the first one is the type (string).
339 the second one is the value. */
340 if (PyTuple_Check(item))
342 /* handle left part. get item from tuple, convert to string, display. */
344 text = PyTuple_GET_ITEM(item, 0);
345 text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
346 const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
347 eSize item_left = eSize(m_seperation, m_itemsize.height());
348 eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
349 painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
352 /* when we have no label, align value to the left. (FIXME:
353 don't we want to specifiy this individually?) */
354 int value_alignment_left = !*string;
356 /* now, handle the value. get 2nd part from tuple*/
357 value = PyTuple_GET_ITEM(item, 1);
360 ePyObject args = PyTuple_New(1);
361 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
363 /* CallObject will call __call__ which should return the value tuple */
364 value = PyObject_CallObject(value, args);
366 if (PyErr_Occurred())
370 /* the PyInt was stolen. */
373 /* check if this is really a tuple */
374 if (value && PyTuple_Check(value))
376 /* convert type to string */
377 ePyObject type = PyTuple_GET_ITEM(value, 0);
378 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
382 if (!strcmp(atype, "text"))
384 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
385 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
386 painter.setFont(fnt2);
387 if (value_alignment_left)
388 painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
390 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
392 /* pvalue is borrowed */
393 } else if (!strcmp(atype, "slider"))
395 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
396 ePyObject psize = PyTuple_GET_ITEM(value, 2);
398 /* convert value to Long. fallback to -1 on error. */
399 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
400 int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
402 /* calc. slider length */
403 int width = item_right.width() * value / size;
404 int height = item_right.height();
408 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
409 //hack - make it customizable
410 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
412 /* pvalue is borrowed */
413 } else if (!strcmp(atype, "mtext"))
415 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
416 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
417 int xoffs = value_alignment_left ? 0 : m_seperation;
418 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
420 para->renderString(text, 0);
421 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
422 int glyphs = para->size();
426 if (PyTuple_Size(value) >= 3)
427 plist = PyTuple_GET_ITEM(value, 2);
431 if (plist && PyList_Check(plist))
432 entries = PyList_Size(plist);
434 int left=0, right=0, last=-1;
436 for (int i = 0; i < entries; ++i)
438 ePyObject entry = PyList_GET_ITEM(plist, i);
439 int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
441 if ((num < 0) || (num >= glyphs))
442 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
445 if (last+1 != num && last != -1) {
446 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
449 para->setGlyphFlag(num, GS_INVERT);
450 bbox = para->getGlyphBBox(num);
451 if (last+1 != num || last == -1)
453 right = bbox.left() + bbox.width();
456 /* entry is borrowed */
459 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
462 painter.renderPara(para, ePoint(0, 0));
463 /* pvalue is borrowed */
464 /* plist is 0 or borrowed */
467 /* type is borrowed */
469 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
474 if (selected && (!local_style || !local_style->m_selection))
475 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
481 int eListboxPythonConfigContent::currentCursorSelectable()
483 return eListboxPythonStringContent::currentCursorSelectable();
486 //////////////////////////////////////
488 /* todo: make a real infrastructure here! */
489 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
491 eListboxPythonMultiContent::eListboxPythonMultiContent()
492 :m_clip(gRegion::invalidRegion()), m_old_clip(gRegion::invalidRegion())
496 eListboxPythonMultiContent::~eListboxPythonMultiContent()
498 Py_XDECREF(m_buildFunc);
499 Py_XDECREF(m_selectableFunc);
502 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
504 m_selection_clip = rect;
506 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
511 if (update && m_listbox)
512 m_listbox->entryChanged(m_cursor);
515 static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *local_style, ePyObject pforeColor, ePyObject pforeColorSelected, ePyObject pbackColor, ePyObject pbackColorSelected, int selected, gRegion &rc, eRect &sel_clip)
517 if (selected && sel_clip.valid())
519 gRegion part = rc - sel_clip;
523 style.setStyle(painter, eWindowStyle::styleListboxNormal);
526 unsigned int color = PyInt_AsUnsignedLongMask(pbackColor);
527 painter.setBackgroundColor(gRGB(color));
528 } // transparent background?
529 // if we have a local background color set, use that.
530 else if (local_style && local_style->m_background_color_set)
531 painter.setBackgroundColor(local_style->m_background_color);
532 if (!pbackColor && local_style && local_style->m_transparent_background)
539 part = rc & sel_clip;
543 style.setStyle(painter, eWindowStyle::styleListboxSelected);
544 if (pbackColorSelected)
546 unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
547 painter.setBackgroundColor(gRGB(color));
549 else if (local_style && local_style->m_background_color_selected_set)
550 painter.setBackgroundColor(local_style->m_background_color_selected);
560 style.setStyle(painter, eWindowStyle::styleListboxSelected);
561 if (pbackColorSelected)
563 unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
564 painter.setBackgroundColor(gRGB(color));
566 else if (local_style && local_style->m_background_color_selected_set)
567 painter.setBackgroundColor(local_style->m_background_color_selected);
572 style.setStyle(painter, eWindowStyle::styleListboxNormal);
575 unsigned int color = PyInt_AsUnsignedLongMask(pbackColor);
576 painter.setBackgroundColor(gRGB(color));
577 }/* if we have a local background color set, use that. */
578 else if (local_style && local_style->m_background_color_set)
579 painter.setBackgroundColor(local_style->m_background_color);
580 /* if we have no transparent background */
581 if (!pbackColor && local_style && local_style->m_transparent_background)
589 if (pforeColorSelected)
591 unsigned int color = PyInt_AsUnsignedLongMask(pforeColorSelected);
592 painter.setForegroundColor(gRGB(color));
594 /* if we have a local foreground color set, use that. */
595 else if (local_style && local_style->m_foreground_color_selected_set)
596 painter.setForegroundColor(local_style->m_foreground_color_selected);
602 unsigned int color = PyInt_AsUnsignedLongMask(pforeColor);
603 painter.setForegroundColor(gRGB(color));
605 /* if we have a local foreground color set, use that. */
606 else if (local_style && local_style->m_foreground_color_set)
607 painter.setForegroundColor(local_style->m_foreground_color);
611 static ePyObject lookupColor(ePyObject color, ePyObject data)
613 if (color == Py_None)
616 if ((!color) && (!data))
619 unsigned int icolor = PyInt_AsUnsignedLongMask(color);
621 /* check if we have the "magic" template color */
622 if ((icolor & 0xFF000000) == 0xFF000000)
624 int index = icolor & 0xFFFFFF;
625 eDebug("[eListboxPythonMultiContent] template color index: %d", index);
626 return PyTuple_GetItem(data, index);
629 if (color == Py_None)
635 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
637 gRegion itemregion(eRect(offset, m_itemsize));
638 eListboxStyle *local_style = 0;
639 eRect sel_clip(m_selection_clip);
640 if (sel_clip.valid())
641 sel_clip.moveBy(offset);
643 /* get local listbox style, if present */
645 local_style = m_listbox->getLocalStyle();
647 painter.clip(itemregion);
648 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip);
650 ePyObject items, buildfunc_ret;
652 if (m_list && cursorValid())
654 /* a multicontent list can be used in two ways:
655 either each item is a list of (TYPE,...)-tuples,
656 or there is a template defined, which is a list of (TYPE,...)-tuples,
657 and the list is an unformatted tuple. The template then references items from the list.
659 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
663 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
665 if (PyTuple_Check(items))
666 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
668 eDebug("items is no tuple");
671 eDebug("buildfunc is not callable");
676 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
682 if (!PyList_Check(items))
684 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
689 if (!PyTuple_Check(items))
691 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
698 /* if we have a template, use the template for the actual formatting.
699 we will later detect that "data" is present, and refer to that, instead
700 of the immediate value. */
709 int size = PyList_Size(items);
710 for (int i = start; i < size; ++i)
712 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
716 eDebug("eListboxPythonMultiContent: ?");
720 if (!PyTuple_Check(item))
722 eDebug("eListboxPythonMultiContent did not receive a tuple.");
726 int size = PyTuple_Size(item);
730 eDebug("eListboxPythonMultiContent receive empty tuple.");
734 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
738 case TYPE_TEXT: // text
741 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
743 ePyObject px = PyTuple_GET_ITEM(item, 1),
744 py = PyTuple_GET_ITEM(item, 2),
745 pwidth = PyTuple_GET_ITEM(item, 3),
746 pheight = PyTuple_GET_ITEM(item, 4),
747 pfnt = PyTuple_GET_ITEM(item, 5),
748 pflags = PyTuple_GET_ITEM(item, 6),
749 pstring = PyTuple_GET_ITEM(item, 7),
750 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
752 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
754 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
759 pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data);
762 pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data);
765 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data);
768 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data);
772 pborderWidth = PyTuple_GET_ITEM(item, 12);
773 if (pborderWidth == Py_None)
774 pborderWidth=ePyObject();
777 pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data);
779 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
780 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
782 /* don't do anything if we have 'None' as string */
783 if (pstring == Py_None)
786 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
787 int x = PyInt_AsLong(px) + offset.x();
788 int y = PyInt_AsLong(py) + offset.y();
789 int width = PyInt_AsLong(pwidth);
790 int height = PyInt_AsLong(pheight);
791 int flags = PyInt_AsLong(pflags);
792 int fnt = PyInt_AsLong(pfnt);
793 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
795 if (m_font.find(fnt) == m_font.end())
797 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
801 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
806 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
809 painter.setFont(m_font[fnt]);
810 painter.renderText(rect, string, flags);
816 eRect rect(eRect(x, y, width, height));
820 unsigned int color = PyInt_AsUnsignedLongMask(pborderColor);
821 painter.setForegroundColor(gRGB(color));
824 rect.setRect(x, y, width, bwidth);
827 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
830 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
833 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
840 case TYPE_PROGRESS: // Progress
843 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
845 ePyObject px = PyTuple_GET_ITEM(item, 1),
846 py = PyTuple_GET_ITEM(item, 2),
847 pwidth = PyTuple_GET_ITEM(item, 3),
848 pheight = PyTuple_GET_ITEM(item, 4),
849 pfilled_perc = PyTuple_GET_ITEM(item, 5),
850 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
852 if (!(px && py && pwidth && pheight && pfilled_perc))
854 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
860 pborderWidth = PyTuple_GET_ITEM(item, 6);
861 if (pborderWidth == Py_None)
862 pborderWidth = ePyObject();
866 pforeColor = PyTuple_GET_ITEM(item, 7);
867 if (pforeColor == Py_None)
868 pforeColor = ePyObject();
872 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
873 if (pforeColorSelected == Py_None)
874 pforeColorSelected=ePyObject();
878 pbackColor = PyTuple_GET_ITEM(item, 9);
879 if (pbackColor == Py_None)
880 pbackColor=ePyObject();
884 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
885 if (pbackColorSelected == Py_None)
886 pbackColorSelected=ePyObject();
889 int x = PyInt_AsLong(px) + offset.x();
890 int y = PyInt_AsLong(py) + offset.y();
891 int width = PyInt_AsLong(pwidth);
892 int height = PyInt_AsLong(pheight);
893 int filled = PyInt_AsLong(pfilled_perc);
895 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
896 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
898 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
900 eRect rect(x, y, width, height);
905 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
909 rect.setRect(x, y, width, bwidth);
912 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
915 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
918 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
922 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
929 case TYPE_PIXMAP_ALPHATEST:
930 case TYPE_PIXMAP: // pixmap
933 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
936 ePyObject px = PyTuple_GET_ITEM(item, 1),
937 py = PyTuple_GET_ITEM(item, 2),
938 pwidth = PyTuple_GET_ITEM(item, 3),
939 pheight = PyTuple_GET_ITEM(item, 4),
940 ppixmap = PyTuple_GET_ITEM(item, 5),
941 pbackColor, pbackColorSelected;
943 if (!(px && py && pwidth && pheight && ppixmap))
945 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
949 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
950 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
952 /* don't do anything if we have 'None' as pixmap */
953 if (ppixmap == Py_None)
956 int x = PyInt_AsLong(px) + offset.x();
957 int y = PyInt_AsLong(py) + offset.y();
958 int width = PyInt_AsLong(pwidth);
959 int height = PyInt_AsLong(pheight);
960 ePtr<gPixmap> pixmap;
961 if (SwigFromPython(pixmap, ppixmap))
963 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
968 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
971 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
973 eRect rect(x, y, width, height);
978 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip);
981 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
986 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
993 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
997 Py_DECREF(buildfunc_ret);
1002 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1004 Py_XDECREF(m_buildFunc);
1006 Py_XINCREF(m_buildFunc);
1009 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1011 Py_XDECREF(m_selectableFunc);
1012 m_selectableFunc=cb;
1013 Py_XINCREF(m_selectableFunc);
1016 int eListboxPythonMultiContent::currentCursorSelectable()
1018 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1019 if (m_list && cursorValid())
1021 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1023 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1024 if (PyTuple_Check(args))
1026 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1029 bool retval = ret == Py_True;
1033 eDebug("call m_selectableFunc failed!!! assume not callable");
1036 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1040 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1041 if (PyList_Check(item))
1043 item = PyList_GET_ITEM(item, 0);
1044 if (item != Py_None)
1046 } else if (PyTuple_Check(item))
1048 item = PyTuple_GET_ITEM(item, 0);
1049 if (item != Py_None)
1052 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1059 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1067 void eListboxPythonMultiContent::setItemHeight(int height)
1069 m_itemheight = height;
1071 m_listbox->setItemHeight(height);
1074 void eListboxPythonMultiContent::setList(ePyObject list)
1076 m_old_clip = m_clip = gRegion::invalidRegion();
1077 eListboxPythonStringContent::setList(list);
1080 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1085 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1086 m_clip -= m_old_clip;
1087 m_old_clip = m_clip;
1090 m_old_clip = m_clip = gRegion::invalidRegion();
1093 void eListboxPythonMultiContent::entryRemoved(int idx)
1096 m_listbox->entryRemoved(idx);
1099 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1101 m_template = tmplate;