blob: abe0a38ade43aca1b31ce702ad556502542dc705 [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") {
738 if (!mList.at(actualSelection).selected) {
739 if (PartitionManager.Mount_By_Path(mList.at(actualSelection).Mount_Point, true)) {
740 mList.at(actualSelection).selected = 1;
741 mUpdate = 1;
742 }
743 } else {
744 if (PartitionManager.UnMount_By_Path(mList.at(actualSelection).Mount_Point, true)) {
745 mList.at(actualSelection).selected = 0;
746 mUpdate = 1;
747 }
748 }
749 } else if (actualSelection < listSize && !mVariable.empty()) {
750 if (ListType == "storage") {
751 int i;
752 std::string str = mList.at(actualSelection).Mount_Point;
753 bool update_size = false;
754 TWPartition* Part = PartitionManager.Find_Partition_By_Path(str);
755 if (Part == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000756 LOGERR("Unable to locate partition for '%s'\n", str.c_str());
Dees_Troya13d74f2013-03-24 08:54:55 -0500757 return 0;
758 }
759 if (!Part->Is_Mounted() && Part->Removable)
760 update_size = true;
761 if (!Part->Mount(true)) {
762 // Do Nothing
763 } else if (update_size && !Part->Update_Size(true)) {
764 // Do Nothing
765 } else {
766 for (i=0; i<listSize; i++)
767 mList.at(i).selected = 0;
768
769 if (update_size) {
770 char free_space[255];
771 sprintf(free_space, "%llu", Part->Free / 1024 / 1024);
772 mList.at(actualSelection).Display_Name = Part->Storage_Name + " (";
773 mList.at(actualSelection).Display_Name += free_space;
774 mList.at(actualSelection).Display_Name += "MB)";
775 }
776 mList.at(actualSelection).selected = 1;
777 mUpdate = 1;
778
779 DataManager::SetValue(mVariable, str);
780 }
781 } else {
782 if (mList.at(actualSelection).selected)
783 mList.at(actualSelection).selected = 0;
784 else
785 mList.at(actualSelection).selected = 1;
786
787 int i;
788 string variablelist;
789 for (i=0; i<listSize; i++) {
790 if (mList.at(i).selected) {
791 variablelist += mList.at(i).Mount_Point + ";";
792 }
793 }
794
795 mUpdate = 1;
796 if (selectedList.empty())
797 DataManager::SetValue(mVariable, variablelist);
798 else
799 DataManager::SetValue(selectedList, variablelist);
800 }
801 }
802 } else {
803 // This is for kinetic scrolling
804 scrollingSpeed = lastY - last2Y;
805 if (abs(scrollingSpeed) > SCROLLING_FLOOR)
806 scrollingSpeed *= SCROLLING_MULTIPLIER;
807 else
808 scrollingSpeed = 0;
809 }
810 case TOUCH_REPEAT:
811 case TOUCH_HOLD:
812 break;
813 }
814 return 0;
815}
816
817int GUIPartitionList::NotifyVarChange(std::string varName, std::string value)
818{
819 if (!mHeaderIsStatic) {
820 std::string newValue = gui_parse_text(mHeaderText);
821 if (mLastValue != newValue) {
822 mLastValue = newValue;
823 mStart = 0;
824 scrollingY = 0;
825 scrollingSpeed = 0;
826 mUpdate = 1;
827 }
828 }
829 if (varName == mVariable && !mUpdate)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200830 {
831 if (ListType == "storage") {
Dees_Troya13d74f2013-03-24 08:54:55 -0500832 int i, listSize = mList.size(), selected_index = 0;
833
834 currentValue = value;
835
836 for (i=0; i<listSize; i++) {
837 if (mList.at(i).Mount_Point == currentValue) {
838 mList.at(i).selected = 1;
839 selected_index = i;
840 } else
841 mList.at(i).selected = 0;
842 }
843
844 int lines = mRenderH / (mLineHeight + mLineSpacing);
845 int line;
846
847 if (selected_index > mStart + lines - 1) {
848 mStart = selected_index;
849 } else if (selected_index < mStart) {
850 mStart = selected_index;
851 }
852 } else if (ListType == "backup") {
853 MatchList();
854 } else if (ListType == "restore") {
855 updateList = true;
856 }
857
858 mUpdate = 1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200859 return 0;
860 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500861 return 0;
862}
863
864int GUIPartitionList::SetRenderPos(int x, int y, int w /* = 0 */, int h /* = 0 */)
865{
866 mRenderX = x;
867 mRenderY = y;
868 if (w || h)
869 {
870 mRenderW = w;
871 mRenderH = h;
872 }
873 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
874 mUpdate = 1;
875 return 0;
876}
877
878void GUIPartitionList::SetPageFocus(int inFocus)
879{
880 if (inFocus) {
881 if (ListType == "storage") {
882 int i, listSize = mList.size(), selected_index = 0;
883
884 DataManager::GetValue(mVariable, currentValue);
885
886 for (i=0; i<listSize; i++) {
887 if (mList.at(i).Mount_Point == currentValue) {
888 mList.at(i).selected = 1;
889 selected_index = i;
890 } else
891 mList.at(i).selected = 0;
892 }
893
894 int lines = mRenderH / (mLineHeight + mLineSpacing);
895 int line;
896
897 if (selected_index > mStart + lines - 1) {
898 mStart = selected_index;
899 } else if (selected_index < mStart) {
900 mStart = selected_index;
901 }
902 }
903 updateList = true;
904 mUpdate = 1;
905 }
906}
907
908void GUIPartitionList::MatchList(void) {
909 int i, listSize = mList.size();
910 string variablelist, searchvalue;
911 size_t pos;
912
913 DataManager::GetValue(mVariable, variablelist);
914
915 for (i=0; i<listSize; i++) {
916 searchvalue = mList.at(i).Mount_Point + ";";
917 pos = variablelist.find(searchvalue);
918 if (pos != string::npos) {
919 mList.at(i).selected = 1;
920 } else {
921 mList.at(i).selected = 0;
922 }
923 }
924}