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