src/video/uikit/SDL_uikitmessagebox.m
author Sam Lantinga
Fri, 27 Jan 2017 06:05:50 -0800
changeset 10856 486aa38c6a88
parent 10737 3406a0f8b041
child 11505 4f3f29b6b666
permissions -rw-r--r--
Added Thrustmaster Wheel FFB entry to the list of wheels
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../../SDL_internal.h"
    22 
    23 #if SDL_VIDEO_DRIVER_UIKIT
    24 
    25 #include "SDL.h"
    26 #include "SDL_uikitvideo.h"
    27 #include "SDL_uikitwindow.h"
    28 
    29 /* Display a UIKit message box */
    30 
    31 static SDL_bool s_showingMessageBox = SDL_FALSE;
    32 
    33 SDL_bool
    34 UIKit_ShowingMessageBox(void)
    35 {
    36     return s_showingMessageBox;
    37 }
    38 
    39 static void
    40 UIKit_WaitUntilMessageBoxClosed(const SDL_MessageBoxData *messageboxdata, int *clickedindex)
    41 {
    42     *clickedindex = messageboxdata->numbuttons;
    43 
    44     @autoreleasepool {
    45         /* Run the main event loop until the alert has finished */
    46         /* Note that this needs to be done on the main thread */
    47         s_showingMessageBox = SDL_TRUE;
    48         while ((*clickedindex) == messageboxdata->numbuttons) {
    49             [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    50         }
    51         s_showingMessageBox = SDL_FALSE;
    52     }
    53 }
    54 
    55 static BOOL
    56 UIKit_ShowMessageBoxAlertController(const SDL_MessageBoxData *messageboxdata, int *buttonid)
    57 {
    58 #ifdef __IPHONE_8_0
    59     int i;
    60     int __block clickedindex = messageboxdata->numbuttons;
    61     const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
    62     UIWindow *window = nil;
    63     UIWindow *alertwindow = nil;
    64 
    65     if (![UIAlertController class]) {
    66         return NO;
    67     }
    68 
    69     UIAlertController *alert;
    70     alert = [UIAlertController alertControllerWithTitle:@(messageboxdata->title)
    71                                                 message:@(messageboxdata->message)
    72                                          preferredStyle:UIAlertControllerStyleAlert];
    73 
    74     for (i = 0; i < messageboxdata->numbuttons; i++) {
    75         UIAlertAction *action;
    76         UIAlertActionStyle style = UIAlertActionStyleDefault;
    77 
    78         if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
    79             style = UIAlertActionStyleCancel;
    80         }
    81 
    82         action = [UIAlertAction actionWithTitle:@(buttons[i].text)
    83                                           style:style
    84                                         handler:^(UIAlertAction *action) {
    85                                             clickedindex = i;
    86                                         }];
    87         [alert addAction:action];
    88     }
    89 
    90     if (messageboxdata->window) {
    91         SDL_WindowData *data = (__bridge SDL_WindowData *) messageboxdata->window->driverdata;
    92         window = data.uiwindow;
    93     }
    94 
    95     if (window == nil || window.rootViewController == nil) {
    96         alertwindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    97         alertwindow.rootViewController = [UIViewController new];
    98         alertwindow.windowLevel = UIWindowLevelAlert;
    99 
   100         window = alertwindow;
   101 
   102         [alertwindow makeKeyAndVisible];
   103     }
   104 
   105     [window.rootViewController presentViewController:alert animated:YES completion:nil];
   106     UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
   107 
   108     if (alertwindow) {
   109         alertwindow.hidden = YES;
   110     }
   111 
   112     *buttonid = messageboxdata->buttons[clickedindex].buttonid;
   113     return YES;
   114 #else
   115     return NO;
   116 #endif /* __IPHONE_8_0 */
   117 }
   118 
   119 /* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
   120 #if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
   121 @interface SDLAlertViewDelegate : NSObject <UIAlertViewDelegate>
   122 
   123 @property (nonatomic, assign) int *clickedIndex;
   124 
   125 @end
   126 
   127 @implementation SDLAlertViewDelegate
   128 
   129 - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
   130 {
   131     if (_clickedIndex != NULL) {
   132         *_clickedIndex = (int) buttonIndex;
   133     }
   134 }
   135 
   136 @end
   137 #endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
   138 
   139 static BOOL
   140 UIKit_ShowMessageBoxAlertView(const SDL_MessageBoxData *messageboxdata, int *buttonid)
   141 {
   142     /* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
   143 #if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
   144     int i;
   145     int clickedindex = messageboxdata->numbuttons;
   146     const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
   147     UIAlertView *alert = [[UIAlertView alloc] init];
   148     SDLAlertViewDelegate *delegate = [[SDLAlertViewDelegate alloc] init];
   149 
   150     alert.delegate = delegate;
   151     alert.title = @(messageboxdata->title);
   152     alert.message = @(messageboxdata->message);
   153 
   154     for (i = 0; i < messageboxdata->numbuttons; i++) {
   155         [alert addButtonWithTitle:@(buttons[i].text)];
   156     }
   157 
   158     delegate.clickedIndex = &clickedindex;
   159 
   160     [alert show];
   161 
   162     UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
   163 
   164     alert.delegate = nil;
   165 
   166     *buttonid = messageboxdata->buttons[clickedindex].buttonid;
   167     return YES;
   168 #else
   169     return NO;
   170 #endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
   171 }
   172 
   173 int
   174 UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
   175 {
   176     BOOL success = NO;
   177 
   178     @autoreleasepool {
   179         success = UIKit_ShowMessageBoxAlertController(messageboxdata, buttonid);
   180         if (!success) {
   181             success = UIKit_ShowMessageBoxAlertView(messageboxdata, buttonid);
   182         }
   183     }
   184 
   185     if (!success) {
   186         return SDL_SetError("Could not show message box.");
   187     }
   188 
   189     return 0;
   190 }
   191 
   192 #endif /* SDL_VIDEO_DRIVER_UIKIT */
   193 
   194 /* vi: set ts=4 sw=4 expandtab: */