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()
53 :m_cursor(0), m_itemheight(25)
57 eListboxPythonStringContent::~eListboxPythonStringContent()
62 void eListboxPythonStringContent::cursorHome()
67 void eListboxPythonStringContent::cursorEnd()
72 int eListboxPythonStringContent::cursorMove(int count)
78 else if (m_cursor > size())
83 int eListboxPythonStringContent::cursorValid()
85 return m_cursor < size();
88 int eListboxPythonStringContent::cursorSet(int n)
94 else if (m_cursor > size())
99 int eListboxPythonStringContent::cursorGet()
104 int eListboxPythonStringContent::currentCursorSelectable()
106 if (m_list && cursorValid())
108 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
109 if (!PyTuple_Check(item))
111 if (PyTuple_Size(item) >= 2)
117 void eListboxPythonStringContent::cursorSave()
119 m_saved_cursor = m_cursor;
122 void eListboxPythonStringContent::cursorRestore()
124 m_cursor = m_saved_cursor;
127 int eListboxPythonStringContent::size()
131 return PyList_Size(m_list);
134 void eListboxPythonStringContent::setSize(const eSize &size)
139 void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
141 ePtr<gFont> fnt = new gFont("Regular", 20);
142 painter.clip(eRect(offset, m_itemsize));
143 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
145 eListboxStyle *local_style = 0;
146 bool cursorValid = this->cursorValid();
148 /* get local listbox style, if present */
150 local_style = m_listbox->getLocalStyle();
156 /* if we have a local background color set, use that. */
157 if (local_style->m_background_color_selected_set)
158 painter.setBackgroundColor(local_style->m_background_color_selected);
159 /* same for foreground */
160 if (local_style->m_foreground_color_selected_set)
161 painter.setForegroundColor(local_style->m_foreground_color_selected);
165 /* if we have a local background color set, use that. */
166 if (local_style->m_background_color_set)
167 painter.setBackgroundColor(local_style->m_background_color);
168 /* same for foreground */
169 if (local_style->m_foreground_color_set)
170 painter.setForegroundColor(local_style->m_foreground_color);
174 /* if we have no transparent background */
175 if (!local_style || !local_style->m_transparent_background)
177 /* blit background picture, if available (otherwise, clear only) */
178 if (local_style && local_style->m_background && cursorValid)
179 painter.blit(local_style->m_background, offset, eRect(), 0);
184 if (local_style->m_background && cursorValid)
185 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
186 else if (selected && !local_style->m_selection)
190 if (m_list && cursorValid)
193 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
194 painter.setFont(fnt);
196 /* the user can supply tuples, in this case the first one will be displayed. */
197 if (PyTuple_Check(item))
199 if (PyTuple_Size(item) == 1)
201 item = PyTuple_GET_ITEM(item, 0);
204 if (selected && local_style && local_style->m_selection)
205 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
210 int half_height = m_itemsize.height() / 2;
211 painter.fill(eRect(offset.x() + half_height, offset.y() + half_height - 2, m_itemsize.width() - m_itemsize.height(), 4));
214 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
215 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
217 painter.setForegroundColor(gRGB(0x808080));
218 painter.renderText(eRect(text_offset, m_itemsize), string);
221 if (selected && (!local_style || !local_style->m_selection))
222 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
228 void eListboxPythonStringContent::setList(ePyObject list)
231 if (!PyList_Check(list))
233 m_list = ePyObject();
241 m_listbox->entryReset(false);
244 PyObject *eListboxPythonStringContent::getCurrentSelection()
246 if (!(m_list && cursorValid()))
249 ePyObject r = PyList_GET_ITEM(m_list, m_cursor);
254 void eListboxPythonStringContent::invalidateEntry(int index)
257 m_listbox->entryChanged(index);
260 void eListboxPythonStringContent::invalidate()
266 m_listbox->moveSelectionTo(s?s-1:0);
268 m_listbox->invalidate();
272 //////////////////////////////////////
274 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
276 ePtr<gFont> fnt = new gFont("Regular", 20);
277 ePtr<gFont> fnt2 = new gFont("Regular", 16);
278 eRect itemrect(offset, m_itemsize);
279 eListboxStyle *local_style = 0;
280 bool cursorValid = this->cursorValid();
282 painter.clip(itemrect);
283 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
285 /* get local listbox style, if present */
287 local_style = m_listbox->getLocalStyle();
293 /* if we have a local background color set, use that. */
294 if (local_style->m_background_color_selected_set)
295 painter.setBackgroundColor(local_style->m_background_color_selected);
296 /* same for foreground */
297 if (local_style->m_foreground_color_selected_set)
298 painter.setForegroundColor(local_style->m_foreground_color_selected);
302 /* if we have a local background color set, use that. */
303 if (local_style->m_background_color_set)
304 painter.setBackgroundColor(local_style->m_background_color);
305 /* same for foreground */
306 if (local_style->m_foreground_color_set)
307 painter.setForegroundColor(local_style->m_foreground_color);
311 if (!local_style || !local_style->m_transparent_background)
312 /* if we have no transparent background */
314 /* blit background picture, if available (otherwise, clear only) */
315 if (local_style && local_style->m_background && cursorValid)
316 painter.blit(local_style->m_background, offset, eRect(), 0);
321 if (local_style->m_background && cursorValid)
322 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
323 else if (selected && !local_style->m_selection)
327 if (m_list && cursorValid)
329 /* get current list item */
330 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
331 ePyObject text, value;
332 painter.setFont(fnt);
334 if (selected && local_style && local_style->m_selection)
335 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
337 /* the first tuple element is a string for the left side.
338 the second one will be called, and the result shall be an tuple.
341 the first one is the type (string).
342 the second one is the value. */
343 if (PyTuple_Check(item))
345 /* handle left part. get item from tuple, convert to string, display. */
347 text = PyTuple_GET_ITEM(item, 0);
348 text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
349 const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
350 eSize item_left = eSize(m_seperation, m_itemsize.height());
351 eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
352 painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
355 /* when we have no label, align value to the left. (FIXME:
356 don't we want to specifiy this individually?) */
357 int value_alignment_left = !*string;
359 /* now, handle the value. get 2nd part from tuple*/
360 value = PyTuple_GET_ITEM(item, 1);
363 ePyObject args = PyTuple_New(1);
364 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
366 /* CallObject will call __call__ which should return the value tuple */
367 value = PyObject_CallObject(value, args);
369 if (PyErr_Occurred())
373 /* the PyInt was stolen. */
376 /* check if this is really a tuple */
377 if (value && PyTuple_Check(value))
379 /* convert type to string */
380 ePyObject type = PyTuple_GET_ITEM(value, 0);
381 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
385 if (!strcmp(atype, "text"))
387 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
388 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
389 painter.setFont(fnt2);
390 if (value_alignment_left)
391 painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
393 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
395 /* pvalue is borrowed */
396 } else if (!strcmp(atype, "slider"))
398 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
399 ePyObject psize = PyTuple_GET_ITEM(value, 2);
401 /* convert value to Long. fallback to -1 on error. */
402 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
403 int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
405 /* calc. slider length */
406 int width = item_right.width() * value / size;
407 int height = item_right.height();
411 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
412 //hack - make it customizable
413 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
415 /* pvalue is borrowed */
416 } else if (!strcmp(atype, "mtext"))
418 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
419 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
420 int xoffs = value_alignment_left ? 0 : m_seperation;
421 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
423 para->renderString(text, 0);
424 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
425 int glyphs = para->size();
429 if (PyTuple_Size(value) >= 3)
430 plist = PyTuple_GET_ITEM(value, 2);
434 if (plist && PyList_Check(plist))
435 entries = PyList_Size(plist);
437 int left=0, right=0, last=-1;
439 for (int i = 0; i < entries; ++i)
441 ePyObject entry = PyList_GET_ITEM(plist, i);
442 int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
444 if ((num < 0) || (num >= glyphs))
445 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
448 if (last+1 != num && last != -1) {
449 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
452 para->setGlyphFlag(num, GS_INVERT);
453 bbox = para->getGlyphBBox(num);
454 if (last+1 != num || last == -1)
456 right = bbox.left() + bbox.width();
459 /* entry is borrowed */
462 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
465 painter.renderPara(para, ePoint(0, 0));
466 /* pvalue is borrowed */
467 /* plist is 0 or borrowed */
470 /* type is borrowed */
472 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
477 if (selected && (!local_style || !local_style->m_selection))
478 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
484 int eListboxPythonConfigContent::currentCursorSelectable()
486 return eListboxPythonStringContent::currentCursorSelectable();
489 //////////////////////////////////////
491 /* todo: make a real infrastructure here! */
492 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
494 eListboxPythonMultiContent::eListboxPythonMultiContent()
495 :m_clip(gRegion::invalidRegion()), m_old_clip(gRegion::invalidRegion())
499 eListboxPythonMultiContent::~eListboxPythonMultiContent()
501 Py_XDECREF(m_buildFunc);
502 Py_XDECREF(m_selectableFunc);
505 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
507 m_selection_clip = rect;
509 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
514 if (update && m_listbox)
515 m_listbox->entryChanged(m_cursor);
518 static void clearRegionHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColor, bool cursorValid)
522 unsigned int color = PyInt_AsUnsignedLongMask(pbackColor);
523 painter.setBackgroundColor(gRGB(color));
525 else if (local_style)
527 if (local_style && local_style->m_background_color_set)
528 painter.setBackgroundColor(local_style->m_background_color);
529 if (local_style->m_background && cursorValid)
531 if (local_style->m_transparent_background)
532 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
534 painter.blit(local_style->m_background, offset, eRect(), 0);
537 else if (local_style->m_transparent_background)
543 static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColorSelected, bool cursorValid)
545 if (pbackColorSelected)
547 unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
548 painter.setBackgroundColor(gRGB(color));
550 else if (local_style)
552 if (local_style && local_style->m_background_color_selected_set)
553 painter.setBackgroundColor(local_style->m_background_color_selected);
554 if (local_style->m_background && cursorValid)
556 if (local_style->m_transparent_background)
557 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
559 painter.blit(local_style->m_background, offset, eRect(), 0);
566 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)
568 if (selected && sel_clip.valid())
570 gRegion part = rc - sel_clip;
574 style.setStyle(painter, eWindowStyle::styleListboxNormal);
575 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
579 part = rc & sel_clip;
583 style.setStyle(painter, eWindowStyle::styleListboxSelected);
584 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
591 style.setStyle(painter, eWindowStyle::styleListboxSelected);
592 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
593 if (local_style && local_style->m_selection)
594 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
598 style.setStyle(painter, eWindowStyle::styleListboxNormal);
599 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
604 if (pforeColorSelected)
606 unsigned int color = PyInt_AsUnsignedLongMask(pforeColorSelected);
607 painter.setForegroundColor(gRGB(color));
609 /* if we have a local foreground color set, use that. */
610 else if (local_style && local_style->m_foreground_color_selected_set)
611 painter.setForegroundColor(local_style->m_foreground_color_selected);
617 unsigned int color = PyInt_AsUnsignedLongMask(pforeColor);
618 painter.setForegroundColor(gRGB(color));
620 /* if we have a local foreground color set, use that. */
621 else if (local_style && local_style->m_foreground_color_set)
622 painter.setForegroundColor(local_style->m_foreground_color);
626 static ePyObject lookupColor(ePyObject color, ePyObject data)
628 if (color == Py_None)
631 if ((!color) && (!data))
634 unsigned int icolor = PyInt_AsUnsignedLongMask(color);
636 /* check if we have the "magic" template color */
637 if ((icolor & 0xFF000000) == 0xFF000000)
639 int index = icolor & 0xFFFFFF;
640 eDebug("[eListboxPythonMultiContent] template color index: %d", index);
641 return PyTuple_GetItem(data, index);
644 if (color == Py_None)
650 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
652 gRegion itemregion(eRect(offset, m_itemsize));
653 eListboxStyle *local_style = 0;
654 eRect sel_clip(m_selection_clip);
655 bool cursorValid = this->cursorValid();
656 if (sel_clip.valid())
657 sel_clip.moveBy(offset);
659 /* get local listbox style, if present */
661 local_style = m_listbox->getLocalStyle();
663 painter.clip(itemregion);
664 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, cursorValid);
666 ePyObject items, buildfunc_ret;
668 if (m_list && cursorValid)
670 /* a multicontent list can be used in two ways:
671 either each item is a list of (TYPE,...)-tuples,
672 or there is a template defined, which is a list of (TYPE,...)-tuples,
673 and the list is an unformatted tuple. The template then references items from the list.
675 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
679 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
681 if (PyTuple_Check(items))
682 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
684 eDebug("items is no tuple");
687 eDebug("buildfunc is not callable");
692 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
698 if (!PyList_Check(items))
700 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
705 if (!PyTuple_Check(items))
707 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
714 /* if we have a template, use the template for the actual formatting.
715 we will later detect that "data" is present, and refer to that, instead
716 of the immediate value. */
725 int size = PyList_Size(items);
726 for (int i = start; i < size; ++i)
728 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
732 eDebug("eListboxPythonMultiContent: ?");
736 if (!PyTuple_Check(item))
738 eDebug("eListboxPythonMultiContent did not receive a tuple.");
742 int size = PyTuple_Size(item);
746 eDebug("eListboxPythonMultiContent receive empty tuple.");
750 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
754 case TYPE_TEXT: // text
757 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
759 ePyObject px = PyTuple_GET_ITEM(item, 1),
760 py = PyTuple_GET_ITEM(item, 2),
761 pwidth = PyTuple_GET_ITEM(item, 3),
762 pheight = PyTuple_GET_ITEM(item, 4),
763 pfnt = PyTuple_GET_ITEM(item, 5),
764 pflags = PyTuple_GET_ITEM(item, 6),
765 pstring = PyTuple_GET_ITEM(item, 7),
766 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
768 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
770 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
775 pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data);
778 pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data);
781 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data);
784 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data);
788 pborderWidth = PyTuple_GET_ITEM(item, 12);
789 if (pborderWidth == Py_None)
790 pborderWidth=ePyObject();
793 pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data);
795 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
796 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
798 /* don't do anything if we have 'None' as string */
799 if (pstring == Py_None)
802 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
803 int x = PyInt_AsLong(px) + offset.x();
804 int y = PyInt_AsLong(py) + offset.y();
805 int width = PyInt_AsLong(pwidth);
806 int height = PyInt_AsLong(pheight);
807 int flags = PyInt_AsLong(pflags);
808 int fnt = PyInt_AsLong(pfnt);
809 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
811 if (m_font.find(fnt) == m_font.end())
813 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
817 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
822 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
825 painter.setFont(m_font[fnt]);
826 painter.renderText(rect, string, flags);
832 eRect rect(eRect(x, y, width, height));
836 unsigned int color = PyInt_AsUnsignedLongMask(pborderColor);
837 painter.setForegroundColor(gRGB(color));
840 rect.setRect(x, y, width, bwidth);
843 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
846 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
849 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
856 case TYPE_PROGRESS_PIXMAP: // Progress
858 (1, x, y, width, height, filled_percent, pixmap [, borderWidth, foreColor, backColor, backColorSelected] )
860 case TYPE_PROGRESS: // Progress
863 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
865 ePyObject px = PyTuple_GET_ITEM(item, 1),
866 py = PyTuple_GET_ITEM(item, 2),
867 pwidth = PyTuple_GET_ITEM(item, 3),
868 pheight = PyTuple_GET_ITEM(item, 4),
869 pfilled_perc = PyTuple_GET_ITEM(item, 5),
870 ppixmap, pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
872 if (type == TYPE_PROGRESS)
874 if (!(px && py && pwidth && pheight && pfilled_perc))
876 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
882 ppixmap = PyTuple_GET_ITEM(item, idx++);
883 if (ppixmap == Py_None)
885 if (!(px && py && pwidth && pheight && pfilled_perc, ppixmap))
887 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS_PIXMAP, x, y, width, height, filled percent, pixmap, [,border width, foreColor, backColor, backColorSelected]))");
894 pborderWidth = PyTuple_GET_ITEM(item, idx++);
895 if (pborderWidth == Py_None)
896 pborderWidth = ePyObject();
900 pforeColor = PyTuple_GET_ITEM(item, idx++);
901 if (pforeColor == Py_None)
902 pforeColor = ePyObject();
906 pforeColorSelected = PyTuple_GET_ITEM(item, idx++);
907 if (pforeColorSelected == Py_None)
908 pforeColorSelected=ePyObject();
912 pbackColor = PyTuple_GET_ITEM(item, idx++);
913 if (pbackColor == Py_None)
914 pbackColor=ePyObject();
918 pbackColorSelected = PyTuple_GET_ITEM(item, idx++);
919 if (pbackColorSelected == Py_None)
920 pbackColorSelected=ePyObject();
923 int x = PyInt_AsLong(px) + offset.x();
924 int y = PyInt_AsLong(py) + offset.y();
925 int width = PyInt_AsLong(pwidth);
926 int height = PyInt_AsLong(pheight);
927 int filled = PyInt_AsLong(pfilled_perc);
929 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
930 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
932 /* don't do anything if percent out of range */
933 if ((filled < 0) || (filled > 100))
936 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
938 eRect rect(x, y, width, height);
943 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
947 rect.setRect(x, y, width, bwidth);
950 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
953 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
956 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
959 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
964 ePtr<gPixmap> pixmap;
965 if (PyInt_Check(ppixmap) && data) /* if the pixmap is in fact a number, it refers to the data list */
966 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
968 if (SwigFromPython(pixmap, ppixmap))
970 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
974 painter.blit(pixmap, rect.topLeft(), rect, 0);
982 case TYPE_PIXMAP_ALPHABLEND:
983 case TYPE_PIXMAP_ALPHATEST:
984 case TYPE_PIXMAP: // pixmap
987 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
990 ePyObject px = PyTuple_GET_ITEM(item, 1),
991 py = PyTuple_GET_ITEM(item, 2),
992 pwidth = PyTuple_GET_ITEM(item, 3),
993 pheight = PyTuple_GET_ITEM(item, 4),
994 ppixmap = PyTuple_GET_ITEM(item, 5),
995 pbackColor, pbackColorSelected;
997 if (!(px && py && pwidth && pheight && ppixmap))
999 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
1003 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
1004 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
1006 /* don't do anything if we have 'None' as pixmap */
1007 if (ppixmap == Py_None)
1010 int x = PyInt_AsLong(px) + offset.x();
1011 int y = PyInt_AsLong(py) + offset.y();
1012 int width = PyInt_AsLong(pwidth);
1013 int height = PyInt_AsLong(pheight);
1014 ePtr<gPixmap> pixmap;
1015 if (SwigFromPython(pixmap, ppixmap))
1017 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
1022 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
1025 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
1027 eRect rect(x, y, width, height);
1032 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
1035 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0);
1040 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1046 if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection))
1047 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1051 Py_DECREF(buildfunc_ret);
1056 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1058 Py_XDECREF(m_buildFunc);
1060 Py_XINCREF(m_buildFunc);
1063 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1065 Py_XDECREF(m_selectableFunc);
1066 m_selectableFunc=cb;
1067 Py_XINCREF(m_selectableFunc);
1070 int eListboxPythonMultiContent::currentCursorSelectable()
1072 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1073 if (m_list && cursorValid())
1075 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1077 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1078 if (PyTuple_Check(args))
1080 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1083 bool retval = ret == Py_True;
1087 eDebug("call m_selectableFunc failed!!! assume not callable");
1090 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1094 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1095 if (PyList_Check(item))
1097 item = PyList_GET_ITEM(item, 0);
1098 if (item != Py_None)
1100 } else if (PyTuple_Check(item))
1102 item = PyTuple_GET_ITEM(item, 0);
1103 if (item != Py_None)
1106 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1113 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1121 void eListboxPythonMultiContent::setItemHeight(int height)
1123 m_itemheight = height;
1125 m_listbox->setItemHeight(height);
1128 void eListboxPythonMultiContent::setList(ePyObject list)
1130 m_old_clip = m_clip = gRegion::invalidRegion();
1131 eListboxPythonStringContent::setList(list);
1134 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1139 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1140 m_clip -= m_old_clip;
1141 m_old_clip = m_clip;
1144 m_old_clip = m_clip = gRegion::invalidRegion();
1147 void eListboxPythonMultiContent::entryRemoved(int idx)
1150 m_listbox->entryRemoved(idx);
1153 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1155 m_template = tmplate;