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