Mercurial > dwindows
comparison ios/dw.m @ 2569:97b30df25fd1
iOS: If DW_FCF_TITLEBAR is passed to dw_window_new() create a UINavigationBar
and an options menu similar to how it works on Android. The options menu
will only function on iOS 14 or higher, but the Navigation bar like a
titlebar will work on iOS 13 without the menu.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Thu, 20 May 2021 10:06:07 +0000 |
parents | bb75e64e6138 |
children | 2c2941e01b67 |
comparison
equal
deleted
inserted
replaced
2568:b536b7b21682 | 2569:97b30df25fd1 |
---|---|
772 -(void)layoutSubviews { }; | 772 -(void)layoutSubviews { }; |
773 @end | 773 @end |
774 | 774 |
775 @interface DWWindow : UIWindow | 775 @interface DWWindow : UIWindow |
776 { | 776 { |
777 UIMenu *popupmenu; | 777 DWMenu *windowmenu, *popupmenu; |
778 int redraw; | 778 int redraw; |
779 int shown; | 779 int shown; |
780 } | 780 } |
781 -(void)sendEvent:(UIEvent *)theEvent; | 781 -(void)sendEvent:(UIEvent *)theEvent; |
782 -(void)keyDown:(UIEvent *)theEvent; | 782 -(void)keyDown:(UIEvent *)theEvent; |
784 -(int)redraw; | 784 -(int)redraw; |
785 -(void)setRedraw:(int)val; | 785 -(void)setRedraw:(int)val; |
786 -(int)shown; | 786 -(int)shown; |
787 -(void)setShown:(int)val; | 787 -(void)setShown:(int)val; |
788 -(void)layoutSubviews; | 788 -(void)layoutSubviews; |
789 -(UIMenu *)popupMenu; | 789 -(void)setMenu:(DWMenu *)input; |
790 -(void)setPopupMenu:(UIMenu *)input; | 790 -(void)setPopupMenu:(DWMenu *)input; |
791 -(DWMenu *)menu; | |
792 -(DWMenu *)popupMenu; | |
791 @end | 793 @end |
792 | 794 |
793 @implementation DWWindow | 795 @implementation DWWindow |
794 -(void)sendEvent:(UIEvent *)theEvent | 796 -(void)sendEvent:(UIEvent *)theEvent |
795 { | 797 { |
805 -(void)mouseDragged:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 5); } | 807 -(void)mouseDragged:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 5); } |
806 -(int)redraw { return redraw; } | 808 -(int)redraw { return redraw; } |
807 -(void)setRedraw:(int)val { redraw = val; } | 809 -(void)setRedraw:(int)val { redraw = val; } |
808 -(int)shown { return shown; } | 810 -(int)shown { return shown; } |
809 -(void)setShown:(int)val { shown = val; } | 811 -(void)setShown:(int)val { shown = val; } |
810 -(void)dealloc { dw_signal_disconnect_by_window(self); [super dealloc]; } | |
811 -(void)layoutSubviews { } | 812 -(void)layoutSubviews { } |
812 -(UIMenu *)popupMenu { return popupmenu; } | 813 -(void)setMenu:(DWMenu *)input { [windowmenu release]; windowmenu = input; [windowmenu retain]; } |
813 -(void)setPopupMenu:(UIMenu *)input { [popupmenu release]; popupmenu = input; [popupmenu retain]; } | 814 -(void)setPopupMenu:(DWMenu *)input { [popupmenu release]; popupmenu = input; [popupmenu retain]; } |
815 -(DWMenu *)menu { return windowmenu; } | |
816 -(DWMenu *)popupMenu { return popupmenu; } | |
817 -(void)dealloc | |
818 { | |
819 if(windowmenu) | |
820 [windowmenu release]; | |
821 if(popupmenu) | |
822 [popupmenu release]; | |
823 dw_signal_disconnect_by_window(self); | |
824 [super dealloc]; | |
825 } | |
814 @end | 826 @end |
815 | 827 |
816 @interface DWImage : NSObject | 828 @interface DWImage : NSObject |
817 { | 829 { |
818 UIImage *image; | 830 UIImage *image; |
1343 @end | 1355 @end |
1344 | 1356 |
1345 /* Subclass for a top-level window */ | 1357 /* Subclass for a top-level window */ |
1346 @interface DWView : DWBox /* <UIWindowDelegate> */ | 1358 @interface DWView : DWBox /* <UIWindowDelegate> */ |
1347 { | 1359 { |
1348 DWMenu *windowmenu, *popupmenu; | |
1349 CGSize oldsize; | 1360 CGSize oldsize; |
1350 } | 1361 } |
1351 -(BOOL)windowShouldClose:(id)sender; | 1362 -(BOOL)windowShouldClose:(id)sender; |
1352 -(void)setMenu:(DWMenu *)input; | |
1353 -(void)setPopupMenu:(DWMenu *)input; | |
1354 -(DWMenu *)menu; | |
1355 -(DWMenu *)popupMenu; | |
1356 -(void)windowDidBecomeMain:(id)sender; | 1363 -(void)windowDidBecomeMain:(id)sender; |
1357 -(void)menuHandler:(id)sender; | 1364 -(void)menuHandler:(id)sender; |
1358 @end | 1365 @end |
1359 | 1366 |
1360 @implementation DWView | 1367 @implementation DWView |
1369 if(newSuperview) | 1376 if(newSuperview) |
1370 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeMain:) name:UIWindowDidBecomeKeyNotification object:[newSuperview window]]; | 1377 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeMain:) name:UIWindowDidBecomeKeyNotification object:[newSuperview window]]; |
1371 } | 1378 } |
1372 -(void)dealloc | 1379 -(void)dealloc |
1373 { | 1380 { |
1374 if(windowmenu) | |
1375 { | |
1376 [windowmenu release]; | |
1377 } | |
1378 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 1381 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
1379 dw_signal_disconnect_by_window(self); | 1382 dw_signal_disconnect_by_window(self); |
1380 [super dealloc]; | 1383 [super dealloc]; |
1381 } | 1384 } |
1382 -(void)windowResized:(CGSize)size; | 1385 -(void)windowResized:(CGSize)size; |
1403 } | 1406 } |
1404 -(void)windowDidBecomeMain:(id)sender | 1407 -(void)windowDidBecomeMain:(id)sender |
1405 { | 1408 { |
1406 _dw_event_handler([self window], nil, 13); | 1409 _dw_event_handler([self window], nil, 13); |
1407 } | 1410 } |
1408 -(void)setMenu:(DWMenu *)input { windowmenu = input; [windowmenu retain]; } | |
1409 -(void)setPopupMenu:(DWMenu *)input { popupmenu = input; [popupmenu retain]; } | |
1410 -(DWMenu *)menu { return windowmenu; } | |
1411 -(DWMenu *)popupMenu { return popupmenu; } | |
1412 -(void)menuHandler:(id)sender | 1411 -(void)menuHandler:(id)sender |
1413 { | 1412 { |
1414 [DWObj menuHandler:sender]; | 1413 [DWObj menuHandler:sender]; |
1415 } | 1414 } |
1416 @end | 1415 @end |
1423 @implementation DWViewController : UIViewController {} | 1422 @implementation DWViewController : UIViewController {} |
1424 -(void)viewWillLayoutSubviews | 1423 -(void)viewWillLayoutSubviews |
1425 { | 1424 { |
1426 DWWindow *window = (DWWindow *)[[self view] window]; | 1425 DWWindow *window = (DWWindow *)[[self view] window]; |
1427 NSArray *array = [window subviews]; | 1426 NSArray *array = [window subviews]; |
1428 DWView *view = [array firstObject]; | |
1429 CGRect frame = [window frame]; | 1427 CGRect frame = [window frame]; |
1430 /* Hide the UITransitionView which is blocking the screen... | 1428 DWView *view = nil; |
1431 * This is probably not the correct solution, but it solves the | 1429 UINavigationBar *nav = nil; |
1432 * problem for the moment. Figure out what to do with this view. | 1430 NSInteger sbheight = 0; |
1433 */ | 1431 |
1434 id object = [array lastObject]; | 1432 for(id obj in array) |
1435 if(![object isMemberOfClass:[DWView class]]) | 1433 { |
1436 [object setHidden:YES]; | 1434 if([obj isMemberOfClass:[DWView class]]) |
1437 /* Adjust the frame to account for the status bar */ | 1435 view = obj; |
1438 NSInteger sbheight = [[[window windowScene] statusBarManager] statusBarFrame].size.height; | 1436 else if([obj isMemberOfClass:[UINavigationBar class]]) |
1437 nav = obj; | |
1438 /* Hide the UITransitionView which is blocking the screen... | |
1439 * This is probably not the correct solution, but it solves the | |
1440 * problem for the moment. Figure out what to do with this view. | |
1441 */ | |
1442 else | |
1443 [obj setHidden:YES]; | |
1444 } | |
1445 /* Adjust the frame to account for the status bar and navigation bar if it exists */ | |
1446 if(nav) | |
1447 { | |
1448 CGRect navrect = [nav frame]; | |
1449 | |
1450 sbheight = navrect.size.height; | |
1451 navrect.size.width = frame.size.width; | |
1452 [nav setFrame:navrect]; | |
1453 | |
1454 if (@available(iOS 14.0, *)) { | |
1455 DWMenu *windowmenu = [window menu]; | |
1456 UINavigationItem *item = [[nav items] firstObject]; | |
1457 | |
1458 if(windowmenu && !item.rightBarButtonItem) | |
1459 { | |
1460 UIBarButtonItem *options = [[UIBarButtonItem alloc] initWithImage:[UIImage systemImageNamed:@"list.bullet"] | |
1461 menu:[windowmenu menu]]; | |
1462 item.rightBarButtonItem = options; | |
1463 } | |
1464 } else { | |
1465 // Fallback on earlier versions | |
1466 } | |
1467 } | |
1468 else | |
1469 sbheight = [[[window windowScene] statusBarManager] statusBarFrame].size.height; | |
1439 frame.size.height -= sbheight; | 1470 frame.size.height -= sbheight; |
1440 /* Account for the special area on iPhone X and iPad Pro | 1471 /* Account for the special area on iPhone X and iPad Pro |
1441 * https://blog.maxrudberg.com/post/165590234593/ui-design-for-iphone-x-bottom-elements | 1472 * https://blog.maxrudberg.com/post/165590234593/ui-design-for-iphone-x-bottom-elements |
1442 */ | 1473 */ |
1443 frame.size.height -= 24; | 1474 frame.size.height -= 24; |
2124 | 2155 |
2125 _dw_event_handler(self, (UIEvent *)params, 10); | 2156 _dw_event_handler(self, (UIEvent *)params, 10); |
2126 | 2157 |
2127 if(window) | 2158 if(window) |
2128 { | 2159 { |
2129 __block UIMenu *popupmenu = [window popupMenu]; | 2160 __block UIMenu *popupmenu = [[window popupMenu] menu]; |
2130 config = [UIContextMenuConfiguration configurationWithIdentifier:@"DWContextMenu" | 2161 config = [UIContextMenuConfiguration configurationWithIdentifier:@"DWContextMenu" |
2131 previewProvider:nil | 2162 previewProvider:nil |
2132 actionProvider:^(NSArray* suggestedAction){return popupmenu;}]; | 2163 actionProvider:^(NSArray* suggestedAction){return popupmenu;}]; |
2133 [window setPopupMenu:nil]; | 2164 [window setPopupMenu:nil]; |
2134 } | 2165 } |
7547 * Parameters: | 7578 * Parameters: |
7548 * location: Handle of a window frame to be attached to. | 7579 * location: Handle of a window frame to be attached to. |
7549 */ | 7580 */ |
7550 HMENUI API dw_menubar_new(HWND location) | 7581 HMENUI API dw_menubar_new(HWND location) |
7551 { | 7582 { |
7552 /* TODO: Implement this with UIMenuSystem */ | 7583 DWWindow *window = location; |
7553 return NULL; | 7584 DWMenu *menu = [[[DWMenu alloc] init] retain]; |
7585 | |
7586 [window setMenu:menu]; | |
7587 return menu; | |
7554 } | 7588 } |
7555 | 7589 |
7556 /* | 7590 /* |
7557 * Destroys a menu created with dw_menubar_new or dw_menu_new. | 7591 * Destroys a menu created with dw_menubar_new or dw_menu_new. |
7558 * Parameters: | 7592 * Parameters: |
7963 DW_FUNCTION_ADD_PARAM3(hwndOwner, title, flStyle) | 7997 DW_FUNCTION_ADD_PARAM3(hwndOwner, title, flStyle) |
7964 DW_FUNCTION_RETURN(dw_window_new, HWND) | 7998 DW_FUNCTION_RETURN(dw_window_new, HWND) |
7965 DW_FUNCTION_RESTORE_PARAM3(DW_UNUSED(hwndOwner), HWND, title, char *, DW_UNUSED(flStyle), ULONG) | 7999 DW_FUNCTION_RESTORE_PARAM3(DW_UNUSED(hwndOwner), HWND, title, char *, DW_UNUSED(flStyle), ULONG) |
7966 { | 8000 { |
7967 DW_FUNCTION_INIT; | 8001 DW_FUNCTION_INIT; |
7968 DWWindow *window = [[DWWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; | 8002 CGRect screenrect = [[UIScreen mainScreen] bounds]; |
8003 DWWindow *window = [[DWWindow alloc] initWithFrame:screenrect]; | |
7969 DWView *view = [[DWView alloc] init]; | 8004 DWView *view = [[DWView alloc] init]; |
7970 UIUserInterfaceStyle style = [[DWObj hiddenWindow] overrideUserInterfaceStyle]; | 8005 UIUserInterfaceStyle style = [[DWObj hiddenWindow] overrideUserInterfaceStyle]; |
7971 | 8006 |
7972 [window setWindowLevel:UIWindowLevelNormal]; | 8007 [window setWindowLevel:UIWindowLevelNormal]; |
7973 [window setRootViewController:[[DWViewController alloc] init]]; | 8008 [window setRootViewController:[[DWViewController alloc] init]]; |
7974 [window addSubview:view]; | 8009 [window addSubview:view]; |
7975 [window setBackgroundColor:[UIColor systemBackgroundColor]]; | 8010 [window setBackgroundColor:[UIColor systemBackgroundColor]]; |
7976 | 8011 |
7977 /* TODO: Handle style flags... if we can? There is no visible frame */ | 8012 /* TODO: Handle style flags... if we can? There is no visible frame */ |
7978 if(@available(iOS 13.0, *)) { | 8013 if(@available(iOS 13.0, *)) { |
7979 [window setLargeContentTitle:[NSString stringWithUTF8String:title]]; | 8014 NSString *nstitle = [NSString stringWithUTF8String:title]; |
8015 [window setLargeContentTitle:nstitle]; | |
8016 if(flStyle & DW_FCF_TITLEBAR) | |
8017 { | |
8018 UINavigationBar* navbar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, screenrect.size.width, 60)]; | |
8019 UINavigationItem* navItem = [[UINavigationItem alloc] initWithTitle:nstitle]; | |
8020 | |
8021 [navbar setItems:@[navItem]]; | |
8022 [window addSubview:navbar]; | |
8023 } | |
7980 } | 8024 } |
7981 /* Copy the overrideUserInterfaceStyle property from the hiddenWindow */ | 8025 /* Copy the overrideUserInterfaceStyle property from the hiddenWindow */ |
7982 if(style != UIUserInterfaceStyleUnspecified) | 8026 if(style != UIUserInterfaceStyleUnspecified) |
7983 [window setOverrideUserInterfaceStyle:style]; | 8027 [window setOverrideUserInterfaceStyle:style]; |
7984 DW_FUNCTION_RETURN_THIS(window); | 8028 DW_FUNCTION_RETURN_THIS(window); |
8544 DW_FUNCTION_NO_RETURN(dw_window_set_text) | 8588 DW_FUNCTION_NO_RETURN(dw_window_set_text) |
8545 DW_FUNCTION_RESTORE_PARAM2(handle, HWND, text, char *) | 8589 DW_FUNCTION_RESTORE_PARAM2(handle, HWND, text, char *) |
8546 { | 8590 { |
8547 DW_FUNCTION_INIT; | 8591 DW_FUNCTION_INIT; |
8548 id object = _dw_text_handle(handle); | 8592 id object = _dw_text_handle(handle); |
8593 Item *item = NULL; | |
8549 | 8594 |
8550 if([object isKindOfClass:[UILabel class]] || [object isKindOfClass:[UITextField class]]) | 8595 if([object isKindOfClass:[UILabel class]] || [object isKindOfClass:[UITextField class]]) |
8596 { | |
8551 [object setText:[NSString stringWithUTF8String:text]]; | 8597 [object setText:[NSString stringWithUTF8String:text]]; |
8598 item = _dw_box_item(handle); | |
8599 } | |
8600 else if([object isMemberOfClass:[DWWindow class]]) | |
8601 { | |
8602 DWWindow *window = object; | |
8603 NSArray *array = [window subviews]; | |
8604 | |
8605 for(id obj in array) | |
8606 { | |
8607 if([obj isMemberOfClass:[UINavigationBar class]]) | |
8608 { | |
8609 UINavigationBar *nav = obj; | |
8610 UINavigationItem *item = [[nav items] firstObject]; | |
8611 | |
8612 [item setTitle:[NSString stringWithUTF8String:text]]; | |
8613 } | |
8614 } | |
8615 } | |
8552 #ifdef DW_INCLUDE_DEPRECATED | 8616 #ifdef DW_INCLUDE_DEPRECATED |
8553 else if([object isKindOfClass:[UIControl class]]) | 8617 else if([object isKindOfClass:[UIControl class]]) |
8554 { | 8618 { |
8555 UIControl *control = object; | 8619 UIControl *control = object; |
8556 [control setText:[NSString stringWithUTF8String:text]]; | 8620 [control setText:[NSString stringWithUTF8String:text]]; |
8621 item = _dw_box_item(handle); | |
8557 } | 8622 } |
8558 #endif | 8623 #endif |
8559 else | 8624 /* If we changed the text... |
8560 return; | 8625 * Check to see if any of the sizes need to be recalculated |
8561 /* If we changed the text... */ | 8626 */ |
8562 Item *item = _dw_box_item(handle); | |
8563 | |
8564 /* Check to see if any of the sizes need to be recalculated */ | |
8565 if(item && (item->origwidth == -1 || item->origheight == -1)) | 8627 if(item && (item->origwidth == -1 || item->origheight == -1)) |
8566 { | 8628 { |
8567 int newwidth, newheight; | 8629 int newwidth, newheight; |
8568 | 8630 |
8569 _dw_control_size(handle, &newwidth, &newheight); | 8631 _dw_control_size(handle, &newwidth, &newheight); |