summaryrefslogtreecommitdiff
path: root/src/ui/mobile.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/mobile.c')
-rw-r--r--src/ui/mobile.c134
1 files changed, 101 insertions, 33 deletions
diff --git a/src/ui/mobile.c b/src/ui/mobile.c
index daa1fa1a..6ea672e6 100644
--- a/src/ui/mobile.c
+++ b/src/ui/mobile.c
@@ -90,15 +90,15 @@ static void unselectAllPanelButtons_(iWidget *topPanel) {
90 90
91static iBool mainDetailSplitHandler_(iWidget *mainDetailSplit, const char *cmd) { 91static iBool mainDetailSplitHandler_(iWidget *mainDetailSplit, const char *cmd) {
92 if (equal_Command(cmd, "window.resized")) { 92 if (equal_Command(cmd, "window.resized")) {
93 const iBool isPortrait = (deviceType_App() == phone_AppDeviceType && isPortrait_App()); 93 const iBool isPortrait = (deviceType_App() == phone_AppDeviceType && isPortrait_App());
94 const iRect safeRoot = safeRect_Root(mainDetailSplit->root); 94 const iRect safeRoot = safeRect_Root(mainDetailSplit->root);
95 setPos_Widget(mainDetailSplit, topLeft_Rect(safeRoot));
96 setFixedSize_Widget(mainDetailSplit, safeRoot.size);
97 iWidget * sheet = parent_Widget(mainDetailSplit); 95 iWidget * sheet = parent_Widget(mainDetailSplit);
98 iWidget * navi = findChild_Widget(sheet, "panel.navi"); 96 iWidget * navi = findChild_Widget(sheet, "panel.navi");
99 iWidget * detailStack = findChild_Widget(mainDetailSplit, "detailstack"); 97 iWidget * detailStack = findChild_Widget(mainDetailSplit, "detailstack");
100 const size_t numPanels = childCount_Widget(detailStack); 98 const size_t numPanels = childCount_Widget(detailStack);
101 const iBool isSideBySide = isSideBySideLayout_() && numPanels > 0; 99 const iBool isSideBySide = isSideBySideLayout_() && numPanels > 0;
100 setPos_Widget(mainDetailSplit, topLeft_Rect(safeRoot));
101 setFixedSize_Widget(mainDetailSplit, safeRoot.size);
102 setFlags_Widget(mainDetailSplit, arrangeHorizontal_WidgetFlag, isSideBySide); 102 setFlags_Widget(mainDetailSplit, arrangeHorizontal_WidgetFlag, isSideBySide);
103 setFlags_Widget(detailStack, expand_WidgetFlag, isSideBySide); 103 setFlags_Widget(detailStack, expand_WidgetFlag, isSideBySide);
104 setFlags_Widget(detailStack, hidden_WidgetFlag, numPanels == 0); 104 setFlags_Widget(detailStack, hidden_WidgetFlag, numPanels == 0);
@@ -172,7 +172,16 @@ static iBool topPanelHandler_(iWidget *topPanel, const char *cmd) {
172 } 172 }
173 unselectAllPanelButtons_(topPanel); 173 unselectAllPanelButtons_(topPanel);
174 if (!wasClosed) { 174 if (!wasClosed) {
175 postCommand_App("prefs.dismiss"); 175 /* TODO: Should come up with a more general-purpose approach here. */
176 if (findWidget_App("prefs")) {
177 postCommand_App("prefs.dismiss");
178 }
179 else if (findWidget_App("upload")) {
180 postCommand_App("upload.cancel");
181 }
182 else {
183 postCommand_App("cancel");
184 }
176 } 185 }
177 return iTrue; 186 return iTrue;
178 } 187 }
@@ -503,11 +512,19 @@ void makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) {
503 else if (equal_Command(spec, "label")) { 512 else if (equal_Command(spec, "label")) {
504 iLabelWidget *lab = new_LabelWidget(label, NULL); 513 iLabelWidget *lab = new_LabelWidget(label, NULL);
505 widget = as_Widget(lab); 514 widget = as_Widget(lab);
506 setWrap_LabelWidget(lab, iTrue); 515 setId_Widget(widget, id);
507 setFlags_Widget(widget, fixedHeight_WidgetFlag | frameless_WidgetFlag, iTrue); 516 setWrap_LabelWidget(lab, !argLabel_Command(spec, "nowrap"));
517 setFlags_Widget(widget,
518 fixedHeight_WidgetFlag |
519 (!argLabel_Command(spec, "frame") ? frameless_WidgetFlag : 0),
520 iTrue);
508 } 521 }
509 else if (equal_Command(spec, "padding")) { 522 else if (equal_Command(spec, "padding")) {
510 widget = makePadding_Widget(lineHeight_Text(labelFont_()) * 1.5f); 523 float height = 1.5f;
524 if (hasLabel_Command(spec, "arg")) {
525 height *= argfLabel_Command(spec, "arg");
526 }
527 widget = makePadding_Widget(lineHeight_Text(labelFont_()) * height);
511 } 528 }
512 /* Apply common styling to the heading. */ 529 /* Apply common styling to the heading. */
513 if (heading) { 530 if (heading) {
@@ -539,7 +556,7 @@ static const iMenuItem *findDialogCancelAction_(const iMenuItem *items, size_t n
539 return NULL; 556 return NULL;
540 } 557 }
541 for (size_t i = 0; i < n; i++) { 558 for (size_t i = 0; i < n; i++) {
542 if (!iCmpStr(items[i].label, "${cancel}")) { 559 if (!iCmpStr(items[i].label, "${cancel}") || !iCmpStr(items[i].label, "${close}")) {
543 return &items[i]; 560 return &items[i];
544 } 561 }
545 } 562 }
@@ -556,13 +573,20 @@ iWidget *makePanelsParent_Mobile(iWidget *parentWidget,
556 const char *id, 573 const char *id,
557 const iMenuItem *itemsNullTerminated, 574 const iMenuItem *itemsNullTerminated,
558 const iMenuItem *actions, size_t numActions) { 575 const iMenuItem *actions, size_t numActions) {
576 iWidget *panels = new_Widget();
577 setId_Widget(panels, id);
578 initPanels_Mobile(panels, parentWidget, itemsNullTerminated, actions, numActions);
579 return panels;
580}
581
582void initPanels_Mobile(iWidget *panels, iWidget *parentWidget,
583 const iMenuItem *itemsNullTerminated,
584 const iMenuItem *actions, size_t numActions) {
559 /* A multipanel widget has a top panel and one or more detail panels. In a horizontal layout, 585 /* A multipanel widget has a top panel and one or more detail panels. In a horizontal layout,
560 the detail panels slide in from the right and cover the top panel. In a landscape layout, 586 the detail panels slide in from the right and cover the top panel. In a landscape layout,
561 the detail panels are always visible on the side. */ 587 the detail panels are always visible on the side. */
562 iWidget *sheet = new_Widget(); 588 setBackgroundColor_Widget(panels, uiBackground_ColorId);
563 setId_Widget(sheet, id); 589 setFlags_Widget(panels,
564 setBackgroundColor_Widget(sheet, uiBackground_ColorId);
565 setFlags_Widget(sheet,
566 resizeToParentWidth_WidgetFlag | resizeToParentHeight_WidgetFlag | 590 resizeToParentWidth_WidgetFlag | resizeToParentHeight_WidgetFlag |
567 frameless_WidgetFlag | focusRoot_WidgetFlag | commandOnClick_WidgetFlag | 591 frameless_WidgetFlag | focusRoot_WidgetFlag | commandOnClick_WidgetFlag |
568 overflowScrollable_WidgetFlag | leftEdgeDraggable_WidgetFlag, 592 overflowScrollable_WidgetFlag | leftEdgeDraggable_WidgetFlag,
@@ -572,7 +596,7 @@ iWidget *makePanelsParent_Mobile(iWidget *parentWidget,
572 setCommandHandler_Widget(mainDetailSplit, mainDetailSplitHandler_); 596 setCommandHandler_Widget(mainDetailSplit, mainDetailSplitHandler_);
573 setFlags_Widget(mainDetailSplit, resizeHeightOfChildren_WidgetFlag, iFalse); 597 setFlags_Widget(mainDetailSplit, resizeHeightOfChildren_WidgetFlag, iFalse);
574 setId_Widget(mainDetailSplit, "mdsplit"); 598 setId_Widget(mainDetailSplit, "mdsplit");
575 addChild_Widget(sheet, iClob(mainDetailSplit)); 599 addChild_Widget(panels, iClob(mainDetailSplit));
576 } 600 }
577 /* The panel roots. */ 601 /* The panel roots. */
578 iWidget *topPanel = new_Widget(); { 602 iWidget *topPanel = new_Widget(); {
@@ -591,7 +615,6 @@ iWidget *makePanelsParent_Mobile(iWidget *parentWidget,
591 setFlags_Widget(detailStack, collapse_WidgetFlag | resizeWidthOfChildren_WidgetFlag, iTrue); 615 setFlags_Widget(detailStack, collapse_WidgetFlag | resizeWidthOfChildren_WidgetFlag, iTrue);
592 addChild_Widget(mainDetailSplit, iClob(detailStack)); 616 addChild_Widget(mainDetailSplit, iClob(detailStack));
593 } 617 }
594 addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(labelFont_()))));
595 /* Slide top panel with detail panels. */ { 618 /* Slide top panel with detail panels. */ {
596 setFlags_Widget(topPanel, refChildrenOffset_WidgetFlag, iTrue); 619 setFlags_Widget(topPanel, refChildrenOffset_WidgetFlag, iTrue);
597 topPanel->offsetRef = detailStack; 620 topPanel->offsetRef = detailStack;
@@ -612,15 +635,17 @@ iWidget *makePanelsParent_Mobile(iWidget *parentWidget,
612 checkIcon_LabelWidget(naviBack); 635 checkIcon_LabelWidget(naviBack);
613 setId_Widget(as_Widget(naviBack), "panel.back"); 636 setId_Widget(as_Widget(naviBack), "panel.back");
614 setFont_LabelWidget(naviBack, labelFont_()); 637 setFont_LabelWidget(naviBack, labelFont_());
615 addChildFlags_Widget(sheet, iClob(navi), 638 addChildFlags_Widget(panels, iClob(navi),
616 drawBackgroundToVerticalSafeArea_WidgetFlag | 639 drawBackgroundToVerticalSafeArea_WidgetFlag |
617 arrangeHeight_WidgetFlag | resizeWidthOfChildren_WidgetFlag | 640 arrangeHeight_WidgetFlag | resizeWidthOfChildren_WidgetFlag |
618 resizeToParentWidth_WidgetFlag | arrangeVertical_WidgetFlag); 641 resizeToParentWidth_WidgetFlag | arrangeVertical_WidgetFlag);
619 } 642 }
643 iBool haveDetailPanels = iFalse;
620 /* Create panel contents based on provided items. */ 644 /* Create panel contents based on provided items. */
621 for (size_t i = 0; itemsNullTerminated[i].label; i++) { 645 for (size_t i = 0; itemsNullTerminated[i].label; i++) {
622 const iMenuItem *item = &itemsNullTerminated[i]; 646 const iMenuItem *item = &itemsNullTerminated[i];
623 if (equal_Command(item->label, "panel")) { 647 if (equal_Command(item->label, "panel")) {
648 haveDetailPanels = iTrue;
624 const char *id = cstr_Rangecc(range_Command(item->label, "id")); 649 const char *id = cstr_Rangecc(range_Command(item->label, "id"));
625 const iString *label = hasLabel_Command(item->label, "text") 650 const iString *label = hasLabel_Command(item->label, "text")
626 ? collect_String(suffix_Command(item->label, "text")) 651 ? collect_String(suffix_Command(item->label, "text"))
@@ -655,10 +680,12 @@ iWidget *makePanelsParent_Mobile(iWidget *parentWidget,
655 setFont_LabelWidget(naviBack, labelBoldFont_()); 680 setFont_LabelWidget(naviBack, labelBoldFont_());
656 } 681 }
657 else if (defaultItem && defaultItem != cancelItem) { 682 else if (defaultItem && defaultItem != cancelItem) {
658 updateTextCStr_LabelWidget(naviBack, cancelItem->label); 683 if (!haveDetailPanels) {
659 setCommand_LabelWidget(naviBack, collectNewCStr_String(cancelItem->command 684 updateTextCStr_LabelWidget(naviBack, cancelItem->label);
660 ? cancelItem->command 685 setCommand_LabelWidget(naviBack, collectNewCStr_String(cancelItem->command
661 : "cancel")); 686 ? cancelItem->command
687 : "cancel"));
688 }
662 iLabelWidget *defaultButton = new_LabelWidget(defaultItem->label, defaultItem->command); 689 iLabelWidget *defaultButton = new_LabelWidget(defaultItem->label, defaultItem->command);
663 setFont_LabelWidget(defaultButton, labelBoldFont_()); 690 setFont_LabelWidget(defaultButton, labelBoldFont_());
664 setFlags_Widget(as_Widget(defaultButton), 691 setFlags_Widget(as_Widget(defaultButton),
@@ -689,16 +716,21 @@ iWidget *makePanelsParent_Mobile(iWidget *parentWidget,
689 } 716 }
690 makePanelItem_Mobile( 717 makePanelItem_Mobile(
691 topPanel, 718 topPanel,
692 &(iMenuItem){ format_CStr("button text:%s", act->label), 0, 0, act->command }); 719 &(iMenuItem){ format_CStr("button text:" uiTextAction_ColorEscape "%s", act->label),
720 0,
721 0,
722 act->command });
693 } 723 }
694 } 724 }
695 /* Finalize the layout. */ 725 /* Finalize the layout. */
696 addChild_Widget(parentWidget, iClob(sheet)); 726 if (parentWidget) {
727 addChild_Widget(parentWidget, iClob(panels));
728 }
697 mainDetailSplitHandler_(mainDetailSplit, "window.resized"); /* make it resize the split */ 729 mainDetailSplitHandler_(mainDetailSplit, "window.resized"); /* make it resize the split */
698 updatePanelSheetMetrics_(sheet); 730 updatePanelSheetMetrics_(panels);
699 arrange_Widget(sheet); 731 arrange_Widget(panels);
700 postCommand_App("widget.overflow"); /* with the correct dimensions */ 732 postCommand_App("widget.overflow"); /* with the correct dimensions */
701 return sheet; 733 printTree_Widget(panels);
702} 734}
703 735
704#if 0 736#if 0
@@ -1130,7 +1162,9 @@ void setupMenuTransition_Mobile(iWidget *sheet, iBool isIncoming) {
1130 } 1162 }
1131} 1163}
1132 1164
1133void setupSheetTransition_Mobile(iWidget *sheet, iBool isIncoming) { 1165void setupSheetTransition_Mobile(iWidget *sheet, int flags) {
1166 const iBool isIncoming = (flags & incoming_TransitionFlag) != 0;
1167 const int dir = flags & dirMask_TransitionFlag;
1134 if (!isUsingPanelLayout_Mobile()) { 1168 if (!isUsingPanelLayout_Mobile()) {
1135 if (prefs_App()->uiAnimations) { 1169 if (prefs_App()->uiAnimations) {
1136 setFlags_Widget(sheet, horizontalOffset_WidgetFlag, iFalse); 1170 setFlags_Widget(sheet, horizontalOffset_WidgetFlag, iFalse);
@@ -1144,17 +1178,51 @@ void setupSheetTransition_Mobile(iWidget *sheet, iBool isIncoming) {
1144 } 1178 }
1145 return; 1179 return;
1146 } 1180 }
1147 if(isSideBySideLayout_()) { 1181 if (isSideBySideLayout_()) {
1182 /* TODO: Landscape transitions? */
1148 return; 1183 return;
1149 } 1184 }
1150 setFlags_Widget(sheet, horizontalOffset_WidgetFlag, iTrue); 1185 setFlags_Widget(sheet,
1186 horizontalOffset_WidgetFlag,
1187 dir == right_TransitionDir || dir == left_TransitionDir);
1151 if (isIncoming) { 1188 if (isIncoming) {
1152 setVisualOffset_Widget(sheet, size_Root(sheet->root).x, 0, 0); 1189 switch (dir) {
1190 case right_TransitionDir:
1191 setVisualOffset_Widget(sheet, size_Root(sheet->root).x, 0, 0);
1192 break;
1193 case left_TransitionDir:
1194 setVisualOffset_Widget(sheet, -size_Root(sheet->root).x, 0, 0);
1195 break;
1196 case top_TransitionDir:
1197 setVisualOffset_Widget(
1198 sheet, -bottom_Rect(boundsWithoutVisualOffset_Widget(sheet)), 0, 0);
1199 break;
1200 case bottom_TransitionDir:
1201 setVisualOffset_Widget(sheet, height_Widget(sheet), 0, 0);
1202 break;
1203 }
1153 setVisualOffset_Widget(sheet, 0, 200, easeOut_AnimFlag); 1204 setVisualOffset_Widget(sheet, 0, 200, easeOut_AnimFlag);
1154 } 1205 }
1155 else { 1206 else {
1156 const iBool wasDragged = iAbs(value_Anim(&sheet->visualOffset)) > 0; 1207 switch (dir) {
1157 setVisualOffset_Widget(sheet, size_Root(sheet->root).x, wasDragged ? 100 : 200, 1208 case right_TransitionDir: {
1158 wasDragged ? 0 : easeIn_AnimFlag); 1209 const iBool wasDragged = iAbs(value_Anim(&sheet->visualOffset)) > 0;
1210 setVisualOffset_Widget(sheet, size_Root(sheet->root).x, wasDragged ? 100 : 200,
1211 wasDragged ? 0 : easeIn_AnimFlag);
1212 break;
1213 }
1214 case left_TransitionDir:
1215 setVisualOffset_Widget(sheet, -size_Root(sheet->root).x, 200, easeIn_AnimFlag);
1216 break;
1217 case top_TransitionDir:
1218 setVisualOffset_Widget(sheet,
1219 -bottom_Rect(boundsWithoutVisualOffset_Widget(sheet)),
1220 200,
1221 easeIn_AnimFlag);
1222 break;
1223 case bottom_TransitionDir:
1224 setVisualOffset_Widget(sheet, height_Widget(sheet), 200, easeIn_AnimFlag);
1225 break;
1226 }
1159 } 1227 }
1160} 1228}