Add a GeditAnimatable and use it.

Now the GeditTheatricsAnimatedWidget is named as GeditFloatingSlider
and it implements the GeditAnimatable. This makes the code more
understandable and easier to extend.
parent 73a15bff
......@@ -101,6 +101,7 @@ BUILT_SOURCES = \
gedit-marshal.h
NOINST_H_FILES = \
gedit-animatable.h \|
gedit-animated-overlay.h \
gedit-close-button.h \
gedit-command-line.h \
......@@ -112,6 +113,7 @@ NOINST_H_FILES = \
gedit-document-saver.h \
gedit-documents-panel.h \
gedit-file-chooser-dialog.h \
gedit-floating-slider.h \
gedit-history-entry.h \
gedit-io-error-info-bar.h \
gedit-language-manager.h \
......@@ -169,6 +171,7 @@ libgedit_private_la_SOURCES = \
gedit-window-activatable.c
libgedit_c_files = \
gedit-animatable.c \
gedit-animated-overlay.c \
gedit-app.c \
gedit-close-button.c \
......@@ -192,6 +195,7 @@ libgedit_c_files = \
gedit-encodings.c \
gedit-encodings-combo-box.c \
gedit-file-chooser-dialog.c \
gedit-floating-slider.c \
gedit-history-entry.c \
gedit-io-error-info-bar.c \
gedit-language-manager.c \
......
/*
* gedit-animatable.c
* This file is part of gedit
*
* Copyright (C) 2011 - Ignacio Casal Quinteiro
*
* gedit 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.
*
* gedit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "gedit-animatable.h"
#include "gedit-overlay-child.h"
#include "theatrics/gedit-theatrics-choreographer.h"
#include "theatrics/gedit-theatrics-enum-types.h"
G_DEFINE_INTERFACE(GeditAnimatable, gedit_animatable, GEDIT_TYPE_OVERLAY_CHILD)
void
gedit_animatable_default_init (GeditAnimatableInterface *iface)
{
static gboolean initialized = FALSE;
if (!initialized)
{
g_object_interface_install_property (iface,
g_param_spec_enum ("easing",
"Easing",
"The Easing",
GEDIT_TYPE_THEATRICS_CHOREOGRAPHER_EASING,
GEDIT_THEATRICS_CHOREOGRAPHER_EASING_LINEAR,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_object_interface_install_property (iface,
g_param_spec_enum ("blocking",
"Blocking",
"The Blocking",
GEDIT_TYPE_THEATRICS_CHOREOGRAPHER_BLOCKING,
GEDIT_THEATRICS_CHOREOGRAPHER_BLOCKING_DOWNSTAGE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_object_interface_install_property (iface,
g_param_spec_enum ("animation-state",
"Animation State",
"The Animation State",
GEDIT_TYPE_THEATRICS_ANIMATION_STATE,
GEDIT_THEATRICS_ANIMATION_STATE_COMING,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_object_interface_install_property (iface,
g_param_spec_uint ("duration",
"Duration",
"The duration",
0,
G_MAXUINT,
300,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_object_interface_install_property (iface,
g_param_spec_double ("percent",
"Percent",
"The percent",
0.0,
G_MAXDOUBLE,
0.0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_object_interface_install_property (iface,
g_param_spec_double ("bias",
"Bias",
"The bias",
0.0,
G_MAXDOUBLE,
1.0,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
initialized = TRUE;
}
}
/* XXX: too lazy to add the methods, should we or can we survive only with props? */
/* ex:set ts=8 noet: */
/*
* gedit-animatable.h
* This file is part of gedit
*
* Copyright (C) 2011 - Ignacio Casal Quinteiro
*
* gedit 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.
*
* gedit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __GEDIT_ANIMATABLE_H__
#define __GEDIT_ANIMATABLE_H__
#include <glib-object.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define GEDIT_TYPE_ANIMATABLE (gedit_animatable_get_type ())
#define GEDIT_ANIMATABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_ANIMATABLE, GeditAnimatable))
#define GEDIT_ANIMATABLE_IFACE(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GEDIT_TYPE_ANIMATABLE, GeditAnimatableInterface))
#define GEDIT_IS_ANIMATABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_ANIMATABLE))
#define GEDIT_ANIMATABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GEDIT_TYPE_ANIMATABLE, GeditAnimatableInterface))
typedef struct _GeditAnimatable GeditAnimatable; /* dummy typedef */
typedef struct _GeditAnimatableInterface GeditAnimatableInterface;
struct _GeditAnimatableInterface
{
GTypeInterface g_iface;
/* Virtual public methods */
};
/*
* Public methods
*/
GType gedit_animatable_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GEDIT_ANIMATABLE_H__ */
/* ex:set ts=8 noet: */
......@@ -23,7 +23,6 @@
#include "gedit-animated-overlay.h"
#include "theatrics/gedit-theatrics-stage.h"
#include "theatrics/gedit-theatrics-animated-widget.h"
struct _GeditAnimatedOverlayPrivate
{
......@@ -62,39 +61,49 @@ on_actor_step (GeditTheatricsStage *stage,
GeditAnimatedOverlay *overlay)
{
GeditTheatricsAnimationState animation_state;
GeditTheatricsAnimatedWidget *anim_widget;
GObject *anim_widget;
guint duration;
anim_widget = GEDIT_THEATRICS_ANIMATED_WIDGET (gedit_theatrics_actor_get_target (actor));
animation_state = gedit_theatrics_animated_widget_get_animation_state (anim_widget);
anim_widget = gedit_theatrics_actor_get_target (actor);
g_assert (GEDIT_IS_ANIMATABLE (anim_widget));
g_object_get (anim_widget, "animation-state", &animation_state,
"duration", &duration, NULL);
switch (animation_state)
{
case GEDIT_THEATRICS_ANIMATION_STATE_COMING:
gtk_widget_queue_draw (GTK_WIDGET (anim_widget));
gedit_theatrics_animated_widget_set_percent (anim_widget,
gedit_theatrics_actor_get_percent (actor));
g_object_set (anim_widget, "percent",
gedit_theatrics_actor_get_percent (actor),
NULL);
if (gedit_theatrics_actor_get_expired (actor))
{
gedit_theatrics_animated_widget_set_animation_state (anim_widget,
GEDIT_THEATRICS_ANIMATION_STATE_IDLE);
g_object_set (anim_widget, "animation-state",
GEDIT_THEATRICS_ANIMATION_STATE_IDLE, NULL);
}
break;
case GEDIT_THEATRICS_ANIMATION_STATE_INTENDING_TO_GO:
gedit_theatrics_animated_widget_set_animation_state (anim_widget,
GEDIT_THEATRICS_ANIMATION_STATE_GOING);
gedit_theatrics_animated_widget_set_bias (anim_widget,
gedit_theatrics_actor_get_percent (actor));
gedit_theatrics_actor_reset (actor, gedit_theatrics_animated_widget_get_duration (anim_widget) *
gedit_theatrics_actor_get_percent (actor));
g_object_set (anim_widget,
"animation-state", GEDIT_THEATRICS_ANIMATION_STATE_GOING,
"bias", gedit_theatrics_actor_get_percent (actor),
NULL);
gedit_theatrics_actor_reset (actor, duration * gedit_theatrics_actor_get_percent (actor));
break;
case GEDIT_THEATRICS_ANIMATION_STATE_GOING:
gtk_widget_queue_draw (GTK_WIDGET (anim_widget));
g_object_set (anim_widget, "percent",
1.0 - gedit_theatrics_actor_get_percent (actor),
NULL);
if (gedit_theatrics_actor_get_expired (actor))
{
gtk_widget_destroy (GTK_WIDGET (anim_widget));
return;
g_object_set (anim_widget, "animation-state",
GEDIT_THEATRICS_ANIMATION_STATE_IDLE, NULL);
}
gtk_widget_queue_draw (GTK_WIDGET (anim_widget));
gedit_theatrics_animated_widget_set_percent (anim_widget, 1.0 - gedit_theatrics_actor_get_percent (actor));
break;
default:
break;
......@@ -116,6 +125,27 @@ gedit_animated_overlay_init (GeditAnimatedOverlay *overlay)
overlay);
}
static void
on_animation_state_changed (GeditAnimatable *animatable,
GParamSpec *pspec,
GeditAnimatedOverlay *overlay)
{
GeditTheatricsAnimationState animation_state;
guint duration;
g_object_get (G_OBJECT (animatable),
"animation-state", &animation_state,
"duration", &duration, NULL);
if (animation_state == GEDIT_THEATRICS_ANIMATION_STATE_COMING ||
animation_state == GEDIT_THEATRICS_ANIMATION_STATE_INTENDING_TO_GO)
{
gedit_theatrics_stage_add_with_duration (overlay->priv->stage,
G_OBJECT (animatable),
duration);
}
}
/**
* gedit_animated_overlay_new:
* @main_widget: a #GtkWidget
......@@ -137,110 +167,30 @@ gedit_animated_overlay_new (GtkWidget *main_widget,
NULL);
}
static GeditTheatricsAnimatedWidget *
get_animated_widget (GeditAnimatedOverlay *overlay,
GtkWidget *widget)
{
GeditTheatricsAnimatedWidget *anim_widget = NULL;
GtkWidget *main_widget;
GList *children, *l;
children = gtk_container_get_children (GTK_CONTAINER (overlay));
g_object_get (G_OBJECT (overlay), "main-widget", &main_widget, NULL);
for (l = children; l != NULL; l = g_list_next (l))
{
GtkWidget *child = GTK_WIDGET (l->data);
/* skip the main widget as it is not a OverlayChild */
if (child == main_widget)
continue;
if (child == widget)
{
anim_widget = GEDIT_THEATRICS_ANIMATED_WIDGET (child);
break;
}
else
{
GtkWidget *in_widget;
/* let's try also with the internal widget */
g_object_get (child, "widget", &in_widget, NULL);
g_assert (in_widget != NULL);
if (in_widget == widget)
{
anim_widget = GEDIT_THEATRICS_ANIMATED_WIDGET (child);
g_object_unref (in_widget);
break;
}
g_object_unref (in_widget);
}
}
g_object_unref (main_widget);
g_list_free (children);
return anim_widget;
}
/**
* gedit_animated_overlay_slide:
* @overlay: a #GeditAnimatedOverlay
* @widget: a #GtkWidget to add to @overlay
* @position: a #GeditOverlayChildPosition
* @offset: offset for @widget
* @duration: the duration of the animation
* @easing: a #GeditTheatricsChoreographerEasing
* @blocking: a #GeditTheatricsChoreographerBlocking
* @orientation: the orientation of the animation
* @in: if %TRUE slide in if %FALSE slide out
*
* Adds @widget in @overlay with a slide in/out animation depending on @in.
*/
void
gedit_animated_overlay_slide (GeditAnimatedOverlay *overlay,
GtkWidget *widget,
GeditOverlayChildPosition position,
guint offset,
guint duration,
GeditTheatricsChoreographerEasing easing,
GeditTheatricsChoreographerBlocking blocking,
GtkOrientation orientation,
gboolean in)
gedit_animated_overlay_add (GeditAnimatedOverlay *overlay,
GeditAnimatable *animatable)
{
GeditTheatricsAnimatedWidget *anim_widget;
GeditOverlayChildPosition position;
guint offset, duration;
anim_widget = get_animated_widget (overlay, widget);
g_return_if_fail (GEDIT_IS_OVERLAY (overlay));
g_return_if_fail (GEDIT_IS_ANIMATABLE (animatable));
if (anim_widget == NULL)
{
anim_widget = gedit_theatrics_animated_widget_new (widget, duration,
easing,
blocking,
orientation);
gtk_widget_show (GTK_WIDGET (anim_widget));
gedit_overlay_add (GEDIT_OVERLAY (overlay),
GTK_WIDGET (anim_widget),
position, offset);
}
else
{
/* we are only interested in the easing and the blocking */
gedit_theatrics_animated_widget_set_easing (anim_widget, easing);
gedit_theatrics_animated_widget_set_blocking (anim_widget, blocking);
}
g_object_get (G_OBJECT (animatable),
"position", &position,
"offset", &offset,
"duration", &duration,
NULL);
if (!in)
{
gedit_theatrics_animated_widget_set_animation_state (anim_widget, GEDIT_THEATRICS_ANIMATION_STATE_GOING);
}
/* FIXME: check that the widget is not already added */
gedit_theatrics_stage_add_with_duration (overlay->priv->stage,
G_OBJECT (anim_widget),
duration);
gedit_overlay_add (GEDIT_OVERLAY (overlay),
GTK_WIDGET (animatable),
position, offset);
g_signal_connect (animatable,
"notify::animation-state",
G_CALLBACK (on_animation_state_changed),
overlay);
}
......@@ -22,6 +22,7 @@
#ifndef __GEDIT_ANIMATED_OVERLAY_H__
#define __GEDIT_ANIMATED_OVERLAY_H__
#include "gedit-animatable.h"
#include "gedit-overlay.h"
#include "theatrics/gedit-theatrics-choreographer.h"
......@@ -56,15 +57,8 @@ GType gedit_animated_overlay_get_type (void) G_GNUC_CONST;
GtkWidget *gedit_animated_overlay_new (GtkWidget *main_widget,
GtkWidget *relative_widget);
void gedit_animated_overlay_slide (GeditAnimatedOverlay *overlay,
GtkWidget *widget,
GeditOverlayChildPosition position,
guint offset,
guint duration,
GeditTheatricsChoreographerEasing easing,
GeditTheatricsChoreographerBlocking blocking,
GtkOrientation orientation,
gboolean in);
void gedit_animated_overlay_add (GeditAnimatedOverlay *overlay,
GeditAnimatable *animatable);
G_END_DECLS
......
/*
* gedit-floating-slider.c
* This file is part of gedit
*
* Copyright (C) 2010 - Ignacio Casal Quinteiro
*
* Based on Scott Peterson <lunchtimemama@gmail.com> work.
*
* gedit is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* gedit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gedit; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#include "gedit-floating-slider.h"
#include "gedit-animatable.h"
struct _GeditFloatingSliderPrivate
{
GtkAllocation widget_alloc;
GeditTheatricsChoreographerEasing easing;
GeditTheatricsChoreographerBlocking blocking;
GeditTheatricsAnimationState animation_state;
GtkOrientation orientation;
guint duration;
gdouble bias;
gdouble percent;
};
enum
{
PROP_0,
PROP_EASING,
PROP_BLOCKING,
PROP_ANIMATION_STATE,
PROP_DURATION,
PROP_PERCENT,
PROP_BIAS,
PROP_ORIENTATION
};
G_DEFINE_TYPE_EXTENDED (GeditFloatingSlider,
gedit_floating_slider,
GEDIT_TYPE_OVERLAY_CHILD,
0,
G_IMPLEMENT_INTERFACE (GEDIT_TYPE_ANIMATABLE,
NULL)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE,
NULL))
static void
gedit_floating_slider_finalize (GObject *object)
{
G_OBJECT_CLASS (gedit_floating_slider_parent_class)->finalize (object);
}
static void
gedit_floating_slider_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GeditFloatingSliderPrivate *priv = GEDIT_FLOATING_SLIDER (object)->priv;
switch (prop_id)
{
case PROP_EASING:
g_value_set_enum (value, priv->easing);
break;
case PROP_BLOCKING:
g_value_set_enum (value, priv->blocking);
break;
case PROP_ANIMATION_STATE:
g_value_set_enum (value, priv->animation_state);
break;
case PROP_DURATION:
g_value_set_uint (value, priv->duration);
break;
case PROP_PERCENT:
g_value_set_double (value, priv->percent);
break;
case PROP_BIAS:
g_value_set_double (value, priv->bias);
break;
case PROP_ORIENTATION:
g_value_set_enum (value, priv->orientation);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gedit_floating_slider_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GeditFloatingSliderPrivate *priv = GEDIT_FLOATING_SLIDER (object)->priv;
switch (prop_id)
{
case PROP_EASING:
priv->easing = g_value_get_enum (value);
break;
case PROP_BLOCKING:
priv->blocking = g_value_get_enum (value);
break;
case PROP_ANIMATION_STATE:
priv->animation_state = g_value_get_enum (value);
break;
case PROP_DURATION:
priv->duration = g_value_get_uint (value);
break;
case PROP_PERCENT:
priv->percent = g_value_get_double (value);
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (object));
/* Make the widget visibility automagic */
if (priv->percent > 0 && !gtk_widget_get_visible (GTK_WIDGET (object)))
{
gtk_widget_show (GTK_WIDGET (object));
}
else if (priv->percent == 0 && gtk_widget_get_visible (GTK_WIDGET (object)))
{
gtk_widget_hide (GTK_WIDGET (object));
}
break;
case PROP_BIAS:
priv->bias = g_value_get_double (value);
break;
case PROP_ORIENTATION:
priv->orientation = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gedit_floating_slider_get_preferred_width (GtkWidget *widget,
gint *minimum,
gint *natural)
{
GeditFloatingSliderPrivate *priv = GEDIT_FLOATING_SLIDER (widget)->priv;
GtkWidget *child;
gint width;
GTK_WIDGET_CLASS (gedit_floating_slider_parent_class)->get_preferred_width (widget, minimum, natural);
child = gtk_bin_get_child (GTK_BIN (widget));
if (child != NULL)
{
gint child_min, child_nat;
gtk_widget_get_preferred_width (child, &child_min, &child_nat);
priv->widget_alloc.width = child_min;
}
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
width = gedit_theatrics_choreographer_pixel_compose (priv->percent,
priv->widget_alloc.width,
priv->easing);
}
else
{
width = priv->widget_alloc.width;
}
*minimum = *natural = width;
}
static void
gedit_floating_slider_get_preferred_height (GtkWidget *widget,
gint *minimum,
gint *natural)
{
GeditFloatingSliderPrivate *priv = GEDIT_FLOATING_SLIDER (widget)->priv;
GtkWidget *child;
gint height;
GTK_WIDGET_CLASS (gedit_floating_slider_parent_class)->get_preferred_height (widget, minimum, natural);
child = gtk_bin_get_child (GTK_BIN (widget));
if (child != NULL)
{
gint child_min, child_nat;
gtk_widget_get_preferred_height (child, &child_min, &child_nat);
priv->widget_alloc.height = child_min;
}
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
height = priv->widget_alloc.height;
}
else
{
height = gedit_theatrics_choreographer_pixel_compose (priv->percent,
priv->widget_alloc.height,
priv->easing);
}
*minimum = *natural = height;
}
static void
gedit_floating_slider_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GeditFloatingSliderPrivate *priv = GEDIT_FLOATING_SLIDER (widget)->priv;
GtkWidget *child;
GTK_WIDGET_CLASS (gedit_floating_slider_parent_class)->size_allocate (widget, allocation);
child = gtk_bin_get_child (GTK_BIN (widget));
if (child != NULL)
{
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
priv->widget_alloc.height = allocation->height;
priv->widget_alloc.x = 0;
if (priv->blocking == GEDIT_THEATRICS_CHOREOGRAPHER_BLOCKING_DOWNSTAGE)
{
priv->widget_alloc.x = allocation->width - priv->widget_alloc.width;
}
}
else
{
priv->widget_alloc.width = allocation->width;
priv->widget_alloc.y = 0;
if (priv->blocking == GEDIT_THEATRICS_CHOREOGRAPHER_BLOCKING_DOWNSTAGE)
{
priv->widget_alloc.y = allocation->height - priv->widget_alloc.height;
}
}
if (priv->widget_alloc.height > 0 && priv->widget_alloc.width > 0)
{
gtk_widget_size_allocate (child, &priv->widget_alloc);
}
}
}
static void
gedit_floating_slider_class_init (GeditFloatingSliderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = gedit_floating_slider_finalize;
object_class->get_property = gedit_floating_slider_get_property;
object_class->set_property = gedit_floating_slider_set_property;
widget_class->get_preferred_width = gedit_floating_slider_get_preferred_width;
widget_class->get_preferred_height = gedit_floating_slider_get_preferred_height;
widget_class->size_allocate = gedit_floating_slider_size_allocate;
g_object_class_override_property (object_class,
PROP_EASING,
"easing");
g_object_class_override_property (object_class,
PROP_BLOCKING,
"blocking");
g_object_class_override_property (object_class,
PROP_ANIMATION_STATE,
"animation-state");
g_object_class_override_property (object_class,
PROP_DURATION,
"duration");
g_object_class_override_property (object_class,