implementing button mappings table in gui
authorJavier S. Pedro <javier@javispedro.com>
Tue, 25 Aug 2009 01:22:25 +0000 (03:22 +0200)
committerJavier S. Pedro <javier@javispedro.com>
Tue, 25 Aug 2009 01:22:25 +0000 (03:22 +0200)
gui/Makefile
gui/cellrendererkey.c [new file with mode: 0644]
gui/cellrendererkey.h [new file with mode: 0644]
gui/controls.c
gui/plugin.h
platform/hgw.h

index 9ab946f..85e8d4a 100644 (file)
@@ -18,7 +18,7 @@ M4DEFS:= -DGAME_VERSION=$(GAME_VERSION) -DGAME_PLUGIN_PATH=$(GAME_PLUGIN_PATH)
 M4DEFS+= -DGAME_CONF_PATH=$(GAME_CONF_PATH) -DGAME_BIN_PATH=$(GAME_BIN_PATH)
 M4DEFS+= -DGAME_GAME_PATH=$(GAME_GAME_PATH) -DGAME_BANNER_PATH=$(GAME_BANNER_PATH)
 
-OBJS := plugin.o state.o save.o controls.o
+OBJS:=plugin.o state.o save.o controls.o cellrendererkey.o
 
 DATA_FILES:=drnoksnes.conf drnoksnes.desktop drnoksnes.game 
 DATA_FILES+=drnoksnes.service drnoksnes.startup.service
