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);
504 Py_XDECREF(m_template);
507 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
509 m_selection_clip = rect;
511 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
516 if (update && m_listbox)
517 m_listbox->entryChanged(m_cursor);
520 static void clearRegionHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColor, bool cursorValid, bool clear=true)
524 unsigned int color = PyInt_AsUnsignedLongMask(pbackColor);
525 painter.setBackgroundColor(gRGB(color));
527 else if (local_style)
529 if (local_style && local_style->m_background_color_set)
530 painter.setBackgroundColor(local_style->m_background_color);
531 if (local_style->m_background && cursorValid)
533 if (local_style->m_transparent_background)
534 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
536 painter.blit(local_style->m_background, offset, eRect(), 0);
539 else if (local_style->m_transparent_background)
546 static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColorSelected, bool cursorValid, bool clear=true)
548 if (pbackColorSelected)
550 unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
551 painter.setBackgroundColor(gRGB(color));
553 else if (local_style)
555 if (local_style && local_style->m_background_color_selected_set)
556 painter.setBackgroundColor(local_style->m_background_color_selected);
557 if (local_style->m_background && cursorValid)
559 if (local_style->m_transparent_background)
560 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
562 painter.blit(local_style->m_background, offset, eRect(), 0);
570 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)
572 if (selected && sel_clip.valid())
574 gRegion part = rc - sel_clip;
578 style.setStyle(painter, eWindowStyle::styleListboxNormal);
579 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid, clear);
583 part = rc & sel_clip;
587 style.setStyle(painter, eWindowStyle::styleListboxSelected);
588 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid, clear);
595 style.setStyle(painter, eWindowStyle::styleListboxSelected);
596 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid, clear);
597 if (local_style && local_style->m_selection)
598 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
602 style.setStyle(painter, eWindowStyle::styleListboxNormal);
603 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid, clear);
608 if (pforeColorSelected)
610 unsigned int color = PyInt_AsUnsignedLongMask(pforeColorSelected);
611 painter.setForegroundColor(gRGB(color));
613 /* if we have a local foreground color set, use that. */
614 else if (local_style && local_style->m_foreground_color_selected_set)
615 painter.setForegroundColor(local_style->m_foreground_color_selected);
621 unsigned int color = PyInt_AsUnsignedLongMask(pforeColor);
622 painter.setForegroundColor(gRGB(color));
624 /* if we have a local foreground color set, use that. */
625 else if (local_style && local_style->m_foreground_color_set)
626 painter.setForegroundColor(local_style->m_foreground_color);
630 static ePyObject lookupColor(ePyObject color, ePyObject data)
632 if (color == Py_None)
635 if ((!color) && (!data))
638 unsigned int icolor = PyInt_AsUnsignedLongMask(color);
640 /* check if we have the "magic" template color */
641 if ((icolor & 0xFF000000) == 0xFF000000)
643 int index = icolor & 0xFFFFFF;
644 eDebug("[eListboxPythonMultiContent] template color index: %d", index);
645 return PyTuple_GetItem(data, index);
648 if (color == Py_None)
654 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
656 gRegion itemregion(eRect(offset, m_itemsize));
657 eListboxStyle *local_style = 0;
658 eRect sel_clip(m_selection_clip);
659 bool cursorValid = this->cursorValid();
660 if (sel_clip.valid())
661 sel_clip.moveBy(offset);
663 /* get local listbox style, if present */
665 local_style = m_listbox->getLocalStyle();
667 painter.clip(itemregion);
668 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, cursorValid);
670 ePyObject items, buildfunc_ret;
672 if (m_list && cursorValid)
674 /* a multicontent list can be used in two ways:
675 either each item is a list of (TYPE,...)-tuples,
676 or there is a template defined, which is a list of (TYPE,...)-tuples,
677 and the list is an unformatted tuple. The template then references items from the list.
679 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
683 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
685 if (PyTuple_Check(items))
686 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
688 eDebug("items is no tuple");
691 eDebug("buildfunc is not callable");
696 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
702 if (!PyList_Check(items))
704 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
709 if (!PyTuple_Check(items))
711 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
718 /* if we have a template, use the template for the actual formatting.
719 we will later detect that "data" is present, and refer to that, instead
720 of the immediate value. */
729 int size = PyList_Size(items);
730 for (int i = start; i < size; ++i)
732 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
736 eDebug("eListboxPythonMultiContent: ?");
740 if (!PyTuple_Check(item))
742 eDebug("eListboxPythonMultiContent did not receive a tuple.");
746 int size = PyTuple_Size(item);
750 eDebug("eListboxPythonMultiContent receive empty tuple.");
754 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
758 case TYPE_TEXT: // text
761 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
763 ePyObject px = PyTuple_GET_ITEM(item, 1),
764 py = PyTuple_GET_ITEM(item, 2),
765 pwidth = PyTuple_GET_ITEM(item, 3),
766 pheight = PyTuple_GET_ITEM(item, 4),
767 pfnt = PyTuple_GET_ITEM(item, 5),
768 pflags = PyTuple_GET_ITEM(item, 6),
769 pstring = PyTuple_GET_ITEM(item, 7),
770 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
772 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
774 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
779 pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data);
782 pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data);
785 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data);
788 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data);
792 pborderWidth = PyTuple_GET_ITEM(item, 12);
793 if (pborderWidth == Py_None)
794 pborderWidth=ePyObject();
797 pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data);
799 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
800 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
802 /* don't do anything if we have 'None' as string */
803 if (pstring == Py_None)
806 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
807 int x = PyInt_AsLong(px) + offset.x();
808 int y = PyInt_AsLong(py) + offset.y();
809 int width = PyInt_AsLong(pwidth);
810 int height = PyInt_AsLong(pheight);
811 int flags = PyInt_AsLong(pflags);
812 int fnt = PyInt_AsLong(pfnt);
813 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
815 if (m_font.find(fnt) == m_font.end())
817 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
821 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
826 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
827 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
830 painter.setFont(m_font[fnt]);
831 painter.renderText(rect, string, flags);
837 eRect rect(eRect(x, y, width, height));
841 unsigned int color = PyInt_AsUnsignedLongMask(pborderColor);
842 painter.setForegroundColor(gRGB(color));
845 rect.setRect(x, y, width, bwidth);
848 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
851 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
854 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
861 case TYPE_PROGRESS_PIXMAP: // Progress
863 (1, x, y, width, height, filled_percent, pixmap [, borderWidth, foreColor, backColor, backColorSelected] )
865 case TYPE_PROGRESS: // Progress
868 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
870 ePyObject px = PyTuple_GET_ITEM(item, 1),
871 py = PyTuple_GET_ITEM(item, 2),
872 pwidth = PyTuple_GET_ITEM(item, 3),
873 pheight = PyTuple_GET_ITEM(item, 4),
874 pfilled_perc = PyTuple_GET_ITEM(item, 5),
875 ppixmap, pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
877 if (type == TYPE_PROGRESS)
879 if (!(px && py && pwidth && pheight && pfilled_perc))
881 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
887 ppixmap = PyTuple_GET_ITEM(item, idx++);
888 if (ppixmap == Py_None)
890 if (!(px && py && pwidth && pheight && pfilled_perc, ppixmap))
892 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS_PIXMAP, x, y, width, height, filled percent, pixmap, [,border width, foreColor, backColor, backColorSelected]))");
899 pborderWidth = PyTuple_GET_ITEM(item, idx++);
900 if (pborderWidth == Py_None)
901 pborderWidth = ePyObject();
905 pforeColor = PyTuple_GET_ITEM(item, idx++);
906 if (pforeColor == Py_None)
907 pforeColor = ePyObject();
911 pforeColorSelected = PyTuple_GET_ITEM(item, idx++);
912 if (pforeColorSelected == Py_None)
913 pforeColorSelected=ePyObject();
917 pbackColor = PyTuple_GET_ITEM(item, idx++);
918 if (pbackColor == Py_None)
919 pbackColor=ePyObject();
923 pbackColorSelected = PyTuple_GET_ITEM(item, idx++);
924 if (pbackColorSelected == Py_None)
925 pbackColorSelected=ePyObject();
928 int x = PyInt_AsLong(px) + offset.x();
929 int y = PyInt_AsLong(py) + offset.y();
930 int width = PyInt_AsLong(pwidth);
931 int height = PyInt_AsLong(pheight);
932 int filled = PyInt_AsLong(pfilled_perc);
934 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
935 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
937 /* don't do anything if percent out of range */
938 if ((filled < 0) || (filled > 100))
941 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
943 eRect rect(x, y, width, height);
948 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
949 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
953 rect.setRect(x, y, width, bwidth);
956 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
959 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
962 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
965 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
970 ePtr<gPixmap> pixmap;
971 if (PyInt_Check(ppixmap) && data) /* if the pixmap is in fact a number, it refers to the data list */
972 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
974 if (SwigFromPython(pixmap, ppixmap))
976 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
980 painter.blit(pixmap, rect.topLeft(), rect, 0);
988 case TYPE_PIXMAP_ALPHABLEND:
989 case TYPE_PIXMAP_ALPHATEST:
990 case TYPE_PIXMAP: // pixmap
993 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
996 ePyObject px = PyTuple_GET_ITEM(item, 1),
997 py = PyTuple_GET_ITEM(item, 2),
998 pwidth = PyTuple_GET_ITEM(item, 3),
999 pheight = PyTuple_GET_ITEM(item, 4),
1000 ppixmap = PyTuple_GET_ITEM(item, 5),
1001 pbackColor, pbackColorSelected;
1003 if (!(px && py && pwidth && pheight && ppixmap))
1005 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
1009 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
1010 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
1012 /* don't do anything if we have 'None' as pixmap */
1013 if (ppixmap == Py_None)
1016 int x = PyInt_AsLong(px) + offset.x();
1017 int y = PyInt_AsLong(py) + offset.y();
1018 int width = PyInt_AsLong(pwidth);
1019 int height = PyInt_AsLong(pheight);
1020 ePtr<gPixmap> pixmap;
1021 if (SwigFromPython(pixmap, ppixmap))
1023 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
1028 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
1031 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
1033 eRect rect(x, y, width, height);
1038 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
1039 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
1042 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0);
1047 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1053 if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection))
1054 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1058 Py_DECREF(buildfunc_ret);
1063 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1065 Py_XDECREF(m_buildFunc);
1067 Py_XINCREF(m_buildFunc);
1070 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1072 Py_XDECREF(m_selectableFunc);
1073 m_selectableFunc=cb;
1074 Py_XINCREF(m_selectableFunc);
1077 int eListboxPythonMultiContent::currentCursorSelectable()
1079 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1080 if (m_list && cursorValid())
1082 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1084 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1085 if (PyTuple_Check(args))
1087 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1090 bool retval = ret == Py_True;
1094 eDebug("call m_selectableFunc failed!!! assume not callable");
1097 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1101 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1102 if (PyList_Check(item))
1104 item = PyList_GET_ITEM(item, 0);
1105 if (item != Py_None)
1107 } else if (PyTuple_Check(item))
1109 item = PyTuple_GET_ITEM(item, 0);
1110 if (item != Py_None)
1113 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1120 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1128 void eListboxPythonMultiContent::setItemHeight(int height)
1130 m_itemheight = height;
1132 m_listbox->setItemHeight(height);
1135 void eListboxPythonMultiContent::setList(ePyObject list)
1137 m_old_clip = m_clip = gRegion::invalidRegion();
1138 eListboxPythonStringContent::setList(list);
1141 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1146 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1147 m_clip -= m_old_clip;
1148 m_old_clip = m_clip;
1151 m_old_clip = m_clip = gRegion::invalidRegion();
1154 void eListboxPythonMultiContent::entryRemoved(int idx)
1157 m_listbox->entryRemoved(idx);
1160 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1162 Py_XDECREF(m_template);
1163 m_template = tmplate;
1164 Py_XINCREF(m_template);