fix memleak
[vuplus_dvbapp] / 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)
378                 return 0;
379         if (!cursorValid())
380                 return 0;
381         PyObject *r = PyList_GET_ITEM(m_list, m_cursor);
382         Py_XINCREF(r);
383         return r;
384 }
385
386 void eListboxPythonStringContent::invalidateEntry(int index)
387 {
388         if (m_listbox)
389                 m_listbox->entryChanged(index);
390 }
391
392 void eListboxPythonStringContent::invalidate()
393 {
394         if (m_listbox)
395                 m_listbox->invalidate();
396 }
397
398 //////////////////////////////////////
399
400 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
401 {
402         ePtr<gFont> fnt = new gFont("Regular", 20);
403         ePtr<gFont> fnt2 = new gFont("Regular", 16);
404         eRect itemrect(offset, m_itemsize);
405         painter.clip(itemrect);
406         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
407         painter.clear();
408
409         if (m_list && cursorValid())
410         {
411                         /* get current list item */
412                 PyObject *item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
413                 PyObject *text = 0, *value = 0;
414                 painter.setFont(fnt);
415
416                         /* the first tuple element is a string for the left side.
417                            the second one will be called, and the result shall be an tuple.
418                            
419                            of this tuple,
420                            the first one is the type (string).
421                            the second one is the value. */
422                 if (PyTuple_Check(item))
423                 {
424                                 /* handle left part. get item from tuple, convert to string, display. */
425                                 
426                         text = PyTuple_GET_ITEM(item, 0);
427 //                      text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
428                         const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
429                         eSize item_left = eSize(m_seperation, m_itemsize.height());
430                         eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
431                         painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
432 //                      Py_XDECREF(text);
433                         
434                                 /* now, handle the value. get 2nd part from tuple*/
435                         value = PyTuple_GET_ITEM(item, 1);
436                         if (value)
437                         {
438                                 PyObject *args = PyTuple_New(1);
439                                 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
440                                 
441                                         /* CallObject will call __call__ which should return the value tuple */
442                                 value = PyObject_CallObject(value, args);
443                                 
444                                 if (PyErr_Occurred())
445                                         PyErr_Print();
446
447                                 Py_DECREF(args);
448                                         /* the PyInt was stolen. */
449                         }
450                         
451                                 /*  check if this is really a tuple */
452                         if (value && PyTuple_Check(value))
453                         {
454                                         /* convert type to string */
455                                 PyObject *type = PyTuple_GET_ITEM(value, 0);
456                                 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
457                                 
458                                 if (atype)
459                                 {
460                                         if (!strcmp(atype, "text"))
461                                         {
462                                                 PyObject *pvalue = PyTuple_GET_ITEM(value, 1);
463                                                 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
464                                                 painter.setFont(fnt2);
465                                                 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
466
467                                                         /* pvalue is borrowed */
468                                         } else if (!strcmp(atype, "slider"))
469                                         {
470                                                 PyObject *pvalue = PyTuple_GET_ITEM(value, 1);
471                                                 
472                                                         /* convert value to Long. fallback to -1 on error. */
473                                                 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
474                                                 
475                                                         /* calc. slider length */
476                                                 int width = item_right.width() * value / 100;
477                                                 int height = item_right.height();
478                                                 
479                                                                                                 
480                                                         /* draw slider */
481                                                 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
482                                                 //hack - make it customizable
483                                                 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
484                                                 
485                                                         /* pvalue is borrowed */
486                                         } else if (!strcmp(atype, "mtext"))
487                                         {
488                                                 PyObject *pvalue = PyTuple_GET_ITEM(value, 1);
489                                                 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
490                                                 
491                                                 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(m_seperation, 0), item_right));
492                                                 para->setFont(fnt2);
493                                                 para->renderString(text, 0);
494                                                 para->realign(eTextPara::dirRight);
495                                                 int glyphs = para->size();
496                                                 
497                                                 PyObject *plist = 0;
498                                                 
499                                                 if (PyTuple_Size(value) >= 3)
500                                                         plist = PyTuple_GET_ITEM(value, 2);
501                                                 
502                                                 int entries = 0;
503
504                                                 if (plist && PyList_Check(plist))
505                                                         entries = PyList_Size(plist);
506                                                 
507                                                 for (int i = 0; i < entries; ++i)
508                                                 {
509                                                         PyObject *entry = PyList_GET_ITEM(plist, i);
510                                                         int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
511                                                         
512                                                         if ((num < 0) || (num >= glyphs))
513                                                                 eWarning("glyph index %d in PythonConfigList out of bounds!");
514                                                         else
515                                                         {
516                                                                 para->setGlyphFlag(num, GS_INVERT);
517                                                                 eRect bbox;
518                                                                 bbox = para->getGlyphBBox(num);
519                                                                 bbox = eRect(bbox.left(), offset.y(), bbox.width(), m_itemsize.height());
520                                                                 painter.fill(bbox);
521                                                         }
522                                                                 /* entry is borrowed */
523                                                 }
524                                                 
525                                                 painter.renderPara(para, ePoint(0, 0));
526                                                         /* pvalue is borrowed */
527                                                         /* plist is 0 or borrowed */
528                                         }
529                                 }
530                                         /* type is borrowed */
531                         } else
532                                 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
533                                 /* value is borrowed */
534                 }
535
536                 if (selected)
537                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
538         }
539         
540         painter.clippop();
541 }
542
543 //////////////////////////////////////
544
545         /* todo: make a real infrastructure here! */
546 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
547
548 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
549 {
550         eRect itemrect(offset, m_itemsize);
551         painter.clip(itemrect);
552         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
553         painter.clear();
554
555         if (m_list && cursorValid())
556         {
557                 PyObject *items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
558                 
559                 if (!items)
560                 {
561                         eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
562                         goto error_out;
563                 }
564                 
565                 if (!PyList_Check(items))
566                 {
567                         eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
568                         goto error_out;
569                 }
570                 
571                 int size = PyList_Size(items);
572                 for (int i = 1; i < size; ++i)
573                 {
574                         PyObject *item = PyList_GET_ITEM(items, i); // borrowed reference!
575                         
576                         if (!item)
577                         {
578                                 eDebug("eListboxPythonMultiContent: ?");
579                                 goto error_out;
580                         }
581                         
582                         PyObject *px = 0, *py = 0, *pwidth = 0, *pheight = 0, *pfnt = 0, *pstring = 0, *pflags = 0;
583                 
584                         /*
585                                 we have a list of tuples:
586                                 
587                                 (0, x, y, width, height, fnt, flags, "bla" ),
588
589                                 or, for a progress:
590                                 (1, x, y, width, height, filled_percent )
591
592                                 or, for a pixmap:
593                                 
594                                 (2, x, y, width, height, pixmap )
595                                 
596                          */
597                         
598                         if (!PyTuple_Check(item))
599                         {
600                                 eDebug("eListboxPythonMultiContent did not receive a tuple.");
601                                 goto error_out;
602                         }
603
604                         int size = PyTuple_Size(item);
605
606                         if (!size)
607                         {
608                                 eDebug("eListboxPythonMultiContent receive empty tuple.");
609                                 goto error_out;
610                         }
611
612                         int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
613
614                         if (size > 5)
615                         {
616                                 px = PyTuple_GET_ITEM(item, 1);
617                                 py = PyTuple_GET_ITEM(item, 2);
618                                 pwidth = PyTuple_GET_ITEM(item, 3);
619                                 pheight = PyTuple_GET_ITEM(item, 4);
620                                 pfnt = PyTuple_GET_ITEM(item, 5); /* could also be an pixmap or an int (progress filled percent) */
621                                 if (size > 7)
622                                 {
623                                         pflags = PyTuple_GET_ITEM(item, 6);
624                                         pstring = PyTuple_GET_ITEM(item, 7);
625                                 }
626                         }
627                         
628                         switch (type)
629                         {
630                         case TYPE_TEXT: // text
631                         {
632                                 if (!(px && py && pwidth && pheight && pfnt && pstring))
633                                 {
634                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string[, ...])");
635                                         goto error_out;
636                                 }
637                                 
638                                 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
639                                 int x = PyInt_AsLong(px);
640                                 int y = PyInt_AsLong(py);
641                                 int width = PyInt_AsLong(pwidth);
642                                 int height = PyInt_AsLong(pheight);
643                                 int flags = PyInt_AsLong(pflags);
644                                 int fnt = PyInt_AsLong(pfnt);
645                                 
646                                 if (m_font.find(fnt) == m_font.end())
647                                 {
648                                         eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
649                                         goto error_out;
650                                 }
651                                 
652                                 eRect r = eRect(x, y, width, height);
653                                 r.moveBy(offset);
654                                 r &= itemrect;
655                                 
656                                 painter.setFont(m_font[fnt]);
657                                 
658                                 painter.clip(r);
659                                 painter.renderText(r, string, flags);
660                                 painter.clippop();
661                                 break;
662                         }
663                         case TYPE_PROGRESS: // Progress
664                         {
665                                 if (!(px && py && pwidth && pheight && pfnt))
666                                 {
667                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent))");
668                                         goto error_out;
669                                 }
670                                 int x = PyInt_AsLong(px);
671                                 int y = PyInt_AsLong(py);
672                                 int width = PyInt_AsLong(pwidth);
673                                 int height = PyInt_AsLong(pheight);
674                                 int filled = PyInt_AsLong(pfnt);
675
676                                 eRect r = eRect(x, y, width, height);
677                                 r.moveBy(offset);
678                                 r &= itemrect;
679
680                                 painter.clip(r);
681                                 int bwidth=2;  // borderwidth hardcoded yet
682
683                                 // border
684                                 eRect rc = eRect(x, y, width, bwidth);
685                                 rc.moveBy(offset);
686                                 painter.fill(rc);
687
688                                 rc = eRect(x, y+bwidth, bwidth, height-bwidth);
689                                 rc.moveBy(offset);
690                                 painter.fill(rc);
691
692                                 rc = eRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
693                                 rc.moveBy(offset);
694                                 painter.fill(rc);
695
696                                 rc = eRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
697                                 rc.moveBy(offset);
698                                 painter.fill(rc);
699
700                                 // progress
701                                 rc = eRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
702                                 rc.moveBy(offset);
703                                 painter.fill(rc);
704
705                                 painter.clippop();
706
707                                 break;
708                         }
709                         case TYPE_PIXMAP: // pixmap
710                         {
711                                 if (!(px && py && pwidth && pheight && pfnt))
712                                 {
713                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap))");
714                                         goto error_out;
715                                 }
716                                 int x = PyInt_AsLong(px);
717                                 int y = PyInt_AsLong(py);
718                                 int width = PyInt_AsLong(pwidth);
719                                 int height = PyInt_AsLong(pheight);
720                                 ePtr<gPixmap> pixmap;
721                                 if (SwigFromPython(pixmap, pfnt))
722                                 {
723                                         eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
724                                         goto error_out;
725                                 }
726
727                                 eRect r = eRect(x, y, width, height);
728                                 r.moveBy(offset);
729                                 r &= itemrect;
730                                 
731                                 painter.clip(r);
732                                 painter.blit(pixmap, r.topLeft(), r);
733                                 painter.clippop();
734
735                                 break;
736                         }
737                         default:
738                                 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
739                                 goto error_out;
740                         }
741                 }
742         }
743         
744         if (selected)
745                 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
746
747 error_out:
748         painter.clippop();
749 }
750
751 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
752 {
753         if (font)
754                 m_font[fnt] = font;
755         else
756                 m_font.erase(fnt);
757 }