1 #include <lib/gui/elistbox.h>
2 #include <lib/gui/elistboxcontent.h>
6 The basic idea is to have an interface which gives all relevant list
7 processing functions, and can be used by the listbox to browse trough
10 The listbox directly uses the implemented cursor. It tries hard to avoid
11 iterating trough the (possibly very large) list, so it should be O(1),
12 i.e. the performance should not be influenced by the size of the list.
14 The list interface knows how to draw the current entry to a specified
15 offset. Different interfaces can be used to adapt different lists,
16 pre-filter lists on the fly etc.
18 cursorSave/Restore is used to avoid re-iterating the list on redraw.
19 The current selection is always selected as cursor position, the
20 cursor is then positioned to the start, and then iterated. This gives
21 at most 2x m_items_per_page cursor movements per redraw, indepenent
22 of the size of the list.
24 Although cursorSet is provided, it should be only used when there is no
25 other way, as it involves iterating trough the list.
28 iListboxContent::~iListboxContent()
32 iListboxContent::iListboxContent(): m_listbox(0)
36 void iListboxContent::setListbox(eListbox *lb)
41 DEFINE_REF(eListboxTestContent);
43 void eListboxTestContent::cursorHome()
48 void eListboxTestContent::cursorEnd()
53 int eListboxTestContent::cursorMove(int count)
59 else if (m_cursor > size())
64 int eListboxTestContent::cursorValid()
66 return m_cursor < size();
69 int eListboxTestContent::cursorSet(int n)
75 else if (m_cursor > size())
80 int eListboxTestContent::cursorGet()
85 void eListboxTestContent::cursorSave()
87 m_saved_cursor = m_cursor;
90 void eListboxTestContent::cursorRestore()
92 m_cursor = m_saved_cursor;
95 int eListboxTestContent::size()
100 RESULT eListboxTestContent::connectItemChanged(const Slot0<void> &itemChanged, ePtr<eConnection> &connection)
105 void eListboxTestContent::setSize(const eSize &size)
110 void eListboxTestContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
112 ePtr<gFont> fnt = new gFont("Arial", 14);
113 painter.clip(eRect(offset, m_size));
114 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
119 painter.setFont(fnt);
121 sprintf(string, "%d.)", m_cursor);
123 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
125 painter.renderText(eRect(text_offset, m_size), string);
128 style.drawFrame(painter, eRect(offset, m_size), eWindowStyle::frameListboxEntry);
134 //////////////////////////////////////
136 DEFINE_REF(eListboxStringContent);
138 eListboxStringContent::eListboxStringContent()
144 void eListboxStringContent::cursorHome()
146 m_cursor = m_list.begin();
150 void eListboxStringContent::cursorEnd()
152 m_cursor = m_list.end();
153 m_cursor_number = m_size;
156 int eListboxStringContent::cursorMove(int count)
160 while (count && (m_cursor != m_list.end()))
166 } else if (count < 0)
168 while (count && (m_cursor != m_list.begin()))
179 int eListboxStringContent::cursorValid()
181 return m_cursor != m_list.end();
184 int eListboxStringContent::cursorSet(int n)
192 int eListboxStringContent::cursorGet()
194 return m_cursor_number;
197 void eListboxStringContent::cursorSave()
199 m_saved_cursor = m_cursor;
200 m_saved_cursor_number = m_cursor_number;
203 void eListboxStringContent::cursorRestore()
205 m_cursor = m_saved_cursor;
206 m_cursor_number = m_saved_cursor_number;
209 int eListboxStringContent::size()
214 void eListboxStringContent::setSize(const eSize &size)
219 void eListboxStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
221 ePtr<gFont> fnt = new gFont("Arial", 14);
222 painter.clip(eRect(offset, m_itemsize));
223 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
226 eDebug("item %d", m_cursor_number);
229 eDebug("is valid..");
230 painter.setFont(fnt);
232 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
234 painter.renderText(eRect(text_offset, m_itemsize), *m_cursor);
237 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
243 void eListboxStringContent::setList(std::list<std::string> &list)
246 m_size = list.size();
250 //////////////////////////////////////
252 DEFINE_REF(eListboxPythonStringContent);
254 eListboxPythonStringContent::eListboxPythonStringContent()
259 eListboxPythonStringContent::~eListboxPythonStringContent()
263 void eListboxPythonStringContent::cursorHome()
268 void eListboxPythonStringContent::cursorEnd()
273 int eListboxPythonStringContent::cursorMove(int count)
279 else if (m_cursor > size())
284 int eListboxPythonStringContent::cursorValid()
286 return m_cursor < size();
289 int eListboxPythonStringContent::cursorSet(int n)
295 else if (m_cursor > size())
300 int eListboxPythonStringContent::cursorGet()
305 void eListboxPythonStringContent::cursorSave()
307 m_saved_cursor = m_cursor;
310 void eListboxPythonStringContent::cursorRestore()
312 m_cursor = m_saved_cursor;
315 int eListboxPythonStringContent::size()
319 return PyList_Size(m_list);
322 void eListboxPythonStringContent::setSize(const eSize &size)
327 void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
329 ePtr<gFont> fnt = new gFont("Arial", 14);
330 painter.clip(eRect(offset, m_itemsize));
331 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
334 if (m_list && cursorValid())
336 PyObject *item = PyList_GetItem(m_list, m_cursor); // borrowed reference!
337 painter.setFont(fnt);
339 /* the user can supply tuples, in this case the first one will be displayed. */
340 if (PyTuple_Check(item))
341 item = PyTuple_GetItem(item, 0);
343 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
345 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
347 painter.renderText(eRect(text_offset, m_itemsize), string);
350 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
356 void eListboxPythonStringContent::setList(PyObject *list)
359 if (!PyList_Check(list))
369 PyObject *eListboxPythonStringContent::getCurrentSelection()
375 PyObject *r = PyList_GetItem(m_list, m_cursor);
380 void eListboxPythonStringContent::invalidateEntry(int index)
383 m_listbox->entryChanged(index);
386 //////////////////////////////////////
388 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
390 ePtr<gFont> fnt = new gFont("Arial", 14);
391 ePtr<gFont> fnt2 = new gFont("Arial", 16);
392 painter.clip(eRect(offset, m_itemsize));
393 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
396 if (m_list && cursorValid())
398 /* get current list item */
399 PyObject *item = PyList_GetItem(m_list, m_cursor); // borrowed reference!
400 PyObject *text = 0, *value = 0;
401 painter.setFont(fnt);
403 /* the first tuple element is a string for the left side.
404 the second one will be called, and the result shall be an tuple.
407 the first one is the type (string).
408 the second one is the value. */
409 if (PyTuple_Check(item))
411 /* handle left part. get item from tuple, convert to string, display. */
413 text = PyTuple_GetItem(item, 0);
414 text = PyObject_Str(text);
415 const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
416 eSize item_left = eSize(m_seperation, m_itemsize.height());
417 eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
418 painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
421 /* now, handle the value. get 2nd part from tuple*/
422 value = PyTuple_GetItem(item, 1);
424 /* CallObject will call __call__ which should return the value tuple */
425 value = PyObject_CallObject(value, 0);
427 /* check if this is really a tuple */
428 if (PyTuple_Check(value))
430 /* convert type to string */
431 PyObject *type = PyTuple_GetItem(value, 0);
432 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
436 if (!strcmp(atype, "text"))
438 PyObject *pvalue = PyTuple_GetItem(value, 1);
439 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
440 painter.setFont(fnt2);
441 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
443 /* pvalue is borrowed */
444 } else if (!strcmp(atype, "slider"))
446 PyObject *pvalue = PyTuple_GetItem(value, 1);
448 /* convert value to Long. fallback to -1 on error. */
449 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
451 /* calc. slider length */
452 int width = item_right.width() * value / 100;
453 int height = item_right.height();
457 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
458 //hack - make it customizable
459 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
461 /* pvalue is borrowed */
466 /* value is borrowed */
470 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
476 //////////////////////////////////////
478 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
480 painter.clip(eRect(offset, m_itemsize));
481 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
484 if (m_list && cursorValid())
486 PyObject *items = PyList_GetItem(m_list, m_cursor); // borrowed reference!
490 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
495 if (!PyList_Check(items))
497 eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
502 int size = PyList_Size(items);
503 for (int i = 1; i < size; ++i)
505 PyObject *item = PyList_GetItem(items, i); // borrowed reference!
509 eDebug("eListboxPythonMultiContent: ?");
515 PyObject *px, *py, *pwidth, *pheight, *pfnt, *pstring, *pflags;
518 we have a list of tuples:
520 (x, y, width, height, fnt, flags, "bla" ),
524 if (!PyTuple_Check(item))
526 eDebug("eListboxPythonMultiContent did not receive a tuple.");
531 px = PyTuple_GetItem(item, 0);
532 py = PyTuple_GetItem(item, 1);
533 pwidth = PyTuple_GetItem(item, 2);
534 pheight = PyTuple_GetItem(item, 3);
535 pfnt = PyTuple_GetItem(item, 4);
536 pflags = PyTuple_GetItem(item, 5);
537 pstring = PyTuple_GetItem(item, 6);
539 if (!(px && py && pwidth && pheight && pfnt && pstring))
541 eDebug("eListboxPythonMultiContent received too small tuple (must be (x, y, width, height, fnt, flags, string[, ...])");
546 pstring = PyObject_Str(pstring);
548 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
550 int x = PyInt_AsLong(px);
551 int y = PyInt_AsLong(py);
552 int width = PyInt_AsLong(pwidth);
553 int height = PyInt_AsLong(pheight);
554 int flags = PyInt_AsLong(pflags);
556 int fnt = PyInt_AsLong(pfnt);
558 if (m_font.find(fnt) == m_font.end())
560 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
566 eRect r = eRect(x, y, width, height);
569 painter.setFont(m_font[fnt]);
571 painter.renderText(r, string, flags);
576 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
583 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)