blob: 35bf702bb055c270869d0d42d059e1fe23fb54f5 [file] [log] [blame]
Dees_Troya13d74f2013-03-24 08:54:55 -05001/*
2 Copyright 2013 bigbiff/Dees_Troy TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include <linux/input.h>
20#include <pthread.h>
21#include <stdarg.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <fcntl.h>
26#include <sys/reboot.h>
27#include <sys/stat.h>
28#include <sys/time.h>
29#include <sys/mman.h>
30#include <sys/types.h>
31#include <sys/ioctl.h>
32#include <time.h>
33#include <unistd.h>
34#include <stdlib.h>
35#include <dirent.h>
36#include <ctype.h>
37
38#include <algorithm>
39
40extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000041#include "../twcommon.h"
Dees_Troya13d74f2013-03-24 08:54:55 -050042#include "../minuitwrp/minui.h"
Dees_Troya13d74f2013-03-24 08:54:55 -050043}
44
45#include "rapidxml.hpp"
46#include "objects.hpp"
47#include "../data.hpp"
48#include "../twrp-functions.hpp"
49#include "../partitions.hpp"
50
51#define SCROLLING_SPEED_DECREMENT 6
52#define SCROLLING_FLOOR 10
53#define SCROLLING_MULTIPLIER 6
54
55GUIPartitionList::GUIPartitionList(xml_node<>* node)
56{
57 xml_attribute<>* attr;
58 xml_node<>* child;
59 int header_separator_color_specified = 0, header_separator_height_specified = 0, header_text_color_specified = 0, header_background_color_specified = 0;
60
61 mStart = mLineSpacing = startY = mFontHeight = mSeparatorH = scrollingY = scrollingSpeed = 0;
62 mIconWidth = mIconHeight = mSelectedIconHeight = mSelectedIconWidth = mUnselectedIconHeight = mUnselectedIconWidth = mHeaderIconHeight = mHeaderIconWidth = 0;
63 mHeaderSeparatorH = mLineHeight = mHeaderIsStatic = mHeaderH = actualLineHeight = 0;
64 mIconSelected = mIconUnselected = mBackground = mFont = mHeaderIcon = NULL;
65 mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = 0;
66 mFastScrollW = mFastScrollLineW = mFastScrollRectW = mFastScrollRectH = 0;
67 mFastScrollRectX = mFastScrollRectY = -1;
68 mUpdate = 0;
69 touchDebounce = 6;
70 ConvertStrToColor("black", &mBackgroundColor);
71 ConvertStrToColor("black", &mHeaderBackgroundColor);
72 ConvertStrToColor("black", &mSeparatorColor);
73 ConvertStrToColor("black", &mHeaderSeparatorColor);
74 ConvertStrToColor("white", &mFontColor);
75 ConvertStrToColor("white", &mHeaderFontColor);
76 ConvertStrToColor("white", &mFastScrollLineColor);
77 ConvertStrToColor("white", &mFastScrollRectColor);
78 hasHighlightColor = false;
79 hasFontHighlightColor = false;
80 isHighlighted = false;
81 updateList = false;
82 startSelection = -1;
83
84 // Load header text
85 child = node->first_node("header");
86 if (child)
87 {
88 attr = child->first_attribute("icon");
89 if (attr)
90 mHeaderIcon = PageManager::FindResource(attr->value());
91
92 attr = child->first_attribute("background");
93 if (attr)
94 {
95 std::string color = attr->value();
96 ConvertStrToColor(color, &mHeaderBackgroundColor);
97 header_background_color_specified = -1;
98 }
99 attr = child->first_attribute("textcolor");
100 if (attr)
101 {
102 std::string color = attr->value();
103 ConvertStrToColor(color, &mHeaderFontColor);
104 header_text_color_specified = -1;
105 }
106 attr = child->first_attribute("separatorcolor");
107 if (attr)
108 {
109 std::string color = attr->value();
110 ConvertStrToColor(color, &mHeaderSeparatorColor);
111 header_separator_color_specified = -1;
112 }
113 attr = child->first_attribute("separatorheight");
114 if (attr) {
115 string parsevalue = gui_parse_text(attr->value());
116 mHeaderSeparatorH = atoi(parsevalue.c_str());
117 header_separator_height_specified = -1;
118 }
119 }
120 child = node->first_node("text");
121 if (child) mHeaderText = child->value();
122
123 memset(&mHighlightColor, 0, sizeof(COLOR));
124 child = node->first_node("highlight");
125 if (child) {
126 attr = child->first_attribute("color");
127 if (attr) {
128 hasHighlightColor = true;
129 std::string color = attr->value();
130 ConvertStrToColor(color, &mHighlightColor);
131 }
132 }
133
134 // Simple way to check for static state
135 mLastValue = gui_parse_text(mHeaderText);
136 if (mLastValue != mHeaderText)
137 mHeaderIsStatic = 0;
138 else
139 mHeaderIsStatic = -1;
140
141 child = node->first_node("icon");
142 if (child)
143 {
144 attr = child->first_attribute("selected");
145 if (attr)
146 mIconSelected = PageManager::FindResource(attr->value());
147 attr = child->first_attribute("unselected");
148 if (attr)
149 mIconUnselected = PageManager::FindResource(attr->value());
150 }
151 child = node->first_node("background");
152 if (child)
153 {
154 attr = child->first_attribute("resource");
155 if (attr)
156 mBackground = PageManager::FindResource(attr->value());
157 attr = child->first_attribute("color");
158 if (attr)
159 {
160 std::string color = attr->value();
161 ConvertStrToColor(color, &mBackgroundColor);
162 if (!header_background_color_specified)
163 ConvertStrToColor(color, &mHeaderBackgroundColor);
164 }
165 }
166
167 // Load the placement
168 LoadPlacement(node->first_node("placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH);
169 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
170
171 // Load the font, and possibly override the color
172 child = node->first_node("font");
173 if (child)
174 {
175 attr = child->first_attribute("resource");
176 if (attr)
177 mFont = PageManager::FindResource(attr->value());
178
179 attr = child->first_attribute("color");
180 if (attr)
181 {
182 std::string color = attr->value();
183 ConvertStrToColor(color, &mFontColor);
184 if (!header_text_color_specified)
185 ConvertStrToColor(color, &mHeaderFontColor);
186 }
187
188 attr = child->first_attribute("spacing");
189 if (attr) {
190 string parsevalue = gui_parse_text(attr->value());
191 mLineSpacing = atoi(parsevalue.c_str());
192 }
193
194 attr = child->first_attribute("highlightcolor");
195 memset(&mFontHighlightColor, 0, sizeof(COLOR));
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200196 if (attr)
197 {
198 std::string color = attr->value();
Dees_Troya13d74f2013-03-24 08:54:55 -0500199 ConvertStrToColor(color, &mFontHighlightColor);
200 hasFontHighlightColor = true;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200201 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500202 }
203
204 // Load the separator if it exists
205 child = node->first_node("separator");
206 if (child)
207 {
208 attr = child->first_attribute("color");
209 if (attr)
210 {
211 std::string color = attr->value();
212 ConvertStrToColor(color, &mSeparatorColor);
213 if (!header_separator_color_specified)
214 ConvertStrToColor(color, &mHeaderSeparatorColor);
215 }
216
217 attr = child->first_attribute("height");
218 if (attr) {
219 string parsevalue = gui_parse_text(attr->value());
220 mSeparatorH = atoi(parsevalue.c_str());
221 if (!header_separator_height_specified)
222 mHeaderSeparatorH = mSeparatorH;
223 }
224 }
225
226 // Handle the result variable
227 child = node->first_node("data");
228 if (child)
229 {
230 attr = child->first_attribute("name");
231 if (attr)
232 mVariable = attr->value();
233 attr = child->first_attribute("selectedlist");
234 if (attr)
235 selectedList = attr->value();
236 }
237
238 // Fast scroll colors
239 child = node->first_node("fastscroll");
240 if (child)
241 {
242 attr = child->first_attribute("linecolor");
243 if(attr)
244 ConvertStrToColor(attr->value(), &mFastScrollLineColor);
245
246 attr = child->first_attribute("rectcolor");
247 if(attr)
248 ConvertStrToColor(attr->value(), &mFastScrollRectColor);
249
250 attr = child->first_attribute("w");
251 if (attr) {
252 string parsevalue = gui_parse_text(attr->value());
253 mFastScrollW = atoi(parsevalue.c_str());
254 }
255
256 attr = child->first_attribute("linew");
257 if (attr) {
258 string parsevalue = gui_parse_text(attr->value());
259 mFastScrollLineW = atoi(parsevalue.c_str());
260 }
261
262 attr = child->first_attribute("rectw");
263 if (attr) {
264 string parsevalue = gui_parse_text(attr->value());
265 mFastScrollRectW = atoi(parsevalue.c_str());
266 }
267
268 attr = child->first_attribute("recth");
269 if (attr) {
270 string parsevalue = gui_parse_text(attr->value());
271 mFastScrollRectH = atoi(parsevalue.c_str());
272 }
273 }
274
275 // Retrieve the line height
276 gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
277 mLineHeight = mFontHeight;
278 mHeaderH = mFontHeight;
279
280 if (mIconSelected && mIconSelected->GetResource())
281 {
282 mSelectedIconWidth = gr_get_width(mIconSelected->GetResource());
283 mSelectedIconHeight = gr_get_height(mIconSelected->GetResource());
284 if (mSelectedIconHeight > (int)mLineHeight)
285 mLineHeight = mSelectedIconHeight;
286 mIconWidth = mSelectedIconWidth;
287 }
288
289 if (mIconUnselected && mIconUnselected->GetResource())
290 {
291 mUnselectedIconWidth = gr_get_width(mIconUnselected->GetResource());
292 mUnselectedIconHeight = gr_get_height(mIconUnselected->GetResource());
293 if (mUnselectedIconHeight > (int)mLineHeight)
294 mLineHeight = mUnselectedIconHeight;
295 if (mUnselectedIconWidth > mIconWidth)
296 mIconWidth = mUnselectedIconWidth;
297 }
298
299 if (mHeaderIcon && mHeaderIcon->GetResource())
300 {
301 mHeaderIconWidth = gr_get_width(mHeaderIcon->GetResource());
302 mHeaderIconHeight = gr_get_height(mHeaderIcon->GetResource());
303 if (mHeaderIconHeight > mHeaderH)
304 mHeaderH = mHeaderIconHeight;
305 if (mHeaderIconWidth > mIconWidth)
306 mIconWidth = mHeaderIconWidth;
307 }
308
309 mHeaderH += mLineSpacing + mHeaderSeparatorH;
310 actualLineHeight = mLineHeight + mLineSpacing + mSeparatorH;
311 if (mHeaderH < actualLineHeight)
312 mHeaderH = actualLineHeight;
313
314 if (actualLineHeight / 3 > 6)
315 touchDebounce = actualLineHeight / 3;
316
317 if (mBackground && mBackground->GetResource())
318 {
319 mBackgroundW = gr_get_width(mBackground->GetResource());
320 mBackgroundH = gr_get_height(mBackground->GetResource());
321 }
322
323 child = node->first_node("listtype");
324 if (child) {
325 attr = child->first_attribute("name");
326 if (attr) {
327 ListType = attr->value();
328 PartitionManager.Get_Partition_List(ListType, &mList);
329 } else {
330 mList.clear();
Dees_Troy2673cec2013-04-02 20:22:16 +0000331 LOGERR("No partition listtype name specified for partitionlist GUI element\n");
Dees_Troya13d74f2013-03-24 08:54:55 -0500332 return;
333 }
334 } else {
335 mList.clear();
Dees_Troy2673cec2013-04-02 20:22:16 +0000336 LOGERR("No partition listtype specified for partitionlist GUI element\n");
Dees_Troya13d74f2013-03-24 08:54:55 -0500337 return;
338 }
339}
340
341GUIPartitionList::~GUIPartitionList()
342{
343}
344
345int GUIPartitionList::Render(void)
346{
347 // First step, fill background
348 gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
349 gr_fill(mRenderX, mRenderY + mHeaderH, mRenderW, mRenderH - mHeaderH);
350
351 // Next, render the background resource (if it exists)
352 if (mBackground && mBackground->GetResource())
353 {
354 mBackgroundX = mRenderX + ((mRenderW - mBackgroundW) / 2);
355 mBackgroundY = mRenderY + ((mRenderH - mBackgroundH) / 2);
356 gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY);
357 }
358
359 // This tells us how many lines we can actually render
360 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
361 int line;
362
363 if (updateList) {
364 mList.clear();
365 PartitionManager.Get_Partition_List(ListType, &mList);
366 updateList = false;
367 if (ListType == "backup")
368 MatchList();
369 }
370
371 int listSize = mList.size();
372 int listW = mRenderW;
373
374 if (listSize < lines) {
375 lines = listSize;
376 scrollingY = 0;
377 mFastScrollRectX = mFastScrollRectY = -1;
378 } else {
379 lines++;
380 if (lines < listSize)
381 lines++;
382 if (listSize >= lines)
383 listW -= mFastScrollW; // space for fast scrollbar
384 else
385 mFastScrollRectX = mFastScrollRectY = -1; // no fast scrollbar
386 }
387
388 void* fontResource = NULL;
389 if (mFont) fontResource = mFont->GetResource();
390
391 int yPos = mRenderY + mHeaderH + scrollingY;
392 int fontOffsetY = (int)((actualLineHeight - mFontHeight) / 2);
393 int currentIconHeight = 0, currentIconWidth = 0;
394 int currentIconOffsetY = 0, currentIconOffsetX = 0;
395 int UnselectedIconOffsetY = (int)((actualLineHeight - mUnselectedIconHeight) / 2), SelectedIconOffsetY = (int)((actualLineHeight - mSelectedIconHeight) / 2);
396 int UnselectedIconOffsetX = (mIconWidth - mUnselectedIconWidth) / 2, SelectedIconOffsetX = (mIconWidth - mSelectedIconWidth) / 2;
397 int actualSelection = mStart;
398
399 if (isHighlighted) {
400 int selectY = scrollingY;
401
402 // Locate the correct line for highlighting
403 while (selectY + actualLineHeight < startSelection) {
404 selectY += actualLineHeight;
405 actualSelection++;
406 }
407 if (hasHighlightColor) {
408 // Highlight the area
409 gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, 255);
410 int HighlightHeight = actualLineHeight;
411 if (mRenderY + mHeaderH + selectY + actualLineHeight > mRenderH + mRenderY) {
412 HighlightHeight = actualLineHeight - (mRenderY + mHeaderH + selectY + actualLineHeight - mRenderH - mRenderY);
413 }
414 gr_fill(mRenderX, mRenderY + mHeaderH + selectY, mRenderW, HighlightHeight);
415 }
416 }
417
418 for (line = 0; line < lines; line++)
419 {
420 Resource* icon;
421 std::string label;
422
423 if (line + mStart >= listSize)
424 continue;
425
426 label = mList.at(line + mStart).Display_Name;
427 if (isHighlighted && hasFontHighlightColor && line + mStart == actualSelection) {
428 // Use the highlight color for the font
429 gr_color(mFontHighlightColor.red, mFontHighlightColor.green, mFontHighlightColor.blue, 255);
430 } else {
431 // Set the color for the font
432 gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, 255);
433 }
434
435 if (mList.at(line + mStart).selected != 0)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200436 {
437 icon = mIconSelected;
Dees_Troya13d74f2013-03-24 08:54:55 -0500438 currentIconHeight = mSelectedIconHeight;
439 currentIconWidth = mSelectedIconWidth;
440 currentIconOffsetY = SelectedIconOffsetY;
441 currentIconOffsetX = SelectedIconOffsetX;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200442 }
443 else
444 {
445 icon = mIconUnselected;
Dees_Troya13d74f2013-03-24 08:54:55 -0500446 currentIconHeight = mSelectedIconHeight;
447 currentIconWidth = mSelectedIconWidth;
448 currentIconOffsetY = SelectedIconOffsetY;
449 currentIconOffsetX = SelectedIconOffsetX;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200450 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500451
452 if (icon && icon->GetResource())
453 {
454 int rect_y = 0, image_y = (yPos + currentIconOffsetY);
455 if (image_y + currentIconHeight > mRenderY + mRenderH)
456 rect_y = mRenderY + mRenderH - image_y;
457 else
458 rect_y = currentIconHeight;
459 gr_blit(icon->GetResource(), 0, 0, currentIconWidth, rect_y, mRenderX + currentIconOffsetX, image_y);
460 }
461 gr_textExWH(mRenderX + mIconWidth + 5, yPos + fontOffsetY, label.c_str(), fontResource, mRenderX + listW, mRenderY + mRenderH);
462
463 // Add the separator
464 if (yPos + actualLineHeight < mRenderH + mRenderY) {
465 gr_color(mSeparatorColor.red, mSeparatorColor.green, mSeparatorColor.blue, 255);
466 gr_fill(mRenderX, yPos + actualLineHeight - mSeparatorH, listW, mSeparatorH);
467 }
468
469 // Move the yPos
470 yPos += actualLineHeight;
471 }
472
473 // Render the Header (last so that it overwrites the top most row for per pixel scrolling)
474 // First step, fill background
475 gr_color(mHeaderBackgroundColor.red, mHeaderBackgroundColor.green, mHeaderBackgroundColor.blue, 255);
476 gr_fill(mRenderX, mRenderY, mRenderW, mHeaderH);
477
478 // Now, we need the header (icon + text)
479 yPos = mRenderY;
480 {
481 Resource* headerIcon;
482 int mIconOffsetX = 0;
483
484 // render the icon if it exists
485 headerIcon = mHeaderIcon;
486 if (headerIcon && headerIcon->GetResource())
487 {
488 gr_blit(headerIcon->GetResource(), 0, 0, mHeaderIconWidth, mHeaderIconHeight, mRenderX + ((mHeaderIconWidth - mIconWidth) / 2), (yPos + (int)((mHeaderH - mHeaderIconHeight) / 2)));
489 mIconOffsetX = mIconWidth;
490 }
491
492 // render the text
493 gr_color(mHeaderFontColor.red, mHeaderFontColor.green, mHeaderFontColor.blue, 255);
494 gr_textExWH(mRenderX + mIconOffsetX + 5, yPos + (int)((mHeaderH - mFontHeight) / 2), mLastValue.c_str(), fontResource, mRenderX + mRenderW, mRenderY + mRenderH);
495
496 // Add the separator
497 gr_color(mHeaderSeparatorColor.red, mHeaderSeparatorColor.green, mHeaderSeparatorColor.blue, 255);
498 gr_fill(mRenderX, yPos + mHeaderH - mHeaderSeparatorH, mRenderW, mHeaderSeparatorH);
499 }
500
501 // render fast scroll
502 lines = (mRenderH - mHeaderH) / (actualLineHeight);
503 if(mFastScrollW > 0 && listSize > lines)
504 {
505 int startX = listW + mRenderX;
506 int fWidth = mRenderW - listW;
507 int fHeight = mRenderH - mHeaderH;
508
509 // line
510 gr_color(mFastScrollLineColor.red, mFastScrollLineColor.green, mFastScrollLineColor.blue, 255);
511 gr_fill(startX + fWidth/2, mRenderY + mHeaderH, mFastScrollLineW, mRenderH - mHeaderH);
512
513 // rect
514 int pct = ((mStart*actualLineHeight - scrollingY)*100)/((listSize)*actualLineHeight-lines*actualLineHeight);
515 mFastScrollRectX = startX + (fWidth - mFastScrollRectW)/2;
516 mFastScrollRectY = mRenderY+mHeaderH + ((fHeight - mFastScrollRectH)*pct)/100;
517
518 gr_color(mFastScrollRectColor.red, mFastScrollRectColor.green, mFastScrollRectColor.blue, 255);
519 gr_fill(mFastScrollRectX, mFastScrollRectY, mFastScrollRectW, mFastScrollRectH);
520 }
521
522 mUpdate = 0;
523 return 0;
524}
525
526int GUIPartitionList::Update(void)
527{
528 if (!mHeaderIsStatic) {
529 std::string newValue = gui_parse_text(mHeaderText);
530 if (mLastValue != newValue) {
531 mLastValue = newValue;
532 mUpdate = 1;
533 }
534 }
535
536 // Check for changes in mount points if the list type is mount and update the list and render if needed
537 if (ListType == "mount") {
538 int listSize = mList.size();
539 for (int i = 0; i < listSize; i++) {
540 if (PartitionManager.Is_Mounted_By_Path(mList.at(i).Mount_Point) && !mList.at(i).selected) {
541 mList.at(i).selected = 1;
542 mUpdate = 1;
543 } else if (!PartitionManager.Is_Mounted_By_Path(mList.at(i).Mount_Point) && mList.at(i).selected) {
544 mList.at(i).selected = 0;
545 mUpdate = 1;
546 }
547 }
548 }
549
550 if (mUpdate)
551 {
552 mUpdate = 0;
553 if (Render() == 0)
554 return 2;
555 }
556
557 // Handle kinetic scrolling
558 if (scrollingSpeed == 0) {
559 // Do nothing
560 } else if (scrollingSpeed > 0) {
561 if (scrollingSpeed < ((int) (actualLineHeight * 2.5))) {
562 scrollingY += scrollingSpeed;
563 scrollingSpeed -= SCROLLING_SPEED_DECREMENT;
564 } else {
565 scrollingY += ((int) (actualLineHeight * 2.5));
566 scrollingSpeed -= SCROLLING_SPEED_DECREMENT;
567 }
568 while (mStart && scrollingY > 0) {
569 mStart--;
570 scrollingY -= actualLineHeight;
571 }
572 if (mStart == 0 && scrollingY > 0) {
573 scrollingY = 0;
574 scrollingSpeed = 0;
575 } else if (scrollingSpeed < SCROLLING_FLOOR)
576 scrollingSpeed = 0;
577 mUpdate = 1;
578 } else if (scrollingSpeed < 0) {
579 int totalSize = mList.size();
580 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
581
582 if (totalSize > lines) {
583 int bottom_offset = ((int)(mRenderH) - mHeaderH) - (lines * actualLineHeight);
584
585 bottom_offset -= actualLineHeight;
586
587 if (abs(scrollingSpeed) < ((int) (actualLineHeight * 2.5))) {
588 scrollingY += scrollingSpeed;
589 scrollingSpeed += SCROLLING_SPEED_DECREMENT;
590 } else {
591 scrollingY -= ((int) (actualLineHeight * 2.5));
592 scrollingSpeed += SCROLLING_SPEED_DECREMENT;
593 }
594 while (mStart + lines + (bottom_offset ? 1 : 0) < totalSize && abs(scrollingY) > actualLineHeight) {
595 mStart++;
596 scrollingY += actualLineHeight;
597 }
598 if (bottom_offset != 0 && mStart + lines + 1 >= totalSize && scrollingY <= bottom_offset) {
599 mStart = totalSize - lines - 1;
600 scrollingY = bottom_offset;
601 } else if (mStart + lines >= totalSize && scrollingY < 0) {
602 mStart = totalSize - lines;
603 scrollingY = 0;
604 } else if (scrollingSpeed * -1 < SCROLLING_FLOOR)
605 scrollingSpeed = 0;
606 mUpdate = 1;
607 }
608 }
609
610 return 0;
611}
612
613int GUIPartitionList::GetSelection(int x, int y)
614{
615 // We only care about y position
616 if (y < mRenderY || y - mRenderY <= mHeaderH || y - mRenderY > mRenderH) return -1;
617 return (y - mRenderY - mHeaderH);
618}
619
620int GUIPartitionList::NotifyTouch(TOUCH_STATE state, int x, int y)
621{
622 static int lastY = 0, last2Y = 0;
623 int selection = 0;
624
625 switch (state)
626 {
627 case TOUCH_START:
628 if (scrollingSpeed != 0)
629 startSelection = -1;
630 else
631 startSelection = GetSelection(x,y);
632 isHighlighted = (startSelection > -1);
633 if (isHighlighted)
634 mUpdate = 1;
635 startY = lastY = last2Y = y;
636 scrollingSpeed = 0;
637 break;
638
639 case TOUCH_DRAG:
640 // Check if we dragged out of the selection window
641 if (GetSelection(x, y) == -1) {
642 last2Y = lastY = 0;
643 if (isHighlighted) {
644 isHighlighted = false;
645 mUpdate = 1;
646 }
647 break;
648 }
649
650 // Fast scroll
651 if(mFastScrollRectX != -1 && x >= mRenderX + mRenderW - mFastScrollW)
652 {
653 int pct = ((y-mRenderY-mHeaderH)*100)/(mRenderH-mHeaderH);
654 int totalSize = mList.size();
655 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
656
657 float l = float((totalSize-lines)*pct)/100;
658 if(l + lines >= totalSize)
659 {
660 mStart = totalSize - lines;
661 scrollingY = 0;
662 }
663 else
664 {
665 mStart = l;
666 scrollingY = -(l - int(l))*actualLineHeight;
667 }
668
669 startSelection = -1;
670 mUpdate = 1;
671 scrollingSpeed = 0;
672 isHighlighted = false;
673 break;
674 }
675
676 // Provide some debounce on initial touches
677 if (startSelection != -1 && abs(y - startY) < touchDebounce) {
678 isHighlighted = true;
679 mUpdate = 1;
680 break;
681 }
682
683 isHighlighted = false;
684 last2Y = lastY;
685 lastY = y;
686 startSelection = -1;
687
688 // Handle scrolling
689 scrollingY += y - startY;
690 startY = y;
691 while(mStart && scrollingY > 0) {
692 mStart--;
693 scrollingY -= actualLineHeight;
694 }
695 if (mStart == 0 && scrollingY > 0)
696 scrollingY = 0;
697 {
698 int totalSize = mList.size();
699 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
700
701 if (totalSize > lines) {
702 int bottom_offset = ((int)(mRenderH) - mHeaderH) - (lines * actualLineHeight);
703
704 bottom_offset -= actualLineHeight;
705
706 while (mStart + lines + (bottom_offset ? 1 : 0) < totalSize && abs(scrollingY) > actualLineHeight) {
707 mStart++;
708 scrollingY += actualLineHeight;
709 }
710 if (bottom_offset != 0 && mStart + lines + 1 >= totalSize && scrollingY <= bottom_offset) {
711 mStart = totalSize - lines - 1;
712 scrollingY = bottom_offset;
713 } else if (mStart + lines >= totalSize && scrollingY < 0) {
714 mStart = totalSize - lines;
715 scrollingY = 0;
716 }
717 } else
718 scrollingY = 0;
719 }
720 mUpdate = 1;
721 break;
722
723 case TOUCH_RELEASE:
724 isHighlighted = false;
725 if (startSelection >= 0)
726 {
727 // We've selected an item!
728 int listSize = mList.size();
729 int selectY = scrollingY, actualSelection = mStart;
730
731 // Move the selection to the proper place in the array
732 while (selectY + actualLineHeight < startSelection) {
733 selectY += actualLineHeight;
734 actualSelection++;
735 }
736
737 if (actualSelection < listSize && ListType == "mount") {
Vojtech Bocek5af8f3f2014-02-08 02:21:23 +0100738 DataManager::Vibrate("tw_button_vibrate");
739
Dees_Troya13d74f2013-03-24 08:54:55 -0500740 if (!mList.at(actualSelection).selected) {
741 if (PartitionManager.Mount_By_Path(mList.at(actualSelection).Mount_Point, true)) {
742 mList.at(actualSelection).selected = 1;
743 mUpdate = 1;
744 }
745 } else {
746 if (PartitionManager.UnMount_By_Path(mList.at(actualSelection).Mount_Point, true)) {
747 mList.at(actualSelection).selected = 0;
748 mUpdate = 1;
749 }
750 }
751 } else if (actualSelection < listSize && !mVariable.empty()) {
Vojtech Bocek5af8f3f2014-02-08 02:21:23 +0100752 DataManager::Vibrate("tw_button_vibrate");
753
Dees_Troya13d74f2013-03-24 08:54:55 -0500754 if (ListType == "storage") {
755 int i;
756 std::string str = mList.at(actualSelection).Mount_Point;
757 bool update_size = false;
758 TWPartition* Part = PartitionManager.Find_Partition_By_Path(str);
759 if (Part == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000760 LOGERR("Unable to locate partition for '%s'\n", str.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500761 return 0;
762 }
763 if (!Part->Is_Mounted() && Part->Removable)
764 update_size = true;
765 if (!Part->Mount(true)) {
766 // Do Nothing
767 } else if (update_size && !Part->Update_Size(true)) {
768 // Do Nothing
769 } else {
770 for (i=0; i<listSize; i++)
771 mList.at(i).selected = 0;
772
773 if (update_size) {
774 char free_space[255];
775 sprintf(free_space, "%llu", Part->Free / 1024 / 1024);
776 mList.at(actualSelection).Display_Name = Part->Storage_Name + " (";
777 mList.at(actualSelection).Display_Name += free_space;
778 mList.at(actualSelection).Display_Name += "MB)";
779 }
780 mList.at(actualSelection).selected = 1;
781 mUpdate = 1;
782
783 DataManager::SetValue(mVariable, str);
784 }
785 } else {
786 if (mList.at(actualSelection).selected)
787 mList.at(actualSelection).selected = 0;
788 else
789 mList.at(actualSelection).selected = 1;
790
791 int i;
792 string variablelist;
793 for (i=0; i<listSize; i++) {
794 if (mList.at(i).selected) {
795 variablelist += mList.at(i).Mount_Point + ";";
796 }
797 }
798
799 mUpdate = 1;
800 if (selectedList.empty())
801 DataManager::SetValue(mVariable, variablelist);
802 else
803 DataManager::SetValue(selectedList, variablelist);
804 }
805 }
806 } else {
807 // This is for kinetic scrolling
808 scrollingSpeed = lastY - last2Y;
809 if (abs(scrollingSpeed) > SCROLLING_FLOOR)
810 scrollingSpeed *= SCROLLING_MULTIPLIER;
811 else
812 scrollingSpeed = 0;
813 }
814 case TOUCH_REPEAT:
815 case TOUCH_HOLD:
816 break;
817 }
818 return 0;
819}
820
821int GUIPartitionList::NotifyVarChange(std::string varName, std::string value)
822{
823 if (!mHeaderIsStatic) {
824 std::string newValue = gui_parse_text(mHeaderText);
825 if (mLastValue != newValue) {
826 mLastValue = newValue;
827 mStart = 0;
828 scrollingY = 0;
829 scrollingSpeed = 0;
830 mUpdate = 1;
831 }
832 }
833 if (varName == mVariable && !mUpdate)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200834 {
835 if (ListType == "storage") {
Dees_Troya13d74f2013-03-24 08:54:55 -0500836 int i, listSize = mList.size(), selected_index = 0;
837
838 currentValue = value;
839
840 for (i=0; i<listSize; i++) {
841 if (mList.at(i).Mount_Point == currentValue) {
842 mList.at(i).selected = 1;
843 selected_index = i;
844 } else
845 mList.at(i).selected = 0;
846 }
847
848 int lines = mRenderH / (mLineHeight + mLineSpacing);
849 int line;
850
851 if (selected_index > mStart + lines - 1) {
852 mStart = selected_index;
853 } else if (selected_index < mStart) {
854 mStart = selected_index;
855 }
856 } else if (ListType == "backup") {
857 MatchList();
858 } else if (ListType == "restore") {
859 updateList = true;
860 }
861
862 mUpdate = 1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200863 return 0;
864 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500865 return 0;
866}
867
868int GUIPartitionList::SetRenderPos(int x, int y, int w /* = 0 */, int h /* = 0 */)
869{
870 mRenderX = x;
871 mRenderY = y;
872 if (w || h)
873 {
874 mRenderW = w;
875 mRenderH = h;
876 }
877 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
878 mUpdate = 1;
879 return 0;
880}
881
882void GUIPartitionList::SetPageFocus(int inFocus)
883{
884 if (inFocus) {
885 if (ListType == "storage") {
886 int i, listSize = mList.size(), selected_index = 0;
887
888 DataManager::GetValue(mVariable, currentValue);
889
890 for (i=0; i<listSize; i++) {
891 if (mList.at(i).Mount_Point == currentValue) {
892 mList.at(i).selected = 1;
893 selected_index = i;
894 } else
895 mList.at(i).selected = 0;
896 }
897
898 int lines = mRenderH / (mLineHeight + mLineSpacing);
899 int line;
900
901 if (selected_index > mStart + lines - 1) {
902 mStart = selected_index;
903 } else if (selected_index < mStart) {
904 mStart = selected_index;
905 }
906 }
907 updateList = true;
908 mUpdate = 1;
909 }
910}
911
912void GUIPartitionList::MatchList(void) {
913 int i, listSize = mList.size();
914 string variablelist, searchvalue;
915 size_t pos;
916
917 DataManager::GetValue(mVariable, variablelist);
918
919 for (i=0; i<listSize; i++) {
920 searchvalue = mList.at(i).Mount_Point + ";";
921 pos = variablelist.find(searchvalue);
922 if (pos != string::npos) {
923 mList.at(i).selected = 1;
924 } else {
925 mList.at(i).selected = 0;
926 }
927 }
928}