Search
lxdream.org :: lxdream/src/cocoaui/cocoa_ctrl.m
lxdream 0.9.1
released Jun 29
Download Now
filename src/cocoaui/cocoa_ctrl.m
changeset 964:f2f3c7612d06
next1034:7044e01148f0
author nkeynes
date Thu Jan 15 04:15:11 2009 +0000 (13 years ago)
permissions -rw-r--r--
last change Add support for the Intel ICC compiler (C only, icc doesn't support Obj-C)
- Rename Obj-C source to .m
- Separate paths.c into paths_unix.c and paths_osx.m
- Add configuration detection of ICC, along with specific opt flags
file annotate diff log raw
nkeynes@964
     1
/**
nkeynes@964
     2
 * $Id$
nkeynes@964
     3
 *
nkeynes@964
     4
 * Construct and manage the controller configuration pane
nkeynes@964
     5
 *
nkeynes@964
     6
 * Copyright (c) 2008 Nathan Keynes.
nkeynes@964
     7
 *
nkeynes@964
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@964
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@964
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@964
    11
 * (at your option) any later version.
nkeynes@964
    12
 *
nkeynes@964
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@964
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@964
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@964
    16
 * GNU General Public License for more details.
nkeynes@964
    17
 */
nkeynes@964
    18
nkeynes@964
    19
#include "cocoaui.h"
nkeynes@964
    20
#include "config.h"
nkeynes@964
    21
#include "display.h"
nkeynes@964
    22
#include "maple/maple.h"
nkeynes@964
    23
nkeynes@964
    24
#include <glib/gstrfuncs.h>
nkeynes@964
    25
nkeynes@964
    26
#define MAX_DEVICES 4
nkeynes@964
    27
nkeynes@964
    28
#define KEYBINDING_SIZE 110
nkeynes@964
    29
nkeynes@964
    30
static void cocoa_config_keysym_hook(void *data, const gchar *keysym);
nkeynes@964
    31
nkeynes@964
    32
@interface KeyBindingEditor (Private)
nkeynes@964
    33
- (void)updateKeysym: (const gchar *)sym;
nkeynes@964
    34
@end
nkeynes@964
    35
nkeynes@964
    36
@implementation KeyBindingEditor
nkeynes@964
    37
- (id)init
nkeynes@964
    38
{
nkeynes@964
    39
    self = [super init];
nkeynes@964
    40
    isPrimed = NO;
nkeynes@964
    41
    lastValue = nil;
nkeynes@964
    42
    [self setFieldEditor: YES];
nkeynes@964
    43
    [self setEditable: FALSE];
nkeynes@964
    44
    return self;
nkeynes@964
    45
}
nkeynes@964
    46
- (void)dealloc
nkeynes@964
    47
{
nkeynes@964
    48
    if( lastValue != nil ) {
nkeynes@964
    49
        [lastValue release];
nkeynes@964
    50
        lastValue = nil;
nkeynes@964
    51
    }
nkeynes@964
    52
    [super dealloc];
nkeynes@964
    53
}
nkeynes@964
    54
- (void)setPrimed: (BOOL)primed
nkeynes@964
    55
{
nkeynes@964
    56
    if( primed != isPrimed ) {
nkeynes@964
    57
        isPrimed = primed;
nkeynes@964
    58
        if( primed ) {
nkeynes@964
    59
            lastValue = [[NSString stringWithString: [self string]] retain];
nkeynes@964
    60
            [self setString: @"<press key>"];
nkeynes@964
    61
            input_set_keysym_hook(cocoa_config_keysym_hook, self);            
nkeynes@964
    62
        } else {
nkeynes@964
    63
            [lastValue release];
nkeynes@964
    64
            lastValue = nil;
nkeynes@964
    65
            input_set_keysym_hook(NULL,NULL);
nkeynes@964
    66
        }
nkeynes@964
    67
    }
nkeynes@964
    68
}
nkeynes@964
    69
- (void)resignFirstResponder
nkeynes@964
    70
{
nkeynes@964
    71
    if( isPrimed ) {
nkeynes@964
    72
        [self setString: lastValue];
nkeynes@964
    73
        [self setPrimed: NO];
nkeynes@964
    74
    }
nkeynes@964
    75
    [super resignFirstResponder];
nkeynes@964
    76
}
nkeynes@964
    77
- (void)fireBindingChanged
nkeynes@964
    78
{
nkeynes@964
    79
    id delegate = [self delegate];
nkeynes@964
    80
    if( delegate != nil && [delegate respondsToSelector:@selector(textDidChange:)] ) {
nkeynes@964
    81
        [delegate textDidChange: [NSNotification notificationWithName: NSTextDidChangeNotification object: self]];
nkeynes@964
    82
    }
nkeynes@964
    83
}
nkeynes@964
    84
        
nkeynes@964
    85
- (void)updateKeysym: (const gchar *)sym
nkeynes@964
    86
{
nkeynes@964
    87
    if( sym != NULL ) {
nkeynes@964
    88
        [self setString: [NSString stringWithCString: sym]];
nkeynes@964
    89
        [self setPrimed: NO];
nkeynes@964
    90
        [self fireBindingChanged];
nkeynes@964
    91
    }
nkeynes@964
    92
}
nkeynes@964
    93
- (void)updateMousesym: (int)button
nkeynes@964
    94
{
nkeynes@964
    95
    gchar *keysym = input_keycode_to_keysym( &system_mouse_driver, (button+1) );
nkeynes@964
    96
    if( keysym != NULL ) {
nkeynes@964
    97
        [self updateKeysym: keysym ];
nkeynes@964
    98
        g_free(keysym);
nkeynes@964
    99
    }
nkeynes@964
   100
}
nkeynes@964
   101
- (void)keyPressed: (int)keycode
nkeynes@964
   102
{
nkeynes@964
   103
    gchar *keysym = input_keycode_to_keysym(NULL, keycode);
nkeynes@964
   104
    if( keysym != NULL ) {
nkeynes@964
   105
        [self updateKeysym: keysym];
nkeynes@964
   106
        g_free(keysym);
nkeynes@964
   107
    }
nkeynes@964
   108
}
nkeynes@964
   109
- (void)insertText:(id)string
nkeynes@964
   110
{
nkeynes@964
   111
    // Do nothing
nkeynes@964
   112
}
nkeynes@964
   113
- (void)mouseDown: (NSEvent *)event
nkeynes@964
   114
{
nkeynes@964
   115
    if( isPrimed ) {
nkeynes@964
   116
        [self updateMousesym: 0];
nkeynes@964
   117
    } else {
nkeynes@964
   118
        [self setPrimed: YES];
nkeynes@964
   119
        [super mouseDown: event];
nkeynes@964
   120
    }
nkeynes@964
   121
}
nkeynes@964
   122
- (void)rightMouseDown: (NSEvent *)event
nkeynes@964
   123
{
nkeynes@964
   124
    if( isPrimed ) {
nkeynes@964
   125
        [self updateMousesym: 1];
nkeynes@964
   126
    }
nkeynes@964
   127
}
nkeynes@964
   128
- (void)otherMouseDown: (NSEvent *)event
nkeynes@964
   129
{
nkeynes@964
   130
    if( isPrimed ) {
nkeynes@964
   131
        [self updateMousesym: [event buttonNumber]];
nkeynes@964
   132
    }
nkeynes@964
   133
}
nkeynes@964
   134
- (void)keyDown: (NSEvent *) event
nkeynes@964
   135
{
nkeynes@964
   136
    NSString *chars = [event characters];
nkeynes@964
   137
    if( isPrimed ) {
nkeynes@964
   138
        if( chars != NULL && [chars length] == 1 && [chars characterAtIndex: 0] == 27 ) {
nkeynes@964
   139
            // Escape char = abort change
nkeynes@964
   140
            [self setString: lastValue];
nkeynes@964
   141
            [self setPrimed: NO];
nkeynes@964
   142
        } else {
nkeynes@964
   143
            [self keyPressed: ([event keyCode]+1)];
nkeynes@964
   144
        }
nkeynes@964
   145
    } else {
nkeynes@964
   146
        if( chars != NULL && [chars length] == 1 ) {
nkeynes@964
   147
            int ch = [chars characterAtIndex: 0];
nkeynes@964
   148
            switch( ch ) {
nkeynes@964
   149
            case 0x7F:
nkeynes@964
   150
                [self setString: @""]; 
nkeynes@964
   151
                [self fireBindingChanged];
nkeynes@964
   152
                break;
nkeynes@964
   153
            case '\r':
nkeynes@964
   154
                [self setPrimed: YES];
nkeynes@964
   155
                break;
nkeynes@964
   156
            default:
nkeynes@964
   157
                [super keyDown: event];
nkeynes@964
   158
                break;
nkeynes@964
   159
            }
nkeynes@964
   160
        } else {
nkeynes@964
   161
            [super keyDown: event];
nkeynes@964
   162
        }
nkeynes@964
   163
    }
nkeynes@964
   164
}
nkeynes@964
   165
- (void)flagsChanged: (NSEvent *) event
nkeynes@964
   166
{
nkeynes@964
   167
    if( isPrimed ) {
nkeynes@964
   168
        [self keyPressed: ([event keyCode]+1)];
nkeynes@964
   169
    }
nkeynes@964
   170
    [super flagsChanged: event];
nkeynes@964
   171
}
nkeynes@964
   172
@end
nkeynes@964
   173
nkeynes@964
   174
static void cocoa_config_keysym_hook(void *data, const gchar *keysym)
nkeynes@964
   175
{
nkeynes@964
   176
    KeyBindingEditor *editor = (KeyBindingEditor *)data;
nkeynes@964
   177
    [editor updateKeysym: keysym];
nkeynes@964
   178
}
nkeynes@964
   179
nkeynes@964
   180
nkeynes@964
   181
@implementation KeyBindingField
nkeynes@964
   182
@end
nkeynes@964
   183
nkeynes@964
   184
/*************************** Key-binding sub-view ***********************/
nkeynes@964
   185
nkeynes@964
   186
#define MAX_KEY_BINDINGS 32
nkeynes@964
   187
nkeynes@964
   188
@interface ControllerKeyBindingView : NSView
nkeynes@964
   189
{
nkeynes@964
   190
    maple_device_t device;
nkeynes@964
   191
    KeyBindingField *field[MAX_KEY_BINDINGS][2];
nkeynes@964
   192
}
nkeynes@964
   193
- (id)initWithFrame: (NSRect)frameRect;
nkeynes@964
   194
- (void)setDevice: (maple_device_t)device;
nkeynes@964
   195
@end
nkeynes@964
   196
nkeynes@964
   197
@implementation ControllerKeyBindingView
nkeynes@964
   198
- (id)initWithFrame: (NSRect)frameRect
nkeynes@964
   199
{
nkeynes@964
   200
    if( [super initWithFrame: frameRect] == nil ) {
nkeynes@964
   201
        return nil;
nkeynes@964
   202
    } else {
nkeynes@964
   203
        device = NULL;
nkeynes@964
   204
        return self;
nkeynes@964
   205
    }
nkeynes@964
   206
}
nkeynes@964
   207
- (BOOL)isFlipped
nkeynes@964
   208
{
nkeynes@964
   209
    return YES;
nkeynes@964
   210
}
nkeynes@964
   211
- (void)removeSubviews
nkeynes@964
   212
{
nkeynes@964
   213
    [[self subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
nkeynes@964
   214
}
nkeynes@964
   215
- (void)controlTextDidChange: (NSNotification *)notify
nkeynes@964
   216
{
nkeynes@964
   217
    int binding = [[notify object] tag];
nkeynes@964
   218
    NSString *val1 = [field[binding][0] stringValue];
nkeynes@964
   219
    NSString *val2 = [field[binding][1] stringValue];
nkeynes@964
   220
    char buf[ [val1 length] + [val2 length] + 2 ];
nkeynes@964
   221
    const gchar *p = NULL;
nkeynes@964
   222
    
nkeynes@964
   223
    if( [val1 length] == 0 ) {
nkeynes@964
   224
        if( [val2 length] != 0 ) {
nkeynes@964
   225
            p = [val2 UTF8String];
nkeynes@964
   226
        }
nkeynes@964
   227
    } else if( [val2 length] == 0 ) {
nkeynes@964
   228
        p = [val1 UTF8String];
nkeynes@964
   229
    } else {
nkeynes@964
   230
        sprintf( buf, "%s,%s", [val1 UTF8String], [val2 UTF8String] );
nkeynes@964
   231
        p = buf;
nkeynes@964
   232
    }
nkeynes@964
   233
    maple_set_device_config_value( device, binding, p ); 
nkeynes@964
   234
    lxdream_save_config();
nkeynes@964
   235
}
nkeynes@964
   236
- (void)setDevice: (maple_device_t)newDevice
nkeynes@964
   237
{
nkeynes@964
   238
    device = newDevice;
nkeynes@964
   239
    [self removeSubviews];
nkeynes@964
   240
    if( device != NULL ) {
nkeynes@964
   241
        lxdream_config_entry_t config = maple_get_device_config(device);
nkeynes@964
   242
        if( config != NULL ) {
nkeynes@964
   243
            int count, i, y, x;
nkeynes@964
   244
nkeynes@964
   245
            for( count=0; config[count].key != NULL; count++ );
nkeynes@964
   246
            x = TEXT_GAP;
nkeynes@964
   247
            NSSize size = NSMakeSize(85+KEYBINDING_SIZE*2+TEXT_GAP*4, count*(TEXT_HEIGHT+TEXT_GAP)+TEXT_GAP);
nkeynes@964
   248
            [self setFrameSize: size];
nkeynes@964
   249
            [self scrollRectToVisible: NSMakeRect(0,0,1,1)]; 
nkeynes@964
   250
            y = TEXT_GAP;
nkeynes@964
   251
            for( i=0; config[i].key != NULL; i++ ) {
nkeynes@964
   252
                NSRect frame = NSMakeRect(x, y + 2, 85, LABEL_HEIGHT);
nkeynes@964
   253
                NSTextField *label = cocoa_gui_add_label(self, NS_(config[i].label), frame);
nkeynes@964
   254
                [label setAlignment: NSRightTextAlignment];
nkeynes@964
   255
nkeynes@964
   256
                frame = NSMakeRect( x + 85 + TEXT_GAP, y, KEYBINDING_SIZE, TEXT_HEIGHT);
nkeynes@964
   257
                field[i][0] = [[KeyBindingField alloc] initWithFrame: frame];
nkeynes@964
   258
                [field[i][0] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
nkeynes@964
   259
                [field[i][0] setTag: i];
nkeynes@964
   260
                [field[i][0] setDelegate: self];
nkeynes@964
   261
                [self addSubview: field[i][0]];
nkeynes@964
   262
                
nkeynes@964
   263
                frame = NSMakeRect( x + 85 + KEYBINDING_SIZE + (TEXT_GAP*2), y, KEYBINDING_SIZE, TEXT_HEIGHT);
nkeynes@964
   264
                field[i][1] = [[KeyBindingField alloc] initWithFrame: frame];
nkeynes@964
   265
                [field[i][1] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
nkeynes@964
   266
                [field[i][1] setTag: i];
nkeynes@964
   267
                [field[i][1] setDelegate: self];
nkeynes@964
   268
                [self addSubview: field[i][1]];
nkeynes@964
   269
nkeynes@964
   270
                if( config[i].value != NULL ) {
nkeynes@964
   271
                    gchar **parts = g_strsplit(config[i].value,",",3);
nkeynes@964
   272
                    if( parts[0] != NULL ) {
nkeynes@964
   273
                        [field[i][0] setStringValue: [NSString stringWithCString: parts[0]]];
nkeynes@964
   274
                        if( parts[1] != NULL ) {
nkeynes@964
   275
                            [field[i][1] setStringValue: [NSString stringWithCString: parts[1]]];
nkeynes@964
   276
                        }
nkeynes@964
   277
                    }
nkeynes@964
   278
                    g_strfreev(parts);
nkeynes@964
   279
                }
nkeynes@964
   280
                
nkeynes@964
   281
                y += (TEXT_HEIGHT + TEXT_GAP);
nkeynes@964
   282
            }
nkeynes@964
   283
        } else {
nkeynes@964
   284
            [self setFrameSize: NSMakeSize(100,TEXT_HEIGHT+TEXT_GAP) ];
nkeynes@964
   285
        }
nkeynes@964
   286
    } else {
nkeynes@964
   287
        [self setFrameSize: NSMakeSize(100,TEXT_HEIGHT+TEXT_GAP) ];
nkeynes@964
   288
    }
nkeynes@964
   289
}
nkeynes@964
   290
@end
nkeynes@964
   291
nkeynes@964
   292
/*************************** Top-level controller pane ***********************/
nkeynes@964
   293
nkeynes@964
   294
@interface LxdreamPrefsControllerPane: LxdreamPrefsPane
nkeynes@964
   295
{
nkeynes@964
   296
    struct maple_device *save_controller[4];
nkeynes@964
   297
    NSButton *radio[4];
nkeynes@964
   298
    ControllerKeyBindingView *key_bindings;
nkeynes@964
   299
}
nkeynes@964
   300
+ (LxdreamPrefsControllerPane *)new;
nkeynes@964
   301
@end
nkeynes@964
   302
nkeynes@964
   303
@implementation LxdreamPrefsControllerPane
nkeynes@964
   304
+ (LxdreamPrefsControllerPane *)new
nkeynes@964
   305
{
nkeynes@964
   306
    return [[LxdreamPrefsControllerPane alloc] initWithFrame: NSMakeRect(0,0,600,400)];
nkeynes@964
   307
}
nkeynes@964
   308
- (id)initWithFrame: (NSRect)frameRect
nkeynes@964
   309
{
nkeynes@964
   310
    if( [super initWithFrame: frameRect title: NS_("Controllers")] == nil ) {
nkeynes@964
   311
        return nil;
nkeynes@964
   312
    } else {
nkeynes@964
   313
        const struct maple_device_class **devices = maple_get_device_classes();
nkeynes@964
   314
        char buf[16];
nkeynes@964
   315
        int i,j;
nkeynes@964
   316
        int y = [self contentHeight] - TEXT_HEIGHT - TEXT_GAP;
nkeynes@964
   317
nkeynes@964
   318
        NSBox *rule = [[NSBox alloc] initWithFrame: 
nkeynes@964
   319
                NSMakeRect(210+(TEXT_GAP*3), 1, 1, [self contentHeight] + TEXT_GAP - 2)];
nkeynes@964
   320
        [rule setAutoresizingMask: (NSViewMaxXMargin|NSViewHeightSizable)];
nkeynes@964
   321
        [rule setBoxType: NSBoxSeparator];
nkeynes@964
   322
        [self addSubview: rule];
nkeynes@964
   323
        
nkeynes@964
   324
        NSRect bindingFrame = NSMakeRect(210+(TEXT_GAP*4), 0,
nkeynes@964
   325
                   frameRect.size.width - (210+(TEXT_GAP*4)), [self contentHeight] + TEXT_GAP );
nkeynes@964
   326
        NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame: bindingFrame];
nkeynes@964
   327
        key_bindings = [[ControllerKeyBindingView alloc] initWithFrame: bindingFrame ];
nkeynes@964
   328
        [scrollView setAutoresizingMask: (NSViewWidthSizable|NSViewHeightSizable)];
nkeynes@964
   329
        [scrollView setDocumentView: key_bindings];
nkeynes@964
   330
        [scrollView setDrawsBackground: NO];
nkeynes@964
   331
        [scrollView setHasVerticalScroller: YES];
nkeynes@964
   332
        [scrollView setAutohidesScrollers: YES];
nkeynes@964
   333
 
nkeynes@964
   334
        [self addSubview: scrollView];
nkeynes@964
   335
        [key_bindings setDevice: maple_get_device(0,0)];
nkeynes@964
   336
        
nkeynes@964
   337
        for( i=0; i<MAX_DEVICES; i++ ) {
nkeynes@964
   338
            int x = TEXT_GAP;
nkeynes@964
   339
            save_controller[i] = NULL;
nkeynes@964
   340
            maple_device_t device = maple_get_device(i,0);
nkeynes@964
   341
nkeynes@964
   342
            snprintf( buf, sizeof(buf), _("Slot %d."), i );
nkeynes@964
   343
            radio[i] = [[NSButton alloc] initWithFrame: NSMakeRect( x, y, 60, TEXT_HEIGHT )];
nkeynes@964
   344
            [radio[i] setTitle: [NSString stringWithUTF8String: buf]];
nkeynes@964
   345
            [radio[i] setTag: i];
nkeynes@964
   346
            [radio[i] setButtonType: NSRadioButton];
nkeynes@964
   347
            [radio[i] setAlignment: NSRightTextAlignment];
nkeynes@964
   348
            [radio[i] setTarget: self];
nkeynes@964
   349
            [radio[i] setAction: @selector(radioChanged:)];
nkeynes@964
   350
            [radio[i] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
nkeynes@964
   351
            [self addSubview: radio[i]];
nkeynes@964
   352
            x += 60 + TEXT_GAP;
nkeynes@964
   353
nkeynes@964
   354
            NSPopUpButton *popup = [[NSPopUpButton alloc] initWithFrame: NSMakeRect(x,y,150,TEXT_HEIGHT) 
nkeynes@964
   355
                                                          pullsDown: NO];
nkeynes@964
   356
            [popup addItemWithTitle: NS_("<empty>")];
nkeynes@964
   357
            [popup setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
nkeynes@964
   358
            [[popup itemAtIndex: 0] setTag: 0];
nkeynes@964
   359
            for( j=0; devices[j] != NULL; j++ ) {
nkeynes@964
   360
                [popup addItemWithTitle: [NSString stringWithUTF8String: devices[j]->name]];
nkeynes@964
   361
                if( device != NULL && device->device_class == devices[j] ) {
nkeynes@964
   362
                    [popup selectItemAtIndex: (j+1)];
nkeynes@964
   363
                }
nkeynes@964
   364
                [[popup itemAtIndex: (j+1)] setTag: (j+1)];
nkeynes@964
   365
            }
nkeynes@964
   366
            [popup setTarget: self];
nkeynes@964
   367
            [popup setAction: @selector(deviceChanged:)];
nkeynes@964
   368
            [popup setTag: i];
nkeynes@964
   369
            [self addSubview: popup];
nkeynes@964
   370
            y -= (TEXT_HEIGHT+TEXT_GAP);
nkeynes@964
   371
        }
nkeynes@964
   372
        
nkeynes@964
   373
        [radio[0] setState: NSOnState];
nkeynes@964
   374
        return self;
nkeynes@964
   375
    }
nkeynes@964
   376
}
nkeynes@964
   377
- (void)radioChanged: (id)sender
nkeynes@964
   378
{
nkeynes@964
   379
    int slot = [sender tag];
nkeynes@964
   380
    int i;
nkeynes@964
   381
    for( i=0; i<MAX_DEVICES; i++ ) {
nkeynes@964
   382
        if( i != slot ) {
nkeynes@964
   383
            [radio[i] setState: NSOffState];
nkeynes@964
   384
        }
nkeynes@964
   385
    }
nkeynes@964
   386
    [key_bindings setDevice: maple_get_device(slot,0)];
nkeynes@964
   387
}
nkeynes@964
   388
- (void)deviceChanged: (id)sender
nkeynes@964
   389
{
nkeynes@964
   390
    int slot = [sender tag];
nkeynes@964
   391
    int new_device_idx = [sender indexOfSelectedItem] - 1, i; 
nkeynes@964
   392
    maple_device_class_t new_device_class = NULL;
nkeynes@964
   393
    
nkeynes@964
   394
    for( i=0; i<MAX_DEVICES; i++ ) {
nkeynes@964
   395
        if( i == slot ) {
nkeynes@964
   396
            [radio[i] setState: NSOnState];
nkeynes@964
   397
        } else {
nkeynes@964
   398
            [radio[i] setState: NSOffState];
nkeynes@964
   399
        }
nkeynes@964
   400
    }
nkeynes@964
   401
    
nkeynes@964
   402
    maple_device_t current = maple_get_device(slot,0);
nkeynes@964
   403
    maple_device_t new_device = NULL;
nkeynes@964
   404
    if( new_device_idx != -1 ) {
nkeynes@964
   405
        new_device_class = maple_get_device_classes()[new_device_idx];
nkeynes@964
   406
    }
nkeynes@964
   407
    if( current == NULL ? new_device_class == NULL : current->device_class == new_device_class ) {
nkeynes@964
   408
        // No change
nkeynes@964
   409
        [key_bindings setDevice: current];
nkeynes@964
   410
        return;
nkeynes@964
   411
    }
nkeynes@964
   412
    if( current != NULL && current->device_class == &controller_class ) {
nkeynes@964
   413
        save_controller[slot] = current->clone(current);
nkeynes@964
   414
    }
nkeynes@964
   415
    if( new_device_class == NULL ) {
nkeynes@964
   416
        maple_detach_device(slot,0);
nkeynes@964
   417
    } else {
nkeynes@964
   418
        if( new_device_class == &controller_class && save_controller[slot] != NULL ) {
nkeynes@964
   419
            new_device = save_controller[slot];
nkeynes@964
   420
            save_controller[slot] = NULL;
nkeynes@964
   421
        } else {
nkeynes@964
   422
            new_device = maple_new_device( new_device_class->name );
nkeynes@964
   423
        }
nkeynes@964
   424
        maple_attach_device(new_device,slot,0);
nkeynes@964
   425
    }
nkeynes@964
   426
    [key_bindings setDevice: maple_get_device(slot,0)];
nkeynes@964
   427
    lxdream_save_config();
nkeynes@964
   428
}
nkeynes@964
   429
@end
nkeynes@964
   430
nkeynes@964
   431
NSView *cocoa_gui_create_prefs_controller_pane()
nkeynes@964
   432
{
nkeynes@964
   433
    return [LxdreamPrefsControllerPane new];
nkeynes@964
   434
}
.