Search
lxdream.org :: lxdream/src/gtkui/ctrl_dlg.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/gtkui/ctrl_dlg.c
changeset 628:bd46e2c4c479
prev616:527ab167712b
next669:ab344e42bca9
author nkeynes
date Tue Feb 12 08:36:29 2008 +0000 (16 years ago)
permissions -rw-r--r--
last change Bug #55: Fix relative path handling
Canonicalize paths before passing to the file dialog
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * Define the main (emu) GTK window, along with its menubars,
     5  * toolbars, etc.
     6  *
     7  * Copyright (c) 2005 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 <assert.h>
    21 #include <gtk/gtk.h>
    22 #include <gdk/gdkkeysyms.h>
    24 #include "lxdream.h"
    25 #include "display.h"
    26 #include "gtkui/gtkui.h"
    27 #include "maple/maple.h"
    29 #define MAX_DEVICES 4
    31 static void controller_device_configure(maple_device_t device);
    33 struct maple_config_class {
    34     const char *name;
    35     void (*config_func)(maple_device_t device);
    36 };
    38 typedef struct maple_slot_data {
    39     maple_device_t old_device;
    40     maple_device_t new_device;
    41     GtkWidget *button;
    42     GtkWidget *combo;
    43 } *maple_slot_data_t;
    45 static struct maple_config_class maple_device_config[] = {
    46     { "Sega Controller", controller_device_configure },
    47     { NULL, NULL } };
    49 static struct maple_slot_data maple_data[MAX_DEVICES];
    51 static void config_keysym_hook( void *data, const gchar *keysym )
    52 {
    53     GtkWidget *widget = (GtkWidget *)data;
    54     gtk_entry_set_text( GTK_ENTRY(widget), keysym );
    55     g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(FALSE) );
    56     input_set_keysym_hook(NULL, NULL);
    57 }
    59 static gboolean config_key_buttonpress( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
    60 {
    61     gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
    62     if( !keypress_mode ) {
    63 	gtk_entry_set_text( GTK_ENTRY(widget), _("<press key>") );
    64 	g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(TRUE) );
    65 	input_set_keysym_hook(config_keysym_hook, widget);
    66     }
    67     return FALSE;
    68 }
    70 static gboolean config_key_keypress( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
    71 {
    72     gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
    73     if( keypress_mode ) {
    74 	if( event->keyval == GDK_Escape ) {
    75 	    gtk_entry_set_text( GTK_ENTRY(widget), "" );
    76 	    g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(FALSE) );
    77 	    return TRUE;
    78 	}
    79 	GdkKeymap *keymap = gdk_keymap_get_default();
    80 	guint keyval;
    82 	gdk_keymap_translate_keyboard_state( keymap, event->hardware_keycode, 0, 0, &keyval, 
    83 					     NULL, NULL, NULL );
    84 	gtk_entry_set_text( GTK_ENTRY(widget), gdk_keyval_name(keyval) );
    85 	g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(FALSE) );
    86 	input_set_keysym_hook(NULL, NULL);
    87 	return TRUE;
    88     } else {
    89 	switch( event->keyval ) {
    90 	case GDK_Return:
    91 	case GDK_KP_Enter:
    92 	    gtk_entry_set_text( GTK_ENTRY(widget), _("<press key>") );
    93 	    g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(TRUE) );
    94 	    input_set_keysym_hook(config_keysym_hook, widget);
    95 	    return TRUE;
    96 	case GDK_BackSpace:
    97 	case GDK_Delete:
    98 	    gtk_entry_set_text( GTK_ENTRY(widget), "" );
    99 	    return TRUE;
   100 	}
   101 	return FALSE;
   102     }
   104 }
   106 static void controller_config_done( GtkWidget *panel, gboolean isOK )
   107 {
   108     if( isOK ) {
   109 	maple_device_t device = (maple_device_t)gtk_object_get_data( GTK_OBJECT(panel), "maple_device" );
   110 	lxdream_config_entry_t conf = device->get_config(device);
   111 	int i;
   112 	for( i=0; conf[i].key != NULL; i++ ) {
   113 	    char buf[64];
   114 	    GtkWidget *entry1, *entry2;
   115 	    const gchar *key1, *key2;
   116 	    snprintf( buf, sizeof(buf), "%s.1", conf[i].key );
   117 	    entry1 = GTK_WIDGET(g_object_get_qdata( G_OBJECT(panel), g_quark_from_string(buf)));
   118 	    key1 = gtk_entry_get_text(GTK_ENTRY(entry1));
   119 	    snprintf( buf, sizeof(buf), "%s.2", conf[i].key );
   120 	    entry2 = GTK_WIDGET(g_object_get_qdata( G_OBJECT(panel), g_quark_from_string(buf)));
   121 	    key2 = gtk_entry_get_text(GTK_ENTRY(entry2));
   122 	    if( key1 == NULL || key1[0] == '\0') {
   123 		lxdream_set_config_value( &conf[i], key2 );
   124 	    } else if( key2 == NULL || key2[0] == '\0') {
   125 		lxdream_set_config_value( &conf[i], key1 );
   126 	    } else {
   127 		char buf[64];
   128 		snprintf( buf, sizeof(buf), "%s, %s", key1, key2 );
   129 		lxdream_set_config_value( &conf[i], buf );
   130 	    }
   131 	}
   132     }
   133     input_set_keysym_hook(NULL, NULL);
   134 }
   136 static void controller_device_configure( maple_device_t device )
   137 {
   138     lxdream_config_entry_t conf = device->get_config(device);
   139     int count, i;
   140     for( count=0; conf[count].key != NULL; count++ );
   142     GtkWidget *table = gtk_table_new( (count+1)>>1, 6, FALSE );
   143     GList *focus_chain = NULL;
   144     gtk_object_set_data( GTK_OBJECT(table), "maple_device", device );
   145     for( i=0; i<count; i++ ) {
   146 	GtkWidget *text, *text2;
   147 	char buf[64];
   148 	int x=0;
   149 	int y=i;
   150 	if( i >= (count+1)>>1 ) {
   151 	    x = 3;
   152 	    y -= (count+1)>>1;
   153 	}
   154 	gtk_table_attach( GTK_TABLE(table), gtk_label_new(conf[i].key), x, x+1, y, y+1, 
   155 			  GTK_SHRINK, GTK_SHRINK, 0, 0 );
   156 	text = gtk_entry_new();
   157 	gtk_entry_set_width_chars( GTK_ENTRY(text), 11 );
   158 	gtk_entry_set_editable( GTK_ENTRY(text), FALSE );
   159 	g_signal_connect( text, "key_press_event", 
   160 			  G_CALLBACK(config_key_keypress), NULL );
   161 	g_signal_connect( text, "button_press_event",
   162 			  G_CALLBACK(config_key_buttonpress), NULL );
   163 	snprintf( buf, sizeof(buf), "%s.1", conf[i].key );
   164 	g_object_set_data( G_OBJECT(text), "keypress_mode", GINT_TO_POINTER(FALSE) );
   165 	g_object_set_qdata( G_OBJECT(table), g_quark_from_string(buf), text );
   166 	gtk_table_attach_defaults( GTK_TABLE(table), text, x+1, x+2, y, y+1);
   167 	focus_chain = g_list_append( focus_chain, text );
   168 	text2 = gtk_entry_new();
   169 	gtk_entry_set_width_chars( GTK_ENTRY(text2), 11 );
   170 	gtk_entry_set_editable( GTK_ENTRY(text2), FALSE );
   171 	g_signal_connect( text2, "key_press_event", 
   172 			  G_CALLBACK(config_key_keypress), NULL );
   173 	g_signal_connect( text2, "button_press_event",
   174 			  G_CALLBACK(config_key_buttonpress), NULL );
   175 	snprintf( buf, sizeof(buf), "%s.2", conf[i].key );
   176 	g_object_set_data( G_OBJECT(text2), "keypress_mode", GINT_TO_POINTER(FALSE) );
   177 	g_object_set_qdata( G_OBJECT(table), g_quark_from_string(buf), text2 );
   178 	gtk_table_attach_defaults( GTK_TABLE(table), text2, x+2, x+3, y, y+1);
   179 	focus_chain = g_list_append( focus_chain, text2 );
   180 	if( conf[i].value != NULL ) {
   181 	    gchar **parts = g_strsplit(conf[i].value,",",3);
   182 	    if( parts[0] != NULL ) {
   183 		gtk_entry_set_text( GTK_ENTRY(text), g_strstrip(parts[0]) );
   184 		if( parts[1] != NULL ) {
   185 		    gtk_entry_set_text( GTK_ENTRY(text2), g_strstrip(parts[1]) );
   186 		}
   187 	    }
   188 	    g_strfreev(parts);
   189 	}
   190     }
   191     gtk_container_set_focus_chain( GTK_CONTAINER(table), focus_chain );
   192     gtk_gui_run_property_dialog( _("Controller Configuration"), table, controller_config_done );
   193 }
   195 gboolean maple_properties_activated( GtkButton *button, gpointer user_data )
   196 {
   197     maple_slot_data_t data = (maple_slot_data_t)user_data;
   198     if( data->new_device != NULL ) {
   199 	int i;
   200 	for( i=0; maple_device_config[i].name != NULL; i++ ) {
   201 	    if( strcmp(data->new_device->device_class->name, maple_device_config[i].name) == 0 ) {
   202 		if( data->new_device == data->old_device ) {
   203 		    // Make a copy at this point if we haven't already
   204 		    data->new_device = data->old_device->clone(data->old_device);
   205 		}
   206 		maple_device_config[i].config_func(data->new_device);
   207 		break;
   208 	    }
   209 	}
   210 	if( maple_device_config[i].name == NULL ) {
   211 	    gui_error_dialog( _("No configuration page available for device type") );
   212 	}
   213     }
   214     return TRUE;
   215 }
   217 gboolean maple_device_changed( GtkComboBox *combo, gpointer user_data )
   218 {
   219     maple_slot_data_t data = (maple_slot_data_t)user_data;
   220     int active = gtk_combo_box_get_active(combo);
   221     gboolean has_config = FALSE;
   222     if( active != 0 ) {
   223 	gchar *devname = gtk_combo_box_get_active_text(combo);
   224 	const maple_device_class_t devclz = maple_get_device_class(devname);
   225 	assert(devclz != NULL);
   226 	if( data->new_device != NULL ) {
   227 	    if( data->new_device->device_class != devclz ) {
   228 		if( data->new_device != data->old_device ) {
   229 		    data->new_device->destroy(data->new_device);
   230 		}
   231 		data->new_device = maple_new_device(devname);
   232 	    }
   233 	} else {
   234 	    data->new_device = maple_new_device(devname);
   235 	}
   236 	has_config = data->new_device != NULL && data->new_device->get_config != NULL;
   237     } else {
   238 	if( data->new_device != NULL && data->new_device != data->old_device ) {
   239 	    data->new_device->destroy(data->new_device);
   240 	}
   241 	data->new_device = NULL;
   242     }
   243     gtk_widget_set_sensitive(data->button, has_config);
   244     return TRUE;
   245 }
   247 void maple_dialog_done( GtkWidget *panel, gboolean isOK )
   248 {
   249     if( isOK ) {
   250 	int i;
   251 	for( i=0; i<MAX_DEVICES; i++ ) {
   252 	    if( maple_data[i].new_device != maple_data[i].old_device ) {
   253 		if( maple_data[i].old_device != NULL ) {
   254 		    maple_detach_device(i,0);
   255 		}
   256 		if( maple_data[i].new_device != NULL ) {
   257 		    maple_attach_device(maple_data[i].new_device, i, 0 );
   258 		}
   259 	    }
   260 	}
   261 	lxdream_save_config();
   262     } else {
   263 	int i;
   264 	for( i=0; i<MAX_DEVICES; i++ ) {
   265 	    if( maple_data[i].new_device != NULL && 
   266 		maple_data[i].new_device != maple_data[i].old_device ) {
   267 		maple_data[i].new_device->destroy(maple_data[i].new_device);
   268 	    }
   269 	}
   270     }
   272 }
   274 GtkWidget *maple_panel_new()
   275 {
   276     GtkWidget *table = gtk_table_new(4, 3, TRUE);
   277     int i,j;
   278     const struct maple_device_class **devices = maple_get_device_classes();
   280     for( i=0; i< MAX_DEVICES; i++ ) {
   281 	char buf[12];
   282 	GtkWidget *combo, *button;
   283 	int active = 0;
   284 	maple_device_t device = maple_get_device(i,0);
   285 	sprintf( buf, _("Slot %d."), i );
   286 	gtk_table_attach_defaults( GTK_TABLE(table), gtk_label_new(buf), 0, 1, i, i+1 );
   287 	combo = gtk_combo_box_new_text();
   288 	gtk_combo_box_append_text( GTK_COMBO_BOX(combo), _("<empty>") );
   289 	for( j=0; devices[j] != NULL; j++ ) {
   290 	    gtk_combo_box_append_text(GTK_COMBO_BOX(combo), devices[j]->name);
   291 	    if( device != NULL && device->device_class == devices[j] ) {
   292 		active = j+1;
   293 	    }
   294 	}
   295 	gtk_combo_box_set_active(GTK_COMBO_BOX(combo), active);
   296 	gtk_table_attach_defaults( GTK_TABLE(table), combo, 1, 2, i, i+1 );
   297 	button = gtk_button_new_from_stock( GTK_STOCK_PROPERTIES );
   298 	gtk_widget_set_sensitive(button, active != 0 && device->get_config != NULL);
   299 	gtk_table_attach_defaults( GTK_TABLE(table), button, 2, 3, i, i+1 );
   301 	maple_data[i].old_device = device;
   302 	maple_data[i].new_device = device;
   303 	maple_data[i].combo = combo;
   304 	maple_data[i].button = button;
   305 	g_signal_connect( button, "clicked", 
   306 			  G_CALLBACK( maple_properties_activated ), &maple_data[i] );
   307 	g_signal_connect( combo, "changed", 
   308 			  G_CALLBACK( maple_device_changed ), &maple_data[i] );
   310     }
   311     return table;
   312 }
   314 void maple_dialog_run( )
   315 {
   316     gtk_gui_run_property_dialog( _("Controller Settings"), maple_panel_new(), maple_dialog_done );
   317 }
.