blob: 60517234866e575ea9d054d6ace0ac6f326abb23 [file] [log] [blame]
Dees_Troyeead9852013-02-15 14:31:06 -06001// FileSelector.cpp - GUIFileSelector object
Dees_Troy51a0e822012-09-05 15:24:24 -04002
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"
Dees_Troyeead9852013-02-15 14:31:06 -060034#include "../twrp-functions.hpp"
35
36#define SCROLLING_SPEED_DECREMENT 6
37#define SCROLLING_FLOOR 10
38#define SCROLLING_MULTIPLIER 6
Dees_Troy51a0e822012-09-05 15:24:24 -040039
40GUIListBox::GUIListBox(xml_node<>* node)
41{
Dees_Troyeead9852013-02-15 14:31:06 -060042 xml_attribute<>* attr;
43 xml_node<>* child;
44 int header_separator_color_specified = 0, header_separator_height_specified = 0, header_text_color_specified = 0, header_background_color_specified = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -040045
Dees_Troyeead9852013-02-15 14:31:06 -060046 mStart = mLineSpacing = startY = mFontHeight = mSeparatorH = scrollingY = scrollingSpeed = 0;
Dees_Troye4284592013-02-19 16:59:35 +000047 mIconWidth = mIconHeight = mSelectedIconHeight = mSelectedIconWidth = mUnselectedIconHeight = mUnselectedIconWidth = mHeaderIconHeight = mHeaderIconWidth = 0;
Dees_Troyeead9852013-02-15 14:31:06 -060048 mHeaderSeparatorH = mLineHeight = mHeaderIsStatic = mHeaderH = actualLineHeight = 0;
49 mIconSelected = mIconUnselected = mBackground = mFont = mHeaderIcon = NULL;
50 mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = 0;
Dees_Troy58f5cf02013-02-27 22:21:41 +000051 mFastScrollW = mFastScrollLineW = mFastScrollRectW = mFastScrollRectH = 0;
52 mFastScrollRectX = mFastScrollRectY = -1;
Dees_Troyeead9852013-02-15 14:31:06 -060053 mUpdate = 0;
54 touchDebounce = 6;
55 ConvertStrToColor("black", &mBackgroundColor);
56 ConvertStrToColor("black", &mHeaderBackgroundColor);
57 ConvertStrToColor("black", &mSeparatorColor);
58 ConvertStrToColor("black", &mHeaderSeparatorColor);
59 ConvertStrToColor("white", &mFontColor);
60 ConvertStrToColor("white", &mHeaderFontColor);
Dees_Troy58f5cf02013-02-27 22:21:41 +000061 ConvertStrToColor("white", &mFastScrollLineColor);
62 ConvertStrToColor("white", &mFastScrollRectColor);
Dees_Troyeead9852013-02-15 14:31:06 -060063 hasHighlightColor = false;
64 hasFontHighlightColor = false;
65 isHighlighted = false;
66 startSelection = -1;
Dees_Troy51a0e822012-09-05 15:24:24 -040067
Dees_Troyeead9852013-02-15 14:31:06 -060068 // Load header text
69 child = node->first_node("header");
70 if (child)
71 {
72 attr = child->first_attribute("icon");
73 if (attr)
74 mHeaderIcon = PageManager::FindResource(attr->value());
Dees_Troy51a0e822012-09-05 15:24:24 -040075
Dees_Troyeead9852013-02-15 14:31:06 -060076 attr = child->first_attribute("background");
77 if (attr)
78 {
79 std::string color = attr->value();
80 ConvertStrToColor(color, &mHeaderBackgroundColor);
81 header_background_color_specified = -1;
Dees_Troy51a0e822012-09-05 15:24:24 -040082 }
Dees_Troyeead9852013-02-15 14:31:06 -060083 attr = child->first_attribute("textcolor");
84 if (attr)
85 {
86 std::string color = attr->value();
87 ConvertStrToColor(color, &mHeaderFontColor);
88 header_text_color_specified = -1;
89 }
90 attr = child->first_attribute("separatorcolor");
91 if (attr)
92 {
93 std::string color = attr->value();
94 ConvertStrToColor(color, &mHeaderSeparatorColor);
95 header_separator_color_specified = -1;
96 }
97 attr = child->first_attribute("separatorheight");
98 if (attr) {
99 string parsevalue = gui_parse_text(attr->value());
100 mHeaderSeparatorH = atoi(parsevalue.c_str());
101 header_separator_height_specified = -1;
102 }
103 }
104 child = node->first_node("text");
105 if (child) mHeaderText = child->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400106
Dees_Troyeead9852013-02-15 14:31:06 -0600107 memset(&mHighlightColor, 0, sizeof(COLOR));
108 child = node->first_node("highlight");
109 if (child) {
110 attr = child->first_attribute("color");
111 if (attr) {
112 hasHighlightColor = true;
113 std::string color = attr->value();
114 ConvertStrToColor(color, &mHighlightColor);
115 }
116 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400117
Dees_Troyeead9852013-02-15 14:31:06 -0600118 // Simple way to check for static state
119 mLastValue = gui_parse_text(mHeaderText);
120 if (mLastValue != mHeaderText)
121 mHeaderIsStatic = 0;
122 else
123 mHeaderIsStatic = -1;
124
125 child = node->first_node("icon");
126 if (child)
127 {
128 attr = child->first_attribute("selected");
129 if (attr)
130 mIconSelected = PageManager::FindResource(attr->value());
131 attr = child->first_attribute("unselected");
132 if (attr)
133 mIconUnselected = PageManager::FindResource(attr->value());
134 }
135 child = node->first_node("background");
136 if (child)
137 {
138 attr = child->first_attribute("resource");
139 if (attr)
140 mBackground = PageManager::FindResource(attr->value());
141 attr = child->first_attribute("color");
142 if (attr)
143 {
144 std::string color = attr->value();
145 ConvertStrToColor(color, &mBackgroundColor);
146 if (!header_background_color_specified)
147 ConvertStrToColor(color, &mHeaderBackgroundColor);
148 }
149 }
150
151 // Load the placement
152 LoadPlacement(node->first_node("placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH);
153 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
154
155 // Load the font, and possibly override the color
156 child = node->first_node("font");
157 if (child)
158 {
159 attr = child->first_attribute("resource");
160 if (attr)
161 mFont = PageManager::FindResource(attr->value());
162
163 attr = child->first_attribute("color");
164 if (attr)
165 {
166 std::string color = attr->value();
167 ConvertStrToColor(color, &mFontColor);
168 if (!header_text_color_specified)
169 ConvertStrToColor(color, &mHeaderFontColor);
170 }
171
172 attr = child->first_attribute("spacing");
173 if (attr) {
174 string parsevalue = gui_parse_text(attr->value());
175 mLineSpacing = atoi(parsevalue.c_str());
176 }
177
178 attr = child->first_attribute("highlightcolor");
179 memset(&mFontHighlightColor, 0, sizeof(COLOR));
180 if (attr)
181 {
182 std::string color = attr->value();
183 ConvertStrToColor(color, &mFontHighlightColor);
184 hasFontHighlightColor = true;
185 }
186 }
187
188 // Load the separator if it exists
189 child = node->first_node("separator");
190 if (child)
191 {
192 attr = child->first_attribute("color");
193 if (attr)
194 {
195 std::string color = attr->value();
196 ConvertStrToColor(color, &mSeparatorColor);
197 if (!header_separator_color_specified)
198 ConvertStrToColor(color, &mHeaderSeparatorColor);
199 }
200
201 attr = child->first_attribute("height");
202 if (attr) {
203 string parsevalue = gui_parse_text(attr->value());
204 mSeparatorH = atoi(parsevalue.c_str());
205 if (!header_separator_height_specified)
206 mHeaderSeparatorH = mSeparatorH;
207 }
208 }
209
210 // Handle the result variable
211 child = node->first_node("data");
212 if (child)
213 {
214 attr = child->first_attribute("name");
215 if (attr)
216 mVariable = attr->value();
217 attr = child->first_attribute("default");
218 if (attr)
219 DataManager::SetValue(mVariable, attr->value());
220 }
221
Dees_Troy58f5cf02013-02-27 22:21:41 +0000222 // Fast scroll colors
223 child = node->first_node("fastscroll");
224 if (child)
225 {
226 attr = child->first_attribute("linecolor");
227 if(attr)
228 ConvertStrToColor(attr->value(), &mFastScrollLineColor);
229
230 attr = child->first_attribute("rectcolor");
231 if(attr)
232 ConvertStrToColor(attr->value(), &mFastScrollRectColor);
233
234 attr = child->first_attribute("w");
235 if (attr) {
236 string parsevalue = gui_parse_text(attr->value());
237 mFastScrollW = atoi(parsevalue.c_str());
238 }
239
240 attr = child->first_attribute("linew");
241 if (attr) {
242 string parsevalue = gui_parse_text(attr->value());
243 mFastScrollLineW = atoi(parsevalue.c_str());
244 }
245
246 attr = child->first_attribute("rectw");
247 if (attr) {
248 string parsevalue = gui_parse_text(attr->value());
249 mFastScrollRectW = atoi(parsevalue.c_str());
250 }
251
252 attr = child->first_attribute("recth");
253 if (attr) {
254 string parsevalue = gui_parse_text(attr->value());
255 mFastScrollRectH = atoi(parsevalue.c_str());
256 }
257 }
258
Dees_Troyeead9852013-02-15 14:31:06 -0600259 // Retrieve the line height
260 gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
261 mLineHeight = mFontHeight;
262 mHeaderH = mFontHeight;
263
264 if (mIconSelected && mIconSelected->GetResource())
265 {
266 mSelectedIconWidth = gr_get_width(mIconSelected->GetResource());
267 mSelectedIconHeight = gr_get_height(mIconSelected->GetResource());
268 if (mSelectedIconHeight > (int)mLineHeight)
269 mLineHeight = mSelectedIconHeight;
270 mIconWidth = mSelectedIconWidth;
271 }
272
273 if (mIconUnselected && mIconUnselected->GetResource())
274 {
275 mUnselectedIconWidth = gr_get_width(mIconUnselected->GetResource());
276 mUnselectedIconHeight = gr_get_height(mIconUnselected->GetResource());
277 if (mUnselectedIconHeight > (int)mLineHeight)
278 mLineHeight = mUnselectedIconHeight;
279 if (mUnselectedIconWidth > mIconWidth)
280 mIconWidth = mUnselectedIconWidth;
281 }
282
283 if (mHeaderIcon && mHeaderIcon->GetResource())
284 {
285 mHeaderIconWidth = gr_get_width(mHeaderIcon->GetResource());
286 mHeaderIconHeight = gr_get_height(mHeaderIcon->GetResource());
287 if (mHeaderIconHeight > mHeaderH)
288 mHeaderH = mHeaderIconHeight;
289 if (mHeaderIconWidth > mIconWidth)
290 mIconWidth = mHeaderIconWidth;
291 }
292
293 mHeaderH += mLineSpacing + mHeaderSeparatorH;
294 actualLineHeight = mLineHeight + mLineSpacing + mSeparatorH;
295 if (mHeaderH < actualLineHeight)
296 mHeaderH = actualLineHeight;
297
298 if (actualLineHeight / 3 > 6)
299 touchDebounce = actualLineHeight / 3;
300
301 if (mBackground && mBackground->GetResource())
302 {
303 mBackgroundW = gr_get_width(mBackground->GetResource());
304 mBackgroundH = gr_get_height(mBackground->GetResource());
305 }
306
Dees_Troy51a0e822012-09-05 15:24:24 -0400307 // Get the currently selected value for the list
308 DataManager::GetValue(mVariable, currentValue);
309
310 // Get the data for the list
311 child = node->first_node("listitem");
312 if (!child) return;
313
314 while (child)
315 {
316 ListData data;
317
318 attr = child->first_attribute("name");
319 if (!attr) return;
320 data.displayName = attr->value();
321
322 data.variableValue = child->value();
Dees_Troyeead9852013-02-15 14:31:06 -0600323 if (child->value() == currentValue) {
Dees_Troy51a0e822012-09-05 15:24:24 -0400324 data.selected = 1;
Dees_Troyeead9852013-02-15 14:31:06 -0600325 } else {
Dees_Troy51a0e822012-09-05 15:24:24 -0400326 data.selected = 0;
Dees_Troyeead9852013-02-15 14:31:06 -0600327 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400328
329 mList.push_back(data);
330
331 child = child->next_sibling("listitem");
332 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400333}
334
335GUIListBox::~GUIListBox()
336{
337}
338
339int GUIListBox::Render(void)
Dees_Troyeead9852013-02-15 14:31:06 -0600340{
Dees_Troy51a0e822012-09-05 15:24:24 -0400341 // First step, fill background
Dees_Troyeead9852013-02-15 14:31:06 -0600342 gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
343 gr_fill(mRenderX, mRenderY + mHeaderH, mRenderW, mRenderH - mHeaderH);
Dees_Troy51a0e822012-09-05 15:24:24 -0400344
Dees_Troyeead9852013-02-15 14:31:06 -0600345 // Next, render the background resource (if it exists)
346 if (mBackground && mBackground->GetResource())
347 {
348 mBackgroundX = mRenderX + ((mRenderW - mBackgroundW) / 2);
349 mBackgroundY = mRenderY + ((mRenderH - mBackgroundH) / 2);
350 gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY);
351 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400352
Dees_Troyeead9852013-02-15 14:31:06 -0600353 // This tells us how many lines we can actually render
354 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
355 int line;
Dees_Troy51a0e822012-09-05 15:24:24 -0400356
Dees_Troyeead9852013-02-15 14:31:06 -0600357 int listSize = mList.size();
Dees_Troy58f5cf02013-02-27 22:21:41 +0000358 int listW = mRenderW;
Dees_Troy51a0e822012-09-05 15:24:24 -0400359
Dees_Troyeead9852013-02-15 14:31:06 -0600360 if (listSize < lines) {
361 lines = listSize;
362 scrollingY = 0;
Dees_Troy58f5cf02013-02-27 22:21:41 +0000363 mFastScrollRectX = mFastScrollRectY = -1;
Dees_Troyeead9852013-02-15 14:31:06 -0600364 } else {
Dees_Troy58f5cf02013-02-27 22:21:41 +0000365 listW -= mFastScrollW; // space for fast scroll
Dees_Troyeead9852013-02-15 14:31:06 -0600366 lines++;
367 if (lines < listSize)
368 lines++;
369 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400370
Dees_Troyeead9852013-02-15 14:31:06 -0600371 void* fontResource = NULL;
372 if (mFont) fontResource = mFont->GetResource();
Dees_Troy51a0e822012-09-05 15:24:24 -0400373
Dees_Troyeead9852013-02-15 14:31:06 -0600374 int yPos = mRenderY + mHeaderH + scrollingY;
375 int fontOffsetY = (int)((actualLineHeight - mFontHeight) / 2);
376 int currentIconHeight = 0, currentIconWidth = 0;
377 int currentIconOffsetY = 0, currentIconOffsetX = 0;
378 int UnselectedIconOffsetY = (int)((actualLineHeight - mUnselectedIconHeight) / 2), SelectedIconOffsetY = (int)((actualLineHeight - mSelectedIconHeight) / 2);
379 int UnselectedIconOffsetX = (mIconWidth - mUnselectedIconWidth) / 2, SelectedIconOffsetX = (mIconWidth - mSelectedIconWidth) / 2;
380 int actualSelection = mStart;
Dees_Troy51a0e822012-09-05 15:24:24 -0400381
Dees_Troyeead9852013-02-15 14:31:06 -0600382 if (isHighlighted) {
383 int selectY = scrollingY;
Dees_Troy51a0e822012-09-05 15:24:24 -0400384
Dees_Troyeead9852013-02-15 14:31:06 -0600385 // Locate the correct line for highlighting
386 while (selectY + actualLineHeight < startSelection) {
387 selectY += actualLineHeight;
388 actualSelection++;
389 }
390 if (hasHighlightColor) {
391 // Highlight the area
392 gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, 255);
393 int HighlightHeight = actualLineHeight;
394 if (mRenderY + mHeaderH + selectY + actualLineHeight > mRenderH + mRenderY) {
395 HighlightHeight = actualLineHeight - (mRenderY + mHeaderH + selectY + actualLineHeight - mRenderH - mRenderY);
396 }
397 gr_fill(mRenderX, mRenderY + mHeaderH + selectY, mRenderW, HighlightHeight);
398 }
399 }
400
401 for (line = 0; line < lines; line++)
402 {
403 Resource* icon;
404 std::string label;
405
406 if (line + mStart >= listSize)
407 continue;
408
409 label = mList.at(line + mStart).displayName;
410 if (isHighlighted && hasFontHighlightColor && line + mStart == actualSelection) {
411 // Use the highlight color for the font
412 gr_color(mFontHighlightColor.red, mFontHighlightColor.green, mFontHighlightColor.blue, 255);
413 } else {
414 // Set the color for the font
415 gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, 255);
416 }
417
Dees_Troy51a0e822012-09-05 15:24:24 -0400418 if (mList.at(line + mStart).selected != 0)
419 {
420 icon = mIconSelected;
Dees_Troyeead9852013-02-15 14:31:06 -0600421 currentIconHeight = mSelectedIconHeight;
422 currentIconWidth = mSelectedIconWidth;
423 currentIconOffsetY = SelectedIconOffsetY;
424 currentIconOffsetX = SelectedIconOffsetX;
Dees_Troy51a0e822012-09-05 15:24:24 -0400425 }
426 else
427 {
428 icon = mIconUnselected;
Dees_Troyeead9852013-02-15 14:31:06 -0600429 currentIconHeight = mSelectedIconHeight;
430 currentIconWidth = mSelectedIconWidth;
431 currentIconOffsetY = SelectedIconOffsetY;
432 currentIconOffsetX = SelectedIconOffsetX;
Dees_Troy51a0e822012-09-05 15:24:24 -0400433 }
434
Dees_Troyeead9852013-02-15 14:31:06 -0600435 if (icon && icon->GetResource())
436 {
437 int rect_y = 0, image_y = (yPos + currentIconOffsetY);
438 if (image_y + currentIconHeight > mRenderY + mRenderH)
439 rect_y = mRenderY + mRenderH - image_y;
440 else
441 rect_y = currentIconHeight;
442 gr_blit(icon->GetResource(), 0, 0, currentIconWidth, rect_y, mRenderX + currentIconOffsetX, image_y);
443 }
Dees_Troy58f5cf02013-02-27 22:21:41 +0000444 gr_textExWH(mRenderX + mIconWidth + 5, yPos + fontOffsetY, label.c_str(), fontResource, mRenderX + listW, mRenderY + mRenderH);
Dees_Troy51a0e822012-09-05 15:24:24 -0400445
Dees_Troyeead9852013-02-15 14:31:06 -0600446 // Add the separator
447 if (yPos + actualLineHeight < mRenderH + mRenderY) {
448 gr_color(mSeparatorColor.red, mSeparatorColor.green, mSeparatorColor.blue, 255);
Dees_Troy58f5cf02013-02-27 22:21:41 +0000449 gr_fill(mRenderX, yPos + actualLineHeight - mSeparatorH, listW, mSeparatorH);
Dees_Troyeead9852013-02-15 14:31:06 -0600450 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400451
Dees_Troyeead9852013-02-15 14:31:06 -0600452 // Move the yPos
453 yPos += actualLineHeight;
454 }
455
456 // Render the Header (last so that it overwrites the top most row for per pixel scrolling)
457 // First step, fill background
458 gr_color(mHeaderBackgroundColor.red, mHeaderBackgroundColor.green, mHeaderBackgroundColor.blue, 255);
459 gr_fill(mRenderX, mRenderY, mRenderW, mHeaderH);
460
461 // Now, we need the header (icon + text)
462 yPos = mRenderY;
463 {
464 Resource* headerIcon;
465 int mIconOffsetX = 0;
466
467 // render the icon if it exists
468 headerIcon = mHeaderIcon;
469 if (headerIcon && headerIcon->GetResource())
470 {
471 gr_blit(headerIcon->GetResource(), 0, 0, mHeaderIconWidth, mHeaderIconHeight, mRenderX + ((mHeaderIconWidth - mIconWidth) / 2), (yPos + (int)((mHeaderH - mHeaderIconHeight) / 2)));
472 mIconOffsetX = mIconWidth;
473 }
474
475 // render the text
476 gr_color(mHeaderFontColor.red, mHeaderFontColor.green, mHeaderFontColor.blue, 255);
477 gr_textExWH(mRenderX + mIconOffsetX + 5, yPos + (int)((mHeaderH - mFontHeight) / 2), mLastValue.c_str(), fontResource, mRenderX + mRenderW, mRenderY + mRenderH);
478
479 // Add the separator
480 gr_color(mHeaderSeparatorColor.red, mHeaderSeparatorColor.green, mHeaderSeparatorColor.blue, 255);
481 gr_fill(mRenderX, yPos + mHeaderH - mHeaderSeparatorH, mRenderW, mHeaderSeparatorH);
482 }
483
Dees_Troy58f5cf02013-02-27 22:21:41 +0000484 // render fast scroll
485 lines = (mRenderH - mHeaderH) / (actualLineHeight);
486 if(mFastScrollW > 0 && listSize > lines)
487 {
488 int startX = listW + mRenderX;
489 int fWidth = mRenderW - listW;
490 int fHeight = mRenderH - mHeaderH;
491
492 // line
493 gr_color(mFastScrollLineColor.red, mFastScrollLineColor.green, mFastScrollLineColor.blue, 255);
494 gr_fill(startX + fWidth/2, mRenderY + mHeaderH, mFastScrollLineW, mRenderH - mHeaderH);
495
496 // rect
497 int pct = ((mStart*actualLineHeight - scrollingY)*100)/((listSize)*actualLineHeight-lines*actualLineHeight);
498 mFastScrollRectX = startX + (fWidth - mFastScrollRectW)/2;
499 mFastScrollRectY = mRenderY+mHeaderH + ((fHeight - mFastScrollRectH)*pct)/100;
500
501 gr_color(mFastScrollRectColor.red, mFastScrollRectColor.green, mFastScrollRectColor.blue, 255);
502 gr_fill(mFastScrollRectX, mFastScrollRectY, mFastScrollRectW, mFastScrollRectH);
503 }
504
Dees_Troyeead9852013-02-15 14:31:06 -0600505 mUpdate = 0;
506 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400507}
508
509int GUIListBox::Update(void)
510{
Dees_Troyeead9852013-02-15 14:31:06 -0600511 if (!mHeaderIsStatic) {
512 std::string newValue = gui_parse_text(mHeaderText);
513 if (mLastValue != newValue) {
514 mLastValue = newValue;
515 mUpdate = 1;
516 }
517 }
518
519 if (mUpdate)
520 {
521 mUpdate = 0;
522 if (Render() == 0)
Dees_Troy51a0e822012-09-05 15:24:24 -0400523 return 2;
Dees_Troyeead9852013-02-15 14:31:06 -0600524 }
525
526 // Handle kinetic scrolling
527 if (scrollingSpeed == 0) {
528 // Do nothing
529 } else if (scrollingSpeed > 0) {
530 if (scrollingSpeed < ((int) (actualLineHeight * 2.5))) {
531 scrollingY += scrollingSpeed;
532 scrollingSpeed -= SCROLLING_SPEED_DECREMENT;
533 } else {
534 scrollingY += ((int) (actualLineHeight * 2.5));
535 scrollingSpeed -= SCROLLING_SPEED_DECREMENT;
536 }
537 while (mStart && scrollingY > 0) {
538 mStart--;
539 scrollingY -= actualLineHeight;
540 }
541 if (mStart == 0 && scrollingY > 0) {
542 scrollingY = 0;
543 scrollingSpeed = 0;
544 } else if (scrollingSpeed < SCROLLING_FLOOR)
545 scrollingSpeed = 0;
546 mUpdate = 1;
547 } else if (scrollingSpeed < 0) {
548 int totalSize = mList.size();
549 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
550
551 if (totalSize > lines) {
552 int bottom_offset = ((int)(mRenderH) - mHeaderH) - (lines * actualLineHeight);
553
554 bottom_offset -= actualLineHeight;
555
556 if (abs(scrollingSpeed) < ((int) (actualLineHeight * 2.5))) {
557 scrollingY += scrollingSpeed;
558 scrollingSpeed += SCROLLING_SPEED_DECREMENT;
559 } else {
560 scrollingY -= ((int) (actualLineHeight * 2.5));
561 scrollingSpeed += SCROLLING_SPEED_DECREMENT;
562 }
563 while (mStart + lines + (bottom_offset ? 1 : 0) < totalSize && abs(scrollingY) > actualLineHeight) {
564 mStart++;
565 scrollingY += actualLineHeight;
566 }
567 if (bottom_offset != 0 && mStart + lines + 1 >= totalSize && scrollingY <= bottom_offset) {
568 mStart = totalSize - lines - 1;
569 scrollingY = bottom_offset;
570 } else if (mStart + lines >= totalSize && scrollingY < 0) {
571 mStart = totalSize - lines;
572 scrollingY = 0;
573 } else if (scrollingSpeed * -1 < SCROLLING_FLOOR)
574 scrollingSpeed = 0;
575 mUpdate = 1;
576 }
577 }
578
579 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400580}
581
582int GUIListBox::GetSelection(int x, int y)
583{
Dees_Troyeead9852013-02-15 14:31:06 -0600584 // We only care about y position
585 if (y < mRenderY || y - mRenderY <= mHeaderH || y - mRenderY > mRenderH) return -1;
586 return (y - mRenderY - mHeaderH);
Dees_Troy51a0e822012-09-05 15:24:24 -0400587}
588
589int GUIListBox::NotifyTouch(TOUCH_STATE state, int x, int y)
590{
Dees_Troyeead9852013-02-15 14:31:06 -0600591 static int lastY = 0, last2Y = 0;
592 int selection = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400593
Dees_Troyeead9852013-02-15 14:31:06 -0600594 switch (state)
595 {
596 case TOUCH_START:
597 if (scrollingSpeed != 0)
598 startSelection = -1;
599 else
600 startSelection = GetSelection(x,y);
601 isHighlighted = (startSelection > -1);
602 if (isHighlighted)
603 mUpdate = 1;
604 startY = lastY = last2Y = y;
605 scrollingSpeed = 0;
606 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400607
Dees_Troyeead9852013-02-15 14:31:06 -0600608 case TOUCH_DRAG:
609 // Check if we dragged out of the selection window
610 if (GetSelection(x, y) == -1) {
611 last2Y = lastY = 0;
612 if (isHighlighted) {
613 isHighlighted = false;
614 mUpdate = 1;
615 }
616 break;
617 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400618
Dees_Troy58f5cf02013-02-27 22:21:41 +0000619 // Fast scroll
620 if(mFastScrollRectX != -1 && x >= mRenderX + mRenderW - mFastScrollW)
621 {
622 int pct = ((y-mRenderY-mHeaderH)*100)/(mRenderH-mHeaderH);
623 int totalSize = mList.size();
624 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
625
626 float l = float((totalSize-lines)*pct)/100;
627 if(l + lines >= totalSize)
628 {
629 mStart = totalSize - lines;
630 scrollingY = 0;
631 }
632 else
633 {
634 mStart = l;
635 scrollingY = -(l - int(l))*actualLineHeight;
636 }
637
638 startSelection = -1;
639 mUpdate = 1;
640 scrollingSpeed = 0;
641 isHighlighted = false;
642 break;
643 }
644
Dees_Troyeead9852013-02-15 14:31:06 -0600645 // Provide some debounce on initial touches
646 if (startSelection != -1 && abs(y - startY) < touchDebounce) {
647 isHighlighted = true;
648 mUpdate = 1;
649 break;
650 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400651
Dees_Troyeead9852013-02-15 14:31:06 -0600652 isHighlighted = false;
653 last2Y = lastY;
654 lastY = y;
655 startSelection = -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400656
Dees_Troyeead9852013-02-15 14:31:06 -0600657 // Handle scrolling
658 scrollingY += y - startY;
659 startY = y;
660 while(mStart && scrollingY > 0) {
661 mStart--;
662 scrollingY -= actualLineHeight;
663 }
664 if (mStart == 0 && scrollingY > 0)
665 scrollingY = 0;
666 {
667 int totalSize = mList.size();
668 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
Dees_Troy51a0e822012-09-05 15:24:24 -0400669
Dees_Troyeead9852013-02-15 14:31:06 -0600670 if (totalSize > lines) {
671 int bottom_offset = ((int)(mRenderH) - mHeaderH) - (lines * actualLineHeight);
Dees_Troy51a0e822012-09-05 15:24:24 -0400672
Dees_Troyeead9852013-02-15 14:31:06 -0600673 bottom_offset -= actualLineHeight;
Dees_Troy51a0e822012-09-05 15:24:24 -0400674
Dees_Troyeead9852013-02-15 14:31:06 -0600675 while (mStart + lines + (bottom_offset ? 1 : 0) < totalSize && abs(scrollingY) > actualLineHeight) {
676 mStart++;
677 scrollingY += actualLineHeight;
678 }
679 if (bottom_offset != 0 && mStart + lines + 1 >= totalSize && scrollingY <= bottom_offset) {
680 mStart = totalSize - lines - 1;
681 scrollingY = bottom_offset;
682 } else if (mStart + lines >= totalSize && scrollingY < 0) {
683 mStart = totalSize - lines;
684 scrollingY = 0;
685 }
686 } else
687 scrollingY = 0;
688 }
689 mUpdate = 1;
690 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400691
Dees_Troyeead9852013-02-15 14:31:06 -0600692 case TOUCH_RELEASE:
693 isHighlighted = false;
694 if (startSelection >= 0)
695 {
696 // We've selected an item!
697 std::string str;
698
699 int listSize = mList.size();
700 int selectY = scrollingY, actualSelection = mStart;
701
702 // Move the selection to the proper place in the array
703 while (selectY + actualLineHeight < startSelection) {
704 selectY += actualLineHeight;
705 actualSelection++;
706 }
707
708 if (actualSelection < listSize && !mVariable.empty())
709 {
710 int i;
711 for (i=0; i<listSize; i++)
712 mList.at(i).selected = 0;
713
714 str = mList.at(actualSelection).variableValue;
715 mList.at(actualSelection).selected = 1;
716 DataManager::SetValue(mVariable, str);
717 mUpdate = 1;
718 }
719 } else {
720 // This is for kinetic scrolling
721 scrollingSpeed = lastY - last2Y;
722 if (abs(scrollingSpeed) > SCROLLING_FLOOR)
723 scrollingSpeed *= SCROLLING_MULTIPLIER;
724 else
725 scrollingSpeed = 0;
726 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400727 case TOUCH_REPEAT:
Dees_Troyeead9852013-02-15 14:31:06 -0600728 case TOUCH_HOLD:
729 break;
730 }
731 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400732}
733
734int GUIListBox::NotifyVarChange(std::string varName, std::string value)
735{
Dees_Troyeead9852013-02-15 14:31:06 -0600736 if (!mHeaderIsStatic) {
737 std::string newValue = gui_parse_text(mHeaderText);
738 if (mLastValue != newValue) {
739 mLastValue = newValue;
740 mStart = 0;
741 scrollingY = 0;
742 scrollingSpeed = 0;
743 mUpdate = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400744 }
Dees_Troyeead9852013-02-15 14:31:06 -0600745 }
746 if (varName == mVariable)
Dees_Troy51a0e822012-09-05 15:24:24 -0400747 {
748 int i, listSize = mList.size(), selected_index = 0;
749
750 currentValue = value;
751
752 for (i=0; i<listSize; i++) {
753 if (mList.at(i).variableValue == currentValue) {
754 mList.at(i).selected = 1;
755 selected_index = i;
756 } else
757 mList.at(i).selected = 0;
758 }
759
760 int lines = mRenderH / (mLineHeight + mLineSpacing);
761 int line;
762
763 if (selected_index > mStart + lines - 1)
764 mStart = selected_index;
765 if (mStart > listSize - lines) {
766 mStart = listSize - lines;
767 } else if (selected_index < mStart) {
768 mStart = selected_index;
769 }
770
771 mUpdate = 1;
772 return 0;
773 }
Dees_Troyeead9852013-02-15 14:31:06 -0600774 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400775}
776
777int GUIListBox::SetRenderPos(int x, int y, int w /* = 0 */, int h /* = 0 */)
778{
Dees_Troyeead9852013-02-15 14:31:06 -0600779 mRenderX = x;
780 mRenderY = y;
781 if (w || h)
782 {
783 mRenderW = w;
784 mRenderH = h;
785 }
786 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
787 mUpdate = 1;
788 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400789}
790
791void GUIListBox::SetPageFocus(int inFocus)
792{
Dees_Troyeead9852013-02-15 14:31:06 -0600793 if (inFocus)
794 {
795 DataManager::GetValue(mVariable, currentValue);
796 NotifyVarChange(mVariable, currentValue);
797 mUpdate = 1;
798 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400799}