summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app.c17
-rw-r--r--src/ui/documentwidget.c4
-rw-r--r--src/ui/labelwidget.c14
-rw-r--r--src/ui/root.c1
-rw-r--r--src/ui/sidebarwidget.c1
-rw-r--r--src/ui/touch.c18
-rw-r--r--src/ui/touch.h1
-rw-r--r--src/ui/util.c83
-rw-r--r--src/ui/util.h7
-rw-r--r--src/ui/widget.c64
-rw-r--r--src/ui/widget.h6
-rw-r--r--src/ui/window.c7
12 files changed, 177 insertions, 46 deletions
diff --git a/src/app.c b/src/app.c
index b80953a1..64348930 100644
--- a/src/app.c
+++ b/src/app.c
@@ -1056,7 +1056,14 @@ void processEvents_App(enum iAppEventMode eventMode) {
1056 } 1056 }
1057 continue; 1057 continue;
1058 } 1058 }
1059 else if (ev.type == SDL_USEREVENT && ev.user.code == arrange_UserEventCode) { 1059 d->lastEventTime = SDL_GetTicks();
1060 if (d->isIdling) {
1061// printf("[App] ...woke up\n");
1062// fflush(stdout);
1063 }
1064 d->isIdling = iFalse;
1065#endif
1066 if (ev.type == SDL_USEREVENT && ev.user.code == arrange_UserEventCode) {
1060 printf("[App] rearrange\n"); 1067 printf("[App] rearrange\n");
1061 resize_Window(d->window, -1, -1); 1068 resize_Window(d->window, -1, -1);
1062 iForIndices(i, d->window->roots) { 1069 iForIndices(i, d->window->roots) {
@@ -1073,13 +1080,6 @@ void processEvents_App(enum iAppEventMode eventMode) {
1073// postRefresh_App(); 1080// postRefresh_App();
1074 continue; 1081 continue;
1075 } 1082 }
1076 d->lastEventTime = SDL_GetTicks();
1077 if (d->isIdling) {
1078// printf("[App] ...woke up\n");
1079// fflush(stdout);
1080 }
1081 d->isIdling = iFalse;
1082#endif
1083 gotEvents = iTrue; 1083 gotEvents = iTrue;
1084 /* Keyboard modifier mapping. */ 1084 /* Keyboard modifier mapping. */
1085 if (ev.type == SDL_KEYDOWN || ev.type == SDL_KEYUP) { 1085 if (ev.type == SDL_KEYDOWN || ev.type == SDL_KEYUP) {
@@ -1508,6 +1508,7 @@ static void updateFontButton_(iLabelWidget *button, int font) {
1508 1508
1509static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { 1509static iBool handlePrefsCommands_(iWidget *d, const char *cmd) {
1510 if (equal_Command(cmd, "prefs.dismiss") || equal_Command(cmd, "preferences")) { 1510 if (equal_Command(cmd, "prefs.dismiss") || equal_Command(cmd, "preferences")) {
1511 setupSheetTransition_Widget(d, iFalse);
1511 setUiScale_Window(get_Window(), 1512 setUiScale_Window(get_Window(),
1512 toFloat_String(text_InputWidget(findChild_Widget(d, "prefs.uiscale")))); 1513 toFloat_String(text_InputWidget(findChild_Widget(d, "prefs.uiscale"))));
1513#if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT) 1514#if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT)
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
32struct Impl_LabelWidget { 33struct Impl_LabelWidget {
33 iWidget widget; 34 iWidget widget;
@@ -46,6 +47,15 @@ struct Impl_LabelWidget {
46 } flags; 47 } flags;
47}; 48};
48 49
50static 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
49static iInt2 padding_LabelWidget_(const iLabelWidget *d, int corner) { 59static 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
341static iWidget *findSlidePanel_Widget_(iWidget *d) { 341static 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
750iBool 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
748size_t numFingers_Touch(void) { 764size_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);
41void widgetDestroyed_Touch (iWidget *widget); 41void widgetDestroyed_Touch (iWidget *widget);
42 42
43iInt2 latestPosition_Touch (void); /* valid during processing of current event */ 43iInt2 latestPosition_Touch (void); /* valid during processing of current event */
44iBool isHovering_Touch (void); /* stationary touch or a long-press drag ongoing */
44size_t numFingers_Touch (void); 45size_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
2259void 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
2228iWidget *makePreferences_Widget(void) { 2276iWidget *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
258iWidget * makeSheet_Widget (const char *id); 258iWidget * makeSheet_Widget (const char *id);
259void finalizeSheet_Widget (iWidget *sheet); 259void finalizeSheet_Widget (iWidget *sheet);
260iWidget * makeDialogButtons_Widget(const iMenuItem *actions, size_t numActions); 260void setupSheetTransition_Widget (iWidget *sheet, iBool isIncoming);
261iWidget * makeDialogButtons_Widget (const iMenuItem *actions, size_t numActions);
261 262
262iInputWidget *addTwoColumnDialogInputField_Widget(iWidget *headings, iWidget *values, 263iInputWidget *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
43static void printInfo_Widget_(const iWidget *);
44
43void releaseChildren_Widget(iWidget *d) { 45void 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
72static 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
68static void visualOffsetAnimation_Widget_(void *ptr) { 81static 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
95static void aboutToBeDestroyed_Widget_(iWidget *d) { 109static 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) { 389iRect 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
379static size_t numArrangedChildren_Widget_(const iWidget *d) { 397static 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
748iRect bounds_Widget(const iWidget *d) { 776iRect bounds_Widget(const iWidget *d) {
@@ -942,7 +970,7 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
942} 970}
943 971
944iBool scrollOverflow_Widget(iWidget *d, int delta) { 972iBool 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
121enum iWidgetAddPos { 124enum 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