[gnome-builder/wip/chergert/fill-box] egg: add EggFillBox



commit 5a32d0839e833e8922a4acb451e08696a4d66b33
Author: Christian Hergert <christian hergert me>
Date:   Mon Aug 24 21:30:09 2015 -0700

    egg: add EggFillBox
    
    EggFillBox is a container that will try to layout children in a series
    of columns. It tries to ensure the columns have similar heights. Contrast
    this with GtkFlowBox or GtkGrid where columns and rows are similarly sized
    with their peers. EggFillBox has no such requirement, other than columns,
    which will allocate to the same width.

 contrib/egg/Makefile.am    |    2 +
 contrib/egg/egg-fill-box.c |  489 ++++++++++++++++++++++++++++++++++++++++++++
 contrib/egg/egg-fill-box.h |   60 ++++++
 tests/Makefile.am          |   10 +
 tests/test-fill-box.c      |  133 ++++++++++++
 5 files changed, 694 insertions(+), 0 deletions(-)
---
diff --git a/contrib/egg/Makefile.am b/contrib/egg/Makefile.am
index ac8968b..45e893e 100644
--- a/contrib/egg/Makefile.am
+++ b/contrib/egg/Makefile.am
@@ -6,6 +6,8 @@ libegg_private_la_SOURCES = \
        egg-binding-group.h \
        egg-counter.c \
        egg-counter.h \
+       egg-fill-box.c \
+       egg-fill-box.h \
        egg-heap.c \
        egg-heap.h \
        egg-search-bar.c \
