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 537:d924be49e192
prev508:ccd2c10edfe6
next561:533f6b478071
author nkeynes
date Thu Nov 22 11:10:15 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Re-add "Load Binary" menu item (misplaced in GUI rewrite)
Prevent running with no code loaded
file annotate diff log raw
nkeynes@447
     1
/**
nkeynes@508
     2
 * $Id: ctrl_dlg.c,v 1.6 2007-11-10 04:45:29 nkeynes Exp $
nkeynes@447
     3
 *
nkeynes@447
     4
 * Define the main (emu) GTK window, along with its menubars,
nkeynes@447
     5
 * toolbars, etc.
nkeynes@447
     6
 *
nkeynes@447
     7
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@447
     8
 *
nkeynes@447
     9
 * This program is free software; you can redistribute it and/or modify
nkeynes@447
    10
 * it under the terms of the GNU General Public License as published by
nkeynes@447
    11
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@447
    12
 * (at your option) any later version.
nkeynes@447
    13
 *
nkeynes@447
    14
 * This program is distributed in the hope that it will be useful,
nkeynes@447
    15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@447
    16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@447
    17
 * GNU General Public License for more details.
nkeynes@447
    18
 */
nkeynes@447
    19
nkeynes@447
    20
#include <assert.h>
nkeynes@447
    21
#include <gtk/gtk.h>
nkeynes@460
    22
#include <gdk/gdkkeysyms.h>
nkeynes@447
    23
nkeynes@447
    24
#include "dream.h"
nkeynes@537
    25
#include "gtkui/gtkui.h"
nkeynes@447
    26
#include "maple/maple.h"
nkeynes@447
    27
nkeynes@447
    28
#define MAX_DEVICES 4
nkeynes@447
    29
nkeynes@455
    30
static void controller_device_configure(maple_device_t device);
nkeynes@455
    31
nkeynes@455
    32
struct maple_config_class {
nkeynes@455
    33
    const char *name;
nkeynes@455
    34
    void (*config_func)(maple_device_t device);
nkeynes@455
    35
};
nkeynes@455
    36
nkeynes@447
    37
typedef struct maple_slot_data {
nkeynes@447
    38
    maple_device_t old_device;
nkeynes@447
    39
    maple_device_t new_device;
nkeynes@447
    40
    GtkWidget *button;
nkeynes@447
    41
    GtkWidget *combo;
nkeynes@447
    42
} *maple_slot_data_t;
nkeynes@447
    43
nkeynes@455
    44
static struct maple_config_class maple_device_config[] = {
nkeynes@455
    45
    { "Sega Controller", controller_device_configure },
nkeynes@455
    46
    { NULL, NULL } };
nkeynes@455
    47
nkeynes@447
    48
static struct maple_slot_data maple_data[MAX_DEVICES];
nkeynes@447
    49
nkeynes@460
    50
static gboolean config_key_buttonpress( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
nkeynes@460
    51
{
nkeynes@460
    52
    gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
nkeynes@460
    53
    if( !keypress_mode ) {
nkeynes@508
    54
	gtk_entry_set_text( GTK_ENTRY(widget), _("<press key>") );
nkeynes@460
    55
	g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(TRUE) );
nkeynes@460
    56
    }
nkeynes@460
    57
    return FALSE;
nkeynes@460
    58
}
nkeynes@460
    59
nkeynes@455
    60
