[gimp/wip/animation: 32/145] plug-ins: add a view of the image layers for cel animation.



commit de73363773099af171c92019a8de3811ff89cb6c
Author: Jehan <jehan girinstud io>
Date:   Mon Aug 8 02:22:37 2016 +0200

    plug-ins: add a view of the image layers for cel animation.

 plug-ins/animation-play/Makefile.am                |    2 +
 plug-ins/animation-play/widgets/animation-dialog.c |   57 ++-
 .../animation-play/widgets/animation-layer-view.c  |  487 ++++++++++++++++++++
 .../animation-play/widgets/animation-layer-view.h  |   56 +++
 4 files changed, 583 insertions(+), 19 deletions(-)
---
diff --git a/plug-ins/animation-play/Makefile.am b/plug-ins/animation-play/Makefile.am
index 0533e6b..9c88c64 100644
--- a/plug-ins/animation-play/Makefile.am
+++ b/plug-ins/animation-play/Makefile.am
@@ -53,6 +53,8 @@ animation_play_SOURCES = \
        widgets/animation-dialog.c              \
        widgets/animation-storyboard.h  \
        widgets/animation-storyboard.c  \
+       widgets/animation-layer-view.h  \
+       widgets/animation-layer-view.c  \
        animation-utils.h                               \
        animation-utils.c                               \
        animation-play.c
diff --git a/plug-ins/animation-play/widgets/animation-dialog.c 
b/plug-ins/animation-play/widgets/animation-dialog.c
index 232d613..f386189 100755
--- a/plug-ins/animation-play/widgets/animation-dialog.c
+++ b/plug-ins/animation-play/widgets/animation-dialog.c
@@ -32,6 +32,7 @@
 #include "core/animationanimatic.h"
 
 #include "animation-dialog.h"
+#include "animation-layer-view.h"
 #include "animation-storyboard.h"
 
 #include "libgimp/stdplugins-intl.h"
@@ -89,6 +90,7 @@ struct _AnimationDialogPrivate
 
   /* The hpaned (left is preview, right is layer list. */
   GtkWidget      *hpaned;
+  GtkWidget      *layer_list;
 
   /* The vpaned (bottom is timeline, above is preview). */
   GtkWidget      *vpaned;
@@ -1080,7 +1082,8 @@ animation_dialog_set_animation (AnimationDialog *dialog,
                                 Animation       *animation)
 {
   AnimationDialogPrivate *priv = GET_PRIVATE (dialog);
-  GtkWidget              *right_pane;
+  GtkWidget              *scrolled_win;
+  GtkWidget              *frame;
   gchar                  *text;
   gdouble                 fps;
   gint                    index;
@@ -1215,36 +1218,48 @@ animation_dialog_set_animation (AnimationDialog *dialog,
                                      G_CALLBACK (progress_button),
                                      dialog);
 
-  right_pane = gtk_paned_get_child2 (GTK_PANED (priv->hpaned));
-  if (right_pane)
-    gtk_widget_destroy (right_pane);
+  frame = gtk_paned_get_child2 (GTK_PANED (priv->hpaned));
+  if (frame)
+    {
+      gtk_widget_destroy (frame);
+      priv->layer_list = NULL;
+    }
+
+  frame = gtk_frame_new (NULL);
+  gtk_paned_pack2 (GTK_PANED (priv->hpaned), frame,
+                   TRUE, TRUE);
+  gtk_widget_show (frame);
+
+  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_container_add (GTK_CONTAINER (frame), scrolled_win);
+  gtk_widget_show (scrolled_win);
 
   if (ANIMATION_IS_ANIMATIC (animation))
     {
-      GtkWidget *scrolled_win;
-      GtkWidget *frame;
+      GtkWidget *storyboard;
 
-      /* The Storyboard view. */
-      frame = gtk_frame_new (_("Storyboard"));
-      gtk_paned_pack2 (GTK_PANED (priv->hpaned), frame,
-                       TRUE, TRUE);
-      gtk_widget_show (frame);
-
-      scrolled_win = gtk_scrolled_window_new (NULL, NULL);
-      gtk_container_add (GTK_CONTAINER (frame), scrolled_win);
-      gtk_widget_show (scrolled_win);
+      gtk_frame_set_label (GTK_FRAME (frame), _("Storyboard"));
 
-      right_pane = animation_storyboard_new (ANIMATION_ANIMATIC (animation));
+      /* The Storyboard view. */
+      storyboard = animation_storyboard_new (ANIMATION_ANIMATIC (animation));
       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win),
-                                             right_pane);
-
-      gtk_widget_show (right_pane);
+                                             storyboard);
+      gtk_widget_show (storyboard);
 
       /* The animation type box. */
       gtk_combo_box_set_active (GTK_COMBO_BOX (priv->animation_type_combo), 0);
     }
   else
     {
+      gtk_frame_set_label (GTK_FRAME (frame), _("Layers"));
+
+      /* The layer list view. */
+      priv->layer_list = animation_layer_view_new (priv->image_id);
+      gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win),
+                                             priv->layer_list);
+      animation_layer_view_refresh (ANIMATION_LAYER_VIEW (priv->layer_list));
+      gtk_widget_show (priv->layer_list);
+
       /* The animation type box. */
       gtk_combo_box_set_active (GTK_COMBO_BOX (priv->animation_type_combo), 1);
     }
