Search
lxdream.org :: lxdream/src/gtkui/gtk_cfg.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/gtkui/gtk_cfg.c
changeset 1072:d82e04e6d497
author nkeynes
date Sat Mar 03 15:52:59 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Swap between run + pause icons when pressed
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/gtkui/gtk_cfg.c Sat Mar 03 15:52:59 2012 +1000
1.3 @@ -0,0 +1,330 @@
1.4 +/**
1.5 + * $Id$
1.6 + *
1.7 + * Configuration pane to display a configuration group
1.8 + * TODO:
1.9 + *
1.10 + * Copyright (c) 2009 Nathan Keynes.
1.11 + *
1.12 + * This program is free software; you can redistribute it and/or modify
1.13 + * it under the terms of the GNU General Public License as published by
1.14 + * the Free Software Foundation; either version 2 of the License, or
1.15 + * (at your option) any later version.
1.16 + *
1.17 + * This program is distributed in the hope that it will be useful,
1.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.20 + * GNU General Public License for more details.
1.21 + */
1.22 +
1.23 +#include <assert.h>
1.24 +#include <string.h>
1.25 +#include <errno.h>
1.26 +#include <gtk/gtk.h>
1.27 +#include <gdk/gdkkeysyms.h>
1.28 +
1.29 +#include "lxdream.h"
1.30 +#include "config.h"
1.31 +#include "lxpaths.h"
1.32 +#include "display.h"
1.33 +#include "gtkui/gtkui.h"
1.34 +
1.35 +struct config_data {
1.36 + lxdream_config_group_t config;
1.37 + GtkWidget *fields[CONFIG_MAX_KEYS][2];
1.38 +};
1.39 +
1.40 +/**
1.41 + * Update the configuration data for the current value of the given field.
1.42 + */
1.43 +static gboolean config_text_changed( GtkWidget *field, gpointer p )
1.44 +{
1.45 + GtkWidget *panel = field->parent;
1.46 + struct config_data *data= (struct config_data *)gtk_object_get_data( GTK_OBJECT(panel), "config_data" );
1.47 + int tag = GPOINTER_TO_INT( g_object_get_data( G_OBJECT(field), "tag" ) );
1.48 +
1.49 + char buf[64];
1.50 + GtkWidget *entry1, *entry2;
1.51 + const gchar *key1 = NULL, *key2 = NULL;
1.52 +
1.53 + if( data->fields[tag][0] != NULL ) {
1.54 + key1 = gtk_entry_get_text(GTK_ENTRY(data->fields[tag][0]));
1.55 + }
1.56 + if( data->fields[tag][1] != NULL ) {
1.57 + key2 = gtk_entry_get_text(GTK_ENTRY(data->fields[tag][1]));
1.58 + }
1.59 +
1.60 + if( key1 == NULL || key1[0] == '\0') {
1.61 + lxdream_set_config_value( data->config, tag, key2 );
1.62 + } else if( key2 == NULL || key2[0] == '\0') {
1.63 + lxdream_set_config_value( data->config, tag, key1 );
1.64 + } else {
1.65 + char buf[strlen(key1) + strlen(key2) + 3];
1.66 + snprintf( buf, sizeof(buf), "%s, %s", key1, key2 );
1.67 + lxdream_set_config_value( data->config, tag, buf );
1.68 + }
1.69 + return TRUE;
1.70 +}
1.71 +
1.72 +/**
1.73 + * Reset the fields (identified by one of the widgets in the field) back to it's
1.74 + * value in the config group.
1.75 + */
1.76 +static void config_text_reset( GtkWidget *field )
1.77 +{
1.78 + GtkWidget *panel = field->parent;
1.79 + struct config_data *data= (struct config_data *)gtk_object_get_data( GTK_OBJECT(panel), "config_data" );
1.80 + int tag = GPOINTER_TO_INT( g_object_get_data( G_OBJECT(field), "tag" ) );
1.81 +
1.82 + const gchar *value = data->config->params[tag].value;
1.83 + if( value == NULL ) {
1.84 + value = "";
1.85 + }
1.86 +
1.87 + if( data->fields[tag][0] == NULL ) {
1.88 + if( data->fields[tag][1] != NULL ) {
1.89 + gtk_entry_set_text( GTK_ENTRY(data->fields[tag][1]), value );
1.90 + }
1.91 + } else if( data->fields[tag][1] == NULL ) {
1.92 + gtk_entry_set_text( GTK_ENTRY(data->fields[tag][0]), value );
1.93 + } else { /* Split between two fields */
1.94 + gchar *v1 = "", *v2 = "";
1.95 + gchar **parts = g_strsplit(value,",",3);
1.96 + if( parts[0] != NULL ) {
1.97 + v1 = parts[0];
1.98 + if( parts[1] != NULL ) {
1.99 + v2 = parts[1];
1.100 + }
1.101 +
1.102 + }
1.103 + gtk_entry_set_text( GTK_ENTRY(data->fields[tag][0]), v1 );
1.104 + gtk_entry_set_text( GTK_ENTRY(data->fields[tag][1]), v2 );
1.105 + g_strfreev(parts);
1.106 + }
1.107 +}
1.108 +
1.109 +static void config_set_field( void *p, const gchar *keysym )
1.110 +{
1.111 + GtkWidget *field = GTK_WIDGET(p);
1.112 + GtkWidget *panel = field->parent;
1.113 +
1.114 + gtk_entry_set_text( GTK_ENTRY(field), keysym );
1.115 + g_object_set_data( G_OBJECT(field), "keypress_mode", GINT_TO_POINTER(FALSE) );
1.116 + input_set_keysym_hook(NULL, NULL);
1.117 + config_text_changed( field, NULL );
1.118 +}
1.119 +
1.120 +static gboolean config_key_buttonpress( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
1.121 +{
1.122 + gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
1.123 + if( keypress_mode ) {
1.124 + gchar *keysym = input_keycode_to_keysym( &system_mouse_driver, event->button);
1.125 + if( keysym != NULL ) {
1.126 + config_set_field( widget, keysym );
1.127 + g_free(keysym);
1.128 + }
1.129 + return TRUE;
1.130 + } else {
1.131 + gtk_entry_set_text( GTK_ENTRY(widget), _("<press key>") );
1.132 + g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(TRUE) );
1.133 + input_set_keysym_hook( (display_keysym_callback_t)config_set_field, widget);
1.134 + gtk_widget_grab_focus( widget );
1.135 + }
1.136 + return FALSE;
1.137 +}
1.138 +
1.139 +static gboolean config_key_keypress( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
1.140 +{
1.141 + gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
1.142 + if( keypress_mode ) {
1.143 + if( event->keyval == GDK_Escape ) {
1.144 + config_text_reset( widget );
1.145 + return TRUE;
1.146 + }
1.147 + GdkKeymap *keymap = gdk_keymap_get_default();
1.148 + guint keyval;
1.149 +
1.150 + gdk_keymap_translate_keyboard_state( keymap, event->hardware_keycode, 0, 0, &keyval,
1.151 + NULL, NULL, NULL );
1.152 + config_set_field( widget, gdk_keyval_name(keyval) );
1.153 + return TRUE;
1.154 + } else {
1.155 + switch( event->keyval ) {
1.156 + case GDK_Return:
1.157 + case GDK_KP_Enter:
1.158 + gtk_entry_set_text( GTK_ENTRY(widget), _("<press key>") );
1.159 + g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(TRUE) );
1.160 + input_set_keysym_hook((display_keysym_callback_t)config_set_field, widget);
1.161 + return TRUE;
1.162 + case GDK_BackSpace:
1.163 + case GDK_Delete:
1.164 + config_set_field( widget, "" );
1.165 + return TRUE;
1.166 + }
1.167 + return FALSE;
1.168 + }
1.169 +}
1.170 +
1.171 +static gboolean config_key_unfocus( GtkWidget *widget, gpointer user_data )
1.172 +{
1.173 + gboolean keypress_mode = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(widget), "keypress_mode"));
1.174 + if( keypress_mode ) {
1.175 + /* We've lost focus while waiting for a key binding - restore the old value */
1.176 + config_text_reset(widget);
1.177 + g_object_set_data( G_OBJECT(widget), "keypress_mode", GINT_TO_POINTER(FALSE) );
1.178 + input_set_keysym_hook(NULL,NULL);
1.179 + }
1.180 + return TRUE;
1.181 +}
1.182 +
1.183 +static gboolean path_file_button_clicked( GtkWidget *button, gpointer user_data )
1.184 +{
1.185 + GtkWidget *entry = GTK_WIDGET(user_data);
1.186 + GtkWidget *file = gtk_file_chooser_dialog_new( _("Select file"), NULL,
1.187 + GTK_FILE_CHOOSER_ACTION_OPEN,
1.188 + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1.189 + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1.190 + NULL );
1.191 + gchar *filename = get_expanded_path(gtk_entry_get_text(GTK_ENTRY(entry)));
1.192 + gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(file), filename );
1.193 + gtk_window_set_modal( GTK_WINDOW(file), TRUE );
1.194 + gtk_widget_show_all( file );
1.195 + gint result = gtk_dialog_run(GTK_DIALOG(file));
1.196 + g_free(filename);
1.197 + if( result == GTK_RESPONSE_ACCEPT ) {
1.198 + filename = get_escaped_path(gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) ));
1.199 + config_set_field( entry, filename );
1.200 + g_free(filename);
1.201 + }
1.202 + gtk_widget_destroy(file);
1.203 + return TRUE;
1.204 +}
1.205 +
1.206 +static gboolean path_dir_button_clicked( GtkWidget *button, gpointer user_data )
1.207 +{
1.208 + GtkWidget *entry = GTK_WIDGET(user_data);
1.209 + GtkWidget *file = gtk_file_chooser_dialog_new( _("Select file"), NULL,
1.210 + GTK_FILE_CHOOSER_ACTION_OPEN,
1.211 + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1.212 + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1.213 + NULL );
1.214 + gchar *filename = get_expanded_path(gtk_entry_get_text(GTK_ENTRY(entry)));
1.215 + gtk_file_chooser_set_action( GTK_FILE_CHOOSER(file), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER );
1.216 + gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(file), filename );
1.217 + gtk_window_set_modal( GTK_WINDOW(file), TRUE );
1.218 + gtk_widget_show_all( file );
1.219 + gint result = gtk_dialog_run(GTK_DIALOG(file));
1.220 + g_free(filename);
1.221 + if( result == GTK_RESPONSE_ACCEPT ) {
1.222 + filename = get_escaped_path(gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(file) ));
1.223 + config_set_field( entry, filename );
1.224 + g_free(filename);
1.225 + }
1.226 + gtk_widget_destroy(file);
1.227 + return TRUE;
1.228 +}
1.229 +
1.230 +
1.231 +static void lxdream_configuration_panel_destroy( GtkWidget *panel, gpointer data )
1.232 +{
1.233 + input_set_keysym_hook(NULL, NULL);
1.234 +}
1.235 +
1.236 +static GtkWidget *gtk_configuration_panel_new( lxdream_config_group_t conf )
1.237 +{
1.238 + int count, i;
1.239 + for( count=0; conf->params[count].label != NULL; count++ );
1.240 +
1.241 + GtkWidget *table = gtk_table_new( count, 5, FALSE );
1.242 + struct config_data *data = g_malloc0( sizeof(struct config_data) );
1.243 + data->config = conf;
1.244 + GList *focus_chain = NULL;
1.245 + gtk_object_set_data_full( GTK_OBJECT(table), "config_data", data, g_free );
1.246 + g_signal_connect( table, "destroy_event", G_CALLBACK(lxdream_configuration_panel_destroy), NULL );
1.247 + for( i=0; conf->params[i].label != NULL; i++ ) {
1.248 + GtkWidget *text, *text2, *button;
1.249 + int x=0;
1.250 + int y=i;
1.251 + gtk_table_attach( GTK_TABLE(table), gtk_label_new(Q_(conf->params[i].label)), x, x+1, y, y+1,
1.252 + GTK_SHRINK, GTK_SHRINK, 0, 0 );
1.253 + switch( conf->params[i].type ) {
1.254 + case CONFIG_TYPE_KEY:
1.255 + data->fields[i][0] = text = gtk_entry_new();
1.256 + gtk_entry_set_width_chars( GTK_ENTRY(text), 11 );
1.257 + gtk_entry_set_editable( GTK_ENTRY(text), FALSE );
1.258 + g_signal_connect( text, "key_press_event",
1.259 + G_CALLBACK(config_key_keypress), NULL );
1.260 + g_signal_connect( text, "button_press_event",
1.261 + G_CALLBACK(config_key_buttonpress), NULL );
1.262 + g_signal_connect( text, "focus_out_event",
1.263 + G_CALLBACK(config_key_unfocus), NULL);
1.264 + g_object_set_data( G_OBJECT(text), "keypress_mode", GINT_TO_POINTER(FALSE) );
1.265 + g_object_set_data( G_OBJECT(text), "tag", GINT_TO_POINTER(i) );
1.266 + gtk_table_attach_defaults( GTK_TABLE(table), text, x+1, x+2, y, y+1);
1.267 + focus_chain = g_list_append( focus_chain, text );
1.268 +
1.269 + data->fields[i][1] = text2 = gtk_entry_new();
1.270 + gtk_entry_set_width_chars( GTK_ENTRY(text2), 11 );
1.271 + gtk_entry_set_editable( GTK_ENTRY(text2), FALSE );
1.272 + g_signal_connect( text2, "key_press_event",
1.273 + G_CALLBACK(config_key_keypress), NULL );
1.274 + g_signal_connect( text2, "button_press_event",
1.275 + G_CALLBACK(config_key_buttonpress), NULL );
1.276 + g_signal_connect( text2, "focus_out_event",
1.277 + G_CALLBACK(config_key_unfocus), NULL);
1.278 + g_object_set_data( G_OBJECT(text2), "keypress_mode", GINT_TO_POINTER(FALSE) );
1.279 + g_object_set_data( G_OBJECT(text2), "tag", GINT_TO_POINTER(i) );
1.280 + gtk_table_attach_defaults( GTK_TABLE(table), text2, x+2, x+3, y, y+1);
1.281 + focus_chain = g_list_append( focus_chain, text2 );
1.282 +
1.283 + if( conf->params[i].value != NULL ) {
1.284 + gchar **parts = g_strsplit(conf->params[i].value,",",3);
1.285 + if( parts[0] != NULL ) {
1.286 + gtk_entry_set_text( GTK_ENTRY(text), g_strstrip(parts[0]) );
1.287 + if( parts[1] != NULL ) {
1.288 + gtk_entry_set_text( GTK_ENTRY(text2), g_strstrip(parts[1]) );
1.289 + }
1.290 + }
1.291 + g_strfreev(parts);
1.292 + }
1.293 + break;
1.294 + case CONFIG_TYPE_FILE:
1.295 + case CONFIG_TYPE_PATH:
1.296 + data->fields[i][0] = text = gtk_entry_new();
1.297 + data->fields[i][1] = NULL;
1.298 + button = gtk_button_new();
1.299 + gtk_entry_set_text( GTK_ENTRY(text), conf->params[i].value );
1.300 + gtk_entry_set_width_chars( GTK_ENTRY(text), 48 );
1.301 + g_object_set_data( G_OBJECT(text), "tag", GINT_TO_POINTER(i) );
1.302 + gtk_table_attach_defaults( GTK_TABLE(table), text, 1, 2, y, y+1 );
1.303 + gtk_table_attach( GTK_TABLE(table), button, 2, 3, y, y+1, GTK_SHRINK, GTK_SHRINK, 0, 0 );
1.304 + g_signal_connect( text, "changed", G_CALLBACK(config_text_changed), NULL );
1.305 + if( conf->params[i].type == CONFIG_TYPE_FILE ) {
1.306 + GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);
1.307 + gtk_button_set_image( GTK_BUTTON(button), image );
1.308 + g_signal_connect( button, "clicked", G_CALLBACK(path_file_button_clicked), text );
1.309 + } else {
1.310 + GtkWidget *image = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);
1.311 + gtk_button_set_image( GTK_BUTTON(button), image );
1.312 + g_signal_connect( button, "clicked", G_CALLBACK(path_dir_button_clicked), text );
1.313 + }
1.314 + break;
1.315 + }
1.316 + }
1.317 + gtk_container_set_focus_chain( GTK_CONTAINER(table), focus_chain );
1.318 +// gtk_gui_run_property_dialog( _("Controller Configuration"), table, controller_config_done );
1.319 + return table;
1.320 +}
1.321 +
1.322 +int gtk_configuration_panel_run( const gchar *title, lxdream_config_group_t group )
1.323 +{
1.324 + struct lxdream_config_group tmp;
1.325 + lxdream_clone_config_group( &tmp, group );
1.326 + GtkWidget *panel = gtk_configuration_panel_new( &tmp );
1.327 + int result = gtk_gui_run_property_dialog( title, panel, NULL );
1.328 + if( result == GTK_RESPONSE_ACCEPT ) {
1.329 + lxdream_copy_config_group( group, &tmp );
1.330 + lxdream_save_config();
1.331 + }
1.332 + return result;
1.333 +}
.