static gboolean config_key_keypress( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
nkeynes@455
    61
{
nkeynes@460
    62
    gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
nkeynes@460
    63
    if( keypress_mode ) {
nkeynes@460
    64
	if( event->keyval == GDK_Escape ) {
nkeynes@460
    65
	    gtk_entry_set_text( GTK_ENTRY(widget), "" );
nkeynes@460
    66
	    g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(FALSE) );
nkeynes@460
    67
	    return TRUE;
nkeynes@460
    68
	}
nkeynes@460
    69
	GdkKeymap *keymap = gdk_keymap_get_default();
nkeynes@460
    70
	guint keyval;
nkeynes@460
    71
	
nkeynes@460
    72
	gdk_keymap_translate_keyboard_state( keymap, event->hardware_keycode, 0, 0, &keyval, 
nkeynes@460
    73
					     NULL, NULL, NULL );
nkeynes@460
    74
	gtk_entry_set_text( GTK_ENTRY(widget), gdk_keyval_name(keyval) );
nkeynes@460
    75
	g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(FALSE) );
nkeynes@460
    76
	return TRUE;
nkeynes@460
    77
    } else {
nkeynes@460
    78
	switch( event->keyval ) {
nkeynes@460
    79
	case GDK_Return:
nkeynes@460
    80
	case GDK_KP_Enter:
nkeynes@508
    81
	    gtk_entry_set_text( GTK_ENTRY(widget), _("<press key>") );
nkeynes@460
    82
	    g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(TRUE) );
nkeynes@460
    83
	    return TRUE;
nkeynes@460
    84
	case GDK_BackSpace:
nkeynes@460
    85
	case GDK_Delete:
nkeynes@460
    86
	    gtk_entry_set_text( GTK_ENTRY(widget), "" );
nkeynes@460
    87
	    return TRUE;
nkeynes@460
    88
	}
nkeynes@460
    89
	return FALSE;
nkeynes@460
    90
    }
nkeynes@460
    91
	    
nkeynes@455
    92
}
nkeynes@447
    93
nkeynes@455
    94
static void controller_config_done( GtkWidget *panel, gboolean isOK )
nkeynes@455
    95
{
nkeynes@460
    96
    if( isOK ) {
nkeynes@460
    97
	maple_device_t device = (maple_device_t)gtk_object_get_data( GTK_OBJECT(panel), "maple_device" );
nkeynes@460
    98
	lxdream_config_entry_t conf = device->get_config(device);
nkeynes@460
    99
	int i;
nkeynes@460
   100
	for( i=0; conf[i].key != NULL; i++ ) {
nkeynes@460
   101
	    char buf[64];
nkeynes@460
   102
	    GtkWidget *entry1, *entry2;
nkeynes@460
   103
	    const gchar *key1, *key2;
nkeynes@460
   104
	    snprintf( buf, sizeof(buf), "%s.1", conf[i].key );
nkeynes@460
   105
	    entry1 = GTK_WIDGET(g_object_get_qdata( G_OBJECT(panel), g_quark_from_string(buf)));
nkeynes@460
   106
	    key1 = gtk_entry_get_text(GTK_ENTRY(entry1));
nkeynes@460
   107
	    snprintf( buf, sizeof(buf), "%s.2", conf[i].key );
nkeynes@460
   108
	    entry2 = GTK_WIDGET(g_object_get_qdata( G_OBJECT(panel), g_quark_from_string(buf)));
nkeynes@460
   109
	    key2 = gtk_entry_get_text(GTK_ENTRY(entry2));
nkeynes@460
   110
	    if( key1 == NULL || key1[0] == '\0') {
nkeynes@460
   111
		lxdream_set_config_value( &conf[i], key2 );
nkeynes@460
   112
	    } else if( key2 == NULL || key2[0] == '\0') {
nkeynes@460
   113
		lxdream_set_config_value( &conf[i], key1 );
nkeynes@460
   114
	    } else {
nkeynes@460
   115
		char buf[64];
nkeynes@460
   116
		snprintf( buf, sizeof(buf), "%s, %s", key1, key2 );
nkeynes@460
   117
		lxdream_set_config_value( &conf[i], buf );
nkeynes@460
   118
	    }
nkeynes@460
   119
	}
nkeynes@460
   120
    }
nkeynes@460
   121
	
nkeynes@455
   122
}
nkeynes@455
   123
nkeynes@455
   124