diff --git a/gui/cellrendererkey.c b/gui/cellrendererkey.c
new file mode 100644 (file)
index 0000000..5f89355
--- /dev/null
@@ -0,0 +1,464 @@
+#include <libintl.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include "cellrendererkey.h"
+
+#define _(x) x
+#define N_(x) x
+
+#define CELL_RENDERER_TEXT_PATH "cell-renderer-key-text"
+
+#define TOOLTIP_TEXT _("New accelerator...")
+
+static void             cell_renderer_key_finalize      (GObject             *object);
+static void             cell_renderer_key_init          (CellRendererKey *cell_key);
+static void             cell_renderer_key_class_init    (CellRendererKeyClass *cell_key_class);
+static GtkCellEditable *cell_renderer_key_start_editing (GtkCellRenderer          *cell,
+                                                             GdkEvent                 *event,
+                                                             GtkWidget                *widget,
+                                                             const gchar              *path,
+                                                             GdkRectangle             *background_area,
+                                                             GdkRectangle             *cell_area,
+                                                             GtkCellRendererState      flags);
+
+static void cell_renderer_key_get_property (GObject         *object,
+                                                guint            param_id,
+                                                GValue          *value,
+                                                GParamSpec      *pspec);
+static void cell_renderer_key_set_property (GObject         *object,
+                                                guint            param_id,
+                                                const GValue    *value,
+                                                GParamSpec      *pspec);
+static void cell_renderer_key_get_size     (GtkCellRenderer *cell,
+                                                GtkWidget       *widget,
+                                                GdkRectangle    *cell_area,
+                                                gint            *x_offset,
+                                                gint            *y_offset,
+                                                gint            *width,
+                                                gint            *height);
+
+
+enum {
+  PROP_0,
+
+  PROP_SCANCODE
+};
+
+static GtkCellRendererTextClass *parent_class = NULL;
+
+GType cell_renderer_key_get_type (void)
+{
+  static GType cell_key_type = 0;
+
+  if (!cell_key_type)
+    {
+      static const GTypeInfo cell_key_info =
+      {
+        sizeof (CellRendererKeyClass),
+       NULL,           /* base_init */
+       NULL,           /* base_finalize */
+        (GClassInitFunc)cell_renderer_key_class_init,
+       NULL,           /* class_finalize */
+       NULL,           /* class_data */
+        sizeof (CellRendererKey),
+       0,              /* n_preallocs */
+        (GInstanceInitFunc) cell_renderer_key_init
+      };
+
+      cell_key_type = g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT, "CellRendererKey", &cell_key_info, 0);
+    }
+
+  return cell_key_type;
+}
+
+static void
+cell_renderer_key_init (CellRendererKey *key)
+{
+       key->scancode = -1;
+}
+
+
+static void
+marshal_VOID__STRING_UINT (GClosure     *closure,
+                                      GValue       *return_value,
+                                     guint         n_param_values,
+                                     const GValue *param_values,
+                                     gpointer      invocation_hint,
+                                     gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__STRING_UINT) (gpointer     data1,
+                                 const char  *arg_1,
+                                                            guint        arg_2,
+                                                            gpointer     data2);
+  register GMarshalFunc_VOID__STRING_UINT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  
+  callback = (GMarshalFunc_VOID__STRING_UINT) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_value_get_string (param_values + 1),
+            g_value_get_uint (param_values + 2),
+            data2);
+}
+
+static void
+cell_renderer_key_class_init (CellRendererKeyClass *cell_key_class)
+{
+  GObjectClass *object_class;
+  GtkCellRendererClass *cell_renderer_class;
+
+  object_class = G_OBJECT_CLASS (cell_key_class);
+  cell_renderer_class = GTK_CELL_RENDERER_CLASS (cell_key_class);
+  parent_class = g_type_class_peek_parent (object_class);
+  
+  GTK_CELL_RENDERER_CLASS(cell_key_class)->start_editing = cell_renderer_key_start_editing;
+
+  object_class->set_property = cell_renderer_key_set_property;
+  object_class->get_property = cell_renderer_key_get_property;
+  cell_renderer_class->get_size = cell_renderer_key_get_size;
+
+  object_class->finalize = cell_renderer_key_finalize;
+   
+  g_object_class_install_property (object_class,
+                                   PROP_SCANCODE,
+                                   g_param_spec_int ("scancode",
+                                                     _("Scancode"),
+                                                     _("Scancode"),
+                                                      -1,
+                                                      G_MAXINT,
+                                                      -1,
+                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
+  
+  g_signal_new ("accel_edited",
+                TYPE_CELL_RENDERER_KEY,
+                G_SIGNAL_RUN_LAST,
+                G_STRUCT_OFFSET(CellRendererKeyClass, accel_edited),
+                NULL, NULL,
+                marshal_VOID__STRING_UINT,
+                G_TYPE_NONE,
+                2,G_TYPE_STRING,G_TYPE_UINT);
+
+  g_signal_new ("accel_cleared",
+                TYPE_CELL_RENDERER_KEY,
+                G_SIGNAL_RUN_LAST,
+                G_STRUCT_OFFSET(CellRendererKeyClass, accel_cleared),
+                NULL, NULL,
+                gtk_marshal_VOID__STRING,
+                G_TYPE_NONE,
+                1,G_TYPE_STRING);
+}
+
+
+GtkCellRenderer *
+cell_renderer_key_new (void)
+{
+  return GTK_CELL_RENDERER (g_object_new (TYPE_CELL_RENDERER_KEY, NULL));
+}
+
+static void
+cell_renderer_key_finalize (GObject *object)
+{
+  
+  (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+static void
+cell_renderer_key_get_property  (GObject                  *object,
+                                      guint                     param_id,
+                                      GValue                   *value,
+                                      GParamSpec               *pspec)
+{
+  CellRendererKey *key;
+
+  g_return_if_fail (IS_CELL_RENDERER_KEY(object));
+
+  key = CELL_RENDERER_KEY(object);
+  
+  switch (param_id)
+    {
+    case PROP_SCANCODE:
+      g_value_set_int(value, key->scancode);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+    }
+}
+
+static void
+cell_renderer_key_set_property  (GObject                  *object,
+                                      guint                     param_id,
+                                      const GValue             *value,
+                                      GParamSpec               *pspec)
+{
+  CellRendererKey *key;
+
+  g_return_if_fail (IS_CELL_RENDERER_KEY(object));
+
+  key = CELL_RENDERER_KEY(object);
+  
+  switch (param_id)
+    {
+    case PROP_SCANCODE:
+      cell_renderer_key_set_scancode(key, g_value_get_int(value));
+      break;
+      
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+    }
+}
+
+static void
+cell_renderer_key_get_size (GtkCellRenderer *cell,
+                                GtkWidget       *widget,
+                                GdkRectangle    *cell_area,
+                                gint            *x_offset,
+                                gint            *y_offset,
+                                gint            *width,
+                                gint            *height)
+
+{
+  CellRendererKey *key = (CellRendererKey *) cell;
+  GtkRequisition requisition;
+
+  if (key->sizing_label == NULL)
+    key->sizing_label = gtk_label_new (TOOLTIP_TEXT);
+
+  gtk_widget_size_request (key->sizing_label, &requisition);
+  (* GTK_CELL_RENDERER_CLASS (parent_class)->get_size) (cell, widget, cell_area, x_offset, y_offset, width, height);
+  /* FIXME: need to take the cell_area et al. into account */
+  if (width)
+    *width = MAX (*width, requisition.width);
+  if (height)
+    *height = MAX (*height, requisition.height);
+}
+
+static gboolean
+grab_key_callback (GtkWidget    *widget,
+                   GdkEventKey  *event,
+                   void         *data)
+{
+  char *path;
+  gboolean edited;
+  gboolean cleared;
+  
+  CellRendererKey* key = CELL_RENDERER_KEY(data);
+
+  edited = FALSE;
+  cleared = FALSE;
+
+  guint scancode = event->hardware_keycode;
+  edited = TRUE;
+ out:
+  gdk_keyboard_ungrab (event->time);
+  gdk_pointer_ungrab (event->time);
+  
+  path = g_strdup (g_object_get_data (G_OBJECT (key->edit_widget), CELL_RENDERER_TEXT_PATH));
+
+  gtk_cell_editable_editing_done(GTK_CELL_EDITABLE (key->edit_widget));
+  gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE (key->edit_widget));
+  key->edit_widget = NULL;
+  key->grab_widget = NULL;
+  
+  if (edited)
+    {
+      cell_renderer_key_set_scancode(key, scancode);
+      g_signal_emit_by_name (G_OBJECT(key), "accel_edited", path, scancode);
+    }
+  else if (cleared)
+    {
+      cell_renderer_key_set_scancode(key, 0);
+      g_signal_emit_by_name (G_OBJECT(key), "accel_cleared", path);
+    }
+
+  g_free (path);
+  return TRUE;
+}
+
+static void
+ungrab_stuff (GtkWidget *widget, gpointer data)
+{
+  CellRendererKey *key = CELL_RENDERER_KEY(data);
+
+  gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+  gdk_pointer_ungrab (GDK_CURRENT_TIME);
+
+  g_signal_handlers_disconnect_by_func (G_OBJECT (key->grab_widget),
+                                        G_CALLBACK (grab_key_callback), data);
+}
+
+static void
+pointless_eventbox_start_editing (GtkCellEditable *cell_editable,
+                                  GdkEvent        *event)
+{
+  /* do nothing, because we are pointless */
+}
+
+static void
+pointless_eventbox_cell_editable_init (GtkCellEditableIface *iface)
+{
+  iface->start_editing = pointless_eventbox_start_editing;
+}
+
+static GType
+pointless_eventbox_subclass_get_type (void)
+{
+  static GType eventbox_type = 0;
+
+  if (!eventbox_type)
+    {
+      static const GTypeInfo eventbox_info =
+      {
+        sizeof (GtkEventBoxClass),
+       NULL,           /* base_init */
+       NULL,           /* base_finalize */
+        NULL,
+       NULL,           /* class_finalize */
+       NULL,           /* class_data */
+        sizeof (GtkEventBox),
+       0,              /* n_preallocs */
+        (GInstanceInitFunc) NULL,
+      };
+
+      static const GInterfaceInfo cell_editable_info = {
+        (GInterfaceInitFunc) pointless_eventbox_cell_editable_init,
+        NULL, NULL };
+
+      eventbox_type = g_type_register_static (GTK_TYPE_EVENT_BOX, "EggCellEditableEventBox", &eventbox_info, 0);
+      
+      g_type_add_interface_static (eventbox_type,
+                                  GTK_TYPE_CELL_EDITABLE,
+                                  &cell_editable_info);
+    }
+
+  return eventbox_type;
+}
+
+static GtkCellEditable *
+cell_renderer_key_start_editing (GtkCellRenderer      *cell,
+                                     GdkEvent             *event,
+                                     GtkWidget            *widget,
+                                     const gchar          *path,
+                                     GdkRectangle         *background_area,
+                                     GdkRectangle         *cell_area,
+                                     GtkCellRendererState  flags)
+{
+  GtkCellRendererText *celltext;
+  CellRendererKey *key;
+  GtkWidget *label;
+  GtkWidget *eventbox;
+  
+  celltext = GTK_CELL_RENDERER_TEXT (cell);
+  key = CELL_RENDERER_KEY (cell);
+
+  /* If the cell isn't editable we return NULL. */
+  if (celltext->editable == FALSE)
+    return NULL;
+
+  g_return_val_if_fail (widget->window != NULL, NULL);
+  
+  if (gdk_keyboard_grab (widget->window, FALSE,
+                         gdk_event_get_time (event)) != GDK_GRAB_SUCCESS)
+    return NULL;
+
+  if (gdk_pointer_grab (widget->window, FALSE,
+                        GDK_BUTTON_PRESS_MASK,
+                        NULL, NULL,
+                        gdk_event_get_time (event)) != GDK_GRAB_SUCCESS)
+    {
+      gdk_keyboard_ungrab (gdk_event_get_time (event));
+      return NULL;
+    }
+  
+  key->grab_widget = widget;
+
+  g_signal_connect (G_OBJECT (widget), "key_press_event",
+                    G_CALLBACK (grab_key_callback), key);
+
+  eventbox = g_object_new (pointless_eventbox_subclass_get_type (),
+                           NULL);
+  key->edit_widget = eventbox;
+  g_object_add_weak_pointer (G_OBJECT (key->edit_widget),
+                             (void**) &key->edit_widget);
+  
+  label = gtk_label_new (NULL);
+  //gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+  
+  gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL,
+                        &widget->style->bg[GTK_STATE_SELECTED]);
+
+  gtk_widget_modify_fg (label, GTK_STATE_NORMAL,
+                        &widget->style->fg[GTK_STATE_SELECTED]);
+  
+  gtk_label_set_text (GTK_LABEL (label),
+                 TOOLTIP_TEXT);
+
+  gtk_container_add (GTK_CONTAINER (eventbox), label);
+  
+  g_object_set_data_full (G_OBJECT (key->edit_widget), CELL_RENDERER_TEXT_PATH,
+                          g_strdup (path), g_free);
+  
+  gtk_widget_show_all (key->edit_widget);
+
+  g_signal_connect (G_OBJECT (key->edit_widget), "unrealize",
+                    G_CALLBACK (ungrab_stuff), key);
+  
+  return GTK_CELL_EDITABLE (key->edit_widget);
+}
+
+void cell_renderer_key_set_scancode (CellRendererKey *key, gint scancode)
+{
+  gboolean changed;
+
+  g_return_if_fail (IS_CELL_RENDERER_KEY(key));
+
+  g_object_freeze_notify(G_OBJECT(key));
+
+  changed = FALSE;
+  
+  if (scancode != key->scancode) {
+    key->scancode = scancode;
+    g_object_notify(G_OBJECT(key), "scancode");
+    changed = TRUE;
+  }
+
+  g_object_thaw_notify(G_OBJECT(key));
+
+  if (changed) {
+      const gchar *text;
+      /* sync string to the key values */
+      if (scancode <= 0) {
+       text = "None";
+      } else {
+        guint keyval = 0;
+
+        gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(),
+         scancode, 0, 0, &keyval, NULL, NULL, NULL);
+        text = gdk_keyval_name(keyval);
+      }
+      g_object_set(key, "text", text, NULL);
+  }
+}
+
+gint cell_renderer_keys_get_scancode(CellRendererKey *key)
+{
+  g_return_if_fail (IS_CELL_RENDERER_KEY(key));
+  return key->scancode;
+}
+
diff --git a/gui/cellrendererkey.h b/gui/cellrendererkey.h
new file mode 100644 (file)
index 0000000..668e5bb
--- /dev/null
@@ -0,0 +1,67 @@
+/* gtkcellrendererkeybinding.h
+ * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __CELL_RENDERER_KEY_H__
+#define __CELL_RENDERER_KEY_H__
+
+#include <gtk/gtkcellrenderertext.h>
+
+G_BEGIN_DECLS
+
+#define TYPE_CELL_RENDERER_KEY         (cell_renderer_key_get_type ())
+#define CELL_RENDERER_KEY(obj)         (GTK_CHECK_CAST ((obj), TYPE_CELL_RENDERER_KEY, CellRendererKey))
+#define CELL_RENDERER_KEY_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_CELL_RENDERER_KEY, CellRendererKeyClass))
+#define IS_CELL_RENDERER_KEY(obj)              (GTK_CHECK_TYPE ((obj), TYPE_CELL_RENDERER_KEY))
+#define IS_CELL_RENDERER_KEY_CLASS(klass)      (GTK_CHECK_CLASS_TYPE ((klass), TYPE_CELL_RENDERER_KEY))
+#define CELL_RENDERER_KEY_GET_CLASS(obj)   (GTK_CHECK_GET_CLASS ((obj), TYPE_CELL_RENDERER_KEY, CellRendererKeyClass))
+
+typedef struct _CellRendererKey      CellRendererKey;
+typedef struct _CellRendererKeyClass CellRendererKeyClass;
+
+struct _CellRendererKey
+{
+  GtkCellRendererText parent;
+  gint scancode;
+  GtkWidget *edit_widget;
+  GtkWidget *grab_widget;
+  GtkWidget *sizing_label;
+};
+
+struct _CellRendererKeyClass
+{
+  GtkCellRendererTextClass parent_class;
+
+  void (* accel_edited) (CellRendererKey    *keys,
+                        const char             *path_string,
+                        guint                   scancode);
+
+  void (* accel_cleared) (CellRendererKey    *keys,
+                         const char             *path_string);
+};
+
+GType            cell_renderer_key_get_type        (void);
+GtkCellRenderer *cell_renderer_key_new             (void);
+
+void cell_renderer_key_set_scancode(CellRendererKey * key, gint scancode);
+gint cell_renderer_key_get_scancode(CellRendererKey * key);
+
+G_END_DECLS
+
+
+#endif /* __GTK_CELL_RENDERER_KEYS_H__ */
index 8b35091..12b7532 100644 (file)
 */
 
 #include <gtk/gtk.h>
-#include <gconf/gconf.h>
-#include <gconf/gconf-client.h>
+#include <hildon/hildon-helper.h>
 
 #include "../platform/hgw.h"
 #include "plugin.h"
+#include "cellrendererkey.h"
 
 static GtkDialog* dialog;
-static GtkTreeView* list;
+static GtkComboBox* combo;
+static GtkScrolledWindow* keys_scroll;
+static GtkListStore* keys_store;
+static GtkTreeView* keys_list;
+
+enum
+{
+  BUTTON_COLUMN,
+  BUTTONENTRY_COLUMN,
+  N_COLUMNS
+};
+
+typedef struct ButtonEntry {
+       const char * name;
+       const char * gconf_key;
+       int scancode;
+} ButtonEntry;
+#define BUTTON_INITIALIZER(name)       { name, kGConfKeysPath name, 0 }
+#define BUTTON_LAST                                    { 0 }
+static const ButtonEntry buttons[] = {
+       BUTTON_INITIALIZER("A"),
+       BUTTON_INITIALIZER("B"),
+       BUTTON_INITIALIZER("X"),
+       BUTTON_INITIALIZER("Y"),
+       BUTTON_INITIALIZER("L"),
+       BUTTON_INITIALIZER("R"),
+       BUTTON_INITIALIZER("Start"),
+       BUTTON_INITIALIZER("Select"),
+       BUTTON_INITIALIZER("Up"),
+       BUTTON_INITIALIZER("Down"),
+       BUTTON_INITIALIZER("Left"),
+       BUTTON_INITIALIZER("Right"),
+       BUTTON_LAST
+};
+
+static void show_widgets()
+{
+       gtk_widget_show_all(GTK_WIDGET(combo));
+       gtk_widget_hide_all(GTK_WIDGET(keys_scroll));
+       switch (gtk_combo_box_get_active(combo)) {
+               case 1:
+                       gtk_widget_show_all(GTK_WIDGET(keys_scroll));
+               break;
+       }
+}
+
+static gboolean load_key_config(GtkTreeModel *model, GtkTreePath *path,
+                                GtkTreeIter *iter, gpointer data)
+{
+       ButtonEntry *button_entry;
+
+       gtk_tree_model_get(model, iter,
+               BUTTONENTRY_COLUMN, &button_entry,
+               -1);
+
+       button_entry->scancode =
+               gconf_client_get_int(gcc, button_entry->gconf_key, NULL);
+       gtk_tree_model_row_changed(GTK_TREE_MODEL(keys_store), path, iter);
+
+       return FALSE;
+}
+
+static void load_config()
+{
+       GConfValue* mapping = gconf_client_get(gcc, kGConfMapping, NULL);
+
+       if (!mapping) {
+               mapping = gconf_value_new(GCONF_VALUE_INT);
+               gconf_value_set_int(mapping, 1);
+               gconf_client_set(gcc, kGConfMapping, mapping, NULL);
+       }
+
+       gtk_combo_box_set_active(combo, gconf_value_get_int(mapping));
+
+       gtk_tree_model_foreach(GTK_TREE_MODEL(keys_store), load_key_config, NULL);
+
+       show_widgets();
+       gconf_value_free(mapping);
+}
+
+static void write_config()
+{
+       gconf_client_set_int(gcc, kGConfMapping,
+               gtk_combo_box_get_active(combo), NULL);
+}
+
+static void
+accel_set_func (GtkTreeViewColumn *tree_column,
+                GtkCellRenderer   *cell,
+                GtkTreeModel      *model,
+                GtkTreeIter       *iter,
+                gpointer           data)
+{
+       ButtonEntry *button_entry;
+
+       gtk_tree_model_get (model, iter,
+                                               BUTTONENTRY_COLUMN, &button_entry,
+                                               -1);
+
+       if (button_entry == NULL) {
+               g_object_set (G_OBJECT (cell),
+                       "visible", FALSE,
+                       NULL);
+       } else {
+               g_object_set (G_OBJECT (cell),
+                       "visible", TRUE,
+                       "editable", TRUE,
+                       "scancode", button_entry->scancode,
+                       "style", PANGO_STYLE_NORMAL,
+                       NULL);
+       }
+}
+
+static void
+cb_key_edited(GtkCellRendererText *cell, const char *path_string,
+       guint scancode, gpointer data)
+{
+       GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
+       GtkTreeIter iter;
+       ButtonEntry *button_entry;
+
+       gtk_tree_model_get_iter(GTK_TREE_MODEL(keys_store), &iter, path);
+       gtk_tree_model_get(GTK_TREE_MODEL(keys_store), &iter,
+               BUTTONENTRY_COLUMN, &button_entry,
+               -1);
+
+    g_debug("Setting scancode for button %s to %u\n",
+               button_entry->name, scancode);
+
+       button_entry->scancode = scancode;
+       gtk_tree_model_row_changed(GTK_TREE_MODEL(keys_store), path, &iter);
+
+       gtk_tree_path_free(path);
+}
+
+static void
+cb_key_cleared(GtkCellRendererText *cell, const char *path_string,
+       gpointer data)
+{
+       GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
+       GtkTreeIter iter;
+       ButtonEntry *button_entry;
+
+       gtk_tree_model_get_iter(GTK_TREE_MODEL(keys_store), &iter, path);
+       gtk_tree_path_free(path);
+       gtk_tree_model_get(GTK_TREE_MODEL(keys_store), &iter,
+               BUTTONENTRY_COLUMN, &button_entry,
+               -1);
+
+       button_entry->scancode = 0;
+}
+
+static void cb_combo_changed(GtkComboBox * widget, gpointer data)
+{
+       show_widgets();
+}
 
 static void cb_dialog_response(GtkWidget * button, gpointer data)
 {
+       write_config();
        gtk_widget_destroy(GTK_WIDGET(dialog));
 }
 
@@ -41,14 +197,62 @@ void controls_dialog(GtkWindow* parent)
                parent, GTK_DIALOG_MODAL,
                GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL));
 
