return None when there is no list or invalid cursor
[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                                                 
480                                                         /* convert value to Long. fallback to -1 on error. */
481                                                 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
482                                                 
483                                                         /* calc. slider length */
484                                                 int width = item_right.width() * value / 100;
485                                                 int height = item_right.height();
486                                                 
487                                                                                                 
488                                                         /* draw slider */
489                                                 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
490                                                 //hack - make it customizable
491                                                 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
492                                                 
493                                                         /* pvalue is borrowed */
494                                         } else if (!strcmp(atype, "mtext"))
495                                         {
496                                                 PyObject *pvalue = PyTuple_GET_ITEM(value, 1);
497                                                 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
498                                                 int xoffs = value_alignment_left ? 0 : m_seperation;
499                                                 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
500                                                 para->setFont(fnt2);
501                                                 para->renderString(text, 0);
502                                                 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
503                                                 int glyphs = para->size();
504                                                 
505                                                 PyObject *plist = 0;
506                                                 
507                                                 if (PyTuple_Size(value) >= 3)
508                                                         plist = PyTuple_GET_ITEM(value, 2);
509                                                 
510                                                 int entries = 0;
511
512                                                 if (plist && PyList_Check(plist))
513                                                         entries = PyList_Size(plist);
514                                                 
515                                                 for (int i = 0; i < entries; ++i)
516                                                 {
517                                                         PyObject *entry = PyList_GET_ITEM(plist, i);
518                                                         int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
519                                                         
520                                                         if ((num < 0) || (num >= glyphs))
521                                                                 eWarning("glyph index %d in PythonConfigList out of bounds!", num);
522                                                         else
523                                                         {
524                                                                 para->setGlyphFlag(num, GS_INVERT);
525                                                                 eRect bbox;
526                                                                 bbox = para->getGlyphBBox(num);
527                                                                 bbox = eRect(bbox.left(), offset.y(), bbox.width(), m_itemsize.height());
528                                                                 painter.fill(bbox);
529                                                         }
530                                                                 /* entry is borrowed */
531                                                 }
532                                                 
533                                                 painter.renderPara(para, ePoint(0, 0));
534                                                         /* pvalue is borrowed */
535                                                         /* plist is 0 or borrowed */
536                                         }
537                                 }
538                                         /* type is borrowed */
539                         } else
540                                 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
541                                 /* value is borrowed */
542                 }
543
544                 if (selected)
545                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
546         }
547         
548         painter.clippop();
549 }
550
551 //////////////////////////////////////
552
553         /* todo: make a real infrastructure here! */
554 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
555
556 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
557 {
558         eRect itemrect(offset, m_itemsize);
559         painter.clip(itemrect);
560         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
561         painter.clear();
562
563         if (m_list && cursorValid())
564         {
565                 PyObject *items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
566                 
567                 if (!items)
568                 {
569                         eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
570                         goto error_out;
571                 }
572                 
573                 if (!PyList_Check(items))
574                 {
575                         eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
576                         goto error_out;
577                 }
578                 
579                 int size = PyList_Size(items);
580                 for (int i = 1; i < size; ++i)
581                 {
582                         PyObject *item = PyList_GET_ITEM(items, i); // borrowed reference!
583                         
584                         if (!item)
585                         {
586                                 eDebug("eListboxPythonMultiContent: ?");
587                                 goto error_out;
588                         }
589                         
590                         PyObject *px = 0, *py = 0, *pwidth = 0, *pheight = 0, *pfnt = 0, *pstring = 0, *pflags = 0;
591                 
592                         /*
593                                 we have a list of tuples:
594                                 
595                                 (0, x, y, width, height, fnt, flags, "bla" ),
596
597                                 or, for a progress:
598                                 (1, x, y, width, height, filled_percent )
599
600                                 or, for a pixmap:
601                                 
602                                 (2, x, y, width, height, pixmap )
603                                 
604                          */
605                         
606                         if (!PyTuple_Check(item))
607                         {
608                                 eDebug("eListboxPythonMultiContent did not receive a tuple.");
609                                 goto error_out;
610                         }
611
612                         int size = PyTuple_Size(item);
613
614                         if (!size)
615                         {
616                                 eDebug("eListboxPythonMultiContent receive empty tuple.");
617                                 goto error_out;
618                         }
619
620                         int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
621
622                         if (size > 5)
623                         {
624                                 px = PyTuple_GET_ITEM(item, 1);
625                                 py = PyTuple_GET_ITEM(item, 2);
626                                 pwidth = PyTuple_GET_ITEM(item, 3);
627                                 pheight = PyTuple_GET_ITEM(item, 4);
628                                 pfnt = PyTuple_GET_ITEM(item, 5); /* could also be an pixmap or an int (progress filled percent) */
629                                 if (size > 7)
630                                 {
631                                         pflags = PyTuple_GET_ITEM(item, 6);
632                                         pstring = PyTuple_GET_ITEM(item, 7);
633                                 }
634                         }
635                         
636                         switch (type)
637                         {
638                         case TYPE_TEXT: // text
639                         {
640                                 if (!(px && py && pwidth && pheight && pfnt && pstring))
641                                 {
642                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string[, ...])");
643                                         goto error_out;
644                                 }
645                                 
646                                 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
647                                 int x = PyInt_AsLong(px);
648                                 int y = PyInt_AsLong(py);
649                                 int width = PyInt_AsLong(pwidth);
650                                 int height = PyInt_AsLong(pheight);
651                                 int flags = PyInt_AsLong(pflags);
652                                 int fnt = PyInt_AsLong(pfnt);
653                                 
654                                 if (m_font.find(fnt) == m_font.end())
655                                 {
656                                         eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
657                                         goto error_out;
658                                 }
659                                 
660                                 eRect r = eRect(x, y, width, height);
661                                 r.moveBy(offset);
662                                 r &= itemrect;
663                                 
664                                 painter.setFont(m_font[fnt]);
665                                 
666                                 painter.clip(r);
667                                 painter.renderText(r, string, flags);
668                                 painter.clippop();
669                                 break;
670                         }
671                         case TYPE_PROGRESS: // Progress
672                         {
673                                 if (!(px && py && pwidth && pheight && pfnt))
674                                 {
675                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent))");
676                                         goto error_out;
677                                 }
678                                 int x = PyInt_AsLong(px);
679                                 int y = PyInt_AsLong(py);
680                                 int width = PyInt_AsLong(pwidth);
681                                 int height = PyInt_AsLong(pheight);
682                                 int filled = PyInt_AsLong(pfnt);
683
684                                 eRect r = eRect(x, y, width, height);
685                                 r.moveBy(offset);
686                                 r &= itemrect;
687
688                                 painter.clip(r);
689                                 int bwidth=2;  // borderwidth hardcoded yet
690
691                                 // border
692                                 eRect rc = eRect(x, y, width, bwidth);
693                                 rc.moveBy(offset);
694                                 painter.fill(rc);
695
696                                 rc = eRect(x, y+bwidth, bwidth, height-bwidth);
697                                 rc.moveBy(offset);
698                                 painter.fill(rc);
699
700                                 rc = eRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
701                                 rc.moveBy(offset);
702                                 painter.fill(rc);
703
704                                 rc = eRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
705                                 rc.moveBy(offset);
706                                 painter.fill(rc);
707
708                                 // progress
709                                 rc = eRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
710                                 rc.moveBy(offset);
711                                 painter.fill(rc);
712
713                                 painter.clippop();
714
715                                 break;
716                         }
717                         case TYPE_PIXMAP_ALPHATEST:
718                         case TYPE_PIXMAP: // pixmap
719                         {
720                                 if (!(px && py && pwidth && pheight && pfnt))
721                                 {
722                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap))");
723                                         goto error_out;
724                                 }
725                                 int x = PyInt_AsLong(px);
726                                 int y = PyInt_AsLong(py);
727                                 int width = PyInt_AsLong(pwidth);
728                                 int height = PyInt_AsLong(pheight);
729                                 ePtr<gPixmap> pixmap;
730                                 if (SwigFromPython(pixmap, pfnt))
731                                 {
732                                         eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
733                                         goto error_out;
734                                 }
735
736                                 eRect r = eRect(x, y, width, height);
737                                 r.moveBy(offset);
738                                 r &= itemrect;
739                                 
740                                 painter.clip(r);
741                                 painter.blit(pixmap, r.topLeft(), r, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : 0);
742                                 painter.clippop();
743
744                                 break;
745                         }
746                         default:
747                                 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
748                                 goto error_out;
749                         }
750                 }
751         }
752         
753         if (selected)
754                 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
755
756 error_out:
757         painter.clippop();
758 }
759
760 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
761 {
762         if (font)
763                 m_font[fnt] = font;
764         else
765                 m_font.erase(fnt);
766 }