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(): m_itemheight(25)
56 eListboxPythonStringContent::~eListboxPythonStringContent()
61 void eListboxPythonStringContent::cursorHome()
66 void eListboxPythonStringContent::cursorEnd()
71 int eListboxPythonStringContent::cursorMove(int count)
77 else if (m_cursor > size())
82 int eListboxPythonStringContent::cursorValid()
84 return m_cursor < size();
87 int eListboxPythonStringContent::cursorSet(int n)
93 else if (m_cursor > size())
98 int eListboxPythonStringContent::cursorGet()
103 int eListboxPythonStringContent::currentCursorSelectable()
105 if (m_list && cursorValid())
107 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
108 if (!PyTuple_Check(item))
110 if (PyTuple_Size(item) >= 2)
116 void eListboxPythonStringContent::cursorSave()
118 m_saved_cursor = m_cursor;
121 void eListboxPythonStringContent::cursorRestore()
123 m_cursor = m_saved_cursor;
126 int eListboxPythonStringContent::size()
130 return PyList_Size(m_list);
133 void eListboxPythonStringContent::setSize(const eSize &size)
138 void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
140 ePtr<gFont> fnt = new gFont("Regular", 20);
141 painter.clip(eRect(offset, m_itemsize));
142 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
144 eListboxStyle *local_style = 0;
146 /* get local listbox style, if present */
148 local_style = m_listbox->getLocalStyle();
154 /* if we have a local background color set, use that. */
155 if (local_style->m_background_color_selected_set)
156 painter.setBackgroundColor(local_style->m_background_color_selected);
157 /* same for foreground */
158 if (local_style->m_foreground_color_selected_set)
159 painter.setForegroundColor(local_style->m_foreground_color_selected);
163 /* if we have a local background color set, use that. */
164 if (local_style->m_background_color_set)
165 painter.setBackgroundColor(local_style->m_background_color);
166 /* same for foreground */
167 if (local_style->m_foreground_color_set)
168 painter.setForegroundColor(local_style->m_foreground_color);
172 /* if we have no transparent background */
173 if (!local_style || !local_style->m_transparent_background)
175 /* blit background picture, if available (otherwise, clear only) */
176 if (local_style && local_style->m_background)
177 painter.blit(local_style->m_background, offset, eRect(), 0);
182 if (local_style->m_background)
183 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
184 else if (selected && !local_style->m_selection)
188 if (m_list && cursorValid())
191 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
192 painter.setFont(fnt);
194 /* the user can supply tuples, in this case the first one will be displayed. */
195 if (PyTuple_Check(item))
197 if (PyTuple_Size(item) == 1)
199 item = PyTuple_GET_ITEM(item, 0);
202 if (selected && local_style && local_style->m_selection)
203 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
208 int half_height = m_itemsize.height() / 2;
209 painter.fill(eRect(offset.x() + half_height, offset.y() + half_height - 2, m_itemsize.width() - m_itemsize.height(), 4));
212 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
213 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
215 painter.setForegroundColor(gRGB(0x808080));
216 painter.renderText(eRect(text_offset, m_itemsize), string);
219 if (selected && (!local_style || !local_style->m_selection))
220 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
226 void eListboxPythonStringContent::setList(ePyObject list)
229 if (!PyList_Check(list))
231 m_list = ePyObject();
239 m_listbox->entryReset(false);
242 PyObject *eListboxPythonStringContent::getCurrentSelection()
244 if (!(m_list && cursorValid()))
247 ePyObject r = PyList_GET_ITEM(m_list, m_cursor);
252 void eListboxPythonStringContent::invalidateEntry(int index)
255 m_listbox->entryChanged(index);
258 void eListboxPythonStringContent::invalidate()
264 m_listbox->moveSelectionTo(s?s-1:0);
266 m_listbox->invalidate();
270 //////////////////////////////////////
272 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
274 ePtr<gFont> fnt = new gFont("Regular", 20);
275 ePtr<gFont> fnt2 = new gFont("Regular", 16);
276 eRect itemrect(offset, m_itemsize);
277 eListboxStyle *local_style = 0;
279 painter.clip(itemrect);
280 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
282 /* get local listbox style, if present */
284 local_style = m_listbox->getLocalStyle();
290 /* if we have a local background color set, use that. */
291 if (local_style->m_background_color_selected_set)
292 painter.setBackgroundColor(local_style->m_background_color_selected);
293 /* same for foreground */
294 if (local_style->m_foreground_color_selected_set)
295 painter.setForegroundColor(local_style->m_foreground_color_selected);
299 /* if we have a local background color set, use that. */
300 if (local_style->m_background_color_set)
301 painter.setBackgroundColor(local_style->m_background_color);
302 /* same for foreground */
303 if (local_style->m_foreground_color_set)
304 painter.setForegroundColor(local_style->m_foreground_color);
308 if (!local_style || !local_style->m_transparent_background)
309 /* if we have no transparent background */
311 /* blit background picture, if available (otherwise, clear only) */
312 if (local_style && local_style->m_background)
313 painter.blit(local_style->m_background, offset, eRect(), 0);
318 if (local_style->m_background)
319 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
320 else if (selected && !local_style->m_selection)
324 if (m_list && cursorValid())
326 /* get current list item */
327 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
328 ePyObject text, value;
329 painter.setFont(fnt);
331 if (selected && local_style && local_style->m_selection)
332 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
334 /* the first tuple element is a string for the left side.
335 the second one will be called, and the result shall be an tuple.
338 the first one is the type (string).
339 the second one is the value. */
340 if (PyTuple_Check(item))
342 /* handle left part. get item from tuple, convert to string, display. */
344 text = PyTuple_GET_ITEM(item, 0);
345 text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
346 const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
347 eSize item_left = eSize(m_seperation, m_itemsize.height());
348 eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
349 painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
352 /* when we have no label, align value to the left. (FIXME:
353 don't we want to specifiy this individually?) */
354 int value_alignment_left = !*string;
356 /* now, handle the value. get 2nd part from tuple*/
357 value = PyTuple_GET_ITEM(item, 1);
360 ePyObject args = PyTuple_New(1);
361 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
363 /* CallObject will call __call__ which should return the value tuple */
364 value = PyObject_CallObject(value, args);
366 if (PyErr_Occurred())
370 /* the PyInt was stolen. */
373 /* check if this is really a tuple */
374 if (value && PyTuple_Check(value))
376 /* convert type to string */
377 ePyObject type = PyTuple_GET_ITEM(value, 0);
378 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
382 if (!strcmp(atype, "text"))
384 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
385 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
386 painter.setFont(fnt2);
387 if (value_alignment_left)
388 painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
390 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
392 /* pvalue is borrowed */
393 } else if (!strcmp(atype, "slider"))
395 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
396 ePyObject psize = PyTuple_GET_ITEM(value, 2);
398 /* convert value to Long. fallback to -1 on error. */
399 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
400 int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
402 /* calc. slider length */
403 int width = item_right.width() * value / size;
404 int height = item_right.height();
408 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
409 //hack - make it customizable
410 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
412 /* pvalue is borrowed */
413 } else if (!strcmp(atype, "mtext"))
415 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
416 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
417 int xoffs = value_alignment_left ? 0 : m_seperation;
418 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
420 para->renderString(text, 0);
421 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
422 int glyphs = para->size();
426 if (PyTuple_Size(value) >= 3)
427 plist = PyTuple_GET_ITEM(value, 2);
431 if (plist && PyList_Check(plist))
432 entries = PyList_Size(plist);
434 int left=0, right=0, last=-1;
436 for (int i = 0; i < entries; ++i)
438 ePyObject entry = PyList_GET_ITEM(plist, i);
439 int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
441 if ((num < 0) || (num >= glyphs))
442 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
445 if (last+1 != num && last != -1) {
446 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
449 para->setGlyphFlag(num, GS_INVERT);
450 bbox = para->getGlyphBBox(num);
451 if (last+1 != num || last == -1)
453 right = bbox.left() + bbox.width();
456 /* entry is borrowed */
459 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
462 painter.renderPara(para, ePoint(0, 0));
463 /* pvalue is borrowed */
464 /* plist is 0 or borrowed */
467 /* type is borrowed */
469 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
470 /* value is borrowed */
473 if (selected && (!local_style || !local_style->m_selection))
474 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
480 int eListboxPythonConfigContent::currentCursorSelectable()
482 return eListboxPythonStringContent::currentCursorSelectable();
485 //////////////////////////////////////
487 /* todo: make a real infrastructure here! */
488 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
490 eListboxPythonMultiContent::eListboxPythonMultiContent()
491 :m_clip(gRegion::invalidRegion()), m_old_clip(gRegion::invalidRegion())
495 eListboxPythonMultiContent::~eListboxPythonMultiContent()
497 Py_XDECREF(m_buildFunc);
498 Py_XDECREF(m_selectableFunc);
501 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
503 m_selection_clip = rect;
505 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
510 if (update && m_listbox)
511 m_listbox->entryChanged(m_cursor);
514 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)
516 if (selected && sel_clip.valid())
518 gRegion part = rc - sel_clip;
522 style.setStyle(painter, eWindowStyle::styleListboxNormal);
525 int color = PyInt_AsLong(pbackColor);
526 painter.setBackgroundColor(gRGB(color));
527 } // transparent background?
528 // if we have a local background color set, use that.
529 else if (local_style && local_style->m_background_color_set)
530 painter.setBackgroundColor(local_style->m_background_color);
531 if (!pbackColor && local_style && local_style->m_transparent_background)
538 part = rc & sel_clip;
542 style.setStyle(painter, eWindowStyle::styleListboxSelected);
543 if (pbackColorSelected)
545 int color = PyInt_AsLong(pbackColorSelected);
546 painter.setBackgroundColor(gRGB(color));
548 else if (local_style && local_style->m_background_color_selected_set)
549 painter.setBackgroundColor(local_style->m_background_color_selected);
559 style.setStyle(painter, eWindowStyle::styleListboxSelected);
560 if (pbackColorSelected)
562 int color = PyInt_AsLong(pbackColorSelected);
563 painter.setBackgroundColor(gRGB(color));
565 else if (local_style && local_style->m_background_color_selected_set)
566 painter.setBackgroundColor(local_style->m_background_color_selected);
571 style.setStyle(painter, eWindowStyle::styleListboxNormal);
574 int color = PyInt_AsLong(pbackColor);
575 painter.setBackgroundColor(gRGB(color));
576 }/* if we have a local background color set, use that. */
577 else if (local_style && local_style->m_background_color_set)
578 painter.setBackgroundColor(local_style->m_background_color);
579 /* if we have no transparent background */
580 if (!pbackColor && local_style && local_style->m_transparent_background)
588 if (pforeColorSelected)
590 int color = PyInt_AsLong(pforeColorSelected);
591 painter.setForegroundColor(gRGB(color));
593 /* if we have a local foreground color set, use that. */
594 else if (local_style && local_style->m_foreground_color_selected_set)
595 painter.setForegroundColor(local_style->m_foreground_color_selected);
601 int color = PyInt_AsLong(pforeColor);
602 painter.setForegroundColor(gRGB(color));
604 /* if we have a local foreground color set, use that. */
605 else if (local_style && local_style->m_foreground_color_set)
606 painter.setForegroundColor(local_style->m_foreground_color);
610 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
612 gRegion itemregion(eRect(offset, m_itemsize));
613 eListboxStyle *local_style = 0;
614 eRect sel_clip(m_selection_clip);
615 if (sel_clip.valid())
616 sel_clip.moveBy(offset);
618 /* get local listbox style, if present */
620 local_style = m_listbox->getLocalStyle();
622 painter.clip(itemregion);
623 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip);
627 if (m_list && cursorValid())
629 /* a multicontent list can be used in two ways:
630 either each item is a list of (TYPE,...)-tuples,
631 or there is a template defined, which is a list of (TYPE,...)-tuples,
632 and the list is an unformatted tuple. The template then references items from the list.
634 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
638 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
640 if (PyTuple_Check(items))
641 items = PyObject_CallObject(m_buildFunc, items);
643 eDebug("items is no tuple");
646 eDebug("buildfunc is not callable");
651 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
657 if (!PyList_Check(items))
659 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
664 if (!PyTuple_Check(items))
666 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
673 /* if we have a template, use the template for the actual formatting.
674 we will later detect that "data" is present, and refer to that, instead
675 of the immediate value. */
684 int size = PyList_Size(items);
685 for (int i = start; i < size; ++i)
687 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
691 eDebug("eListboxPythonMultiContent: ?");
695 if (!PyTuple_Check(item))
697 eDebug("eListboxPythonMultiContent did not receive a tuple.");
701 int size = PyTuple_Size(item);
705 eDebug("eListboxPythonMultiContent receive empty tuple.");
709 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
713 case TYPE_TEXT: // text
716 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
718 ePyObject px = PyTuple_GET_ITEM(item, 1),
719 py = PyTuple_GET_ITEM(item, 2),
720 pwidth = PyTuple_GET_ITEM(item, 3),
721 pheight = PyTuple_GET_ITEM(item, 4),
722 pfnt = PyTuple_GET_ITEM(item, 5),
723 pflags = PyTuple_GET_ITEM(item, 6),
724 pstring = PyTuple_GET_ITEM(item, 7),
725 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
727 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
729 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
735 pforeColor = PyTuple_GET_ITEM(item, 8);
736 if (pforeColor == Py_None)
737 pforeColor=ePyObject();
741 pforeColorSelected = PyTuple_GET_ITEM(item, 9);
742 if (pforeColorSelected == Py_None)
743 pforeColorSelected=ePyObject();
747 pbackColor = PyTuple_GET_ITEM(item, 10);
748 if (pbackColor == Py_None)
749 pbackColor=ePyObject();
753 pbackColorSelected = PyTuple_GET_ITEM(item, 11);
754 if (pbackColorSelected == Py_None)
755 pbackColorSelected=ePyObject();
759 pborderWidth = PyTuple_GET_ITEM(item, 12);
760 if (pborderWidth == Py_None)
761 pborderWidth=ePyObject();
765 pborderColor = PyTuple_GET_ITEM(item, 13);
766 if (pborderColor == Py_None)
767 pborderColor=ePyObject();
770 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
771 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
773 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
774 int x = PyInt_AsLong(px) + offset.x();
775 int y = PyInt_AsLong(py) + offset.y();
776 int width = PyInt_AsLong(pwidth);
777 int height = PyInt_AsLong(pheight);
778 int flags = PyInt_AsLong(pflags);
779 int fnt = PyInt_AsLong(pfnt);
780 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
782 if (m_font.find(fnt) == m_font.end())
784 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
788 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
793 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
796 painter.setFont(m_font[fnt]);
797 painter.renderText(rect, string, flags);
803 eRect rect(eRect(x, y, width, height));
807 int color = PyInt_AsLong(pborderColor);
808 painter.setForegroundColor(gRGB(color));
811 rect.setRect(x, y, width, bwidth);
814 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
817 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
820 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
827 case TYPE_PROGRESS: // Progress
830 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
832 ePyObject px = PyTuple_GET_ITEM(item, 1),
833 py = PyTuple_GET_ITEM(item, 2),
834 pwidth = PyTuple_GET_ITEM(item, 3),
835 pheight = PyTuple_GET_ITEM(item, 4),
836 pfilled_perc = PyTuple_GET_ITEM(item, 5),
837 pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
839 if (!(px && py && pwidth && pheight && pfilled_perc))
841 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
847 pborderWidth = PyTuple_GET_ITEM(item, 6);
848 if (pborderWidth == Py_None)
849 pborderWidth = ePyObject();
853 pforeColor = PyTuple_GET_ITEM(item, 7);
854 if (pforeColor == Py_None)
855 pforeColor = ePyObject();
859 pforeColorSelected = PyTuple_GET_ITEM(item, 8);
860 if (pforeColorSelected == Py_None)
861 pforeColorSelected=ePyObject();
865 pbackColor = PyTuple_GET_ITEM(item, 9);
866 if (pbackColor == Py_None)
867 pbackColor=ePyObject();
871 pbackColorSelected = PyTuple_GET_ITEM(item, 10);
872 if (pbackColorSelected == Py_None)
873 pbackColorSelected=ePyObject();
876 int x = PyInt_AsLong(px) + offset.x();
877 int y = PyInt_AsLong(py) + offset.y();
878 int width = PyInt_AsLong(pwidth);
879 int height = PyInt_AsLong(pheight);
880 int filled = PyInt_AsLong(pfilled_perc);
882 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
883 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
885 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
887 eRect rect(x, y, width, height);
892 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip);
896 rect.setRect(x, y, width, bwidth);
899 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
902 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
905 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
909 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
916 case TYPE_PIXMAP_ALPHATEST:
917 case TYPE_PIXMAP: // pixmap
920 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
923 ePyObject px = PyTuple_GET_ITEM(item, 1),
924 py = PyTuple_GET_ITEM(item, 2),
925 pwidth = PyTuple_GET_ITEM(item, 3),
926 pheight = PyTuple_GET_ITEM(item, 4),
927 ppixmap = PyTuple_GET_ITEM(item, 5),
928 pbackColor, pbackColorSelected;
930 if (!(px && py && pwidth && pheight && ppixmap))
932 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
936 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
937 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
939 int x = PyInt_AsLong(px) + offset.x();
940 int y = PyInt_AsLong(py) + offset.y();
941 int width = PyInt_AsLong(pwidth);
942 int height = PyInt_AsLong(pheight);
943 ePtr<gPixmap> pixmap;
944 if (SwigFromPython(pixmap, ppixmap))
946 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
952 pbackColor = PyTuple_GET_ITEM(item, 6);
953 if (pbackColor == Py_None)
954 pbackColor=ePyObject();
958 pbackColorSelected = PyTuple_GET_ITEM(item, 7);
959 if (pbackColorSelected == Py_None)
960 pbackColorSelected=ePyObject();
963 eRect rect(x, y, width, height);
968 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip);
971 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
976 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
983 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
986 if (m_buildFunc && PyCallable_Check(m_buildFunc) && items)
992 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
994 Py_XDECREF(m_buildFunc);
996 Py_XINCREF(m_buildFunc);
999 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1001 Py_XDECREF(m_selectableFunc);
1002 m_selectableFunc=cb;
1003 Py_XINCREF(m_selectableFunc);
1006 int eListboxPythonMultiContent::currentCursorSelectable()
1008 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1009 if (m_list && cursorValid())
1011 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1013 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1014 if (PyTuple_Check(args))
1016 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1018 return ret == Py_True;
1019 eDebug("call m_selectableFunc failed!!! assume not callable");
1022 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1026 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1027 if (PyList_Check(item))
1029 item = PyList_GET_ITEM(item, 0);
1030 if (item != Py_None)
1032 } else if (PyTuple_Check(item))
1034 item = PyTuple_GET_ITEM(item, 0);
1035 if (item != Py_None)
1038 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1045 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1053 void eListboxPythonMultiContent::setItemHeight(int height)
1055 m_itemheight = height;
1057 m_listbox->setItemHeight(height);
1060 void eListboxPythonMultiContent::setList(ePyObject list)
1062 m_old_clip = m_clip = gRegion::invalidRegion();
1063 eListboxPythonStringContent::setList(list);
1066 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1071 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1072 m_clip -= m_old_clip;
1073 m_old_clip = m_clip;
1076 m_old_clip = m_clip = gRegion::invalidRegion();
1079 void eListboxPythonMultiContent::entryRemoved(int idx)
1082 m_listbox->entryRemoved(idx);
1085 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1087 m_template = tmplate;