Commit 79169301 authored by Daiki Ueno's avatar Daiki Ueno
Browse files

Implement serialization to GVariant.

parent 11026923
......@@ -82,7 +82,6 @@ eek_container_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekContainerPrivate *priv = EEK_CONTAINER_GET_PRIVATE(self);
GVariant *array, *child;
GVariantIter iter;
......@@ -94,9 +93,9 @@ eek_container_real_deserialize (EekSerializable *self,
g_variant_iter_init (&iter, array);
while (g_variant_iter_next (&iter, "v", &child)) {
EekSerializable *serializable = eek_serializable_deserialize (child);
priv->children = g_slist_prepend (priv->children, serializable);
eek_container_add_child (EEK_CONTAINER(self),
EEK_ELEMENT(serializable));
}
priv->children = g_slist_reverse (priv->children);
return index;
}
......@@ -122,6 +121,7 @@ eek_container_real_add_child (EekContainer *self,
priv->children = g_slist_prepend (priv->children, child);
eek_element_set_parent (child, EEK_ELEMENT(self));
g_signal_emit_by_name (self, "child-added", child);
}
static void
......@@ -137,6 +137,7 @@ eek_container_real_remove_child (EekContainer *self,
g_object_unref (child);
priv->children = g_slist_remove_link (priv->children, head);
eek_element_set_parent (child, NULL);
g_signal_emit_by_name (self, "child-removed", child);
}
static void
......@@ -202,6 +203,10 @@ eek_container_class_init (EekContainerClass *klass)
klass->foreach_child = eek_container_real_foreach_child;
klass->find = eek_container_real_find;
/* signals */
klass->child_added = NULL;
klass->child_removed = NULL;
gobject_class->finalize = eek_container_finalize;
gobject_class->dispose = eek_container_dispose;
......@@ -290,3 +295,11 @@ eek_container_find (EekContainer *container,
func,
user_data);
}
void
eek_container_add_child (EekContainer *container, EekElement *element)
{
g_return_if_fail (EEK_IS_CONTAINER(container));
g_return_if_fail (EEK_IS_ELEMENT(element));
return EEK_CONTAINER_GET_CLASS(container)->add_child (container, element);
}
......@@ -81,14 +81,16 @@ struct _EekContainerClass
gpointer pdummy[24];
};
GType eek_container_get_type (void) G_GNUC_CONST;
GType eek_container_get_type (void) G_GNUC_CONST;
void eek_container_foreach_child (EekContainer *container,
EekCallback callback,
gpointer user_data);
EekElement *eek_container_find (EekContainer *container,
EekCompareFunc func,
gpointer user_data);
void eek_container_foreach_child (EekContainer *container,
EekCallback callback,
gpointer user_data);
EekElement *eek_container_find (EekContainer *container,
EekCompareFunc func,
gpointer user_data);
void eek_container_add_child (EekContainer *container,
EekElement *element);
G_END_DECLS
#endif /* EEK_CONTAINER_H */
......@@ -89,7 +89,7 @@ eek_element_real_serialize (EekSerializable *self,
{
EekElementPrivate *priv = EEK_ELEMENT_GET_PRIVATE(self);
g_variant_builder_add (builder, "s", priv->name);
g_variant_builder_add (builder, "s", priv->name == NULL ? "" : priv->name);
g_variant_builder_add (builder, "v", _g_variant_new_bounds (&priv->bounds));
}
......
......@@ -46,7 +46,7 @@ enum {
PROP_SYMBOL_MATRIX,
PROP_COLUMN,
PROP_ROW,
PROP_OUTLINE,
PROP_OREF,
PROP_LAST
};
......@@ -74,7 +74,7 @@ struct _EekKeyPrivate
EekSymbolMatrix *symbol_matrix;
gint column;
gint row;
EekOutline *outline;
gulong oref;
gboolean is_pressed;
};
......@@ -86,23 +86,45 @@ _g_variant_new_symbol_matrix (EekSymbolMatrix *symbol_matrix)
GVariantBuilder builder, array;
gint i, num_symbols = symbol_matrix->num_groups * symbol_matrix->num_levels;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("iiav"));
g_variant_builder_init (&builder, G_VARIANT_TYPE ("(iiv)"));
g_variant_builder_add (&builder, "i", symbol_matrix->num_groups);
g_variant_builder_add (&builder, "i", symbol_matrix->num_levels);
g_variant_builder_init (&array, G_VARIANT_TYPE ("av"));
for (i = 0; i < num_symbols; i++) {
GVariant *symbol = eek_serializable_serialize
(EEK_SERIALIZABLE(symbol_matrix->data[i]));
g_variant_builder_add (&builder, "v", symbol);
g_variant_builder_add (&array, "v", symbol);
}
g_variant_builder_add (&builder, "av", g_variant_builder_end (&array));
g_variant_builder_add (&builder, "v", g_variant_builder_end (&array));
return g_variant_builder_end (&builder);
}
static EekSymbolMatrix *
_g_variant_get_symbol_matrix (GVariant *variant)
{
g_return_val_if_reached (NULL); /* TODO */
gint num_groups, num_levels, i;
EekSymbolMatrix *symbol_matrix;
GVariant *array, *child;
GVariantIter iter;
g_variant_get_child (variant, 0, "i", &num_groups);
g_variant_get_child (variant, 1, "i", &num_levels);
symbol_matrix = eek_symbol_matrix_new (num_groups, num_levels);
g_variant_get_child (variant, 2, "v", &array);
g_variant_iter_init (&iter, array);
for (i = 0; i < num_groups * num_levels; i++) {
EekSerializable *serializable;
if (!g_variant_iter_next (&iter, "v", &child)) {
eek_symbol_matrix_free (symbol_matrix);
g_return_val_if_reached (NULL);
}
serializable = eek_serializable_deserialize (child);
symbol_matrix->data[i] = EEK_SYMBOL(serializable);
}
return symbol_matrix;
}
static void
......@@ -118,6 +140,7 @@ eek_key_real_serialize (EekSerializable *self,
_g_variant_new_symbol_matrix (priv->symbol_matrix));
g_variant_builder_add (builder, "i", priv->column);
g_variant_builder_add (builder, "i", priv->row);
g_variant_builder_add (builder, "u", priv->oref);
}
static gsize
......@@ -137,6 +160,7 @@ eek_key_real_deserialize (EekSerializable *self,
priv->symbol_matrix = _g_variant_get_symbol_matrix (symbol_matrix);
g_variant_get_child (variant, index++, "i", &priv->column);
g_variant_get_child (variant, index++, "i", &priv->row);
g_variant_get_child (variant, index++, "u", &priv->oref);
return index;
}
......@@ -208,17 +232,17 @@ eek_key_real_get_index (EekKey *self,
}
static void
eek_key_real_set_outline (EekKey *self, EekOutline *outline)
eek_key_real_set_oref (EekKey *self, gulong oref)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
priv->outline = outline;
priv->oref = oref;
}
static EekOutline *
eek_key_real_get_outline (EekKey *self)
static gulong
eek_key_real_get_oref (EekKey *self)
{
EekKeyPrivate *priv = EEK_KEY_GET_PRIVATE(self);
return priv->outline;
return priv->oref;
}
static gboolean
......@@ -283,8 +307,8 @@ eek_key_set_property (GObject *object,
eek_key_get_index (EEK_KEY(object), &column, &row);
eek_key_set_index (EEK_KEY(object), column, g_value_get_int (value));
break;
case PROP_OUTLINE:
eek_key_set_outline (EEK_KEY(object), g_value_get_pointer (value));
case PROP_OREF:
eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value));
break;
default:
g_object_set_property (object,
......@@ -319,8 +343,8 @@ eek_key_get_property (GObject *object,
eek_key_get_index (EEK_KEY(object), &column, &row);
g_value_set_int (value, row);
break;
case PROP_OUTLINE:
g_value_set_pointer (value, eek_key_get_outline (EEK_KEY(object)));
case PROP_OREF:
g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object)));
break;
default:
g_object_get_property (object,
......@@ -345,8 +369,8 @@ eek_key_class_init (EekKeyClass *klass)
klass->get_symbol_matrix = eek_key_real_get_symbol_matrix;
klass->set_index = eek_key_real_set_index;
klass->get_index = eek_key_real_get_index;
klass->set_outline = eek_key_real_set_outline;
klass->get_outline = eek_key_real_get_outline;
klass->set_oref = eek_key_real_set_oref;
klass->get_oref = eek_key_real_get_oref;
klass->is_pressed = eek_key_real_is_pressed;
gobject_class->set_property = eek_key_set_property;
......@@ -406,18 +430,16 @@ eek_key_class_init (EekKeyClass *klass)
g_object_class_install_property (gobject_class, PROP_ROW, pspec);
/**
* EekKey:outline:
* EekKey:oref:
*
* The pointer to the outline shape of #EekKey.
* The outline id of #EekKey.
*/
/* Use pointer instead of boxed to avoid copy, since we can
assume that only a few outline shapes are used in a whole
keyboard (unlike symbol matrix and bounds). */
pspec = g_param_spec_pointer ("outline",
"Outline",
"Pointer to outline shape of the key",
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_OUTLINE, pspec);
pspec = g_param_spec_ulong ("oref",
"Oref",
"Outline id of the key",
0, G_MAXULONG, 0,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_OREF, pspec);
/**
* EekKey::pressed:
......@@ -463,7 +485,7 @@ eek_key_init (EekKey *self)
priv->keycode = 0;
priv->symbol_matrix = eek_symbol_matrix_new (0, 0);
priv->column = priv->row = 0;
priv->outline = NULL;
priv->oref = 0;
}
/**
......@@ -639,8 +661,7 @@ eek_key_get_symbol_at_index (EekKey *key,
* @column: column index of @key in #EekSection
* @row: row index of @key in #EekSection
*
* Set the index of @key (i.e. logical location of @key in
* #EekSection) to @column and @row.
* Set the location of @key in #EekSection with @column and @row.
*/
void
eek_key_set_index (EekKey *key,
......@@ -657,8 +678,7 @@ eek_key_set_index (EekKey *key,
* @column: pointer where the column index of @key in #EekSection will be stored
* @row: pointer where the row index of @key in #EekSection will be stored
*
* Get the index of @key (i.e. logical location of @key in
* #EekSection).
* Get the location of @key in #EekSection.
*/
void
eek_key_get_index (EekKey *key,
......@@ -670,32 +690,32 @@ eek_key_get_index (EekKey *key,
}
/**
* eek_key_set_outline:
* eek_key_set_oref:
* @key: an #EekKey
* @outline: outline of @key
* @oref: outline id of @key
*
* Set the outline shape of @key to @outline.
* Set the outline id of @key to @oref.
*/
void
eek_key_set_outline (EekKey *key,
EekOutline *outline)
eek_key_set_oref (EekKey *key,
gulong oref)
{
g_return_if_fail (EEK_IS_KEY(key));
EEK_KEY_GET_CLASS(key)->set_outline (key, outline);
EEK_KEY_GET_CLASS(key)->set_oref (key, oref);
}
/**
* eek_key_get_outline:
* eek_key_get_oref:
* @key: an #EekKey
*
* Get the outline shape of @key.
* Returns: an #EekOutline pointer or NULL on failure
* Get the outline id of @key.
* Returns: a non-zero unsigned integer on success, 0 if the id is not set
*/
EekOutline *
eek_key_get_outline (EekKey *key)
gulong
eek_key_get_oref (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY (key), NULL);
return EEK_KEY_GET_CLASS(key)->get_outline (key);
g_return_val_if_fail (EEK_IS_KEY (key), 0);
return EEK_KEY_GET_CLASS(key)->get_oref (key);
}
/**
......
......@@ -54,8 +54,8 @@ struct _EekKey
* section
* @get_index: virtual function for getting position of the key in the
* section
* @set_outline: virtual function for setting outline shape of the key
* @get_outline: virtual function for getting outline shape of the key
* @set_oref: virtual function for setting outline id of the key
* @get_oref: virtual function for getting outline id of the key
* @pressed: class handler for #EekKey::pressed signal
* @released: class handler for #EekKey::released signal
* @is_pressed: virtual function for getting whether the key is pressed
......@@ -80,9 +80,9 @@ struct _EekKeyClass
gint *column,
gint *row);
void (* set_outline) (EekKey *self,
EekOutline *outline);
EekOutline *(* get_outline) (EekKey *self);
void (* set_oref) (EekKey *self,
gulong oref);
gulong (* get_oref) (EekKey *self);
gboolean (* is_pressed) (EekKey *self);
......@@ -104,7 +104,7 @@ void eek_key_set_symbol_matrix (EekKey *key,
EekSymbolMatrix *matrix);
EekSymbolMatrix *eek_key_get_symbol_matrix (EekKey *key);
EekSymbol *eek_key_get_symbol (EekKey *key);
EekSymbol * eek_key_get_symbol_with_fallback
EekSymbol *eek_key_get_symbol_with_fallback
(EekKey *key,
gint fallback_group,
gint fallback_level);
......@@ -121,9 +121,9 @@ void eek_key_get_index (EekKey *key,
gint *column,
gint *row);
void eek_key_set_outline (EekKey *key,
EekOutline *outline);
EekOutline *eek_key_get_outline (EekKey *key);
void eek_key_set_oref (EekKey *key,
gulong oref);
gulong eek_key_get_oref (EekKey *key);
gboolean eek_key_is_pressed (EekKey *key);
......
......@@ -36,6 +36,7 @@
#include "eek-key.h"
#include "eek-symbol.h"
#include "eek-marshalers.h"
#include "eek-serializable.h"
enum {
PROP_0,
......@@ -55,7 +56,11 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER,
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init));
#define EEK_KEYBOARD_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYBOARD, EekKeyboardPrivate))
......@@ -68,8 +73,117 @@ struct _EekKeyboardPrivate
EekLayout *layout;
EekModifierBehavior modifier_behavior;
EekModifierType modifiers;
GArray *outline_array;
};
static EekSerializableIface *eek_keyboard_parent_serializable_iface;
static GVariant *_g_variant_new_outline (EekOutline *outline);
static EekOutline *_g_variant_get_outline (GVariant *variant);
static GVariant *
_g_variant_new_outline (EekOutline *outline)
{
GVariantBuilder builder, array;
gint i;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("(div)"));
g_variant_builder_add (&builder, "d", outline->corner_radius);
g_variant_builder_add (&builder, "i", outline->num_points);
g_variant_builder_init (&array, G_VARIANT_TYPE ("a(dd)"));
for (i = 0; i < outline->num_points; i++)
g_variant_builder_add (&array,
"(dd)",
outline->points[i].x,
outline->points[i].y);
g_variant_builder_add (&builder, "v", g_variant_builder_end (&array));
return g_variant_builder_end (&builder);
}
static EekOutline *
_g_variant_get_outline (GVariant *variant)
{
EekOutline *outline;
GVariant *array;
GVariantIter iter;
gdouble x, y;
gint i;
outline = g_slice_new0 (EekOutline);
g_variant_get_child (variant, 0, "d", &outline->corner_radius);
g_variant_get_child (variant, 1, "i", &outline->num_points);
outline->points = g_slice_alloc0 (sizeof (EekPoint) * outline->num_points);
g_variant_get_child (variant, 2, "v", &array);
g_variant_iter_init (&iter, array);
for (i = 0; i < outline->num_points; i++) {
if (!g_variant_iter_next (&iter, "(dd)", &x, &y)) {
eek_outline_free (outline);
g_return_val_if_reached (NULL);
}
outline->points[i].x = x;
outline->points[i].y = y;
}
return outline;
}
static void
eek_keyboard_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
GVariantBuilder array;
guint i;
eek_keyboard_parent_serializable_iface->serialize (self, builder);
g_variant_builder_init (&array, G_VARIANT_TYPE ("av"));
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline =
eek_keyboard_get_outline (EEK_KEYBOARD(self), i + 1);
g_variant_builder_add (&array, "v",
_g_variant_new_outline (outline));
}
g_variant_builder_add (builder, "v", g_variant_builder_end (&array));
}
static gsize
eek_keyboard_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
GVariant *array, *outline;
GVariantIter iter;
index = eek_keyboard_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "v", &array);
g_variant_iter_init (&iter, array);
while (g_variant_iter_next (&iter, "v", &outline)) {
EekOutline *_outline = _g_variant_get_outline (outline);
g_array_append_val (priv->outline_array, *_outline);
}
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_keyboard_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_keyboard_real_serialize;
iface->deserialize = eek_keyboard_real_deserialize;
}
static void
eek_keyboard_real_set_symbol_index (EekKeyboard *self,
gint group,
......@@ -123,11 +237,6 @@ eek_keyboard_real_create_section (EekKeyboard *self)
section = g_object_new (EEK_TYPE_SECTION, NULL);
g_return_val_if_fail (section, NULL);
g_signal_connect (section, "key-pressed",
G_CALLBACK(on_key_pressed), self);
g_signal_connect (section, "key-released",
G_CALLBACK(on_key_released), self);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(section));
return section;
......@@ -318,9 +427,46 @@ eek_keyboard_dispose (GObject *object)
G_OBJECT_CLASS (eek_keyboard_parent_class)->dispose (object);
}
static void
eek_keyboard_finalize (GObject *object)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
gint i;
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline = &g_array_index (priv->outline_array,
EekOutline,
i);
g_slice_free1 (sizeof (EekPoint) * outline->num_points,
outline->points);
}
g_array_free (priv->outline_array, TRUE);
G_OBJECT_CLASS (eek_keyboard_parent_class)->finalize (object);
}
static void
eek_keyboard_real_child_added (EekContainer *self,
EekElement *element)
{
g_signal_connect (element, "key-pressed",
G_CALLBACK(on_key_pressed), self);
g_signal_connect (element, "key-released",
G_CALLBACK(on_key_released), self);
}
static void
eek_keyboard_real_child_removed (EekContainer *self,
EekElement *element)
{
g_signal_handlers_disconnect_by_func (element, on_key_pressed, self);
g_signal_handlers_disconnect_by_func (element, on_key_released, self);
}
static void
eek_keyboard_class_init (EekKeyboardClass *klass)
{
EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
......@@ -337,9 +483,13 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
klass->key_released = eek_keyboard_real_key_released;
klass->symbol_index_changed = eek_keyboard_real_symbol_index_changed;
container_class->child_added = eek_keyboard_real_child_added;
container_class->child_removed = eek_keyboard_real_child_removed;
gobject_class->get_property = eek_keyboard_get_property;
gobject_class->set_property = eek_keyboard_set_property;
gobject_class->dispose = eek_keyboard_dispose;
gobject_class->finalize = eek_keyboard_finalize;
/**
* EekKeyboard:group:
......@@ -470,6 +620,7 @@ eek_keyboard_init (EekKeyboard *self)
priv->layout = NULL;
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
priv->modifiers = 0;
priv->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
}
/**
......@@ -692,3 +843,49 @@ eek_keyboard_get_modifiers (EekKeyboard *keyboard)
return priv->modifiers;
}
/**
* eek_keyboard_add_outline:
* @keyboard: an #EekKeyboard
* @outline: an #EekOutline
*
* Register an outline of @keyboard.
* Returns: an unsigned long id of the registered outline, for later reference
*/
gulong
eek_keyboard_add_outline (EekKeyboard *keyboard,
EekOutline *outline)
{
EekKeyboardPrivate *priv;
EekOutline *_outline;
g_assert (EEK_IS_KEYBOARD(keyboard));
priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
_outline = eek_outline_copy (outline);
g_array_append_val (priv->outline_array, *_outline);
return priv->outline_array->len;
}
/**
* eek_keyboard_get_outline:
* @keyboard: an #EekKeyboard
* @oref: an unsigned long id
*
* Get an outline associated with @oref in @keyboard.
* Returns: an #EekOutline, which should not be released
*/