added #define GIMP_CONTROLLER_PARAM_SERIALIZE. Made all properties

2004-06-16  Michael Natterer  <mitch@gimp.org>

	* libgimpwidgets/gimpcontroller.[ch]: added #define
	GIMP_CONTROLLER_PARAM_SERIALIZE. Made all properties serializable.

	* modules/controller_linux_input.c: made "device-name"
	serializable.

	* app/config/gimpconfig-params.h: added macro
	GIMP_CONFIG_INSTALL_PROP_POINTER() which needs to be handled
	by custom (de)serialize_property() implementations.

	* app/config/gimpconfig-deserialize.c
	* app/config/gimpconfig-serialize.c: made object (de)serialization
	work for object properties which are *not* GIMP_PARAM_AGGREGATE.
	Write/parse the exact type of the object to create to enable this.

	* app/core/gimpmarshal.list: new marshaller for GimpControllerInfo.

	* app/widgets/gimpcontrollerinfo.[ch]: implement GimpConfigInterface
	and add "controller" and "mapping" properties. Add "event-mapped"
	signal which carries the action_name.

	* app/widgets/gimpcontrollers.c: removed all deserialization code
	and simply (de)serialize the controller container. Install a
	container handler for "event-mapped" and do the action_name ->
	action mapping in the callback.

	* etc/controllerrc: regenerated with new syntax. Delete your old one!
This commit is contained in:
Michael Natterer 2004-06-16 18:14:44 +00:00 committed by Michael Natterer
parent 429b090fd4
commit 3a7f7d54e7
15 changed files with 557 additions and 315 deletions

View File

@ -1,3 +1,33 @@
2004-06-16 Michael Natterer <mitch@gimp.org>
* libgimpwidgets/gimpcontroller.[ch]: added #define
GIMP_CONTROLLER_PARAM_SERIALIZE. Made all properties serializable.
* modules/controller_linux_input.c: made "device-name"
serializable.
* app/config/gimpconfig-params.h: added macro
GIMP_CONFIG_INSTALL_PROP_POINTER() which needs to be handled
by custom (de)serialize_property() implementations.
* app/config/gimpconfig-deserialize.c
* app/config/gimpconfig-serialize.c: made object (de)serialization
work for object properties which are *not* GIMP_PARAM_AGGREGATE.
Write/parse the exact type of the object to create to enable this.
* app/core/gimpmarshal.list: new marshaller for GimpControllerInfo.
* app/widgets/gimpcontrollerinfo.[ch]: implement GimpConfigInterface
and add "controller" and "mapping" properties. Add "event-mapped"
signal which carries the action_name.
* app/widgets/gimpcontrollers.c: removed all deserialization code
and simply (de)serialize the controller container. Install a
container handler for "event-mapped" and do the action_name ->
action mapping in the callback.
* etc/controllerrc: regenerated with new syntax. Delete your old one!
2004-06-16 Sven Neumann <sven@gimp.org>
* app/widgets/gimpcontrollerwheel.c

View File

@ -666,7 +666,33 @@ gimp_config_deserialize_object (GValue *value,
prop_object = g_value_get_object (value);
if (! prop_object)
{
/* if the object property is not GIMP_PARAM_AGGREGATE, read
* the type of the object and create it
*/
if (! (prop_spec->flags & GIMP_PARAM_AGGREGATE))
{
gchar *type_name;
GType type;
if (! gimp_scanner_parse_string (scanner, &type_name))
return G_TOKEN_STRING;
type = g_type_from_name (type_name);
g_free (type_name);
if (! g_type_is_a (type, prop_spec->value_type))
return G_TOKEN_STRING;
prop_object = g_object_new (type, NULL);
g_value_take_object (value, prop_object);
}
else
{
return G_TOKEN_RIGHT_PAREN;
}
}
config_iface = GIMP_CONFIG_GET_INTERFACE (prop_object);

View File

@ -223,7 +223,7 @@ GParamSpec * gimp_param_spec_unit (const gchar *name,
flags | GIMP_CONFIG_PARAM_FLAGS))
/* object properties are _not_ G_PARAM_CONSTRUCT */
/* object and pointer properties are _not_ G_PARAM_CONSTRUCT */
#define GIMP_CONFIG_INSTALL_PROP_OBJECT(class, id,\
name, blurb, object_type, flags)\
@ -233,5 +233,12 @@ GParamSpec * gimp_param_spec_unit (const gchar *name,
flags |\
G_PARAM_READWRITE | GIMP_PARAM_SERIALIZE))
#define GIMP_CONFIG_INSTALL_PROP_POINTER(class, id,\
name, blurb, flags)\
g_object_class_install_property (class, id,\
g_param_spec_pointer (name, NULL, blurb,\
flags |\
G_PARAM_READWRITE | GIMP_PARAM_SERIALIZE))
#endif /* __GIMP_CONFIG_PARAMS_H__ */

