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)
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();
154 fnt = local_style->m_font;
157 /* if we have a local background color set, use that. */
158 if (local_style->m_background_color_selected_set)
159 painter.setBackgroundColor(local_style->m_background_color_selected);
160 /* same for foreground */
161 if (local_style->m_foreground_color_selected_set)
162 painter.setForegroundColor(local_style->m_foreground_color_selected);
166 /* if we have a local background color set, use that. */
167 if (local_style->m_background_color_set)
168 painter.setBackgroundColor(local_style->m_background_color);
169 /* same for foreground */
170 if (local_style->m_foreground_color_set)
171 painter.setForegroundColor(local_style->m_foreground_color);
174 if (!fnt) fnt = new gFont("Regular", 20);
176 /* if we have no transparent background */
177 if (!local_style || !local_style->m_transparent_background)
179 /* blit background picture, if available (otherwise, clear only) */
180 if (local_style && local_style->m_background && cursorValid)
181 painter.blit(local_style->m_background, offset, eRect(), 0);
186 if (local_style->m_background && cursorValid)
187 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
188 else if (selected && !local_style->m_selection)
192 if (m_list && cursorValid)
195 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
196 painter.setFont(fnt);
198 /* the user can supply tuples, in this case the first one will be displayed. */
199 if (PyTuple_Check(item))
201 if (PyTuple_Size(item) == 1)
203 item = PyTuple_GET_ITEM(item, 0);
206 if (selected && local_style && local_style->m_selection)
207 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
212 int half_height = m_itemsize.height() / 2;
213 painter.fill(eRect(offset.x() + half_height, offset.y() + half_height - 2, m_itemsize.width() - m_itemsize.height(), 4));
216 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
217 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
219 painter.setForegroundColor(gRGB(0x808080));
220 painter.renderText(eRect(text_offset, m_itemsize), string);
223 if (selected && (!local_style || !local_style->m_selection))
224 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
230 void eListboxPythonStringContent::setList(ePyObject list)
233 if (!PyList_Check(list))
235 m_list = ePyObject();
243 m_listbox->entryReset(false);
246 PyObject *eListboxPythonStringContent::getCurrentSelection()
248 if (!(m_list && cursorValid()))
251 ePyObject r = PyList_GET_ITEM(m_list, m_cursor);
256 void eListboxPythonStringContent::invalidateEntry(int index)
259 m_listbox->entryChanged(index);
262 void eListboxPythonStringContent::invalidate()
268 m_listbox->moveSelectionTo(s?s-1:0);
270 m_listbox->invalidate();
274 //////////////////////////////////////
276 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
280 eRect itemrect(offset, m_itemsize);
281 eListboxStyle *local_style = 0;
282 bool cursorValid = this->cursorValid();
284 painter.clip(itemrect);
285 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
287 /* get local listbox style, if present */
289 local_style = m_listbox->getLocalStyle();
293 fnt = local_style->m_font;
296 /* if we have a local background color set, use that. */
297 if (local_style->m_background_color_selected_set)
298 painter.setBackgroundColor(local_style->m_background_color_selected);
299 /* same for foreground */
300 if (local_style->m_foreground_color_selected_set)
301 painter.setForegroundColor(local_style->m_foreground_color_selected);
305 /* if we have a local background color set, use that. */
306 if (local_style->m_background_color_set)
307 painter.setBackgroundColor(local_style->m_background_color);
308 /* same for foreground */
309 if (local_style->m_foreground_color_set)
310 painter.setForegroundColor(local_style->m_foreground_color);
316 fnt2 = new gFont(fnt->family, fnt->pointSize - fnt->pointSize/5);
320 fnt = new gFont("Regular", 20);
321 fnt2 = new gFont("Regular", 16);
324 if (!local_style || !local_style->m_transparent_background)
325 /* if we have no transparent background */
327 /* blit background picture, if available (otherwise, clear only) */
328 if (local_style && local_style->m_background && cursorValid)
329 painter.blit(local_style->m_background, offset, eRect(), 0);
334 if (local_style->m_background && cursorValid)
335 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
336 else if (selected && !local_style->m_selection)
340 if (m_list && cursorValid)
342 /* get current list item */
343 ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
344 ePyObject text, value;
345 painter.setFont(fnt);
347 if (selected && local_style && local_style->m_selection)
348 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
350 /* the first tuple element is a string for the left side.
351 the second one will be called, and the result shall be an tuple.
354 the first one is the type (string).
355 the second one is the value. */
356 if (PyTuple_Check(item))
358 /* handle left part. get item from tuple, convert to string, display. */
359 text = PyTuple_GET_ITEM(item, 0);
360 text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
361 const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
362 eSize item_left = eSize(m_seperation, m_itemsize.height());
363 eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
364 painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
367 /* when we have no label, align value to the left. (FIXME:
368 don't we want to specifiy this individually?) */
369 int value_alignment_left = !*string;
371 /* now, handle the value. get 2nd part from tuple*/
372 if (PyTuple_Size(item) >= 2) // when no 2nd entry is in tuple this is a non selectable entry without config part
373 value = PyTuple_GET_ITEM(item, 1);
377 ePyObject args = PyTuple_New(1);
378 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
380 /* CallObject will call __call__ which should return the value tuple */
381 value = PyObject_CallObject(value, args);
383 if (PyErr_Occurred())
387 /* the PyInt was stolen. */
390 /* check if this is really a tuple */
391 if (value && PyTuple_Check(value))
393 /* convert type to string */
394 ePyObject type = PyTuple_GET_ITEM(value, 0);
395 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
399 if (!strcmp(atype, "text"))
401 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
402 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
403 painter.setFont(fnt2);
404 if (value_alignment_left)
405 painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
407 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
409 /* pvalue is borrowed */
410 } else if (!strcmp(atype, "slider"))
412 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
413 ePyObject psize = PyTuple_GET_ITEM(value, 2);
415 /* convert value to Long. fallback to -1 on error. */
416 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
417 int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
419 /* calc. slider length */
420 int width = item_right.width() * value / size;
421 int height = item_right.height();
425 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
426 //hack - make it customizable
427 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
429 /* pvalue is borrowed */
430 } else if (!strcmp(atype, "mtext"))
432 ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
433 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
434 int xoffs = value_alignment_left ? 0 : m_seperation;
435 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
437 para->renderString(text, 0);
438 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
439 int glyphs = para->size();
443 if (PyTuple_Size(value) >= 3)
444 plist = PyTuple_GET_ITEM(value, 2);
448 if (plist && PyList_Check(plist))
449 entries = PyList_Size(plist);
451 int left=0, right=0, last=-1;
453 for (int i = 0; i < entries; ++i)
455 ePyObject entry = PyList_GET_ITEM(plist, i);
456 int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
458 if ((num < 0) || (num >= glyphs))
459 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
462 if (last+1 != num && last != -1) {
463 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
466 para->setGlyphFlag(num, GS_INVERT);
467 bbox = para->getGlyphBBox(num);
468 if (last+1 != num || last == -1)
470 right = bbox.left() + bbox.width();
473 /* entry is borrowed */
476 bbox = eRect(left, offset.y(), right-left, m_itemsize.height());
479 painter.renderPara(para, ePoint(0, 0));
480 /* pvalue is borrowed */
481 /* plist is 0 or borrowed */
484 /* type is borrowed */
486 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
491 if (selected && (!local_style || !local_style->m_selection))
492 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
498 int eListboxPythonConfigContent::currentCursorSelectable()
500 return eListboxPythonStringContent::currentCursorSelectable();
503 //////////////////////////////////////
505 /* todo: make a real infrastructure here! */
506 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
508 eListboxPythonMultiContent::eListboxPythonMultiContent()
509 :m_clip(gRegion::invalidRegion()), m_old_clip(gRegion::invalidRegion())
513 eListboxPythonMultiContent::~eListboxPythonMultiContent()
515 Py_XDECREF(m_buildFunc);
516 Py_XDECREF(m_selectableFunc);
517 Py_XDECREF(m_template);
520 void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
522 m_selection_clip = rect;
524 rect.moveBy(ePoint(0, m_listbox->getEntryTop()));
529 if (update && m_listbox)
530 m_listbox->entryChanged(m_cursor);
533 static void clearRegionHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColor, bool cursorValid, bool clear=true)
537 unsigned int color = PyInt_AsUnsignedLongMask(pbackColor);
538 painter.setBackgroundColor(gRGB(color));
540 else if (local_style)
542 if (local_style && local_style->m_background_color_set)
543 painter.setBackgroundColor(local_style->m_background_color);
544 if (local_style->m_background && cursorValid)
546 if (local_style->m_transparent_background)
547 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
549 painter.blit(local_style->m_background, offset, eRect(), 0);
552 else if (local_style->m_transparent_background)
559 static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColorSelected, bool cursorValid, bool clear=true)
561 if (pbackColorSelected)
563 unsigned int color = PyInt_AsUnsignedLongMask(pbackColorSelected);
564 painter.setBackgroundColor(gRGB(color));
566 else if (local_style)
568 if (local_style && local_style->m_background_color_selected_set)
569 painter.setBackgroundColor(local_style->m_background_color_selected);
570 if (local_style->m_background && cursorValid)
572 if (local_style->m_transparent_background)
573 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
575 painter.blit(local_style->m_background, offset, eRect(), 0);
583 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)
585 if (selected && sel_clip.valid())
587 gRegion part = rc - sel_clip;
591 style.setStyle(painter, eWindowStyle::styleListboxNormal);
592 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid, clear);
596 part = rc & sel_clip;
600 style.setStyle(painter, eWindowStyle::styleListboxSelected);
601 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid, clear);
608 style.setStyle(painter, eWindowStyle::styleListboxSelected);
609 clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid, clear);
610 if (local_style && local_style->m_selection)
611 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
615 style.setStyle(painter, eWindowStyle::styleListboxNormal);
616 clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid, clear);
621 if (pforeColorSelected)
623 unsigned int color = PyInt_AsUnsignedLongMask(pforeColorSelected);
624 painter.setForegroundColor(gRGB(color));
626 /* if we have a local foreground color set, use that. */
627 else if (local_style && local_style->m_foreground_color_selected_set)
628 painter.setForegroundColor(local_style->m_foreground_color_selected);
634 unsigned int color = PyInt_AsUnsignedLongMask(pforeColor);
635 painter.setForegroundColor(gRGB(color));
637 /* if we have a local foreground color set, use that. */
638 else if (local_style && local_style->m_foreground_color_set)
639 painter.setForegroundColor(local_style->m_foreground_color);
643 static ePyObject lookupColor(ePyObject color, ePyObject data)
645 if (color == Py_None)
648 if ((!color) && (!data))
651 unsigned int icolor = PyInt_AsUnsignedLongMask(color);
653 /* check if we have the "magic" template color */
654 if ((icolor & 0xFF000000) == 0xFF000000)
656 int index = icolor & 0xFFFFFF;
657 if (PyTuple_GetItem(data, index) == Py_None)
659 return PyTuple_GetItem(data, index);
662 if (color == Py_None)
668 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
670 gRegion itemregion(eRect(offset, m_itemsize));
671 eListboxStyle *local_style = 0;
672 eRect sel_clip(m_selection_clip);
673 bool cursorValid = this->cursorValid();
674 if (sel_clip.valid())
675 sel_clip.moveBy(offset);
677 /* get local listbox style, if present */
679 local_style = m_listbox->getLocalStyle();
681 painter.clip(itemregion);
682 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), ePyObject(), ePyObject(), selected, itemregion, sel_clip, offset, cursorValid);
684 ePyObject items, buildfunc_ret;
686 if (m_list && cursorValid)
688 /* a multicontent list can be used in two ways:
689 either each item is a list of (TYPE,...)-tuples,
690 or there is a template defined, which is a list of (TYPE,...)-tuples,
691 and the list is an unformatted tuple. The template then references items from the list.
693 items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
697 if (PyCallable_Check(m_buildFunc)) // when we have a buildFunc then call it
699 if (PyTuple_Check(items))
700 buildfunc_ret = items = PyObject_CallObject(m_buildFunc, items);
702 eDebug("items is no tuple");
705 eDebug("buildfunc is not callable");
710 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
716 if (!PyList_Check(items))
718 eDebug("eListboxPythonMultiContent: list entry %d is not a list (non-templated)", m_cursor);
723 if (!PyTuple_Check(items))
725 eDebug("eListboxPythonMultiContent: list entry %d is not a tuple (templated)", m_cursor);
732 /* if we have a template, use the template for the actual formatting.
733 we will later detect that "data" is present, and refer to that, instead
734 of the immediate value. */
743 int size = PyList_Size(items);
744 for (int i = start; i < size; ++i)
746 ePyObject item = PyList_GET_ITEM(items, i); // borrowed reference!
750 eDebug("eListboxPythonMultiContent: ?");
754 if (!PyTuple_Check(item))
756 eDebug("eListboxPythonMultiContent did not receive a tuple.");
760 int size = PyTuple_Size(item);
764 eDebug("eListboxPythonMultiContent receive empty tuple.");
768 int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
772 case TYPE_TEXT: // text
775 (0, x, y, width, height, fnt, flags, "bla" [, color, colorSelected, backColor, backColorSelected, borderWidth, borderColor] )
777 ePyObject px = PyTuple_GET_ITEM(item, 1),
778 py = PyTuple_GET_ITEM(item, 2),
779 pwidth = PyTuple_GET_ITEM(item, 3),
780 pheight = PyTuple_GET_ITEM(item, 4),
781 pfnt = PyTuple_GET_ITEM(item, 5),
782 pflags = PyTuple_GET_ITEM(item, 6),
783 pstring = PyTuple_GET_ITEM(item, 7),
784 pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, pborderWidth, pborderColor;
786 if (!(px && py && pwidth && pheight && pfnt && pflags && pstring))
788 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string [, color, backColor, backColorSelected, borderWidth, borderColor])");
793 pforeColor = lookupColor(PyTuple_GET_ITEM(item, 8), data);
796 pforeColorSelected = lookupColor(PyTuple_GET_ITEM(item, 9), data);
799 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 10), data);
802 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 11), data);
806 pborderWidth = PyTuple_GET_ITEM(item, 12);
807 if (pborderWidth == Py_None)
808 pborderWidth=ePyObject();
811 pborderColor = lookupColor(PyTuple_GET_ITEM(item, 13), data);
813 if (PyInt_Check(pstring) && data) /* if the string is in fact a number, it refers to the 'data' list. */
814 pstring = PyTuple_GetItem(data, PyInt_AsLong(pstring));
816 /* don't do anything if we have 'None' as string */
817 if (pstring == Py_None)
820 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
821 int x = PyInt_AsLong(px) + offset.x();
822 int y = PyInt_AsLong(py) + offset.y();
823 int width = PyInt_AsLong(pwidth);
824 int height = PyInt_AsLong(pheight);
825 int flags = PyInt_AsLong(pflags);
826 int fnt = PyInt_AsLong(pfnt);
827 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 0;
829 if (m_font.find(fnt) == m_font.end())
831 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
835 eRect rect(x+bwidth, y+bwidth, width-bwidth*2, height-bwidth*2);
840 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
841 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
844 painter.setFont(m_font[fnt]);
845 painter.renderText(rect, string, flags);
851 eRect rect(eRect(x, y, width, height));
855 unsigned int color = PyInt_AsUnsignedLongMask(pborderColor);
856 painter.setForegroundColor(gRGB(color));
859 rect.setRect(x, y, width, bwidth);
862 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
865 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
868 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
875 case TYPE_PROGRESS_PIXMAP: // Progress
877 (1, x, y, width, height, filled_percent, pixmap [, borderWidth, foreColor, backColor, backColorSelected] )
879 case TYPE_PROGRESS: // Progress
882 (1, x, y, width, height, filled_percent [, borderWidth, foreColor, backColor, backColorSelected] )
884 ePyObject px = PyTuple_GET_ITEM(item, 1),
885 py = PyTuple_GET_ITEM(item, 2),
886 pwidth = PyTuple_GET_ITEM(item, 3),
887 pheight = PyTuple_GET_ITEM(item, 4),
888 pfilled_perc = PyTuple_GET_ITEM(item, 5),
889 ppixmap, pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
891 if (type == TYPE_PROGRESS)
893 if (!(px && py && pwidth && pheight && pfilled_perc))
895 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
901 ppixmap = PyTuple_GET_ITEM(item, idx++);
902 if (ppixmap == Py_None)
904 if (!(px && py && pwidth && pheight && pfilled_perc, ppixmap))
906 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS_PIXMAP, x, y, width, height, filled percent, pixmap, [,border width, foreColor, backColor, backColorSelected]))");
913 pborderWidth = PyTuple_GET_ITEM(item, idx++);
914 if (pborderWidth == Py_None)
915 pborderWidth = ePyObject();
919 pforeColor = PyTuple_GET_ITEM(item, idx++);
920 if (pforeColor == Py_None)
921 pforeColor = ePyObject();
925 pforeColorSelected = PyTuple_GET_ITEM(item, idx++);
926 if (pforeColorSelected == Py_None)
927 pforeColorSelected=ePyObject();
931 pbackColor = PyTuple_GET_ITEM(item, idx++);
932 if (pbackColor == Py_None)
933 pbackColor=ePyObject();
937 pbackColorSelected = PyTuple_GET_ITEM(item, idx++);
938 if (pbackColorSelected == Py_None)
939 pbackColorSelected=ePyObject();
942 int x = PyInt_AsLong(px) + offset.x();
943 int y = PyInt_AsLong(py) + offset.y();
944 int width = PyInt_AsLong(pwidth);
945 int height = PyInt_AsLong(pheight);
946 int filled = PyInt_AsLong(pfilled_perc);
948 if ((filled < 0) && data) /* if the string is in a negative number, it refers to the 'data' list. */
949 filled = PyInt_AsLong(PyTuple_GetItem(data, -filled));
951 /* don't do anything if percent out of range */
952 if ((filled < 0) || (filled > 100))
955 int bwidth = pborderWidth ? PyInt_AsLong(pborderWidth) : 2;
957 eRect rect(x, y, width, height);
962 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
963 clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
967 rect.setRect(x, y, width, bwidth);
970 rect.setRect(x, y+bwidth, bwidth, height-bwidth);
973 rect.setRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
976 rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
979 rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
984 ePtr<gPixmap> pixmap;
985 if (PyInt_Check(ppixmap) && data) /* if the pixmap is in fact a number, it refers to the data list */
986 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
988 if (SwigFromPython(pixmap, ppixmap))
990 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
994 painter.blit(pixmap, rect.topLeft(), rect, 0);
1002 case TYPE_PIXMAP_ALPHABLEND:
1003 case TYPE_PIXMAP_ALPHATEST:
1004 case TYPE_PIXMAP: // pixmap
1007 (2, x, y, width, height, pixmap [, backColor, backColorSelected] )
1010 ePyObject px = PyTuple_GET_ITEM(item, 1),
1011 py = PyTuple_GET_ITEM(item, 2),
1012 pwidth = PyTuple_GET_ITEM(item, 3),
1013 pheight = PyTuple_GET_ITEM(item, 4),
1014 ppixmap = PyTuple_GET_ITEM(item, 5),
1015 pbackColor, pbackColorSelected;
1017 if (!(px && py && pwidth && pheight && ppixmap))
1019 eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))");
1023 if (PyInt_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
1024 ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
1026 /* don't do anything if we have 'None' as pixmap */
1027 if (ppixmap == Py_None)
1030 int x = PyInt_AsLong(px) + offset.x();
1031 int y = PyInt_AsLong(py) + offset.y();
1032 int width = PyInt_AsLong(pwidth);
1033 int height = PyInt_AsLong(pheight);
1034 ePtr<gPixmap> pixmap;
1035 if (SwigFromPython(pixmap, ppixmap))
1037 eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
1042 pbackColor = lookupColor(PyTuple_GET_ITEM(item, 6), data);
1045 pbackColorSelected = lookupColor(PyTuple_GET_ITEM(item, 7), data);
1047 eRect rect(x, y, width, height);
1052 bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
1053 clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
1056 painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0);
1061 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
1067 if (selected && !sel_clip.valid() && (!local_style || !local_style->m_selection))
1068 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
1072 Py_DECREF(buildfunc_ret);
1077 void eListboxPythonMultiContent::setBuildFunc(ePyObject cb)
1079 Py_XDECREF(m_buildFunc);
1081 Py_XINCREF(m_buildFunc);
1084 void eListboxPythonMultiContent::setSelectableFunc(ePyObject cb)
1086 Py_XDECREF(m_selectableFunc);
1087 m_selectableFunc=cb;
1088 Py_XINCREF(m_selectableFunc);
1091 int eListboxPythonMultiContent::currentCursorSelectable()
1093 /* each list-entry is a list of tuples. if the first of these is none, it's not selectable */
1094 if (m_list && cursorValid())
1096 if (m_selectableFunc && PyCallable_Check(m_selectableFunc))
1098 ePyObject args = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
1099 if (PyTuple_Check(args))
1101 ePyObject ret = PyObject_CallObject(m_selectableFunc, args);
1104 bool retval = ret == Py_True;
1108 eDebug("call m_selectableFunc failed!!! assume not callable");
1111 eDebug("m_list[m_cursor] is not a tuple!!! assume not callable");
1115 ePyObject item = PyList_GET_ITEM(m_list, m_cursor);
1116 if (PyList_Check(item))
1118 item = PyList_GET_ITEM(item, 0);
1119 if (item != Py_None)
1121 } else if (PyTuple_Check(item))
1123 item = PyTuple_GET_ITEM(item, 0);
1124 if (item != Py_None)
1127 else if (m_buildFunc && PyCallable_Check(m_buildFunc))
1134 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
1142 void eListboxPythonMultiContent::setItemHeight(int height)
1144 m_itemheight = height;
1146 m_listbox->setItemHeight(height);
1149 void eListboxPythonMultiContent::setList(ePyObject list)
1151 m_old_clip = m_clip = gRegion::invalidRegion();
1152 eListboxPythonStringContent::setList(list);
1155 void eListboxPythonMultiContent::updateClip(gRegion &clip)
1160 if (m_old_clip.valid() && !(m_clip-m_old_clip).empty())
1161 m_clip -= m_old_clip;
1162 m_old_clip = m_clip;
1165 m_old_clip = m_clip = gRegion::invalidRegion();
1168 void eListboxPythonMultiContent::entryRemoved(int idx)
1171 m_listbox->entryRemoved(idx);
1174 void eListboxPythonMultiContent::setTemplate(ePyObject tmplate)
1176 Py_XDECREF(m_template);
1177 m_template = tmplate;
1178 Py_XINCREF(m_template);