387 lines
10 KiB
C
387 lines
10 KiB
C
/*
|
|
* mooactionfactory.c
|
|
*
|
|
* Copyright (C) 2004-2007 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* See COPYING file that comes with this distribution.
|
|
*/
|
|
|
|
#include "mooutils/mooactionfactory.h"
|
|
#include "mooutils/mooutils-gobject.h"
|
|
#include "mooutils/mooaction.h"
|
|
#include "mooutils/mooactionbase.h"
|
|
#include <gobject/gvaluecollector.h>
|
|
#include <string.h>
|
|
|
|
|
|
static MooActionFactory *moo_action_factory_new_valist (GType action_type,
|
|
const char *first_prop_name,
|
|
va_list var_args);
|
|
|
|
|
|
G_DEFINE_TYPE(MooActionFactory, moo_action_factory, G_TYPE_OBJECT)
|
|
|
|
|
|
static void
|
|
moo_action_factory_dispose (GObject *object)
|
|
{
|
|
MooActionFactory *factory = MOO_ACTION_FACTORY (object);
|
|
|
|
if (factory->props)
|
|
{
|
|
_moo_param_array_free (factory->props, factory->n_props);
|
|
factory->props = NULL;
|
|
factory->n_props = 0;
|
|
}
|
|
|
|
G_OBJECT_CLASS(moo_action_factory_parent_class)->dispose (object);
|
|
}
|
|
|
|
|
|
static void
|
|
moo_action_factory_class_init (MooActionFactoryClass *klass)
|
|
{
|
|
G_OBJECT_CLASS(klass)->dispose = moo_action_factory_dispose;
|
|
}
|
|
|
|
|
|
static void
|
|
moo_action_factory_init (MooActionFactory *factory)
|
|
{
|
|
factory->action_type = MOO_TYPE_ACTION;
|
|
}
|
|
|
|
|
|
static GtkAction *
|
|
moo_action_new_valist (GType action_type,
|
|
const char *name,
|
|
const char *first_prop_name,
|
|
va_list var_args)
|
|
{
|
|
MooActionFactory *factory;
|
|
GtkAction *action;
|
|
|
|
g_return_val_if_fail (g_type_is_a (action_type, MOO_TYPE_ACTION_BASE), NULL);
|
|
|
|
factory = moo_action_factory_new_valist (action_type, first_prop_name, var_args);
|
|
action = moo_action_factory_create_action (factory, NULL, "name", name, NULL);
|
|
|
|
g_object_unref (factory);
|
|
return action;
|
|
}
|
|
|
|
|
|
GtkAction *
|
|
moo_action_group_add_action (GtkActionGroup *group,
|
|
const char *name,
|
|
const char *first_prop_name,
|
|
...)
|
|
{
|
|
GtkAction *action;
|
|
GType action_type = MOO_TYPE_ACTION;
|
|
va_list var_args;
|
|
|
|
g_return_val_if_fail (GTK_IS_ACTION_GROUP (group), NULL);
|
|
|
|
va_start (var_args, first_prop_name);
|
|
|
|
if (first_prop_name &&
|
|
(!strcmp (first_prop_name, "action-type::") || !strcmp (first_prop_name, "action_type::")))
|
|
{
|
|
action_type = va_arg (var_args, GType);
|
|
g_return_val_if_fail (g_type_is_a (action_type, MOO_TYPE_ACTION_BASE), NULL);
|
|
first_prop_name = va_arg (var_args, char*);
|
|
}
|
|
|
|
action = moo_action_new_valist (action_type, name, first_prop_name, var_args);
|
|
|
|
va_end (var_args);
|
|
|
|
g_return_val_if_fail (action != NULL, NULL);
|
|
|
|
gtk_action_group_add_action (group, action);
|
|
g_object_unref (action);
|
|
|
|
return action;
|
|
}
|
|
|
|
|
|
static gboolean
|
|
collect_valist (GType type,
|
|
GParameter **props_p,
|
|
guint *n_props_p,
|
|
const char *first_prop_name,
|
|
va_list var_args)
|
|
{
|
|
GObjectClass *klass;
|
|
GArray *props;
|
|
const char *prop_name;
|
|
|
|
g_return_val_if_fail (first_prop_name != NULL, FALSE);
|
|
|
|
klass = g_type_class_ref (type);
|
|
g_return_val_if_fail (klass != NULL, FALSE);
|
|
|
|
props = g_array_new (FALSE, TRUE, sizeof (GParameter));
|
|
prop_name = first_prop_name;
|
|
|
|
while (prop_name)
|
|
{
|
|
char *error = NULL;
|
|
GParameter param;
|
|
GParamSpec *pspec;
|
|
|
|
pspec = g_object_class_find_property (klass, prop_name);
|
|
|
|
if (!pspec)
|
|
{
|
|
g_warning ("%s: could not find property '%s' for class '%s'",
|
|
G_STRLOC, prop_name, g_type_name (type));
|
|
|
|
_moo_param_array_free ((GParameter*) props->data, props->len);
|
|
g_array_free (props, FALSE);
|
|
|
|
g_type_class_unref (klass);
|
|
return FALSE;
|
|
}
|
|
|
|
param.name = g_strdup (prop_name);
|
|
param.value.g_type = 0;
|
|
g_value_init (¶m.value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
|
G_VALUE_COLLECT (¶m.value, var_args, 0, &error);
|
|
|
|
if (error)
|
|
{
|
|
g_critical ("%s: %s", G_STRLOC, error);
|
|
g_free (error);
|
|
g_value_unset (¶m.value);
|
|
g_free ((char*)param.name);
|
|
|
|
_moo_param_array_free ((GParameter*) props->data, props->len);
|
|
g_array_free (props, FALSE);
|
|
|
|
g_type_class_unref (klass);
|
|
return FALSE;
|
|
}
|
|
|
|
g_array_append_val (props, param);
|
|
|
|
prop_name = va_arg (var_args, char*);
|
|
}
|
|
|
|
g_type_class_unref (klass);
|
|
|
|
*n_props_p = props->len;
|
|
*props_p = (GParameter*) g_array_free (props, FALSE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static MooActionFactory *
|
|
moo_action_factory_new_valist (GType action_type,
|
|
const char *first_prop_name,
|
|
va_list var_args)
|
|
{
|
|
MooActionFactory *factory;
|
|
|
|
g_return_val_if_fail (g_type_is_a (action_type, MOO_TYPE_ACTION_BASE), NULL);
|
|
|
|
factory = g_object_new (MOO_TYPE_ACTION_FACTORY, NULL);
|
|
|
|
factory->action_type = action_type;
|
|
|
|
if (!collect_valist (action_type,
|
|
&factory->props, &factory->n_props,
|
|
first_prop_name, var_args))
|
|
{
|
|
g_object_unref (factory);
|
|
return NULL;
|
|
}
|
|
|
|
return factory;
|
|
}
|
|
|
|
|
|
static void
|
|
array_add_parameter (GArray *array,
|
|
GParameter *param)
|
|
{
|
|
GParameter p;
|
|
p.name = g_strdup (param->name);
|
|
p.value.g_type = 0;
|
|
g_value_init (&p.value, G_VALUE_TYPE (¶m->value));
|
|
g_value_copy (¶m->value, &p.value);
|
|
g_array_append_val (array, p);
|
|
}
|
|
|
|
|
|
static GParameter *
|
|
param_array_concatenate (GParameter *props1,
|
|
guint n_props1,
|
|
GParameter *props2,
|
|
guint n_props2,
|
|
guint *n_props)
|
|
{
|
|
GArray *array;
|
|
guint i;
|
|
|
|
array = g_array_new (FALSE, TRUE, sizeof (GParameter));
|
|
|
|
for (i = 0; i < n_props1; ++i)
|
|
array_add_parameter (array, &props1[i]);
|
|
for (i = 0; i < n_props2; ++i)
|
|
array_add_parameter (array, &props2[i]);
|
|
|
|
*n_props = array->len;
|
|
return (GParameter*) g_array_free (array, FALSE);
|
|
}
|
|
|
|
|
|
gpointer
|
|
moo_action_factory_create_action (MooActionFactory *factory,
|
|
gpointer data,
|
|
const char *prop_name,
|
|
...)
|
|
{
|
|
GObject *object;
|
|
GParameter *props, *add_props;
|
|
guint n_props, n_add_props;
|
|
va_list var_args;
|
|
gboolean success;
|
|
|
|
g_return_val_if_fail (MOO_IS_ACTION_FACTORY (factory), NULL);
|
|
|
|
if (factory->factory_func)
|
|
{
|
|
if (factory->factory_func_data)
|
|
data = factory->factory_func_data;
|
|
return factory->factory_func (data, factory);
|
|
}
|
|
|
|
if (!prop_name)
|
|
return g_object_newv (factory->action_type,
|
|
factory->n_props,
|
|
factory->props);
|
|
|
|
va_start (var_args, prop_name);
|
|
|
|
success = collect_valist (factory->action_type,
|
|
&add_props, &n_add_props,
|
|
prop_name, var_args);
|
|
|
|
va_end (var_args);
|
|
|
|
if (!success)
|
|
return NULL;
|
|
|
|
props = param_array_concatenate (factory->props,
|
|
factory->n_props,
|
|
add_props,
|
|
n_add_props,
|
|
&n_props);
|
|
|
|
object = g_object_newv (factory->action_type, n_props, props);
|
|
|
|
_moo_param_array_free (props, n_props);
|
|
_moo_param_array_free (add_props, n_add_props);
|
|
|
|
return object;
|
|
}
|
|
|
|
|
|
#if 0
|
|
MooActionFactory *
|
|
moo_action_factory_new (GType action_type,
|
|
const char *first_prop_name,
|
|
...)
|
|
{
|
|
MooActionFactory *factory;
|
|
va_list var_args;
|
|
|
|
g_return_val_if_fail (g_type_is_a (action_type, MOO_TYPE_ACTION_BASE), NULL);
|
|
|
|
va_start (var_args, first_prop_name);
|
|
factory = moo_action_factory_new_valist (action_type, first_prop_name, var_args);
|
|
va_end (var_args);
|
|
|
|
return factory;
|
|
}
|
|
#endif
|
|
|
|
|
|
MooActionFactory *
|
|
moo_action_factory_new_a (GType action_type,
|
|
GParameter *params,
|
|
guint n_params)
|
|
{
|
|
MooActionFactory *factory;
|
|
GObjectClass *klass;
|
|
GArray *props;
|
|
guint i;
|
|
|
|
g_return_val_if_fail (g_type_is_a (action_type, MOO_TYPE_ACTION_BASE), NULL);
|
|
|
|
klass = g_type_class_ref (action_type);
|
|
props = g_array_new (FALSE, TRUE, sizeof (GParameter));
|
|
|
|
for (i = 0; i < n_params; ++i)
|
|
{
|
|
GParameter param;
|
|
GParamSpec *pspec;
|
|
const char *prop_name = params[i].name;
|
|
|
|
pspec = g_object_class_find_property (klass, prop_name);
|
|
|
|
if (!pspec)
|
|
{
|
|
g_warning ("%s: could not find property '%s' for class '%s'",
|
|
G_STRLOC, prop_name, g_type_name (action_type));
|
|
|
|
_moo_param_array_free ((GParameter*) props->data, props->len);
|
|
g_array_free (props, FALSE);
|
|
|
|
g_type_class_unref (klass);
|
|
return NULL;
|
|
}
|
|
|
|
param.name = g_strdup (prop_name);
|
|
param.value.g_type = 0;
|
|
g_value_init (¶m.value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
|
g_value_copy (¶ms[i].value, ¶m.value);
|
|
|
|
g_array_append_val (props, param);
|
|
}
|
|
|
|
g_type_class_unref (klass);
|
|
|
|
factory = g_object_new (MOO_TYPE_ACTION_FACTORY, NULL);
|
|
factory->action_type = action_type;
|
|
|
|
factory->n_props = props->len;
|
|
factory->props = (GParameter*) g_array_free (props, FALSE);
|
|
|
|
return factory;
|
|
}
|
|
|
|
|
|
MooActionFactory*
|
|
moo_action_factory_new_func (MooActionFactoryFunc factory_func,
|
|
gpointer data)
|
|
{
|
|
MooActionFactory *factory;
|
|
|
|
g_return_val_if_fail (factory_func != NULL, NULL);
|
|
|
|
factory = g_object_new (MOO_TYPE_ACTION_FACTORY, NULL);
|
|
factory->factory_func = factory_func;
|
|
factory->factory_func_data = data;
|
|
|
|
return factory;
|
|
}
|