summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/inputwidget.c2
-rw-r--r--src/ui/mobile.c427
-rw-r--r--src/ui/root.c4
-rw-r--r--src/ui/touch.c10
-rw-r--r--src/ui/util.c2
-rw-r--r--src/ui/widget.c2
-rw-r--r--src/ui/widget.h2
-rw-r--r--src/ui/window.c2
8 files changed, 32 insertions, 419 deletions
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c
index e20d6f17..eb4cd0cf 100644
--- a/src/ui/inputwidget.c
+++ b/src/ui/inputwidget.c
@@ -278,7 +278,7 @@ static void eraseBackup_InputWidget_(iInputWidget *d) {
278static uint32_t backupTimeout_InputWidget_(uint32_t interval, void *context) { 278static uint32_t backupTimeout_InputWidget_(uint32_t interval, void *context) {
279 iInputWidget *d = context; 279 iInputWidget *d = context;
280 postCommand_Widget(d, "input.backup"); 280 postCommand_Widget(d, "input.backup");
281 return 0; 281 return 0; /* does not repeat */
282} 282}
283 283
284static void restartBackupTimer_InputWidget_(iInputWidget *d) { 284static void restartBackupTimer_InputWidget_(iInputWidget *d) {
diff --git a/src/ui/mobile.c b/src/ui/mobile.c
index af17b78c..f0c471de 100644
--- a/src/ui/mobile.c
+++ b/src/ui/mobile.c
@@ -815,413 +815,26 @@ void initPanels_Mobile(iWidget *panels, iWidget *parentWidget,
815// printTree_Widget(panels); 815// printTree_Widget(panels);
816} 816}
817 817
818#if 0 818/*
819 /* The sheet contents are completely rearranged and restyled on a phone. 819 Landscape Layout Portrait Layout
820 We'll set up a linear fullscreen arrangement of the widgets. Sheets are already 820
821 scrollable so they can be taller than the display. In hindsight, it may have been 821┌─────────┬──────Detail─Stack─────┐ ┌─────────┬ ─ ─ ─ ─ ┐
822 easier to create phone versions of each dialog, but at least this works with any 822│ │┌───────────────────┐ │ │ │Detail
823 future changes to the UI (..."works"). At least this way it is possible to enforce 823│ ││┌──────────────────┴┐ │ │ │Stack │
824 a consistent styling. */ 824│ │││┌──────────────────┴┐│ │ │┌──────┐
825 if (useMobileSheetLayout_() && parent_Widget(sheet) == root_Widget(sheet)) { 825│ ││││ ││ │ ││┌─────┴┐│
826 if (~flags_Widget(sheet) & keepOnTop_WidgetFlag) { 826│ ││││ ││ │ │││ │
827 /* Already finalized. */ 827│Top Panel││││ ││ │Top Panel│││ ││
828 arrange_Widget(sheet); 828│ ││││ Panels ││ │ │││Panels│
829 postRefresh_App(); 829│ ││││ ││ │ │││ ││
830 return; 830│ │└┤│ ││ │ │││ │
831 } 831│ │ └┤ ││ │ │└┤ ││
832 /* TODO: In portrait, top panel and detail stack are all stacked together. 832│ │ └───────────────────┘│ │ │ └──────┘
833 833└─────────┴───────────────────────┘ └─────────┴ ─ ─ ─ ─ ┘
834 Landscape Layout Portrait Layout 834 underneath
835 835
836 ┌─────────┬──────Detail─Stack─────┐ ┌─────────┬ ─ ─ ─ ─ ┐ 836In portrait, top panel and detail stack are all stacked together.
837 │ │┌───────────────────┐ │ │ │Detail 837*/
838 │ ││┌──────────────────┴┐ │ │ │Stack │
839 │ │││┌──────────────────┴┐│ │ │┌──────┐
840 │ ││││ ││ │ ││┌─────┴┐│
841 │ ││││ ││ │ │││ │
842 │Top Panel││││ ││ │Top Panel│││ ││
843 │ ││││ Panels ││ │ │││Panels│
844 │ ││││ ││ │ │││ ││
845 │ │└┤│ ││ │ │││ │
846 │ │ └┤ ││ │ │└┤ ││
847 │ │ └───────────────────┘│ │ │ └──────┘
848 └─────────┴───────────────────────┘ └─────────┴ ─ ─ ─ ─ ┘
849 underneath
850 */
851 /* Modify the top sheet to act as a fullscreen background. */
852 setPadding1_Widget(sheet, 0);
853 setBackgroundColor_Widget(sheet, uiBackground_ColorId);
854 setFlags_Widget(sheet,
855 keepOnTop_WidgetFlag |
856 parentCannotResize_WidgetFlag |
857 arrangeSize_WidgetFlag |
858 centerHorizontal_WidgetFlag |
859 arrangeVertical_WidgetFlag |
860 arrangeHorizontal_WidgetFlag |
861 overflowScrollable_WidgetFlag,
862 iFalse);
863 setFlags_Widget(sheet,
864 frameless_WidgetFlag |
865 //resizeWidthOfChildren_WidgetFlag |
866 leftEdgeDraggable_WidgetFlag |
867 commandOnClick_WidgetFlag,
868 iTrue);
869 iPtrArray * contents = collect_PtrArray(new_PtrArray()); /* two-column pages */
870 iPtrArray * panelButtons = collect_PtrArray(new_PtrArray());
871 iWidget * prefsTabs = findChild_Widget(sheet, "prefs.tabs");
872 iWidget * dialogHeading = (prefsTabs ? NULL : child_Widget(sheet, 0));
873 const iBool isPrefs = (prefsTabs != NULL);
874 const int64_t panelButtonFlags = borderBottom_WidgetFlag | alignLeft_WidgetFlag |
875 frameless_WidgetFlag | extraPadding_WidgetFlag;
876 iWidget *mainDetailSplit = makeHDiv_Widget();
877 setCommandHandler_Widget(mainDetailSplit, mainDetailSplitHandler_);
878 setFlags_Widget(mainDetailSplit, resizeHeightOfChildren_WidgetFlag, iFalse);
879 setId_Widget(mainDetailSplit, "mdsplit");
880 iWidget *topPanel = new_Widget(); {
881 setId_Widget(topPanel, "panel.top");
882 setCommandHandler_Widget(topPanel, topPanelHandler_);
883 setFlags_Widget(topPanel,
884 arrangeVertical_WidgetFlag |
885 resizeWidthOfChildren_WidgetFlag |
886 arrangeHeight_WidgetFlag |
887 overflowScrollable_WidgetFlag |
888 commandOnClick_WidgetFlag,
889 iTrue);
890 addChild_Widget(mainDetailSplit, iClob(topPanel));
891 }
892 iWidget *detailStack = new_Widget(); {
893 setId_Widget(detailStack, "detailstack");
894 setFlags_Widget(detailStack, collapse_WidgetFlag | resizeWidthOfChildren_WidgetFlag, iTrue);
895 addChild_Widget(mainDetailSplit, iClob(detailStack));
896 }
897 addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(labelFont_()))));
898 /* Slide top panel with detail panels. */ {
899 setFlags_Widget(topPanel, refChildrenOffset_WidgetFlag, iTrue);
900 topPanel->offsetRef = detailStack;
901 }
902 if (prefsTabs) {
903 iRelease(removeChild_Widget(sheet, child_Widget(sheet, 0))); /* heading */
904 iRelease(removeChild_Widget(sheet, findChild_Widget(sheet, "dialogbuttons")));
905 /* Pull out the pages and make them panels. */
906 iWidget *pages = findChild_Widget(prefsTabs, "tabs.pages");
907 size_t pageCount = tabCount_Widget(prefsTabs);
908 for (size_t i = 0; i < pageCount; i++) {
909 iString *text = copy_String(text_LabelWidget(tabPageButton_Widget(prefsTabs, tabPage_Widget(prefsTabs, 0))));
910 iWidget *page = removeTabPage_Widget(prefsTabs, 0);
911 iWidget *pageContent = child_Widget(page, 1); /* surrounded by padding widgets */
912 pushBack_PtrArray(contents, ref_Object(pageContent));
913 iLabelWidget *panelButton;
914 pushBack_PtrArray(panelButtons,
915 addChildFlags_Widget(topPanel,
916 iClob(panelButton = makePanelButton_(
917 i == 1 ? "${heading.prefs.userinterface}" : cstr_String(text),
918 "panel.open")),
919 (i == 0 ? borderTop_WidgetFlag : 0) |
920 chevron_WidgetFlag));
921 const iChar icons[] = {
922 0x02699, /* gear */
923 0x1f4f1, /* mobile phone */
924 0x1f3a8, /* palette */
925 0x1f5da, /* aA */
926 0x1f660, /* pointing bud */
927 0x1f5a7, /* computer network */
928 };
929 setIcon_LabelWidget(panelButton, icons[i]);
930// setFont_LabelWidget(panelButton, labelFont_());
931// setBackgroundColor_Widget(as_Widget(panelButton), uiBackgroundSidebar_ColorId);
932 iRelease(page);
933 delete_String(text);
934 }
935 destroy_Widget(prefsTabs);
936 }
937 iForEach(ObjectList, i, children_Widget(sheet)) {
938 iWidget *child = i.object;
939 if (isTwoColumnPage_(child)) {
940 pushBack_PtrArray(contents, removeChild_Widget(sheet, child));
941 }
942 else {
943 removeChild_Widget(sheet, child);
944 addChild_Widget(topPanel, child);
945 iRelease(child);
946 }
947 }
948 const iBool useSlidePanels = (size_PtrArray(contents) == size_PtrArray(panelButtons));
949 addChild_Widget(sheet, iClob(mainDetailSplit));
950 iForEach(PtrArray, j, contents) {
951 iWidget *owner = topPanel;
952 if (useSlidePanels) {
953 /* Create a new child panel. */
954 iLabelWidget *button = at_PtrArray(panelButtons, index_PtrArrayIterator(&j));
955 owner = addChildPanel_(detailStack, button,
956 collect_String(upper_String(text_LabelWidget(button))));
957 }
958 iWidget *pageContent = j.ptr;
959 iWidget *headings = child_Widget(pageContent, 0);
960 iWidget *values = child_Widget(pageContent, 1);
961 enum iPrefsElement prevElement = panelTitle_PrefsElement;
962 /* Identify the types of controls in the dialog and restyle/organize them. */
963 while (!isEmpty_ObjectList(children_Widget(headings))) {
964 iWidget *heading = child_Widget(headings, 0);
965 iWidget *value = child_Widget(values, 0);
966 removeChild_Widget(headings, heading);
967 removeChild_Widget(values, value);
968 /* Can we ignore these widgets? */
969 if (isOmittedPref_(id_Widget(value)) ||
970 (class_Widget(heading) == &Class_Widget &&
971 class_Widget(value) == &Class_Widget) /* just padding */) {
972 iRelease(heading);
973 iRelease(value);
974 continue;
975 }
976 enum iPrefsElement element = toggle_PrefsElement;
977 iLabelWidget *headingLabel = NULL;
978 iLabelWidget *valueLabel = NULL;
979 iInputWidget *valueInput = NULL;
980 const iBool isMenuButton = findChild_Widget(value, "menu") != NULL;
981 if (isInstance_Object(heading, &Class_LabelWidget)) {
982 headingLabel = (iLabelWidget *) heading;
983 stripTrailingColon_(headingLabel);
984 }
985 if (isInstance_Object(value, &Class_LabelWidget)) {
986 valueLabel = (iLabelWidget *) value;
987 setFont_LabelWidget(valueLabel, labelFont_());
988 }
989 if (isInstance_Object(value, &Class_InputWidget)) {
990 valueInput = (iInputWidget *) value;
991 setFlags_Widget(value, borderBottom_WidgetFlag, iFalse);
992 element = textInput_PrefsElement;
993 }
994 if (childCount_Widget(value) >= 2) {
995 if (isInstance_Object(child_Widget(value, 0), &Class_InputWidget)) {
996 element = textInput_PrefsElement;
997 setPadding_Widget(value, 0, 0, gap_UI, 0);
998 valueInput = child_Widget(value, 0);
999 }
1000 }
1001 if (valueInput) {
1002 setFont_InputWidget(valueInput, labelFont_());
1003 setContentPadding_InputWidget(valueInput, 3 * gap_UI, 0);
1004 }
1005 /* Toggles have the button on the right. */
1006 if (valueLabel && cmp_String(command_LabelWidget(valueLabel), "toggle") == 0) {
1007 element = toggle_PrefsElement;
1008 addPanelChild_(owner,
1009 iClob(makeValuePaddingWithHeading_(headingLabel, value)),
1010 0,
1011 element,
1012 prevElement);
1013 }
1014 else if (valueLabel && isEmpty_String(text_LabelWidget(valueLabel))) {
1015 element = heading_PrefsElement;
1016 iRelease(value);
1017 addPanelChild_(owner, iClob(heading), 0, element, prevElement);
1018 setFont_LabelWidget(headingLabel, uiLabel_FontId);
1019 }
1020 else if (isMenuButton) {
1021 element = dropdown_PrefsElement;
1022 setFlags_Widget(value,
1023 alignRight_WidgetFlag | noBackground_WidgetFlag |
1024 frameless_WidgetFlag, iTrue);
1025 setFlags_Widget(value, alignLeft_WidgetFlag, iFalse);
1026 iWidget *pad = addPanelChild_(owner, iClob(makeValuePaddingWithHeading_(headingLabel, value)), 0,
1027 element, prevElement);
1028 pad->padding[2] = gap_UI;
1029 }
1030 else if (valueInput) {
1031 addPanelChild_(owner, iClob(makeValuePaddingWithHeading_(headingLabel, value)), 0,
1032 element, prevElement);
1033 }
1034 else {
1035 if (childCount_Widget(value) >= 2) {
1036 element = radioButton_PrefsElement;
1037 /* Always padding before radio buttons. */
1038 addChild_Widget(owner, iClob(makePadding_Widget(lineHeight_Text(labelFont_()))));
1039 }
1040 addChildFlags_Widget(owner, iClob(heading), borderBottom_WidgetFlag);
1041 if (headingLabel) {
1042 setTextColor_LabelWidget(headingLabel, uiSubheading_ColorId);
1043 setText_LabelWidget(headingLabel,
1044 collect_String(upper_String(text_LabelWidget(headingLabel))));
1045 }
1046 addPanelChild_(owner, iClob(value), 0, element, prevElement);
1047 /* Radio buttons expand to fill the space. */
1048 if (element == radioButton_PrefsElement) {
1049 setBackgroundColor_Widget(value, uiBackgroundSidebar_ColorId);
1050 setPadding_Widget(value, 4 * gap_UI, 2 * gap_UI, 4 * gap_UI, 2 * gap_UI);
1051 setFlags_Widget(value, arrangeWidth_WidgetFlag, iFalse);
1052 setFlags_Widget(value,
1053 borderBottom_WidgetFlag |
1054 resizeToParentWidth_WidgetFlag |
1055 resizeWidthOfChildren_WidgetFlag,
1056 iTrue);
1057 iForEach(ObjectList, sub, children_Widget(value)) {
1058 if (isInstance_Object(sub.object, &Class_LabelWidget)) {
1059 iLabelWidget *opt = sub.object;
1060 setFont_LabelWidget(opt, uiLabelMedium_FontId);
1061 setFlags_Widget(as_Widget(opt), noBackground_WidgetFlag, iTrue);
1062 }
1063 }
1064 }
1065 }
1066 prevElement = element;
1067 }
1068 addPanelChild_(owner, NULL, 0, 0, prevElement);
1069 destroy_Widget(pageContent);
1070 }
1071 destroyPending_Root(sheet->root);
1072 /* Additional elements for preferences. */
1073 if (isPrefs) {
1074 addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(labelFont_()))));
1075 /* Management. */ {
1076 iLabelWidget *idManButton = addChildFlags_Widget(topPanel,
1077 iClob(makePanelButton_(person_Icon " ${sidebar.identities}", "panel.open")),
1078 chevron_WidgetFlag | borderTop_WidgetFlag);
1079 }
1080 addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(labelFont_()))));
1081 iLabelWidget *aboutButton = addChildFlags_Widget(topPanel,
1082 iClob(makePanelButton_(planet_Icon " ${menu.about}", "panel.open")),
1083 chevron_WidgetFlag | borderTop_WidgetFlag);
1084 addChildFlags_Widget(topPanel,
1085 iClob(makePanelButton_(info_Icon " ${menu.help}", "!open url:about:help")), 0);
1086 /* The About panel. */ {
1087 iWidget *panel = addChildPanel_(detailStack, aboutButton, NULL);
1088 iString *msg = collectNew_String();
1089 setCStr_String(msg, "Lagrange " LAGRANGE_APP_VERSION);
1090#if defined (iPlatformAppleMobile)
1091 appendCStr_String(msg, " (" LAGRANGE_IOS_VERSION ")");
1092#endif
1093 addChildFlags_Widget(panel, iClob(new_LabelWidget(cstr_String(msg), NULL)),
1094 frameless_WidgetFlag);
1095 addChildFlags_Widget(panel,
1096 iClob(makePanelButton_(globe_Icon " By @jk@skyjake.fi",
1097 "!open url:https://skyjake.fi/@jk")),
1098 borderTop_WidgetFlag);
1099 addChildFlags_Widget(panel,
1100 iClob(makePanelButton_(clock_Icon " ${menu.releasenotes}",
1101 "!open url:about:version")),
1102 0);
1103 addChildFlags_Widget(panel,
1104 iClob(makePanelButton_(info_Icon " ${menu.aboutpages}",
1105 "!open url:about:about")),
1106 0);
1107 addChildFlags_Widget(panel,
1108 iClob(makePanelButton_(bug_Icon " ${menu.debug}",
1109 "!open url:about:debug")),
1110 0);
1111 }
1112 }
1113 else {
1114 setFlags_Widget(topPanel, overflowScrollable_WidgetFlag, iTrue);
1115 /* Update heading style. */
1116 setFont_LabelWidget((iLabelWidget *) dialogHeading, uiLabelLargeBold_FontId);
1117 setFlags_Widget(dialogHeading, alignLeft_WidgetFlag, iTrue);
1118 }
1119 if (findChild_Widget(sheet, "valueinput.prompt")) {
1120 iWidget *prompt = findChild_Widget(sheet, "valueinput.prompt");
1121 setFlags_Widget(prompt, alignLeft_WidgetFlag, iTrue);
1122 iInputWidget *input = findChild_Widget(sheet, "input");
1123 removeChild_Widget(parent_Widget(input), input);
1124 addChild_Widget(topPanel, iClob(makeValuePadding_(as_Widget(input))));
1125 }
1126 /* Top padding for each panel, to account for the overlaid navbar. */ {
1127 setId_Widget(addChildPos_Widget(topPanel,
1128 iClob(makePadding_Widget(0)), front_WidgetAddPos),
1129 "panel.toppad");
1130 }
1131 /* Navbar. */ {
1132 iWidget *navi = new_Widget();
1133 setId_Widget(navi, "panel.navi");
1134 setBackgroundColor_Widget(navi, uiBackground_ColorId);
1135 addChild_Widget(navi, iClob(makePadding_Widget(0)));
1136 iLabelWidget *back = addChildFlags_Widget(navi,
1137 iClob(new_LabelWidget(leftAngle_Icon " ${panel.back}", "panel.close")),
1138 noBackground_WidgetFlag | frameless_WidgetFlag |
1139 alignLeft_WidgetFlag | extraPadding_WidgetFlag);
1140 checkIcon_LabelWidget(back);
1141 setId_Widget(as_Widget(back), "panel.back");
1142 setFont_LabelWidget(back, labelFont_());
1143 if (!isPrefs) {
1144 /* Pick up the dialog buttons for the navbar. */
1145 iWidget *buttons = findChild_Widget(sheet, "dialogbuttons");
1146 iLabelWidget *cancel = findMenuItem_Widget(buttons, "cancel");
1147// if (!cancel) {
1148// cancel = findMenuItem_Widget(buttons, "translation.cancel");
1149// }
1150 if (cancel) {
1151 updateText_LabelWidget(back, text_LabelWidget(cancel));
1152 setCommand_LabelWidget(back, command_LabelWidget(cancel));
1153 }
1154 iLabelWidget *def = (iLabelWidget *) lastChild_Widget(buttons);
1155 if (def && !cancel) {
1156 updateText_LabelWidget(back, text_LabelWidget(def));
1157 setCommand_LabelWidget(back, command_LabelWidget(def));
1158 setFlags_Widget(as_Widget(back), alignLeft_WidgetFlag, iFalse);
1159 setFlags_Widget(as_Widget(back), alignRight_WidgetFlag, iTrue);
1160 setIcon_LabelWidget(back, 0);
1161 setFont_LabelWidget(back, labelBoldFont_());
1162 }
1163 else if (def != cancel) {
1164 removeChild_Widget(buttons, def);
1165 setFont_LabelWidget(def, labelBoldFont_());
1166 setFlags_Widget(as_Widget(def),
1167 frameless_WidgetFlag | extraPadding_WidgetFlag |
1168 noBackground_WidgetFlag, iTrue);
1169 addChildFlags_Widget(as_Widget(back), iClob(def), moveToParentRightEdge_WidgetFlag);
1170 updateSize_LabelWidget(def);
1171 }
1172 /* Action buttons are added in the bottom as extra buttons. */ {
1173 iBool isFirstAction = iTrue;
1174 iForEach(ObjectList, i, children_Widget(buttons)) {
1175 if (isInstance_Object(i.object, &Class_LabelWidget) &&
1176 i.object != cancel && i.object != def) {
1177 iLabelWidget *item = i.object;
1178 setBackgroundColor_Widget(i.object, uiBackgroundSidebar_ColorId);
1179 setFont_LabelWidget(item, labelFont_());
1180 removeChild_Widget(buttons, item);
1181 addChildFlags_Widget(topPanel, iClob(item), panelButtonFlags |
1182 (isFirstAction ? borderTop_WidgetFlag : 0));
1183 updateSize_LabelWidget(item);
1184 isFirstAction = iFalse;
1185 }
1186 }
1187 }
1188 iRelease(removeChild_Widget(parent_Widget(buttons), buttons));
1189 /* Styling for remaining elements. */
1190 iForEach(ObjectList, i, children_Widget(topPanel)) {
1191 if (isInstance_Object(i.object, &Class_LabelWidget) &&
1192 isEmpty_String(command_LabelWidget(i.object)) &&
1193 isEmpty_String(id_Widget(i.object))) {
1194 setFlags_Widget(i.object, alignLeft_WidgetFlag, iTrue);
1195 if (font_LabelWidget(i.object) == uiLabel_FontId) {
1196 setFont_LabelWidget(i.object, uiContent_FontId);
1197 }
1198 }
1199 }
1200 }
1201 addChildFlags_Widget(sheet, iClob(navi),
1202 drawBackgroundToVerticalSafeArea_WidgetFlag |
1203 arrangeHeight_WidgetFlag | resizeWidthOfChildren_WidgetFlag |
1204 resizeToParentWidth_WidgetFlag | arrangeVertical_WidgetFlag);
1205 }
1206 if (isPrefs && isSideBySideLayout_()) {
1207 /* Show the General panel. */
1208 postCommand_Widget(at_PtrArray(panelButtons, 0), "panel.open");
1209 }
1210 mainDetailSplitHandler_(mainDetailSplit, "window.resized"); /* make it resize the split */
1211 updatePanelSheetMetrics_(sheet);
1212 iAssert(sheet->parent);
1213 arrange_Widget(sheet->parent);
1214 postCommand_App("widget.overflow"); /* with the correct dimensions */
1215 }
1216 else {
1217 arrange_Widget(sheet);
1218 }
1219 if (!useMobileSheetLayout_()) {
1220 setupSheetTransition_Mobile(sheet, iTrue);
1221 }
1222 postRefresh_App();
1223}
1224#endif
1225 838
1226void setupMenuTransition_Mobile(iWidget *sheet, iBool isIncoming) { 839void setupMenuTransition_Mobile(iWidget *sheet, iBool isIncoming) {
1227 if (!isUsingPanelLayout_Mobile()) { 840 if (!isUsingPanelLayout_Mobile()) {
diff --git a/src/ui/root.c b/src/ui/root.c
index ba8d95ee..d847480f 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -804,7 +804,7 @@ static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) {
804 if (isTabButton_Widget(widget)) { 804 if (isTabButton_Widget(widget)) {
805 if (!isVisible_Widget(menu)) { 805 if (!isVisible_Widget(menu)) {
806 iWidget *tabs = findWidget_App("doctabs"); 806 iWidget *tabs = findWidget_App("doctabs");
807 iWidget *page = tabPage_Widget(tabs, childIndex_Widget(widget->parent, widget)); 807 iWidget *page = tabPage_Widget(tabs, indexOfChild_Widget(widget->parent, widget));
808 if (argLabel_Command(cmd, "button") == SDL_BUTTON_MIDDLE) { 808 if (argLabel_Command(cmd, "button") == SDL_BUTTON_MIDDLE) {
809 postCommandf_App("tabs.close id:%s", cstr_String(id_Widget(page))); 809 postCommandf_App("tabs.close id:%s", cstr_String(id_Widget(page)));
810 return iTrue; 810 return iTrue;
@@ -1327,7 +1327,7 @@ void createUserInterface_Root(iRoot *d) {
1327 /* The search bar appears at the top on mobile, because there is a virtual keyboard 1327 /* The search bar appears at the top on mobile, because there is a virtual keyboard
1328 covering the bottom. */ 1328 covering the bottom. */
1329 insertChildAfter_Widget(div, iClob(searchBar), 1329 insertChildAfter_Widget(div, iClob(searchBar),
1330 childIndex_Widget(div, findChild_Widget(div, "navbar"))); 1330 indexOfChild_Widget(div, findChild_Widget(div, "navbar")));
1331 } 1331 }
1332 setBackgroundColor_Widget(searchBar, uiBackground_ColorId); 1332 setBackgroundColor_Widget(searchBar, uiBackground_ColorId);
1333 setCommandHandler_Widget(searchBar, handleSearchBarCommands_); 1333 setCommandHandler_Widget(searchBar, handleSearchBarCommands_);
diff --git a/src/ui/touch.c b/src/ui/touch.c
index 884cc605..195d1dff 100644
--- a/src/ui/touch.c
+++ b/src/ui/touch.c
@@ -617,11 +617,11 @@ iBool processEvent_Touch(const SDL_Event *ev) {
617 if (touch->axis == y_TouchAxis) { 617 if (touch->axis == y_TouchAxis) {
618 pixels.x = 0; 618 pixels.x = 0;
619 } 619 }
620 printf("%p (%s) py: %i wy: %f acc: %f edge: %d\n", 620// printf("%p (%s) py: %i wy: %f acc: %f edge: %d\n",
621 touch->affinity, 621// touch->affinity,
622 class_Widget(touch->affinity)->name, 622// class_Widget(touch->affinity)->name,
623 pixels.y, y_F3(amount), y_F3(touch->accum), 623// pixels.y, y_F3(amount), y_F3(touch->accum),
624 touch->edge); 624// touch->edge);
625 if (pixels.x || pixels.y) { 625 if (pixels.x || pixels.y) {
626 //setFocus_Widget(NULL); 626 //setFocus_Widget(NULL);
627 dispatchMotion_Touch_(touch->startPos /*pos[0]*/, 0); 627 dispatchMotion_Touch_(touch->startPos /*pos[0]*/, 0);
diff --git a/src/ui/util.c b/src/ui/util.c
index 7af9ca8b..e3454cd9 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -1512,7 +1512,7 @@ void setTabPageLabel_Widget(iWidget *tabs, const iAnyObject *page, const iString
1512 1512
1513size_t tabPageIndex_Widget(const iWidget *tabs, const iAnyObject *page) { 1513size_t tabPageIndex_Widget(const iWidget *tabs, const iAnyObject *page) {
1514 iWidget *pages = findChild_Widget(tabs, "tabs.pages"); 1514 iWidget *pages = findChild_Widget(tabs, "tabs.pages");
1515 return childIndex_Widget(pages, page); 1515 return indexOfChild_Widget(pages, page);
1516} 1516}
1517 1517
1518const iWidget *currentTabPage_Widget(const iWidget *tabs) { 1518const iWidget *currentTabPage_Widget(const iWidget *tabs) {
diff --git a/src/ui/widget.c b/src/ui/widget.c
index 3cea260b..8a7127a2 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -1708,7 +1708,7 @@ iAny *child_Widget(iWidget *d, size_t index) {
1708 return NULL; 1708 return NULL;
1709} 1709}
1710 1710
1711size_t childIndex_Widget(const iWidget *d, const iAnyObject *child) { 1711size_t indexOfChild_Widget(const iWidget *d, const iAnyObject *child) {
1712 size_t index = 0; 1712 size_t index = 0;
1713 iConstForEach(ObjectList, i, d->children) { 1713 iConstForEach(ObjectList, i, d->children) {
1714 if (i.object == child) { 1714 if (i.object == child) {
diff --git a/src/ui/widget.h b/src/ui/widget.h
index b119610a..d93b0344 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -279,7 +279,7 @@ iAny * insertChildAfter_Widget (iWidget *, iAnyObject *child, size_t afterI
279iAny * insertChildAfterFlags_Widget(iWidget *, iAnyObject *child, size_t afterIndex, int64_t childFlags); 279iAny * insertChildAfterFlags_Widget(iWidget *, iAnyObject *child, size_t afterIndex, int64_t childFlags);
280iAny * removeChild_Widget (iWidget *, iAnyObject *child); /* returns a ref */ 280iAny * removeChild_Widget (iWidget *, iAnyObject *child); /* returns a ref */
281iAny * child_Widget (iWidget *, size_t index); /* O(n) */ 281iAny * child_Widget (iWidget *, size_t index); /* O(n) */
282size_t childIndex_Widget (const iWidget *, const iAnyObject *child); /* O(n) */ 282size_t indexOfChild_Widget (const iWidget *, const iAnyObject *child); /* O(n) */
283void arrange_Widget (iWidget *); 283void arrange_Widget (iWidget *);
284iBool scrollOverflow_Widget (iWidget *, int delta); /* moves the widget */ 284iBool scrollOverflow_Widget (iWidget *, int delta); /* moves the widget */
285iBool dispatchEvent_Widget (iWidget *, const SDL_Event *); 285iBool dispatchEvent_Widget (iWidget *, const SDL_Event *);
diff --git a/src/ui/window.c b/src/ui/window.c
index eed0a951..c63ad76a 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1483,7 +1483,7 @@ void setSplitMode_MainWindow(iMainWindow *d, int splitFlags) {
1483 iRelease(tabs); 1483 iRelease(tabs);
1484 postCommandf_App("tabs.switch id:%s", cstr_String(id_Widget(constAs_Widget(curPage)))); 1484 postCommandf_App("tabs.switch id:%s", cstr_String(id_Widget(constAs_Widget(curPage))));
1485 } 1485 }
1486 else if (splitMode && oldCount == 1) { 1486 else if (oldCount == 1 && splitMode) {
1487 /* Add a second root. */ 1487 /* Add a second root. */
1488 iDocumentWidget *moved = document_Root(w->roots[0]); 1488 iDocumentWidget *moved = document_Root(w->roots[0]);
1489 iAssert(w->roots[1] == NULL); 1489 iAssert(w->roots[1] == NULL);