diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-09-21 11:51:55 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-09-21 11:51:55 +0300 |
commit | 282e1376091e850565b5c5166755ae94afe56ad2 (patch) | |
tree | 8c4334f0dbe18bb1fa23939ff800ce9051c070d6 /src/ui/util.c | |
parent | e48a9a27bd11dbef9531bd12d3c0c60cc771b2c3 (diff) |
macOS: Improving native menu behavior
Selected items and dynamic label updates.
Diffstat (limited to 'src/ui/util.c')
-rw-r--r-- | src/ui/util.c | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/src/ui/util.c b/src/ui/util.c index 0baf541d..a5b1cfb3 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -872,6 +872,36 @@ static void updateMenuItemFonts_Widget_(iWidget *d) { | |||
872 | } | 872 | } |
873 | } | 873 | } |
874 | 874 | ||
875 | iMenuItem *findNativeMenuItem_Widget(iWidget *menu, const char *commandSuffix) { | ||
876 | iAssert(flags_Widget(menu) & nativeMenu_WidgetFlag); | ||
877 | iForEach(Array, i, userData_Object(menu)) { | ||
878 | iMenuItem *item = i.value; | ||
879 | if (item->command && endsWith_Rangecc(range_CStr(item->command), commandSuffix)) { | ||
880 | return item; | ||
881 | } | ||
882 | } | ||
883 | return NULL; | ||
884 | } | ||
885 | |||
886 | void setSelected_NativeMenuItem(iMenuItem *item, iBool isSelected) { | ||
887 | if (!item->label) { | ||
888 | return; | ||
889 | } | ||
890 | const iBool hasPrefix = startsWith_CStr(item->label, "###"); | ||
891 | if (hasPrefix && !isSelected) { | ||
892 | char *label = strdup(item->label + 3); | ||
893 | free((char *) item->label); | ||
894 | item->label = label; | ||
895 | } | ||
896 | else if (!hasPrefix && isSelected) { | ||
897 | char *label = malloc(strlen(item->label) + 4); | ||
898 | memcpy(label, "###", 3); | ||
899 | strcpy(label + 3, item->label); | ||
900 | free((char *) item->label); | ||
901 | item->label = label; | ||
902 | } | ||
903 | } | ||
904 | |||
875 | void updateMenuItemLabel_Widget(iWidget *menu, const char *command, const char *newLabel) { | 905 | void updateMenuItemLabel_Widget(iWidget *menu, const char *command, const char *newLabel) { |
876 | if (~flags_Widget(menu) & nativeMenu_WidgetFlag) { | 906 | if (~flags_Widget(menu) & nativeMenu_WidgetFlag) { |
877 | iLabelWidget *menuItem = findMenuItem_Widget(menu, command); | 907 | iLabelWidget *menuItem = findMenuItem_Widget(menu, command); |
@@ -894,6 +924,14 @@ void updateMenuItemLabel_Widget(iWidget *menu, const char *command, const char * | |||
894 | } | 924 | } |
895 | } | 925 | } |
896 | 926 | ||
927 | void unselectAllNativeMenuItems_Widget(iWidget *menu) { | ||
928 | iArray *items = userData_Object(menu); | ||
929 | iAssert(items); | ||
930 | iForEach(Array, i, items) { | ||
931 | setSelected_NativeMenuItem(i.value, iFalse); | ||
932 | } | ||
933 | } | ||
934 | |||
897 | iLocalDef iBool isUsingMenuPopupWindows_(void) { | 935 | iLocalDef iBool isUsingMenuPopupWindows_(void) { |
898 | return deviceType_App() == desktop_AppDeviceType; | 936 | return deviceType_App() == desktop_AppDeviceType; |
899 | } | 937 | } |
@@ -915,7 +953,7 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) { | |||
915 | const iArray *items = userData_Object(d); | 953 | const iArray *items = userData_Object(d); |
916 | iAssert(flags_Widget(d) & nativeMenu_WidgetFlag); | 954 | iAssert(flags_Widget(d) & nativeMenu_WidgetFlag); |
917 | iAssert(items); | 955 | iAssert(items); |
918 | showPopupMenu_MacOS(d, mouseCoord_Window(get_Window(), 0), | 956 | showPopupMenu_MacOS(d, windowCoord, //mouseCoord_Window(get_Window(), 0), |
919 | constData_Array(items), size_Array(items)); | 957 | constData_Array(items), size_Array(items)); |
920 | #else | 958 | #else |
921 | const iRect rootRect = rect_Root(d->root); | 959 | const iRect rootRect = rect_Root(d->root); |
@@ -1075,8 +1113,34 @@ iLabelWidget *makeMenuButton_LabelWidget(const char *label, const iMenuItem *ite | |||
1075 | return button; | 1113 | return button; |
1076 | } | 1114 | } |
1077 | 1115 | ||
1116 | const iString *removeMenuItemLabelPrefixes_String(const iString *d) { | ||
1117 | iString *str = copy_String(d); | ||
1118 | for (;;) { | ||
1119 | if (startsWith_String(str, "###")) { | ||
1120 | remove_Block(&str->chars, 0, 3); | ||
1121 | continue; | ||
1122 | } | ||
1123 | if (startsWith_String(str, "```")) { | ||
1124 | remove_Block(&str->chars, 0, 3); | ||
1125 | continue; | ||
1126 | } | ||
1127 | break; | ||
1128 | } | ||
1129 | return collect_String(str); | ||
1130 | } | ||
1131 | |||
1078 | void updateDropdownSelection_LabelWidget(iLabelWidget *dropButton, const char *selectedCommand) { | 1132 | void updateDropdownSelection_LabelWidget(iLabelWidget *dropButton, const char *selectedCommand) { |
1079 | iWidget *menu = findChild_Widget(as_Widget(dropButton), "menu"); | 1133 | iWidget *menu = findChild_Widget(as_Widget(dropButton), "menu"); |
1134 | if (flags_Widget(menu) & nativeMenu_WidgetFlag) { | ||
1135 | unselectAllNativeMenuItems_Widget(menu); | ||
1136 | iMenuItem *item = findNativeMenuItem_Widget(menu, selectedCommand); | ||
1137 | if (item) { | ||
1138 | setSelected_NativeMenuItem(item, iTrue); | ||
1139 | updateText_LabelWidget(dropButton, | ||
1140 | removeMenuItemLabelPrefixes_String(collectNewCStr_String(item->label))); | ||
1141 | } | ||
1142 | return; | ||
1143 | } | ||
1080 | iForEach(ObjectList, i, children_Widget(menu)) { | 1144 | iForEach(ObjectList, i, children_Widget(menu)) { |
1081 | if (isInstance_Object(i.object, &Class_LabelWidget)) { | 1145 | if (isInstance_Object(i.object, &Class_LabelWidget)) { |
1082 | iLabelWidget *item = i.object; | 1146 | iLabelWidget *item = i.object; |