0a10b27a5bbb1717d1ba29422e9fef009fe6b7a0
[vuplus_dvbapp] / lib / gui / elistboxcontent.cpp
1 #include <lib/gui/elistbox.h>
2 #include <lib/gui/elistboxcontent.h>
3 #include <Python.h>
4
5 /*
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
8     the list.
9     
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.
13     
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.
17     
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.
23     
24     Although cursorSet is provided, it should be only used when there is no
25     other way, as it involves iterating trough the list.
26  */
27
28 iListboxContent::~iListboxContent()
29 {
30 }
31
32 void iListboxContent::setListbox(eListbox *lb)
33 {
34         m_listbox = lb;
35 }
36
37 DEFINE_REF(eListboxTestContent);
38
39 void eListboxTestContent::cursorHome()
40 {
41         m_cursor = 0;
42 }
43
44 void eListboxTestContent::cursorEnd()
45 {
46         m_cursor = size();
47 }
48
49 int eListboxTestContent::cursorMove(int count)
50 {
51         m_cursor += count;
52         
53         if (m_cursor < 0)
54                 cursorHome();
55         else if (m_cursor > size())
56                 cursorEnd();
57         return 0;
58 }
59
60 int eListboxTestContent::cursorValid()
61 {
62         return m_cursor < size();
63 }
64
65 int eListboxTestContent::cursorSet(int n)
66 {
67         m_cursor = n;
68         
69         if (m_cursor < 0)
70                 cursorHome();
71         else if (m_cursor > size())
72                 cursorEnd();
73         return 0;
74 }
75
76 int eListboxTestContent::cursorGet()
77 {
78         return m_cursor;
79 }
80
81 void eListboxTestContent::cursorSave()
82 {
83         m_saved_cursor = m_cursor;
84 }
85
86 void eListboxTestContent::cursorRestore()
87 {
88         m_cursor = m_saved_cursor;
89 }
90
91 int eListboxTestContent::size()
92 {
93         return 10;
94 }
95         
96 RESULT eListboxTestContent::connectItemChanged(const Slot0<void> &itemChanged, ePtr<eConnection> &connection)
97 {
98         return 0;
99 }
100
101 void eListboxTestContent::setSize(const eSize &size)
102 {
103         m_size = size;
104 }
105
106 void eListboxTestContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
107 {
108         ePtr<gFont> fnt = new gFont("Arial", 14);
109         painter.clip(eRect(offset, m_size));
110         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
111         painter.clear();
112
113         if (cursorValid())
114         {
115                 painter.setFont(fnt);
116                 char string[10];
117                 sprintf(string, "%d.)", m_cursor);
118                 
119                 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
120                 
121                 painter.renderText(eRect(text_offset, m_size), string);
122                 
123                 if (selected)
124                         style.drawFrame(painter, eRect(offset, m_size), eWindowStyle::frameListboxEntry);
125         }
126         
127         painter.clippop();
128 }
129
130 //////////////////////////////////////
131
132 DEFINE_REF(eListboxStringContent);
133
134 eListboxStringContent::eListboxStringContent()
135 {
136         m_size = 0;
137         cursorHome();
138 }
139
140 void eListboxStringContent::cursorHome()
141 {
142         m_cursor = m_list.begin();
143         m_cursor_number = 0;
144 }
145
146 void eListboxStringContent::cursorEnd()
147 {
148         m_cursor = m_list.end();
149         m_cursor_number = m_size;
150 }
151
152 int eListboxStringContent::cursorMove(int count)
153 {
154         if (count > 0)
155         {
156                 while (count && (m_cursor != m_list.end()))
157                 {
158                         ++m_cursor;
159                         ++m_cursor_number;
160                         --count;
161                 }
162         } else if (count < 0)
163         {
164                 while (count && (m_cursor != m_list.begin()))
165                 {
166                         --m_cursor;
167                         --m_cursor_number;
168                         ++count;
169                 }
170         }
171         
172         return 0;
173 }
174
175 int eListboxStringContent::cursorValid()
176 {
177         return m_cursor != m_list.end();
178 }
179
180 int eListboxStringContent::cursorSet(int n)
181 {
182         cursorHome();
183         cursorMove(n);
184         
185         return 0;
186 }
187
188 int eListboxStringContent::cursorGet()
189 {
190         return m_cursor_number;
191 }
192
193 void eListboxStringContent::cursorSave()
194 {
195         m_saved_cursor = m_cursor;
196         m_saved_cursor_number = m_cursor_number;
197 }
198
199 void eListboxStringContent::cursorRestore()
200 {
201         m_cursor = m_saved_cursor;
202         m_cursor_number = m_saved_cursor_number;
203 }
204
205 int eListboxStringContent::size()
206 {
207         return m_size;
208 }
209         
210 void eListboxStringContent::setSize(const eSize &size)
211 {
212         m_itemsize = size;
213 }
214
215 void eListboxStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
216 {
217         ePtr<gFont> fnt = new gFont("Arial", 14);
218         painter.clip(eRect(offset, m_itemsize));
219         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
220         painter.clear();
221         
222         eDebug("item %d", m_cursor_number);
223         if (cursorValid())
224         {
225                 eDebug("is valid..");
226                 painter.setFont(fnt);
227                 
228                 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
229                 
230                 painter.renderText(eRect(text_offset, m_itemsize), *m_cursor);
231                 
232                 if (selected)
233                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
234         }
235         
236         painter.clippop();
237 }
238
239 void eListboxStringContent::setList(std::list<std::string> &list)
240 {
241         m_list = list;
242         m_size = list.size();
243         cursorHome();
244 }
245
246 //////////////////////////////////////
247
248 DEFINE_REF(eListboxPythonStringContent);
249
250 eListboxPythonStringContent::eListboxPythonStringContent()
251 {
252         m_list = 0;
253 }
254
255 eListboxPythonStringContent::~eListboxPythonStringContent()
256 {
257 }
258
259 void eListboxPythonStringContent::cursorHome()
260 {
261         m_cursor = 0;
262 }
263
264 void eListboxPythonStringContent::cursorEnd()
265 {
266         m_cursor = size();
267 }
268
269 int eListboxPythonStringContent::cursorMove(int count)
270 {
271         m_cursor += count;
272         
273         if (m_cursor < 0)
274                 cursorHome();
275         else if (m_cursor > size())
276                 cursorEnd();
277         return 0;
278 }
279
280 int eListboxPythonStringContent::cursorValid()
281 {
282         return m_cursor < size();
283 }
284
285 int eListboxPythonStringContent::cursorSet(int n)
286 {
287         m_cursor = n;
288         
289         if (m_cursor < 0)
290                 cursorHome();
291         else if (m_cursor > size())
292                 cursorEnd();
293         return 0;
294 }
295
296 int eListboxPythonStringContent::cursorGet()
297 {
298         return m_cursor;
299 }
300
301 void eListboxPythonStringContent::cursorSave()
302 {
303         m_saved_cursor = m_cursor;
304 }
305
306 void eListboxPythonStringContent::cursorRestore()
307 {
308         m_cursor = m_saved_cursor;
309 }
310
311 int eListboxPythonStringContent::size()
312 {
313         if (!m_list)
314                 return 0;
315         return PyList_Size(m_list);
316 }
317         
318 void eListboxPythonStringContent::setSize(const eSize &size)
319 {
320         m_itemsize = size;
321 }
322
323 void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
324 {
325         ePtr<gFont> fnt = new gFont("Arial", 14);
326         painter.clip(eRect(offset, m_itemsize));
327         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
328         painter.clear();
329
330         if (m_list && cursorValid())
331         {
332                 PyObject *item = PyList_GetItem(m_list, m_cursor); // borrowed reference!
333                 painter.setFont(fnt);
334
335                         /* the user can supply tuples, in this case the first one will be displayed. */         
336                 if (PyTuple_Check(item))
337                         item = PyTuple_GetItem(item, 0);
338                 
339                 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
340                 
341                 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
342                 
343                 painter.renderText(eRect(text_offset, m_itemsize), string);
344                 
345                 if (selected)
346                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
347         }
348         
349         painter.clippop();
350 }
351
352 void eListboxPythonStringContent::setList(PyObject *list)
353 {
354         Py_XDECREF(m_list);
355         if (!PyList_Check(list))
356         {
357                 m_list = 0;
358         } else
359         {
360                 m_list = list;
361                 Py_INCREF(m_list);
362         }
363 }
364
365 PyObject *eListboxPythonStringContent::getCurrentSelection()
366 {
367         if (!m_list)
368                 return 0;
369         if (!cursorValid())
370                 return 0;
371         PyObject *r = PyList_GetItem(m_list, m_cursor);
372         Py_XINCREF(r);
373         return r;
374 }
375
376 //////////////////////////////////////