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)
382 m_listbox->entryChanged(index);
385 //////////////////////////////////////
387 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
389 ePtr<gFont> fnt = new gFont("Arial", 14);
390 ePtr<gFont> fnt2 = new gFont("Arial", 16);
391 painter.clip(eRect(offset, m_itemsize));
392 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
395 if (m_list && cursorValid())
397 PyObject *item = PyList_GetItem(m_list, m_cursor); // borrowed reference!
398 PyObject *text = 0, *value = 0;
399 painter.setFont(fnt);
401 /* the user can supply tuples, in this case the first one will be displayed. */
402 if (PyTuple_Check(item))
404 text = PyTuple_GetItem(item, 0);
405 value = PyTuple_GetItem(item, 1);
408 text = PyObject_Str(text);
409 value = PyObject_Str(value);
411 const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
412 const char *string_val = (value && PyString_Check(value)) ? PyString_AsString(value) : "<not-a-string>";
414 eSize item_left = eSize(m_seperation, m_itemsize.height());
415 eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
417 painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
419 painter.setFont(fnt2);
420 painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), string_val, gPainter::RT_HALIGN_RIGHT);
426 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
432 //////////////////////////////////////
434 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
436 painter.clip(eRect(offset, m_itemsize));
437 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
440 if (m_list && cursorValid())
442 PyObject *items = PyList_GetItem(m_list, m_cursor); // borrowed reference!
446 eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
451 if (!PyList_Check(items))
453 eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
458 int size = PyList_Size(items);
459 for (int i = 1; i < size; ++i)
461 PyObject *item = PyList_GetItem(items, i); // borrowed reference!
465 eDebug("eListboxPythonMultiContent: ?");
471 PyObject *px, *py, *pwidth, *pheight, *pfnt, *pstring, *pflags;
474 we have a list of tuples:
476 (x, y, width, height, fnt, flags, "bla" ),
480 if (!PyTuple_Check(item))
482 eDebug("eListboxPythonMultiContent did not receive a tuple.");
487 px = PyTuple_GetItem(item, 0);
488 py = PyTuple_GetItem(item, 1);
489 pwidth = PyTuple_GetItem(item, 2);
490 pheight = PyTuple_GetItem(item, 3);
491 pfnt = PyTuple_GetItem(item, 4);
492 pflags = PyTuple_GetItem(item, 5);
493 pstring = PyTuple_GetItem(item, 6);
495 if (!(px && py && pwidth && pheight && pfnt && pstring))
497 eDebug("eListboxPythonMultiContent received too small tuple (must be (x, y, width, height, fnt, flags, string[, ...])");
502 pstring = PyObject_Str(pstring);
504 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
506 int x = PyInt_AsLong(px);
507 int y = PyInt_AsLong(py);
508 int width = PyInt_AsLong(pwidth);
509 int height = PyInt_AsLong(pheight);
510 int flags = PyInt_AsLong(pflags);
512 int fnt = PyInt_AsLong(pfnt);
514 if (m_font.find(fnt) == m_font.end())
516 eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
522 eRect r = eRect(x, y, width, height);
525 painter.setFont(m_font[fnt]);
527 painter.renderText(r, string, flags);
532 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
539 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)