summaryrefslogtreecommitdiff
path: root/src/ui/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/util.c')
-rw-r--r--src/ui/util.c122
1 files changed, 121 insertions, 1 deletions
diff --git a/src/ui/util.c b/src/ui/util.c
index 38977b96..0baf541d 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -44,6 +44,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
44# include "../ios.h" 44# include "../ios.h"
45#endif 45#endif
46 46
47#if defined (iPlatformAppleDesktop)
48# include "macos.h"
49#endif
50
47#include <the_Foundation/math.h> 51#include <the_Foundation/math.h>
48#include <the_Foundation/path.h> 52#include <the_Foundation/path.h>
49#include <SDL_timer.h> 53#include <SDL_timer.h>
@@ -749,10 +753,65 @@ void makeMenuItems_Widget(iWidget *menu, const iMenuItem *items, size_t n) {
749 } 753 }
750 } 754 }
751 } 755 }
752 }} 756 }
757}
758
759static iArray *deepCopyMenuItems_(iWidget *menu, const iMenuItem *items, size_t n) {
760 iArray *array = new_Array(sizeof(iMenuItem));
761 iString cmd;
762 init_String(&cmd);
763 for (size_t i = 0; i < n; i++) {
764 const iMenuItem *item = &items[i];
765 const char *itemCommand = item->command;
766#if 0
767 if (itemCommand) {
768 /* Make it appear the command is coming from the right widget. */
769 setCStr_String(&cmd, itemCommand);
770 if (!hasLabel_Command(itemCommand, "ptr")) {
771 size_t firstSpace = indexOf_String(&cmd, ' ');
772 iBlock ptr;
773 init_Block(&ptr, 0);
774 printf_Block(&ptr, " ptr:%p", menu);
775 if (firstSpace != iInvalidPos) {
776 insertData_Block(&cmd.chars, firstSpace, data_Block(&ptr), size_Block(&ptr));
777 }
778 else {
779 append_Block(&cmd.chars, &ptr);
780 }
781 deinit_Block(&ptr);
782 }
783 itemCommand = cstr_String(&cmd);
784 }
785#endif
786 pushBack_Array(array, &(iMenuItem){
787 item->label ? strdup(item->label) : NULL,
788 item->key,
789 item->kmods,
790 itemCommand ? strdup(itemCommand) : NULL /* NOTE: Only works with string commands. */
791 });
792 }
793 deinit_String(&cmd);
794 return array;
795}
796
797static void deleteMenuItems_(iArray *items) {
798 iForEach(Array, i, items) {
799 iMenuItem *item = i.value;
800 free((void *) item->label);
801 free((void *) item->command);
802 }
803 delete_Array(items);
804}
753 805
754iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { 806iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) {
755 iWidget *menu = new_Widget(); 807 iWidget *menu = new_Widget();
808#if defined (iHaveNativeMenus)
809 setFlags_Widget(menu, hidden_WidgetFlag | nativeMenu_WidgetFlag, iTrue);
810 setUserData_Object(menu, deepCopyMenuItems_(menu, items, n));
811 addChild_Widget(parent, menu);
812 iRelease(menu); /* owned by parent now */
813#else
814 /* Non-native custom popup menu. This may still be displayed inside a separate window. */
756 setDrawBufferEnabled_Widget(menu, iTrue); 815 setDrawBufferEnabled_Widget(menu, iTrue);
757 setBackgroundColor_Widget(menu, uiBackgroundMenu_ColorId); 816 setBackgroundColor_Widget(menu, uiBackgroundMenu_ColorId);
758 if (deviceType_App() != desktop_AppDeviceType) { 817 if (deviceType_App() != desktop_AppDeviceType) {
@@ -777,6 +836,7 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) {
777 iWidget *cancel = addAction_Widget(menu, SDLK_ESCAPE, 0, "cancel"); 836 iWidget *cancel = addAction_Widget(menu, SDLK_ESCAPE, 0, "cancel");
778 setId_Widget(cancel, "menu.cancel"); 837 setId_Widget(cancel, "menu.cancel");
779 setFlags_Widget(cancel, disabled_WidgetFlag, iTrue); 838 setFlags_Widget(cancel, disabled_WidgetFlag, iTrue);
839#endif
780 return menu; 840 return menu;
781} 841}
782 842
@@ -812,11 +872,52 @@ static void updateMenuItemFonts_Widget_(iWidget *d) {
812 } 872 }
813} 873}
814 874
875void updateMenuItemLabel_Widget(iWidget *menu, const char *command, const char *newLabel) {
876 if (~flags_Widget(menu) & nativeMenu_WidgetFlag) {
877 iLabelWidget *menuItem = findMenuItem_Widget(menu, command);
878 if (menuItem) {
879 setTextCStr_LabelWidget(menuItem, newLabel);
880 checkIcon_LabelWidget(menuItem);
881 }
882 }
883 else {
884 iArray *items = userData_Object(menu);
885 iAssert(items);
886 iForEach(Array, i, items) {
887 iMenuItem *item = i.value;
888 if (item->command && !iCmpStr(item->command, command)) {
889 free((void *) item->label);
890 item->label = strdup(newLabel);
891 break;
892 }
893 }
894 }
895}
896
815iLocalDef iBool isUsingMenuPopupWindows_(void) { 897iLocalDef iBool isUsingMenuPopupWindows_(void) {
816 return deviceType_App() == desktop_AppDeviceType; 898 return deviceType_App() == desktop_AppDeviceType;
817} 899}
818 900
901void releaseNativeMenu_Widget(iWidget *d) {
902#if defined (iHaveNativeMenus)
903 iArray *items = userData_Object(d);
904 iAssert(flags_Widget(d) & nativeMenu_WidgetFlag);
905 iAssert(items);
906 deleteMenuItems_(items);
907 setUserData_Object(d, NULL);
908#else
909 iUnused(d);
910#endif
911}
912
819void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) { 913void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) {
914#if defined (iHaveNativeMenus)
915 const iArray *items = userData_Object(d);
916 iAssert(flags_Widget(d) & nativeMenu_WidgetFlag);
917 iAssert(items);
918 showPopupMenu_MacOS(d, mouseCoord_Window(get_Window(), 0),
919 constData_Array(items), size_Array(items));
920#else
820 const iRect rootRect = rect_Root(d->root); 921 const iRect rootRect = rect_Root(d->root);
821 const iInt2 rootSize = rootRect.size; 922 const iInt2 rootSize = rootRect.size;
822 const iBool isPortraitPhone = (deviceType_App() == phone_AppDeviceType && isPortrait_App()); 923 const iBool isPortraitPhone = (deviceType_App() == phone_AppDeviceType && isPortrait_App());
@@ -904,9 +1005,13 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) {
904 postCommand_Widget(d, "menu.opened"); 1005 postCommand_Widget(d, "menu.opened");
905 } 1006 }
906 setupMenuTransition_Mobile(d, iTrue); 1007 setupMenuTransition_Mobile(d, iTrue);
1008#endif
907} 1009}
908 1010
909void closeMenu_Widget(iWidget *d) { 1011void closeMenu_Widget(iWidget *d) {
1012 if (flags_Widget(d) & nativeMenu_WidgetFlag) {
1013 return; /* Handled natively. */
1014 }
910 if (d == NULL || flags_Widget(d) & hidden_WidgetFlag) { 1015 if (d == NULL || flags_Widget(d) & hidden_WidgetFlag) {
911 return; /* Already closed. */ 1016 return; /* Already closed. */
912 } 1017 }
@@ -1780,6 +1885,21 @@ size_t findWidestLabel_MenuItem(const iMenuItem *items, size_t num) {
1780 return widestPos; 1885 return widestPos;
1781} 1886}
1782 1887
1888iChar removeIconPrefix_String(iString *d) {
1889 if (isEmpty_String(d)) {
1890 return 0;
1891 }
1892 iStringConstIterator iter;
1893 init_StringConstIterator(&iter, d);
1894 iChar icon = iter.value;
1895 next_StringConstIterator(&iter);
1896 if (iter.value == ' ' && icon >= 0x100) {
1897 remove_Block(&d->chars, 0, iter.next - constBegin_String(d));
1898 return icon;
1899 }
1900 return 0;
1901}
1902
1783iWidget *makeDialog_Widget(const char *id, 1903iWidget *makeDialog_Widget(const char *id,
1784 const iMenuItem *itemsNullTerminated, 1904 const iMenuItem *itemsNullTerminated,
1785 const iMenuItem *actions, size_t numActions) { 1905 const iMenuItem *actions, size_t numActions) {