Commit 3a7f7d54 authored by Michael Natterer's avatar Michael Natterer 😴 Committed by Michael Natterer

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!
parent 429b090f
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
......
......@@ -666,7 +666,33 @@ gimp_config_deserialize_object (GValue *value,
prop_object = g_value_get_object (value);
if (! prop_object)
return G_TOKEN_RIGHT_PAREN;
{
/* 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);
......
......@@ -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__ */
......@@ -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)
......
......@@ -25,6 +25,7 @@
BOOLEAN: BOOLEAN
BOOLEAN: ENUM, INT
BOOLEAN: OBJECT, POINTER
BOOLEAN: OBJECT, POINTER, STRING
VOID: BOXED
VOID: DOUBLE
......
......@@ -22,33 +22,77 @@
#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"
static void gimp_controller_info_class_init (GimpControllerInfoClass *klass);
static void gimp_controller_info_init (GimpControllerInfo *info);
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,
const GValue *value,
GParamSpec *pspec);
static void gimp_controller_info_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_controller_info_finalize (GObject *object);
static void gimp_controller_info_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_controller_info_get_property (GObject *object,
guint property_id,
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;
}
......@@ -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);
};
......
......@@ -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,
const GimpControllerEvent *event,
GimpControllerInfo *info);
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);
/* 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))
{
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));
token = G_TOKEN_LEFT_PAREN;
while (g_scanner_peek_next_token (scanner) == token)
{
token = g_scanner_get_next_token (scanner);
switch (token)
if (error->code == GIMP_CONFIG_ERROR_OPEN_ENOENT)
{
case G_TOKEN_LEFT_PAREN:
token = G_TOKEN_SYMBOL;
break;
g_clear_error (&error);
g_free (filename);
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);
filename = g_build_filename (gimp_sysconf_directory (),
"controllerrc", NULL);
if (token == G_TOKEN_RIGHT_PAREN)
g_scanner_set_scope (scanner, 0);
else
break;
if (! gimp_config_deserialize_file (GIMP_CONFIG (manager->controllers),
filename, NULL, &error))
{
g_message (error->message);
}
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);
}
else
{
g_message (error->message);
}
if (error)
{
g_message (error->message);
g_clear_error (&error);
gimp_config_file_backup_on_error (filename, "controllerrc", NULL);
}
gimp_scanner_destroy (scanner);
g_free (filename);
gimp_list_reverse (GIMP_LIST (manager->controllers));
manager->controllers = g_list_reverse (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,204 +229,39 @@ 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</