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)
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)
544 static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColorSelected, bool cursorValid)
546 if (pbackColorSelected)
548 unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
549 painter.setBackgroundColor(gRGB(color));
551 else if (local_style)
553 if (local_style && local_style->m_background_color_selected_set)
554 painter.setBackgroundColor(local_style->m_background_color_selected);
555 if (local_style->m_background && cursorValid)
557 if (local_style->m_transparent_background)
558 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
560 painter.blit(local_style->m_background, offset, eRect(), 0);
567 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)
569 if (selected && sel_clip.valid())
571 gRegion part = rc - sel_clip;
575 style.setStyle(painter, eWindowStyle::styleListboxNormal);
576 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
580 part = rc & sel_clip;
584 style.setStyle(painter, eWindowStyle::styleListboxSelected);
585 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
592 style.setStyle(painter, eWindowStyle::styleListboxSelected);
593 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
594 if (local_style && local_style->m_selection)
595 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
599 style.setStyle(painter, eWindowStyle::styleListboxNormal);
600 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
605 if (pforeColorSelected)
607 unsigned int color = PyInt_AsUnsignedLongMask(pforeColorSelected);
608 painter.setForegroundColor(gRGB(color));
610 /* if we have a local foreground color set, use that. */
611 else if (local_style && local_style->m_foreground_color_selected_set)
612 painter.setForegroundColor(local_style->m_foreground_color_selected);
618 unsigned int color = PyInt_AsUnsignedLongMask(pforeColor);
619 painter.setForegroundColor(gRGB(color));
621 /* if we have a local foreground color set, use that. */
622 else if (local_style && local_style->m_foreground_color_set)
623 painter.setForegroundColor(local_style->m_foreground_color);
627 static ePyObject lookupColor(ePyObject color, ePyObject data)
629 if (color == Py_None)
632 if ((!color) && (!data))
635 unsigned int icolor = PyInt_AsUnsignedLongMask(color);
637 /* check if we have the "magic" template color */
638 if ((icolor & 0xFF000000) == 0xFF000000)
640 int index = icolor & 0xFFFFFF;
641 eDebug("[eListboxPythonMultiContent] template color index: %d", index);
642 return PyTuple_GetItem(data, index);
645 if (color == Py_None)
651 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
653 gRegion itemregion(eRect(offset, m_itemsize));
654 eListboxStyle *local_style = 0;
655 eRect sel_clip(m_selection_clip);
656 bool cursorValid = this->cursorValid();
657 if (sel_clip.valid())
658 sel_clip.moveBy(offset);
660 /* get local listbox style, if present */
662 local_style = m_listbox->getLocalStyle();
664 painter.clip(itemregion);
665 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, cursorValid);
667 ePyObject items, buildfunc_ret;
669 if (m_list && cursorValid)
671 /* a multicontent list can be used in two ways:
672 either each item is a list of (TYPE,...)-tuples,
673 or there is a template defined, which is a list of (TYPE,...)-tuples,
674 and the list is an unformatted tuple. The template then references items from the list.
676 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
680 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
682 if (PyTuple_Check(items))
683 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
685 eDebug("items is no tuple");
688 eDebug("buildfunc is not callable");
693 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
699 if (!PyList_Check(items))
701 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
706 if (!PyTuple_Check(items))
708 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
715 /* if we have a template, use the template for the actual formatting.
716 we will later detect that "data" is present, and refer to that, instead
717 of the immediate value. */
726 int size = PyList_Size(items);
727 for (int i = start; i < size; ++i)
729 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
733 eDebug("eListboxPythonMultiContent: ?");
737 if (!PyTuple_Check(item))
739 eDebug("eListboxPythonMultiContent did not receive a tuple.");
743 int size = PyTuple_Size(item);
747 eDebug("eListboxPythonMultiContent receive empty tuple.");
751 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
755 case TYPE_TEXT: // text
758 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
760 ePyObject px = PyTuple_GET_ITEM(item, 1),
761 py = PyTuple_GET_ITEM(item, 2),
762 pwidth = PyTuple_GET_ITEM(item, 3),
763 pheight = PyTuple_GET_ITEM(item, 4),
764 pfnt = PyTuple_GET_ITEM(item, 5),
765 pflags = PyTuple_GET_ITEM(item, 6),
766 pstring = PyTuple_GET_ITEM(item, 7),
767 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
769 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
771 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
776 pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data);
779 pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data);
782 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data);
785 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data);
789 pborderWidth = PyTuple_GET_ITEM(item, 12);
790 if (pborderWidth == Py_None)
791 pborderWidth=ePyObject();
794 pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data);
796 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
797 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
799 /* don't do anything if we have 'None' as string */
800 if (pstring == Py_None)
803 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
804 int x = PyInt_AsLong(px) + offset.x();
805 int y = PyInt_AsLong(py) + offset.y();
806 int width = PyInt_AsLong(pwidth);
807 int height = PyInt_AsLong(pheight);
808 int flags = PyInt_AsLong(pflags);
809 int fnt = PyInt_AsLong(pfnt);
810 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
812 if (m_font.find(fnt) == m_font.end())
814 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
818 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
823 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
826 painter.setFont(m_font[fnt]);
827 painter.renderText(rect, string, flags);
833 eRect rect(eRect(x, y, width, height));
837 unsigned int color = PyInt_AsUnsignedLongMask(pborderColor);
838 painter.setForegroundColor(gRGB(color));
841 rect.setRect(x, y, width, bwidth);
844 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
847 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
850 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
857 case TYPE_PROGRESS: // Progress
860 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
862 ePyObject px = PyTuple_GET_ITEM(item, 1),
863 py = PyTuple_GET_ITEM(item, 2),
864 pwidth = PyTuple_GET_ITEM(item, 3),
865 pheight = PyTuple_GET_ITEM(item, 4),
866 pfilled_perc = PyTuple_GET_ITEM(item, 5),
867 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
869 if (!(px && py && pwidth && pheight && pfilled_perc))
871 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
877 pborderWidth = PyTuple_GET_ITEM(item, 6);
878 if (pborderWidth == Py_None)
879 pborderWidth = ePyObject();
883 pforeColor = PyTuple_GET_ITEM(item, 7);
884 if (pforeColor == Py_None)
885 pforeColor = ePyObject();
889 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
890 if (pforeColorSelected == Py_None)
891 pforeColorSelected=ePyObject();
895 pbackColor = PyTuple_GET_ITEM(item, 9);
896 if (pbackColor == Py_None)
897 pbackColor=ePyObject();
901 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
902 if (pbackColorSelected == Py_None)
903 pbackColorSelected=ePyObject();
906 int x = PyInt_AsLong(px) + offset.x();
907 int y = PyInt_AsLong(py) + offset.y();
908 int width = PyInt_AsLong(pwidth);
909 int height = PyInt_AsLong(pheight);
910 int filled = PyInt_AsLong(pfilled_perc);
912 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
913 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
915 /* don't do anything if percent out of range */
916 if ((filled < 0) || (filled > 100))
919 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
921 eRect rect(x, y, width, height);
926 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
930 rect.setRect(x, y, width, bwidth);
933 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
936 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
939 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
943 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
950 case TYPE_PIXMAP_ALPHABLEND:
951 case TYPE_PIXMAP_ALPHATEST:
952 case TYPE_PIXMAP: // pixmap
955 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
958 ePyObject px = PyTuple_GET_ITEM(item, 1),
959 py = PyTuple_GET_ITEM(item, 2),
960 pwidth = PyTuple_GET_ITEM(item, 3),
961 pheight = PyTuple_GET_ITEM(item, 4),
962 ppixmap = PyTuple_GET_ITEM(item, 5),
963 pbackColor, pbackColorSelected;
965 if (!(px && py && pwidth && pheight && ppixmap))
967 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
971 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
972 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
974 /* don't do anything if we have 'None' as pixmap */
975 if (ppixmap == Py_None)
978 int x = PyInt_AsLong(px) + offset.x();
979 int y = PyInt_AsLong(py) + offset.y();
980 int width = PyInt_AsLong(pwidth);
981 int height = PyInt_AsLong(pheight);
982 ePtr<gPixmap> pixmap;
983 if (SwigFromPython(pixmap, ppixmap))
985 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
990 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
993 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
995 eRect rect(x, y, width, height);
1000 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
1003 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0);
1008 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1014 if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection))
1015 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1019 Py_DECREF(buildfunc_ret);
1024 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1026 Py_XDECREF(m_buildFunc);
1028 Py_XINCREF(m_buildFunc);
1031 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1033 Py_XDECREF(m_selectableFunc);
1034 m_selectableFunc=cb;
1035 Py_XINCREF(m_selectableFunc);
1038 int eListboxPythonMultiContent::currentCursorSelectable()
1040 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1041 if (m_list && cursorValid())
1043 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1045 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1046 if (PyTuple_Check(args))
1048 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1051 bool retval = ret == Py_True;
1055 eDebug("call m_selectableFunc failed!!! assume not callable");
1058 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1062 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1063 if (PyList_Check(item))
1065 item = PyList_GET_ITEM(item, 0);
1066 if (item != Py_None)
1068 } else if (PyTuple_Check(item))
1070 item = PyTuple_GET_ITEM(item, 0);
1071 if (item != Py_None)
1074 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1081 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1089 void eListboxPythonMultiContent::setItemHeight(int height)
1091 m_itemheight = height;
1093 m_listbox->setItemHeight(height);
1096 void eListboxPythonMultiContent::setList(ePyObject list)
1098 m_old_clip = m_clip = gRegion::invalidRegion();
1099 eListboxPythonStringContent::setList(list);
1102 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1107 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1108 m_clip -= m_old_clip;
1109 m_old_clip = m_clip;
1112 m_old_clip = m_clip = gRegion::invalidRegion();
1115 void eListboxPythonMultiContent::entryRemoved(int idx)
1118 m_listbox->entryRemoved(idx);
1121 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1123 m_template = tmplate;