View File

@ -257,8 +257,7 @@ gimp_config_serialize_property (GimpConfig *config,
if (! success)
{
if (G_VALUE_HOLDS_OBJECT (&value) &&
(param_spec->flags & GIMP_PARAM_AGGREGATE))
if (G_VALUE_HOLDS_OBJECT (&value))
{
GimpConfigInterface *config_iface = NULL;
GimpConfig *prop_object;
@ -274,6 +273,17 @@ gimp_config_serialize_property (GimpConfig *config,
{
gimp_config_writer_open (writer, param_spec->name);
/* if the object property is not GIMP_PARAM_AGGREGATE,
* deserializing will need to know the exact type
* in order to create the object
*/
if (! (param_spec->flags & GIMP_PARAM_AGGREGATE))
{
GType object_type = G_TYPE_FROM_INSTANCE (prop_object);
gimp_config_writer_string (writer, g_type_name (object_type));
}
success = config_iface->serialize (prop_object, writer, NULL);
if (success)

View File

@ -25,6 +25,7 @@
BOOLEAN: BOOLEAN
BOOLEAN: ENUM, INT
BOOLEAN: OBJECT, POINTER
BOOLEAN: OBJECT, POINTER, STRING
VOID: BOXED
VOID: DOUBLE

View File

@ -22,20 +22,46 @@
#include "config.h"
#include <string.h>
#include <gtk/gtk.h>
#include "libgimpwidgets/gimpwidgets.h"
#include "libgimpwidgets/gimpcontroller.h"
#include "widgets-types.h"
#include "config/gimpconfig.h"
#include "config/gimpconfig-params.h"
#include "config/gimpconfigwriter.h"
#include "config/gimpscanner.h"
#include "core/gimpmarshal.h"
#include "gimpcontrollerinfo.h"
#include "gimp-intl.h"
enum
{
PROP_0,
PROP_CONTROLLER,
PROP_MAPPING
};
enum
{
EVENT_MAPPED,
LAST_SIGNAL
};
static void gimp_controller_info_class_init (GimpControllerInfoClass *klass);
static void gimp_controller_info_init (GimpControllerInfo *info);
static void gimp_controller_info_config_iface_init (GimpConfigInterface *config_iface);
static void gimp_controller_info_finalize (GObject *object);
static void gimp_controller_info_set_property (GObject *object,
guint property_id,
@ -46,9 +72,27 @@ static void gimp_controller_info_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
static gboolean gimp_controller_info_serialize_property (GimpConfig *config,
guint property_id,
const GValue *value,
GParamSpec *pspec,
GimpConfigWriter *writer);
static gboolean gimp_controller_info_deserialize_property (GimpConfig *config,
guint property_id,
GValue *value,
GParamSpec *pspec,
GScanner *scanner,
GTokenType *expected);
static gboolean gimp_controller_info_event (GimpController *controller,
const GimpControllerEvent *event,
GimpControllerInfo *info);
static GimpObjectClass *parent_class = NULL;
static guint info_signals[LAST_SIGNAL] = { 0 };
GType
gimp_controller_info_get_type (void)
@ -69,15 +113,40 @@ gimp_controller_info_get_type (void)
0, /* n_preallocs */
(GInstanceInitFunc) gimp_controller_info_init,
};
static const GInterfaceInfo config_iface_info =
{
(GInterfaceInitFunc) gimp_controller_info_config_iface_init,
NULL, /* iface_finalize */
NULL /* iface_data */
};
controller_type = g_type_register_static (GIMP_TYPE_OBJECT,
"GimpControllerInfo",
&controller_info, 0);
g_type_add_interface_static (controller_type, GIMP_TYPE_CONFIG,
&config_iface_info);
}
return controller_type;
}
gboolean
gimp_controller_info_boolean_handled_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer dummy)
{
gboolean continue_emission;
gboolean signal_handled;
signal_handled = g_value_get_boolean (handler_return);
g_value_set_boolean (return_accu, signal_handled);
continue_emission = ! signal_handled;
return continue_emission;
}
static void
gimp_controller_info_class_init (GimpControllerInfoClass *klass)
{
@ -88,16 +157,40 @@ gimp_controller_info_class_init (GimpControllerInfoClass *klass)
object_class->finalize = gimp_controller_info_finalize;
object_class->set_property = gimp_controller_info_set_property;
object_class->get_property = gimp_controller_info_get_property;
GIMP_CONFIG_INSTALL_PROP_OBJECT (object_class, PROP_CONTROLLER,
"controller", NULL,
GIMP_TYPE_CONTROLLER,
0);
GIMP_CONFIG_INSTALL_PROP_POINTER (object_class, PROP_MAPPING,
"mapping", NULL,
0);
info_signals[EVENT_MAPPED] =
g_signal_new ("event-mapped",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GimpControllerInfoClass, event_mapped),
gimp_controller_info_boolean_handled_accumulator, NULL,
gimp_marshal_BOOLEAN__OBJECT_POINTER_STRING,
G_TYPE_BOOLEAN, 3,
G_TYPE_OBJECT,
G_TYPE_POINTER,
G_TYPE_STRING);
}
static void
gimp_controller_info_init (GimpControllerInfo *info)
{
info->controller = NULL;
info->mapping = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_object_unref);
info->mapping = NULL;
}
static void
gimp_controller_info_config_iface_init (GimpConfigInterface *config_iface)
{
config_iface->serialize_property = gimp_controller_info_serialize_property;
config_iface->deserialize_property = gimp_controller_info_deserialize_property;
}
static void
@ -124,6 +217,31 @@ gimp_controller_info_set_property (GObject *object,
switch (property_id)
{
case PROP_CONTROLLER:
if (info->controller)
{
g_signal_handlers_disconnect_by_func (info->controller,
gimp_controller_info_event,
info);
g_object_unref (info->controller);
}
info->controller = (GimpController *) g_value_dup_object (value);
if (info->controller)
{
g_signal_connect_object (info->controller, "event",
G_CALLBACK (gimp_controller_info_event),
G_OBJECT (info),
0);
}
break;
case PROP_MAPPING:
if (info->mapping)
g_hash_table_destroy (info->mapping);
info->mapping = g_value_get_pointer (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -140,8 +258,185 @@ gimp_controller_info_get_property (GObject *object,
switch (property_id)
{
case PROP_CONTROLLER:
g_value_set_object (value, info->controller);
break;
case PROP_MAPPING:
g_value_set_pointer (value, info->mapping);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_controller_info_serialize_mapping (gpointer key,
gpointer value,
gpointer data)
{
const gchar *event_name = key;
const gchar *action_name = value;
GimpConfigWriter *writer = data;
gimp_config_writer_open (writer, "map");
gimp_config_writer_string (writer, event_name);
gimp_config_writer_string (writer, action_name);
gimp_config_writer_close (writer);
}
static gboolean
gimp_controller_info_serialize_property (GimpConfig *config,
guint property_id,
const GValue *value,
GParamSpec *pspec,
GimpConfigWriter *writer)
{
GHashTable *mapping;
if (property_id != PROP_MAPPING)
return FALSE;
mapping = g_value_get_pointer (value);
gimp_config_writer_open (writer, pspec->name);
g_hash_table_foreach (mapping,
(GHFunc) gimp_controller_info_serialize_mapping,
writer);
gimp_config_writer_close (writer);
return TRUE;
}
static gboolean
gimp_controller_info_deserialize_property (GimpConfig *config,
guint property_id,
GValue *value,
GParamSpec *pspec,
GScanner *scanner,
GTokenType *expected)
{
GHashTable *mapping = NULL;
GTokenType token;
if (property_id != PROP_MAPPING)
return FALSE;
mapping = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_free);
token = G_TOKEN_LEFT_PAREN;
while (g_scanner_peek_next_token (scanner) == token)
{
token = g_scanner_get_next_token (scanner);
switch (token)
{
case G_TOKEN_LEFT_PAREN:
token = G_TOKEN_IDENTIFIER;
break;
case G_TOKEN_IDENTIFIER:
if (! strcmp (scanner->value.v_identifier, "map"))
{
gchar *event_name;
gchar *action_name;
token = G_TOKEN_STRING;
if (! gimp_scanner_parse_string (scanner, &event_name))
goto error;
token = G_TOKEN_STRING;
if (! gimp_scanner_parse_string (scanner, &action_name))
goto error;
g_hash_table_insert (mapping, event_name, action_name);
}
token = G_TOKEN_RIGHT_PAREN;
break;
case G_TOKEN_RIGHT_PAREN:
token = G_TOKEN_LEFT_PAREN;
break;
default:
break;
}
}
if (token == G_TOKEN_LEFT_PAREN)
{
token = G_TOKEN_RIGHT_PAREN;
if (g_scanner_peek_next_token (scanner) == token)
{
g_value_set_pointer (value, mapping);
}
else
{
goto error;
}
}
else
{
error:
if (mapping)
g_hash_table_destroy (mapping);
*expected = token;
}
return TRUE;
}
static gboolean
gimp_controller_info_event (GimpController *controller,
const GimpControllerEvent *event,
GimpControllerInfo *info)
{
const gchar *class_name;
const gchar *event_name;
const gchar *event_blurb;
const gchar *action_name;
class_name = GIMP_CONTROLLER_GET_CLASS (controller)->name;
event_name = gimp_controller_get_event_name (controller, event->any.event_id);
event_blurb = gimp_controller_get_event_blurb (controller, event->any.event_id);
g_print ("Received '%s' (class '%s')\n"
" controller event '%s (%s)'\n",
controller->name, class_name,
event_name, event_blurb);
action_name = g_hash_table_lookup (info->mapping, event_name);
if (action_name)
{
gboolean retval = FALSE;
g_print (" maps to action '%s'\n", action_name);
g_signal_emit (info, info_signals[EVENT_MAPPED], 0,
controller, event, action_name, &retval);
if (retval)
g_print (" action was found\n\n");
else
g_print (" action NOT found\n\n");
return retval;
}
else
{
g_print (" doesn't map to action\n\n");
}
return FALSE;
}

View File

@ -48,6 +48,11 @@ struct _GimpControllerInfo
struct _GimpControllerInfoClass
{
GimpObjectClass parent_class;
gboolean (* event_mapped) (GimpControllerInfo *info,
GimpController *controller,
const GimpControllerEvent *event,
const gchar *action_name);
};

View File

@ -22,16 +22,19 @@
#include "libgimpbase/gimpbase.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "libgimpwidgets/gimpcontroller.h"
#include "widgets-types.h"
#include "config/gimpconfig.h"
#include "config/gimpconfig-error.h"
#include "config/gimpconfig-params.h"
#include "config/gimpconfig-utils.h"
#include "config/gimpconfigwriter.h"
#include "config/gimpscanner.h"
#include "core/gimp.h"
#include "core/gimplist.h"
#include "gimpcontrollerinfo.h"
#include "gimpcontrollers.h"
@ -48,7 +51,8 @@ typedef struct _GimpControllerManager GimpControllerManager;
struct _GimpControllerManager
{
GList *controllers;
GimpContainer *controllers;
GQuark event_mapped_id;
GimpController *wheel;
GimpUIManager *ui_manager;
};
@ -59,12 +63,11 @@ struct _GimpControllerManager
static GimpControllerManager * gimp_controller_manager_get (Gimp *gimp);
static void gimp_controller_manager_free (GimpControllerManager *manager);
static gboolean gimp_controller_info_event (GimpController *controller,
static gboolean gimp_controllers_event_mapped (GimpControllerInfo *info,
GimpController *controller,
const GimpControllerEvent *event,
GimpControllerInfo *info);
static GTokenType gimp_controller_deserialize (GimpControllerManager *manager,
GScanner *scanner);
const gchar *action_name,
GimpControllerManager *manager);
/* public functions */
@ -83,6 +86,13 @@ gimp_controllers_init (Gimp *gimp)
GIMP_CONTROLLER_MANAGER_DATA_KEY, manager,
(GDestroyNotify) gimp_controller_manager_free);
manager->controllers = gimp_list_new (GIMP_TYPE_CONTROLLER_INFO, TRUE);
manager->event_mapped_id =
gimp_container_add_handler (manager->controllers, "event-mapped",
G_CALLBACK (gimp_controllers_event_mapped),
manager);
/* EEEEEEK */
{
static const GInterfaceInfo config_iface_info =
@ -110,21 +120,12 @@ gimp_controllers_exit (Gimp *gimp)
g_type_class_unref (g_type_class_peek (GIMP_TYPE_CONTROLLER_WHEEL));
}
enum
{
CONTROLLER,
CONTROLLER_OPTIONS,
CONTROLLER_MAPPING
};
void
gimp_controllers_restore (Gimp *gimp,
GimpUIManager *ui_manager)
{
GimpControllerManager *manager;
gchar *filename;
GScanner *scanner;
GTokenType token;
GError *error = NULL;
g_return_if_fail (GIMP_IS_GIMP (gimp));
@ -139,81 +140,46 @@ gimp_controllers_restore (Gimp *gimp,
filename = gimp_personal_rc_file ("controllerrc");
scanner = gimp_scanner_new_file (filename, &error);
if (! scanner)
if (! gimp_config_deserialize_file (GIMP_CONFIG (manager->controllers),
filename, NULL, &error))
{
if (error->code == GIMP_CONFIG_ERROR_OPEN_ENOENT)
{
g_clear_error (&error);
g_free (filename);
return;
}
g_scanner_scope_add_symbol (scanner, 0, "controller",
GINT_TO_POINTER (CONTROLLER));
g_scanner_scope_add_symbol (scanner, CONTROLLER, "options",
GINT_TO_POINTER (CONTROLLER_OPTIONS));
g_scanner_scope_add_symbol (scanner, CONTROLLER, "mapping",
GINT_TO_POINTER (CONTROLLER_MAPPING));
filename = g_build_filename (gimp_sysconf_directory (),
"controllerrc", NULL);
token = G_TOKEN_LEFT_PAREN;
while (g_scanner_peek_next_token (scanner) == token)
{
token = g_scanner_get_next_token (scanner);
switch (token)
{
case G_TOKEN_LEFT_PAREN:
token = G_TOKEN_SYMBOL;
break;
case G_TOKEN_SYMBOL:
if (scanner->value.v_symbol == GINT_TO_POINTER (CONTROLLER))
{
g_scanner_set_scope (scanner, CONTROLLER);
token = gimp_controller_deserialize (manager, scanner);
if (token == G_TOKEN_RIGHT_PAREN)
g_scanner_set_scope (scanner, 0);
else
break;
}
token = G_TOKEN_RIGHT_PAREN;
break;
case G_TOKEN_RIGHT_PAREN:
token = G_TOKEN_LEFT_PAREN;
break;
default: /* do nothing */
break;
}
}
if (token != G_TOKEN_LEFT_PAREN)
{
g_scanner_get_next_token (scanner);
g_scanner_unexp_token (scanner, token, NULL, NULL, NULL,
_("fatal parse error"), TRUE);
}
if (error)
if (! gimp_config_deserialize_file (GIMP_CONFIG (manager->controllers),
filename, NULL, &error))
{
g_message (error->message);
}
}
else
{
g_message (error->message);
g_clear_error (&error);
gimp_config_file_backup_on_error (filename, "controllerrc", NULL);
}
gimp_scanner_destroy (scanner);
g_free (filename);
g_clear_error (&error);
}
manager->controllers = g_list_reverse (manager->controllers);
gimp_list_reverse (GIMP_LIST (manager->controllers));
g_free (filename);
}
void
gimp_controllers_save (Gimp *gimp)
{
const gchar *header =
"GIMP controllerrc\n"
"\n"
"This file will be entirely rewritten every time you quit the gimp.";
const gchar *footer =
"end of controllerrc";
GimpControllerManager *manager;
gchar *filename;
GError *error = NULL;
@ -225,6 +191,16 @@ gimp_controllers_save (Gimp *gimp)
g_return_if_fail (manager != NULL);
filename = gimp_personal_rc_file ("controllerrc");
if (! gimp_config_serialize_to_file (GIMP_CONFIG (manager->controllers),
filename,
header, footer, NULL,
&error))
{
g_message (error->message);
g_error_free (error);
}
g_free (filename);
}
@ -253,203 +229,38 @@ gimp_controller_manager_get (Gimp *gimp)
static void
gimp_controller_manager_free (GimpControllerManager *manager)
{
g_list_foreach (manager->controllers, (GFunc) g_object_unref, NULL);
g_list_free (manager->controllers);
gimp_container_remove_handler (manager->controllers,
manager->event_mapped_id);
g_object_unref (manager->controllers);
g_object_unref (manager->ui_manager);
g_free (manager);
}
static GTokenType
gimp_controller_deserialize (GimpControllerManager *manager,
GScanner *scanner)
static gboolean
gimp_controllers_event_mapped (GimpControllerInfo *info,
GimpController *controller,
const GimpControllerEvent *event,
const gchar *action_name,
GimpControllerManager *manager)
{
GimpControllerInfo *info = NULL;
GTokenType token;
gchar *controller_name;
GType controller_type;
token = G_TOKEN_STRING;
if (! gimp_scanner_parse_string (scanner, &controller_name))
goto error;
controller_type = g_type_from_name (controller_name);
g_free (controller_name);
if (! g_type_is_a (controller_type, GIMP_TYPE_CONTROLLER))
goto error;
info = g_object_new (GIMP_TYPE_CONTROLLER_INFO, NULL);
info->controller = gimp_controller_new (controller_type);
/* EEEEEK */
{
GParamSpec **props;
gint n_props;
gint i;
props = g_object_class_list_properties (g_type_class_peek (controller_type),
&n_props);
for (i = 0; i < n_props; i++)
props[i]->flags |= GIMP_PARAM_SERIALIZE;
g_free (props);
}
token = G_TOKEN_LEFT_PAREN;
while (g_scanner_peek_next_token (scanner) == token)
{
token = g_scanner_get_next_token (scanner);
switch (token)
{
case G_TOKEN_LEFT_PAREN:
token = G_TOKEN_SYMBOL;
break;
case G_TOKEN_SYMBOL:
switch (GPOINTER_TO_INT (scanner->value.v_symbol))
{
case CONTROLLER_OPTIONS:
{
GimpConfigInterface *config_iface;
config_iface = GIMP_CONFIG_GET_INTERFACE (info->controller);
if (! config_iface->deserialize (GIMP_CONFIG (info->controller),
scanner,
1,
FALSE))
{
goto error;
}
}
break;
case CONTROLLER_MAPPING:
{
GtkAction *action = NULL;
GList *list;
gchar *event_name;
gchar *action_name;
token = G_TOKEN_INT;
if (! gimp_scanner_parse_string (scanner, &event_name))
goto error;
token = G_TOKEN_STRING;
if (! gimp_scanner_parse_string (scanner, &action_name))
goto error;
for (list = gtk_ui_manager_get_action_groups (GTK_UI_MANAGER (manager->ui_manager));
list;
list = g_list_next (list))
{
GtkActionGroup *group = list->data;
GtkAction *action;
action = gtk_action_group_get_action (group, action_name);
if (action)
break;
}
if (action)
{
g_hash_table_insert (info->mapping, event_name,
g_object_ref (action));
}
else
{
g_free (event_name);
g_printerr ("%s: action '%s' not found\n",
G_STRFUNC, action_name);
}
g_free (action_name);
}
break;
default:
break;
}
token = G_TOKEN_RIGHT_PAREN;
break;
case G_TOKEN_RIGHT_PAREN:
token = G_TOKEN_LEFT_PAREN;
break;
default:
break;
}
}
if (token == G_TOKEN_LEFT_PAREN)
{
token = G_TOKEN_RIGHT_PAREN;
if (g_scanner_peek_next_token (scanner) == token)
{
g_signal_connect (info->controller, "event",
G_CALLBACK (gimp_controller_info_event),
info);
if (GIMP_IS_CONTROLLER_WHEEL (info->controller))
manager->wheel = info->controller;
manager->controllers = g_list_prepend (manager->controllers, info);
}
else
{
goto error;
}
}
else
{
error:
if (info)
g_object_unref (info);
}
return token;
}
static gboolean
gimp_controller_info_event (GimpController *controller,
const GimpControllerEvent *event,
GimpControllerInfo *info)
{
GtkAction *action;
const gchar *class_name;
const gchar *event_name;
const gchar *event_blurb;
class_name = GIMP_CONTROLLER_GET_CLASS (controller)->name;
event_name = gimp_controller_get_event_name (controller, event->any.event_id);
event_blurb = gimp_controller_get_event_blurb (controller, event->any.event_id);
g_print ("Received '%s' (class '%s')\n"
" controller event '%s (%s)'\n",
controller->name, class_name,
event_name, event_blurb);
action = g_hash_table_lookup (info->mapping, event_name);
if (action)
{
g_print (" handled by action '%s'\n\n", gtk_action_get_name (action));
gtk_action_activate (action);
return TRUE;
}
else
{
g_print (" not handled\n\n");
}
return FALSE;

View File

@ -1,30 +1,37 @@
# GIMP controllerrc
#
# This file will be entirely rewritten every time you quit the gimp.
(GimpControllerInfo "Main Mouse Wheel"
(controller "GimpControllerWheel"
(options
(name "Main Mouse Wheel"))
(mapping "scroll-up-shift-control-alt" "context-font-next")
(mapping "scroll-up-control-alt" "context-gradient-next")
(mapping "scroll-up-shift-alt" "context-pattern-next")
(mapping "scroll-up-shift-control" "context-brush-next")
(mapping "scroll-up-alt" "context-opacity-increase-skip")
(mapping "scroll-down-shift-control-alt" "context-font-previous")
(mapping "scroll-down-control-alt" "context-gradient-previous")
(mapping "scroll-down-shift-alt" "context-pattern-previous")
(mapping "scroll-down-shift-control" "context-brush-previous")
(mapping "scroll-down-alt" "context-opacity-decrease-skip"))
(name "Main Mouse Wheel")
(enabled yes))
(mapping
(map "scroll-down-alt" "context-opacity-decrease-skip")
(map "scroll-down-control-alt" "context-gradient-previous")
(map "scroll-down-shift-alt" "context-pattern-previous")
(map "scroll-down-shift-control" "context-brush-previous")
(map "scroll-down-shift-control-alt" "context-font-previous")
(map "scroll-up-alt" "context-opacity-increase-skip")
(map "scroll-up-control-alt" "context-gradient-next")
(map "scroll-up-shift-alt" "context-pattern-next")
(map "scroll-up-shift-control" "context-brush-next")
(map "scroll-up-shift-control-alt" "context-font-next")))
(GimpControllerInfo "ShuttlePRO"
(controller "ControllerLinuxInput"
(options
(name "ShuttlePRO")
(enabled yes)
(device "/dev/input/event2"))
(mapping "button-0" "tools-rect-select")
(mapping "button-1" "tools-ellipse-select")
(mapping "button-2" "tools-bucket-fill")
(mapping "button-3" "tools-blend")
(mapping "button-4" "tools-pencil")
(mapping "button-5" "tools-paintbrush")
(mapping "button-6" "tools-eraser")
(mapping "button-7" "tools-airbrush")
(mapping "wheel-turn-left" "context-brush-radius-decrease")
(mapping "wheel-turn-right" "context-brush-radius-increase"))
(mapping
(map "button-0" "tools-rect-select")
(map "button-1" "tools-ellipse-select")
(map "button-2" "tools-bucket-fill")
(map "button-3" "tools-blend")
(map "button-4" "tools-pencil")
(map "button-5" "tools-paintbrush")
(map "button-6" "tools-eraser")
(map "button-7" "tools-airbrush")
(map "wheel-turn-left" "context-brush-radius-decrease")
(map "wheel-turn-right" "context-brush-radius-increase")))
# end of controllerrc

View File

@ -666,7 +666,33 @@ gimp_config_deserialize_object (GValue *value,
prop_object = g_value_get_object (value);
if (! prop_object)
{
/* if the object property is not GIMP_PARAM_AGGREGATE, read
* the type of the object and create it
*/
if (! (prop_spec->flags & GIMP_PARAM_AGGREGATE))
{
gchar *type_name;
GType type;
if (! gimp_scanner_parse_string (scanner, &type_name))
return G_TOKEN_STRING;
type = g_type_from_name (type_name);
g_free (type_name);
if (! g_type_is_a (type, prop_spec->value_type))
return G_TOKEN_STRING;
prop_object = g_object_new (type, NULL);
g_value_take_object (value, prop_object);
}
else
{
return G_TOKEN_RIGHT_PAREN;
}
}
config_iface = GIMP_CONFIG_GET_INTERFACE (prop_object);

View File

@ -223,7 +223,7 @@ GParamSpec * gimp_param_spec_unit (const gchar *name,
flags | GIMP_CONFIG_PARAM_FLAGS))
/* object properties are _not_ G_PARAM_CONSTRUCT */
/* object and pointer properties are _not_ G_PARAM_CONSTRUCT */
#define GIMP_CONFIG_INSTALL_PROP_OBJECT(class, id,\
name, blurb, object_type, flags)\
@ -233,5 +233,12 @@ GParamSpec * gimp_param_spec_unit (const gchar *name,
flags |\
G_PARAM_READWRITE | GIMP_PARAM_SERIALIZE))
#define GIMP_CONFIG_INSTALL_PROP_POINTER(class, id,\
name, blurb, flags)\
g_object_class_install_property (class, id,\
g_param_spec_pointer (name, NULL, blurb,\
flags |\
G_PARAM_READWRITE | GIMP_PARAM_SERIALIZE))
#endif /* __GIMP_CONFIG_PARAMS_H__ */