static void controller_device_configure( maple_device_t device )
nkeynes@455
   125
{
nkeynes@455
   126
    lxdream_config_entry_t conf = device->get_config(device);
nkeynes@455
   127
    int count, i;
nkeynes@455
   128
    for( count=0; conf[count].key != NULL; count++ );
nkeynes@455
   129
nkeynes@455
   130
    GtkWidget *table = gtk_table_new( (count+1)>>1, 6, FALSE );
nkeynes@460
   131
    GList *focus_chain = NULL;
nkeynes@460
   132
    gtk_object_set_data( GTK_OBJECT(table), "maple_device", device );
nkeynes@455
   133
    for( i=0; i<count; i++ ) {
nkeynes@455
   134
	GtkWidget *text, *text2;
nkeynes@460
   135
	char buf[64];
nkeynes@455
   136
	int x=0;
nkeynes@455
   137
	int y=i;
nkeynes@455
   138
	if( i >= (count+1)>>1 ) {
nkeynes@455
   139
	    x = 3;
nkeynes@455
   140
	    y -= (count+1)>>1;
nkeynes@455
   141
	}
nkeynes@455
   142
	gtk_table_attach( GTK_TABLE(table), gtk_label_new(conf[i].key), x, x+1, y, y+1, 
nkeynes@455
   143
			  GTK_SHRINK, GTK_SHRINK, 0, 0 );
nkeynes@455
   144
	text = gtk_entry_new();
nkeynes@455
   145
	gtk_entry_set_width_chars( GTK_ENTRY(text), 8 );
nkeynes@460
   146
	gtk_entry_set_editable( GTK_ENTRY(text), FALSE );
nkeynes@455
   147
	g_signal_connect( text, "key_press_event", 
nkeynes@455
   148
			  G_CALLBACK(config_key_keypress), NULL );
nkeynes@460
   149
	g_signal_connect( text, "button_press_event",
nkeynes@460
   150
			  G_CALLBACK(config_key_buttonpress), NULL );
nkeynes@460
   151
	snprintf( buf, sizeof(buf), "%s.1", conf[i].key );
nkeynes@460
   152
	g_object_set_data( G_OBJECT(text), "keypress_mode", GINT_TO_POINTER(FALSE) );
nkeynes@460
   153
	g_object_set_qdata( G_OBJECT(table), g_quark_from_string(buf), text );
nkeynes@455
   154
	gtk_table_attach_defaults( GTK_TABLE(table), text, x+1, x+2, y, y+1);
nkeynes@460
   155
	focus_chain = g_list_append( focus_chain, text );
nkeynes@455
   156
	text2 = gtk_entry_new();
nkeynes@455
   157
	gtk_entry_set_width_chars( GTK_ENTRY(text2), 8 );
nkeynes@460
   158
	gtk_entry_set_editable( GTK_ENTRY(text2), FALSE );
nkeynes@455
   159
	g_signal_connect( text2, "key_press_event", 
nkeynes@455
   160
			  G_CALLBACK(config_key_keypress), NULL );
nkeynes@460
   161
	g_signal_connect( text2, "button_press_event",
nkeynes@460
   162
			  G_CALLBACK(config_key_buttonpress), NULL );
nkeynes@460
   163
	snprintf( buf, sizeof(buf), "%s.2", conf[i].key );
nkeynes@460
   164
	g_object_set_data( G_OBJECT(text2), "keypress_mode", GINT_TO_POINTER(FALSE) );
nkeynes@460
   165
	g_object_set_qdata( G_OBJECT(table), g_quark_from_string(buf), text2 );
nkeynes@455
   166
	gtk_table_attach_defaults( GTK_TABLE(table), text2, x+2, x+3, y, y+1);
nkeynes@460
   167
	focus_chain = g_list_append( focus_chain, text2 );
nkeynes@460
   168
	if( conf[i].value != NULL ) {
nkeynes@460
   169
	    gchar **parts = g_strsplit(conf[i].value,",",3);
nkeynes@460
   170
	    if( parts[0] != NULL ) {
nkeynes@460
   171
		gtk_entry_set_text( GTK_ENTRY(text), g_strstrip(parts[0]) );
nkeynes@460
   172
		if( parts[1] != NULL ) {
nkeynes@460
   173
		    gtk_entry_set_text( GTK_ENTRY(text2), g_strstrip(parts[1]) );
nkeynes@460
   174
		}
nkeynes@455
   175
	    }
nkeynes@460
   176
	    g_strfreev(parts);
nkeynes@455
   177
	}
nkeynes@455
   178
    }
nkeynes@460
   179
    gtk_container_set_focus_chain( GTK_CONTAINER(table), focus_chain );
nkeynes@508
   180
    gtk_gui_run_property_dialog( _("Controller Configuration"), table, controller_config_done );
nkeynes@455
   181
}
nkeynes@455
   182
