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: // Progress
859 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
861 ePyObject px = PyTuple_GET_ITEM(item, 1),
862 py = PyTuple_GET_ITEM(item, 2),
863 pwidth = PyTuple_GET_ITEM(item, 3),
864 pheight = PyTuple_GET_ITEM(item, 4),
865 pfilled_perc = PyTuple_GET_ITEM(item, 5),
866 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
868 if (!(px && py && pwidth && pheight && pfilled_perc))
870 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
876 pborderWidth = PyTuple_GET_ITEM(item, 6);
877 if (pborderWidth == Py_None)
878 pborderWidth = ePyObject();
882 pforeColor = PyTuple_GET_ITEM(item, 7);
883 if (pforeColor == Py_None)
884 pforeColor = ePyObject();
888 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
889 if (pforeColorSelected == Py_None)
890 pforeColorSelected=ePyObject();
894 pbackColor = PyTuple_GET_ITEM(item, 9);
895 if (pbackColor == Py_None)
896 pbackColor=ePyObject();
900 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
901 if (pbackColorSelected == Py_None)
902 pbackColorSelected=ePyObject();
905 int x = PyInt_AsLong(px) + offset.x();
906 int y = PyInt_AsLong(py) + offset.y();
907 int width = PyInt_AsLong(pwidth);
908 int height = PyInt_AsLong(pheight);
909 int filled = PyInt_AsLong(pfilled_perc);
911 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
912 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
914 /* don't do anything if percent out of range */
915 if ((filled < 0) || (filled > 100))
918 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
920 eRect rect(x, y, width, height);
925 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
929 rect.setRect(x, y, width, bwidth);
932 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
935 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
938 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
942 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
949 case TYPE_PIXMAP_ALPHABLEND:
950 case TYPE_PIXMAP_ALPHATEST:
951 case TYPE_PIXMAP: // pixmap
954 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
957 ePyObject px = PyTuple_GET_ITEM(item, 1),
958 py = PyTuple_GET_ITEM(item, 2),
959 pwidth = PyTuple_GET_ITEM(item, 3),
960 pheight = PyTuple_GET_ITEM(item, 4),
961 ppixmap = PyTuple_GET_ITEM(item, 5),
962 pbackColor, pbackColorSelected;
964 if (!(px && py && pwidth && pheight && ppixmap))
966 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
970 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
971 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
973 /* don't do anything if we have 'None' as pixmap */
974 if (ppixmap == Py_None)
977 int x = PyInt_AsLong(px) + offset.x();
978 int y = PyInt_AsLong(py) + offset.y();
979 int width = PyInt_AsLong(pwidth);
980 int height = PyInt_AsLong(pheight);
981 ePtr<gPixmap> pixmap;
982 if (SwigFromPython(pixmap, ppixmap))
984 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
989 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
992 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
994 eRect rect(x, y, width, height);
999 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
1002 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0);
1007 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1013 if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection))
1014 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1018 Py_DECREF(buildfunc_ret);
1023 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1025 Py_XDECREF(m_buildFunc);
1027 Py_XINCREF(m_buildFunc);
1030 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1032 Py_XDECREF(m_selectableFunc);
1033 m_selectableFunc=cb;
1034 Py_XINCREF(m_selectableFunc);
1037 int eListboxPythonMultiContent::currentCursorSelectable()
1039 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1040 if (m_list && cursorValid())
1042 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1044 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1045 if (PyTuple_Check(args))
1047 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1050 bool retval = ret == Py_True;
1054 eDebug("call m_selectableFunc failed!!! assume not callable");
1057 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1061 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1062 if (PyList_Check(item))
1064 item = PyList_GET_ITEM(item, 0);
1065 if (item != Py_None)
1067 } else if (PyTuple_Check(item))
1069 item = PyTuple_GET_ITEM(item, 0);
1070 if (item != Py_None)
1073 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1080 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1088 void eListboxPythonMultiContent::setItemHeight(int height)
1090 m_itemheight = height;
1092 m_listbox->setItemHeight(height);
1095 void eListboxPythonMultiContent::setList(ePyObject list)
1097 m_old_clip = m_clip = gRegion::invalidRegion();
1098 eListboxPythonStringContent::setList(list);
1101 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1106 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1107 m_clip -= m_old_clip;
1108 m_old_clip = m_clip;
1111 m_old_clip = m_clip = gRegion::invalidRegion();
1114 void eListboxPythonMultiContent::entryRemoved(int idx)
1117 m_listbox->entryRemoved(idx);
1120 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1122 m_template = tmplate;