96214aea6abb762abbac7edb49146b16dec1d46f
[enigma2.git] / lib / gui / elistbox.cpp
1 #include <lib/gui/elistbox.h>
2 #include <lib/gui/elistboxcontent.h>
3
4 eListbox::eListbox(eWidget *parent): eWidget(parent)
5 {
6         setContent(new eListboxStringContent());
7 }
8
9 void eListbox::setContent(iListboxContent *content)
10 {
11         m_content = content;
12         invalidate();
13         m_content->cursorHome();
14         m_top = 0;
15         m_selected = 0;
16 }
17
18 void eListbox::moveSelection(int dir)
19 {
20                 /* we need the old top/sel to see what we have to redraw */
21         int oldtop = m_top;
22         int oldsel = m_selected;
23         
24                 /* first, move cursor */
25         switch (dir)
26         {
27         case moveUp:
28                 m_content->cursorMove(-1);
29                 break;
30         case moveDown:
31                 m_content->cursorMove(1);
32                         /* ok - we could have reached the end. we just go one back then. */
33                 if (!m_content->cursorValid())
34                         m_content->cursorMove(-1);
35                 break;
36         case moveTop:
37                 m_content->cursorHome();
38                 m_top = 0; /* align with top, speeds up process */
39                 break;
40         case moveEnd:
41                         /* move to last existing one ("end" is already invalid) */
42                 m_content->cursorEnd(); m_content->cursorMove(-1); 
43                 
44                 m_top = m_content->cursorGet() - m_items_per_page + 1;
45                 if (m_top < 0)
46                         m_top = 0;
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         if (m_selected < m_top)
57         {
58                 m_top -= m_items_per_page;
59                 if (m_top < 0)
60                         m_top = 0;
61         } else if (m_selected >= m_top + m_items_per_page)
62         {
63                         /* m_top should be always valid here as it's selected */
64                 m_top += m_items_per_page;
65         }
66         
67         if (m_top != oldtop)
68                 invalidate();
69         else
70         {
71                         /* redraw the old and newly selected */
72                 gRegion inv = eRect(0, m_itemheight * (m_selected-m_top), size().width(), m_itemheight);
73                 inv |= eRect(0, m_itemheight * (oldsel-m_top), size().width(), m_itemheight);
74                 
75                 invalidate(inv);
76         }
77 }
78
79 int eListbox::event(int event, void *data, void *data2)
80 {
81         switch (event)
82         {
83         case evtPaint:
84         {
85                 ePtr<eWindowStyle> style;
86                 
87                 assert(m_content);
88                 recalcSize(); // move to event
89                 
90                 getStyle(style);
91                 
92                 if (!m_content)
93                         return 0;
94                 
95                 gPainter &painter = *(gPainter*)data2;
96                 
97                 m_content->cursorSave();
98                 m_content->cursorMove(m_top - m_selected);
99                 
100                 for (int y = 0, i = 0; i < m_items_per_page; y += m_itemheight, ++i)
101                 {
102                         m_content->paint(painter, *style, ePoint(0, y), m_selected == m_content->cursorGet());
103                         m_content->cursorMove(+1);
104                 }
105                 
106                 m_content->cursorRestore();
107                 
108                 return 0;
109         }
110         default:
111                 return eWidget::event(event, data, data2);
112         }
113 }
114
115 void eListbox::recalcSize()
116 {
117         eDebug("recalc size");
118         m_itemheight = 20;
119         m_content->setSize(eSize(size().width(), m_itemheight));
120         m_items_per_page = size().height() / m_itemheight;
121         eDebug("done!");
122 }