nkeynes@455
   183
nkeynes@455
   184
gboolean maple_properties_activated( GtkButton *button, gpointer user_data )
nkeynes@447
   185
{
nkeynes@447
   186
    maple_slot_data_t data = (maple_slot_data_t)user_data;
nkeynes@455
   187
    if( data->new_device != NULL ) {
nkeynes@455
   188
	int i;
nkeynes@455
   189
	for( i=0; maple_device_config[i].name != NULL; i++ ) {
nkeynes@455
   190
	    if( strcmp(data->new_device->device_class->name, maple_device_config[i].name) == 0 ) {
nkeynes@460
   191
		if( data->new_device == data->old_device ) {
nkeynes@460
   192
		    // Make a copy at this point if we haven't already
nkeynes@460
   193
		    data->new_device = data->old_device->clone(data->old_device);
nkeynes@460
   194
		}
nkeynes@455
   195
		maple_device_config[i].config_func(data->new_device);
nkeynes@455
   196
		break;
nkeynes@455
   197
	    }
nkeynes@455
   198
	}
nkeynes@455
   199
	if( maple_device_config[i].name == NULL ) {
nkeynes@508
   200
	    gui_error_dialog( _("No configuration page available for device type") );
nkeynes@455
   201
	}
nkeynes@455
   202
    }
nkeynes@455
   203
    return TRUE;
nkeynes@447
   204
}
nkeynes@447
   205
nkeynes@455
   206
gboolean maple_device_changed( GtkComboBox *combo, gpointer user_data )
nkeynes@447
   207
{
nkeynes@447
   208
    maple_slot_data_t data = (maple_slot_data_t)user_data;
nkeynes@447
   209
    int active = gtk_combo_box_get_active(combo);
nkeynes@447
   210
    gtk_widget_set_sensitive(data->button, active != 0);
nkeynes@447
   211
    if( active != 0 ) {
nkeynes@447
   212
	gchar *devname = gtk_combo_box_get_active_text(combo);
nkeynes@447
   213
	const maple_device_class_t devclz = maple_get_device_class(devname);
nkeynes@447
   214
	assert(devclz != NULL);
nkeynes@447
   215
	if( data->new_device != NULL ) {
nkeynes@447
   216
	    if( data->new_device->device_class != devclz ) {
nkeynes@447
   217
		data->new_device->destroy(data->new_device);
nkeynes@447
   218
		data->new_device = maple_new_device(devname);
nkeynes@447
   219
	    }
nkeynes@447
   220
	} else {
nkeynes@447
   221
	    data->new_device = maple_new_device(devname);
nkeynes@447
   222
	}
nkeynes@447
   223
    } else {
nkeynes@447
   224
	if( data->new_device != NULL && data->new_device != data->old_device ) {
nkeynes@447
   225
	    data->new_device->destroy(data->new_device);
nkeynes@447
   226
	}
nkeynes@447
   227
	data->new_device = NULL;
nkeynes@447
   228
    }
nkeynes@455
   229
    return TRUE;
nkeynes@447
   230
}
nkeynes@447
   231
nkeynes@460
   232