-       list = GTK_TREE_VIEW(gtk_tree_view_new());
+       combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
+       gtk_combo_box_append_text(combo, "No controls/Use config file");
+       gtk_combo_box_append_text(combo, "Use physical keys");
+       gtk_combo_box_append_text(combo, "Use touchscreen");
+
+       keys_scroll = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
+       keys_store = GTK_LIST_STORE(gtk_list_store_new(N_COLUMNS,
+               G_TYPE_STRING, G_TYPE_POINTER));
+       keys_list = GTK_TREE_VIEW(
+               gtk_tree_view_new_with_model(GTK_TREE_MODEL(keys_store)));
+
+       GtkCellRenderer* renderer = GTK_CELL_RENDERER(gtk_cell_renderer_text_new());
+       GtkTreeViewColumn * column =
+                gtk_tree_view_column_new_with_attributes ("Button",
+                       gtk_cell_renderer_text_new(),
+                       "text", BUTTON_COLUMN,
+                       NULL);
+       gtk_tree_view_column_set_resizable(column, FALSE);
+       gtk_tree_view_column_set_expand(column, TRUE);
+       gtk_tree_view_append_column(keys_list, column);
+
+       renderer = GTK_CELL_RENDERER(cell_renderer_key_new());
+       column = gtk_tree_view_column_new_with_attributes("Key", renderer, NULL);
+       gtk_tree_view_column_set_cell_data_func(column, renderer, accel_set_func, NULL, NULL);
+       gtk_tree_view_column_set_resizable(column, FALSE);
+       gtk_tree_view_column_set_min_width(column, 200);
+       gtk_tree_view_append_column(keys_list, column);
+       gtk_tree_view_set_headers_visible(keys_list, TRUE);
+
+       int i;
+       for (i = 0; buttons[i].name; i++) {
+               GtkTreeIter iter;
+               gtk_list_store_append(keys_store, &iter);
+               gtk_list_store_set(keys_store, &iter,
+                       BUTTON_COLUMN, buttons[i].name,
+                       BUTTONENTRY_COLUMN, &buttons[i],
+                       -1);
+       }
+
+       gtk_window_resize(GTK_WINDOW(dialog), 600, 340);
+       gtk_box_pack_start(GTK_BOX(dialog->vbox), GTK_WIDGET(combo),
+               FALSE, FALSE, HILDON_MARGIN_HALF);
+       gtk_container_add(GTK_CONTAINER(keys_scroll), GTK_WIDGET(keys_list));
+       gtk_box_pack_start_defaults(GTK_BOX(dialog->vbox), GTK_WIDGET(keys_scroll));
 
