fix movemode
[enigma2.git] / lib / service / listboxservice.cpp
1 #include <lib/service/listboxservice.h>
2 #include <lib/service/service.h>
3
4 void eListboxServiceContent::setRoot(const eServiceReference &root)
5 {
6         m_list.clear();
7         m_root = root;
8         
9         assert(m_service_center);
10         
11         ePtr<iListableService> lst;
12         if (m_service_center->list(m_root, lst))
13                 eDebug("no list available!");
14         else
15                 if (lst->getContent(m_list))
16                         eDebug("getContent failed");
17
18         m_size = m_list.size();
19         cursorHome();
20         
21         if (m_listbox)
22                 m_listbox->entryReset();
23 }
24
25 void eListboxServiceContent::setCurrent(const eServiceReference &ref)
26 {
27         int index=0;
28         for (list::iterator i(m_list.begin()); i != m_list.end(); ++i, ++index)
29                 if ( *i == ref )
30                 {
31                         m_cursor = i;
32                         m_cursor_number = index;
33                         break;
34                 }
35 }
36
37 void eListboxServiceContent::getCurrent(eServiceReference &ref)
38 {
39         if (cursorValid())
40                 ref = *m_cursor;
41         else
42                 ref = eServiceReference();
43 }
44
45 void eListboxServiceContent::initMarked()
46 {
47         m_marked.clear();
48 }
49
50 void eListboxServiceContent::addMarked(const eServiceReference &ref)
51 {
52         m_marked.insert(ref);
53         if (m_listbox)
54                 m_listbox->entryChanged(lookupService(ref));
55 }
56
57 void eListboxServiceContent::removeMarked(const eServiceReference &ref)
58 {
59         m_marked.erase(ref);
60         if (m_listbox)
61                 m_listbox->entryChanged(lookupService(ref));
62 }
63
64 int eListboxServiceContent::isMarked(const eServiceReference &ref)
65 {
66         return m_marked.find(ref) != m_marked.end();
67 }
68
69 void eListboxServiceContent::markedQueryStart()
70 {
71         m_marked_iterator = m_marked.begin();
72 }
73
74 int eListboxServiceContent::markedQueryNext(eServiceReference &ref)
75 {
76         if (m_marked_iterator == m_marked.end())
77                 return -1;
78         ref = *m_marked_iterator++;
79         return 0;
80 }
81
82 int eListboxServiceContent::lookupService(const eServiceReference &ref)
83 {
84                 /* shortcut for cursor */
85         if (ref == *m_cursor)
86                 return m_cursor_number;
87                 /* otherwise, search in the list.. */
88         int index = 0;
89         for (list::const_iterator i(m_list.begin()); i != m_list.end(); ++i, ++index);
90         
91                 /* this is ok even when the index was not found. */
92         return index;
93 }
94
95 void eListboxServiceContent::setVisualMode(int mode)
96 {
97         m_visual_mode = mode;
98         
99         if (m_visual_mode == visModeSimple)
100         {
101                 m_element_position[celServiceName] = eRect(ePoint(0, 0), m_itemsize);
102                 m_element_font[celServiceName] = new gFont("Arial", 23);
103                 m_element_position[celServiceNumber] = eRect();
104                 m_element_font[celServiceNumber] = 0;
105                 m_element_position[celIcon] = eRect();
106                 m_element_position[celServiceInfo] = eRect();
107                 m_element_font[celServiceInfo] = 0;
108         }
109 }
110
111 void eListboxServiceContent::setElementPosition(int element, eRect where)
112 {
113         if ((element >= 0) && (element < celElements))
114                 m_element_position[element] = where;
115 }
116
117 void eListboxServiceContent::setElementFont(int element, gFont *font)
118 {
119         if ((element >= 0) && (element < celElements))
120                 m_element_font[element] = font;
121 }
122
123 void eListboxServiceContent::sort()
124 {
125         ePtr<iListableService> lst;
126   if (!m_service_center->list(m_root, lst))
127   {
128                 m_list.sort(iListableServiceCompare(lst));
129                         /* FIXME: is this really required or can we somehow keep the current entry? */
130                 cursorHome();
131                 if (m_listbox)
132                         m_listbox->entryReset();
133         }
134 }
135
136 DEFINE_REF(eListboxServiceContent);
137
138 eListboxServiceContent::eListboxServiceContent()
139         :m_visual_mode(visModeSimple), m_size(0), m_current_marked(false), m_numberoffset(0)
140 {
141         cursorHome();
142         eServiceCenter::getInstance(m_service_center);
143 }
144
145 void eListboxServiceContent::cursorHome()
146 {
147         if (m_current_marked && m_saved_cursor == m_list.end())
148         {
149                 while (m_cursor_number)
150                 {
151                         std::iter_swap(m_cursor--, m_cursor);
152                         --m_cursor_number;
153                         if (m_listbox && m_cursor_number)
154                                 m_listbox->entryChanged(m_cursor_number);
155                 }
156         }
157         else
158         {
159                 m_cursor = m_list.begin();
160                 m_cursor_number = 0;
161         }
162 }
163
164 void eListboxServiceContent::cursorEnd()
165 {
166         if (m_current_marked && m_saved_cursor == m_list.end())
167         {
168                 while (m_cursor != m_list.end())
169                 {
170                         list::iterator prev = m_cursor++;
171                         ++m_cursor_number;
172                         if ( prev != m_list.end() && m_cursor != m_list.end() )
173                         {
174                                 std::iter_swap(m_cursor, prev);
175                                 if ( m_listbox )
176                                         m_listbox->entryChanged(m_cursor_number);
177                         }
178                 }
179         }
180         else
181         {
182                 m_cursor = m_list.end();
183                 m_cursor_number = m_size;
184         }
185 }
186
187 int eListboxServiceContent::setCurrentMarked(bool state)
188 {
189         bool prev = m_current_marked;
190         m_current_marked = state;
191
192         if (state != prev && m_listbox)
193         {
194                 m_listbox->entryChanged(m_cursor_number);
195                 if (!state)
196                 {
197                         ePtr<iListableService> lst;
198                         if (m_service_center->list(m_root, lst))
199                                 eDebug("no list available!");
200                         else
201                         {
202                                 ePtr<iMutableServiceList> list;
203                                 if (lst->startEdit(list))
204                                         eDebug("no editable list");
205                                 else
206                                 {
207                                         eServiceReference ref;
208                                         getCurrent(ref);
209                                         if(!ref)
210                                                 eDebug("no valid service selected");
211                                         else
212                                         {
213                                                 int pos = cursorGet();
214                                                 eDebugNoNewLine("move %s to %d ", ref.toString().c_str(), pos);
215                                                 if (list->moveService(ref, cursorGet()))
216                                                         eDebug("failed");
217                                                 else
218                                                         eDebug("ok");
219                                         }
220                                 }
221                         }
222                 }
223         }
224
225         return 0;
226 }
227
228 int eListboxServiceContent::cursorMove(int count)
229 {
230         int prev = m_cursor_number, last = m_cursor_number + count;
231         if (count > 0)
232         {
233                 while(count && m_cursor != m_list.end())
234                 {
235                         list::iterator prev_it = m_cursor++;
236                         if ( m_current_marked && m_cursor != m_list.end() && m_saved_cursor == m_list.end() )
237                         {
238                                 std::iter_swap(prev_it, m_cursor);
239                                 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
240                                         m_listbox->entryChanged(m_cursor_number);
241                         }
242                         ++m_cursor_number;
243                         --count;
244         }
245         } else if (count < 0)
246         {
247                 while (count && m_cursor != m_list.begin())
248                 {
249                         list::iterator prev_it = m_cursor--;
250                         if ( m_current_marked && m_cursor != m_list.end() && prev_it != m_list.end() && m_saved_cursor == m_list.end() )
251                         {
252                                 std::iter_swap(prev_it, m_cursor);
253                                 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
254                                         m_listbox->entryChanged(m_cursor_number);
255                         }
256                         --m_cursor_number;
257                         ++count;
258                 }
259         }
260         return 0;
261 }
262
263 int eListboxServiceContent::cursorValid()
264 {
265         return m_cursor != m_list.end();
266 }
267
268 int eListboxServiceContent::cursorSet(int n)
269 {
270         cursorHome();
271         cursorMove(n);
272         
273         return 0;
274 }
275
276 int eListboxServiceContent::cursorGet()
277 {
278         return m_cursor_number;
279 }
280
281 void eListboxServiceContent::cursorSave()
282 {
283         m_saved_cursor = m_cursor;
284         m_saved_cursor_number = m_cursor_number;
285 }
286
287 void eListboxServiceContent::cursorRestore()
288 {
289         m_cursor = m_saved_cursor;
290         m_cursor_number = m_saved_cursor_number;
291         m_saved_cursor = m_list.end();
292 }
293
294 int eListboxServiceContent::size()
295 {
296         return m_size;
297 }
298         
299 void eListboxServiceContent::setSize(const eSize &size)
300 {
301         m_itemsize = size;
302         setVisualMode(m_visual_mode);
303 }
304
305 void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
306 {
307         painter.clip(eRect(offset, m_itemsize));
308
309         if (m_current_marked && selected)
310                 style.setStyle(painter, eWindowStyle::styleListboxMarked);
311         else if (cursorValid() && isMarked(*m_cursor))
312                 style.setStyle(painter, eWindowStyle::styleListboxMarked);
313         else
314                 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
315         painter.clear();
316         
317         if (cursorValid())
318         {
319                         /* get service information */
320                 ePtr<iStaticServiceInformation> service_info;
321                 m_service_center->info(*m_cursor, service_info);
322                 
323                 for (int e = 0; e < celElements; ++e)
324                 {
325                         if (!m_element_font[e])
326                                 continue;
327                         painter.setFont(m_element_font[e]);
328                         
329                         std::string text = "<n/a>";
330                         
331                         switch (e)
332                         {
333                         case celServiceName:
334                         {
335                                 if (service_info)
336                                         service_info->getName(*m_cursor, text);
337                                 break;
338                         }
339                         case celServiceNumber:
340                         {
341                                 char bla[10];
342                                 sprintf(bla, "%d", m_numberoffset + m_cursor_number + 1);
343                                 text = bla;
344                                 break;
345                         }
346                         case celServiceInfo:
347                         {
348                                 text = "now&next";
349                                 break;
350                         }
351                         case celIcon:
352                                 continue;
353                         }
354                         
355                         eRect area = m_element_position[e];
356                         area.moveBy(offset.x(), offset.y());
357                         
358                         painter.renderText(area, text);
359                 }
360                 
361                 if (selected)
362                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
363         }
364         
365         painter.clippop();
366 }
367