diff --git a/contrib/egg/egg-fill-box.c b/contrib/egg/egg-fill-box.c
new file mode 100644
index 0000000..f902636
--- /dev/null
+++ b/contrib/egg/egg-fill-box.c
@@ -0,0 +1,489 @@
+/* egg-fill-box.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program 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 3 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 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/>.
+ */
+
+#include "egg-fill-box.h"
+
+typedef struct
+{
+  GtkWidget      *widget;
+  gint            min_width;
+  gint            nat_width;
+  gint            min_height;
+  gint            nat_height;
+  GtkAllocation   alloc;
+} EggFillBoxChild;
+
+typedef struct
+{
+  GSequence *children;
+  gint       min_columns;
+  gint       max_columns;
+  gint       height;
+} EggFillBoxPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (EggFillBox, egg_fill_box, GTK_TYPE_CONTAINER)
+
+enum {
+  PROP_0,
+  PROP_MIN_COLUMNS,
+  PROP_MAX_COLUMNS,
+  LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+static gint
+egg_fill_box_child_compare (gconstpointer a,
+                            gconstpointer b,
+                            gpointer      data)
+{
+  const EggFillBoxChild *ac = a;
+  const EggFillBoxChild *bc = b;
+
+  return MAX (bc->min_height, bc->nat_height) - MAX (ac->min_height, ac->nat_height);
+}
+
+static void
+egg_fill_box_child_free (gpointer data)
+{
+  EggFillBoxChild *child = data;
+
+  if (child != NULL)
+    g_slice_free (EggFillBoxChild, child);
+}
+
+static void
+egg_fill_box_relayout (EggFillBox *self,
+                       gint        width)
+{
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+  GSequenceIter *iter;
+  g_autofree gint *columns = NULL;
+  GtkAllocation allocation;
+  gint num_columns;
+  gint max_min_width = -1;
+  gint max_nat_width = -1;
+  gint begin_space = 0;
+  gint column_width;
+  gint consumed;
+  gint column = 0;
+  gint i;
+
+  g_assert (EGG_IS_FILL_BOX (self));
+
+  gtk_widget_get_allocation (GTK_WIDGET (self), &allocation);
+
+  if (width <= 0)
+    width = allocation.width;
+
+  for (iter = g_sequence_get_begin_iter (priv->children);
+       !g_sequence_iter_is_end (iter);
+       iter = g_sequence_iter_next (iter))
+    {
+      EggFillBoxChild *child = g_sequence_get (iter);
+
+      gtk_widget_get_preferred_width (child->widget, &child->min_width, &child->nat_width);
+      gtk_widget_get_preferred_height (child->widget, &child->min_height, &child->nat_height);
+
+      if (child->min_width > max_min_width)
+        max_min_width = child->min_width;
+
+      if (child->nat_width > max_nat_width)
+        max_nat_width = child->nat_width;
+    }
+
+  g_sequence_sort (priv->children, egg_fill_box_child_compare, NULL);
+
+  max_min_width = MAX (1, max_min_width);
+  max_nat_width = MAX (1, max_nat_width);
+
+  if (max_nat_width < width)
+    {
+      num_columns = MAX (1, width / max_nat_width);
+      consumed = num_columns * max_nat_width;
+      column_width = max_nat_width;
+      begin_space = (width - consumed) / 2;
+    }
+  else
+    {
+      num_columns = 1;
+      consumed = width;
+      column_width = width;
+    }
+
+  columns = g_new0 (gint, num_columns);
+
+  for (iter = g_sequence_get_begin_iter (priv->children);
+       !g_sequence_iter_is_end (iter);
+       iter = g_sequence_iter_next (iter))
+    {
+      EggFillBoxChild *child = g_sequence_get (iter);
+      gint min_height = G_MAXINT;
+
+      for (i = 0; i < num_columns; i++)
+        {
+          if (columns [i] < min_height)
+            {
+              min_height = columns [i];
+              column = i;
+            }
+        }
+
+      child->alloc.x = begin_space + (column_width * column);
+      child->alloc.y = columns [column];
+      child->alloc.width = column_width;
+
+      gtk_widget_get_preferred_height_for_width (child->widget,
+                                                 column_width,
+                                                 NULL,
+                                                 &child->alloc.height);
+
+      columns [column] += child->alloc.height;
+    }
+
+  priv->height = 0;
+
+  for (i = 0; i < num_columns; i++)
+    {
+      if ((priv->height == 0) || (columns [i] > priv->height))
+        priv->height = columns [i];
+    }
+}
+
+static void
+egg_fill_box_add (GtkContainer *container,
+                  GtkWidget    *widget)
+{
+  EggFillBox *self = (EggFillBox *)container;
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+  EggFillBoxChild *child;
+
+  g_assert (EGG_IS_FILL_BOX (self));
+  g_assert (GTK_IS_WIDGET (widget));
+
+  child = g_slice_new0 (EggFillBoxChild);
+  child->widget = widget;
+  gtk_widget_get_preferred_width (widget, &child->min_width, &child->nat_width);
+  g_sequence_insert_sorted (priv->children, child, egg_fill_box_child_compare, NULL);
+  gtk_widget_set_parent (widget, GTK_WIDGET (self));
+  gtk_widget_queue_resize (GTK_WIDGET (container));
+}
+
+static void
+egg_fill_box_remove (GtkContainer *container,
+                     GtkWidget    *widget)
+{
+  EggFillBox *self = (EggFillBox *)container;
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+  GSequenceIter *iter;
+
+  g_assert (EGG_IS_FILL_BOX (self));
+  g_assert (GTK_IS_WIDGET (widget));
+
+  for (iter = g_sequence_get_begin_iter (priv->children);
+       !g_sequence_iter_is_end (iter);
+       iter = g_sequence_iter_next (iter))
+    {
+      EggFillBoxChild *child = g_sequence_get (iter);
+
+      if (child->widget == widget)
+        {
+          g_sequence_remove (iter);
+          egg_fill_box_relayout (self, -1);
+          break;
+        }
+    }
+}
+
+static void
+egg_fill_box_size_allocate (GtkWidget     *widget,
+                            GtkAllocation *allocation)
+{
+  EggFillBox *self = (EggFillBox *)widget;
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+  GSequenceIter *iter;
+
+  g_assert (EGG_IS_FILL_BOX (self));
+
+  GTK_WIDGET_CLASS (egg_fill_box_parent_class)->size_allocate (widget, allocation);
+
+  egg_fill_box_relayout (self, -1);
+
+  for (iter = g_sequence_get_begin_iter (priv->children);
+       !g_sequence_iter_is_end (iter);
+       iter = g_sequence_iter_next (iter))
+    {
+      EggFillBoxChild *child = g_sequence_get (iter);
+
+      gtk_widget_size_allocate (child->widget, &child->alloc);
+    }
+}
+
+static GtkSizeRequestMode
+egg_fill_box_get_request_mode (GtkWidget *widget)
+{
+  return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
+}
+
+static void
+egg_fill_box_get_preferred_width (GtkWidget *widget,
+                                  gint      *min_width,
+                                  gint      *nat_width)
+{
+  EggFillBox *self = (EggFillBox *)widget;
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+  GSequenceIter *iter;
+  gint real_min_width = 0;
+  gint real_nat_width = 0;
+
+  g_assert (EGG_IS_FILL_BOX (self));
+
+  for (iter = g_sequence_get_begin_iter (priv->children);
+       !g_sequence_iter_is_end (iter);
+       iter = g_sequence_iter_next (iter))
+    {
+      EggFillBoxChild *child = g_sequence_get (iter);
+      gint child_min_width;
+      gint child_nat_width;
+
+      gtk_widget_get_preferred_width (child->widget, &child_min_width, &child_nat_width);
+
+      if (child_min_width > real_min_width)
+        real_min_width = child_min_width;
+
+      if (child_nat_width > real_nat_width)
+        real_nat_width = child_nat_width;
+    }
+
+  if (min_width)
+    *min_width = real_min_width;
+
+  if (nat_width)
+    *nat_width = real_nat_width;
+}
+
+static void
+egg_fill_box_get_preferred_height_for_width (GtkWidget *widget,
+                                             gint       width,
+                                             gint      *min_height,
+                                             gint      *nat_height)
+{
+  EggFillBox *self = (EggFillBox *)widget;
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+
+  g_assert (EGG_IS_FILL_BOX (self));
+
+  egg_fill_box_relayout (self, width);
+
+  if (min_height)
+    *min_height = priv->height;
+
+  if (nat_height)
+    *nat_height = priv->height;
+}
+
+static void
+egg_fill_box_realize (GtkWidget *widget)
+{
+  EggFillBox *self = (EggFillBox *)widget;
+
+  g_assert (EGG_IS_FILL_BOX (self));
+
+  GTK_WIDGET_CLASS (egg_fill_box_parent_class)->realize (widget);
+
+  egg_fill_box_relayout (self, -1);
+}
+
+static void
+egg_fill_box_forall (GtkContainer *container,
+                     gboolean      include_internals,
+                     GtkCallback   callback,
+                     gpointer      callback_data)
+{
+  EggFillBox *self = (EggFillBox *)container;
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+  GSequenceIter *iter;
+
+  g_assert (EGG_IS_FILL_BOX (self));
+
+  for (iter = g_sequence_get_begin_iter (priv->children);
+       !g_sequence_iter_is_end (iter);
+       iter = g_sequence_iter_next (iter))
+    {
+      EggFillBoxChild *child = g_sequence_get (iter);
+
+      callback (child->widget, callback_data);
+    }
+}
+
+static void
+egg_fill_box_finalize (GObject *object)
+{
+  EggFillBox *self = (EggFillBox *)object;
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+
+  g_clear_pointer (&priv->children, g_sequence_free);
+
+  G_OBJECT_CLASS (egg_fill_box_parent_class)->finalize (object);
+}
+
+static void
+egg_fill_box_get_property (GObject    *object,
+                           guint       prop_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
+{
+  EggFillBox *self = EGG_FILL_BOX (object);
+
+  switch (prop_id)
+    {
+    case PROP_MAX_COLUMNS:
+      g_value_set_int (value, egg_fill_box_get_max_columns (self));
+      break;
+
+    case PROP_MIN_COLUMNS:
+      g_value_set_int (value, egg_fill_box_get_min_columns (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+egg_fill_box_set_property (GObject      *object,
+                           guint         prop_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
+{
+  EggFillBox *self = EGG_FILL_BOX (object);
+
+  switch (prop_id)
+    {
+    case PROP_MAX_COLUMNS:
+      egg_fill_box_set_max_columns (self, g_value_get_int (value));
+      break;
+
+    case PROP_MIN_COLUMNS:
+      egg_fill_box_set_min_columns (self, g_value_get_int (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+egg_fill_box_class_init (EggFillBoxClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+  object_class->finalize = egg_fill_box_finalize;
+  object_class->get_property = egg_fill_box_get_property;
+  object_class->set_property = egg_fill_box_set_property;
+
+  widget_class->get_preferred_width = egg_fill_box_get_preferred_width;
+  widget_class->get_request_mode = egg_fill_box_get_request_mode;
+  widget_class->get_preferred_height_for_width = egg_fill_box_get_preferred_height_for_width;
+  widget_class->realize = egg_fill_box_realize;
+  widget_class->size_allocate = egg_fill_box_size_allocate;
+
+  container_class->add = egg_fill_box_add;
+  container_class->forall = egg_fill_box_forall;
+  container_class->remove = egg_fill_box_remove;
+}
+
+static void
+egg_fill_box_init (EggFillBox *self)
+{
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+
+  gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
+
+  priv->children = g_sequence_new (egg_fill_box_child_free);
+  priv->min_columns = -1;
+  priv->max_columns = -1;
+}
+
+GtkWidget *
+egg_fill_box_new (void)
+{
+  return g_object_new (EGG_TYPE_FILL_BOX, NULL);
+}
+
+gint
+egg_fill_box_get_max_columns (EggFillBox *self)
+{
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+
+  g_return_val_if_fail (EGG_IS_FILL_BOX (self), -1);
+
+  return priv->max_columns;
+}
+
+void
+egg_fill_box_set_max_columns (EggFillBox *self,
+                              gint        max_columns)
+{
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+
+  g_return_if_fail (EGG_IS_FILL_BOX (self));
+  g_return_if_fail (max_columns >= -1);
+
+  if (max_columns <= 0)
+    max_columns = -1;
+
+  if (max_columns != priv->max_columns)
+    {
+      priv->max_columns = max_columns;
+      gtk_widget_queue_resize (GTK_WIDGET (self));
+      g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_MAX_COLUMNS]);
+    }
+}
+
+gint
+egg_fill_box_get_min_columns (EggFillBox *self)
+{
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+
+  g_return_val_if_fail (EGG_IS_FILL_BOX (self), -1);
+
+  return priv->min_columns;
+}
+
+void
+egg_fill_box_set_min_columns (EggFillBox *self,
+                              gint        min_columns)
+{
+  EggFillBoxPrivate *priv = egg_fill_box_get_instance_private (self);
+
+  g_return_if_fail (EGG_IS_FILL_BOX (self));
+  g_return_if_fail (min_columns >= -1);
+
+  if (min_columns <= 0)
+    min_columns = -1;
+
+  if (min_columns != priv->min_columns)
+    {
+      priv->min_columns = min_columns;
+      gtk_widget_queue_resize (GTK_WIDGET (self));
+      g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_MIN_COLUMNS]);
+    }
+}
diff --git a/contrib/egg/egg-fill-box.h b/contrib/egg/egg-fill-box.h
new file mode 100644
index 0000000..0ce4157
--- /dev/null
+++ b/contrib/egg/egg-fill-box.h
@@ -0,0 +1,60 @@
+/* egg-fill-box.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program 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 3 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 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_FILL_BOX_H
+#define EGG_FILL_BOX_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+/**
+ * SECTION:egg-fill-box:
+ * @title: EggFillBox
+ * @short_description: a box that fills content based on child allocation size
+ *
+ * #EggFillBox is a container type that will allocate children in a series of
+ * columns. You can specify the number of columns, or allow the container to
+ * determine this based on the largest allocation width of the children.
+ *
+ * The #EggFillBox will layout children starting from the tallest to the
+ * shortest. Each item will be placed into the column with the shortest
+ * combined height. This gives the overall appearance that all the columns
+ * are of similar height.
+ */
+
+#define EGG_TYPE_FILL_BOX (egg_fill_box_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (EggFillBox, egg_fill_box, EGG, FILL_BOX, GtkContainer)
+
+struct _EggFillBoxClass
+{
+  GtkContainerClass parent;
+};
+
+GtkWidget *egg_fill_box_new             (void);
+gint       egg_fill_box_get_max_columns (EggFillBox *self);
+void       egg_fill_box_set_max_columns (EggFillBox *self,
+                                         gint        max_columns);
+gint       egg_fill_box_get_min_columns (EggFillBox *self);
+void       egg_fill_box_set_min_columns (EggFillBox *self,
+                                         gint        min_columns);
+
+G_END_DECLS
+
+#endif /* EGG_FILL_BOX_H */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1d0de47..449ed57 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -155,6 +155,16 @@ test_vim_LDADD = \
        $(NULL)
 
 
+TESTS += test-fill-box
+test_fill_box_SOURCES = test-fill-box.c
+test_fill_box_CFLAGS = \
+       $(tests_cflags) \
+       $(NULL)
+test_fill_box_LDADD = \
+       $(tests_libs) \
+       $(NULL)
+
+
 misc_programs += test-ide-source-view
 test_ide_source_view_SOURCES = test-ide-source-view.c
 test_ide_source_view_CFLAGS = $(tests_cflags)
diff --git a/tests/test-fill-box.c b/tests/test-fill-box.c
new file mode 100644
index 0000000..690058c
--- /dev/null
+++ b/tests/test-fill-box.c
@@ -0,0 +1,133 @@
+/* test-fill-box.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program 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 3 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 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/>.
+ */
+
+#include <stdlib.h>
+
+#include "egg-fill-box.h"
+
+static void
+new_pixbuf_cb (GObject      *object,
+               GAsyncResult *result,
+               gpointer      user_data)
+{
+  GdkPixbuf *pixbuf = NULL;
+  EggFillBox *fill_box = user_data;
+  GtkWidget *image;
+  GError *error = NULL;
+
+  pixbuf = gdk_pixbuf_new_from_stream_finish (result, &error);
+
+  if (pixbuf == NULL)
+    {
+      g_printerr ("%s\n", error->message);
+      g_clear_error (&error);
+      return;
+    }
+
+  image = g_object_new (GTK_TYPE_IMAGE,
+                        "pixbuf", pixbuf,
+                        "visible", TRUE,
+                        NULL);
+  gtk_container_add (GTK_CONTAINER (fill_box), image);
+
+  g_clear_object (&pixbuf);
+}
+
+static void
+load_directory (EggFillBox  *fill_box,
+                const gchar *directory)
+{
+  const gchar *name;
+  GError *error = NULL;
+  GDir *dir;
+
+  dir = g_dir_open (directory, 0, &error);
+
+  if (dir == NULL)
+    {
+      g_printerr ("%s\n", error->message);
+      g_clear_error (&error);
+      exit (1);
+    }
+
+  while ((name = g_dir_read_name (dir)))
+    {
+      g_autofree gchar *filename = NULL;
+      g_autoptr(GFile) file = NULL;
+      g_autoptr(GFileInputStream) stream = NULL;
+
+      if (!(g_str_has_suffix (name, ".jpg") ||
+            g_str_has_suffix (name, ".JPG") ||
+            g_str_has_suffix (name, ".png")))
+        continue;
+
+      filename = g_build_filename (directory, name, NULL);
+      file = g_file_new_for_path (filename);
+      stream = g_file_read (file, NULL, NULL);
+
+      if (stream == NULL)
+        continue;
+
+      gdk_pixbuf_new_from_stream_at_scale_async (G_INPUT_STREAM (stream),
+                                                 150,
+                                                 -1,
+                                                 TRUE,
+                                                 NULL,
+                                                 new_pixbuf_cb,
+                                                 fill_box);
+    }
+
+  g_dir_close (dir);
+}
+
+gint
+main (gint   argc,
+      gchar *argv[])
+{
+  GtkWindow *window;
+  GtkScrolledWindow *scroller;
+  EggFillBox *fill_box;
+  GtkSettings *settings;
+  const gchar *path;
+
+  gtk_init (&argc, &argv);
+
+  if (argc < 2)
+    path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
+  else
+    path = argv [1];
+
+  settings = gtk_settings_get_default ();
+  g_object_set (settings, "gtk-application-prefer-dark-theme", TRUE, NULL);
+
+  window = g_object_new (GTK_TYPE_WINDOW, NULL);
+  scroller = g_object_new (GTK_TYPE_SCROLLED_WINDOW,
+                           "visible", TRUE,
+                           NULL);
+  gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (scroller));
+  fill_box = g_object_new (EGG_TYPE_FILL_BOX,
+                           "visible", TRUE,
+                           NULL);
+  gtk_container_add (GTK_CONTAINER (scroller), GTK_WIDGET (fill_box));
+  load_directory (fill_box, path);
+  g_signal_connect (window, "delete-event", gtk_main_quit, NULL);
+  gtk_window_present (window);
+  gtk_main ();
+
+  return 0;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]