filename | src/cocoaui/cocoa_ctrl.c |
changeset | 770:429ff505c450 |
prev | 765:4cd066048203 |
next | 787:6717c02ff81f |
author | nkeynes |
date | Mon Jul 28 03:41:25 2008 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Implement key-binding configuration pane for Cocoa UI Minor tweaks for consistency and static-correctness |
file | annotate | diff | log | raw |
1.1 --- a/src/cocoaui/cocoa_ctrl.c Wed Jul 23 11:11:30 2008 +00001.2 +++ b/src/cocoaui/cocoa_ctrl.c Mon Jul 28 03:41:25 2008 +00001.3 @@ -18,10 +18,254 @@1.5 #include "cocoaui.h"1.6 #include "config.h"1.7 +#include "display.h"1.8 #include "maple/maple.h"1.10 +#include <glib/gstrfuncs.h>1.11 +1.12 #define MAX_DEVICES 41.14 +static void cocoa_config_keysym_hook(void *data, const gchar *keysym);1.15 +1.16 +@interface KeyBindingEditor (Private)1.17 +- (void)updateKeysym: (const gchar *)sym;1.18 +@end1.19 +1.20 +@implementation KeyBindingEditor1.21 +- (id)init1.22 +{1.23 + self = [super init];1.24 + isPrimed = NO;1.25 + lastValue = nil;1.26 + [self setFieldEditor: YES];1.27 + [self setEditable: FALSE];1.28 + return self;1.29 +}1.30 +- (void)dealloc1.31 +{1.32 + if( lastValue != nil ) {1.33 + [lastValue release];1.34 + lastValue = nil;1.35 + }1.36 + [super dealloc];1.37 +}1.38 +- (void)setPrimed: (BOOL)primed1.39 +{1.40 + if( primed != isPrimed ) {1.41 + isPrimed = primed;1.42 + if( primed ) {1.43 + lastValue = [[NSString stringWithString: [self string]] retain];1.44 + [self setString: @"<press key>"];1.45 + input_set_keysym_hook(cocoa_config_keysym_hook, self);1.46 + } else {1.47 + [lastValue release];1.48 + lastValue = nil;1.49 + input_set_keysym_hook(NULL,NULL);1.50 + }1.51 + }1.52 +}1.53 +- (void)fireBindingChanged1.54 +{1.55 + id delegate = [self delegate];1.56 + if( delegate != nil && [delegate respondsToSelector:@selector(textDidChange:)] ) {1.57 + [delegate textDidChange: [NSNotification notificationWithName: NSTextDidChangeNotification object: self]];1.58 + }1.59 +}1.60 +1.61 +- (void)updateKeysym: (const gchar *)sym1.62 +{1.63 + if( sym != NULL ) {1.64 + [self setString: [NSString stringWithCString: sym]];1.65 + [self setPrimed: NO];1.66 + [self fireBindingChanged];1.67 + }1.68 +}1.69 +- (void)keyPressed: (int)keycode1.70 +{1.71 + gchar *keysym = input_keycode_to_keysym(NULL, keycode);1.72 + if( keysym != NULL ) {1.73 + [self updateKeysym: keysym];1.74 + g_free(keysym);1.75 + }1.76 +}1.77 +- (void)insertText:(id)string1.78 +{1.79 + // Do nothing1.80 +}1.81 +- (void)mouseDown: (NSEvent *)event1.82 +{1.83 + [self setPrimed: YES];1.84 + [super mouseDown: event];1.85 +}1.86 +- (void)keyDown: (NSEvent *) event1.87 +{1.88 + NSString *chars = [event characters];1.89 + if( isPrimed ) {1.90 + if( chars != NULL && [chars length] == 1 && [chars characterAtIndex: 0] == 27 ) {1.91 + // Escape char = abort change1.92 + [self setString: lastValue];1.93 + [self setPrimed: NO];1.94 + } else {1.95 + [self keyPressed: ([event keyCode]+1)];1.96 + }1.97 + } else {1.98 + if( chars != NULL && [chars length] == 1 ) {1.99 + int ch = [chars characterAtIndex: 0];1.100 + switch( ch ) {1.101 + case 0x7F:1.102 + [self setString: @""];1.103 + [self fireBindingChanged];1.104 + break;1.105 + case '\r':1.106 + [self setPrimed: YES];1.107 + break;1.108 + default:1.109 + [super keyDown: event];1.110 + break;1.111 + }1.112 + } else {1.113 + [super keyDown: event];1.114 + }1.115 + }1.116 +}1.117 +- (void)flagsChanged: (NSEvent *) event1.118 +{1.119 + if( isPrimed ) {1.120 + [self keyPressed: ([event keyCode]+1)];1.121 + }1.122 + [super flagsChanged: event];1.123 +}1.124 +@end1.125 +1.126 +static void cocoa_config_keysym_hook(void *data, const gchar *keysym)1.127 +{1.128 + KeyBindingEditor *editor = (KeyBindingEditor *)data;1.129 + [editor updateKeysym: keysym];1.130 +}1.131 +1.132 +1.133 +@implementation KeyBindingField1.134 +@end1.135 +1.136 +/*************************** Key-binding sub-view ***********************/1.137 +1.138 +#define MAX_KEY_BINDINGS 321.139 +1.140 +@interface ControllerKeyBindingView : NSView1.141 +{1.142 + maple_device_t device;1.143 + KeyBindingField *field[MAX_KEY_BINDINGS][2];1.144 +}1.145 +- (id)initWithFrame: (NSRect)frameRect;1.146 +- (void)setDevice: (maple_device_t)device;1.147 +@end1.148 +1.149 +@implementation ControllerKeyBindingView1.150 +- (id)initWithFrame: (NSRect)frameRect1.151 +{1.152 + if( [super initWithFrame: frameRect] == nil ) {1.153 + return nil;1.154 + } else {1.155 + device = NULL;1.156 + return self;1.157 + }1.158 +}1.159 +- (BOOL)isFlipped1.160 +{1.161 + return YES;1.162 +}1.163 +- (void)removeSubviews1.164 +{1.165 + [[self subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];1.166 +}1.167 +- (void)controlTextDidChange: (NSNotification *)notify1.168 +{1.169 + int binding = [[notify object] tag];1.170 + NSString *val1 = [field[binding][0] stringValue];1.171 + NSString *val2 = [field[binding][1] stringValue];1.172 + char buf[ [val1 length] + [val2 length] + 2 ];1.173 + const gchar *p = NULL;1.174 +1.175 + if( [val1 length] == 0 ) {1.176 + if( [val2 length] != 0 ) {1.177 + p = [val2 UTF8String];1.178 + }1.179 + } else if( [val2 length] == 0 ) {1.180 + p = [val1 UTF8String];1.181 + } else {1.182 + sprintf( buf, "%s,%s", [val1 UTF8String], [val2 UTF8String] );1.183 + p = buf;1.184 + }1.185 + maple_set_device_config_value( device, binding, p );1.186 + lxdream_save_config();1.187 +}1.188 +- (void)setDevice: (maple_device_t)newDevice1.189 +{1.190 + device = newDevice;1.191 + [self removeSubviews];1.192 + if( device != NULL ) {1.193 + lxdream_config_entry_t config = maple_get_device_config(device);1.194 + if( config != NULL ) {1.195 + int count, i, y, x;1.196 +1.197 + for( count=0; config[count].key != NULL; count++ );1.198 + x = TEXT_GAP;1.199 + NSSize size = NSMakeSize(85*3+TEXT_GAP*4, count*(TEXT_HEIGHT+TEXT_GAP)+TEXT_GAP);1.200 + [self setFrameSize: size];1.201 + [self scrollRectToVisible: NSMakeRect(0,0,1,1)];1.202 + y = TEXT_GAP;1.203 + for( i=0; config[i].key != NULL; i++ ) {1.204 + NSRect frame = NSMakeRect(x, y + 2, 85, LABEL_HEIGHT);1.205 + NSTextField *label = cocoa_gui_add_label(self, NS_(config[i].label), frame);1.206 + [label setAlignment: NSRightTextAlignment];1.207 +1.208 + frame = NSMakeRect( x + 85 + TEXT_GAP, y, 85, TEXT_HEIGHT);1.209 + field[i][0] = [[KeyBindingField alloc] initWithFrame: frame];1.210 + [field[i][0] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];1.211 + [field[i][0] setTag: i];1.212 + [field[i][0] setDelegate: self];1.213 + [self addSubview: field[i][0]];1.214 +1.215 + frame = NSMakeRect( x + (85*2) + (TEXT_GAP*2), y, 85, TEXT_HEIGHT);1.216 + field[i][1] = [[KeyBindingField alloc] initWithFrame: frame];1.217 + [field[i][1] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];1.218 + [field[i][1] setTag: i];1.219 + [field[i][1] setDelegate: self];1.220 + [self addSubview: field[i][1]];1.221 +1.222 + if( config[i].value != NULL ) {1.223 + gchar **parts = g_strsplit(config[i].value,",",3);1.224 + if( parts[0] != NULL ) {1.225 + [field[i][0] setStringValue: [NSString stringWithCString: parts[0]]];1.226 + if( parts[1] != NULL ) {1.227 + [field[i][1] setStringValue: [NSString stringWithCString: parts[1]]];1.228 + }1.229 + }1.230 + g_strfreev(parts);1.231 + }1.232 +1.233 + y += (TEXT_HEIGHT + TEXT_GAP);1.234 + }1.235 + } else {1.236 + [self setFrameSize: NSMakeSize(100,TEXT_HEIGHT+TEXT_GAP) ];1.237 + }1.238 + } else {1.239 + [self setFrameSize: NSMakeSize(100,TEXT_HEIGHT+TEXT_GAP) ];1.240 + }1.241 +}1.242 +@end1.243 +1.244 +/*************************** Top-level controller pane ***********************/1.245 +1.246 +@interface LxdreamPrefsControllerPane: LxdreamPrefsPane1.247 +{1.248 + struct maple_device *save_controller[4];1.249 + NSButton *radio[4];1.250 + ControllerKeyBindingView *key_bindings;1.251 +}1.252 ++ (LxdreamPrefsControllerPane *)new;1.253 +@end1.254 +1.255 @implementation LxdreamPrefsControllerPane1.256 + (LxdreamPrefsControllerPane *)new1.257 {1.258 @@ -35,19 +279,46 @@1.259 const struct maple_device_class **devices = maple_get_device_classes();1.260 char buf[16];1.261 int i,j;1.262 - int height = [self contentHeight] - TEXT_HEIGHT - TEXT_GAP;1.263 + int y = [self contentHeight] - TEXT_HEIGHT - TEXT_GAP;1.264 +1.265 + NSBox *rule = [[NSBox alloc] initWithFrame:1.266 + NSMakeRect(210+(TEXT_GAP*3), 1, 1, [self contentHeight] + TEXT_GAP - 2)];1.267 + [rule setAutoresizingMask: (NSViewMaxXMargin|NSViewHeightSizable)];1.268 + [rule setBoxType: NSBoxSeparator];1.269 + [self addSubview: rule];1.270 +1.271 + NSRect bindingFrame = NSMakeRect(210+(TEXT_GAP*4), 0,1.272 + frameRect.size.width - (210+(TEXT_GAP*4)), [self contentHeight] + TEXT_GAP );1.273 + NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame: bindingFrame];1.274 + key_bindings = [[ControllerKeyBindingView alloc] initWithFrame: bindingFrame ];1.275 + [scrollView setAutoresizingMask: (NSViewWidthSizable|NSViewHeightSizable)];1.276 + [scrollView setDocumentView: key_bindings];1.277 + [scrollView setDrawsBackground: NO];1.278 + [scrollView setHasVerticalScroller: YES];1.279 + [scrollView setAutohidesScrollers: YES];1.280 +1.281 + [self addSubview: scrollView];1.282 + [key_bindings setDevice: maple_get_device(0,0)];1.283 +1.284 for( i=0; i<MAX_DEVICES; i++ ) {1.285 + int x = TEXT_GAP;1.286 save_controller[i] = NULL;1.287 maple_device_t device = maple_get_device(i,0);1.288 - NSRect frame = NSMakeRect( TEXT_GAP, height -((TEXT_HEIGHT+TEXT_GAP)*i - 2),1.289 - 50, LABEL_HEIGHT );1.290 +1.291 snprintf( buf, sizeof(buf), _("Slot %d."), i );1.292 - NSTextField *label = [self addLabel: [NSString stringWithUTF8String: buf]1.293 - withFrame: frame ];1.294 - [label setAlignment: NSRightTextAlignment];1.295 - frame = NSMakeRect( 50 + (TEXT_GAP*2), height - ((TEXT_HEIGHT+TEXT_GAP)*i),1.296 - 150, TEXT_HEIGHT );1.297 - NSPopUpButton *popup = [[NSPopUpButton alloc] initWithFrame: frame pullsDown: NO];1.298 + radio[i] = [[NSButton alloc] initWithFrame: NSMakeRect( x, y, 60, TEXT_HEIGHT )];1.299 + [radio[i] setTitle: [NSString stringWithUTF8String: buf]];1.300 + [radio[i] setTag: i];1.301 + [radio[i] setButtonType: NSRadioButton];1.302 + [radio[i] setAlignment: NSRightTextAlignment];1.303 + [radio[i] setTarget: self];1.304 + [radio[i] setAction: @selector(radioChanged:)];1.305 + [radio[i] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];1.306 + [self addSubview: radio[i]];1.307 + x += 60 + TEXT_GAP;1.308 +1.309 + NSPopUpButton *popup = [[NSPopUpButton alloc] initWithFrame: NSMakeRect(x,y,150,TEXT_HEIGHT)1.310 + pullsDown: NO];1.311 [popup addItemWithTitle: NS_("<empty>")];1.312 [popup setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];1.313 [[popup itemAtIndex: 0] setTag: 0];1.314 @@ -62,16 +333,38 @@1.315 [popup setAction: @selector(deviceChanged:)];1.316 [popup setTag: i];1.317 [self addSubview: popup];1.318 + y -= (TEXT_HEIGHT+TEXT_GAP);1.319 }1.320 +1.321 + [radio[0] setState: NSOnState];1.322 return self;1.323 }1.324 }1.325 +- (void)radioChanged: (id)sender1.326 +{1.327 + int slot = [sender tag];1.328 + int i;1.329 + for( i=0; i<MAX_DEVICES; i++ ) {1.330 + if( i != slot ) {1.331 + [radio[i] setState: NSOffState];1.332 + }1.333 + }1.334 + [key_bindings setDevice: maple_get_device(slot,0)];1.335 +}1.336 - (void)deviceChanged: (id)sender1.337 {1.338 int slot = [sender tag];1.339 - int new_device_idx = [sender indexOfSelectedItem] - 1;1.340 + int new_device_idx = [sender indexOfSelectedItem] - 1, i;1.341 maple_device_class_t new_device_class = NULL;1.343 + for( i=0; i<MAX_DEVICES; i++ ) {1.344 + if( i == slot ) {1.345 + [radio[i] setState: NSOnState];1.346 + } else {1.347 + [radio[i] setState: NSOffState];1.348 + }1.349 + }1.350 +1.351 maple_device_t current = maple_get_device(slot,0);1.352 maple_device_t new_device = NULL;1.353 if( new_device_idx != -1 ) {1.354 @@ -79,6 +372,7 @@1.355 }1.356 if( current == NULL ? new_device_class == NULL : current->device_class == new_device_class ) {1.357 // No change1.358 + [key_bindings setDevice: current];1.359 return;1.360 }1.361 if( current != NULL && current->device_class == &controller_class ) {1.362 @@ -95,7 +389,12 @@1.363 }1.364 maple_attach_device(new_device,slot,0);1.365 }1.366 -1.367 + [key_bindings setDevice: maple_get_device(slot,0)];1.368 lxdream_save_config();1.369 }1.370 @end1.371 +1.372 +NSView *cocoa_gui_create_prefs_controller_pane()1.373 +{1.374 + return [LxdreamPrefsControllerPane new];1.375 +}
.