void maple_dialog_done( GtkWidget *panel, gboolean isOK )
nkeynes@447
   233
{
nkeynes@460
   234
    if( isOK ) {
nkeynes@460
   235
	int i;
nkeynes@460
   236
	for( i=0; i<MAX_DEVICES; i++ ) {
nkeynes@460
   237
	    if( maple_data[i].new_device != maple_data[i].old_device ) {
nkeynes@460
   238
		if( maple_data[i].old_device != NULL ) {
nkeynes@460
   239
		    maple_detach_device(i,0);
nkeynes@460
   240
		}
nkeynes@460
   241
		if( maple_data[i].new_device != NULL ) {
nkeynes@460
   242
		    maple_attach_device(maple_data[i].new_device, i, 0 );
nkeynes@460
   243
		}
nkeynes@447
   244
	    }
nkeynes@460
   245
	}
nkeynes@460
   246
	lxdream_save_config();
nkeynes@460
   247
    } else {
nkeynes@460
   248
	int i;
nkeynes@460
   249
	for( i=0; i<MAX_DEVICES; i++ ) {
nkeynes@460
   250
	    if( maple_data[i].new_device != NULL && 
nkeynes@460
   251
		maple_data[i].new_device != maple_data[i].old_device ) {
nkeynes@460
   252
		maple_data[i].new_device->destroy(maple_data[i].new_device);
nkeynes@447
   253
	    }
nkeynes@447
   254
	}
nkeynes@447
   255
    }
nkeynes@447
   256
nkeynes@447
   257
}
nkeynes@447
   258
nkeynes@455
   259
GtkWidget *maple_panel_new()
nkeynes@447
   260
{
nkeynes@447
   261
    GtkWidget *table = gtk_table_new(4, 3, TRUE);
nkeynes@447
   262
    int i,j;
nkeynes@447
   263
    const struct maple_device_class **devices = maple_get_device_classes();
nkeynes@447
   264
nkeynes@447
   265
    for( i=0; i< MAX_DEVICES; i++ ) {
nkeynes@447
   266
	char buf[12];
nkeynes@447
   267
	GtkWidget *combo, *button;
nkeynes@447
   268
	int active = 0;
nkeynes@447
   269
	maple_device_t device = maple_get_device(i,0);
nkeynes@508
   270
	sprintf( buf, _("Slot %d."), i );
nkeynes@447
   271
	gtk_table_attach_defaults( GTK_TABLE(table), gtk_label_new(buf), 0, 1, i, i+1 );
nkeynes@447
   272
	combo = gtk_combo_box_new_text();
nkeynes@508
   273
	gtk_combo_box_append_text( GTK_COMBO_BOX(combo), _("<empty>") );
nkeynes@447
   274
	for( j=0; devices[j] != NULL; j++ ) {
nkeynes@447
   275
	    gtk_combo_box_append_text(GTK_COMBO_BOX(combo), devices[j]->name);
nkeynes@447
   276
	    if( device != NULL && device->device_class == devices[j] ) {
nkeynes@447
   277
		active = j+1;
nkeynes@447
   278
	    }
nkeynes@447
   279
	}
nkeynes@447
   280
	gtk_combo_box_set_active(GTK_COMBO_BOX(combo), active);
nkeynes@447
   281
	gtk_table_attach_defaults( GTK_TABLE(table), combo, 1, 2, i, i+1 );
nkeynes@447
   282
	button = gtk_button_new_from_stock( GTK_STOCK_PROPERTIES );
nkeynes@447
   283
	gtk_widget_set_sensitive(button, active != 0);
nkeynes@447
   284
	gtk_table_attach_defaults( GTK_TABLE(table), button, 2, 3, i, i+1 );
nkeynes@447
   285
nkeynes@447
   286
	maple_data[i].old_device = device;
nkeynes@447
   287
	maple_data[i].new_device = device;
nkeynes@447
   288
	maple_data[i].combo = combo;
nkeynes@447
   289
	maple_data[i].button = button;
nkeynes@450
   290
	g_signal_connect( button, "clicked", 
nkeynes@455
   291
			  G_CALLBACK( maple_properties_activated ), &maple_data[i] );
nkeynes@447
   292
	g_signal_connect( combo, "changed", 
nkeynes@455
   293
			  G_CALLBACK( maple_device_changed ), &maple_data[i] );
nkeynes@447
   294
nkeynes@447
   295
    }
nkeynes@447
   296
    return table;
nkeynes@447
   297
}
nkeynes@447
   298
nkeynes@460
   299
void maple_dialog_run( )
nkeynes@447
   300
{
nkeynes@508
   301
    gtk_gui_run_property_dialog( _("Controller Settings"), maple_panel_new(), maple_dialog_done );
nkeynes@447
   302
}
.