blob: 888947b290141880a95031d3c3377ce375248cee [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -04001// ListBox.cpp - GUIListBox object
2
3#include <linux/input.h>
4#include <pthread.h>
5#include <stdarg.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <fcntl.h>
10#include <sys/reboot.h>
11#include <sys/stat.h>
12#include <sys/time.h>
13#include <sys/mman.h>
14#include <sys/types.h>
15#include <sys/ioctl.h>
16#include <time.h>
17#include <unistd.h>
18#include <stdlib.h>
19#include <dirent.h>
20#include <ctype.h>
21
22#include <algorithm>
23
24extern "C" {
25#include "../common.h"
26#include "../roots.h"
27#include "../minuitwrp/minui.h"
28#include "../recovery_ui.h"
29}
30
31#include "rapidxml.hpp"
32#include "objects.hpp"
33#include "../data.hpp"
34
35GUIListBox::GUIListBox(xml_node<>* node)
36{
37 xml_attribute<>* attr;
38 xml_node<>* child;
39
40 mStart = mLineSpacing = mIconWidth = mIconHeight = 0;
41 mIconSelected = mIconUnselected = mBackground = mFont = NULL;
42 mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = 0;
43 mUpdate = 0;
44 ConvertStrToColor("black", &mBackgroundColor);
45 ConvertStrToColor("white", &mFontColor);
46
47 child = node->first_node("icon");
48 if (child)
49 {
50 attr = child->first_attribute("selected");
51 if (attr)
52 mIconSelected = PageManager::FindResource(attr->value());
53 attr = child->first_attribute("unselected");
54 if (attr)
55 mIconUnselected = PageManager::FindResource(attr->value());
56 }
57 child = node->first_node("background");
58 if (child)
59 {
60 attr = child->first_attribute("resource");
61 if (attr)
62 mBackground = PageManager::FindResource(attr->value());
63 attr = child->first_attribute("color");
64 if (attr)
65 {
66 std::string color = attr->value();
67 ConvertStrToColor(color, &mBackgroundColor);
68 }
69 }
70
71 // Load the placement
72 LoadPlacement(node->first_node("placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH);
73 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
74
75 // Load the font, and possibly override the color
76 child = node->first_node("font");
77 if (child)
78 {
79 attr = child->first_attribute("resource");
80 if (attr)
81 mFont = PageManager::FindResource(attr->value());
82
83 attr = child->first_attribute("color");
84 if (attr)
85 {
86 std::string color = attr->value();
87 ConvertStrToColor(color, &mFontColor);
88 }
89
90 attr = child->first_attribute("spacing");
91 if (attr) {
92 string parsevalue = gui_parse_text(attr->value());
93 mLineSpacing = atoi(parsevalue.c_str());
94 }
95 }
96
97 // Handle the result variable
98 child = node->first_node("data");
99 if (child)
100 {
101 attr = child->first_attribute("name");
102 if (attr)
103 mVariable = attr->value();
104 attr = child->first_attribute("default");
105 if (attr)
106 DataManager::SetValue(mVariable, attr->value());
107 }
108
109 // Retrieve the line height
110 gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
111 mLineHeight = mFontHeight;
112 if (mIconSelected && mIconSelected->GetResource())
113 {
114 if (gr_get_height(mIconSelected->GetResource()) > mLineHeight)
115 mLineHeight = gr_get_height(mIconSelected->GetResource());
116 mIconWidth = gr_get_width(mIconSelected->GetResource());
117 mIconHeight = gr_get_height(mIconSelected->GetResource());
118 }
119 if (mIconUnselected && mIconUnselected->GetResource())
120 {
121 if (gr_get_height(mIconUnselected->GetResource()) > mLineHeight)
122 mLineHeight = gr_get_height(mIconUnselected->GetResource());
123 mIconWidth = gr_get_width(mIconUnselected->GetResource());
124 mIconHeight = gr_get_height(mIconUnselected->GetResource());
125 }
126
127 if (mBackground && mBackground->GetResource())
128 {
129 mBackgroundW = gr_get_width(mBackground->GetResource());
130 mBackgroundH = gr_get_height(mBackground->GetResource());
131 }
132
133 // Get the currently selected value for the list
134 DataManager::GetValue(mVariable, currentValue);
135
136 // Get the data for the list
137 child = node->first_node("listitem");
138 if (!child) return;
139
140 while (child)
141 {
142 ListData data;
143
144 attr = child->first_attribute("name");
145 if (!attr) return;
146 data.displayName = attr->value();
147
148 data.variableValue = child->value();
149 if (child->value() == currentValue)
150 data.selected = 1;
151 else
152 data.selected = 0;
153
154 mList.push_back(data);
155
156 child = child->next_sibling("listitem");
157 }
158
159 // Call this to get the selected item to be shown in the list on first render
160 NotifyVarChange(mVariable, currentValue);
161}
162
163GUIListBox::~GUIListBox()
164{
165}
166
167int GUIListBox::Render(void)
168{
169 // First step, fill background
170 gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
171 gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
172
173 // Next, render the background resource (if it exists)
174 if (mBackground && mBackground->GetResource())
175 {
176 mBackgroundX = mRenderX + ((mRenderW - mBackgroundW) / 2);
177 mBackgroundY = mRenderY + ((mRenderH - mBackgroundH) / 2);
178 gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY);
179 }
180
181 // Now, we need the lines (icon + text)
182 gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha);
183
184 // This tells us how many lines we can actually render
185 int lines = mRenderH / (mLineHeight + mLineSpacing);
186 int line;
187
188 int listSize = mList.size();
189
190 if (listSize < lines) lines = listSize;
191
192 void* fontResource = NULL;
193 if (mFont) fontResource = mFont->GetResource();
194
195 int yPos = mRenderY + (mLineSpacing / 2);
196 for (line = 0; line < lines; line++)
197 {
198 Resource* icon;
199 std::string label;
200
201 label = mList.at(line + mStart).displayName;
202 if (mList.at(line + mStart).selected != 0)
203 {
204 icon = mIconSelected;
205 }
206 else
207 {
208 icon = mIconUnselected;
209 }
210
211 if (icon && icon->GetResource())
212 {
213 gr_blit(icon->GetResource(), 0, 0, mIconWidth, mIconHeight, mRenderX, (yPos + (int)((mLineHeight - mIconHeight) / 2)));
214 }
215 gr_textExW(mRenderX + mIconWidth + 5, yPos, label.c_str(), fontResource, mRenderX + mRenderW - mIconWidth - 5);
216
217 // Move the yPos
218 yPos += mLineHeight + mLineSpacing;
219 }
220
221 mUpdate = 0;
222 return 0;
223}
224
225int GUIListBox::Update(void)
226{
227 if (mUpdate)
228 {
229 mUpdate = 0;
230 if (Render() == 0)
231 return 2;
232 }
233 return 0;
234}
235
236int GUIListBox::GetSelection(int x, int y)
237{
238 // We only care about y position
239 return (y - mRenderY) / (mLineHeight + mLineSpacing);
240}
241
242int GUIListBox::NotifyTouch(TOUCH_STATE state, int x, int y)
243{
244 static int startSelection = -1;
245 static int startY = 0;
246 int selection = 0;
247
248 switch (state)
249 {
250 case TOUCH_START:
251 startSelection = GetSelection(x,y);
252 startY = y;
253 break;
254
255 case TOUCH_DRAG:
256 // Check if we dragged out of the selection window
257 selection = GetSelection(x,y);
258 if (startSelection != selection)
259 {
260 startSelection = -1;
261
262 // Handle scrolling
263 if (y > (int) (startY + (mLineHeight + mLineSpacing)))
264 {
265 if (mStart) mStart--;
266 mUpdate = 1;
267 startY = y;
268 }
269 else if (y < (int) (startY - (mLineHeight + mLineSpacing)))
270 {
271 int listSize = mList.size();
272 int lines = mRenderH / (mLineHeight + mLineSpacing);
273
274 if (mStart + lines < listSize) mStart++;
275 mUpdate = 1;
276 startY = y;
277 }
278 }
279 break;
280
281 case TOUCH_RELEASE:
282 if (startSelection >= 0)
283 {
284 // We've selected an item!
285 std::string str;
286
287 int listSize = mList.size();
288
289 // Move the selection to the proper place in the array
290 startSelection += mStart;
291
292 if (startSelection < listSize)
293 {
294 if (!mVariable.empty())
295 {
296 int i;
297 for (i=0; i<listSize; i++)
298 mList.at(i).selected = 0;
299
300 str = mList.at(startSelection).variableValue;
301 mList.at(startSelection).selected = 1;
302 DataManager::SetValue(mVariable, str);
303 mUpdate = 1;
304 }
305 }
306 }
307 case TOUCH_HOLD:
308 case TOUCH_REPEAT:
309 break;
310 }
311 return 0;
312}
313
314int GUIListBox::NotifyVarChange(std::string varName, std::string value)
315{
316 string checkValue;
317 int var_changed = 0;
318
319 if (varName.empty())
320 {
321 DataManager::GetValue(mVariable, checkValue);
322 if (checkValue != currentValue) {
323 varName = mVariable;
324 value = checkValue;
325 currentValue = checkValue;
326 var_changed = 1;
327 }
328 }
329 if (varName == mVariable || var_changed != 0)
330 {
331 int i, listSize = mList.size(), selected_index = 0;
332
333 currentValue = value;
334
335 for (i=0; i<listSize; i++) {
336 if (mList.at(i).variableValue == currentValue) {
337 mList.at(i).selected = 1;
338 selected_index = i;
339 } else
340 mList.at(i).selected = 0;
341 }
342
343 int lines = mRenderH / (mLineHeight + mLineSpacing);
344 int line;
345
346 if (selected_index > mStart + lines - 1)
347 mStart = selected_index;
348 if (mStart > listSize - lines) {
349 mStart = listSize - lines;
350 } else if (selected_index < mStart) {
351 mStart = selected_index;
352 }
353
354 mUpdate = 1;
355 return 0;
356 }
357 return 0;
358}
359
360int GUIListBox::SetRenderPos(int x, int y, int w /* = 0 */, int h /* = 0 */)
361{
362 mRenderX = x;
363 mRenderY = y;
364 if (w || h)
365 {
366 mRenderW = w;
367 mRenderH = h;
368 }
369 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
370 mUpdate = 1;
371 return 0;
372}
373
374void GUIListBox::SetPageFocus(int inFocus)
375{
376 if (inFocus)
377 {
378 mUpdate = 1;
379 }
380}
381