View File

@ -257,8 +257,7 @@ gimp_config_serialize_property (GimpConfig *config,
if (! success)
{
if (G_VALUE_HOLDS_OBJECT (&value) &&
(param_spec->flags & GIMP_PARAM_AGGREGATE))
if (G_VALUE_HOLDS_OBJECT (&value))
{
GimpConfigInterface *config_iface = NULL;
GimpConfig *prop_object;
@ -274,6 +273,17 @@ gimp_config_serialize_property (GimpConfig *config,
{
gimp_config_writer_open (writer, param_spec->name);
/* if the object property is not GIMP_PARAM_AGGREGATE,
* deserializing will need to know the exact type
* in order to create the object
*/
if (! (param_spec->flags & GIMP_PARAM_AGGREGATE))
{
GType object_type = G_TYPE_FROM_INSTANCE (prop_object);
gimp_config_writer_string (writer, g_type_name (object_type));
}
success = config_iface->serialize (prop_object, writer, NULL);
if (success)

View File

@ -120,12 +120,14 @@ gimp_controller_class_init (GimpControllerClass *klass)
g_param_spec_string ("name", NULL, NULL,
"Unnamed Controller",
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
G_PARAM_CONSTRUCT |
GIMP_CONTROLLER_PARAM_SERIALIZE));
g_object_class_install_property (object_class, PROP_ENABLED,
g_param_spec_boolean ("enabled", NULL, NULL,
TRUE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
G_PARAM_CONSTRUCT |
GIMP_CONTROLLER_PARAM_SERIALIZE));
controller_signals[EVENT] =
g_signal_new ("event",

View File

@ -27,6 +27,10 @@ G_BEGIN_DECLS
/* For information look at the html documentation */
#define GIMP_CONTROLLER_PARAM_SERIALIZE (1 << (0 + G_PARAM_USER_SHIFT))
typedef enum
{
GIMP_CONTROLLER_EVENT_TRIGGER,

View File

@ -211,7 +211,8 @@ linux_input_class_init (ControllerLinuxInputClass *klass)
g_param_spec_string ("device", NULL, NULL,
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
G_PARAM_CONSTRUCT |
GIMP_CONTROLLER_PARAM_SERIALIZE));
controller_class->name = _("Linux Input Events");