summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-09-11 07:43:57 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-09-11 07:43:57 +0300
commit1410bbde7779efe3a20f603523547c8b8f55b6a1 (patch)
tree54e8ab43ea6d3dc35d7993b6909096c6c8429e50 /src/ui
parent61c23be799956615ceeeda10aaeccc2bb11e9c94 (diff)
Mobile: Many UI improvements; Upload UI
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/certimportwidget.c120
-rw-r--r--src/ui/documentwidget.c9
-rw-r--r--src/ui/labelwidget.c17
-rw-r--r--src/ui/mobile.c134
-rw-r--r--src/ui/mobile.h19
-rw-r--r--src/ui/root.c10
-rw-r--r--src/ui/uploadwidget.c188
-rw-r--r--src/ui/util.c15
-rw-r--r--src/ui/widget.c4
9 files changed, 323 insertions, 193 deletions
diff --git a/src/ui/certimportwidget.c b/src/ui/certimportwidget.c
index 2e60c71f..65cb6654 100644
--- a/src/ui/certimportwidget.c
+++ b/src/ui/certimportwidget.c
@@ -104,61 +104,83 @@ static iBool tryImport_CertImportWidget_(iCertImportWidget *d, const iBlock *dat
104 104
105void init_CertImportWidget(iCertImportWidget *d) { 105void init_CertImportWidget(iCertImportWidget *d) {
106 iWidget *w = as_Widget(d); 106 iWidget *w = as_Widget(d);
107 const iMenuItem actions[] = {
108#if defined (iPlatformAppleMobile)
109 { "${dlg.certimport.pickfile}", 0, 0, "certimport.pickfile" },
110 { "---" },
111#endif
112 { "${cancel}" },
113 { uiTextAction_ColorEscape "${dlg.certimport.import}",
114 SDLK_RETURN, KMOD_PRIMARY,
115 "certimport.accept" }
116 };
107 init_Widget(w); 117 init_Widget(w);
108 setId_Widget(w, "certimport"); 118 setId_Widget(w, "certimport");
109 d->cert = NULL; 119 d->cert = NULL;
110 /* This should behave similar to sheets. */ 120 if (isUsingPanelLayout_Mobile()) {
111 useSheetStyle_Widget(w); 121 initPanels_Mobile(w, NULL, (iMenuItem[]){
112 addChildFlags_Widget( 122 { "title id:heading.certimport" },
113 w, 123 { format_CStr("label id:certimport.info text:%s", infoText_) },
114 iClob(new_LabelWidget(uiHeading_ColorEscape "${heading.certimport}", NULL)), 124 //{ "padding" },
115 frameless_WidgetFlag); 125 { "label id:certimport.crt nowrap:1 frame:1" },
116 d->info = addChildFlags_Widget(w, iClob(new_LabelWidget(infoText_, NULL)), frameless_WidgetFlag); 126 { "padding arg:0.25" },
117 addChild_Widget(w, iClob(makePadding_Widget(gap_UI))); 127 { "label id:certimport.key nowrap:1 frame:1" },
118 d->crtLabel = new_LabelWidget("", NULL); { 128 { "heading text:${dlg.certimport.notes}" },
119 setFont_LabelWidget(d->crtLabel, uiContent_FontId); 129 { "input id:certimport.notes hint:hint.certimport.description noheading:1" },
120 addChildFlags_Widget(w, iClob(d->crtLabel), 0); 130 { NULL }
121 setFrameColor_Widget(as_Widget(d->crtLabel), uiTextCaution_ColorId); 131 }, actions, iElemCount(actions));
132 d->info = findChild_Widget(w, "certimport.info");
133 d->crtLabel = findChild_Widget(w, "certimport.crt");
134 d->keyLabel = findChild_Widget(w, "certimport.key");
135 d->notes = findChild_Widget(w, "certimport.notes");
136 setFixedSize_Widget(as_Widget(d->crtLabel), init_I2(-1, gap_UI * 12));
137 setFixedSize_Widget(as_Widget(d->keyLabel), init_I2(-1, gap_UI * 12));
122 } 138 }
123 d->keyLabel = new_LabelWidget("", NULL); { 139 else {
124 setFont_LabelWidget(d->keyLabel, uiContent_FontId); 140 /* This should behave similar to sheets. */
141 useSheetStyle_Widget(w);
142 addChildFlags_Widget(
143 w,
144 iClob(new_LabelWidget(uiHeading_ColorEscape "${heading.certimport}", NULL)),
145 frameless_WidgetFlag);
146 d->info = addChildFlags_Widget(w, iClob(new_LabelWidget(infoText_, NULL)), frameless_WidgetFlag);
125 addChild_Widget(w, iClob(makePadding_Widget(gap_UI))); 147 addChild_Widget(w, iClob(makePadding_Widget(gap_UI)));
126 addChildFlags_Widget(w, iClob(d->keyLabel), 0); 148 d->crtLabel = new_LabelWidget("", NULL); {
127 setFrameColor_Widget(as_Widget(d->keyLabel), uiTextCaution_ColorId); 149 setFont_LabelWidget(d->crtLabel, uiContent_FontId);
128 } 150 addChildFlags_Widget(w, iClob(d->crtLabel), 0);
129 addChild_Widget(w, iClob(makePadding_Widget(gap_UI))); 151 }
130 /* TODO: Use makeTwoColumnWidget_() */ 152 d->keyLabel = new_LabelWidget("", NULL); {
131 iWidget *page = new_Widget(); { 153 setFont_LabelWidget(d->keyLabel, uiContent_FontId);
132 setFlags_Widget(page, arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag, iTrue); 154 addChild_Widget(w, iClob(makePadding_Widget(gap_UI)));
133 iWidget *headings = addChildFlags_Widget( 155 addChildFlags_Widget(w, iClob(d->keyLabel), 0);
134 page, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag); 156 }
135 iWidget *values = addChildFlags_Widget( 157 addChild_Widget(w, iClob(makePadding_Widget(gap_UI)));
136 page, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag); 158 /* TODO: Use makeTwoColumnWidget_() */
137// addChild_Widget(headings, iClob(makeHeading_Widget("${dlg.certimport.notes}"))); 159 iWidget *page = new_Widget(); {
138// addChild_Widget(values, iClob(d->notes = new_InputWidget(0))); 160 setFlags_Widget(page, arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag, iTrue);
139// setHint_InputWidget(d->notes, "${hint.certimport.description}"); 161 iWidget *headings = addChildFlags_Widget(
140 addTwoColumnDialogInputField_Widget( 162 page, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag);
141 headings, 163 iWidget *values = addChildFlags_Widget(
142 values, 164 page, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag);
143 "${dlg.certimport.notes}", 165 addTwoColumnDialogInputField_Widget(
144 "", 166 headings,
145 iClob(d->notes = newHint_InputWidget(0, "${hint.certimport.description}"))); 167 values,
146 as_Widget(d->notes)->rect.size.x = gap_UI * 70; 168 "${dlg.certimport.notes}",
169 "",
170 iClob(d->notes = newHint_InputWidget(0, "${hint.certimport.description}")));
171 as_Widget(d->notes)->rect.size.x = gap_UI * 70;
172 }
173 addChild_Widget(w, iClob(page));
174 arrange_Widget(w);
175 setFixedSize_Widget(as_Widget(d->crtLabel), init_I2(width_Widget(w) - 6.5 * gap_UI, gap_UI * 12));
176 setFixedSize_Widget(as_Widget(d->keyLabel), init_I2(width_Widget(w) - 6.5 * gap_UI, gap_UI * 12));
177 /* Buttons. */
178 addChild_Widget(w, iClob(makePadding_Widget(gap_UI)));
179 iWidget *buttons = makeDialogButtons_Widget(actions, iElemCount(actions));
180 addChild_Widget(w, iClob(buttons));
147 } 181 }
148 addChild_Widget(w, iClob(page)); 182 setFrameColor_Widget(as_Widget(d->crtLabel), uiTextCaution_ColorId);
149 arrange_Widget(w); 183 setFrameColor_Widget(as_Widget(d->keyLabel), uiTextCaution_ColorId);
150 setFixedSize_Widget(as_Widget(d->crtLabel), init_I2(width_Widget(w) - 6.5 * gap_UI, gap_UI * 12));
151 setFixedSize_Widget(as_Widget(d->keyLabel), init_I2(width_Widget(w) - 6.5 * gap_UI, gap_UI * 12));
152 /* Buttons. */
153 addChild_Widget(w, iClob(makePadding_Widget(gap_UI)));
154 iWidget *buttons = makeDialogButtons_Widget(
155 (iMenuItem[]){ { "${cancel}" },
156 { uiTextAction_ColorEscape "${dlg.certimport.import}",
157 SDLK_RETURN,
158 KMOD_PRIMARY,
159 "certimport.accept" } },
160 2);
161 addChild_Widget(w, iClob(buttons));
162 if (deviceType_App() != desktop_AppDeviceType) { 184 if (deviceType_App() != desktop_AppDeviceType) {
163 /* Try auto-pasting. */ 185 /* Try auto-pasting. */
164 postCommand_App("certimport.paste"); 186 postCommand_App("certimport.paste");
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 83f2ea6a..4b3c2db0 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -2852,7 +2852,8 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2852 setUrl_UploadWidget(upload, d->mod.url); 2852 setUrl_UploadWidget(upload, d->mod.url);
2853 setResponseViewer_UploadWidget(upload, d); 2853 setResponseViewer_UploadWidget(upload, d);
2854 addChild_Widget(get_Root()->widget, iClob(upload)); 2854 addChild_Widget(get_Root()->widget, iClob(upload));
2855 finalizeSheet_Mobile(as_Widget(upload)); 2855// finalizeSheet_Mobile(as_Widget(upload));
2856 setupSheetTransition_Mobile(as_Widget(upload), iTrue);
2856 postRefresh_App(); 2857 postRefresh_App();
2857 } 2858 }
2858 return iTrue; 2859 return iTrue;
@@ -3679,16 +3680,10 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
3679 { "---" }, 3680 { "---" },
3680 { book_Icon " ${menu.page.import}", 0, 0, "bookmark.links confirm:1" }, 3681 { book_Icon " ${menu.page.import}", 0, 0, "bookmark.links confirm:1" },
3681 { globe_Icon " ${menu.page.translate}", 0, 0, "document.translate" }, 3682 { globe_Icon " ${menu.page.translate}", 0, 0, "document.translate" },
3682#if defined (iPlatformMobile)
3683 { "---" },
3684 { "${menu.page.copyurl}", 0, 0, "document.copylink" } },
3685 14);
3686#else
3687 { upload_Icon " ${menu.page.upload}", 0, 0, "document.upload" }, 3683 { upload_Icon " ${menu.page.upload}", 0, 0, "document.upload" },
3688 { "---" }, 3684 { "---" },
3689 { "${menu.page.copyurl}", 0, 0, "document.copylink" } }, 3685 { "${menu.page.copyurl}", 0, 0, "document.copylink" } },
3690 15); 3686 15);
3691#endif
3692 if (isEmpty_Range(&d->selectMark)) { 3687 if (isEmpty_Range(&d->selectMark)) {
3693 pushBackN_Array( 3688 pushBackN_Array(
3694 &items, 3689 &items,
diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c
index 03595d1a..ec324d02 100644
--- a/src/ui/labelwidget.c
+++ b/src/ui/labelwidget.c
@@ -244,6 +244,9 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int
244 } 244 }
245 } 245 }
246 } 246 }
247 if (d->forceFg >= 0) {
248 *fg = d->forceFg;
249 }
247 if (isPress) { 250 if (isPress) {
248 *bg = uiBackgroundPressed_ColorId | permanent_ColorId; 251 *bg = uiBackgroundPressed_ColorId | permanent_ColorId;
249 if (isButton) { 252 if (isButton) {
@@ -257,9 +260,6 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int
257 *fg = isDark_ColorTheme(colorTheme_App()) ? white_ColorId : black_ColorId; 260 *fg = isDark_ColorTheme(colorTheme_App()) ? white_ColorId : black_ColorId;
258 } 261 }
259 } 262 }
260 if (d->forceFg >= 0) {
261 *fg = d->forceFg;
262 }
263} 263}
264 264
265iLocalDef int iconPadding_LabelWidget_(const iLabelWidget *d) { 265iLocalDef int iconPadding_LabelWidget_(const iLabelWidget *d) {
@@ -318,6 +318,10 @@ static void draw_LabelWidget_(const iLabelWidget *d) {
318 } 318 }
319 setClip_Paint(&p, rect); 319 setClip_Paint(&p, rect);
320 const int iconPad = iconPadding_LabelWidget_(d); 320 const int iconPad = iconPadding_LabelWidget_(d);
321 const int iconColor = isCaution ? uiTextCaution_ColorId
322 : flags & (disabled_WidgetFlag | pressed_WidgetFlag) ? fg
323 : isHover ? uiIconHover_ColorId
324 : uiIcon_ColorId;
321 if (d->icon && d->icon != 0x20) { /* no need to draw an empty icon */ 325 if (d->icon && d->icon != 0x20) { /* no need to draw an empty icon */
322 iString str; 326 iString str;
323 initUnicodeN_String(&str, &d->icon, 1); 327 initUnicodeN_String(&str, &d->icon, 1);
@@ -331,10 +335,7 @@ static void draw_LabelWidget_(const iLabelWidget *d) {
331 -gap_UI / 8)), 335 -gap_UI / 8)),
332 init_I2(iconPad, lineHeight_Text(d->font)) }, 336 init_I2(iconPad, lineHeight_Text(d->font)) },
333 iTrue, 337 iTrue,
334 isCaution ? uiTextCaution_ColorId 338 iconColor,
335 : flags & (disabled_WidgetFlag | pressed_WidgetFlag) ? fg
336 : isHover ? uiIconHover_ColorId
337 : uiIcon_ColorId,
338 "%s", 339 "%s",
339 cstr_String(&str)); 340 cstr_String(&str));
340 deinit_String(&str); 341 deinit_String(&str);
@@ -387,7 +388,7 @@ static void draw_LabelWidget_(const iLabelWidget *d) {
387 drawCentered_Text(d->font, 388 drawCentered_Text(d->font,
388 (iRect){ addX_I2(topRight_Rect(chRect), -iconPad), 389 (iRect){ addX_I2(topRight_Rect(chRect), -iconPad),
389 init_I2(chSize, height_Rect(chRect)) }, 390 init_I2(chSize, height_Rect(chRect)) },
390 iTrue, uiSeparator_ColorId, rightAngle_Icon); 391 iTrue, iconColor /*uiSeparator_ColorId*/, rightAngle_Icon);
391 } 392 }
392 unsetClip_Paint(&p); 393 unsetClip_Paint(&p);
393} 394}
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}
diff --git a/src/ui/mobile.h b/src/ui/mobile.h
index 30679c7c..e1131953 100644
--- a/src/ui/mobile.h
+++ b/src/ui/mobile.h
@@ -35,8 +35,23 @@ iWidget * makePanelsParent_Mobile (iWidget *parent,
35 const char *id, 35 const char *id,
36 const iMenuItem *itemsNullTerminated, 36 const iMenuItem *itemsNullTerminated,
37 const iMenuItem *actions, size_t numActions); 37 const iMenuItem *actions, size_t numActions);
38void initPanels_Mobile (iWidget *panels, iWidget *parentWidget,
39 const iMenuItem *itemsNullTerminated,
40 const iMenuItem *actions, size_t numActions);
41
42enum iTransitionFlags {
43 incoming_TransitionFlag = iBit(1),
44 dirMask_TransitionFlag = iBit(2) | iBit(3),
45};
46
47enum iTransitionDir {
48 right_TransitionDir = 0,
49 bottom_TransitionDir = 2,
50 left_TransitionDir = 4,
51 top_TransitionDir = 6,
52};
38 53
39void setupMenuTransition_Mobile (iWidget *menu, iBool isIncoming); 54void setupMenuTransition_Mobile (iWidget *menu, iBool isIncoming);
40void setupSheetTransition_Mobile (iWidget *sheet, iBool isIncoming); 55void setupSheetTransition_Mobile (iWidget *sheet, int flags);
41 56
42void finalizeSheet_Mobile (iWidget *sheet); 57void finalizeSheet_Mobile (iWidget *sheet);
diff --git a/src/ui/root.c b/src/ui/root.c
index eae8e4bb..a792e93d 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -118,7 +118,7 @@ static const iMenuItem phoneNavMenuItems_[] = {
118 { "${menu.downloads}", 0, 0, "downloads.open" }, 118 { "${menu.downloads}", 0, 0, "downloads.open" },
119 { "${menu.feeds.entrylist}", 0, 0, "!open url:about:feeds" }, 119 { "${menu.feeds.entrylist}", 0, 0, "!open url:about:feeds" },
120 { "---" }, 120 { "---" },
121 { gear_Icon " Settings...", SDLK_COMMA, KMOD_PRIMARY, "preferences" }, 121 { gear_Icon " ${menu.settings}", SDLK_COMMA, KMOD_PRIMARY, "preferences" },
122}; 122};
123#endif /* Mobile */ 123#endif /* Mobile */
124 124
@@ -1163,20 +1163,12 @@ void createUserInterface_Root(iRoot *d) {
1163 { star_Icon " ${menu.page.subscribe}", subscribeToPage_KeyModifier, "feeds.subscribe" }, 1163 { star_Icon " ${menu.page.subscribe}", subscribeToPage_KeyModifier, "feeds.subscribe" },
1164 { book_Icon " ${menu.page.import}", 0, 0, "bookmark.links confirm:1" }, 1164 { book_Icon " ${menu.page.import}", 0, 0, "bookmark.links confirm:1" },
1165 { globe_Icon " ${menu.page.translate}", 0, 0, "document.translate" }, 1165 { globe_Icon " ${menu.page.translate}", 0, 0, "document.translate" },
1166#if defined (iPlatformMobile)
1167 { "---" },
1168 { "${menu.page.copyurl}", 0, 0, "document.copylink" },
1169 { "${menu.page.copysource}", 'c', KMOD_PRIMARY, "copy" },
1170 { download_Icon " " saveToDownloads_Label, SDLK_s, KMOD_PRIMARY, "document.save" } },
1171 11);
1172#else
1173 { upload_Icon " ${menu.page.upload}", 0, 0, "document.upload" }, 1166 { upload_Icon " ${menu.page.upload}", 0, 0, "document.upload" },
1174 { "---" }, 1167 { "---" },
1175 { "${menu.page.copyurl}", 0, 0, "document.copylink" }, 1168 { "${menu.page.copyurl}", 0, 0, "document.copylink" },
1176 { "${menu.page.copysource}", 'c', KMOD_PRIMARY, "copy" }, 1169 { "${menu.page.copysource}", 'c', KMOD_PRIMARY, "copy" },
1177 { download_Icon " " saveToDownloads_Label, SDLK_s, KMOD_PRIMARY, "document.save" } }, 1170 { download_Icon " " saveToDownloads_Label, SDLK_s, KMOD_PRIMARY, "document.save" } },
1178 12); 1171 12);
1179#endif
1180 setId_Widget(as_Widget(pageMenuButton), "pagemenubutton"); 1172 setId_Widget(as_Widget(pageMenuButton), "pagemenubutton");
1181 setFont_LabelWidget(pageMenuButton, uiContentBold_FontId); 1173 setFont_LabelWidget(pageMenuButton, uiContentBold_FontId);
1182 setAlignVisually_LabelWidget(pageMenuButton, iTrue); 1174 setAlignVisually_LabelWidget(pageMenuButton, iTrue);
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c
index 4c72c60a..fb8aaf0a 100644
--- a/src/ui/uploadwidget.c
+++ b/src/ui/uploadwidget.c
@@ -81,91 +81,122 @@ void init_UploadWidget(iUploadWidget *d) {
81 iWidget *w = as_Widget(d); 81 iWidget *w = as_Widget(d);
82 init_Widget(w); 82 init_Widget(w);
83 setId_Widget(w, "upload"); 83 setId_Widget(w, "upload");
84 useSheetStyle_Widget(w);
85 init_String(&d->originalUrl); 84 init_String(&d->originalUrl);
86 init_String(&d->url); 85 init_String(&d->url);
87 d->viewer = NULL; 86 d->viewer = NULL;
88 d->request = NULL; 87 d->request = NULL;
89 init_String(&d->filePath); 88 init_String(&d->filePath);
90 d->fileSize = 0; 89 d->fileSize = 0;
91 addChildFlags_Widget(w, 90 const iMenuItem actions[] = {
92 iClob(new_LabelWidget(uiHeading_ColorEscape "${heading.upload}", NULL)), 91 { "${upload.port}", 0, 0, "upload.setport" },
93 frameless_WidgetFlag); 92 { "---" },
94 d->info = addChildFlags_Widget(w, iClob(new_LabelWidget("", NULL)), 93 { "${close}", SDLK_ESCAPE, 0, "upload.cancel" },
95 frameless_WidgetFlag | resizeToParentWidth_WidgetFlag | 94 { uiTextAction_ColorEscape "${dlg.upload.send}", SDLK_RETURN, KMOD_PRIMARY, "upload.accept" }
96 fixedHeight_WidgetFlag); 95 };
97 setWrap_LabelWidget(d->info, iTrue); 96 if (isUsingPanelLayout_Mobile()) {
98 /* Tabs for input data. */ 97 const iMenuItem textItems[] = {
99 iWidget *tabs = makeTabs_Widget(w); 98 { "title id:heading.upload.text" },
100 /* Make the tabs support vertical expansion based on content. */ { 99 { "input id:upload.text noheading:1" },
101 setFlags_Widget(tabs, resizeHeightOfChildren_WidgetFlag, iFalse); 100 { NULL }
102 setFlags_Widget(tabs, arrangeHeight_WidgetFlag, iTrue); 101 };
103 iWidget *tabPages = findChild_Widget(tabs, "tabs.pages"); 102 const iMenuItem fileItems[] = {
104 setFlags_Widget(tabPages, resizeHeightOfChildren_WidgetFlag, iFalse); 103 { "title id:heading.upload.file" },
105 setFlags_Widget(tabPages, arrangeHeight_WidgetFlag, iTrue); 104 { "button text:" uiTextAction_ColorEscape "${dlg.upload.pickfile}", 0, 0, "upload.pickfile" },
105 { "heading id:upload.file.name" },
106 { "label id:upload.filepathlabel" },
107 { "heading id:upload.file.size" },
108 { "label id:upload.filesizelabel" },
109 { "padding" },
110 { "input id:upload.mime" },
111 { "label id:upload.counter text:" },
112 { NULL }
113 };
114 initPanels_Mobile(w, NULL, (iMenuItem[]){
115 { "title id:heading.upload" },
116 { "label id:upload.info" },
117// { "padding" },
118 { "panel id:dlg.upload.text icon:0x1f5b9", 0, 0, (const void *) textItems },
119 { "panel id:dlg.upload.file icon:0x1f4c1", 0, 0, (const void *) fileItems },
120 { "padding" },
121 { "input id:upload.token hint:hint.upload.token" },
122 { NULL }
123 }, actions, iElemCount(actions));
124 d->info = findChild_Widget(w, "upload.info");
125 d->input = findChild_Widget(w, "upload.text");
126 d->filePathLabel = findChild_Widget(w, "upload.file.name");
127 d->fileSizeLabel = findChild_Widget(w, "upload.file.size");
128 d->mime = findChild_Widget(w, "upload.mime");
129 d->token = findChild_Widget(w, "upload.token");
130 d->counter = findChild_Widget(w, "upload.counter");
106 } 131 }
107 iWidget *headings, *values; 132 else {
108 setBackgroundColor_Widget(findChild_Widget(tabs, "tabs.buttons"), uiBackgroundSidebar_ColorId); 133 useSheetStyle_Widget(w);
109 setId_Widget(tabs, "upload.tabs"); 134 addChildFlags_Widget(w,
110// const int bigGap = lineHeight_Text(uiLabel_FontId) * 3 / 4; 135 iClob(new_LabelWidget(uiHeading_ColorEscape "${heading.upload}", NULL)),
111 /* Text input. */ { 136 frameless_WidgetFlag);
112 //appendTwoColumnTabPage_Widget(tabs, "${heading.upload.text}", '1', &headings, &values); 137 d->info = addChildFlags_Widget(w, iClob(new_LabelWidget("", NULL)),
113 iWidget *page = new_Widget(); 138 frameless_WidgetFlag | resizeToParentWidth_WidgetFlag |
114 setFlags_Widget(page, arrangeSize_WidgetFlag, iTrue); 139 fixedHeight_WidgetFlag);
115 d->input = new_InputWidget(0); 140 setWrap_LabelWidget(d->info, iTrue);
116 setId_Widget(as_Widget(d->input), "upload.text"); 141 /* Tabs for input data. */
117 setFont_InputWidget(d->input, monospace_FontId); 142 iWidget *tabs = makeTabs_Widget(w);
118 setLineLimits_InputWidget(d->input, 7, 20); 143 /* Make the tabs support vertical expansion based on content. */ {
119 setUseReturnKeyBehavior_InputWidget(d->input, iFalse); /* traditional text editor */ 144 setFlags_Widget(tabs, resizeHeightOfChildren_WidgetFlag, iFalse);
120 setHint_InputWidget(d->input, "${hint.upload.text}"); 145 setFlags_Widget(tabs, arrangeHeight_WidgetFlag, iTrue);
121 setFixedSize_Widget(as_Widget(d->input), init_I2(120 * gap_UI, -1)); 146 iWidget *tabPages = findChild_Widget(tabs, "tabs.pages");
122 addChild_Widget(page, iClob(d->input)); 147 setFlags_Widget(tabPages, resizeHeightOfChildren_WidgetFlag, iFalse);
123 appendFramelessTabPage_Widget(tabs, iClob(page), "${heading.upload.text}", '1', 0); 148 setFlags_Widget(tabPages, arrangeHeight_WidgetFlag, iTrue);
124 } 149 }
125 /* File content. */ { 150 iWidget *headings, *values;
126 appendTwoColumnTabPage_Widget(tabs, "${heading.upload.file}", '2', &headings, &values); 151 setBackgroundColor_Widget(findChild_Widget(tabs, "tabs.buttons"), uiBackgroundSidebar_ColorId);
127// iWidget *pad = addChild_Widget(headings, iClob(makePadding_Widget(0))); 152 setId_Widget(tabs, "upload.tabs");
128// iWidget *hint = addChild_Widget(values, iClob(new_LabelWidget("${upload.file.drophint}", NULL))); 153 /* Text input. */ {
129// pad->sizeRef = hint; 154 iWidget *page = new_Widget();
130 addChildFlags_Widget(headings, iClob(new_LabelWidget("${upload.file.name}", NULL)), frameless_WidgetFlag); 155 setFlags_Widget(page, arrangeSize_WidgetFlag, iTrue);
131 d->filePathLabel = addChildFlags_Widget(values, iClob(new_LabelWidget(uiTextAction_ColorEscape "${upload.file.drophere}", NULL)), frameless_WidgetFlag); 156 d->input = new_InputWidget(0);
132 addChildFlags_Widget(headings, iClob(new_LabelWidget("${upload.file.size}", NULL)), frameless_WidgetFlag); 157 setId_Widget(as_Widget(d->input), "upload.text");
133 d->fileSizeLabel = addChildFlags_Widget(values, iClob(new_LabelWidget("\u2014", NULL)), frameless_WidgetFlag); 158 setFixedSize_Widget(as_Widget(d->input), init_I2(120 * gap_UI, -1));
134 d->mime = new_InputWidget(0); 159 addChild_Widget(page, iClob(d->input));
135 setFixedSize_Widget(as_Widget(d->mime), init_I2(70 * gap_UI, -1)); 160 appendFramelessTabPage_Widget(tabs, iClob(page), "${heading.upload.text}", '1', 0);
136 addTwoColumnDialogInputField_Widget(headings, values, "${upload.mime}", "upload.mime", iClob(d->mime)); 161 }
137 } 162 /* File content. */ {
138 /* Token. */ { 163 appendTwoColumnTabPage_Widget(tabs, "${heading.upload.file}", '2', &headings, &values);
139 addChild_Widget(w, iClob(makePadding_Widget(gap_UI))); 164 addChildFlags_Widget(headings, iClob(new_LabelWidget("${upload.file.name}", NULL)), frameless_WidgetFlag);
140 iWidget *page = makeTwoColumns_Widget(&headings, &values); 165 d->filePathLabel = addChildFlags_Widget(values, iClob(new_LabelWidget(uiTextAction_ColorEscape "${upload.file.drophere}", NULL)), frameless_WidgetFlag);
141 d->token = addTwoColumnDialogInputField_Widget( 166 addChildFlags_Widget(headings, iClob(new_LabelWidget("${upload.file.size}", NULL)), frameless_WidgetFlag);
142 headings, values, "${upload.token}", "upload.token", iClob(new_InputWidget(0))); 167 d->fileSizeLabel = addChildFlags_Widget(values, iClob(new_LabelWidget("\u2014", NULL)), frameless_WidgetFlag);
143 setHint_InputWidget(d->token, "${hint.upload.token}"); 168 d->mime = new_InputWidget(0);
144 setFixedSize_Widget(as_Widget(d->token), init_I2(50 * gap_UI, -1)); 169 setFixedSize_Widget(as_Widget(d->mime), init_I2(70 * gap_UI, -1));
145 addChild_Widget(w, iClob(page)); 170 addTwoColumnDialogInputField_Widget(headings, values, "${upload.mime}", "upload.mime", iClob(d->mime));
146 } 171 }
147 /* Buttons. */ { 172 /* Token. */ {
148 addChild_Widget(w, iClob(makePadding_Widget(gap_UI))); 173 addChild_Widget(w, iClob(makePadding_Widget(gap_UI)));
149 iWidget *buttons = 174 iWidget *page = makeTwoColumns_Widget(&headings, &values);
150 makeDialogButtons_Widget((iMenuItem[]){ { "${upload.port}", 0, 0, "upload.setport" }, 175 d->token = addTwoColumnDialogInputField_Widget(
151 { "---" }, 176 headings, values, "${upload.token}", "upload.token", iClob(new_InputWidget(0)));
152 { "${close}", SDLK_ESCAPE, 0, "upload.cancel" }, 177 setHint_InputWidget(d->token, "${hint.upload.token}");
153 { uiTextAction_ColorEscape "${dlg.upload.send}", 178 setFixedSize_Widget(as_Widget(d->token), init_I2(50 * gap_UI, -1));
154 SDLK_RETURN, 179 addChild_Widget(w, iClob(page));
155 KMOD_PRIMARY, 180 }
156 "upload.accept" } }, 181 /* Buttons. */ {
157 4); 182 addChild_Widget(w, iClob(makePadding_Widget(gap_UI)));
158 setId_Widget(insertChildAfterFlags_Widget(buttons, 183 iWidget *buttons = makeDialogButtons_Widget(actions, iElemCount(actions));
159 iClob(d->counter = new_LabelWidget("", NULL)), 184 setId_Widget(insertChildAfterFlags_Widget(buttons,
160 0, frameless_WidgetFlag), 185 iClob(d->counter = new_LabelWidget("", NULL)),
161 "upload.counter"); 186 0, frameless_WidgetFlag),
162 addChild_Widget(w, iClob(buttons)); 187 "upload.counter");
188 addChild_Widget(w, iClob(buttons));
189 }
190 resizeToLargestPage_Widget(tabs);
191 arrange_Widget(w);
192 setFixedSize_Widget(as_Widget(d->token), init_I2(width_Widget(tabs) - left_Rect(parent_Widget(d->token)->rect), -1));
193 setFlags_Widget(as_Widget(d->token), expand_WidgetFlag, iTrue);
194 setFocus_Widget(as_Widget(d->input));
163 } 195 }
164 resizeToLargestPage_Widget(tabs); 196 setFont_InputWidget(d->input, monospace_FontId);
165 arrange_Widget(w); 197 setUseReturnKeyBehavior_InputWidget(d->input, iFalse); /* traditional text editor */
166 setFixedSize_Widget(as_Widget(d->token), init_I2(width_Widget(tabs) - left_Rect(parent_Widget(d->token)->rect), -1)); 198 setLineLimits_InputWidget(d->input, 7, 20);
167 setFlags_Widget(as_Widget(d->token), expand_WidgetFlag, iTrue); 199 setHint_InputWidget(d->input, "${hint.upload.text}");
168 setFocus_Widget(as_Widget(d->input));
169 setBackupFileName_InputWidget(d->input, "uploadbackup.txt"); 200 setBackupFileName_InputWidget(d->input, "uploadbackup.txt");
170 updateInputMaxHeight_UploadWidget_(d); 201 updateInputMaxHeight_UploadWidget_(d);
171} 202}
@@ -201,6 +232,7 @@ static void setUrlPort_UploadWidget_(iUploadWidget *d, const iString *url, uint1
201 appendFormat_String(&d->url, ":%u", overridePort ? overridePort : titanPortForUrl_(url)); 232 appendFormat_String(&d->url, ":%u", overridePort ? overridePort : titanPortForUrl_(url));
202 appendRange_String(&d->url, (iRangecc){ parts.path.start, constEnd_String(url) }); 233 appendRange_String(&d->url, (iRangecc){ parts.path.start, constEnd_String(url) });
203 setText_LabelWidget(d->info, &d->url); 234 setText_LabelWidget(d->info, &d->url);
235 arrange_Widget(as_Widget(d));
204} 236}
205 237
206void setUrl_UploadWidget(iUploadWidget *d, const iString *url) { 238void setUrl_UploadWidget(iUploadWidget *d, const iString *url) {
@@ -233,7 +265,7 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
233 if (isResize_UserEvent(ev)) { 265 if (isResize_UserEvent(ev)) {
234 updateInputMaxHeight_UploadWidget_(d); 266 updateInputMaxHeight_UploadWidget_(d);
235 } 267 }
236 if (isCommand_Widget(w, ev, "upload.cancel")) { 268 if (equal_Command(cmd, "upload.cancel")) {
237 setupSheetTransition_Mobile(w, iFalse); 269 setupSheetTransition_Mobile(w, iFalse);
238 destroy_Widget(w); 270 destroy_Widget(w);
239 return iTrue; 271 return iTrue;
diff --git a/src/ui/util.c b/src/ui/util.c
index b875e260..6069e800 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -1061,6 +1061,7 @@ iWidget *removeTabPage_Widget(iWidget *tabs, size_t index) {
1061} 1061}
1062 1062
1063void resizeToLargestPage_Widget(iWidget *tabs) { 1063void resizeToLargestPage_Widget(iWidget *tabs) {
1064 if (!tabs) return;
1064// puts("RESIZE TO LARGEST PAGE ..."); 1065// puts("RESIZE TO LARGEST PAGE ...");
1065 iWidget *pages = findChild_Widget(tabs, "tabs.pages"); 1066 iWidget *pages = findChild_Widget(tabs, "tabs.pages");
1066 iForEach(ObjectList, i, children_Widget(pages)) { 1067 iForEach(ObjectList, i, children_Widget(pages)) {
@@ -1216,7 +1217,7 @@ iBool valueInputHandler_(iWidget *dlg, const char *cmd) {
1216 postCommandf_App("valueinput.cancelled id:%s", cstr_String(id_Widget(dlg))); 1217 postCommandf_App("valueinput.cancelled id:%s", cstr_String(id_Widget(dlg)));
1217 setId_Widget(dlg, ""); /* no further commands to emit */ 1218 setId_Widget(dlg, ""); /* no further commands to emit */
1218 } 1219 }
1219 setupSheetTransition_Mobile(dlg, iFalse); 1220 setupSheetTransition_Mobile(dlg, top_TransitionDir);
1220 destroy_Widget(dlg); 1221 destroy_Widget(dlg);
1221 return iTrue; 1222 return iTrue;
1222 } 1223 }
@@ -1225,13 +1226,13 @@ iBool valueInputHandler_(iWidget *dlg, const char *cmd) {
1225 else if (equal_Command(cmd, "valueinput.cancel")) { 1226 else if (equal_Command(cmd, "valueinput.cancel")) {
1226 postCommandf_App("valueinput.cancelled id:%s", cstr_String(id_Widget(dlg))); 1227 postCommandf_App("valueinput.cancelled id:%s", cstr_String(id_Widget(dlg)));
1227 setId_Widget(dlg, ""); /* no further commands to emit */ 1228 setId_Widget(dlg, ""); /* no further commands to emit */
1228 setupSheetTransition_Mobile(dlg, iFalse); 1229 setupSheetTransition_Mobile(dlg, top_TransitionDir);
1229 destroy_Widget(dlg); 1230 destroy_Widget(dlg);
1230 return iTrue; 1231 return iTrue;
1231 } 1232 }
1232 else if (equal_Command(cmd, "valueinput.accept")) { 1233 else if (equal_Command(cmd, "valueinput.accept")) {
1233 acceptValueInput_(dlg); 1234 acceptValueInput_(dlg);
1234 setupSheetTransition_Mobile(dlg, iFalse); 1235 setupSheetTransition_Mobile(dlg, top_TransitionDir);
1235 destroy_Widget(dlg); 1236 destroy_Widget(dlg);
1236 return iTrue; 1237 return iTrue;
1237 } 1238 }
@@ -1345,7 +1346,9 @@ iWidget *makeValueInput_Widget(iWidget *parent, const iString *initialValue, con
1345 acceptKeyMod_ReturnKeyBehavior(prefs_App()->returnKey), 1346 acceptKeyMod_ReturnKeyBehavior(prefs_App()->returnKey),
1346 "valueinput.accept" } }, 1347 "valueinput.accept" } },
1347 2))); 1348 2)));
1348 finalizeSheet_Mobile(dlg); 1349// finalizeSheet_Mobile(dlg);
1350 arrange_Widget(dlg);
1351 setupSheetTransition_Mobile(dlg, incoming_TransitionFlag | top_TransitionDir);
1349 if (parent) { 1352 if (parent) {
1350 setFocus_Widget(as_Widget(input)); 1353 setFocus_Widget(as_Widget(input));
1351 } 1354 }
@@ -1915,6 +1918,7 @@ iWidget *makePreferences_Widget(void) {
1915 { NULL } 1918 { NULL }
1916 }; 1919 };
1917 iWidget *dlg = makePanels_Mobile("prefs", (iMenuItem[]){ 1920 iWidget *dlg = makePanels_Mobile("prefs", (iMenuItem[]){
1921 { "title id:heading.settings" },
1918 { "panel text:" gear_Icon " ${heading.prefs.general}", 0, 0, (const void *) generalPanelItems }, 1922 { "panel text:" gear_Icon " ${heading.prefs.general}", 0, 0, (const void *) generalPanelItems },
1919 { "panel icon:0x1f5a7 id:heading.prefs.network", 0, 0, (const void *) networkPanelItems }, 1923 { "panel icon:0x1f5a7 id:heading.prefs.network", 0, 0, (const void *) networkPanelItems },
1920 { "panel text:" person_Icon " ${sidebar.identities}", 0, 0, (const void *) identityPanelItems }, 1924 { "panel text:" person_Icon " ${sidebar.identities}", 0, 0, (const void *) identityPanelItems },
@@ -2405,7 +2409,7 @@ iWidget *makeFeedSettings_Widget(uint32_t bookmarkId) {
2405 arrange_Widget(dlg); 2409 arrange_Widget(dlg);
2406 as_Widget(input)->rect.size.x = 100 * gap_UI - headings->rect.size.x; 2410 as_Widget(input)->rect.size.x = 100 * gap_UI - headings->rect.size.x;
2407 addChild_Widget(get_Root()->widget, iClob(dlg)); 2411 addChild_Widget(get_Root()->widget, iClob(dlg));
2408 finalizeSheet_Mobile(dlg); 2412// finalizeSheet_Mobile(dlg);
2409 } 2413 }
2410 /* Initialize. */ { 2414 /* Initialize. */ {
2411 const iBookmark *bm = bookmarkId ? get_Bookmarks(bookmarks_App(), bookmarkId) : NULL; 2415 const iBookmark *bm = bookmarkId ? get_Bookmarks(bookmarks_App(), bookmarkId) : NULL;
@@ -2419,6 +2423,7 @@ iWidget *makeFeedSettings_Widget(uint32_t bookmarkId) {
2419 iTrue); 2423 iTrue);
2420 setCommandHandler_Widget(dlg, handleFeedSettingCommands_); 2424 setCommandHandler_Widget(dlg, handleFeedSettingCommands_);
2421 } 2425 }
2426 setupSheetTransition_Mobile(dlg, incoming_TransitionFlag);
2422 return dlg; 2427 return dlg;
2423} 2428}
2424 2429
diff --git a/src/ui/widget.c b/src/ui/widget.c
index 4fd8f066..659a00cc 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -452,7 +452,7 @@ static void arrange_Widget_(iWidget *d) {
452 else if (d->flags & centerHorizontal_WidgetFlag) { 452 else if (d->flags & centerHorizontal_WidgetFlag) {
453 centerHorizontal_Widget_(d); 453 centerHorizontal_Widget_(d);
454 } 454 }
455 if (d->flags & resizeToParentWidth_WidgetFlag) { 455 if (d->flags & resizeToParentWidth_WidgetFlag && d->parent) {
456 iRect childBounds = zero_Rect(); 456 iRect childBounds = zero_Rect();
457 if (flags_Widget(d->parent) & arrangeWidth_WidgetFlag) { 457 if (flags_Widget(d->parent) & arrangeWidth_WidgetFlag) {
458 /* Can't go narrower than what the children require, though. */ 458 /* Can't go narrower than what the children require, though. */
@@ -462,7 +462,7 @@ static void arrange_Widget_(iWidget *d) {
462 setWidth_Widget_(d, iMaxi(width_Rect(innerRect_Widget_(d->parent)), 462 setWidth_Widget_(d, iMaxi(width_Rect(innerRect_Widget_(d->parent)),
463 width_Rect(childBounds))); 463 width_Rect(childBounds)));
464 } 464 }
465 if (d->flags & resizeToParentHeight_WidgetFlag) { 465 if (d->flags & resizeToParentHeight_WidgetFlag && d->parent) {
466 TRACE(d, "resize to parent height"); 466 TRACE(d, "resize to parent height");
467 setHeight_Widget_(d, height_Rect(innerRect_Widget_(d->parent))); 467 setHeight_Widget_(d, height_Rect(innerRect_Widget_(d->parent)));
468 } 468 }