comparison ios/dw.m @ 2807:975df4680ff7

iOS: Need to trigger window menu rebuilds if a menu item changes. Currently if code changes the checked or enabled state of a menu item it triggers a repopulation of all menus on all windows. We may be able to reduce this by attempting to detect which window the menu item is a descendant of and only repopulate that menu... however this will do for now.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Wed, 20 Jul 2022 19:22:06 +0000
parents deefe6f5d716
children 9c9b680f7772
comparison
equal deleted inserted replaced
2806:d7b6e19e44d2 2807:975df4680ff7
713 { 713 {
714 UIMenu *menu; 714 UIMenu *menu;
715 NSMutableArray *children; 715 NSMutableArray *children;
716 NSString *title; 716 NSString *title;
717 unsigned long tag; 717 unsigned long tag;
718 UIWindow *window;
718 } 719 }
719 -(id)initWithTag:(unsigned long)newtag; 720 -(id)initWithTag:(unsigned long)newtag;
720 -(void)setTitle:(NSString *)input; 721 -(void)setTitle:(NSString *)input;
721 -(UIMenu *)menu; 722 -(UIMenu *)menu;
722 -(unsigned long)tag; 723 -(unsigned long)tag;
811 -(void)layoutSubviews; 812 -(void)layoutSubviews;
812 -(void)setMenu:(DWMenu *)input; 813 -(void)setMenu:(DWMenu *)input;
813 -(void)setPopupMenu:(DWMenu *)input; 814 -(void)setPopupMenu:(DWMenu *)input;
814 -(DWMenu *)menu; 815 -(DWMenu *)menu;
815 -(DWMenu *)popupMenu; 816 -(DWMenu *)popupMenu;
817 -(void)updateMenu;
816 -(void *)userdata; 818 -(void *)userdata;
817 -(void)setUserdata:(void *)input; 819 -(void)setUserdata:(void *)input;
818 @end 820 @end
819 821
820 @implementation DWWindow 822 @implementation DWWindow
832 -(int)shown { return shown; } 834 -(int)shown { return shown; }
833 -(void)setShown:(int)val { shown = val; } 835 -(void)setShown:(int)val { shown = val; }
834 -(void)layoutSubviews { } 836 -(void)layoutSubviews { }
835 -(void)setMenu:(DWMenu *)input { [windowmenu release]; windowmenu = input; [windowmenu retain]; } 837 -(void)setMenu:(DWMenu *)input { [windowmenu release]; windowmenu = input; [windowmenu retain]; }
836 -(void)setPopupMenu:(DWMenu *)input { [popupmenu release]; popupmenu = input; [popupmenu retain]; } 838 -(void)setPopupMenu:(DWMenu *)input { [popupmenu release]; popupmenu = input; [popupmenu retain]; }
839 -(void)updateMenu
840 {
841 if(windowmenu)
842 {
843 NSArray *array = [[[self rootViewController] view] subviews];
844 UINavigationBar *nav = nil;
845
846 for(id obj in array)
847 {
848 if([obj isMemberOfClass:[UINavigationBar class]])
849 nav = obj;
850 }
851 if(nav)
852 {
853 UINavigationItem *item = [[nav items] firstObject];
854
855 if (@available(iOS 14.0, *)) {
856 if(item && item.rightBarButtonItem && item.rightBarButtonItem.menu)
857 [item.rightBarButtonItem setMenu:[windowmenu menu]];
858 }
859 }
860 }
861 }
837 -(DWMenu *)menu { return windowmenu; } 862 -(DWMenu *)menu { return windowmenu; }
838 -(DWMenu *)popupMenu { return popupmenu; } 863 -(DWMenu *)popupMenu { return popupmenu; }
839 -(void)closeWindow:(id)sender 864 -(void)closeWindow:(id)sender
840 { 865 {
841 if(_dw_event_handler(self, nil, _DW_EVENT_DELETE) < 1) 866 if(_dw_event_handler(self, nil, _DW_EVENT_DELETE) < 1)
1843 if(@available(iOS 14.0, *)) 1868 if(@available(iOS 14.0, *))
1844 menu = [UIMenu menuWithChildren:menuchildren]; 1869 menu = [UIMenu menuWithChildren:menuchildren];
1845 else 1870 else
1846 menu = [UIMenu menuWithTitle:@"" children:menuchildren]; 1871 menu = [UIMenu menuWithTitle:@"" children:menuchildren];
1847 } 1872 }
1873 [menu retain];
1848 if(oldmenu) 1874 if(oldmenu)
1849 [oldmenu release]; 1875 [oldmenu release];
1850 return menu; 1876 return menu;
1851 } 1877 }
1852 -(void)addItem:(id)item 1878 -(void)addItem:(id)item
1868 return child; 1894 return child;
1869 } 1895 }
1870 } 1896 }
1871 return nil; 1897 return nil;
1872 } 1898 }
1873 -(void)dealloc { [super dealloc]; } 1899 -(void)dealloc
1900 {
1901 if(menu)
1902 [menu release];
1903 [super dealloc];
1904 }
1874 @end 1905 @end
1875 1906
1876 @implementation DWImage 1907 @implementation DWImage
1877 -(id)initWithSize:(CGSize)size 1908 -(id)initWithSize:(CGSize)size
1878 { 1909 {
8591 nstr = [NSString stringWithUTF8String:newtitle]; 8622 nstr = [NSString stringWithUTF8String:newtitle];
8592 free(newtitle); 8623 free(newtitle);
8593 8624
8594 item = [DWMenuItem actionWithTitle:nstr image:nil identifier:nil 8625 item = [DWMenuItem actionWithTitle:nstr image:nil identifier:nil
8595 handler:^(__kindof UIAction * _Nonnull action) { 8626 handler:^(__kindof UIAction * _Nonnull action) {
8627 if(check)
8628 {
8629 UIMenuElementState state = [item state] == UIMenuElementStateOn ? UIMenuElementStateOff : UIMenuElementStateOn;
8630 [item setState:state];
8631 }
8596 [DWObj menuHandler:item]; 8632 [DWObj menuHandler:item];
8633 if(check)
8634 {
8635 for(id obj in _dw_toplevel_windows)
8636 [obj updateMenu];
8637 }
8597 }]; 8638 }];
8598 /* Don't set the tag if the ID is 0 or -1 */ 8639 /* Don't set the tag if the ID is 0 or -1 */
8599 if(itemid != DW_MENU_AUTO && itemid != DW_MENU_POPUP) 8640 if(itemid != DW_MENU_AUTO && itemid != DW_MENU_POPUP)
8600 [item setTag:itemid]; 8641 [item setTag:itemid];
8601 [menu addItem:item]; 8642 [menu addItem:item];
8633 id menu = menux; 8674 id menu = menux;
8634 DWMenuItem *menuitem = [menu childWithTag:itemid]; 8675 DWMenuItem *menuitem = [menu childWithTag:itemid];
8635 8676
8636 if(menuitem != nil) 8677 if(menuitem != nil)
8637 { 8678 {
8638 if(check) 8679 UIMenuElementState newstate = check ? UIMenuElementStateOn : UIMenuElementStateOff;
8639 [menuitem setState:UIMenuElementStateOn]; 8680
8640 else 8681 /* Only force the menus to repopulate if something changed */
8641 [menuitem setState:UIMenuElementStateOff]; 8682 if(newstate != [menuitem state])
8683 {
8684 [menuitem setState:newstate];
8685 for(id obj in _dw_toplevel_windows)
8686 [obj updateMenu];
8687 }
8642 } 8688 }
8643 } 8689 }
8644 8690
8645 /* 8691 /*
8646 * Deletes the menu item specified. 8692 * Deletes the menu item specified.
8676 id menu = menux; 8722 id menu = menux;
8677 DWMenuItem *menuitem = [menu childWithTag:itemid]; 8723 DWMenuItem *menuitem = [menu childWithTag:itemid];
8678 8724
8679 if(menuitem != nil) 8725 if(menuitem != nil)
8680 { 8726 {
8727 UIMenuElementState oldstate = [menuitem state];
8728 BOOL oldenabled = [menuitem enabled];
8729
8681 if(state & DW_MIS_CHECKED) 8730 if(state & DW_MIS_CHECKED)
8682 {
8683 [menuitem setState:UIMenuElementStateOn]; 8731 [menuitem setState:UIMenuElementStateOn];
8684 }
8685 else if(state & DW_MIS_UNCHECKED) 8732 else if(state & DW_MIS_UNCHECKED)
8686 {
8687 [menuitem setState:UIMenuElementStateOff]; 8733 [menuitem setState:UIMenuElementStateOff];
8688 }
8689 if(state & DW_MIS_ENABLED) 8734 if(state & DW_MIS_ENABLED)
8690 {
8691 [menuitem setEnabled:YES]; 8735 [menuitem setEnabled:YES];
8692 }
8693 else if(state & DW_MIS_DISABLED) 8736 else if(state & DW_MIS_DISABLED)
8694 {
8695 [menuitem setEnabled:NO]; 8737 [menuitem setEnabled:NO];
8738
8739 /* Only force the menus to repopulate if something changed */
8740 if(oldstate != [menuitem state] || oldenabled != [menuitem enabled])
8741 {
8742 for(id obj in _dw_toplevel_windows)
8743 [obj updateMenu];
8696 } 8744 }
8697 } 8745 }
8698 } 8746 }
8699 8747
8700 /* Gets the notebook page from associated ID */ 8748 /* Gets the notebook page from associated ID */
9195 [mle setTextAlignment:(style & mask)]; 9243 [mle setTextAlignment:(style & mask)];
9196 } 9244 }
9197 else if([object isMemberOfClass:[DWMenuItem class]]) 9245 else if([object isMemberOfClass:[DWMenuItem class]])
9198 { 9246 {
9199 DWMenuItem *menuitem = object; 9247 DWMenuItem *menuitem = object;
9248 UIMenuElementState oldstate = [menuitem state];
9249 BOOL oldenabled = [menuitem enabled];
9200 9250
9201 if(mask & (DW_MIS_CHECKED | DW_MIS_UNCHECKED)) 9251 if(mask & (DW_MIS_CHECKED | DW_MIS_UNCHECKED))
9202 { 9252 {
9203 if(style & DW_MIS_CHECKED) 9253 if(style & DW_MIS_CHECKED)
9204 [menuitem setState:UIMenuElementStateOn]; 9254 [menuitem setState:UIMenuElementStateOn];
9209 { 9259 {
9210 if(style & DW_MIS_ENABLED) 9260 if(style & DW_MIS_ENABLED)
9211 [menuitem setEnabled:YES]; 9261 [menuitem setEnabled:YES];
9212 else if(style & DW_MIS_DISABLED) 9262 else if(style & DW_MIS_DISABLED)
9213 [menuitem setEnabled:NO]; 9263 [menuitem setEnabled:NO];
9264 }
9265 /* Only force the menus to repopulate if something changed */
9266 if(oldstate != [menuitem state] || oldenabled != [menuitem enabled])
9267 {
9268 for(id obj in _dw_toplevel_windows)
9269 [obj updateMenu];
9214 } 9270 }
9215 } 9271 }
9216 DW_FUNCTION_RETURN_NOTHING; 9272 DW_FUNCTION_RETURN_NOTHING;
9217 } 9273 }
9218 9274