diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-05-15 22:38:13 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-05-15 22:38:13 +0300 |
commit | afce90c9f6b52db97de29824d1afd1a0742550df (patch) | |
tree | c22eeafe577995215ef6edf448a35f8d8328cb8d /src/ui | |
parent | d268545d12db5b02ee5975acb311d5b3cd875d6a (diff) |
Mobile: Various improvements and fixes
- fill the safe area with theme background
- don't set button hover states if dragging/scrolling
- edge-draggable widgets must be flagged as such
- Preferences top panel offset matches sibling panels' offset
- allow toolbar to unhide when document is not scrollable
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/documentwidget.c | 4 | ||||
-rw-r--r-- | src/ui/labelwidget.c | 14 | ||||
-rw-r--r-- | src/ui/root.c | 1 | ||||
-rw-r--r-- | src/ui/sidebarwidget.c | 1 | ||||
-rw-r--r-- | src/ui/touch.c | 18 | ||||
-rw-r--r-- | src/ui/touch.h | 1 | ||||
-rw-r--r-- | src/ui/util.c | 83 | ||||
-rw-r--r-- | src/ui/util.h | 7 | ||||
-rw-r--r-- | src/ui/widget.c | 64 | ||||
-rw-r--r-- | src/ui/widget.h | 6 | ||||
-rw-r--r-- | src/ui/window.c | 7 |
11 files changed, 168 insertions, 38 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 23731105..ea86a810 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1444,8 +1444,8 @@ static void scrollBegan_DocumentWidget_(iAnyObject *any, int offset, uint32_t du | |||
1444 | } | 1444 | } |
1445 | /* Show and hide toolbar on scroll. */ | 1445 | /* Show and hide toolbar on scroll. */ |
1446 | if (deviceType_App() == phone_AppDeviceType) { | 1446 | if (deviceType_App() == phone_AppDeviceType) { |
1447 | if (prefs_App()->hideToolbarOnScroll && iAbs(offset) > 5 && | 1447 | const float normPos = normScrollPos_DocumentWidget_(d); |
1448 | normScrollPos_DocumentWidget_(d) > 0) { | 1448 | if (prefs_App()->hideToolbarOnScroll && iAbs(offset) > 5 && normPos >= 0) { |
1449 | showToolbars_Root(as_Widget(d)->root, offset < 0); | 1449 | showToolbars_Root(as_Widget(d)->root, offset < 0); |
1450 | } | 1450 | } |
1451 | } | 1451 | } |
diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 5d0f0041..44ed795b 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c | |||
@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
28 | #include "app.h" | 28 | #include "app.h" |
29 | #include "util.h" | 29 | #include "util.h" |
30 | #include "keys.h" | 30 | #include "keys.h" |
31 | #include "touch.h" | ||
31 | 32 | ||
32 | struct Impl_LabelWidget { | 33 | struct Impl_LabelWidget { |
33 | iWidget widget; | 34 | iWidget widget; |
@@ -46,6 +47,15 @@ struct Impl_LabelWidget { | |||
46 | } flags; | 47 | } flags; |
47 | }; | 48 | }; |
48 | 49 | ||
50 | static iBool isHover_LabelWidget_(const iLabelWidget *d) { | ||
51 | #if defined (iPlatformMobile) | ||
52 | if (!isHovering_Touch()) { | ||
53 | return iFalse; | ||
54 | } | ||
55 | #endif | ||
56 | return isHover_Widget(d); | ||
57 | } | ||
58 | |||
49 | static iInt2 padding_LabelWidget_(const iLabelWidget *d, int corner) { | 59 | static iInt2 padding_LabelWidget_(const iLabelWidget *d, int corner) { |
50 | const iWidget *w = constAs_Widget(d); | 60 | const iWidget *w = constAs_Widget(d); |
51 | const int64_t flags = flags_Widget(w); | 61 | const int64_t flags = flags_Widget(w); |
@@ -199,7 +209,7 @@ static void getColors_LabelWidget_(const iLabelWidget *d, int *bg, int *fg, int | |||
199 | if (startsWith_String(&d->label, "\r")) { | 209 | if (startsWith_String(&d->label, "\r")) { |
200 | colorEscape = cstr_String(&d->label)[1] - asciiBase_ColorEscape; /* TODO: can be two bytes long */ | 210 | colorEscape = cstr_String(&d->label)[1] - asciiBase_ColorEscape; /* TODO: can be two bytes long */ |
201 | } | 211 | } |
202 | if (isHover_Widget(w)) { | 212 | if (isHover_LabelWidget_(d)) { |
203 | if (isFrameless) { | 213 | if (isFrameless) { |
204 | *bg = uiBackgroundFramelessHover_ColorId; | 214 | *bg = uiBackgroundFramelessHover_ColorId; |
205 | *fg = uiTextFramelessHover_ColorId; | 215 | *fg = uiTextFramelessHover_ColorId; |
@@ -257,7 +267,7 @@ static void draw_LabelWidget_(const iLabelWidget *d) { | |||
257 | const int64_t flags = flags_Widget(w); | 267 | const int64_t flags = flags_Widget(w); |
258 | const iRect bounds = bounds_Widget(w); | 268 | const iRect bounds = bounds_Widget(w); |
259 | iRect rect = bounds; | 269 | iRect rect = bounds; |
260 | const iBool isHover = isHover_Widget(w); | 270 | const iBool isHover = isHover_LabelWidget_(d); |
261 | if (isButton) { | 271 | if (isButton) { |
262 | shrink_Rect(&rect, divi_I2(gap2_UI, 4)); | 272 | shrink_Rect(&rect, divi_I2(gap2_UI, 4)); |
263 | adjustEdges_Rect(&rect, gap_UI / 8, 0, -gap_UI / 8, 0); | 273 | adjustEdges_Rect(&rect, gap_UI / 8, 0, -gap_UI / 8, 0); |
diff --git a/src/ui/root.c b/src/ui/root.c index 233de51c..913f82e9 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -350,6 +350,7 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { | |||
350 | } | 350 | } |
351 | else if (equal_Command(cmd, "input.resized")) { | 351 | else if (equal_Command(cmd, "input.resized")) { |
352 | /* No parent handled this, so do a full rearrangement. */ | 352 | /* No parent handled this, so do a full rearrangement. */ |
353 | /* TODO: Defer this and do a single rearrangement later. */ | ||
353 | arrange_Widget(root); | 354 | arrange_Widget(root); |
354 | postRefresh_App(); | 355 | postRefresh_App(); |
355 | return iTrue; | 356 | return iTrue; |
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 2c7ee75f..5d51b144 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -555,7 +555,6 @@ static void updateMetrics_SidebarWidget_(iSidebarWidget *d) { | |||
555 | .x); | 555 | .x); |
556 | } | 556 | } |
557 | } | 557 | } |
558 | printf("maxButtonLabelWidth: %d\n", d->maxButtonLabelWidth); | ||
559 | updateItemHeight_SidebarWidget_(d); | 558 | updateItemHeight_SidebarWidget_(d); |
560 | } | 559 | } |
561 | 560 | ||
diff --git a/src/ui/touch.c b/src/ui/touch.c index f1aa8f06..c373ebd3 100644 --- a/src/ui/touch.c +++ b/src/ui/touch.c | |||
@@ -340,7 +340,7 @@ static void update_TouchState_(void *ptr) { | |||
340 | 340 | ||
341 | static iWidget *findSlidePanel_Widget_(iWidget *d) { | 341 | static iWidget *findSlidePanel_Widget_(iWidget *d) { |
342 | for (iWidget *w = d; w; w = parent_Widget(w)) { | 342 | for (iWidget *w = d; w; w = parent_Widget(w)) { |
343 | if (isVisible_Widget(w) && flags_Widget(w) & horizontalOffset_WidgetFlag) { | 343 | if (isVisible_Widget(w) && flags_Widget(w) & edgeDraggable_WidgetFlag) { |
344 | return w; | 344 | return w; |
345 | } | 345 | } |
346 | } | 346 | } |
@@ -453,6 +453,8 @@ iBool processEvent_Touch(const SDL_Event *ev) { | |||
453 | if (edge == left_TouchEdge) { | 453 | if (edge == left_TouchEdge) { |
454 | dragging = findSlidePanel_Widget_(aff); | 454 | dragging = findSlidePanel_Widget_(aff); |
455 | if (dragging) { | 455 | if (dragging) { |
456 | printf("Selected for dragging: "); | ||
457 | identify_Widget(dragging); | ||
456 | setFlags_Widget(dragging, dragged_WidgetFlag, iTrue); | 458 | setFlags_Widget(dragging, dragged_WidgetFlag, iTrue); |
457 | } | 459 | } |
458 | } | 460 | } |
@@ -745,6 +747,20 @@ iInt2 latestPosition_Touch(void) { | |||
745 | return touchState_()->currentTouchPos; | 747 | return touchState_()->currentTouchPos; |
746 | } | 748 | } |
747 | 749 | ||
750 | iBool isHovering_Touch(void) { | ||
751 | iTouchState *d = touchState_(); | ||
752 | if (numFingers_Touch() == 1) { | ||
753 | const iTouch *touch = constFront_Array(d->touches); | ||
754 | if (touch->isTapBegun && isStationary_Touch_(touch)) { | ||
755 | return iTrue; | ||
756 | } | ||
757 | if (touch->isTapAndHold) { | ||
758 | return iTrue; | ||
759 | } | ||
760 | } | ||
761 | return iFalse; | ||
762 | } | ||
763 | |||
748 | size_t numFingers_Touch(void) { | 764 | size_t numFingers_Touch(void) { |
749 | return size_Array(touchState_()->touches); | 765 | return size_Array(touchState_()->touches); |
750 | } | 766 | } |
diff --git a/src/ui/touch.h b/src/ui/touch.h index 1a6fb350..e048224a 100644 --- a/src/ui/touch.h +++ b/src/ui/touch.h | |||
@@ -41,4 +41,5 @@ enum iWidgetTouchMode widgetMode_Touch (const iWidget *widget); | |||
41 | void widgetDestroyed_Touch (iWidget *widget); | 41 | void widgetDestroyed_Touch (iWidget *widget); |
42 | 42 | ||
43 | iInt2 latestPosition_Touch (void); /* valid during processing of current event */ | 43 | iInt2 latestPosition_Touch (void); /* valid during processing of current event */ |
44 | iBool isHovering_Touch (void); /* stationary touch or a long-press drag ongoing */ | ||
44 | size_t numFingers_Touch (void); | 45 | size_t numFingers_Touch (void); |
diff --git a/src/ui/util.c b/src/ui/util.c index fe35031b..e653b58c 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -837,7 +837,7 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) { | |||
837 | if (postCommands) { | 837 | if (postCommands) { |
838 | postCommand_Widget(d, "menu.opened"); | 838 | postCommand_Widget(d, "menu.opened"); |
839 | } | 839 | } |
840 | if (isPortraitPhone) { | 840 | if (deviceType_App() == phone_AppDeviceType) { |
841 | setVisualOffset_Widget(d, isSlidePanel ? width_Widget(d) : height_Widget(d), 0, 0); | 841 | setVisualOffset_Widget(d, isSlidePanel ? width_Widget(d) : height_Widget(d), 0, 0); |
842 | setVisualOffset_Widget(d, 0, 330, easeOut_AnimFlag | softer_AnimFlag); | 842 | setVisualOffset_Widget(d, 0, 330, easeOut_AnimFlag | softer_AnimFlag); |
843 | } | 843 | } |
@@ -851,7 +851,7 @@ void closeMenu_Widget(iWidget *d) { | |||
851 | setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iTrue); | 851 | setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iTrue); |
852 | postRefresh_App(); | 852 | postRefresh_App(); |
853 | postCommand_Widget(d, "menu.closed"); | 853 | postCommand_Widget(d, "menu.closed"); |
854 | if (isPortrait_App() && deviceType_App() == phone_AppDeviceType) { | 854 | if (deviceType_App() == phone_AppDeviceType) { |
855 | const iBool wasDragged = iAbs(value_Anim(&d->visualOffset) - 0) > 1; | 855 | const iBool wasDragged = iAbs(value_Anim(&d->visualOffset) - 0) > 1; |
856 | setVisualOffset_Widget(d, | 856 | setVisualOffset_Widget(d, |
857 | flags_Widget(d) & horizontalOffset_WidgetFlag ? | 857 | flags_Widget(d) & horizontalOffset_WidgetFlag ? |
@@ -1206,7 +1206,13 @@ static iBool slidePanelHandler_(iWidget *d, const char *cmd) { | |||
1206 | iWidget *panel = userData_Object(button); | 1206 | iWidget *panel = userData_Object(button); |
1207 | openMenu_Widget(panel, innerToWindow_Widget(panel, zero_I2())); | 1207 | openMenu_Widget(panel, innerToWindow_Widget(panel, zero_I2())); |
1208 | setFlags_Widget(panel, disabled_WidgetFlag, iFalse); | 1208 | setFlags_Widget(panel, disabled_WidgetFlag, iFalse); |
1209 | // updateTextCStr_LabelWidget(findWidget_App("panel.back"), ); | 1209 | /* |
1210 | if (deviceType_App() == phone_AppDeviceType && isPortrait_App()) { | ||
1211 | setFlags_Widget(d, visualOffset_WidgetFlag | horizontalOffset_WidgetFlag, iTrue); | ||
1212 | d->visualOffset = panel->visualOffset; | ||
1213 | d->visualOffset.to = -d->visualOffset.from / 3; | ||
1214 | d->visualOffset.from = 0; | ||
1215 | }*/ | ||
1210 | return iTrue; | 1216 | return iTrue; |
1211 | } | 1217 | } |
1212 | if (equal_Command(cmd, "mouse.clicked") && arg_Command(cmd) && | 1218 | if (equal_Command(cmd, "mouse.clicked") && arg_Command(cmd) && |
@@ -1220,6 +1226,13 @@ static iBool slidePanelHandler_(iWidget *d, const char *cmd) { | |||
1220 | iWidget *child = i.object; | 1226 | iWidget *child = i.object; |
1221 | if (!cmp_String(id_Widget(child), "panel") && isVisible_Widget(child)) { | 1227 | if (!cmp_String(id_Widget(child), "panel") && isVisible_Widget(child)) { |
1222 | closeMenu_Widget(child); | 1228 | closeMenu_Widget(child); |
1229 | /* | ||
1230 | if (deviceType_App() == phone_AppDeviceType && isPortrait_App()) { | ||
1231 | setFlags_Widget(d, visualOffset_WidgetFlag | horizontalOffset_WidgetFlag, iTrue); | ||
1232 | d->visualOffset = child->visualOffset; | ||
1233 | d->visualOffset.from = -d->visualOffset.to / 3; | ||
1234 | d->visualOffset.to = 0; | ||
1235 | }*/ | ||
1223 | setFlags_Widget(child, disabled_WidgetFlag, iTrue); | 1236 | setFlags_Widget(child, disabled_WidgetFlag, iTrue); |
1224 | setFocus_Widget(NULL); | 1237 | setFocus_Widget(NULL); |
1225 | updateTextCStr_LabelWidget(findWidget_App("panel.back"), "Back"); | 1238 | updateTextCStr_LabelWidget(findWidget_App("panel.back"), "Back"); |
@@ -1373,6 +1386,15 @@ static iWidget *makeValuePaddingWithHeading_(iLabelWidget *heading, iWidget *val | |||
1373 | if (isInstance_Object(value, &Class_InputWidget)) { | 1386 | if (isInstance_Object(value, &Class_InputWidget)) { |
1374 | addChildFlags_Widget(div, iClob(value), expand_WidgetFlag); | 1387 | addChildFlags_Widget(div, iClob(value), expand_WidgetFlag); |
1375 | } | 1388 | } |
1389 | else if (isInstance_Object(value, &Class_LabelWidget) && | ||
1390 | cmp_String(command_LabelWidget((iLabelWidget *) value), "toggle")) { | ||
1391 | addChildFlags_Widget(div, iClob(value), expand_WidgetFlag); | ||
1392 | /* TODO: This doesn't work? */ | ||
1393 | // setCommand_LabelWidget(heading, | ||
1394 | // collectNewFormat_String("!%s ptr:%p", | ||
1395 | // cstr_String(command_LabelWidget((iLabelWidget *) value)), | ||
1396 | // value)); | ||
1397 | } | ||
1376 | else { | 1398 | else { |
1377 | addChildFlags_Widget(div, iClob(new_Widget()), expand_WidgetFlag); | 1399 | addChildFlags_Widget(div, iClob(new_Widget()), expand_WidgetFlag); |
1378 | addChild_Widget(div, iClob(value)); | 1400 | addChild_Widget(div, iClob(value)); |
@@ -1400,7 +1422,8 @@ static iWidget *addChildPanel_(iWidget *sheet, iLabelWidget *panelButton, | |||
1400 | focusRoot_WidgetFlag | hidden_WidgetFlag | disabled_WidgetFlag | | 1422 | focusRoot_WidgetFlag | hidden_WidgetFlag | disabled_WidgetFlag | |
1401 | arrangeVertical_WidgetFlag | resizeWidthOfChildren_WidgetFlag | | 1423 | arrangeVertical_WidgetFlag | resizeWidthOfChildren_WidgetFlag | |
1402 | arrangeHeight_WidgetFlag | overflowScrollable_WidgetFlag | | 1424 | arrangeHeight_WidgetFlag | overflowScrollable_WidgetFlag | |
1403 | horizontalOffset_WidgetFlag | commandOnClick_WidgetFlag); | 1425 | horizontalOffset_WidgetFlag | edgeDraggable_WidgetFlag | |
1426 | commandOnClick_WidgetFlag); | ||
1404 | return owner; | 1427 | return owner; |
1405 | } | 1428 | } |
1406 | 1429 | ||
@@ -1433,7 +1456,8 @@ void finalizeSheet_Widget(iWidget *sheet) { | |||
1433 | setFlags_Widget(sheet, | 1456 | setFlags_Widget(sheet, |
1434 | commandOnClick_WidgetFlag | | 1457 | commandOnClick_WidgetFlag | |
1435 | frameless_WidgetFlag | | 1458 | frameless_WidgetFlag | |
1436 | resizeWidthOfChildren_WidgetFlag, | 1459 | resizeWidthOfChildren_WidgetFlag | |
1460 | edgeDraggable_WidgetFlag, | ||
1437 | iTrue); | 1461 | iTrue); |
1438 | iPtrArray * contents = collect_PtrArray(new_PtrArray()); /* two-column pages */ | 1462 | iPtrArray * contents = collect_PtrArray(new_PtrArray()); /* two-column pages */ |
1439 | iPtrArray * panelButtons = collect_PtrArray(new_PtrArray()); | 1463 | iPtrArray * panelButtons = collect_PtrArray(new_PtrArray()); |
@@ -1443,6 +1467,7 @@ void finalizeSheet_Widget(iWidget *sheet) { | |||
1443 | const int64_t panelButtonFlags = borderBottom_WidgetFlag | alignLeft_WidgetFlag | | 1467 | const int64_t panelButtonFlags = borderBottom_WidgetFlag | alignLeft_WidgetFlag | |
1444 | frameless_WidgetFlag | extraPadding_WidgetFlag; | 1468 | frameless_WidgetFlag | extraPadding_WidgetFlag; |
1445 | iWidget *topPanel = new_Widget(); | 1469 | iWidget *topPanel = new_Widget(); |
1470 | setFlags_Widget(topPanel, topPanelOffset_WidgetFlag, iTrue); /* slide with children */ | ||
1446 | setId_Widget(topPanel, "panel.top"); | 1471 | setId_Widget(topPanel, "panel.top"); |
1447 | addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(defaultBig_FontId)))); | 1472 | addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(defaultBig_FontId)))); |
1448 | if (prefsTabs) { | 1473 | if (prefsTabs) { |
@@ -1493,7 +1518,8 @@ void finalizeSheet_Widget(iWidget *sheet) { | |||
1493 | const iBool useSlidePanels = (size_PtrArray(contents) == size_PtrArray(panelButtons)); | 1518 | const iBool useSlidePanels = (size_PtrArray(contents) == size_PtrArray(panelButtons)); |
1494 | addChildFlags_Widget(sheet, iClob(topPanel), | 1519 | addChildFlags_Widget(sheet, iClob(topPanel), |
1495 | arrangeVertical_WidgetFlag | | 1520 | arrangeVertical_WidgetFlag | |
1496 | resizeWidthOfChildren_WidgetFlag | arrangeHeight_WidgetFlag | | 1521 | resizeWidthOfChildren_WidgetFlag | |
1522 | arrangeHeight_WidgetFlag | | ||
1497 | overflowScrollable_WidgetFlag | | 1523 | overflowScrollable_WidgetFlag | |
1498 | commandOnClick_WidgetFlag); | 1524 | commandOnClick_WidgetFlag); |
1499 | setCommandHandler_Widget(topPanel, slidePanelHandler_); | 1525 | setCommandHandler_Widget(topPanel, slidePanelHandler_); |
@@ -1636,7 +1662,8 @@ void finalizeSheet_Widget(iWidget *sheet) { | |||
1636 | #if defined (iPlatformAppleMobile) | 1662 | #if defined (iPlatformAppleMobile) |
1637 | appendCStr_String(msg, " (" LAGRANGE_IOS_VERSION ")"); | 1663 | appendCStr_String(msg, " (" LAGRANGE_IOS_VERSION ")"); |
1638 | #endif | 1664 | #endif |
1639 | addChild_Widget(panel, iClob(new_LabelWidget(cstr_String(msg), NULL))); | 1665 | addChildFlags_Widget(panel, iClob(new_LabelWidget(cstr_String(msg), NULL)), |
1666 | frameless_WidgetFlag); | ||
1640 | addChildFlags_Widget(panel, | 1667 | addChildFlags_Widget(panel, |
1641 | iClob(makePanelButton_(globe_Icon " By @jk@skyjake.fi", | 1668 | iClob(makePanelButton_(globe_Icon " By @jk@skyjake.fi", |
1642 | "!open url:https://skyjake.fi/@jk")), | 1669 | "!open url:https://skyjake.fi/@jk")), |
@@ -2011,13 +2038,17 @@ iWidget *makeQuestion_Widget(const char *title, const char *msg, | |||
2011 | const iMenuItem *item = &items[i]; | 2038 | const iMenuItem *item = &items[i]; |
2012 | const char first = item->label[0]; | 2039 | const char first = item->label[0]; |
2013 | if (first == '*' || first == '&') { | 2040 | if (first == '*' || first == '&') { |
2014 | addChildFlags_Widget(dlg, | 2041 | iLabelWidget *option = |
2042 | addChildFlags_Widget(dlg, | ||
2015 | iClob(newKeyMods_LabelWidget(item->label + 1, | 2043 | iClob(newKeyMods_LabelWidget(item->label + 1, |
2016 | item->key, | 2044 | item->key, |
2017 | item->kmods, | 2045 | item->kmods, |
2018 | item->command)), | 2046 | item->command)), |
2019 | resizeToParentWidth_WidgetFlag | | 2047 | resizeToParentWidth_WidgetFlag | |
2020 | (first == '&' ? selected_WidgetFlag : 0)); | 2048 | (first == '&' ? selected_WidgetFlag : 0)); |
2049 | if (deviceType_App() != desktop_AppDeviceType) { | ||
2050 | setFont_LabelWidget(option, defaultBig_FontId); | ||
2051 | } | ||
2021 | } | 2052 | } |
2022 | } | 2053 | } |
2023 | addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); | 2054 | addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); |
@@ -2225,6 +2256,23 @@ static void addPrefsInputWithHeading_(iWidget *headings, iWidget *values, | |||
2225 | addDialogInputWithHeading_(headings, values, format_CStr("${%s}", id), id, input); | 2256 | addDialogInputWithHeading_(headings, values, format_CStr("${%s}", id), id, input); |
2226 | } | 2257 | } |
2227 | 2258 | ||
2259 | void setupSheetTransition_Widget(iWidget *sheet, iBool isIncoming) { | ||
2260 | if (deviceType_App() == phone_AppDeviceType && isPortrait_App()) { | ||
2261 | identify_Widget(sheet); | ||
2262 | /* View transition. */ | ||
2263 | if (isIncoming) { | ||
2264 | setFlags_Widget(sheet, horizontalOffset_WidgetFlag, iTrue); | ||
2265 | setVisualOffset_Widget(sheet, size_Root(sheet->root).x, 0, 0); | ||
2266 | setVisualOffset_Widget(sheet, 0, 200, easeOut_AnimFlag); | ||
2267 | } | ||
2268 | else { | ||
2269 | const iBool wasDragged = iAbs(value_Anim(&sheet->visualOffset)) > 0; | ||
2270 | setVisualOffset_Widget(sheet, size_Root(sheet->root).x, wasDragged ? 100 : 200, | ||
2271 | wasDragged ? 0 : easeIn_AnimFlag); | ||
2272 | } | ||
2273 | } | ||
2274 | } | ||
2275 | |||
2228 | iWidget *makePreferences_Widget(void) { | 2276 | iWidget *makePreferences_Widget(void) { |
2229 | iWidget *dlg = makeSheet_Widget("prefs"); | 2277 | iWidget *dlg = makeSheet_Widget("prefs"); |
2230 | addChildFlags_Widget(dlg, | 2278 | addChildFlags_Widget(dlg, |
@@ -2257,14 +2305,16 @@ iWidget *makePreferences_Widget(void) { | |||
2257 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.hoverlink"))); | 2305 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.hoverlink"))); |
2258 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.archive.openindex}"))); | 2306 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.archive.openindex}"))); |
2259 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.archive.openindex"))); | 2307 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.archive.openindex"))); |
2260 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.pinsplit}"))); | 2308 | if (deviceType_App() != phone_AppDeviceType) { |
2261 | iWidget *pinSplit = new_Widget(); | 2309 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.pinsplit}"))); |
2262 | /* Split mode document pinning. */ { | 2310 | iWidget *pinSplit = new_Widget(); |
2263 | addRadioButton_(pinSplit, "prefs.pinsplit.0", "${prefs.pinsplit.none}", "pinsplit.set arg:0"); | 2311 | /* Split mode document pinning. */ { |
2264 | addRadioButton_(pinSplit, "prefs.pinsplit.1", "${prefs.pinsplit.left}", "pinsplit.set arg:1"); | 2312 | addRadioButton_(pinSplit, "prefs.pinsplit.0", "${prefs.pinsplit.none}", "pinsplit.set arg:0"); |
2265 | addRadioButton_(pinSplit, "prefs.pinsplit.2", "${prefs.pinsplit.right}", "pinsplit.set arg:2"); | 2313 | addRadioButton_(pinSplit, "prefs.pinsplit.1", "${prefs.pinsplit.left}", "pinsplit.set arg:1"); |
2266 | } | 2314 | addRadioButton_(pinSplit, "prefs.pinsplit.2", "${prefs.pinsplit.right}", "pinsplit.set arg:2"); |
2267 | addChildFlags_Widget(values, iClob(pinSplit), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | 2315 | } |
2316 | addChildFlags_Widget(values, iClob(pinSplit), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | ||
2317 | } | ||
2268 | addChild_Widget(headings, iClob(makePadding_Widget(bigGap))); | 2318 | addChild_Widget(headings, iClob(makePadding_Widget(bigGap))); |
2269 | addChild_Widget(values, iClob(makePadding_Widget(bigGap))); | 2319 | addChild_Widget(values, iClob(makePadding_Widget(bigGap))); |
2270 | /* UI languages. */ { | 2320 | /* UI languages. */ { |
@@ -2486,6 +2536,7 @@ iWidget *makePreferences_Widget(void) { | |||
2486 | (iMenuItem[]){ { "${dismiss}", SDLK_ESCAPE, 0, "prefs.dismiss" } }, 1))); | 2536 | (iMenuItem[]){ { "${dismiss}", SDLK_ESCAPE, 0, "prefs.dismiss" } }, 1))); |
2487 | addChild_Widget(dlg->root->widget, iClob(dlg)); | 2537 | addChild_Widget(dlg->root->widget, iClob(dlg)); |
2488 | finalizeSheet_Widget(dlg); | 2538 | finalizeSheet_Widget(dlg); |
2539 | setupSheetTransition_Widget(dlg, iTrue); | ||
2489 | // printTree_Widget(dlg); | 2540 | // printTree_Widget(dlg); |
2490 | return dlg; | 2541 | return dlg; |
2491 | } | 2542 | } |
diff --git a/src/ui/util.h b/src/ui/util.h index 50845280..6185945f 100644 --- a/src/ui/util.h +++ b/src/ui/util.h | |||
@@ -255,9 +255,10 @@ size_t tabCount_Widget (const iWidget *tabs); | |||
255 | 255 | ||
256 | /*-----------------------------------------------------------------------------------------------*/ | 256 | /*-----------------------------------------------------------------------------------------------*/ |
257 | 257 | ||
258 | iWidget * makeSheet_Widget (const char *id); | 258 | iWidget * makeSheet_Widget (const char *id); |
259 | void finalizeSheet_Widget (iWidget *sheet); | 259 | void finalizeSheet_Widget (iWidget *sheet); |
260 | iWidget * makeDialogButtons_Widget(const iMenuItem *actions, size_t numActions); | 260 | void setupSheetTransition_Widget (iWidget *sheet, iBool isIncoming); |
261 | iWidget * makeDialogButtons_Widget (const iMenuItem *actions, size_t numActions); | ||
261 | 262 | ||
262 | iInputWidget *addTwoColumnDialogInputField_Widget(iWidget *headings, iWidget *values, | 263 | iInputWidget *addTwoColumnDialogInputField_Widget(iWidget *headings, iWidget *values, |
263 | const char *labelText, const char *inputId, | 264 | const char *labelText, const char *inputId, |
diff --git a/src/ui/widget.c b/src/ui/widget.c index dd0c1b05..3a67bf4e 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -40,6 +40,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
40 | # include "../ios.h" | 40 | # include "../ios.h" |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | static void printInfo_Widget_(const iWidget *); | ||
44 | |||
43 | void releaseChildren_Widget(iWidget *d) { | 45 | void releaseChildren_Widget(iWidget *d) { |
44 | iForEach(ObjectList, i, d->children) { | 46 | iForEach(ObjectList, i, d->children) { |
45 | ((iWidget *) i.object)->parent = NULL; /* the actual reference being held */ | 47 | ((iWidget *) i.object)->parent = NULL; /* the actual reference being held */ |
@@ -59,12 +61,23 @@ void init_Widget(iWidget *d) { | |||
59 | d->bgColor = none_ColorId; | 61 | d->bgColor = none_ColorId; |
60 | d->frameColor = none_ColorId; | 62 | d->frameColor = none_ColorId; |
61 | init_Anim(&d->visualOffset, 0.0f); | 63 | init_Anim(&d->visualOffset, 0.0f); |
64 | // init_Anim(&d->fadeOpacity, 0.0f); | ||
62 | d->children = NULL; | 65 | d->children = NULL; |
63 | d->parent = NULL; | 66 | d->parent = NULL; |
64 | d->commandHandler = NULL; | 67 | d->commandHandler = NULL; |
65 | iZap(d->padding); | 68 | iZap(d->padding); |
66 | } | 69 | } |
67 | 70 | ||
71 | #if 0 | ||
72 | static void animateFadeOpacity_Widget_(void *ptr) { | ||
73 | iWidget *d = ptr; | ||
74 | postRefresh_App(); | ||
75 | if (!isFinished_Anim(&d->fadeOpacity)) { | ||
76 | addTicker_App(animateFadeOpacity_Widget_, ptr); | ||
77 | } | ||
78 | } | ||
79 | #endif | ||
80 | |||
68 | static void visualOffsetAnimation_Widget_(void *ptr) { | 81 | static void visualOffsetAnimation_Widget_(void *ptr) { |
69 | iWidget *d = ptr; | 82 | iWidget *d = ptr; |
70 | postRefresh_App(); | 83 | postRefresh_App(); |
@@ -89,10 +102,12 @@ void deinit_Widget(iWidget *d) { | |||
89 | if (d->flags & visualOffset_WidgetFlag) { | 102 | if (d->flags & visualOffset_WidgetFlag) { |
90 | removeTicker_App(visualOffsetAnimation_Widget_, d); | 103 | removeTicker_App(visualOffsetAnimation_Widget_, d); |
91 | } | 104 | } |
105 | // removeTicker_App(animateFadeOpacity_Widget_, d); | ||
92 | widgetDestroyed_Touch(d); | 106 | widgetDestroyed_Touch(d); |
93 | } | 107 | } |
94 | 108 | ||
95 | static void aboutToBeDestroyed_Widget_(iWidget *d) { | 109 | static void aboutToBeDestroyed_Widget_(iWidget *d) { |
110 | d->flags |= destroyPending_WidgetFlag; | ||
96 | if (isFocused_Widget(d)) { | 111 | if (isFocused_Widget(d)) { |
97 | setFocus_Widget(NULL); | 112 | setFocus_Widget(NULL); |
98 | return; | 113 | return; |
@@ -371,10 +386,13 @@ iRect innerBounds_Widget(const iWidget *d) { | |||
371 | return ib; | 386 | return ib; |
372 | } | 387 | } |
373 | 388 | ||
374 | //iLocalDef iBool isArranged_Widget_(const iWidget *d) { | 389 | iRect innerBoundsWithoutVisualOffset_Widget(const iWidget *d) { |
375 | // return !isCollapsed_Widget_(d) && ~d->flags & fixedPosition_WidgetFlag; | 390 | iRect ib = adjusted_Rect(boundsWithoutVisualOffset_Widget(d), |
376 | //} | 391 | init_I2(d->padding[0], d->padding[1]), |
377 | 392 | init_I2(-d->padding[2], -d->padding[3])); | |
393 | ib.size = max_I2(zero_I2(), ib.size); | ||
394 | return ib; | ||
395 | } | ||
378 | 396 | ||
379 | static size_t numArrangedChildren_Widget_(const iWidget *d) { | 397 | static size_t numArrangedChildren_Widget_(const iWidget *d) { |
380 | size_t count = 0; | 398 | size_t count = 0; |
@@ -743,6 +761,16 @@ static void applyVisualOffset_Widget_(const iWidget *d, iInt2 *pos) { | |||
743 | pos->y += off; | 761 | pos->y += off; |
744 | } | 762 | } |
745 | } | 763 | } |
764 | if (d->flags & topPanelOffset_WidgetFlag) { | ||
765 | iConstForEach(ObjectList, i, children_Widget(parent_Widget(d))) { | ||
766 | const iWidget *child = i.object; | ||
767 | if (child == d) continue; | ||
768 | if (child->flags & (visualOffset_WidgetFlag | dragged_WidgetFlag)) { | ||
769 | const int invOff = size_Root(d->root).x - iRound(value_Anim(&child->visualOffset)); | ||
770 | pos->x -= invOff / 3; | ||
771 | } | ||
772 | } | ||
773 | } | ||
746 | } | 774 | } |
747 | 775 | ||
748 | iRect bounds_Widget(const iWidget *d) { | 776 | iRect bounds_Widget(const iWidget *d) { |
@@ -942,7 +970,7 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { | |||
942 | } | 970 | } |
943 | 971 | ||
944 | iBool scrollOverflow_Widget(iWidget *d, int delta) { | 972 | iBool scrollOverflow_Widget(iWidget *d, int delta) { |
945 | iRect bounds = bounds_Widget(d); | 973 | iRect bounds = boundsWithoutVisualOffset_Widget(d); |
946 | const iInt2 rootSize = size_Root(d->root); | 974 | const iInt2 rootSize = size_Root(d->root); |
947 | const iRect winRect = safeRect_Root(d->root); | 975 | const iRect winRect = safeRect_Root(d->root); |
948 | const int yTop = top_Rect(winRect); | 976 | const int yTop = top_Rect(winRect); |
@@ -1046,6 +1074,7 @@ void drawBackground_Widget(const iWidget *d) { | |||
1046 | if (d->flags & noBackground_WidgetFlag) { | 1074 | if (d->flags & noBackground_WidgetFlag) { |
1047 | return; | 1075 | return; |
1048 | } | 1076 | } |
1077 | // iAnim *fadeOpacity = (iAnim *) &d->fadeOpacity; | ||
1049 | if (d->flags & hidden_WidgetFlag && ~d->flags & visualOffset_WidgetFlag) { | 1078 | if (d->flags & hidden_WidgetFlag && ~d->flags & visualOffset_WidgetFlag) { |
1050 | return; | 1079 | return; |
1051 | } | 1080 | } |
@@ -1063,10 +1092,24 @@ void drawBackground_Widget(const iWidget *d) { | |||
1063 | init_Paint(&p); | 1092 | init_Paint(&p); |
1064 | drawSoftShadow_Paint(&p, bounds_Widget(d), 12 * gap_UI, black_ColorId, 30); | 1093 | drawSoftShadow_Paint(&p, bounds_Widget(d), 12 * gap_UI, black_ColorId, 30); |
1065 | } | 1094 | } |
1066 | 1095 | const iBool isFaded = fadeBackground && | |
1067 | if (fadeBackground && ~d->flags & noFadeBackground_WidgetFlag) { | 1096 | ~d->flags & noFadeBackground_WidgetFlag && |
1097 | ~d->flags & destroyPending_WidgetFlag; | ||
1098 | #if 0 | ||
1099 | if (isFaded && fadeOpacity->to != 1.0f) { | ||
1100 | setValue_Anim(fadeOpacity, 1.0f, 150); | ||
1101 | animateFadeOpacity_Widget_((void *) d); | ||
1102 | } | ||
1103 | else if (!isFaded && fadeOpacity->to != 0.0f) { | ||
1104 | setValue_Anim(fadeOpacity, 0.0f, 150); | ||
1105 | animateFadeOpacity_Widget_((void *) d); | ||
1106 | } | ||
1107 | if (value_Anim(fadeOpacity) > 0.0f) { | ||
1108 | #endif | ||
1109 | if (isFaded) { | ||
1068 | iPaint p; | 1110 | iPaint p; |
1069 | init_Paint(&p); | 1111 | init_Paint(&p); |
1112 | // p.alpha = (uint8_t) (2 * 0x50 * value_Anim(&d->fadeOpacity)); | ||
1070 | p.alpha = 0x50; | 1113 | p.alpha = 0x50; |
1071 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND); | 1114 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND); |
1072 | int fadeColor; | 1115 | int fadeColor; |
@@ -1081,9 +1124,7 @@ void drawBackground_Widget(const iWidget *d) { | |||
1081 | fadeColor = gray50_ColorId; | 1124 | fadeColor = gray50_ColorId; |
1082 | break; | 1125 | break; |
1083 | } | 1126 | } |
1084 | fillRect_Paint(&p, | 1127 | fillRect_Paint(&p, rect_Root(d->root), fadeColor); |
1085 | rect_Root(d->root), | ||
1086 | fadeColor); | ||
1087 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE); | 1128 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE); |
1088 | } | 1129 | } |
1089 | if (d->bgColor >= 0 || d->frameColor >= 0) { | 1130 | if (d->bgColor >= 0 || d->frameColor >= 0) { |
@@ -1603,7 +1644,8 @@ static void printInfo_Widget_(const iWidget *d) { | |||
1603 | cstr_String(text_LabelWidget((const iLabelWidget *) d)), | 1644 | cstr_String(text_LabelWidget((const iLabelWidget *) d)), |
1604 | cstr_String(command_LabelWidget((const iLabelWidget *) d))); | 1645 | cstr_String(command_LabelWidget((const iLabelWidget *) d))); |
1605 | } | 1646 | } |
1606 | printf("size:%dx%d {min:%dx%d} [%d..%d %d:%d] flags:%08llx%s%s%s%s%s%s%s\n", | 1647 | printf("pos:%d,%d size:%dx%d {min:%dx%d} [%d..%d %d:%d] flags:%08llx%s%s%s%s%s%s%s\n", |
1648 | d->rect.pos.x, d->rect.pos.y, | ||
1607 | d->rect.size.x, d->rect.size.y, | 1649 | d->rect.size.x, d->rect.size.y, |
1608 | d->minSize.x, d->minSize.y, | 1650 | d->minSize.x, d->minSize.y, |
1609 | d->padding[0], d->padding[2], | 1651 | d->padding[0], d->padding[2], |
diff --git a/src/ui/widget.h b/src/ui/widget.h index 13f400d1..7e464077 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h | |||
@@ -117,6 +117,9 @@ enum iWidgetFlag { | |||
117 | #define parentCannotResizeHeight_WidgetFlag iBit64(58) | 117 | #define parentCannotResizeHeight_WidgetFlag iBit64(58) |
118 | #define ignoreForParentWidth_WidgetFlag iBit64(59) | 118 | #define ignoreForParentWidth_WidgetFlag iBit64(59) |
119 | #define noFadeBackground_WidgetFlag iBit64(60) | 119 | #define noFadeBackground_WidgetFlag iBit64(60) |
120 | #define destroyPending_WidgetFlag iBit64(61) /* TODO: needed? */ | ||
121 | #define edgeDraggable_WidgetFlag iBit64(62) | ||
122 | #define topPanelOffset_WidgetFlag iBit64(63) /* visual offset determined by the offset of siblings */ | ||
120 | 123 | ||
121 | enum iWidgetAddPos { | 124 | enum iWidgetAddPos { |
122 | back_WidgetAddPos, | 125 | back_WidgetAddPos, |
@@ -139,9 +142,10 @@ struct Impl_Widget { | |||
139 | iAnim visualOffset; | 142 | iAnim visualOffset; |
140 | int bgColor; | 143 | int bgColor; |
141 | int frameColor; | 144 | int frameColor; |
145 | // iAnim fadeOpacity; | ||
142 | iObjectList *children; | 146 | iObjectList *children; |
143 | iWidget * parent; | 147 | iWidget * parent; |
144 | iBool (*commandHandler)(iWidget *, const char *); | 148 | iBool (*commandHandler)(iWidget *, const char *); |
145 | iRoot * root; | 149 | iRoot * root; |
146 | }; | 150 | }; |
147 | 151 | ||
diff --git a/src/ui/window.c b/src/ui/window.c index 5699da4c..ff565b84 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -1008,7 +1008,12 @@ void draw_Window(iWindow *d) { | |||
1008 | /* Clear the window. The clear color is visible as a border around the window | 1008 | /* Clear the window. The clear color is visible as a border around the window |
1009 | when the custom frame is being used. */ { | 1009 | when the custom frame is being used. */ { |
1010 | #if defined (iPlatformAppleMobile) | 1010 | #if defined (iPlatformAppleMobile) |
1011 | const iColor back = get_Color(uiBackground_ColorId); | 1011 | iColor back = get_Color(uiBackground_ColorId); |
1012 | if (deviceType_App() == phone_AppDeviceType) { | ||
1013 | /* Page background extends to safe area, so fill it completely. */ | ||
1014 | setCurrent_Root(d->roots[0]); | ||
1015 | back = get_Color(tmBackground_ColorId); | ||
1016 | } | ||
1012 | #else | 1017 | #else |
1013 | const iColor back = get_Color(gotFocus && d->place.snap != maximized_WindowSnap && | 1018 | const iColor back = get_Color(gotFocus && d->place.snap != maximized_WindowSnap && |
1014 | ~winFlags & SDL_WINDOW_FULLSCREEN_DESKTOP | 1019 | ~winFlags & SDL_WINDOW_FULLSCREEN_DESKTOP |