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 if (PyTuple_GetItem(data, index) == Py_None)
646 return PyTuple_GetItem(data, index);
649 if (color == Py_None)
655 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
657 gRegion itemregion(eRect(offset, m_itemsize));
658 eListboxStyle *local_style = 0;
659 eRect sel_clip(m_selection_clip);
660 bool cursorValid = this->cursorValid();
661 if (sel_clip.valid())
662 sel_clip.moveBy(offset);
664 /* get local listbox style, if present */
666 local_style = m_listbox->getLocalStyle();
668 painter.clip(itemregion);
669 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, cursorValid);
671 ePyObject items, buildfunc_ret;
673 if (m_list && cursorValid)
675 /* a multicontent list can be used in two ways:
676 either each item is a list of (TYPE,...)-tuples,
677 or there is a template defined, which is a list of (TYPE,...)-tuples,
678 and the list is an unformatted tuple. The template then references items from the list.
680 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
684 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
686 if (PyTuple_Check(items))
687 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
689 eDebug("items is no tuple");
692 eDebug("buildfunc is not callable");
697 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
703 if (!PyList_Check(items))
705 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
710 if (!PyTuple_Check(items))
712 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
719 /* if we have a template, use the template for the actual formatting.
720 we will later detect that "data" is present, and refer to that, instead
721 of the immediate value. */
730 int size = PyList_Size(items);
731 for (int i = start; i < size; ++i)
733 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
737 eDebug("eListboxPythonMultiContent: ?");
741 if (!PyTuple_Check(item))
743 eDebug("eListboxPythonMultiContent did not receive a tuple.");
747 int size = PyTuple_Size(item);
751 eDebug("eListboxPythonMultiContent receive empty tuple.");
755 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
759 case TYPE_TEXT: // text
762 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
764 ePyObject px = PyTuple_GET_ITEM(item, 1),
765 py = PyTuple_GET_ITEM(item, 2),
766 pwidth = PyTuple_GET_ITEM(item, 3),
767 pheight = PyTuple_GET_ITEM(item, 4),
768 pfnt = PyTuple_GET_ITEM(item, 5),
769 pflags = PyTuple_GET_ITEM(item, 6),
770 pstring = PyTuple_GET_ITEM(item, 7),
771 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
773 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
775 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
780 pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data);
783 pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data);
786 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data);
789 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data);
793 pborderWidth = PyTuple_GET_ITEM(item, 12);
794 if (pborderWidth == Py_None)
795 pborderWidth=ePyObject();
798 pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data);
800 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
801 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
803 /* don't do anything if we have 'None' as string */
804 if (pstring == Py_None)
807 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
808 int x = PyInt_AsLong(px) + offset.x();
809 int y = PyInt_AsLong(py) + offset.y();
810 int width = PyInt_AsLong(pwidth);
811 int height = PyInt_AsLong(pheight);
812 int flags = PyInt_AsLong(pflags);
813 int fnt = PyInt_AsLong(pfnt);
814 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
816 if (m_font.find(fnt) == m_font.end())
818 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
822 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
827 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
828 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
831 painter.setFont(m_font[fnt]);
832 painter.renderText(rect, string, flags);
838 eRect rect(eRect(x, y, width, height));
842 unsigned int color = PyInt_AsUnsignedLongMask(pborderColor);
843 painter.setForegroundColor(gRGB(color));
846 rect.setRect(x, y, width, bwidth);
849 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
852 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
855 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
862 case TYPE_PROGRESS_PIXMAP: // Progress
864 (1, x, y, width, height, filled_percent, pixmap [, borderWidth, foreColor, backColor, backColorSelected] )
866 case TYPE_PROGRESS: // Progress
869 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
871 ePyObject px = PyTuple_GET_ITEM(item, 1),
872 py = PyTuple_GET_ITEM(item, 2),
873 pwidth = PyTuple_GET_ITEM(item, 3),
874 pheight = PyTuple_GET_ITEM(item, 4),
875 pfilled_perc = PyTuple_GET_ITEM(item, 5),
876 ppixmap, pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
878 if (type == TYPE_PROGRESS)
880 if (!(px && py && pwidth && pheight && pfilled_perc))
882 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
888 ppixmap = PyTuple_GET_ITEM(item, idx++);
889 if (ppixmap == Py_None)
891 if (!(px && py && pwidth && pheight && pfilled_perc, ppixmap))
893 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS_PIXMAP, x, y, width, height, filled percent, pixmap, [,border width, foreColor, backColor, backColorSelected]))");
900 pborderWidth = PyTuple_GET_ITEM(item, idx++);
901 if (pborderWidth == Py_None)
902 pborderWidth = ePyObject();
906 pforeColor = PyTuple_GET_ITEM(item, idx++);
907 if (pforeColor == Py_None)
908 pforeColor = ePyObject();
912 pforeColorSelected = PyTuple_GET_ITEM(item, idx++);
913 if (pforeColorSelected == Py_None)
914 pforeColorSelected=ePyObject();
918 pbackColor = PyTuple_GET_ITEM(item, idx++);
919 if (pbackColor == Py_None)
920 pbackColor=ePyObject();
924 pbackColorSelected = PyTuple_GET_ITEM(item, idx++);
925 if (pbackColorSelected == Py_None)
926 pbackColorSelected=ePyObject();
929 int x = PyInt_AsLong(px) + offset.x();
930 int y = PyInt_AsLong(py) + offset.y();
931 int width = PyInt_AsLong(pwidth);
932 int height = PyInt_AsLong(pheight);
933 int filled = PyInt_AsLong(pfilled_perc);
935 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
936 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
938 /* don't do anything if percent out of range */
939 if ((filled < 0) || (filled > 100))
942 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
944 eRect rect(x, y, width, height);
949 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
950 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
954 rect.setRect(x, y, width, bwidth);
957 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
960 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
963 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
966 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
971 ePtr<gPixmap> pixmap;
972 if (PyInt_Check(ppixmap) && data) /* if the pixmap is in fact a number, it refers to the data list */
973 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
975 if (SwigFromPython(pixmap, ppixmap))
977 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
981 painter.blit(pixmap, rect.topLeft(), rect, 0);
989 case TYPE_PIXMAP_ALPHABLEND:
990 case TYPE_PIXMAP_ALPHATEST:
991 case TYPE_PIXMAP: // pixmap
994 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
997 ePyObject px = PyTuple_GET_ITEM(item, 1),
998 py = PyTuple_GET_ITEM(item, 2),
999 pwidth = PyTuple_GET_ITEM(item, 3),
1000 pheight = PyTuple_GET_ITEM(item, 4),
1001 ppixmap = PyTuple_GET_ITEM(item, 5),
1002 pbackColor, pbackColorSelected;
1004 if (!(px && py && pwidth && pheight && ppixmap))
1006 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
1010 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
1011 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
1013 /* don't do anything if we have 'None' as pixmap */
1014 if (ppixmap == Py_None)
1017 int x = PyInt_AsLong(px) + offset.x();
1018 int y = PyInt_AsLong(py) + offset.y();
1019 int width = PyInt_AsLong(pwidth);
1020 int height = PyInt_AsLong(pheight);
1021 ePtr<gPixmap> pixmap;
1022 if (SwigFromPython(pixmap, ppixmap))
1024 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
1029 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
1032 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
1034 eRect rect(x, y, width, height);
1039 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
1040 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
1043 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0);
1048 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1054 if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection))
1055 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1059 Py_DECREF(buildfunc_ret);
1064 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1066 Py_XDECREF(m_buildFunc);
1068 Py_XINCREF(m_buildFunc);
1071 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1073 Py_XDECREF(m_selectableFunc);
1074 m_selectableFunc=cb;
1075 Py_XINCREF(m_selectableFunc);
1078 int eListboxPythonMultiContent::currentCursorSelectable()
1080 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1081 if (m_list && cursorValid())
1083 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1085 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1086 if (PyTuple_Check(args))
1088 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1091 bool retval = ret == Py_True;
1095 eDebug("call m_selectableFunc failed!!! assume not callable");
1098 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1102 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1103 if (PyList_Check(item))
1105 item = PyList_GET_ITEM(item, 0);
1106 if (item != Py_None)
1108 } else if (PyTuple_Check(item))
1110 item = PyTuple_GET_ITEM(item, 0);
1111 if (item != Py_None)
1114 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1121 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1129 void eListboxPythonMultiContent::setItemHeight(int height)
1131 m_itemheight = height;
1133 m_listbox->setItemHeight(height);
1136 void eListboxPythonMultiContent::setList(ePyObject list)
1138 m_old_clip = m_clip = gRegion::invalidRegion();
1139 eListboxPythonStringContent::setList(list);
1142 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1147 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1148 m_clip -= m_old_clip;
1149 m_old_clip = m_clip;
1152 m_old_clip = m_clip = gRegion::invalidRegion();
1155 void eListboxPythonMultiContent::entryRemoved(int idx)
1158 m_listbox->entryRemoved(idx);
1161 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1163 Py_XDECREF(m_template);
1164 m_template = tmplate;
1165 Py_XINCREF(m_template);