blob: 3ec15488a406c9179b93c672cc613e18c29bd367 [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
Vojtech Bocekede51c52014-02-07 23:58:09 +010055GUIPartitionList::GUIPartitionList(xml_node<>* node) : GUIObject(node)
Dees_Troya13d74f2013-03-24 08:54:55 -050056{
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
Vojtech Bocek76ee9032014-09-07 15:01:56 +0200276 mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL);
Dees_Troya13d74f2013-03-24 08:54:55 -0500277 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{
Vojtech Bocekede51c52014-02-07 23:58:09 +0100347 if(!isConditionTrue())
348 return 0;
349
Dees_Troya13d74f2013-03-24 08:54:55 -0500350 // First step, fill background
351 gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
352 gr_fill(mRenderX, mRenderY + mHeaderH, mRenderW, mRenderH - mHeaderH);
353
354 // Next, render the background resource (if it exists)
355 if (mBackground && mBackground->GetResource())
356 {
357 mBackgroundX = mRenderX + ((mRenderW - mBackgroundW) / 2);
358 mBackgroundY = mRenderY + ((mRenderH - mBackgroundH) / 2);
359 gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY);
360 }
361
362 // This tells us how many lines we can actually render
363 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
364 int line;
365
366 if (updateList) {
367 mList.clear();
368 PartitionManager.Get_Partition_List(ListType, &mList);
369 updateList = false;
370 if (ListType == "backup")
371 MatchList();
372 }
373
374 int listSize = mList.size();
375 int listW = mRenderW;
376
377 if (listSize < lines) {
378 lines = listSize;
379 scrollingY = 0;
380 mFastScrollRectX = mFastScrollRectY = -1;
381 } else {
382 lines++;
383 if (lines < listSize)
384 lines++;
385 if (listSize >= lines)
386 listW -= mFastScrollW; // space for fast scrollbar
387 else
388 mFastScrollRectX = mFastScrollRectY = -1; // no fast scrollbar
389 }
390
391 void* fontResource = NULL;
392 if (mFont) fontResource = mFont->GetResource();
393
394 int yPos = mRenderY + mHeaderH + scrollingY;
395 int fontOffsetY = (int)((actualLineHeight - mFontHeight) / 2);
396 int currentIconHeight = 0, currentIconWidth = 0;
397 int currentIconOffsetY = 0, currentIconOffsetX = 0;
398 int UnselectedIconOffsetY = (int)((actualLineHeight - mUnselectedIconHeight) / 2), SelectedIconOffsetY = (int)((actualLineHeight - mSelectedIconHeight) / 2);
399 int UnselectedIconOffsetX = (mIconWidth - mUnselectedIconWidth) / 2, SelectedIconOffsetX = (mIconWidth - mSelectedIconWidth) / 2;
400 int actualSelection = mStart;
401
402 if (isHighlighted) {
403 int selectY = scrollingY;
404
405 // Locate the correct line for highlighting
406 while (selectY + actualLineHeight < startSelection) {
407 selectY += actualLineHeight;
408 actualSelection++;
409 }
410 if (hasHighlightColor) {
411 // Highlight the area
412 gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, 255);
413 int HighlightHeight = actualLineHeight;
414 if (mRenderY + mHeaderH + selectY + actualLineHeight > mRenderH + mRenderY) {
415 HighlightHeight = actualLineHeight - (mRenderY + mHeaderH + selectY + actualLineHeight - mRenderH - mRenderY);
416 }
417 gr_fill(mRenderX, mRenderY + mHeaderH + selectY, mRenderW, HighlightHeight);
418 }
419 }
420
421 for (line = 0; line < lines; line++)
422 {
423 Resource* icon;
424 std::string label;
425
426 if (line + mStart >= listSize)
427 continue;
428
429 label = mList.at(line + mStart).Display_Name;
430 if (isHighlighted && hasFontHighlightColor && line + mStart == actualSelection) {
431 // Use the highlight color for the font
432 gr_color(mFontHighlightColor.red, mFontHighlightColor.green, mFontHighlightColor.blue, 255);
433 } else {
434 // Set the color for the font
435 gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, 255);
436 }
437
438 if (mList.at(line + mStart).selected != 0)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200439 {
440 icon = mIconSelected;
Dees_Troya13d74f2013-03-24 08:54:55 -0500441 currentIconHeight = mSelectedIconHeight;
442 currentIconWidth = mSelectedIconWidth;
443 currentIconOffsetY = SelectedIconOffsetY;
444 currentIconOffsetX = SelectedIconOffsetX;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200445 }
446 else
447 {
448 icon = mIconUnselected;
Dees_Troya13d74f2013-03-24 08:54:55 -0500449 currentIconHeight = mSelectedIconHeight;
450 currentIconWidth = mSelectedIconWidth;
451 currentIconOffsetY = SelectedIconOffsetY;
452 currentIconOffsetX = SelectedIconOffsetX;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200453 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500454
455 if (icon && icon->GetResource())
456 {
457 int rect_y = 0, image_y = (yPos + currentIconOffsetY);
458 if (image_y + currentIconHeight > mRenderY + mRenderH)
459 rect_y = mRenderY + mRenderH - image_y;
460 else
461 rect_y = currentIconHeight;
462 gr_blit(icon->GetResource(), 0, 0, currentIconWidth, rect_y, mRenderX + currentIconOffsetX, image_y);
463 }
464 gr_textExWH(mRenderX + mIconWidth + 5, yPos + fontOffsetY, label.c_str(), fontResource, mRenderX + listW, mRenderY + mRenderH);
465
466 // Add the separator
467 if (yPos + actualLineHeight < mRenderH + mRenderY) {
468 gr_color(mSeparatorColor.red, mSeparatorColor.green, mSeparatorColor.blue, 255);
469 gr_fill(mRenderX, yPos + actualLineHeight - mSeparatorH, listW, mSeparatorH);
470 }
471
472 // Move the yPos
473 yPos += actualLineHeight;
474 }
475
476 // Render the Header (last so that it overwrites the top most row for per pixel scrolling)
477 // First step, fill background
478 gr_color(mHeaderBackgroundColor.red, mHeaderBackgroundColor.green, mHeaderBackgroundColor.blue, 255);
479 gr_fill(mRenderX, mRenderY, mRenderW, mHeaderH);
480
481 // Now, we need the header (icon + text)
482 yPos = mRenderY;
483 {
484 Resource* headerIcon;
485 int mIconOffsetX = 0;
486
487 // render the icon if it exists
488 headerIcon = mHeaderIcon;
489 if (headerIcon && headerIcon->GetResource())
490 {
491 gr_blit(headerIcon->GetResource(), 0, 0, mHeaderIconWidth, mHeaderIconHeight, mRenderX + ((mHeaderIconWidth - mIconWidth) / 2), (yPos + (int)((mHeaderH - mHeaderIconHeight) / 2)));
492 mIconOffsetX = mIconWidth;
493 }
494
495 // render the text
496 gr_color(mHeaderFontColor.red, mHeaderFontColor.green, mHeaderFontColor.blue, 255);
497 gr_textExWH(mRenderX + mIconOffsetX + 5, yPos + (int)((mHeaderH - mFontHeight) / 2), mLastValue.c_str(), fontResource, mRenderX + mRenderW, mRenderY + mRenderH);
498
499 // Add the separator
500 gr_color(mHeaderSeparatorColor.red, mHeaderSeparatorColor.green, mHeaderSeparatorColor.blue, 255);
501 gr_fill(mRenderX, yPos + mHeaderH - mHeaderSeparatorH, mRenderW, mHeaderSeparatorH);
502 }
503
504 // render fast scroll
505 lines = (mRenderH - mHeaderH) / (actualLineHeight);
506 if(mFastScrollW > 0 && listSize > lines)
507 {
508 int startX = listW + mRenderX;
509 int fWidth = mRenderW - listW;
510 int fHeight = mRenderH - mHeaderH;
511
512 // line
513 gr_color(mFastScrollLineColor.red, mFastScrollLineColor.green, mFastScrollLineColor.blue, 255);
514 gr_fill(startX + fWidth/2, mRenderY + mHeaderH, mFastScrollLineW, mRenderH - mHeaderH);
515
516 // rect
517 int pct = ((mStart*actualLineHeight - scrollingY)*100)/((listSize)*actualLineHeight-lines*actualLineHeight);
518 mFastScrollRectX = startX + (fWidth - mFastScrollRectW)/2;
519 mFastScrollRectY = mRenderY+mHeaderH + ((fHeight - mFastScrollRectH)*pct)/100;
520
521 gr_color(mFastScrollRectColor.red, mFastScrollRectColor.green, mFastScrollRectColor.blue, 255);
522 gr_fill(mFastScrollRectX, mFastScrollRectY, mFastScrollRectW, mFastScrollRectH);
523 }
524
525 mUpdate = 0;
526 return 0;
527}
528
529int GUIPartitionList::Update(void)
530{
Vojtech Bocekede51c52014-02-07 23:58:09 +0100531 if(!isConditionTrue())
532 return 0;
533
Dees_Troya13d74f2013-03-24 08:54:55 -0500534 if (!mHeaderIsStatic) {
535 std::string newValue = gui_parse_text(mHeaderText);
536 if (mLastValue != newValue) {
537 mLastValue = newValue;
538 mUpdate = 1;
539 }
540 }
541
542 // Check for changes in mount points if the list type is mount and update the list and render if needed
543 if (ListType == "mount") {
544 int listSize = mList.size();
545 for (int i = 0; i < listSize; i++) {
546 if (PartitionManager.Is_Mounted_By_Path(mList.at(i).Mount_Point) && !mList.at(i).selected) {
547 mList.at(i).selected = 1;
548 mUpdate = 1;
549 } else if (!PartitionManager.Is_Mounted_By_Path(mList.at(i).Mount_Point) && mList.at(i).selected) {
550 mList.at(i).selected = 0;
551 mUpdate = 1;
552 }
553 }
554 }
555
556 if (mUpdate)
557 {
558 mUpdate = 0;
559 if (Render() == 0)
560 return 2;
561 }
562
563 // Handle kinetic scrolling
564 if (scrollingSpeed == 0) {
565 // Do nothing
566 } else if (scrollingSpeed > 0) {
567 if (scrollingSpeed < ((int) (actualLineHeight * 2.5))) {
568 scrollingY += scrollingSpeed;
569 scrollingSpeed -= SCROLLING_SPEED_DECREMENT;
570 } else {
571 scrollingY += ((int) (actualLineHeight * 2.5));
572 scrollingSpeed -= SCROLLING_SPEED_DECREMENT;
573 }
574 while (mStart && scrollingY > 0) {
575 mStart--;
576 scrollingY -= actualLineHeight;
577 }
578 if (mStart == 0 && scrollingY > 0) {
579 scrollingY = 0;
580 scrollingSpeed = 0;
581 } else if (scrollingSpeed < SCROLLING_FLOOR)
582 scrollingSpeed = 0;
583 mUpdate = 1;
584 } else if (scrollingSpeed < 0) {
585 int totalSize = mList.size();
586 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
587
588 if (totalSize > lines) {
589 int bottom_offset = ((int)(mRenderH) - mHeaderH) - (lines * actualLineHeight);
590
591 bottom_offset -= actualLineHeight;
592
593 if (abs(scrollingSpeed) < ((int) (actualLineHeight * 2.5))) {
594 scrollingY += scrollingSpeed;
595 scrollingSpeed += SCROLLING_SPEED_DECREMENT;
596 } else {
597 scrollingY -= ((int) (actualLineHeight * 2.5));
598 scrollingSpeed += SCROLLING_SPEED_DECREMENT;
599 }
600 while (mStart + lines + (bottom_offset ? 1 : 0) < totalSize && abs(scrollingY) > actualLineHeight) {
601 mStart++;
602 scrollingY += actualLineHeight;
603 }
604 if (bottom_offset != 0 && mStart + lines + 1 >= totalSize && scrollingY <= bottom_offset) {
605 mStart = totalSize - lines - 1;
606 scrollingY = bottom_offset;
607 } else if (mStart + lines >= totalSize && scrollingY < 0) {
608 mStart = totalSize - lines;
609 scrollingY = 0;
610 } else if (scrollingSpeed * -1 < SCROLLING_FLOOR)
611 scrollingSpeed = 0;
612 mUpdate = 1;
613 }
614 }
615
616 return 0;
617}
618
619int GUIPartitionList::GetSelection(int x, int y)
620{
621 // We only care about y position
622 if (y < mRenderY || y - mRenderY <= mHeaderH || y - mRenderY > mRenderH) return -1;
623 return (y - mRenderY - mHeaderH);
624}
625
626int GUIPartitionList::NotifyTouch(TOUCH_STATE state, int x, int y)
627{
Vojtech Bocekede51c52014-02-07 23:58:09 +0100628 if(!isConditionTrue())
629 return -1;
630
Dees_Troya13d74f2013-03-24 08:54:55 -0500631 static int lastY = 0, last2Y = 0;
632 int selection = 0;
633
634 switch (state)
635 {
636 case TOUCH_START:
637 if (scrollingSpeed != 0)
638 startSelection = -1;
639 else
640 startSelection = GetSelection(x,y);
641 isHighlighted = (startSelection > -1);
642 if (isHighlighted)
643 mUpdate = 1;
644 startY = lastY = last2Y = y;
645 scrollingSpeed = 0;
646 break;
647
648 case TOUCH_DRAG:
649 // Check if we dragged out of the selection window
650 if (GetSelection(x, y) == -1) {
651 last2Y = lastY = 0;
652 if (isHighlighted) {
653 isHighlighted = false;
654 mUpdate = 1;
655 }
656 break;
657 }
658
659 // Fast scroll
660 if(mFastScrollRectX != -1 && x >= mRenderX + mRenderW - mFastScrollW)
661 {
662 int pct = ((y-mRenderY-mHeaderH)*100)/(mRenderH-mHeaderH);
663 int totalSize = mList.size();
664 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
665
666 float l = float((totalSize-lines)*pct)/100;
667 if(l + lines >= totalSize)
668 {
669 mStart = totalSize - lines;
670 scrollingY = 0;
671 }
672 else
673 {
674 mStart = l;
675 scrollingY = -(l - int(l))*actualLineHeight;
676 }
677
678 startSelection = -1;
679 mUpdate = 1;
680 scrollingSpeed = 0;
681 isHighlighted = false;
682 break;
683 }
684
685 // Provide some debounce on initial touches
686 if (startSelection != -1 && abs(y - startY) < touchDebounce) {
687 isHighlighted = true;
688 mUpdate = 1;
689 break;
690 }
691
692 isHighlighted = false;
693 last2Y = lastY;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500694 lastY = y;
Dees_Troya13d74f2013-03-24 08:54:55 -0500695 startSelection = -1;
696
697 // Handle scrolling
698 scrollingY += y - startY;
699 startY = y;
700 while(mStart && scrollingY > 0) {
701 mStart--;
702 scrollingY -= actualLineHeight;
703 }
704 if (mStart == 0 && scrollingY > 0)
705 scrollingY = 0;
706 {
707 int totalSize = mList.size();
708 int lines = (mRenderH - mHeaderH) / (actualLineHeight);
709
710 if (totalSize > lines) {
711 int bottom_offset = ((int)(mRenderH) - mHeaderH) - (lines * actualLineHeight);
712
713 bottom_offset -= actualLineHeight;
714
715 while (mStart + lines + (bottom_offset ? 1 : 0) < totalSize && abs(scrollingY) > actualLineHeight) {
716 mStart++;
717 scrollingY += actualLineHeight;
718 }
719 if (bottom_offset != 0 && mStart + lines + 1 >= totalSize && scrollingY <= bottom_offset) {
720 mStart = totalSize - lines - 1;
721 scrollingY = bottom_offset;
722 } else if (mStart + lines >= totalSize && scrollingY < 0) {
723 mStart = totalSize - lines;
724 scrollingY = 0;
725 }
726 } else
727 scrollingY = 0;
728 }
729 mUpdate = 1;
730 break;
731
732 case TOUCH_RELEASE:
733 isHighlighted = false;
734 if (startSelection >= 0)
735 {
736 // We've selected an item!
737 int listSize = mList.size();
738 int selectY = scrollingY, actualSelection = mStart;
739
740 // Move the selection to the proper place in the array
741 while (selectY + actualLineHeight < startSelection) {
742 selectY += actualLineHeight;
743 actualSelection++;
744 }
745
746 if (actualSelection < listSize && ListType == "mount") {
Vojtech Bocek5af8f3f2014-02-08 02:21:23 +0100747 DataManager::Vibrate("tw_button_vibrate");
748
Dees_Troya13d74f2013-03-24 08:54:55 -0500749 if (!mList.at(actualSelection).selected) {
750 if (PartitionManager.Mount_By_Path(mList.at(actualSelection).Mount_Point, true)) {
751 mList.at(actualSelection).selected = 1;
Ethan Yonker726a0202014-12-16 20:01:38 -0600752 PartitionManager.Add_MTP_Storage(mList.at(actualSelection).Mount_Point);
Dees_Troya13d74f2013-03-24 08:54:55 -0500753 mUpdate = 1;
754 }
755 } else {
756 if (PartitionManager.UnMount_By_Path(mList.at(actualSelection).Mount_Point, true)) {
757 mList.at(actualSelection).selected = 0;
758 mUpdate = 1;
759 }
760 }
761 } else if (actualSelection < listSize && !mVariable.empty()) {
Vojtech Bocek5af8f3f2014-02-08 02:21:23 +0100762 DataManager::Vibrate("tw_button_vibrate");
763
Dees_Troya13d74f2013-03-24 08:54:55 -0500764 if (ListType == "storage") {
765 int i;
766 std::string str = mList.at(actualSelection).Mount_Point;
767 bool update_size = false;
768 TWPartition* Part = PartitionManager.Find_Partition_By_Path(str);
769 if (Part == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000770 LOGERR("Unable to locate partition for '%s'\n", str.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500771 return 0;
772 }
773 if (!Part->Is_Mounted() && Part->Removable)
774 update_size = true;
775 if (!Part->Mount(true)) {
776 // Do Nothing
777 } else if (update_size && !Part->Update_Size(true)) {
778 // Do Nothing
779 } else {
780 for (i=0; i<listSize; i++)
781 mList.at(i).selected = 0;
782
783 if (update_size) {
784 char free_space[255];
785 sprintf(free_space, "%llu", Part->Free / 1024 / 1024);
786 mList.at(actualSelection).Display_Name = Part->Storage_Name + " (";
787 mList.at(actualSelection).Display_Name += free_space;
788 mList.at(actualSelection).Display_Name += "MB)";
789 }
790 mList.at(actualSelection).selected = 1;
791 mUpdate = 1;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500792
Dees_Troya13d74f2013-03-24 08:54:55 -0500793 DataManager::SetValue(mVariable, str);
794 }
795 } else {
Ethan Yonker96af84a2015-01-05 14:58:36 -0600796 if (ListType == "flashimg") { // only one item can be selected for flashing images
797 for (int i=0; i<listSize; i++)
798 mList.at(i).selected = 0;
799 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500800 if (mList.at(actualSelection).selected)
801 mList.at(actualSelection).selected = 0;
802 else
803 mList.at(actualSelection).selected = 1;
804
805 int i;
806 string variablelist;
807 for (i=0; i<listSize; i++) {
808 if (mList.at(i).selected) {
809 variablelist += mList.at(i).Mount_Point + ";";
810 }
811 }
812
813 mUpdate = 1;
814 if (selectedList.empty())
815 DataManager::SetValue(mVariable, variablelist);
816 else
817 DataManager::SetValue(selectedList, variablelist);
818 }
819 }
820 } else {
821 // This is for kinetic scrolling
822 scrollingSpeed = lastY - last2Y;
823 if (abs(scrollingSpeed) > SCROLLING_FLOOR)
824 scrollingSpeed *= SCROLLING_MULTIPLIER;
825 else
826 scrollingSpeed = 0;
827 }
828 case TOUCH_REPEAT:
829 case TOUCH_HOLD:
830 break;
831 }
832 return 0;
833}
834
Vojtech Bocek07220562014-02-08 02:05:33 +0100835int GUIPartitionList::NotifyVarChange(const std::string& varName, const std::string& value)
Dees_Troya13d74f2013-03-24 08:54:55 -0500836{
Vojtech Bocek07220562014-02-08 02:05:33 +0100837 GUIObject::NotifyVarChange(varName, value);
838
Vojtech Bocekede51c52014-02-07 23:58:09 +0100839 if(!isConditionTrue())
840 return 0;
841
Dees_Troya13d74f2013-03-24 08:54:55 -0500842 if (!mHeaderIsStatic) {
843 std::string newValue = gui_parse_text(mHeaderText);
844 if (mLastValue != newValue) {
845 mLastValue = newValue;
846 mStart = 0;
847 scrollingY = 0;
848 scrollingSpeed = 0;
849 mUpdate = 1;
850 }
851 }
852 if (varName == mVariable && !mUpdate)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200853 {
854 if (ListType == "storage") {
Dees_Troya13d74f2013-03-24 08:54:55 -0500855 int i, listSize = mList.size(), selected_index = 0;
856
857 currentValue = value;
858
859 for (i=0; i<listSize; i++) {
860 if (mList.at(i).Mount_Point == currentValue) {
861 mList.at(i).selected = 1;
862 selected_index = i;
863 } else
864 mList.at(i).selected = 0;
865 }
866
867 int lines = mRenderH / (mLineHeight + mLineSpacing);
868 int line;
869
870 if (selected_index > mStart + lines - 1) {
871 mStart = selected_index;
872 } else if (selected_index < mStart) {
873 mStart = selected_index;
874 }
875 } else if (ListType == "backup") {
876 MatchList();
877 } else if (ListType == "restore") {
878 updateList = true;
879 }
880
881 mUpdate = 1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200882 return 0;
883 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500884 return 0;
885}
886
887int GUIPartitionList::SetRenderPos(int x, int y, int w /* = 0 */, int h /* = 0 */)
888{
889 mRenderX = x;
890 mRenderY = y;
891 if (w || h)
892 {
893 mRenderW = w;
894 mRenderH = h;
895 }
896 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
897 mUpdate = 1;
898 return 0;
899}
900
901void GUIPartitionList::SetPageFocus(int inFocus)
902{
903 if (inFocus) {
904 if (ListType == "storage") {
905 int i, listSize = mList.size(), selected_index = 0;
906
907 DataManager::GetValue(mVariable, currentValue);
908
909 for (i=0; i<listSize; i++) {
910 if (mList.at(i).Mount_Point == currentValue) {
911 mList.at(i).selected = 1;
912 selected_index = i;
913 } else
914 mList.at(i).selected = 0;
915 }
916
917 int lines = mRenderH / (mLineHeight + mLineSpacing);
918 int line;
919
920 if (selected_index > mStart + lines - 1) {
921 mStart = selected_index;
922 } else if (selected_index < mStart) {
923 mStart = selected_index;
924 }
925 }
926 updateList = true;
927 mUpdate = 1;
928 }
929}
930
931void GUIPartitionList::MatchList(void) {
932 int i, listSize = mList.size();
933 string variablelist, searchvalue;
934 size_t pos;
935
936 DataManager::GetValue(mVariable, variablelist);
937
938 for (i=0; i<listSize; i++) {
939 searchvalue = mList.at(i).Mount_Point + ";";
940 pos = variablelist.find(searchvalue);
941 if (pos != string::npos) {
942 mList.at(i).selected = 1;
943 } else {
944 mList.at(i).selected = 0;
945 }
946 }
947}