-       gtk_box_pack_start_defaults(GTK_BOX(dialog->vbox), GTK_WIDGET(list));
+       load_config();
 
        g_signal_connect(G_OBJECT(dialog), "response",
                                        G_CALLBACK (cb_dialog_response), NULL);
+       g_signal_connect(G_OBJECT(combo), "changed",
+                                       G_CALLBACK(cb_combo_changed), NULL);
+       g_signal_connect(G_OBJECT(renderer), "accel_edited",
+                                       G_CALLBACK(cb_key_edited), NULL);
+       g_signal_connect(G_OBJECT(renderer), "accel_cleared",
+                    G_CALLBACK(cb_key_cleared), NULL);
 
-       gtk_window_resize(GTK_WINDOW(dialog), 600, 300);
-       gtk_widget_show_all(GTK_WIDGET(dialog));
+       gtk_widget_show(GTK_WIDGET(dialog));
 }
 
index 548899b..9c82288 100644 (file)
@@ -3,8 +3,11 @@
 
 #include <glib.h>
 #include <gtk/gtk.h>
+#include <gconf/gconf.h>
+#include <gconf/gconf-client.h>
 
 /* plugin.c */
+extern GConfClient * gcc;
 extern char * current_rom_file;
 
 /* state.c */
index 68c351c..ec948ec 100644 (file)
@@ -17,6 +17,8 @@ void HgwPollEvents();
 #define kGConfFrameskip kGConfPath "frameskip"
 #define kGConfTransparency kGConfPath "transparency"
 #define kGConfSpeedhacks kGConfPath "speedhacks"
+#define kGConfMapping kGConfPath "mapping"
+#define kGConfKeysPath kGConfPath "keys/"
 
 #endif