[libgd] Add GdRevealer
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgd] Add GdRevealer
- Date: Fri, 8 Feb 2013 10:26:15 +0000 (UTC)
commit 223bd8a8cca021a30cccd18f6b41a66c29045e8e
Author: Alexander Larsson <alexl redhat com>
Date: Thu Feb 7 21:43:23 2013 +0100
Add GdRevealer
A revealer is a bin that has two states: revealed, which always
allocates the natural size of the child and shows nothing else,
or not revealed which allocates a zero size.
The widget animates the state transition by sliding in the
child from the top/left depending on the orientation.
Makefile.am | 10 +
libgd.m4 | 6 +
libgd/gd-revealer.c | 725 +++++++++++++++++++++++++++++++++++++++++++++++++++
libgd/gd-revealer.h | 65 +++++
libgd/gd.h | 4 +
5 files changed, 810 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index b44e8d1..6fb49bb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -112,6 +112,16 @@ nodist_libgd_la_SOURCES += $(notification_sources)
EXTRA_DIST += $(notification_sources)
endif
+if LIBGD_REVEALER
+revealer_sources = \
+ libgd/gd-revealer.c \
+ libgd/gd-revealer.h \
+ $(NULL)
+
+nodist_libgd_la_SOURCES += $(revealer_sources)
+EXTRA_DIST += $(revealer_sources)
+endif
+
if LIBGD_TAGGED_ENTRY
tagged_entry_sources = \
libgd/gd-tagged-entry.c \
diff --git a/libgd.m4 b/libgd.m4
index 3fc431e..231b147 100644
--- a/libgd.m4
+++ b/libgd.m4
@@ -96,6 +96,12 @@ AC_DEFUN([LIBGD_INIT], [
AC_DEFINE([LIBGD_NOTIFICATION], [1], [Description])
])
+ # revealer:
+ AM_CONDITIONAL([LIBGD_REVEALER],[_LIBGD_IF_OPTION_SET([revealer],[true],[false])])
+ _LIBGD_IF_OPTION_SET([revealer],[
+ AC_DEFINE([LIBGD_REVEALER], [1], [Description])
+ ])
+
# tagged-entry: Gtk+ widget
AM_CONDITIONAL([LIBGD_TAGGED_ENTRY],[_LIBGD_IF_OPTION_SET([tagged-entry],[true],[false])])
_LIBGD_IF_OPTION_SET([tagged-entry],[
diff --git a/libgd/gd-revealer.c b/libgd/gd-revealer.c
new file mode 100644
index 0000000..5836c60
--- /dev/null
+++ b/libgd/gd-revealer.c
@@ -0,0 +1,725 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * This program 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 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Alexander Larsson <alexl redhat com>
+ *
+ */
+
+#include <gtk/gtk.h>
+#include "gd-revealer.h"
+#include <math.h>
+
+enum {
+ PROP_0,
+ PROP_ORIENTATION,
+ PROP_DURATION
+};
+
+#define FRAME_TIME_MSEC 17 /* 17 msec => 60 fps */
+
+struct _GdRevealerPrivate {
+ GtkOrientation orientation;
+ gint duration;
+
+ GdkWindow* bin_window;
+ GdkWindow* view_window;
+
+ gdouble current_pos;
+ gdouble source_pos;
+ gdouble target_pos;
+
+ guint timeout;
+ gint64 start_time;
+ gint64 end_time;
+};
+
+#define GTK_PARAM_READWRITE G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
+#define GD_REVEALER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GD_TYPE_REVEALER, GdRevealerPrivate))
+
+static void gd_revealer_get_child_allocation (GdRevealer *revealer,
+ GtkAllocation *allocation,
+ GtkAllocation *child_allocation);
+static void gd_revealer_real_realize (GtkWidget *widget);
+static void gd_revealer_real_unrealize (GtkWidget *widget);
+static void gd_revealer_real_add (GtkContainer *widget,
+ GtkWidget *child);
+static void gd_revealer_real_style_updated (GtkWidget *widget);
+static void gd_revealer_real_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gd_revealer_set_position (GdRevealer *revealer,
+ gdouble amount);
+static void gd_revealer_animate_step (GdRevealer *revealer,
+ gint64 now);
+static gboolean gd_revealer_animate_cb (GdRevealer *revealer);
+static void gd_revealer_start_animation (GdRevealer *revealer,
+ gdouble target);
+static gboolean _gd_revealer_animate_cb_gsource_func (gpointer revealer);
+static void gd_revealer_stop_animation (GdRevealer *revealer);
+static void gd_revealer_real_map (GtkWidget *widget);
+static void gd_revealer_real_unmap (GtkWidget *widget);
+static gboolean gd_revealer_real_draw (GtkWidget *widget,
+ cairo_t *cr);
+static void gd_revealer_real_get_preferred_height (GtkWidget *widget,
+ gint *minimum_height,
+ gint *natural_height);
+static void gd_revealer_real_get_preferred_height_for_width (GtkWidget *widget,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height);
+static void gd_revealer_real_get_preferred_width (GtkWidget *widget,
+ gint *minimum_width,
+ gint *natural_width);
+static void gd_revealer_real_get_preferred_width_for_height (GtkWidget *widget,
+ gint height,
+ gint *minimum_width,
+ gint *natural_width);
+static void gd_revealer_finalize (GObject *obj);
+static void gd_revealer_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gd_revealer_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+G_DEFINE_TYPE(GdRevealer, gd_revealer, GTK_TYPE_BIN);
+
+static void
+gd_revealer_init (GdRevealer *revealer)
+{
+ GdRevealerPrivate *priv;
+
+ priv = GD_REVEALER_GET_PRIVATE (revealer);
+ revealer->priv = priv;
+
+ priv->orientation = GTK_ORIENTATION_HORIZONTAL;
+ priv->duration = 250;
+ priv->current_pos = 0.0;
+ priv->target_pos = 0.0;
+
+ gtk_widget_set_has_window ((GtkWidget*) revealer, TRUE);
+ gtk_widget_set_redraw_on_allocate ((GtkWidget*) revealer, FALSE);
+}
+
+static void
+gd_revealer_finalize (GObject* obj)
+{
+ GdRevealer *revealer = GD_REVEALER (obj);
+ GdRevealerPrivate *priv = revealer->priv;
+
+ if (priv->timeout != 0)
+ g_source_remove (priv->timeout);
+ priv->timeout = 0;
+
+ G_OBJECT_CLASS (gd_revealer_parent_class)->finalize (obj);
+}
+
+static void
+gd_revealer_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdRevealer *revealer = GD_REVEALER (object);
+
+ switch (property_id) {
+ case PROP_ORIENTATION:
+ g_value_set_enum (value, gd_revealer_get_orientation (revealer));
+ break;
+ case PROP_DURATION:
+ g_value_set_int (value, gd_revealer_get_duration (revealer));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gd_revealer_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdRevealer *revealer = GD_REVEALER (object);
+
+ switch (property_id) {
+ case PROP_ORIENTATION:
+ gd_revealer_set_orientation (revealer, g_value_get_enum (value));
+ break;
+ case PROP_DURATION:
+ gd_revealer_set_duration (revealer, g_value_get_int (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gd_revealer_class_init (GdRevealerClass * klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+ object_class->get_property = gd_revealer_get_property;
+ object_class->set_property = gd_revealer_set_property;
+ object_class->finalize = gd_revealer_finalize;
+
+ widget_class->realize = gd_revealer_real_realize;
+ widget_class->unrealize = gd_revealer_real_unrealize;
+ widget_class->style_updated = gd_revealer_real_style_updated;
+ widget_class->size_allocate = gd_revealer_real_size_allocate;
+ widget_class->map = gd_revealer_real_map;
+ widget_class->unmap = gd_revealer_real_unmap;
+ widget_class->draw = gd_revealer_real_draw;
+ widget_class->get_preferred_height = gd_revealer_real_get_preferred_height;
+ widget_class->get_preferred_height_for_width = gd_revealer_real_get_preferred_height_for_width;
+ widget_class->get_preferred_width = gd_revealer_real_get_preferred_width;
+ widget_class->get_preferred_width_for_height = gd_revealer_real_get_preferred_width_for_height;
+
+ container_class->add = gd_revealer_real_add;
+
+ g_object_class_install_property (object_class,
+ PROP_ORIENTATION,
+ g_param_spec_enum ("orientation", "orientation",
+ "The orientation of the widget",
+ GTK_TYPE_ORIENTATION,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class,
+ PROP_DURATION,
+ g_param_spec_int ("duration", "duration",
+ "The animation duration, in milliseconds",
+ G_MININT, G_MAXINT,
+ 250,
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_type_class_add_private (klass, sizeof (GdRevealerPrivate));
+}
+
+
+GdRevealer *
+gd_revealer_new (void)
+{
+ return g_object_new (GD_TYPE_REVEALER, NULL);
+}
+
+static void
+gd_revealer_get_child_allocation (GdRevealer *revealer,
+ GtkAllocation* allocation,
+ GtkAllocation* child_allocation)
+{
+ GtkWidget *child;
+ GdRevealerPrivate *priv;
+
+ g_return_if_fail (revealer != NULL);
+ g_return_if_fail (allocation != NULL);
+
+ priv = revealer->priv;
+
+ child_allocation->x = 0;
+ child_allocation->y = 0;
+ child_allocation->width = allocation->width;
+ child_allocation->height = allocation->height;
+
+ child = gtk_bin_get_child (GTK_BIN (revealer));
+ if (child != NULL && gtk_widget_get_visible (child))
+ {
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ gtk_widget_get_preferred_height_for_width (child, child_allocation->width, NULL,
+ &child_allocation->height);
+ else
+ gtk_widget_get_preferred_width_for_height (child, child_allocation->height, NULL,
+ &child_allocation->width);
+ }
+}
+
+static void
+gd_revealer_real_realize (GtkWidget *widget)
+{
+ GdRevealer *revealer = GD_REVEALER (widget);
+ GdRevealerPrivate *priv = revealer->priv;
+ GtkAllocation allocation;
+ GdkWindowAttr attributes = { 0 };
+ GdkWindowAttributesType attributes_mask;
+ GtkAllocation child_allocation;
+ GtkWidget *child;
+ GtkStyleContext *context;
+
+ gtk_widget_set_realized (widget, TRUE);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.event_mask =
+ gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+ attributes_mask = (GDK_WA_X | GDK_WA_Y) | GDK_WA_VISUAL;
+
+ priv->view_window =
+ gdk_window_new (gtk_widget_get_parent_window ((GtkWidget*) revealer),
+ &attributes, attributes_mask);
+ gtk_widget_set_window (widget, priv->view_window);
+ gtk_widget_register_window (widget, priv->view_window);
+
+ gd_revealer_get_child_allocation (revealer, &allocation, &child_allocation);
+
+ attributes.x = 0;
+ attributes.y = 0;
+ attributes.width = child_allocation.width;
+ attributes.height = child_allocation.height;
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ attributes.y = allocation.height - child_allocation.height;
+ else
+ attributes.x = allocation.width - child_allocation.width;
+
+ priv->bin_window =
+ gdk_window_new (priv->view_window, &attributes, attributes_mask);
+ gtk_widget_register_window (widget, priv->bin_window);
+
+ child = gtk_bin_get_child (GTK_BIN (revealer));
+ if (child != NULL)
+ gtk_widget_set_parent_window (child, priv->bin_window);
+
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_set_background (context, priv->view_window);
+ gtk_style_context_set_background (context, priv->bin_window);
+ gdk_window_show (priv->bin_window);
+}
+
+
+static void
+gd_revealer_real_unrealize (GtkWidget* widget)
+{
+ GdRevealer *revealer = GD_REVEALER (widget);
+ GdRevealerPrivate *priv = revealer->priv;
+
+ gtk_widget_unregister_window (widget, priv->bin_window);
+ gdk_window_destroy (priv->bin_window);
+ priv->view_window = NULL;
+
+ GTK_WIDGET_CLASS (gd_revealer_parent_class)->unrealize (widget);
+}
+
+
+static void
+gd_revealer_real_add (GtkContainer* container,
+ GtkWidget* child)
+{
+ GdRevealer *revealer = GD_REVEALER (container);
+ GdRevealerPrivate *priv = revealer->priv;
+
+ g_return_if_fail (child != NULL);
+
+ gtk_widget_set_parent_window (child, priv->bin_window);
+ gtk_widget_set_child_visible (child, priv->current_pos != 0.0);
+
+ GTK_CONTAINER_CLASS (gd_revealer_parent_class)->add (container, child);
+}
+
+
+static void
+gd_revealer_real_style_updated (GtkWidget* widget)
+{
+ GdRevealer *revealer = GD_REVEALER (widget);
+ GdRevealerPrivate *priv = revealer->priv;
+ GtkStyleContext* context;
+
+ GTK_WIDGET_CLASS (gd_revealer_parent_class)->style_updated (widget);
+
+ if (gtk_widget_get_realized (widget))
+ {
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_set_background (context, priv->bin_window);
+ gtk_style_context_set_background (context, priv->view_window);
+ }
+}
+
+
+static void
+gd_revealer_real_size_allocate (GtkWidget* widget,
+ GtkAllocation* allocation)
+{
+ GdRevealer *revealer = GD_REVEALER (widget);
+ GdRevealerPrivate *priv = revealer->priv;
+ GtkAllocation child_allocation;
+ GtkWidget *child;
+ gboolean window_visible;
+ int bin_x, bin_y;
+
+ g_return_if_fail (allocation != NULL);
+
+ gtk_widget_set_allocation (widget, allocation);
+ gd_revealer_get_child_allocation (revealer, allocation, &child_allocation);
+
+ child = gtk_bin_get_child (GTK_BIN (revealer));
+ if (child != NULL &&
+ gtk_widget_get_visible (child))
+ gtk_widget_size_allocate (child, &child_allocation);
+
+ if (gtk_widget_get_realized (widget))
+ {
+ if (gtk_widget_get_mapped (widget))
+ {
+ window_visible =
+ allocation->width > 0 && allocation->height > 0;
+
+ if (!window_visible &&
+ gdk_window_is_visible (priv->view_window))
+ gdk_window_hide (priv->view_window);
+
+ if (window_visible &&
+ !gdk_window_is_visible (priv->view_window))
+ gdk_window_show (priv->view_window);
+ }
+
+ gdk_window_move_resize (priv->view_window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ bin_x = 0;
+ bin_y = 0;
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ bin_y = allocation->height - child_allocation.height;
+ else
+ bin_x = allocation->width - child_allocation.width;
+
+ gdk_window_move_resize (priv->bin_window,
+ bin_x, bin_y,
+ child_allocation.width, child_allocation.height);
+ }
+}
+
+
+static void
+gd_revealer_set_position (GdRevealer *revealer,
+ gdouble pos)
+{
+ GdRevealerPrivate *priv = revealer->priv;
+ gboolean new_visible;
+ GtkWidget *child;
+
+ priv->current_pos = pos;
+
+ /* We check target_pos here too, because we want to ensure we set
+ * child_visible immediately when starting a reveal operation
+ * otherwise the child widgets will not be properly realized
+ * after the reveal returns.
+ */
+ new_visible = priv->current_pos != 0.0 || priv->target_pos != 0.0;
+
+ child = gtk_bin_get_child (GTK_BIN (revealer));
+ if (child != NULL &&
+ new_visible != gtk_widget_get_child_visible (child))
+ gtk_widget_set_child_visible (child, new_visible);
+
+ gtk_widget_queue_resize (GTK_WIDGET (revealer));
+}
+
+static gdouble
+ease_out_quad (gdouble t, gdouble d)
+{
+ gdouble p = t / d;
+ return ((-1.0) * p) * (p - 2);
+}
+
+static void
+gd_revealer_animate_step (GdRevealer *revealer,
+ gint64 now)
+{
+ GdRevealerPrivate *priv = revealer->priv;
+ gdouble t;
+
+ t = 1.0;
+ if (now < priv->end_time)
+ t = (now - priv->start_time) / (double) (priv->end_time - priv->start_time);
+ t = ease_out_quad (t, 1.0);
+
+ gd_revealer_set_position (revealer,
+ priv->source_pos + (t * (priv->target_pos - priv->source_pos)));
+}
+
+static gboolean
+gd_revealer_animate_cb (GdRevealer *revealer)
+{
+ GdRevealerPrivate *priv = revealer->priv;
+ gint64 now;
+
+ now = g_get_monotonic_time ();
+ gd_revealer_animate_step (revealer, now);
+ if (priv->current_pos == priv->target_pos)
+ {
+ priv->timeout = (guint) 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+gd_revealer_start_animation (GdRevealer *revealer,
+ gdouble target)
+{
+ GdRevealerPrivate *priv = revealer->priv;
+
+ if (priv->target_pos == target)
+ return;
+
+ priv->target_pos = target;
+ if (gtk_widget_get_mapped (GTK_WIDGET (revealer)))
+ {
+ priv->source_pos = priv->current_pos;
+ priv->start_time = g_get_monotonic_time ();
+ priv->end_time = priv->start_time + (priv->duration * 1000);
+ if (priv->timeout == 0)
+ priv->timeout =
+ gdk_threads_add_timeout ((guint) FRAME_TIME_MSEC,
+ (GSourceFunc)gd_revealer_animate_cb, revealer);
+ gd_revealer_animate_step (revealer, priv->start_time);
+ }
+ else
+ gd_revealer_set_position (revealer, target);
+}
+
+
+static void
+gd_revealer_stop_animation (GdRevealer *revealer)
+{
+ GdRevealerPrivate *priv = revealer->priv;
+
+ priv->current_pos = priv->target_pos;
+ if (priv->timeout != 0)
+ {
+ g_source_remove (priv->timeout);
+ priv->timeout = 0;
+ }
+}
+
+
+static void
+gd_revealer_real_map (GtkWidget *widget)
+{
+ GdRevealer *revealer = GD_REVEALER (widget);
+ GdRevealerPrivate *priv = revealer->priv;
+ GtkAllocation allocation;
+
+ if (!gtk_widget_get_mapped (widget))
+ {
+ gtk_widget_get_allocation (widget, &allocation);
+
+ if (allocation.width > 0 && allocation.height > 0)
+ gdk_window_show (priv->view_window);
+
+ gd_revealer_start_animation (revealer, priv->target_pos);
+ }
+
+ GTK_WIDGET_CLASS (gd_revealer_parent_class)->map (widget);
+}
+
+static void
+gd_revealer_real_unmap (GtkWidget *widget)
+{
+ GdRevealer *revealer = GD_REVEALER (widget);
+
+ GTK_WIDGET_CLASS (gd_revealer_parent_class)->unmap (widget);
+
+ gd_revealer_stop_animation (revealer);
+}
+
+
+static gboolean
+gd_revealer_real_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ GdRevealer *revealer = GD_REVEALER (widget);
+ GdRevealerPrivate *priv = revealer->priv;
+
+ if (gtk_cairo_should_draw_window (cr, priv->bin_window))
+ GTK_WIDGET_CLASS (gd_revealer_parent_class)->draw (widget, cr);
+
+ return TRUE;
+}
+
+void
+gd_revealer_reveal (GdRevealer *revealer)
+{
+ g_return_if_fail (revealer != NULL);
+
+ gd_revealer_start_animation (revealer, 1.0);
+}
+
+void
+gd_revealer_unreveal (GdRevealer *revealer)
+{
+ g_return_if_fail (revealer != NULL);
+
+ gd_revealer_start_animation (revealer, 0.0);
+}
+
+
+/* These all report only the natural size, ignoring the minimal size,
+ * because its not really possible to allocate the right size during
+ * animation if the child size can change (without the child
+ * re-arranging itself during the animation).
+ */
+
+static void
+gd_revealer_real_get_preferred_height (GtkWidget* widget,
+ gint* minimum_height_out,
+ gint* natural_height_out)
+{
+ GdRevealer *revealer = GD_REVEALER (widget);
+ GdRevealerPrivate *priv = revealer->priv;
+ gint minimum_height;
+ gint natural_height;
+
+ GTK_WIDGET_CLASS (gd_revealer_parent_class)->get_preferred_height (widget, &minimum_height, &natural_height);
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ natural_height = round (natural_height * priv->current_pos);
+
+ minimum_height = natural_height;
+
+ if (minimum_height_out)
+ *minimum_height_out = minimum_height;
+ if (natural_height_out)
+ *natural_height_out = natural_height;
+}
+
+static void
+gd_revealer_real_get_preferred_height_for_width (GtkWidget* widget,
+ gint width,
+ gint* minimum_height_out,
+ gint* natural_height_out)
+{
+ GdRevealer *revealer = GD_REVEALER (widget);
+ GdRevealerPrivate *priv = revealer->priv;
+ gint minimum_height;
+ gint natural_height;
+
+ GTK_WIDGET_CLASS (gd_revealer_parent_class)->get_preferred_height_for_width (widget, width, &minimum_height, &natural_height);
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ natural_height = round (natural_height * priv->current_pos);
+
+ minimum_height = natural_height;
+
+ if (minimum_height_out)
+ *minimum_height_out = minimum_height;
+ if (natural_height_out)
+ *natural_height_out = natural_height;
+}
+
+static void
+gd_revealer_real_get_preferred_width (GtkWidget* widget,
+ gint* minimum_width_out,
+ gint* natural_width_out)
+{
+ GdRevealer *revealer = GD_REVEALER (widget);
+ GdRevealerPrivate *priv = revealer->priv;
+ gint minimum_width;
+ gint natural_width;
+
+ GTK_WIDGET_CLASS (gd_revealer_parent_class)->get_preferred_width (widget, &minimum_width, &natural_width);
+
+ if (priv->orientation == GTK_ORIENTATION_VERTICAL)
+ natural_width = round (natural_width * priv->current_pos);
+
+ minimum_width = natural_width;
+
+ if (minimum_width_out)
+ *minimum_width_out = minimum_width;
+ if (natural_width_out)
+ *natural_width_out = natural_width;
+}
+
+static void
+gd_revealer_real_get_preferred_width_for_height (GtkWidget* widget,
+ gint height,
+ gint* minimum_width_out,
+ gint* natural_width_out)
+{
+ GdRevealer *revealer = GD_REVEALER (widget);
+ GdRevealerPrivate *priv = revealer->priv;
+ gint minimum_width;
+ gint natural_width;
+
+ GTK_WIDGET_CLASS (gd_revealer_parent_class)->get_preferred_width_for_height (widget, height, &minimum_width, &natural_width);
+
+ if (priv->orientation == GTK_ORIENTATION_VERTICAL)
+ natural_width = round (natural_width * priv->current_pos);
+
+ minimum_width = natural_width;
+
+ if (minimum_width_out)
+ *minimum_width_out = minimum_width;
+ if (natural_width_out)
+ *natural_width_out = natural_width;
+}
+
+GtkOrientation
+gd_revealer_get_orientation (GdRevealer *revealer)
+{
+ g_return_val_if_fail (revealer != NULL, 0);
+
+ return revealer->priv->orientation;
+}
+
+void
+gd_revealer_set_orientation (GdRevealer *revealer,
+ GtkOrientation value)
+{
+ g_return_if_fail (revealer != NULL);
+
+ revealer->priv->orientation = value;
+ g_object_notify (G_OBJECT (revealer), "orientation");
+}
+
+gint
+gd_revealer_get_duration (GdRevealer *revealer)
+{
+ g_return_val_if_fail (revealer != NULL, 0);
+
+ return revealer->priv->duration;
+}
+
+void
+gd_revealer_set_duration (GdRevealer *revealer,
+ gint value)
+{
+ g_return_if_fail (revealer != NULL);
+
+ revealer->priv->duration = value;
+ g_object_notify (G_OBJECT (revealer), "duration");
+}
+
+gboolean
+gd_revealer_get_is_revealed (GdRevealer *revealer)
+{
+ g_return_val_if_fail (revealer != NULL, FALSE);
+
+ return revealer->priv->target_pos != 0.0;
+}
diff --git a/libgd/gd-revealer.h b/libgd/gd-revealer.h
new file mode 100644
index 0000000..2be0509
--- /dev/null
+++ b/libgd/gd-revealer.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * This program 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 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Alexander Larsson <alexl redhat com>
+ *
+ */
+
+#ifndef __GD_REVEALER_H__
+#define __GD_REVEALER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+
+#define GD_TYPE_REVEALER (gd_revealer_get_type ())
+#define GD_REVEALER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GD_TYPE_REVEALER, GdRevealer))
+#define GD_REVEALER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GD_TYPE_REVEALER, GdRevealerClass))
+#define GD_IS_REVEALER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GD_TYPE_REVEALER))
+#define GD_IS_REVEALER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GD_TYPE_REVEALER))
+#define GD_REVEALER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GD_TYPE_REVEALER, GdRevealerClass))
+
+typedef struct _GdRevealer GdRevealer;
+typedef struct _GdRevealerClass GdRevealerClass;
+typedef struct _GdRevealerPrivate GdRevealerPrivate;
+
+struct _GdRevealer {
+ GtkBin parent_instance;
+ GdRevealerPrivate * priv;
+};
+
+struct _GdRevealerClass {
+ GtkBinClass parent_class;
+};
+
+
+GType gd_revealer_get_type (void) G_GNUC_CONST;
+GdRevealer* gd_revealer_new (void);
+void gd_revealer_reveal (GdRevealer *revealer);
+void gd_revealer_unreveal (GdRevealer *revealer);
+gboolean gd_revealer_get_is_revealed (GdRevealer *revealer);
+GtkOrientation gd_revealer_get_orientation (GdRevealer *revealer);
+void gd_revealer_set_orientation (GdRevealer *revealer,
+ GtkOrientation value);
+gint gd_revealer_get_duration (GdRevealer *revealer);
+void gd_revealer_set_duration (GdRevealer *revealer,
+ gint duration_msec);
+
+G_END_DECLS
+
+#endif
diff --git a/libgd/gd.h b/libgd/gd.h
index 62f1306..83cfba5 100644
--- a/libgd/gd.h
+++ b/libgd/gd.h
@@ -64,6 +64,10 @@ G_BEGIN_DECLS
# include <libgd/gd-notification.h>
#endif
+#ifdef LIBGD_REVEALER
+# include <libgd/gd-revealer.h>
+#endif
+
G_END_DECLS
#endif /* __GD_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]