filename | src/gtkui/gtk_cfg.c |
changeset | 1072:d82e04e6d497 |
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 * Configuration pane to display a configuration group
5 * TODO:
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 <assert.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <gtk/gtk.h>
24 #include <gdk/gdkkeysyms.h>
26 #include "lxdream.h"
27 #include "config.h"
28 #include "lxpaths.h"
29 #include "display.h"
30 #include "gtkui/gtkui.h"
32 struct config_data {
33 lxdream_config_group_t config;
34 GtkWidget *fields[CONFIG_MAX_KEYS][2];
35 };
37 /**
38 * Update the configuration data for the current value of the given field.
39 */
40 static gboolean config_text_changed( GtkWidget *field, gpointer p )
41 {
42 GtkWidget *panel = field->parent;
43 struct config_data *data= (struct config_data *)gtk_object_get_data( GTK_OBJECT(panel), "config_data" );
44 int tag = GPOINTER_TO_INT( g_object_get_data( G_OBJECT(field), "tag" ) );
46 char buf[64];
47 GtkWidget *entry1, *entry2;
48 const gchar *key1 = NULL, *key2 = NULL;
50 if( data->fields[tag][0] != NULL ) {
51 key1 = gtk_entry_get_text(GTK_ENTRY(data->fields[tag][0]));
52 }
53 if( data->fields[tag][1] != NULL ) {
54 key2 = gtk_entry_get_text(GTK_ENTRY(data->fields[tag][1]));
55 }
57 if( key1 == NULL || key1[0] == '\0') {
58 lxdream_set_config_value( data->config, tag, key2 );
59 } else if( key2 == NULL || key2[0] == '\0') {
60 lxdream_set_config_value( data->config, tag, key1 );
61 } else {
62 char buf[strlen(key1) + strlen(key2) + 3];
63 snprintf( buf, sizeof(buf), "%s, %s", key1, key2 );
64 lxdream_set_config_value( data->config, tag, buf );
65 }
66 return TRUE;
67 }
69 /**
70 * Reset the fields (identified by one of the widgets in the field) back to it's
71 * value in the config group.
72 */
73 static void config_text_reset( GtkWidget *field )
74 {
75 GtkWidget *panel = field->parent;
76 struct config_data *data= (struct config_data *)gtk_object_get_data( GTK_OBJECT(panel), "config_data" );
77 int tag = GPOINTER_TO_INT( g_object_get_data( G_OBJECT(field), "tag" ) );
79 const gchar *value = data->config->params[tag].value;
80 if( value == NULL ) {
81 value = "";
82 }
84 if( data->fields[tag][0] == NULL ) {
85 if( data->fields[tag][1] != NULL ) {
86 gtk_entry_set_text( GTK_ENTRY(data->fields[tag][1]), value );
87 }
88 } else if( data->fields[tag][1] == NULL ) {
89 gtk_entry_set_text( GTK_ENTRY(data->fields[tag][0]), value );
90 } else { /* Split between two fields */
91 gchar *v1 = "", *v2 = "";
92 gchar **parts = g_strsplit(value,",",3);
93 if( parts[0] != NULL ) {
94 v1 = parts[0];
95 if( parts[1] != NULL ) {
96 v2 = parts[1];
97 }
99 }
100 gtk_entry_set_text( GTK_ENTRY(data->fields[tag][0]), v1 );
101 gtk_entry_set_text( GTK_ENTRY(data->fields[tag][1]), v2 );
102 g_strfreev(parts);
103 }
104 }
106 static void config_set_field( void *p, const gchar *keysym )
107 {
108 GtkWidget *field = GTK_WIDGET(p);
109 GtkWidget *panel = field->parent;
111 gtk_entry_set_text( GTK_ENTRY(field), keysym );
112 g_object_set_data( G_OBJECT(field), "keypress_mode", GINT_TO_POINTER(FALSE) );
113 input_set_keysym_hook(NULL, NULL);
114 config_text_changed( field, NULL );
115 }
117 static gboolean config_key_buttonpress( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
118 {
119 gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
120 if( keypress_mode ) {
121 gchar *keysym = input_keycode_to_keysym( &system_mouse_driver, event->button);
122 if( keysym != NULL ) {
123 config_set_field( widget, keysym );
124 g_free(keysym);
125 }
126 return TRUE;
127 } else {
128 gtk_entry_set_text( GTK_ENTRY(widget), _("<press key>") );
129 g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(TRUE) );
130 input_set_keysym_hook( (display_keysym_callback_t)config_set_field, widget);
131 gtk_widget_grab_focus( widget );
132 }
133 return FALSE;
134 }
136 static gboolean config_key_keypress( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
137 {
138 gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
139 if( keypress_mode ) {
140 if( event->keyval == GDK_Escape ) {
141 config_text_reset( widget );
142 return TRUE;
143 }
144 GdkKeymap *keymap = gdk_keymap_get_default();
145 guint keyval;
147 gdk_keymap_translate_keyboard_state( keymap, event->hardware_keycode, 0, 0, &keyval,
148 NULL, NULL, NULL );
149 config_set_field( widget, gdk_keyval_name(keyval) );
150 return TRUE;
151 } else {
152 switch( event->keyval ) {
153 case GDK_Return:
154 case GDK_KP_Enter:
155 gtk_entry_set_text( GTK_ENTRY(widget), _("<press key>") );
156 g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(TRUE) );
157 input_set_keysym_hook((display_keysym_callback_t)config_set_field, widget);
158 return TRUE;
159 case GDK_BackSpace:
160 case GDK_Delete:
161 config_set_field( widget, "" );
162 return TRUE;
163 }
164 return FALSE;
165 }
166 }
168 static gboolean config_key_unfocus( GtkWidget *widget, gpointer user_data )
169 {
170 gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
171 if( keypress_mode ) {
172 /* We've lost focus while waiting for a key binding - restore the old value */
173 config_text_reset(widget);
174 g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(FALSE) );
175 input_set_keysym_hook(NULL,NULL);
176 }
177 return TRUE;
178 }
180 static gboolean path_file_button_clicked( GtkWidget *button, gpointer user_data )
181 {
182 GtkWidget *entry = GTK_WIDGET(user_data);
183 GtkWidget *file = gtk_file_chooser_dialog_new( _("Select file"), NULL,
184 GTK_FILE_CHOOSER_ACTION_OPEN,
185 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
186 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
187 NULL );
188 gchar *filename = get_expanded_path(gtk_entry_get_text(GTK_ENTRY(entry)));
189 gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(file), filename );
190 gtk_window_set_modal( GTK_WINDOW(file), TRUE );
191 gtk_widget_show_all( file );
192 gint result = gtk_dialog_run(GTK_DIALOG(file));
193 g_free(filename);
194 if( result == GTK_RESPONSE_ACCEPT ) {
195 filename = get_escaped_path(gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) ));
196 config_set_field( entry, filename );
197 g_free(filename);
198 }
199 gtk_widget_destroy(file);
200 return TRUE;
201 }
203 static gboolean path_dir_button_clicked( GtkWidget *button, gpointer user_data )
204 {
205 GtkWidget *entry = GTK_WIDGET(user_data);
206 GtkWidget *file = gtk_file_chooser_dialog_new( _("Select file"), NULL,
207 GTK_FILE_CHOOSER_ACTION_OPEN,
208 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
209 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
210 NULL );
211 gchar *filename = get_expanded_path(gtk_entry_get_text(GTK_ENTRY(entry)));
212 gtk_file_chooser_set_action( GTK_FILE_CHOOSER(file), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER );
213 gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(file), filename );
214 gtk_window_set_modal( GTK_WINDOW(file), TRUE );
215 gtk_widget_show_all( file );
216 gint result = gtk_dialog_run(GTK_DIALOG(file));
217 g_free(filename);
218 if( result == GTK_RESPONSE_ACCEPT ) {
219 filename = get_escaped_path(gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) ));
220 config_set_field( entry, filename );
221 g_free(filename);
222 }
223 gtk_widget_destroy(file);
224 return TRUE;
225 }
228 static void lxdream_configuration_panel_destroy( GtkWidget *panel, gpointer data )
229 {
230 input_set_keysym_hook(NULL, NULL);
231 }
233 static GtkWidget *gtk_configuration_panel_new( lxdream_config_group_t conf )
234 {
235 int count, i;
236 for( count=0; conf->params[count].label != NULL; count++ );
238 GtkWidget *table = gtk_table_new( count, 5, FALSE );
239 struct config_data *data = g_malloc0( sizeof(struct config_data) );
240 data->config = conf;
241 GList *focus_chain = NULL;
242 gtk_object_set_data_full( GTK_OBJECT(table), "config_data", data, g_free );
243 g_signal_connect( table, "destroy_event", G_CALLBACK(lxdream_configuration_panel_destroy), NULL );
244 for( i=0; conf->params[i].label != NULL; i++ ) {
245 GtkWidget *text, *text2, *button;
246 int x=0;
247 int y=i;
248 gtk_table_attach( GTK_TABLE(table), gtk_label_new(Q_(conf->params[i].label)), x, x+1, y, y+1,
249 GTK_SHRINK, GTK_SHRINK, 0, 0 );
250 switch( conf->params[i].type ) {
251 case CONFIG_TYPE_KEY:
252 data->fields[i][0] = text = gtk_entry_new();
253 gtk_entry_set_width_chars( GTK_ENTRY(text), 11 );
254 gtk_entry_set_editable( GTK_ENTRY(text), FALSE );
255 g_signal_connect( text, "key_press_event",
256 G_CALLBACK(config_key_keypress), NULL );
257 g_signal_connect( text, "button_press_event",
258 G_CALLBACK(config_key_buttonpress), NULL );
259 g_signal_connect( text, "focus_out_event",
260 G_CALLBACK(config_key_unfocus), NULL);
261 g_object_set_data( G_OBJECT(text), "keypress_mode", GINT_TO_POINTER(FALSE) );
262 g_object_set_data( G_OBJECT(text), "tag", GINT_TO_POINTER(i) );
263 gtk_table_attach_defaults( GTK_TABLE(table), text, x+1, x+2, y, y+1);
264 focus_chain = g_list_append( focus_chain, text );
266 data->fields[i][1] = text2 = gtk_entry_new();
267 gtk_entry_set_width_chars( GTK_ENTRY(text2), 11 );
268 gtk_entry_set_editable( GTK_ENTRY(text2), FALSE );
269 g_signal_connect( text2, "key_press_event",
270 G_CALLBACK(config_key_keypress), NULL );
271 g_signal_connect( text2, "button_press_event",
272 G_CALLBACK(config_key_buttonpress), NULL );
273 g_signal_connect( text2, "focus_out_event",
274 G_CALLBACK(config_key_unfocus), NULL);
275 g_object_set_data( G_OBJECT(text2), "keypress_mode", GINT_TO_POINTER(FALSE) );
276 g_object_set_data( G_OBJECT(text2), "tag", GINT_TO_POINTER(i) );
277 gtk_table_attach_defaults( GTK_TABLE(table), text2, x+2, x+3, y, y+1);
278 focus_chain = g_list_append( focus_chain, text2 );
280 if( conf->params[i].value != NULL ) {
281 gchar **parts = g_strsplit(conf->params[i].value,",",3);
282 if( parts[0] != NULL ) {
283 gtk_entry_set_text( GTK_ENTRY(text), g_strstrip(parts[0]) );
284 if( parts[1] != NULL ) {
285 gtk_entry_set_text( GTK_ENTRY(text2), g_strstrip(parts[1]) );
286 }
287 }
288 g_strfreev(parts);
289 }
290 break;
291 case CONFIG_TYPE_FILE:
292 case CONFIG_TYPE_PATH:
293 data->fields[i][0] = text = gtk_entry_new();
294 data->fields[i][1] = NULL;
295 button = gtk_button_new();
296 gtk_entry_set_text( GTK_ENTRY(text), conf->params[i].value );
297 gtk_entry_set_width_chars( GTK_ENTRY(text), 48 );
298 g_object_set_data( G_OBJECT(text), "tag", GINT_TO_POINTER(i) );
299 gtk_table_attach_defaults( GTK_TABLE(table), text, 1, 2, y, y+1 );
300 gtk_table_attach( GTK_TABLE(table), button, 2, 3, y, y+1, GTK_SHRINK, GTK_SHRINK, 0, 0 );
301 g_signal_connect( text, "changed", G_CALLBACK(config_text_changed), NULL );
302 if( conf->params[i].type == CONFIG_TYPE_FILE ) {
303 GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);
304 gtk_button_set_image( GTK_BUTTON(button), image );
305 g_signal_connect( button, "clicked", G_CALLBACK(path_file_button_clicked), text );
306 } else {
307 GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);
308 gtk_button_set_image( GTK_BUTTON(button), image );
309 g_signal_connect( button, "clicked", G_CALLBACK(path_dir_button_clicked), text );
310 }
311 break;
312 }
313 }
314 gtk_container_set_focus_chain( GTK_CONTAINER(table), focus_chain );
315 // gtk_gui_run_property_dialog( _("Controller Configuration"), table, controller_config_done );
316 return table;
317 }
319 int gtk_configuration_panel_run( const gchar *title, lxdream_config_group_t group )
320 {
321 struct lxdream_config_group tmp;
322 lxdream_clone_config_group( &tmp, group );
323 GtkWidget *panel = gtk_configuration_panel_new( &tmp );
324 int result = gtk_gui_run_property_dialog( title, panel, NULL );
325 if( result == GTK_RESPONSE_ACCEPT ) {
326 lxdream_copy_config_group( group, &tmp );
327 lxdream_save_config();
328 }
329 return result;
330 }
.