[gnome-builder] egg: add EggElasticBin
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] egg: add EggElasticBin
- Date: Fri, 7 Apr 2017 21:56:13 +0000 (UTC)
commit 4929739fd170ed87fcbdcb94f33288ab59cb4677
Author: Christian Hergert <chergert redhat com>
Date: Fri Apr 7 14:28:35 2017 -0700
egg: add EggElasticBin
This is a simple bin that animates between vertical sizes.
contrib/egg/Makefile.am | 2 +
contrib/egg/egg-elastic-bin.c | 278 +++++++++++++++++++++++++++++++++++++++++
contrib/egg/egg-elastic-bin.h | 44 +++++++
3 files changed, 324 insertions(+), 0 deletions(-)
---
diff --git a/contrib/egg/Makefile.am b/contrib/egg/Makefile.am
index 7772555..6a97101 100644
--- a/contrib/egg/Makefile.am
+++ b/contrib/egg/Makefile.am
@@ -15,6 +15,7 @@ headers_DATA = \
egg-column-layout.h \
egg-counter.h \
egg-date-time.h \
+ egg-elastic-bin.h \
egg-empty-state.h \
egg-entry-box.h \
egg-file-chooser-entry.h \
@@ -51,6 +52,7 @@ libegg_private_la_SOURCES = \
egg-column-layout.c \
egg-counter.c \
egg-date-time.c \
+ egg-elastic-bin.c \
egg-empty-state.c \
egg-entry-box.c \
egg-file-chooser-entry.c \
diff --git a/contrib/egg/egg-elastic-bin.c b/contrib/egg/egg-elastic-bin.c
new file mode 100644
index 0000000..3e90c36
--- /dev/null
+++ b/contrib/egg/egg-elastic-bin.c
@@ -0,0 +1,278 @@
+/* egg-elastic-bin.c
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * This file 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.
+ *
+ * This file 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 General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "egg-elastic-bin"
+
+#include "egg-animation.h"
+#include "egg-elastic-bin.h"
+
+#define MM_PER_SECOND (100.0)
+#define MIN_FRAMES_PER_ANIM (5)
+#define MAX_FRAMES_PER_ANIM (500)
+
+#if 0
+# define _TRACE_LEVEL (1<<G_LOG_LEVEL_USER_SHIFT)
+# define _TRACE(...) do { g_log(G_LOG_DOMAIN, _TRACE_LEVEL, __VA_ARGS__); } while (0)
+# define TRACE_MSG(m,...) _TRACE(" MSG: %s():%u: "m, G_STRFUNC, __LINE__, __VA_ARGS__)
+# define ENTRY _TRACE(" ENTRY: %s(): %u", G_STRFUNC, __LINE__)
+# define EXIT do { _TRACE(" EXIT: %s(): %u", G_STRFUNC, __LINE__); return; } while (0)
+# define RETURN(r) do { _TRACE(" EXIT: %s(): %u", G_STRFUNC, __LINE__); return (r); } while (0)
+#else
+# define TRACE_MSG(m,...) do { } while (0)
+# define ENTRY do { } while (0)
+# define EXIT return
+# define RETURN(r) return (r)
+#endif
+
+typedef struct
+{
+ GtkAdjustment *hadj;
+ EggAnimation *hanim;
+ gint cached_min_height;
+ gint cached_nat_height;
+} EggElasticBinPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (EggElasticBin, egg_elastic_bin, GTK_TYPE_BIN)
+
+static void
+egg_elastic_bin_cancel_animation (EggElasticBin *self)
+{
+ EggElasticBinPrivate *priv = egg_elastic_bin_get_instance_private (self);
+
+ ENTRY;
+
+ g_assert (EGG_IS_ELASTIC_BIN (self));
+
+ if (priv->hanim != NULL)
+ {
+ EggAnimation *anim = priv->hanim;
+
+ g_object_remove_weak_pointer (G_OBJECT (priv->hanim), (gpointer *)&priv->hanim);
+ priv->hanim = NULL;
+
+ egg_animation_stop (anim);
+ }
+
+ EXIT;
+}
+
+static guint
+egg_elastic_bin_calculate_duration (EggElasticBin *self,
+ gdouble from_value,
+ gdouble to_value)
+{
+ GdkDisplay *display;
+ GdkMonitor *monitor;
+ GdkWindow *window;
+
+ g_assert (EGG_IS_ELASTIC_BIN (self));
+ g_assert (from_value >= 0.0);
+ g_assert (to_value >= 0.0);
+
+ if (NULL != (display = gtk_widget_get_display (GTK_WIDGET (self))) &&
+ NULL != (window = gtk_widget_get_window (GTK_WIDGET (self))) &&
+ NULL != (monitor = gdk_display_get_monitor_at_window (display, window)))
+ return egg_animation_calculate_duration (monitor, from_value, to_value);
+
+ return 0;
+}
+
+static void
+egg_elastic_bin_animate_to (EggElasticBin *self,
+ gdouble value)
+{
+ EggElasticBinPrivate *priv = egg_elastic_bin_get_instance_private (self);
+ guint duration;
+
+ ENTRY;
+
+ g_assert (EGG_IS_ELASTIC_BIN (self));
+
+ egg_elastic_bin_cancel_animation (self);
+
+ duration = egg_elastic_bin_calculate_duration (self,
+ gtk_adjustment_get_value (priv->hadj),
+ value);
+
+ TRACE_MSG ("Duration is %u milliseconds", duration);
+
+ priv->hanim = egg_object_animate (priv->hadj,
+ EGG_ANIMATION_EASE_OUT_CUBIC,
+ duration,
+ gtk_widget_get_frame_clock (GTK_WIDGET (self)),
+ "value", value,
+ NULL);
+ g_object_add_weak_pointer (G_OBJECT (priv->hanim), (gpointer *)&priv->hanim);
+
+ EXIT;
+}
+
+static void
+egg_elastic_bin_get_preferred_height_for_width (GtkWidget *widget,
+ gint width,
+ gint *min_height,
+ gint *nat_height)
+{
+ EggElasticBin *self = (EggElasticBin *)widget;
+ EggElasticBinPrivate *priv = egg_elastic_bin_get_instance_private (self);
+
+ ENTRY;
+
+ TRACE_MSG ("width=%d", width);
+
+ g_assert (EGG_IS_ELASTIC_BIN (self));
+
+ /*
+ * We must always chain up to the parent get_preferred_height_for_width()
+ * so that we can detect changes while we are animating.
+ */
+
+ GTK_WIDGET_CLASS (egg_elastic_bin_parent_class)->get_preferred_height_for_width (widget, width,
min_height, nat_height);
+
+ /*
+ * If we are animating the widget, and the size request hasn't changed since
+ * our last animation frame, go ahead and process that now.
+ */
+
+ if (*min_height == priv->cached_min_height &&
+ *nat_height == priv->cached_nat_height &&
+ priv->hanim != NULL)
+ {
+ *min_height = priv->cached_min_height;
+ *nat_height = (gint)gtk_adjustment_get_value (priv->hadj);
+
+ TRACE_MSG ("Fast path min=%d nat=%d", *min_height, *nat_height);
+
+ if (*nat_height == priv->cached_nat_height)
+ egg_elastic_bin_cancel_animation (self);
+
+ EXIT;
+ }
+
+ if (*min_height != priv->cached_min_height || *nat_height != priv->cached_nat_height)
+ {
+ priv->cached_min_height = *min_height;
+ priv->cached_nat_height = *nat_height;
+
+ TRACE_MSG ("New requested height is min=%d nat=%d",
+ *min_height, *nat_height);
+
+ if (*min_height > (gint)gtk_adjustment_get_value (priv->hadj))
+ gtk_adjustment_set_value (priv->hadj, *min_height);
+
+ *min_height = priv->cached_min_height;
+ *nat_height = (gint)gtk_adjustment_get_value (priv->hadj);
+
+ egg_elastic_bin_animate_to (self, priv->cached_nat_height);
+
+ TRACE_MSG ("!!! min=%d nat=%d", *min_height, *nat_height);
+
+ EXIT;
+ }
+
+ TRACE_MSG ("*** min=%d nat=%d", *min_height, *nat_height);
+
+ EXIT;
+}
+
+static void
+egg_elastic_bin_hadj_value_changed (EggElasticBin *self,
+ GtkAdjustment *adj)
+{
+ ENTRY;
+
+ g_assert (EGG_IS_ELASTIC_BIN (self));
+ g_assert (GTK_IS_ADJUSTMENT (adj));
+
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+
+ EXIT;
+}
+
+static void
+egg_elastic_bin_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ g_assert (GTK_IS_WIDGET (widget));
+ g_assert (allocation != NULL);
+
+ TRACE_MSG ("Allocating %d,%d %dx%d",
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ GTK_WIDGET_CLASS (egg_elastic_bin_parent_class)->size_allocate (widget, allocation);
+}
+
+static GtkSizeRequestMode
+egg_elastic_bin_get_request_mode (GtkWidget *widget)
+{
+ return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
+}
+
+static void
+egg_elastic_bin_destroy (GtkWidget *widget)
+{
+ EggElasticBin *self = (EggElasticBin *)widget;
+
+ g_assert (EGG_IS_ELASTIC_BIN (self));
+
+ egg_elastic_bin_cancel_animation (self);
+
+ GTK_WIDGET_CLASS (egg_elastic_bin_parent_class)->destroy (widget);
+}
+
+static void
+egg_elastic_bin_finalize (GObject *object)
+{
+ EggElasticBin *self = (EggElasticBin *)object;
+ EggElasticBinPrivate *priv = egg_elastic_bin_get_instance_private (self);
+
+ g_clear_object (&priv->hadj);
+
+ G_OBJECT_CLASS (egg_elastic_bin_parent_class)->finalize (object);
+}
+
+static void
+egg_elastic_bin_class_init (EggElasticBinClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = egg_elastic_bin_finalize;
+
+ widget_class->destroy = egg_elastic_bin_destroy;
+ widget_class->get_preferred_height_for_width = egg_elastic_bin_get_preferred_height_for_width;
+ widget_class->size_allocate = egg_elastic_bin_size_allocate;
+ widget_class->get_request_mode = egg_elastic_bin_get_request_mode;
+
+ gtk_widget_class_set_css_name (widget_class, "elastic");
+}
+
+static void
+egg_elastic_bin_init (EggElasticBin *self)
+{
+ EggElasticBinPrivate *priv = egg_elastic_bin_get_instance_private (self);
+
+ priv->hadj = gtk_adjustment_new (0, 0, G_MAXINT, 1, 1, 1);
+
+ g_signal_connect_object (priv->hadj,
+ "value-changed",
+ G_CALLBACK (egg_elastic_bin_hadj_value_changed),
+ self,
+ G_CONNECT_SWAPPED);
+}
diff --git a/contrib/egg/egg-elastic-bin.h b/contrib/egg/egg-elastic-bin.h
new file mode 100644
index 0000000..dcd0805
--- /dev/null
+++ b/contrib/egg/egg-elastic-bin.h
@@ -0,0 +1,44 @@
+/* egg-elastic-bin.h
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * This file 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.
+ *
+ * This file 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 General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EGG_ELASTIC_BIN_H
+#define EGG_ELASTIC_BIN_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_ELASTIC_BIN (egg_elastic_bin_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (EggElasticBin, egg_elastic_bin, EGG, ELASTIC_BIN, GtkBin)
+
+struct _EggElasticBinClass
+{
+ GtkBinClass parent_class;
+
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+};
+
+GtkWidget *egg_elastic_bin_new (void);
+
+G_END_DECLS
+
+#endif /* EGG_ELASTIC_BIN_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]