]> Shamusworld >> Repos - virtualjaguar/blob - src/gui/listbox.cpp
9b47ff9b877b6274c5a9615d8567686f33745aca
[virtualjaguar] / src / gui / listbox.cpp
1 //
2 // ListBox class
3 //
4 // by James L. Hammons
5 //
6
7 #include "listbox.h"
8
9 #include "guimisc.h"
10
11 ListBox::ListBox(uint32 x, uint32 y, uint32 w, uint32 h): Element(x, y, w, h),
12         thumbClicked(false), windowPtr(0), cursor(0), limit(0), charWidth((w / FONT_WIDTH) - 1),
13         charHeight(h / FONT_HEIGHT), elementToTell(NULL), upArrow(w - 8, 0, upArrowBox),
14         downArrow(w - 8, h - 8, downArrowBox), upArrow2(w - 8, h - 16, upArrowBox)
15 {
16         upArrow.SetNotificationElement(this);
17         downArrow.SetNotificationElement(this);
18         upArrow2.SetNotificationElement(this);
19         extents.w -= 8;                                                                 // Make room for scrollbar...
20 }
21
22 void ListBox::HandleKey(SDLKey key)
23 {
24         if (key == SDLK_DOWN)
25         {
26                 if (cursor != limit - 1)        // Cursor is within its window
27                         cursor++;
28                 else                                            // Otherwise, scroll the window...
29                 {
30                         if (cursor + windowPtr != item.size() - 1)
31                                 windowPtr++;
32                 }
33         }
34         else if (key == SDLK_UP)
35         {
36                 if (cursor != 0)
37                         cursor--;
38                 else
39                 {
40                         if (windowPtr != 0)
41                                 windowPtr--;
42                 }
43         }
44         else if (key == SDLK_PAGEDOWN)
45         {
46                 if (cursor != limit - 1)
47                         cursor = limit - 1;
48                 else
49                 {
50                         windowPtr += limit;
51                         if (windowPtr > item.size() - limit)
52                                 windowPtr = item.size() - limit;
53                 }
54         }
55         else if (key == SDLK_PAGEUP)
56         {
57                 if (cursor != 0)
58                         cursor = 0;
59                 else
60                 {
61                         if (windowPtr < limit)
62                                 windowPtr = 0;
63                         else
64                                 windowPtr -= limit;
65                 }
66         }
67         else if (key >= SDLK_a && key <= SDLK_z)
68         {
69                 // Advance cursor to filename with first letter pressed...
70                 uint8 which = (key - SDLK_a) + 65;      // Convert key to A-Z char
71
72                 for(uint32 i=0; i<item.size(); i++)
73                 {
74                         if ((item[i][0] & 0xDF) == which)
75                         {
76                                 cursor = i - windowPtr;
77                                 if (i > windowPtr + limit - 1)
78                                         windowPtr = i - limit + 1, cursor = limit - 1;
79                                 if (i < windowPtr)
80                                         windowPtr = i, cursor = 0;
81                                 break;
82                         }
83                 }
84         }
85 }
86
87 void ListBox::HandleMouseMove(uint32 x, uint32 y)
88 {
89         upArrow.HandleMouseMove(x - extents.x, y - extents.y);
90         downArrow.HandleMouseMove(x - extents.x, y - extents.y);
91         upArrow2.HandleMouseMove(x - extents.x, y - extents.y);
92
93         if (thumbClicked)
94         {
95                 uint32 sbHeight = extents.h - 24,
96                         thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight);
97
98 //yRelativePoint is the spot on the thumb where we clicked...
99                 int32 newThumbStart = y - yRelativePoint;
100
101                 if (newThumbStart < 0)
102                         newThumbStart = 0;
103
104                 if ((uint32)newThumbStart > sbHeight - thumb)
105                         newThumbStart = sbHeight - thumb;
106
107                 windowPtr = (uint32)(((float)newThumbStart / (float)sbHeight) * (float)item.size());
108 //Check for cursor bounds as well... Or do we need to???
109 //Actually, we don't...!
110         }
111 }
112
113 void ListBox::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
114 {
115         if (Inside(x, y) && mouseDown)
116         {
117                 // Why do we have to do this??? (- extents.y?)
118                 // I guess it's because only the Window class has offsetting implemented... !!! FIX !!!
119 //              cursor = (y - extents.y) / 8;
120                 cursor = (y - extents.y) / FONT_HEIGHT;
121         }
122
123         // Check for a hit on the scrollbar...
124         if (x > (uint32)(extents.x + extents.w) && x <= (uint32)(extents.x + extents.w + 8)
125                 && y > (uint32)(extents.y + 8) && y <= (uint32)(extents.y + extents.h - 16))
126         {
127                 if (mouseDown)
128                 {
129 // This shiaut should be calculated in AddItem(), not here... (or in Draw() for that matter)
130                         uint32 sbHeight = extents.h - 24,
131                                 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight),
132                                 thumbStart = (uint32)(((float)windowPtr / (float)item.size()) * (float)sbHeight);
133
134                         // Did we hit the thumb?
135                         if (y >= (extents.y + 8 + thumbStart) && y < (extents.y + 8 + thumbStart + thumb))
136                                 thumbClicked = true, yRelativePoint = y - thumbStart;
137                 }
138 //Seems that this is useless--never reached except in rare cases and that the code outside is
139 //more effective...
140 //              else
141 //                      thumbClicked = false;
142         }
143
144         if (!mouseDown)
145                 thumbClicked = false;
146
147         upArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
148         downArrow.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
149         upArrow2.HandleMouseButton(x - extents.x, y - extents.y, mouseDown);
150 }
151
152 void ListBox::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
153 {
154         for(uint32 i=0; i<limit; i++)
155         {
156                 // Strip off the extension
157                 // (extension stripping should be an option, not default!)
158                 std::string s(item[windowPtr + i], 0, item[windowPtr + i].length() - 4);
159 //              DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY + i*8,
160                 DrawString(screenBuffer, extents.x + offsetX, extents.y + offsetY + i*FONT_HEIGHT,
161                         (cursor == i ? true : false), "%-*.*s", charWidth, charWidth, s.c_str());
162         }
163
164         upArrow.Draw(extents.x + offsetX, extents.y + offsetY);
165         downArrow.Draw(extents.x + offsetX, extents.y + offsetY);
166         upArrow2.Draw(extents.x + offsetX, extents.y + offsetY);
167
168         uint32 sbHeight = extents.h - 24,
169                 thumb = (uint32)(((float)limit / (float)item.size()) * (float)sbHeight),
170                 thumbStart = (uint32)(((float)windowPtr / (float)item.size()) * (float)sbHeight);
171
172         for(uint32 y=extents.y+offsetY+8; y<extents.y+offsetY+extents.h-16; y++)
173         {
174 //              for(uint32 x=extents.x+offsetX+extents.w-8; x<extents.x+offsetX+extents.w; x++)
175                 for(uint32 x=extents.x+offsetX+extents.w; x<extents.x+offsetX+extents.w+8; x++)
176                 {
177                         if (y >= thumbStart + (extents.y+offsetY+8) && y < thumbStart + thumb + (extents.y+offsetY+8))
178 //                              screenBuffer[x + (y * pitch)] = (thumbClicked ? 0x458E : 0xFFFF);
179 //458E -> 01 0001  0 1100  0 1110 -> 0100 0101  0110 0011  0111 0011 -> 45 63 73
180                                 screenBuffer[x + (y * pitch)] = (thumbClicked ? 0xFF736345 : 0xFFFFFFFF);
181                         else
182 //                              screenBuffer[x + (y * pitch)] = 0x0200;
183 //0200 -> 000000 10000 00000 -> 00 1000 0100 00
184                                 screenBuffer[x + (y * pitch)] = 0xFF008400;
185                 }
186         }
187 }
188
189 void ListBox::Notify(Element * e)
190 {
191         if (e == &upArrow || e == &upArrow2)
192         {
193                 if (windowPtr != 0)
194                 {
195                         windowPtr--;
196
197                         if (cursor < limit - 1)
198                                 cursor++;
199                 }
200         }
201         else if (e == &downArrow)
202         {
203                 if (windowPtr < item.size() - limit)
204                 {
205                         windowPtr++;
206
207                         if (cursor != 0)
208                                 cursor--;
209                 }
210         }
211 }
212
213 void ListBox::SetNotificationElement(Element * e)
214 {
215         elementToTell = e;
216 }
217
218 void ListBox::AddItem(std::string s)
219 {
220         // Do a simple insertion sort
221         bool inserted = false;
222
223         for(std::vector<std::string>::iterator i=item.begin(); i<item.end(); i++)
224         {
225                 if (stringCmpi(s, *i) == -1)
226                 {
227                         item.insert(i, s);
228                         inserted = true;
229                         break;
230                 }
231         }
232
233         if (!inserted)
234                 item.push_back(s);
235
236         limit = (item.size() > charHeight ? charHeight : item.size());
237 }
238
239 std::string ListBox::GetSelectedItem(void)
240 {
241         return item[windowPtr + cursor];
242 }