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_PIXMAP: // Progress
862 (1, x, y, width, height, filled_percent, pixmap [, borderWidth, foreColor, backColor, backColorSelected] )
864 case TYPE_PROGRESS: // Progress
867 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
869 ePyObject px = PyTuple_GET_ITEM(item, 1),
870 py = PyTuple_GET_ITEM(item, 2),
871 pwidth = PyTuple_GET_ITEM(item, 3),
872 pheight = PyTuple_GET_ITEM(item, 4),
873 pfilled_perc = PyTuple_GET_ITEM(item, 5),
874 ppixmap, pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
876 if (type == TYPE_PROGRESS)
878 if (!(px && py && pwidth && pheight && pfilled_perc))
880 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
886 ppixmap = PyTuple_GET_ITEM(item, idx++);
887 if (ppixmap == Py_None)
889 if (!(px && py && pwidth && pheight && pfilled_perc, ppixmap))
891 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS_PIXMAP, x, y, width, height, filled percent, pixmap, [,border width, foreColor, backColor, backColorSelected]))");
898 pborderWidth = PyTuple_GET_ITEM(item, idx++);
899 if (pborderWidth == Py_None)
900 pborderWidth = ePyObject();
904 pforeColor = PyTuple_GET_ITEM(item, idx++);
905 if (pforeColor == Py_None)
906 pforeColor = ePyObject();
910 pforeColorSelected = PyTuple_GET_ITEM(item, idx++);
911 if (pforeColorSelected == Py_None)
912 pforeColorSelected=ePyObject();
916 pbackColor = PyTuple_GET_ITEM(item, idx++);
917 if (pbackColor == Py_None)
918 pbackColor=ePyObject();
922 pbackColorSelected = PyTuple_GET_ITEM(item, idx++);
923 if (pbackColorSelected == Py_None)
924 pbackColorSelected=ePyObject();
927 int x = PyInt_AsLong(px) + offset.x();
928 int y = PyInt_AsLong(py) + offset.y();
929 int width = PyInt_AsLong(pwidth);
930 int height = PyInt_AsLong(pheight);
931 int filled = PyInt_AsLong(pfilled_perc);
933 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
934 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
936 /* don't do anything if percent out of range */
937 if ((filled < 0) || (filled > 100))
940 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
942 eRect rect(x, y, width, height);
947 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
948 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
952 rect.setRect(x, y, width, bwidth);
955 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
958 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
961 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
964 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
969 ePtr<gPixmap> pixmap;
970 if (PyInt_Check(ppixmap) && data) /* if the pixmap is in fact a number, it refers to the data list */
971 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
973 if (SwigFromPython(pixmap, ppixmap))
975 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
979 painter.blit(pixmap, rect.topLeft(), rect, 0);
987 case TYPE_PIXMAP_ALPHABLEND:
988 case TYPE_PIXMAP_ALPHATEST:
989 case TYPE_PIXMAP: // pixmap
992 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
995 ePyObject px = PyTuple_GET_ITEM(item, 1),
996 py = PyTuple_GET_ITEM(item, 2),
997 pwidth = PyTuple_GET_ITEM(item, 3),
998 pheight = PyTuple_GET_ITEM(item, 4),
999 ppixmap = PyTuple_GET_ITEM(item, 5),
1000 pbackColor, pbackColorSelected;
1002 if (!(px && py && pwidth && pheight && ppixmap))
1004 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
1008 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
1009 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
1011 /* don't do anything if we have 'None' as pixmap */
1012 if (ppixmap == Py_None)
1015 int x = PyInt_AsLong(px) + offset.x();
1016 int y = PyInt_AsLong(py) + offset.y();
1017 int width = PyInt_AsLong(pwidth);
1018 int height = PyInt_AsLong(pheight);
1019 ePtr<gPixmap> pixmap;
1020 if (SwigFromPython(pixmap, ppixmap))
1022 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
1027 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
1030 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
1032 eRect rect(x, y, width, height);
1037 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
1038 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
1041 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0);
1046 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1052 if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection))
1053 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1057 Py_DECREF(buildfunc_ret);
1062 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1064 Py_XDECREF(m_buildFunc);
1066 Py_XINCREF(m_buildFunc);
1069 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1071 Py_XDECREF(m_selectableFunc);
1072 m_selectableFunc=cb;
1073 Py_XINCREF(m_selectableFunc);
1076 int eListboxPythonMultiContent::currentCursorSelectable()
1078 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1079 if (m_list && cursorValid())
1081 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1083 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1084 if (PyTuple_Check(args))
1086 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1089 bool retval = ret == Py_True;
1093 eDebug("call m_selectableFunc failed!!! assume not callable");
1096 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1100 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1101 if (PyList_Check(item))
1103 item = PyList_GET_ITEM(item, 0);
1104 if (item != Py_None)
1106 } else if (PyTuple_Check(item))
1108 item = PyTuple_GET_ITEM(item, 0);
1109 if (item != Py_None)
1112 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1119 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1127 void eListboxPythonMultiContent::setItemHeight(int height)
1129 m_itemheight = height;
1131 m_listbox->setItemHeight(height);
1134 void eListboxPythonMultiContent::setList(ePyObject list)
1136 m_old_clip = m_clip = gRegion::invalidRegion();
1137 eListboxPythonStringContent::setList(list);
1140 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1145 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1146 m_clip -= m_old_clip;
1147 m_old_clip = m_clip;
1150 m_old_clip = m_clip = gRegion::invalidRegion();
1153 void eListboxPythonMultiContent::entryRemoved(int idx)
1156 m_listbox->entryRemoved(idx);
1159 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1161 m_template = tmplate;