sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_uikitmessagebox.m (6748B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 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     int i;
     59     int __block clickedindex = messageboxdata->numbuttons;
     60     UIWindow *window = nil;
     61     UIWindow *alertwindow = nil;
     62 
     63     if (![UIAlertController class]) {
     64         return NO;
     65     }
     66 
     67     UIAlertController *alert;
     68     alert = [UIAlertController alertControllerWithTitle:@(messageboxdata->title)
     69                                                 message:@(messageboxdata->message)
     70                                          preferredStyle:UIAlertControllerStyleAlert];
     71 
     72     for (i = 0; i < messageboxdata->numbuttons; i++) {
     73         UIAlertAction *action;
     74         UIAlertActionStyle style = UIAlertActionStyleDefault;
     75         const SDL_MessageBoxButtonData *sdlButton;
     76 
     77         if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
     78             sdlButton = &messageboxdata->buttons[messageboxdata->numbuttons - 1 - i];
     79         } else {
     80             sdlButton = &messageboxdata->buttons[i];
     81         }
     82 
     83         if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
     84             style = UIAlertActionStyleCancel;
     85         }
     86 
     87         action = [UIAlertAction actionWithTitle:@(sdlButton->text)
     88                                 style:style
     89                                 handler:^(UIAlertAction *action) {
     90                                     clickedindex = (int)(sdlButton - messageboxdata->buttons);
     91                                 }];
     92         [alert addAction:action];
     93 
     94         if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
     95             alert.preferredAction = action;
     96         }
     97     }
     98 
     99     if (messageboxdata->window) {
    100         SDL_WindowData *data = (__bridge SDL_WindowData *) messageboxdata->window->driverdata;
    101         window = data.uiwindow;
    102     }
    103 
    104     if (window == nil || window.rootViewController == nil) {
    105         alertwindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    106         alertwindow.rootViewController = [UIViewController new];
    107         alertwindow.windowLevel = UIWindowLevelAlert;
    108 
    109         window = alertwindow;
    110 
    111         [alertwindow makeKeyAndVisible];
    112     }
    113 
    114     [window.rootViewController presentViewController:alert animated:YES completion:nil];
    115     UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
    116 
    117     if (alertwindow) {
    118         alertwindow.hidden = YES;
    119     }
    120 
    121     UIKit_ForceUpdateHomeIndicator();
    122 
    123     *buttonid = messageboxdata->buttons[clickedindex].buttonid;
    124     return YES;
    125 }
    126 
    127 /* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
    128 #if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
    129 @interface SDLAlertViewDelegate : NSObject <UIAlertViewDelegate>
    130 
    131 @property (nonatomic, assign) int *clickedIndex;
    132 
    133 @end
    134 
    135 @implementation SDLAlertViewDelegate
    136 
    137 - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
    138 {
    139     if (_clickedIndex != NULL) {
    140         *_clickedIndex = (int) buttonIndex;
    141     }
    142 }
    143 
    144 @end
    145 #endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
    146 
    147 static BOOL
    148 UIKit_ShowMessageBoxAlertView(const SDL_MessageBoxData *messageboxdata, int *buttonid)
    149 {
    150     /* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
    151 #if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
    152     int i;
    153     int clickedindex = messageboxdata->numbuttons;
    154     UIAlertView *alert = [[UIAlertView alloc] init];
    155     SDLAlertViewDelegate *delegate = [[SDLAlertViewDelegate alloc] init];
    156 
    157     alert.delegate = delegate;
    158     alert.title = @(messageboxdata->title);
    159     alert.message = @(messageboxdata->message);
    160 
    161     for (i = 0; i < messageboxdata->numbuttons; i++) {
    162         const SDL_MessageBoxButtonData *sdlButton;
    163         if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
    164             sdlButton = &messageboxdata->buttons[messageboxdata->numbuttons - 1 - i];
    165         } else {
    166             sdlButton = &messageboxdata->buttons[i];
    167         }
    168         [alert addButtonWithTitle:@(sdlButton->text)];
    169     }
    170 
    171     delegate.clickedIndex = &clickedindex;
    172 
    173     [alert show];
    174 
    175     UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
    176 
    177     alert.delegate = nil;
    178 
    179     if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
    180         clickedindex = messageboxdata->numbuttons - 1 - clickedindex;
    181     }
    182     *buttonid = messageboxdata->buttons[clickedindex].buttonid;
    183     return YES;
    184 #else
    185     return NO;
    186 #endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
    187 }
    188 
    189 int
    190 UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
    191 {
    192     BOOL success = NO;
    193 
    194     @autoreleasepool {
    195         success = UIKit_ShowMessageBoxAlertController(messageboxdata, buttonid);
    196         if (!success) {
    197             success = UIKit_ShowMessageBoxAlertView(messageboxdata, buttonid);
    198         }
    199     }
    200 
    201     if (!success) {
    202         return SDL_SetError("Could not show message box.");
    203     }
    204 
    205     return 0;
    206 }
    207 
    208 #endif /* SDL_VIDEO_DRIVER_UIKIT */
    209 
    210 /* vi: set ts=4 sw=4 expandtab: */