Esempio n. 1
0
void
egg_state_machine_add_property_valist (EggStateMachine *self,
                                       const gchar     *state,
                                       gpointer         object,
                                       const gchar     *property,
                                       va_list          var_args)
{
  GParamSpec *pspec;
  gchar *error = NULL;
  GValue value = G_VALUE_INIT;

  g_return_if_fail (EGG_IS_STATE_MACHINE (self));
  g_return_if_fail (state != NULL);
  g_return_if_fail (object != NULL);
  g_return_if_fail (property != NULL);

  pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
                                        property);
  g_return_if_fail (pspec != NULL);

  G_VALUE_COLLECT_INIT (&value, pspec->value_type, var_args, 0, &error);

  if (error != NULL)
    {
      g_critical ("%s: %s", G_STRFUNC, error);
      g_free (error);
    }
  else
    {
      egg_state_machine_add_propertyv (self, state, object,
                                       property, &value);
    }

  g_value_unset (&value);
}
Esempio n. 2
0
void
egg_state_machine_add_propertyv (EggStateMachine *self,
                                 const gchar     *state,
                                 gpointer         object,
                                 const gchar     *property,
                                 const GValue    *value)
{
  EggStateMachinePrivate *priv = egg_state_machine_get_instance_private (self);
  EggState *state_obj;
  EggStateProperty *state_prop;

  g_return_if_fail (EGG_IS_STATE_MACHINE (self));
  g_return_if_fail (state != NULL);
  g_return_if_fail (G_IS_OBJECT (object));
  g_return_if_fail (property != NULL);
  g_return_if_fail (G_IS_VALUE (value));

  state_obj = egg_state_machine_get_state_obj (self, state);

  state_prop = g_slice_new0 (EggStateProperty);
  state_prop->state_machine = self;
  state_prop->object = object;
  state_prop->property = g_strdup (property);
  g_value_init (&state_prop->value, G_VALUE_TYPE (value));
  g_value_copy (value, &state_prop->value);

  g_object_weak_ref (object,
                     egg_state_machine__property_object_weak_notify,
                     state_prop);

  g_ptr_array_add (state_obj->properties, state_prop);

  if (g_strcmp0 (state, priv->state) == 0)
    g_object_set_property (object, property, value);
}
Esempio n. 3
0
static void
egg_state_unapply (EggStateMachine *self,
                   EggState        *state)
{
  GHashTableIter iter;
  gpointer key;
  gpointer value;
  gsize i;

  g_assert (EGG_IS_STATE_MACHINE (self));
  g_assert (state != NULL);

  g_hash_table_iter_init (&iter, state->bindings);
  while (g_hash_table_iter_next (&iter, &key, &value))
    egg_binding_group_set_source (value, NULL);

  g_hash_table_iter_init (&iter, state->signals);
  while (g_hash_table_iter_next (&iter, &key, &value))
    egg_signal_group_set_target (value, NULL);

  for (i = 0; i < state->styles->len; i++)
    {
      EggStateStyle *style;
      GtkStyleContext *style_context;

      style = g_ptr_array_index (state->styles, i);
      style_context = gtk_widget_get_style_context (GTK_WIDGET (style->widget));
      gtk_style_context_remove_class (style_context, style->name);
    }
}
Esempio n. 4
0
/**
 * egg_state_machine_set_state:
 * @self: the #EggStateMachine @self: the #
 *
 * Sets the #EggStateMachine:state property.
 *
 * Registered state transformations will be applied during the state
 * transformation.
 *
 * If the transition results in a cyclic operation, the state will stop at
 * the last state before the cycle was detected.
 */
void
egg_state_machine_set_state (EggStateMachine *self,
                             const gchar     *state)
{
  EggStateMachinePrivate *priv = egg_state_machine_get_instance_private (self);

  g_return_if_fail (EGG_IS_STATE_MACHINE (self));

  if (g_strcmp0 (priv->state, state) != 0)
    {
      gchar *old_state = priv->state;
      gchar *new_state = g_strdup (state);

      /*
       * Steal ownership of old state and create a copy for new state
       * to ensure that we own the references. State machines tend to
       * get used in re-entrant fashion.
       */

      priv->state = g_strdup (state);

      egg_state_machine_transition (self, old_state, state);

      g_free (new_state);
      g_free (old_state);
    }
}
Esempio n. 5
0
static void
egg_state_machine__signal_source_weak_notify (gpointer  data,
                                              GObject  *where_object_was)
{
  EggStateMachine *self = data;
  EggStateMachinePrivate *priv = egg_state_machine_get_instance_private (self);
  GHashTableIter iter;
  EggState *state;

  g_assert (EGG_IS_STATE_MACHINE (self));
  g_assert (where_object_was != NULL);

  g_hash_table_iter_init (&iter, priv->states);
  while (g_hash_table_iter_next (&iter, NULL, (gpointer)&state))
    {
      EggSignalGroup *signals;

      signals = g_hash_table_lookup (state->signals, where_object_was);

      if (signals != NULL)
        {
          g_hash_table_remove (state->signals, where_object_was);
          return;
        }
    }

  g_critical ("Failed to find signals for %p", where_object_was);
}
Esempio n. 6
0
/**
 * egg_state_machine_connect_object: (skip)
 * @self: A #EggStateMachine.
 * @state: The state the signal connection should exist within
 * @source: the source object to connect to
 * @detailed_signal: The detailed signal of @source to connect.
 * @callback: (scope notified) (closure user_data): The callback to execute upon signal emission.
 * @user_data: The user data for @callback.
 * @flags: signal connection flags.
 *
 * Connects to the @detailed_signal of @source only when the current
 * state of the state machine is @state.
 */
