- added iStaticServiceInformation
[enigma2.git] / lib / gui / elistbox.cpp
1         /* written by: Felix Domke <tmbinc@elitedvb.net> */
2 #include <lib/gui/elistbox.h>
3 #include <lib/gui/elistboxcontent.h>
4
5 eListbox::eListbox(eWidget *parent): eWidget(parent)
6 {
7         setContent(new eListboxStringContent());
8 }
9
10 void eListbox::setContent(iListboxContent *content)
11 {
12         m_content = content;
13         entryReset();
14 }
15
16 void eListbox::moveSelection(int dir)
17 {
18                 /* we need the old top/sel to see what we have to redraw */
19         int oldtop = m_top;
20         int oldsel = m_selected;
21         
22                 /* first, move cursor */
23         switch (dir)
24         {
25         case moveUp:
26                 m_content->cursorMove(-1);
27                 break;
28         case moveDown:
29                 m_content->cursorMove(1);
30                         /* ok - we could have reached the end. we just go one back then. */
31                 if (!m_content->cursorValid())
32                         m_content->cursorMove(-1);
33                 break;
34         case moveTop:
35                 m_content->cursorHome();
36                 m_top = 0; /* align with top, speeds up process */
37                 break;
38         case moveEnd:
39                         /* move to last existing one ("end" is already invalid) */
40                 m_content->cursorEnd(); m_content->cursorMove(-1); 
41                 
42                 m_top = m_content->cursorGet() - m_items_per_page + 1;
43                 if (m_top < 0)
44                         m_top = 0;
45                 break;
46         case justCheck:
47                 break;
48         }
49         
50                 /* note that we could be on an invalid cursor position, but we don't
51                    care. this only happens on empty lists, and should have almost no
52                    side effects. */
53         
54                 /* now, look wether the current selection is out of screen */
55         m_selected = m_content->cursorGet();
56         
57         if (m_selected < m_top)
58         {
59                 m_top -= m_items_per_page;
60                 if (m_top < 0)
61                         m_top = 0;
62         } else if (m_selected >= m_top + m_items_per_page)
63         {
64                         /* m_top should be always valid here as it's selected */
65                 m_top += m_items_per_page;
66         }
67
68         if (m_top != oldtop)
69                 invalidate();
70         else if (m_selected != oldsel)
71         {
72                 
73                         /* redraw the old and newly selected */
74                 gRegion inv = eRect(0, m_itemheight * (m_selected-m_top), size().width(), m_itemheight);
75                 inv |= eRect(0, m_itemheight * (oldsel-m_top), size().width(), m_itemheight);
76                 
77                 invalidate(inv);
78         }
79 }
80
81 int eListbox::event(int event, void *data, void *data2)
82 {
83         switch (event)
84         {
85         case evtPaint:
86         {
87                 ePtr<eWindowStyle> style;
88                 
89                 assert(m_content);
90                 recalcSize(); // move to event
91                 
92                 getStyle(style);
93                 
94                 if (!m_content)
95                         return 0;
96                 
97                 gPainter &painter = *(gPainter*)data2;
98                 
99                 m_content->cursorSave();
100                 m_content->cursorMove(m_top - m_selected);
101                 
102                 for (int y = 0, i = 0; i < m_items_per_page; y += m_itemheight, ++i)
103                 {
104                         m_content->paint(painter, *style, ePoint(0, y), m_selected == m_content->cursorGet());
105                         m_content->cursorMove(+1);
106                 }
107                 
108                 m_content->cursorRestore();
109                 
110                 return 0;
111         }
112         default:
113                 return eWidget::event(event, data, data2);
114         }
115 }
116
117 void eListbox::recalcSize()
118 {
119         m_itemheight = 20;
120         m_content->setSize(eSize(size().width(), m_itemheight));
121         m_items_per_page = size().height() / m_itemheight;
122 }
123
124 void eListbox::entryAdded(int index)
125 {
126                 /* manage our local pointers. when the entry was added before the current position, we have to advance. */
127                 
128                 /* we need to check <= - when the new entry has the (old) index of the cursor, the cursor was just moved down. */
129         if (index <= m_selected)
130                 ++m_selected;
131         if (index <= m_top)
132                 ++m_top;
133                 
134                 /* we have to check wether our current cursor is gone out of the screen. */
135                 /* moveSelection will check for this case */
136         moveSelection(justCheck);
137         
138                 /* now, check if the new index is visible. */
139         if ((m_top <= index) && (index < (m_top + m_items_per_page)))
140         {
141                         /* todo, calc exact invalidation... */
142                 invalidate();
143         }
144 }
145
146 void eListbox::entryRemoved(int index)
147 {
148         if (index == m_selected)
149                 m_selected = m_content->cursorGet();
150
151         moveSelection(justCheck);
152         
153         if ((m_top <= index) && (index < (m_top + m_items_per_page)))
154         {
155                         /* todo, calc exact invalidation... */
156                 invalidate();
157         }
158 }
159
160 void eListbox::entryChanged(int index)
161 {
162         if ((m_top <= index) && (index < (m_top + m_items_per_page)))
163         {
164                 gRegion inv = eRect(0, m_itemheight * (index-m_top), size().width(), m_itemheight);
165                 invalidate(inv);
166         }
167 }
168
169 void eListbox::entryReset()
170 {
171         invalidate();
172         if (m_content)
173                 m_content->cursorHome();
174         m_top = 0;
175         m_selected = 0;
176 }