@@ -1319,6 +1334,10 @@ animation_dialog_refresh (AnimationDialog *dialog)
 
       gtk_window_reshow_with_initial_size (GTK_WINDOW (dialog));
   }
+  if (priv->layer_list)
+    {
+      animation_layer_view_refresh (ANIMATION_LAYER_VIEW (priv->layer_list));
+    }
 }
 
 /* Update the tool sensitivity for playing, depending on the number of frames. */
diff --git a/plug-ins/animation-play/widgets/animation-layer-view.c 
b/plug-ins/animation-play/widgets/animation-layer-view.c
new file mode 100644
index 0000000..ef58139
--- /dev/null
+++ b/plug-ins/animation-play/widgets/animation-layer-view.c
@@ -0,0 +1,487 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * animation-layer_view.c
+ * Copyright (C) 2015 Jehan <jehan gimp org>
+ *
+ * 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 "config.h"
+
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "libgimp/stdplugins-intl.h"
+
+#include "animation-layer-view.h"
+
+/* Properties. */
+enum
+{
+  PROP_0,
+  PROP_IMAGE
+};
+
+/* Tree model rows. */
+enum
+{
+  COLUMN_LAYER_ID,
+  COLUMN_LAYER_NAME,
+  COLUMN_SIZE
+};
+
+/* Signals. */
+enum
+{
+  LAYER_SELECTION,
+  LAST_SIGNAL
+};
+
+struct _AnimationLayerViewPrivate
+{
+  gint32 image_id;
+};
+
+/* GObject handlers */
+static void animation_layer_view_constructed  (GObject      *object);
+static void animation_layer_view_set_property (GObject      *object,
+                                               guint         property_id,
+                                               const GValue *value,
+                                               GParamSpec   *pspec);
+static void animation_layer_view_get_property (GObject      *object,
+                                               guint         property_id,
+                                               GValue       *value,
+                                               GParamSpec   *pspec);
+
+/* GtkWidget handlers */
+static gboolean animation_layer_view_button_press (GtkWidget          *widget,
+                                                   GdkEventButton     *event);
+
+/* Utils */
+static void          animation_layer_view_fill    (AnimationLayerView *view,
+                                                   GtkTreeStore       *store,
+                                                   gint                parent_layer,
+                                                   GtkTreeIter        *parent);
+static GtkTreePath * animation_layer_view_get_row (AnimationLayerView *view,
+                                                   gint                layer_id,
+                                                   GtkTreeIter        *parent);
+
+/* Signal handlers */
+static void          on_selection_changed         (GtkTreeSelection   *selection,
+                                                   AnimationLayerView *view);
+
+G_DEFINE_TYPE (AnimationLayerView, animation_layer_view, GTK_TYPE_TREE_VIEW)
+
+#define parent_class animation_layer_view_parent_class
+
+static guint   animation_layer_view_signals[LAST_SIGNAL] = { 0 };
+
+static void
+animation_layer_view_class_init (AnimationLayerViewClass *klass)
+{
+  GObjectClass   *object_class     = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class     = GTK_WIDGET_CLASS (klass);
+
+  /**
+   * AnimationLayerView::layer-selection:
+   * @layer_view: the widget which received the signal.
+   * @layers: the #GList of layer ids which are currently selected.
+   *
+   * The ::layer-selection signal is emitted each time the selection changes
+   * in @layer_view.
+   */
+  animation_layer_view_signals[LAYER_SELECTION] =
+    g_signal_new ("layer-selection",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  0,
+                  NULL, NULL,
+                  NULL,
+                  G_TYPE_NONE,
+                  1,
+                  G_TYPE_POINTER);
+
+  object_class->constructed  = animation_layer_view_constructed;
+  object_class->get_property = animation_layer_view_get_property;
+  object_class->set_property = animation_layer_view_set_property;
+
+  widget_class->button_press_event = animation_layer_view_button_press;
+
+  /**
+   * AnimationLayerView:animation:
+   *
+   * The associated #GimpImage id.
+   */
+  g_object_class_install_property (object_class, PROP_IMAGE,
+                                   g_param_spec_int ("image", NULL, NULL,
+                                                     0, G_MAXINT, 0,
+                                                     G_PARAM_READWRITE |
+                                                     G_PARAM_CONSTRUCT_ONLY));
+
+  g_type_class_add_private (klass, sizeof (AnimationLayerViewPrivate));
+}
+
+static void
+animation_layer_view_init (AnimationLayerView *view)
+{
+  view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view,
+                                            ANIMATION_TYPE_LAYER_VIEW,
+                                            AnimationLayerViewPrivate);
+
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), 0,
+                                               _("Layer"),
+                                               gtk_cell_renderer_text_new (),
+                                               "text", COLUMN_LAYER_NAME,
+                                               NULL);
+  gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (view), TRUE);
+  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
+}
+
+/************ Public Functions ****************/
+
+/**
+ * animation_layer_view_new:
+ * @image_id: the #GimpImage id.
+ *
+ * Creates a new layer view tied to @image_id, ready to be displayed.
+ */
+GtkWidget *
+animation_layer_view_new (gint32 image_id)
+{
+  GtkWidget        *layer_view;
+  GtkTreeStore     *store;
+
+  store = gtk_tree_store_new (COLUMN_SIZE, G_TYPE_INT, G_TYPE_STRING);
+
+  layer_view = g_object_new (ANIMATION_TYPE_LAYER_VIEW,
+                             "image", image_id,
+                             "model", store,
+                             NULL);
+  g_object_unref (store);
+
+  return layer_view;
+}
+
+/**
+ * animation_layer_view_refresh:
+ * @view: the #AnimationLayerView.
+ *
+ * Refresh the list of layers by reloading the #GimpImage layers.
+ */
+void
+animation_layer_view_refresh (AnimationLayerView *view)
+{
+  GtkTreeStore *store;
+
+  store = GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (view)));
+  gtk_tree_store_clear (store);
+  animation_layer_view_fill (view, store, 0, NULL);
+}
+
+/**
+ * animation_layer_view_select:
+ * @view: the #AnimationLayerView.
+ * @layers: a #GList of #GimpLayer ids.
+ *
+ * Selects the rows for all @layers in @view.
+ */
+void
+animation_layer_view_select (AnimationLayerView *view,
+                             const GList        *layers)
+{
+  GtkTreeSelection *selection;
+  const GList      *layer;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
+  g_signal_handlers_block_by_func (selection,
+                                   G_CALLBACK (on_selection_changed),
+                                   view);
+  gtk_tree_selection_unselect_all (selection);
+  for (layer = layers; layer; layer = layer->next)
+    {
+      GtkTreePath *path;
+      gint         layer_id = GPOINTER_TO_INT (layer->data);
+      
+      path = animation_layer_view_get_row (view, layer_id, NULL);
+      g_warn_if_fail (path != NULL);
+      if (path)
+        {
+          gtk_tree_selection_select_path (selection, path);
+          gtk_tree_path_free (path);
+        }
+    }
+  g_signal_handlers_unblock_by_func (selection,
+                                     G_CALLBACK (on_selection_changed),
+                                     view);
+}
+
+/************ Private Functions ****************/
+
+static void
+animation_layer_view_constructed (GObject *object)
+{
+  GtkTreeView      *view = GTK_TREE_VIEW (object);
+  GtkTreeSelection *selection;
+
+  selection = gtk_tree_view_get_selection (view);
+  gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+
+  g_signal_connect (selection, "changed",
+                    G_CALLBACK (on_selection_changed),
+                    view);
+}
+
+static void
+animation_layer_view_set_property (GObject      *object,
+                                   guint         property_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  AnimationLayerView *view = ANIMATION_LAYER_VIEW (object);
+
+  switch (property_id)
+    {
+    case PROP_IMAGE:
+      view->priv->image_id = g_value_get_int (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+animation_layer_view_get_property (GObject      *object,
+                                   guint         property_id,
+                                   GValue       *value,
+                                   GParamSpec   *pspec)
+{
+  AnimationLayerView *view = ANIMATION_LAYER_VIEW (object);
+
+  switch (property_id)
+    {
+    case PROP_IMAGE:
+      g_value_set_int (value, view->priv->image_id);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static gboolean
+animation_layer_view_button_press (GtkWidget      *widget,
+                                   GdkEventButton *event)
+{
+  GtkTreeView         *tree_view = GTK_TREE_VIEW (widget);
+  GtkTreeModel        *model;
+  GtkTreeSelection    *selection;
+  GtkTreeRowReference *reference = NULL;
+  GList               *rows;
+
+  model = gtk_tree_view_get_model (tree_view);
+  selection = gtk_tree_view_get_selection (tree_view);
+
+  rows = gtk_tree_selection_get_selected_rows (selection, &model);
+  if (g_list_length (rows) == 1)
+    {
+      reference = gtk_tree_row_reference_new (model, rows->data);
+    }
+  g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
+  g_list_free (rows);
+
+  g_signal_handlers_block_by_func (selection,
+                                   G_CALLBACK (on_selection_changed),
+                                   tree_view);
+  GTK_WIDGET_CLASS (animation_layer_view_parent_class)->button_press_event (widget, event);
+  g_signal_handlers_unblock_by_func (selection,
+                                     G_CALLBACK (on_selection_changed),
+                                     tree_view);
+
+  rows = gtk_tree_selection_get_selected_rows (selection, &model);
+  if (g_list_length (rows) == 1 && reference != NULL)
+    {
+      GtkTreePath *prev_path = gtk_tree_row_reference_get_path (reference);
+      GtkTreePath *new_path = rows->data;
+
+      /* We keep globally the same behavior as default tree view, except that
+       * when there is only 1 item selected and you click it, you unselect it.
+       * You also unselect it by clicking outside any item.
+       */
+      if (gtk_tree_path_compare (new_path, prev_path) == 0)
+        {
+          gtk_tree_selection_unselect_path (selection, new_path);
+        }
+      else
+        {
+          /* Since we blocked the signal callback, call it ourselves. */
+          on_selection_changed (selection, ANIMATION_LAYER_VIEW (widget));
+        }
+      gtk_tree_path_free (prev_path);
+      gtk_tree_row_reference_free (reference);
+    }
+  else
+    {
+      /* Since we blocked the signal callback, call it ourselves. */
+      on_selection_changed (selection, ANIMATION_LAYER_VIEW (widget));
+    }
+  g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
+  g_list_free (rows);
+
+  return TRUE;
+}
+
+/* animation_layer_view_fill:
+ * @view: the #AnimationLayerView.
+ * @store: the #GtkTreeStore to fill.
+ * @parent_layer: the parent #GimpLayer id. Set 0 for first call.
+ * @parent: %NULL to search from the first call (used for recursivity).
+ *
+ * Recursively fills @store with the #GimpLayers data of the #GimpImage
+ * tied to @view.
+ */
+static void
+animation_layer_view_fill (AnimationLayerView *view,
+                           GtkTreeStore       *store,
+                           gint                parent_layer,
+                           GtkTreeIter        *parent)
+{
+  gint        *layers;
+  gint         num_layers;
+  GtkTreeIter  iter;
+  gint         i;
+
+  if (parent_layer == 0)
+    {
+      layers = gimp_image_get_layers (view->priv->image_id,
+                                      &num_layers);
+    }
+  else
+    {
+      layers = gimp_item_get_children (parent_layer, &num_layers);
+    }
+
+  for (i = 0; i < num_layers; i++)
+    {
+      gtk_tree_store_insert (store, &iter, parent, i);
+      gtk_tree_store_set (store, &iter,
+                          COLUMN_LAYER_ID, layers[i],
+                          COLUMN_LAYER_NAME, gimp_item_get_name (layers[i]),
+                          -1);
+      if (gimp_item_is_group (layers[i]))
+        {
+          animation_layer_view_fill (view, store, layers[i], &iter);
+        }
+    }
+}
+
+/* animation_layer_view_get_row:
+ * @view: the #AnimationLayerView.
+ * @layer_id: the #GimpLayer id.
+ * @parent: %NULL to search from the first call (used for recursivity).
+ *
+ * Returns: the #GtkTreePath for the row of @layer_id, NULL if not found
+ * in @view.
+ * The returned path should be freed with gtk_tree_path_free()
+ */
+static GtkTreePath *
+animation_layer_view_get_row (AnimationLayerView *view,
+                              gint                layer_id,
+                              GtkTreeIter        *parent)
+{
+  GtkTreeModel *model;
+  GtkTreeIter   iter;
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+  if (! gtk_tree_model_iter_children (model, &iter, parent))
+    return NULL;
+
+  do
+    {
+      GtkTreePath *path;
+      GValue       value = { 0, };
+
+      gtk_tree_model_get_value (model, &iter,
+                                COLUMN_LAYER_ID,
+                                &value);
+      if (g_value_get_int (&value) == layer_id)
+        path = gtk_tree_model_get_path (model, &iter);
+
+      g_value_unset (&value);
+
+      if (path)
+        {
+          return path;
+        }
+      else if (gtk_tree_model_iter_has_child (model, &iter))
+        {
+          GtkTreePath *found_path;
+
+          found_path = animation_layer_view_get_row (view, layer_id, &iter);
+
+          if (found_path)
+            return found_path;
+        }
+    }
+  while (gtk_tree_model_iter_next (model, &iter));
+
+  return NULL;
+}
+
+static void
+on_selection_changed (GtkTreeSelection   *selection,
+                      AnimationLayerView *view)
+{
+  GtkTreeView         *tree_view = GTK_TREE_VIEW (view);
+  GList               *layers = NULL;
+  GtkTreeModel        *model;
+  GList               *rows;
+  GList               *row;
+
+  model = gtk_tree_view_get_model (tree_view);
+  rows = gtk_tree_selection_get_selected_rows (selection, &model);
+
+  for (row = rows; row; row = row->next)
+    {
+      GtkTreePath *path = row->data;
+      GtkTreeIter  iter;
+
+      if (gtk_tree_model_get_iter (model, &iter, path))
+        {
+          GValue value = { 0, };
+
+          gtk_tree_model_get_value (model, &iter,
+                                    COLUMN_LAYER_ID,
+                                    &value);
+          layers = g_list_prepend (layers,
+                                   GINT_TO_POINTER (g_value_get_int (&value)));
+          g_value_unset (&value);
+
+          gtk_tree_model_get_value (model, &iter,
+                                    COLUMN_LAYER_NAME,
+                                    &value);
+          g_value_unset (&value);
+        }
+    }
+
+  g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
+  g_list_free (rows);
+
+  g_signal_emit (view, animation_layer_view_signals[LAYER_SELECTION], 0,
+                 layers);
+  g_list_free (layers);
+}
diff --git a/plug-ins/animation-play/widgets/animation-layer-view.h 
b/plug-ins/animation-play/widgets/animation-layer-view.h
new file mode 100644
index 0000000..f20ddf4
--- /dev/null
+++ b/plug-ins/animation-play/widgets/animation-layer-view.h
@@ -0,0 +1,56 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * animation-layer_view.h
+ * Copyright (C) 2015 Jehan <jehan gimp org>
+ *
+ * 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 __ANIMATION_LAYER_VIEW_H__
+#define __ANIMATION_LAYER_VIEW_H__
+
+#define ANIMATION_TYPE_LAYER_VIEW            (animation_layer_view_get_type ())
+#define ANIMATION_LAYER_VIEW(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANIMATION_TYPE_LAYER_VIEW, 
AnimationLayerView))
+#define ANIMATION_LAYER_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ANIMATION_TYPE_LAYER_VIEW, 
AnimationLayerViewClass))
+#define ANIMATION_IS_LAYER_VIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANIMATION_TYPE_LAYER_VIEW))
+#define ANIMATION_IS_LAYER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANIMATION_TYPE_LAYER_VIEW))
+#define ANIMATION_LAYER_VIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), ANIMATION_TYPE_LAYER_VIEW, 
AnimationLayerViewClass))
+
+typedef struct _AnimationLayerView        AnimationLayerView;
+typedef struct _AnimationLayerViewClass   AnimationLayerViewClass;
+typedef struct _AnimationLayerViewPrivate AnimationLayerViewPrivate;
+
+struct _AnimationLayerView
+{
+  GtkTreeView                parent_instance;
+
+  AnimationLayerViewPrivate *priv;
+};
+
+struct _AnimationLayerViewClass
+{
+  GtkTreeViewClass  parent_class;
+};
+
+GType       animation_layer_view_get_type (void) G_GNUC_CONST;
+
+GtkWidget * animation_layer_view_new      (gint32              image_id);
+
+void        animation_layer_view_refresh  (AnimationLayerView *view);
+
+void        animation_layer_view_select   (AnimationLayerView *view,
+                                           const GList        *layers);
+#endif  /*  __ANIMATION_LAYER_VIEW_H__  */
+


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