void
egg_state_machine_connect_object (EggStateMachine *self,
                                  const gchar     *state,
                                  gpointer         source,
                                  const gchar     *detailed_signal,
                                  GCallback        callback,
                                  gpointer         user_data,
                                  GConnectFlags    flags)
{
  EggState *state_obj;
  EggSignalGroup *signals;

  g_return_if_fail (EGG_IS_STATE_MACHINE (self));
  g_return_if_fail (state != NULL);
  g_return_if_fail (G_IS_OBJECT (source));
  g_return_if_fail (detailed_signal != NULL);
  g_return_if_fail (callback != NULL);

  state_obj = egg_state_machine_get_state_obj (self, state);

  if (!(signals = g_hash_table_lookup (state_obj->signals, source)))
    {
      signals = egg_signal_group_new (G_OBJECT_TYPE (source));
      g_hash_table_insert (state_obj->signals, source, signals);

      g_object_weak_ref (source,
                         egg_state_machine__signal_source_weak_notify,
                         self);
    }

  egg_signal_group_connect_object (signals, detailed_signal, callback, user_data, flags);
}
Esempio n. 7
0
void
egg_state_machine_add_binding (EggStateMachine *self,
                               const gchar     *state,
                               gpointer         source_object,
                               const gchar     *source_property,
                               gpointer         target_object,
                               const gchar     *target_property,
                               GBindingFlags    flags)
{
  EggBindingGroup *bindings;
  EggState *state_obj;

  g_return_if_fail (EGG_IS_STATE_MACHINE (self));
  g_return_if_fail (state != NULL);
  g_return_if_fail (G_IS_OBJECT (source_object));
  g_return_if_fail (source_property != NULL);
  g_return_if_fail (G_IS_OBJECT (target_object));
  g_return_if_fail (target_property != NULL);

  state_obj = egg_state_machine_get_state_obj (self, state);

  bindings = g_hash_table_lookup (state_obj->bindings, source_object);

  if (bindings == NULL)
    {
      bindings = egg_binding_group_new ();
      g_hash_table_insert (state_obj->bindings, source_object, bindings);

      g_object_weak_ref (source_object,
                         egg_state_machine__binding_source_weak_notify,
                         self);
    }

  egg_binding_group_bind (bindings, source_property, target_object, target_property, flags);
}
Esempio n. 8
0
/**
 * egg_state_machine_create_action:
 * @self: An #EggStateMachine
 * @name: the name of the action.
 *
 * Creates a new #GAction with the name of @name.
 *
 * Setting the state of this action will toggle the state of the state machine.
 * You should use g_variant_new_string() or similar to create the state.
 *
 * Returns: (transfer full): A newly created #GAction.
 */
GAction *
egg_state_machine_create_action (EggStateMachine *self,
                                 const gchar     *name)
{
  g_return_val_if_fail (EGG_IS_STATE_MACHINE (self), NULL);
  g_return_val_if_fail (name != NULL, NULL);

  return G_ACTION (g_property_action_new (name, self, "state"));
}
Esempio n. 9
0
/**
 * egg_state_machine_get_state:
 * @self: the #EggStateMachine.
 *
 * Gets the #EggStateMachine:state property. This is the name of the
 * current state of the machine.
 *
 * Returns: The current state of the machine.
 */
const gchar *
egg_state_machine_get_state (EggStateMachine *self)
{
  EggStateMachinePrivate *priv = egg_state_machine_get_instance_private (self);

  g_return_val_if_fail (EGG_IS_STATE_MACHINE (self), NULL);

  return priv->state;
}
Esempio n. 10
0
/**
 * egg_state_machine_create_action:
 * @self: An #EggStateMachine
 * @name: the name of the action.
 *
 * Creates a new #GAction with the name of @name.
 *
 * Setting the state of this action will toggle the state of the state machine.
 * You should use g_variant_new_string() or similar to create the state.
 *
 * Returns: (transfer full): A newly created #GAction.
 */
