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. */
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 if (PyTuple_Size(item) >= 2) // when no 2nd entry is in tuple this is a non selectable entry without config part
360 value = PyTuple_GET_ITEM(item, 1);
364 ePyObject args = PyTuple_New(1);
365 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
367 /* CallObject will call __call__ which should return the value tuple */
368 value = PyObject_CallObject(value, args);
370 if (PyErr_Occurred())
374 /* the PyInt was stolen. */
377 /* check if this is really a tuple */
378 if (value && PyTuple_Check(value))
380 /* convert type to string */
381 ePyObject type = PyTuple_GET_ITEM(value, 0);
382 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
386 if (!strcmp(atype, "text"))
388 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
389 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
390 painter.setFont(fnt2);
391 if (value_alignment_left)
392 painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
394 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
396 /* pvalue is borrowed */
397 } else if (!strcmp(atype, "slider"))
399 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
400 ePyObject psize = PyTuple_GET_ITEM(value, 2);
402 /* convert value to Long. fallback to -1 on error. */
403 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
404 int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
406 /* calc. slider length */
407 int width = item_right.width() * value / size;
408 int height = item_right.height();
412 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
413 //hack - make it customizable
414 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
416 /* pvalue is borrowed */
417 } else if (!strcmp(atype, "mtext"))
419 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
420 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
421 int xoffs = value_alignment_left ? 0 : m_seperation;
422 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
424 para->renderString(text, 0);
425 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
426 int glyphs = para->size();
430 if (PyTuple_Size(value) >= 3)
431 plist = PyTuple_GET_ITEM(value, 2);
435 if (plist && PyList_Check(plist))
436 entries = PyList_Size(plist);
438 int left=0, right=0, last=-1;
440 for (int i = 0; i < entries; ++i)
442 ePyObject entry = PyList_GET_ITEM(plist, i);
443 int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
445 if ((num < 0) || (num >= glyphs))
446 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
449 if (last+1 != num && last != -1) {
450 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
453 para->setGlyphFlag(num, GS_INVERT);
454 bbox = para->getGlyphBBox(num);
455 if (last+1 != num || last == -1)
457 right = bbox.left() + bbox.width();
460 /* entry is borrowed */
463 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
466 painter.renderPara(para, ePoint(0, 0));
467 /* pvalue is borrowed */
468 /* plist is 0 or borrowed */
471 /* type is borrowed */
473 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
478 if (selected && (!local_style || !local_style->m_selection))
479 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
485 int eListboxPythonConfigContent::currentCursorSelectable()
487 return eListboxPythonStringContent::currentCursorSelectable();
490 //////////////////////////////////////
492 /* todo: make a real infrastructure here! */
493 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
495 eListboxPythonMultiContent::eListboxPythonMultiContent()
496 :m_clip(gRegion::invalidRegion()), m_old_clip(gRegion::invalidRegion())
500 eListboxPythonMultiContent::~eListboxPythonMultiContent()
502 Py_XDECREF(m_buildFunc);
503 Py_XDECREF(m_selectableFunc);
506 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
508 m_selection_clip = rect;
510 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
515 if (update && m_listbox)
516 m_listbox->entryChanged(m_cursor);
519 static void clearRegionHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColor, bool cursorValid, bool clear=true)
523 unsigned int color = PyInt_AsUnsignedLongMask(pbackColor);
524 painter.setBackgroundColor(gRGB(color));
526 else if (local_style)
528 if (local_style && local_style->m_background_color_set)
529 painter.setBackgroundColor(local_style->m_background_color);
530 if (local_style->m_background && cursorValid)
532 if (local_style->m_transparent_background)
533 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
535 painter.blit(local_style->m_background, offset, eRect(), 0);
538 else if (local_style->m_transparent_background)
545 static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColorSelected, bool cursorValid, bool clear=true)
547 if (pbackColorSelected)
549 unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
550 painter.setBackgroundColor(gRGB(color));
552 else if (local_style)
554 if (local_style && local_style->m_background_color_selected_set)
555 painter.setBackgroundColor(local_style->m_background_color_selected);
556 if (local_style->m_background && cursorValid)
558 if (local_style->m_transparent_background)
559 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
561 painter.blit(local_style->m_background, offset, eRect(), 0);
569 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, bool clear=true)
571 if (selected && sel_clip.valid())
573 gRegion part = rc - sel_clip;
577 style.setStyle(painter, eWindowStyle::styleListboxNormal);
578 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid, clear);
582 part = rc & sel_clip;
586 style.setStyle(painter, eWindowStyle::styleListboxSelected);
587 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid, clear);
594 style.setStyle(painter, eWindowStyle::styleListboxSelected);
595 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid, clear);
596 if (local_style && local_style->m_selection)
597 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
601 style.setStyle(painter, eWindowStyle::styleListboxNormal);
602 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid, clear);
607 if (pforeColorSelected)
609 unsigned int color = PyInt_AsUnsignedLongMask(pforeColorSelected);
610 painter.setForegroundColor(gRGB(color));
612 /* if we have a local foreground color set, use that. */
613 else if (local_style && local_style->m_foreground_color_selected_set)
614 painter.setForegroundColor(local_style->m_foreground_color_selected);
620 unsigned int color = PyInt_AsUnsignedLongMask(pforeColor);
621 painter.setForegroundColor(gRGB(color));
623 /* if we have a local foreground color set, use that. */
624 else if (local_style && local_style->m_foreground_color_set)
625 painter.setForegroundColor(local_style->m_foreground_color);
629 static ePyObject lookupColor(ePyObject color, ePyObject data)
631 if (color == Py_None)
634 if ((!color) && (!data))
637 unsigned int icolor = PyInt_AsUnsignedLongMask(color);
639 /* check if we have the "magic" template color */
640 if ((icolor & 0xFF000000) == 0xFF000000)
642 int index = icolor & 0xFFFFFF;
643 eDebug("[eListboxPythonMultiContent] template color index: %d", index);
644 return PyTuple_GetItem(data, index);
647 if (color == Py_None)
653 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
655 gRegion itemregion(eRect(offset, m_itemsize));
656 eListboxStyle *local_style = 0;
657 eRect sel_clip(m_selection_clip);
658 bool cursorValid = this->cursorValid();
659 if (sel_clip.valid())
660 sel_clip.moveBy(offset);
662 /* get local listbox style, if present */
664 local_style = m_listbox->getLocalStyle();
666 painter.clip(itemregion);
667 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, cursorValid);
669 ePyObject items, buildfunc_ret;
671 if (m_list && cursorValid)
673 /* a multicontent list can be used in two ways:
674 either each item is a list of (TYPE,...)-tuples,
675 or there is a template defined, which is a list of (TYPE,...)-tuples,
676 and the list is an unformatted tuple. The template then references items from the list.
678 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
682 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
684 if (PyTuple_Check(items))
685 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
687 eDebug("items is no tuple");
690 eDebug("buildfunc is not callable");
695 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
701 if (!PyList_Check(items))
703 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
708 if (!PyTuple_Check(items))
710 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
717 /* if we have a template, use the template for the actual formatting.
718 we will later detect that "data" is present, and refer to that, instead
719 of the immediate value. */
728 int size = PyList_Size(items);
729 for (int i = start; i < size; ++i)
731 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
735 eDebug("eListboxPythonMultiContent: ?");
739 if (!PyTuple_Check(item))
741 eDebug("eListboxPythonMultiContent did not receive a tuple.");
745 int size = PyTuple_Size(item);
749 eDebug("eListboxPythonMultiContent receive empty tuple.");
753 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
757 case TYPE_TEXT: // text
760 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
762 ePyObject px = PyTuple_GET_ITEM(item, 1),
763 py = PyTuple_GET_ITEM(item, 2),
764 pwidth = PyTuple_GET_ITEM(item, 3),
765 pheight = PyTuple_GET_ITEM(item, 4),
766 pfnt = PyTuple_GET_ITEM(item, 5),
767 pflags = PyTuple_GET_ITEM(item, 6),
768 pstring = PyTuple_GET_ITEM(item, 7),
769 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
771 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
773 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
778 pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data);
781 pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data);
784 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data);
787 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data);
791 pborderWidth = PyTuple_GET_ITEM(item, 12);
792 if (pborderWidth == Py_None)
793 pborderWidth=ePyObject();
796 pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data);
798 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
799 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
801 /* don't do anything if we have 'None' as string */
802 if (pstring == Py_None)
805 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
806 int x = PyInt_AsLong(px) + offset.x();
807 int y = PyInt_AsLong(py) + offset.y();
808 int width = PyInt_AsLong(pwidth);
809 int height = PyInt_AsLong(pheight);
810 int flags = PyInt_AsLong(pflags);
811 int fnt = PyInt_AsLong(pfnt);
812 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
814 if (m_font.find(fnt) == m_font.end())
816 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
820 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
825 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
826 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
829 painter.setFont(m_font[fnt]);
830 painter.renderText(rect, string, flags);
836 eRect rect(eRect(x, y, width, height));
840 unsigned int color = PyInt_AsUnsignedLongMask(pborderColor);
841 painter.setForegroundColor(gRGB(color));
844 rect.setRect(x, y, width, bwidth);
847 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
850 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
853 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
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 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
872 if (!(px && py && pwidth && pheight && pfilled_perc))
874 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
880 pborderWidth = PyTuple_GET_ITEM(item, 6);
881 if (pborderWidth == Py_None)
882 pborderWidth = ePyObject();
886 pforeColor = PyTuple_GET_ITEM(item, 7);
887 if (pforeColor == Py_None)
888 pforeColor = ePyObject();
892 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
893 if (pforeColorSelected == Py_None)
894 pforeColorSelected=ePyObject();
898 pbackColor = PyTuple_GET_ITEM(item, 9);
899 if (pbackColor == Py_None)
900 pbackColor=ePyObject();
904 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
905 if (pbackColorSelected == Py_None)
906 pbackColorSelected=ePyObject();
909 int x = PyInt_AsLong(px) + offset.x();
910 int y = PyInt_AsLong(py) + offset.y();
911 int width = PyInt_AsLong(pwidth);
912 int height = PyInt_AsLong(pheight);
913 int filled = PyInt_AsLong(pfilled_perc);
915 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
916 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
918 /* don't do anything if percent out of range */
919 if ((filled < 0) || (filled > 100))
922 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
924 eRect rect(x, y, width, height);
929 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
930 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
934 rect.setRect(x, y, width, bwidth);
937 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
940 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
943 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
947 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
954 case TYPE_PIXMAP_ALPHABLEND:
955 case TYPE_PIXMAP_ALPHATEST:
956 case TYPE_PIXMAP: // pixmap
959 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
962 ePyObject px = PyTuple_GET_ITEM(item, 1),
963 py = PyTuple_GET_ITEM(item, 2),
964 pwidth = PyTuple_GET_ITEM(item, 3),
965 pheight = PyTuple_GET_ITEM(item, 4),
966 ppixmap = PyTuple_GET_ITEM(item, 5),
967 pbackColor, pbackColorSelected;
969 if (!(px && py && pwidth && pheight && ppixmap))
971 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
975 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
976 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
978 /* don't do anything if we have 'None' as pixmap */
979 if (ppixmap == Py_None)
982 int x = PyInt_AsLong(px) + offset.x();
983 int y = PyInt_AsLong(py) + offset.y();
984 int width = PyInt_AsLong(pwidth);
985 int height = PyInt_AsLong(pheight);
986 ePtr<gPixmap> pixmap;
987 if (SwigFromPython(pixmap, ppixmap))
989 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
994 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
997 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
999 eRect rect(x, y, width, height);
1004 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
1005 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
1008 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0);
1013 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1019 if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection))
1020 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1024 Py_DECREF(buildfunc_ret);
1029 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1031 Py_XDECREF(m_buildFunc);
1033 Py_XINCREF(m_buildFunc);
1036 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1038 Py_XDECREF(m_selectableFunc);
1039 m_selectableFunc=cb;
1040 Py_XINCREF(m_selectableFunc);
1043 int eListboxPythonMultiContent::currentCursorSelectable()
1045 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1046 if (m_list && cursorValid())
1048 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1050 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1051 if (PyTuple_Check(args))
1053 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1056 bool retval = ret == Py_True;
1060 eDebug("call m_selectableFunc failed!!! assume not callable");
1063 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1067 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1068 if (PyList_Check(item))
1070 item = PyList_GET_ITEM(item, 0);
1071 if (item != Py_None)
1073 } else if (PyTuple_Check(item))
1075 item = PyTuple_GET_ITEM(item, 0);
1076 if (item != Py_None)
1079 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1086 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1094 void eListboxPythonMultiContent::setItemHeight(int height)
1096 m_itemheight = height;
1098 m_listbox->setItemHeight(height);
1101 void eListboxPythonMultiContent::setList(ePyObject list)
1103 m_old_clip = m_clip = gRegion::invalidRegion();
1104 eListboxPythonStringContent::setList(list);
1107 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1112 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1113 m_clip -= m_old_clip;
1114 m_old_clip = m_clip;
1117 m_old_clip = m_clip = gRegion::invalidRegion();
1120 void eListboxPythonMultiContent::entryRemoved(int idx)
1123 m_listbox->entryRemoved(idx);
1126 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1128 m_template = tmplate;