Search
lxdream.org :: lxdream/src/cocoaui/cocoa_cfg.m
lxdream 0.9.1
released Jun 29
Download Now
filename src/cocoaui/cocoa_cfg.m
changeset 1072:d82e04e6d497
next1298:d0eb2307b847
author nkeynes
date Fri Mar 02 23:49:10 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Android WIP:
* Rename gui_jni.c to gui_android.c - now quite android specific.
* Implement generic EGL driver with very minimal Java wrapper
* Run emulation in separate thread, and implement simple queue for
inter-thread communication.
* Add menu/action-bar items for start + reset
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * Construct and manage a configuration pane based on an underlying
     5  * configuration group.
     6  *
     7  * Copyright (c) 2009 Nathan Keynes.
     8  *
     9  * This program is free software; you can redistribute it and/or modify
    10  * it under the terms of the GNU General Public License as published by
    11  * the Free Software Foundation; either version 2 of the License, or
    12  * (at your option) any later version.
    13  *
    14  * This program is distributed in the hope that it will be useful,
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17  * GNU General Public License for more details.
    18  */
    20 #include "cocoaui.h"
    21 #include "display.h"
    22 #include "lxpaths.h"
    23 #include "maple/maple.h"
    25 static void cocoa_config_keysym_hook(void *data, const gchar *keysym);
    27 @interface KeyBindingEditor (Private)
    28 - (void)updateKeysym: (const gchar *)sym;
    29 @end
    31 @implementation KeyBindingEditor
    32 - (id)init
    33 {
    34     self = [super init];
    35     isPrimed = NO;
    36     lastValue = nil;
    37     [self setFieldEditor: YES];
    38     [self setEditable: FALSE];
    39     return self;
    40 }
    41 - (void)dealloc
    42 {
    43     if( lastValue != nil ) {
    44         [lastValue release];
    45         lastValue = nil;
    46     }
    47     [super dealloc];
    48 }
    49 - (void)setPrimed: (BOOL)primed
    50 {
    51     if( primed != isPrimed ) {
    52         isPrimed = primed;
    53         if( primed ) {
    54             lastValue = [[NSString stringWithString: [self string]] retain];
    55             [self setString: @"<press key>"];
    56             input_set_keysym_hook(cocoa_config_keysym_hook, self);
    57         } else {
    58             [lastValue release];
    59             lastValue = nil;
    60             input_set_keysym_hook(NULL,NULL);
    61         }
    62     }
    63 }
    64 - (BOOL)resignFirstResponder
    65 {
    66     if( isPrimed ) {
    67         [self setString: lastValue];
    68         [self setPrimed: NO];
    69     }
    70     return [super resignFirstResponder];
    71 }
    72 - (void)fireBindingChanged
    73 {
    74     id delegate = [self delegate];
    75     if( delegate != nil && [delegate respondsToSelector:@selector(textDidChange:)] ) {
    76         [delegate textDidChange: [NSNotification notificationWithName: NSTextDidChangeNotification object: self]];
    77     }
    78 }
    80 - (void)updateKeysym: (const gchar *)sym
    81 {
    82     if( sym != NULL ) {
    83         [self setString: [NSString stringWithCString: sym]];
    84         [self setPrimed: NO];
    85         [self fireBindingChanged];
    86     }
    87 }
    88 - (void)updateMousesym: (int)button
    89 {
    90     gchar *keysym = input_keycode_to_keysym( &system_mouse_driver, (button+1) );
    91     if( keysym != NULL ) {
    92         [self updateKeysym: keysym ];
    93         g_free(keysym);
    94     }
    95 }
    96 - (void)keyPressed: (int)keycode
    97 {
    98     gchar *keysym = input_keycode_to_keysym(NULL, keycode);
    99     if( keysym != NULL ) {
   100         [self updateKeysym: keysym];
   101         g_free(keysym);
   102     }
   103 }
   104 - (void)insertText:(id)string
   105 {
   106     // Do nothing
   107 }
   108 - (void)mouseDown: (NSEvent *)event
   109 {
   110     if( isPrimed ) {
   111         [self updateMousesym: 0];
   112     } else {
   113         [self setPrimed: YES];
   114         [super mouseDown: event];
   115     }
   116 }
   117 - (void)rightMouseDown: (NSEvent *)event
   118 {
   119     if( isPrimed ) {
   120         [self updateMousesym: 1];
   121     }
   122 }
   123 - (void)otherMouseDown: (NSEvent *)event
   124 {
   125     if( isPrimed ) {
   126         [self updateMousesym: [event buttonNumber]];
   127     }
   128 }
   129 - (void)keyDown: (NSEvent *) event
   130 {
   131     NSString *chars = [event characters];
   132     if( isPrimed ) {
   133         if( chars != NULL && [chars length] == 1 && [chars characterAtIndex: 0] == 27 ) {
   134             // Escape char = abort change
   135             [self setString: lastValue];
   136             [self setPrimed: NO];
   137         } else {
   138             [self keyPressed: ([event keyCode]+1)];
   139         }
   140     } else {
   141         if( chars != NULL && [chars length] == 1 ) {
   142             int ch = [chars characterAtIndex: 0];
   143             switch( ch ) {
   144             case 0x7F:
   145                 [self setString: @""];
   146                 [self fireBindingChanged];
   147                 break;
   148             case '\r':
   149                 [self setPrimed: YES];
   150                 break;
   151             default:
   152                 [super keyDown: event];
   153                 break;
   154             }
   155         } else {
   156             [super keyDown: event];
   157         }
   158     }
   159 }
   160 - (void)flagsChanged: (NSEvent *) event
   161 {
   162     if( isPrimed ) {
   163         [self keyPressed: ([event keyCode]+1)];
   164     }
   165     [super flagsChanged: event];
   166 }
   167 @end
   169 static void cocoa_config_keysym_hook(void *data, const gchar *keysym)
   170 {
   171     KeyBindingEditor *editor = (KeyBindingEditor *)data;
   172     [editor updateKeysym: keysym];
   173 }
   175 @implementation KeyBindingField
   176 @end
   178 /*************************** Configuration sub-view ***********************/
   180 #define KEYBINDING_SIZE 110
   181 #define DEFAULT_LABEL_WIDTH 150
   182 #define RIGHT_MARGIN 40
   184 @implementation ConfigurationView
   185 - (id)initWithFrame: (NSRect)frameRect
   186 {
   187     return [self initWithFrame: frameRect configGroup: NULL];
   188 }
   189 - (id)initWithFrame: (NSRect)frameRect configGroup: (lxdream_config_group_t)config
   190 {
   191     if( [super initWithFrame: frameRect] == nil ) {
   192         return nil;
   193     } else {
   194         group = NULL;
   195         labelWidth = DEFAULT_LABEL_WIDTH;
   196         [self setConfigGroup: config];
   197         return self;
   198     }
   199 }
   200 - (BOOL)isFlipped
   201 {
   202     return YES;
   203 }
   204 - (void)setLabelWidth: (int)width
   205 {
   206     labelWidth = width;
   207 }
   208 - (void)removeSubviews
   209 {
   210     [[self subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
   211 }
   212 - (void)updateField: (int)binding
   213 {
   214     const gchar *p = NULL;
   215     NSString *val1 = [fields[binding][0] stringValue];
   216      if( fields[binding][1] == NULL ) {
   217          p = [val1 UTF8String];
   218          lxdream_set_config_value( group, binding, p );
   219      } else {
   220          NSString *val2 = [fields[binding][1] stringValue];
   221          char buf[ [val1 length] + [val2 length] + 2 ];
   223          if( [val1 length] == 0 ) {
   224              if( [val2 length] != 0 ) {
   225                  p = [val2 UTF8String];
   226              }
   227          } else if( [val2 length] == 0 ) {
   228              p = [val1 UTF8String];
   229          } else {
   230              sprintf( buf, "%s,%s", [val1 UTF8String], [val2 UTF8String] );
   231              p = buf;
   232          }
   233          lxdream_set_config_value( group, binding, p );
   234      }
   235      lxdream_save_config();
   236 }
   238 - (void)controlTextDidChange: (NSNotification *)notify
   239 {
   240     if( [[notify object] isKindOfClass: [KeyBindingField class]] ) {
   241         [self updateField: [[notify object] tag]];
   242     }
   243 }
   244 - (void)controlTextDidEndEditing: (NSNotification *)notify
   245 {
   246     [self updateField: [[notify object] tag]];
   247 }
   249 - (void)openFileDialog: (id)sender
   250 {
   251     int tag = [sender tag];
   252     NSString *text = [fields[tag][0] stringValue];
   253     NSOpenPanel *panel = [NSOpenPanel openPanel];
   254     int result = [panel runModalForDirectory: nil file: nil types: nil];
   255     if( result == NSOKButton && [[panel filenames] count] > 0 ) {
   256         NSString *filename = [[panel filenames] objectAtIndex: 0];
   257         gchar *str = get_escaped_path( [filename UTF8String] );
   258         [fields[tag][0] setStringValue: [NSString stringWithUTF8String: str]];
   259         lxdream_set_global_config_value(tag,str);
   260         lxdream_save_config();
   261     }
   262 }
   263 - (void)openDirDialog: (id)sender
   264 {
   265     int tag = [sender tag];
   266     NSString *text = [fields[tag][0] stringValue];
   267     NSOpenPanel *panel = [NSOpenPanel openPanel];
   268     [panel setCanChooseDirectories: YES];
   269     [panel setCanCreateDirectories: YES];
   270     int result = [panel runModalForDirectory: nil file: nil types: nil];
   271     if( result == NSOKButton && [[panel filenames] count] > 0 ) {
   272         NSString *filename = [[panel filenames] objectAtIndex: 0];
   273         gchar *str = get_escaped_path( [filename UTF8String] );
   274         [fields[tag][0] setStringValue: [NSString stringWithUTF8String: str]];
   275         lxdream_set_global_config_value(tag,str);
   276         lxdream_save_config();
   277     }
   278 }
   280 - (void)setConfigGroup: (lxdream_config_group_t) config
   281 {
   282     if( group == config ) {
   283         return;
   284     }
   285     int width = [self frame].size.width;
   286     int fieldWidth;
   288     group = config;
   289     [self removeSubviews];
   290     if( config != NULL && config->params[0].key != NULL ) {
   291         int count, i, y, x;
   293         for( count=0; config->params[count].label != NULL; count++ );
   294         int minWidth = labelWidth+KEYBINDING_SIZE*2+TEXT_GAP*4;
   295         if( minWidth > width ) {
   296             width = minWidth;
   297         }
   298         NSSize size = NSMakeSize( width, count*(TEXT_HEIGHT+TEXT_GAP)+TEXT_GAP);
   299         [self setFrameSize: size];
   300         [self scrollRectToVisible: NSMakeRect(0,0,1,1)];
   302         x = TEXT_GAP;
   303         y = TEXT_GAP;
   304         for( i=0; config->params[i].label != NULL; i++ ) {
   305             /* Add label */
   306             NSRect frame = NSMakeRect(x, y + 2, labelWidth, LABEL_HEIGHT);
   307             NSTextField *label = cocoa_gui_add_label(self, NS_(config->params[i].label), frame);
   308             [label setAlignment: NSRightTextAlignment];
   310             switch(config->params[i].type) {
   311             case CONFIG_TYPE_KEY:
   312                 frame = NSMakeRect( x + labelWidth + TEXT_GAP, y, KEYBINDING_SIZE, TEXT_HEIGHT);
   313                 fields[i][0] = [[KeyBindingField alloc] initWithFrame: frame];
   314                 [fields[i][0] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
   315                 [fields[i][0] setTag: i];
   316                 [fields[i][0] setDelegate: self];
   317                 [self addSubview: fields[i][0]];
   319                 frame = NSMakeRect( x + labelWidth + KEYBINDING_SIZE + (TEXT_GAP*2), y, KEYBINDING_SIZE, TEXT_HEIGHT);
   320                 fields[i][1] = [[KeyBindingField alloc] initWithFrame: frame];
   321                 [fields[i][1] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
   322                 [fields[i][1] setTag: i];
   323                 [fields[i][1] setDelegate: self];
   324                 [self addSubview: fields[i][1]];
   326                 if( config->params[i].value != NULL ) {
   327                     gchar **parts = g_strsplit(config->params[i].value,",",3);
   328                     if( parts[0] != NULL ) {
   329                         [fields[i][0] setStringValue: [NSString stringWithCString: parts[0]]];
   330                         if( parts[1] != NULL ) {
   331                             [fields[i][1] setStringValue: [NSString stringWithCString: parts[1]]];
   332                         }
   333                     }
   334                     g_strfreev(parts);
   335                 }
   336                 break;
   337             case CONFIG_TYPE_FILE:
   338             case CONFIG_TYPE_PATH:
   339                 fieldWidth = width - labelWidth - x - TEXT_HEIGHT - RIGHT_MARGIN - (TEXT_GAP*2);
   340                 frame = NSMakeRect( x + labelWidth + TEXT_GAP, y, fieldWidth, TEXT_HEIGHT );
   341                 NSTextField *field = [[NSTextField alloc] initWithFrame: frame];
   342                 [field setTag: i];
   343                 [field setStringValue: [NSString stringWithCString: config->params[i].value]];
   344                 [field setDelegate: self];
   345                 [field setAutoresizingMask: (NSViewMinYMargin|NSViewWidthSizable)];
   347                 frame = NSMakeRect( x+ labelWidth + fieldWidth + (TEXT_GAP*2), y,  TEXT_HEIGHT, TEXT_HEIGHT );
   348                 NSButton *button = [[NSButton alloc] initWithFrame: frame];
   349                 [button setTag: i];
   350                 [button setTitle: @""];
   351                 [button setButtonType: NSMomentaryPushInButton];
   352                 [button setBezelStyle: NSRoundedDisclosureBezelStyle];
   353                 [button setAutoresizingMask: (NSViewMinYMargin|NSViewMinXMargin)];
   354                 [button setTarget: self];
   355                 if( config->params[i].type == CONFIG_TYPE_FILE ) {
   356                     [button setAction: @selector(openFileDialog:)];
   357                 } else {
   358                     [button setAction: @selector(openDirDialog:)];
   359                 }
   361                 [self addSubview: label];
   362                 [self addSubview: field];
   363                 [self addSubview: button];
   364                 fields[i][0] = field;
   365                 fields[i][1] = NULL;
   366             }
   367             y += (TEXT_HEIGHT + TEXT_GAP);
   368         }
   369     } else {
   370         [self setFrameSize: NSMakeSize(100,TEXT_HEIGHT+TEXT_GAP) ];
   371     }
   372 }
   374 - (void)setDevice: (maple_device_t)newDevice
   375 {
   376     if( newDevice != NULL && !MAPLE_IS_VMU(newDevice) ) {
   377         [self setConfigGroup: maple_get_device_config(newDevice)];
   378     } else {
   379         [self setConfigGroup: NULL];
   380     }
   381 }
   382 @end
.