GAction *
egg_state_machine_create_action (EggStateMachine *self,
                                 const gchar     *name)
{
  g_return_val_if_fail (EGG_IS_STATE_MACHINE (self), NULL);
  g_return_val_if_fail (name != NULL, NULL);

  return g_object_new (EGG_TYPE_STATE_MACHINE_ACTION,
                       "state-machine", self,
                       "name", name,
                       NULL);
}
Esempio n. 11
0
void
egg_state_machine_add_property (EggStateMachine *self,
                                const gchar     *state,
                                gpointer         object,
                                const gchar     *property,
                                ...)
{
  va_list var_args;

  g_return_if_fail (EGG_IS_STATE_MACHINE (self));
  g_return_if_fail (state != NULL);
  g_return_if_fail (object != NULL);
  g_return_if_fail (property != NULL);

  va_start (var_args, property);
  egg_state_machine_add_property_valist (self, state, object,
                                         property, var_args);
  va_end (var_args);
}
Esempio n. 12
0
static void
egg_state_machine_transition (EggStateMachine *self,
                              const gchar     *old_state,
                              const gchar     *new_state)
{
  EggState *state_obj;

  g_assert (EGG_IS_STATE_MACHINE (self));

  g_object_freeze_notify (G_OBJECT (self));

  if (old_state && (state_obj = egg_state_machine_get_state_obj (self, old_state)))
    egg_state_unapply (self, state_obj);

  if (new_state && (state_obj = egg_state_machine_get_state_obj (self, new_state)))
    egg_state_apply (self, state_obj);

  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_STATE]);

  g_object_thaw_notify (G_OBJECT (self));
}
Esempio n. 13
0
static void
egg_state_machine__style_object_weak_notify (gpointer  data,
                                             GObject  *where_object_was)
{
  EggStateStyle *style_prop = data;
  EggStateMachine *self = style_prop->state_machine;
  EggStateMachinePrivate *priv = egg_state_machine_get_instance_private (self);
  GHashTableIter iter;
  EggState *state;

  g_assert (EGG_IS_STATE_MACHINE (self));
  g_assert (where_object_was != NULL);

  style_prop->widget = NULL;

  g_hash_table_iter_init (&iter, priv->states);
  while (g_hash_table_iter_next (&iter, NULL, (gpointer)&state))
    {
      if (g_ptr_array_remove_fast (state->styles, style_prop))
        return;
    }

  g_critical ("Failed to find style for %p", where_object_was);
}
Esempio n. 14
0
void
egg_state_machine_add_style (EggStateMachine *self,
                             const gchar     *state,
                             GtkWidget       *widget,
                             const gchar     *style)
{
  EggStateMachinePrivate *priv = egg_state_machine_get_instance_private (self);
  EggState *state_obj;
  EggStateStyle *style_obj;

  g_return_if_fail (EGG_IS_STATE_MACHINE (self));
  g_return_if_fail (state != NULL);
  g_return_if_fail (GTK_IS_WIDGET (widget));
  g_return_if_fail (style != NULL);

  state_obj = egg_state_machine_get_state_obj (self, state);

  style_obj = g_slice_new0 (EggStateStyle);
  style_obj->state_machine = self;
  style_obj->name = g_strdup (style);
  style_obj->widget = widget;

  g_object_weak_ref (G_OBJECT (widget),
                     egg_state_machine__style_object_weak_notify,
                     style_obj);

  g_ptr_array_add (state_obj->styles, style_obj);

  if (g_strcmp0 (state, priv->state) == 0)
    {
      GtkStyleContext *style_context;

      style_context = gtk_widget_get_style_context (widget);
      gtk_style_context_add_class (style_context, style);
    }
}
Esempio n. 15
0
static EggState *
egg_state_machine_get_state_obj (EggStateMachine *self,
                                 const gchar     *state)
{
  EggStateMachinePrivate *priv = egg_state_machine_get_instance_private (self);
  EggState *state_obj;

  g_assert (EGG_IS_STATE_MACHINE (self));

  state_obj = g_hash_table_lookup (priv->states, state);

  if (state_obj == NULL)
    {
      state_obj = g_slice_new0 (EggState);
      state_obj->name = g_strdup (state);
      state_obj->signals = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
      state_obj->bindings = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
      state_obj->properties = g_ptr_array_new_with_free_func (egg_state_property_free);
      state_obj->styles = g_ptr_array_new_with_free_func (egg_state_style_free);
      g_hash_table_insert (priv->states, g_strdup (state), state_obj);
    }

  return state_obj;
}