f5ae2b3837d3507d8b2239f4bd27e7fb42c8f4fa
[enigma2.git] / lib / gui / elistboxcontent.cpp
1 #include <lib/gui/elistbox.h>
2 #include <lib/gui/elistboxcontent.h>
3 #include <lib/gdi/font.h>
4 #include <Python.h>
5
6 /*
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
9     the list.
10     
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.
14     
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.
18     
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.
24     
25     Although cursorSet is provided, it should be only used when there is no
26     other way, as it involves iterating trough the list.
27  */
28
29 iListboxContent::~iListboxContent()
30 {
31 }
32
33 iListboxContent::iListboxContent(): m_listbox(0)
34 {
35 }
36
37 void iListboxContent::setListbox(eListbox *lb)
38 {
39         m_listbox = lb;
40 }
41
42 DEFINE_REF(eListboxTestContent);
43
44 void eListboxTestContent::cursorHome()
45 {
46         m_cursor = 0;
47 }
48
49 void eListboxTestContent::cursorEnd()
50 {
51         m_cursor = size();
52 }
53
54 int eListboxTestContent::cursorMove(int count)
55 {
56         m_cursor += count;
57         
58         if (m_cursor < 0)
59                 cursorHome();
60         else if (m_cursor > size())
61                 cursorEnd();
62         return 0;
63 }
64
65 int eListboxTestContent::cursorValid()
66 {
67         return m_cursor < size();
68 }
69
70 int eListboxTestContent::cursorSet(int n)
71 {
72         m_cursor = n;
73         
74         if (m_cursor < 0)
75                 cursorHome();
76         else if (m_cursor > size())
77                 cursorEnd();
78         return 0;
79 }
80
81 int eListboxTestContent::cursorGet()
82 {
83         return m_cursor;
84 }
85
86 void eListboxTestContent::cursorSave()
87 {
88         m_saved_cursor = m_cursor;
89 }
90
91 void eListboxTestContent::cursorRestore()
92 {
93         m_cursor = m_saved_cursor;
94 }
95
96 int eListboxTestContent::size()
97 {
98         return 10;
99 }
100         
101 RESULT eListboxTestContent::connectItemChanged(const Slot0<void> &itemChanged, ePtr<eConnection> &connection)
102 {
103         return 0;
104 }
105
106 void eListboxTestContent::setSize(const eSize &size)
107 {
108         m_size = size;
109 }
110
111 void eListboxTestContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
112 {
113         ePtr<gFont> fnt = new gFont("Regular", 20);
114         painter.clip(eRect(offset, m_size));
115         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
116         painter.clear();
117
118         if (cursorValid())
119         {
120                 painter.setFont(fnt);
121                 char string[10];
122                 sprintf(string, "%d.)", m_cursor);
123                 
124                 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
125                 
126                 painter.renderText(eRect(text_offset, m_size), string);
127                 
128                 if (selected)
129                         style.drawFrame(painter, eRect(offset, m_size), eWindowStyle::frameListboxEntry);
130         }
131         
132         painter.clippop();
133 }
134
135 //////////////////////////////////////
136
137 DEFINE_REF(eListboxStringContent);
138
139 eListboxStringContent::eListboxStringContent()
140 {
141         m_size = 0;
142         cursorHome();
143 }
144
145 void eListboxStringContent::cursorHome()
146 {
147         m_cursor = m_list.begin();
148         m_cursor_number = 0;
149 }
150
151 void eListboxStringContent::cursorEnd()
152 {
153         m_cursor = m_list.end();
154         m_cursor_number = m_size;
155 }
156
157 int eListboxStringContent::cursorMove(int count)
158 {
159         if (count > 0)
160         {
161                 while (count && (m_cursor != m_list.end()))
162                 {
163                         ++m_cursor;
164                         ++m_cursor_number;
165                         --count;
166                 }
167         } else if (count < 0)
168         {
169                 while (count && (m_cursor != m_list.begin()))
170                 {
171                         --m_cursor;
172                         --m_cursor_number;
173                         ++count;
174                 }
175         }
176         
177         return 0;
178 }
179
180 int eListboxStringContent::cursorValid()
181 {
182         return m_cursor != m_list.end();
183 }
184
185 int eListboxStringContent::cursorSet(int n)
186 {
187         cursorHome();
188         cursorMove(n);
189         
190         return 0;
191 }
192
193 int eListboxStringContent::cursorGet()
194 {
195         return m_cursor_number;
196 }
197
198 void eListboxStringContent::cursorSave()
199 {
200         m_saved_cursor = m_cursor;
201         m_saved_cursor_number = m_cursor_number;
202 }
203
204 void eListboxStringContent::cursorRestore()
205 {
206         m_cursor = m_saved_cursor;
207         m_cursor_number = m_saved_cursor_number;
208 }
209
210 int eListboxStringContent::size()
211 {
212         return m_size;
213 }
214         
215 void eListboxStringContent::setSize(const eSize &size)
216 {
217         m_itemsize = size;
218 }
219
220 void eListboxStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
221 {
222         ePtr<gFont> fnt = new gFont("Regular", 20);
223         painter.clip(eRect(offset, m_itemsize));
224         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
225         painter.clear();
226         
227         eDebug("item %d", m_cursor_number);
228         if (cursorValid())
229         {
230                 eDebug("is valid..");
231                 painter.setFont(fnt);
232                 
233                 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
234                 
235                 painter.renderText(eRect(text_offset, m_itemsize), *m_cursor);
236                 
237                 if (selected)
238                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
239         }
240         
241         painter.clippop();
242 }
243
244 void eListboxStringContent::setList(std::list<std::string> &list)
245 {
246         m_list = list;
247         m_size = list.size();
248         cursorHome();
249         m_listbox->entryReset(false);
250 }
251
252 //////////////////////////////////////
253
254 DEFINE_REF(eListboxPythonStringContent);
255
256 eListboxPythonStringContent::eListboxPythonStringContent()
257 {
258         m_list = 0;
259 }
260
261 eListboxPythonStringContent::~eListboxPythonStringContent()
262 {
263         Py_XDECREF(m_list);
264 }
265
266 void eListboxPythonStringContent::cursorHome()
267 {
268         m_cursor = 0;
269 }
270
271 void eListboxPythonStringContent::cursorEnd()
272 {
273         m_cursor = size();
274 }
275
276 int eListboxPythonStringContent::cursorMove(int count)
277 {
278         m_cursor += count;
279         
280         if (m_cursor < 0)
281                 cursorHome();
282         else if (m_cursor > size())
283                 cursorEnd();
284         return 0;
285 }
286
287 int eListboxPythonStringContent::cursorValid()
288 {
289         return m_cursor < size();
290 }
291
292 int eListboxPythonStringContent::cursorSet(int n)
293 {
294         m_cursor = n;
295         
296         if (m_cursor < 0)
297                 cursorHome();
298         else if (m_cursor > size())
299                 cursorEnd();
300         return 0;
301 }
302
303 int eListboxPythonStringContent::cursorGet()
304 {
305         return m_cursor;
306 }
307
308 void eListboxPythonStringContent::cursorSave()
309 {
310         m_saved_cursor = m_cursor;
311 }
312
313 void eListboxPythonStringContent::cursorRestore()
314 {
315         m_cursor = m_saved_cursor;
316 }
317
318 int eListboxPythonStringContent::size()
319 {
320         if (!m_list)
321                 return 0;
322         return PyList_Size(m_list);
323 }
324         
325 void eListboxPythonStringContent::setSize(const eSize &size)
326 {
327         m_itemsize = size;
328 }
329
330 void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
331 {
332         ePtr<gFont> fnt = new gFont("Regular", 20);
333         painter.clip(eRect(offset, m_itemsize));
334         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
335         painter.clear();
336
337         if (m_list && cursorValid())
338         {
339                 PyObject *item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
340                 painter.setFont(fnt);
341
342                         /* the user can supply tuples, in this case the first one will be displayed. */         
343                 if (PyTuple_Check(item))
344                         item = PyTuple_GET_ITEM(item, 0);
345                 
346                 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
347                 
348                 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
349                 
350                 painter.renderText(eRect(text_offset, m_itemsize), string);
351                 
352                 if (selected)
353                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
354         }
355         
356         painter.clippop();
357 }
358
359 void eListboxPythonStringContent::setList(PyObject *list)
360 {
361         Py_XDECREF(m_list);
362         if (!PyList_Check(list))
363         {
364                 m_list = 0;
365         } else
366         {
367                 m_list = list;
368                 Py_INCREF(m_list);
369         }
370
371         if (m_listbox)
372                 m_listbox->entryReset(false);
373 }
374
375 PyObject *eListboxPythonStringContent::getCurrentSelection()
376 {
377         if (!(m_list && cursorValid()))
378         {
379                 Py_INCREF(Py_None);
380                 return Py_None;
381         }
382         PyObject *r = PyList_GET_ITEM(m_list, m_cursor);
383         Py_XINCREF(r);
384         return r;
385 }
386
387 void eListboxPythonStringContent::invalidateEntry(int index)
388 {
389         if (m_listbox)
390                 m_listbox->entryChanged(index);
391 }
392
393 void eListboxPythonStringContent::invalidate()
394 {
395         if (m_listbox)
396                 m_listbox->invalidate();
397 }
398
399 //////////////////////////////////////
400
401 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
402 {
403         ePtr<gFont> fnt = new gFont("Regular", 20);
404         ePtr<gFont> fnt2 = new gFont("Regular", 16);
405         eRect itemrect(offset, m_itemsize);
406         painter.clip(itemrect);
407         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
408         painter.clear();
409
410         if (m_list && cursorValid())
411         {
412                         /* get current list item */
413                 PyObject *item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
414                 PyObject *text = 0, *value = 0;
415                 painter.setFont(fnt);
416
417                         /* the first tuple element is a string for the left side.
418                            the second one will be called, and the result shall be an tuple.
419                            
420                            of this tuple,
421                            the first one is the type (string).
422                            the second one is the value. */
423                 if (PyTuple_Check(item))
424                 {
425                                 /* handle left part. get item from tuple, convert to string, display. */
426                                 
427                         text = PyTuple_GET_ITEM(item, 0);
428                         text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
429                         const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
430                         eSize item_left = eSize(m_seperation, m_itemsize.height());
431                         eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
432                         painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
433                         Py_XDECREF(text);
434                         
435                                 /* when we have no label, align value to the left. (FIXME: 
436                                    don't we want to specifiy this individually?) */
437                         int value_alignment_left = !*string;
438                         
439                                 /* now, handle the value. get 2nd part from tuple*/
440                         value = PyTuple_GET_ITEM(item, 1);
441                         if (value)
442                         {
443                                 PyObject *args = PyTuple_New(1);
444                                 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
445                                 
446                                         /* CallObject will call __call__ which should return the value tuple */
447                                 value = PyObject_CallObject(value, args);
448                                 
449                                 if (PyErr_Occurred())
450                                         PyErr_Print();
451
452                                 Py_DECREF(args);
453                                         /* the PyInt was stolen. */
454                         }
455                         
456                                 /*  check if this is really a tuple */
457                         if (value && PyTuple_Check(value))
458                         {
459                                         /* convert type to string */
460                                 PyObject *type = PyTuple_GET_ITEM(value, 0);
461                                 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
462                                 
463                                 if (atype)
464                                 {
465                                         if (!strcmp(atype, "text"))
466                                         {
467                                                 PyObject *pvalue = PyTuple_GET_ITEM(value, 1);
468                                                 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
469                                                 painter.setFont(fnt2);
470                                                 if (value_alignment_left)
471                                                         painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
472                                                 else
473                                                         painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
474
475                                                         /* pvalue is borrowed */
476                                         } else if (!strcmp(atype, "slider"))
477                                         {
478                                                 PyObject *pvalue = PyTuple_GET_ITEM(value, 1);
479                                                 PyObject *psize = PyTuple_GET_ITEM(value, 2);
480                                                 
481                                                         /* convert value to Long. fallback to -1 on error. */
482                                                 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
483                                                 int size = (pvalue && PyInt_Check(psize)) ? PyInt_AsLong(psize) : 100;
484                                                 
485                                                         /* calc. slider length */
486                                                 int width = item_right.width() * value / size;
487                                                 int height = item_right.height();
488                                                 
489                                                                                                 
490                                                         /* draw slider */
491                                                 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
492                                                 //hack - make it customizable
493                                                 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
494                                                 
495                                                         /* pvalue is borrowed */
496                                         } else if (!strcmp(atype, "mtext"))
497                                         {
498                                                 PyObject *pvalue = PyTuple_GET_ITEM(value, 1);
499                                                 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
500                                                 int xoffs = value_alignment_left ? 0 : m_seperation;
501                                                 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
502                                                 para->setFont(fnt2);
503                                                 para->renderString(text, 0);
504                                                 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
505                                                 int glyphs = para->size();
506                                                 
507                                                 PyObject *plist = 0;
508                                                 
509                                                 if (PyTuple_Size(value) >= 3)
510                                                         plist = PyTuple_GET_ITEM(value, 2);
511                                                 
512                                                 int entries = 0;
513
514                                                 if (plist && PyList_Check(plist))
515                                                         entries = PyList_Size(plist);
516                                                 
517                                                 for (int i = 0; i < entries; ++i)
518                                                 {
519                                                         PyObject *entry = PyList_GET_ITEM(plist, i);
520                                                         int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
521                                                         
522                                                         if ((num < 0) || (num >= glyphs))
523                                                                 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
524                                                         else
525                                                         {
526                                                                 para->setGlyphFlag(num, GS_INVERT);
527                                                                 eRect bbox;
528                                                                 bbox = para->getGlyphBBox(num);
529                                                                 bbox = eRect(bbox.left(), offset.y(), bbox.width(), m_itemsize.height());
530                                                                 painter.fill(bbox);
531                                                         }
532                                                                 /* entry is borrowed */
533                                                 }
534                                                 
535                                                 painter.renderPara(para, ePoint(0, 0));
536                                                         /* pvalue is borrowed */
537                                                         /* plist is 0 or borrowed */
538                                         }
539                                 }
540                                         /* type is borrowed */
541                         } else
542                                 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
543                                 /* value is borrowed */
544                 }
545
546                 if (selected)
547                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
548         }
549         
550         painter.clippop();
551 }
552
553 //////////////////////////////////////
554
555         /* todo: make a real infrastructure here! */
556 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
557
558 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
559 {
560         eRect itemrect(offset, m_itemsize);
561         painter.clip(itemrect);
562         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
563         painter.clear();
564
565         if (m_list && cursorValid())
566         {
567                 PyObject *items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
568                 
569                 if (!items)
570                 {
571                         eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
572                         goto error_out;
573                 }
574                 
575                 if (!PyList_Check(items))
576                 {
577                         eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
578                         goto error_out;
579                 }
580                 
581                 int size = PyList_Size(items);
582                 for (int i = 1; i < size; ++i)
583                 {
584                         PyObject *item = PyList_GET_ITEM(items, i); // borrowed reference!
585                         
586                         if (!item)
587                         {
588                                 eDebug("eListboxPythonMultiContent: ?");
589                                 goto error_out;
590                         }
591                         
592                         PyObject *px = 0, *py = 0, *pwidth = 0, *pheight = 0, *pfnt = 0, *pstring = 0, *pflags = 0;
593                 
594                         /*
595                                 we have a list of tuples:
596                                 
597                                 (0, x, y, width, height, fnt, flags, "bla" ),
598
599                                 or, for a progress:
600                                 (1, x, y, width, height, filled_percent )
601
602                                 or, for a pixmap:
603                                 
604                                 (2, x, y, width, height, pixmap )
605                                 
606                          */
607                         
608                         if (!PyTuple_Check(item))
609                         {
610                                 eDebug("eListboxPythonMultiContent did not receive a tuple.");
611                                 goto error_out;
612                         }
613
614                         int size = PyTuple_Size(item);
615
616                         if (!size)
617                         {
618                                 eDebug("eListboxPythonMultiContent receive empty tuple.");
619                                 goto error_out;
620                         }
621
622                         int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
623
624                         if (size > 5)
625                         {
626                                 px = PyTuple_GET_ITEM(item, 1);
627                                 py = PyTuple_GET_ITEM(item, 2);
628                                 pwidth = PyTuple_GET_ITEM(item, 3);
629                                 pheight = PyTuple_GET_ITEM(item, 4);
630                                 pfnt = PyTuple_GET_ITEM(item, 5); /* could also be an pixmap or an int (progress filled percent) */
631                                 if (size > 7)
632                                 {
633                                         pflags = PyTuple_GET_ITEM(item, 6);
634                                         pstring = PyTuple_GET_ITEM(item, 7);
635                                 }
636                         }
637                         
638                         switch (type)
639                         {
640                         case TYPE_TEXT: // text
641                         {
642                                 if (!(px && py && pwidth && pheight && pfnt && pstring))
643                                 {
644                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string[, ...])");
645                                         goto error_out;
646                                 }
647                                 
648                                 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
649                                 int x = PyInt_AsLong(px);
650                                 int y = PyInt_AsLong(py);
651                                 int width = PyInt_AsLong(pwidth);
652                                 int height = PyInt_AsLong(pheight);
653                                 int flags = PyInt_AsLong(pflags);
654                                 int fnt = PyInt_AsLong(pfnt);
655                                 
656                                 if (m_font.find(fnt) == m_font.end())
657                                 {
658                                         eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
659                                         goto error_out;
660                                 }
661                                 
662                                 eRect r = eRect(x, y, width, height);
663                                 r.moveBy(offset);
664                                 r &= itemrect;
665                                 
666                                 painter.setFont(m_font[fnt]);
667                                 
668                                 painter.clip(r);
669                                 painter.renderText(r, string, flags);
670                                 painter.clippop();
671                                 break;
672                         }
673                         case TYPE_PROGRESS: // Progress
674                         {
675                                 if (!(px && py && pwidth && pheight && pfnt))
676                                 {
677                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent))");
678                                         goto error_out;
679                                 }
680                                 int x = PyInt_AsLong(px);
681                                 int y = PyInt_AsLong(py);
682                                 int width = PyInt_AsLong(pwidth);
683                                 int height = PyInt_AsLong(pheight);
684                                 int filled = PyInt_AsLong(pfnt);
685
686                                 eRect r = eRect(x, y, width, height);
687                                 r.moveBy(offset);
688                                 r &= itemrect;
689
690                                 painter.clip(r);
691                                 int bwidth=2;  // borderwidth hardcoded yet
692
693                                 // border
694                                 eRect rc = eRect(x, y, width, bwidth);
695                                 rc.moveBy(offset);
696                                 painter.fill(rc);
697
698                                 rc = eRect(x, y+bwidth, bwidth, height-bwidth);
699                                 rc.moveBy(offset);
700                                 painter.fill(rc);
701
702                                 rc = eRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
703                                 rc.moveBy(offset);
704                                 painter.fill(rc);
705
706                                 rc = eRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
707                                 rc.moveBy(offset);
708                                 painter.fill(rc);
709
710                                 // progress
711                                 rc = eRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
712                                 rc.moveBy(offset);
713                                 painter.fill(rc);
714
715                                 painter.clippop();
716
717                                 break;
718                         }
719                         case TYPE_PIXMAP_ALPHATEST:
720                         case TYPE_PIXMAP: // pixmap
721                         {
722                                 if (!(px && py && pwidth && pheight && pfnt))
723                                 {
724                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap))");
725                                         goto error_out;
726                                 }
727                                 int x = PyInt_AsLong(px);
728                                 int y = PyInt_AsLong(py);
729                                 int width = PyInt_AsLong(pwidth);
730                                 int height = PyInt_AsLong(pheight);
731                                 ePtr<gPixmap> pixmap;
732                                 if (SwigFromPython(pixmap, pfnt))
733                                 {
734                                         eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
735                                         goto error_out;
736                                 }
737
738                                 eRect r = eRect(x, y, width, height);
739                                 r.moveBy(offset);
740                                 r &= itemrect;
741                                 
742                                 painter.clip(r);
743                                 painter.blit(pixmap, r.topLeft(), r, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
744                                 painter.clippop();
745
746                                 break;
747                         }
748                         default:
749                                 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
750                                 goto error_out;
751                         }
752                 }
753         }
754         
755         if (selected)
756                 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
757
758 error_out:
759         painter.clippop();
760 }
761
762 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
763 {
764         if (font)
765                 m_font[fnt] = font;
766         else
767                 m_font.erase(fnt);
768 }