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