[gimp/wip/animation: 331/373] plug-ins: add drag'n drop in storyboard.
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/wip/animation: 331/373] plug-ins: add drag'n drop in storyboard.
- Date: Sat, 7 Oct 2017 02:22:33 +0000 (UTC)
commit e4748834d23f87fa0d831d6a26aa19bd0f96ce8c
Author: Jehan <jehan girinstud io>
Date: Wed Jun 21 23:57:15 2017 +0200
plug-ins: add drag'n drop in storyboard.
Reorder panel by drag'n dropping them around. This also edits the order
in the actual image. This first version reloads the storyboard, which is
still kind of fast even with many dozens of layers.
Yet we will want to have a proper reordering of the GUI without full
reload at some point.
plug-ins/animation-play/animation-utils.h | 8 +
.../animation-play/widgets/animation-storyboard.c | 153 +++++++++++++++++++-
2 files changed, 159 insertions(+), 2 deletions(-)
---
diff --git a/plug-ins/animation-play/animation-utils.h b/plug-ins/animation-play/animation-utils.h
index 79c598c..30d3bf2 100755
--- a/plug-ins/animation-play/animation-utils.h
+++ b/plug-ins/animation-play/animation-utils.h
@@ -30,6 +30,14 @@
#define MAX_FRAMERATE 300.0
#define DEFAULT_FRAMERATE 24.0
+typedef enum
+{
+ ANIMATION_DND_TYPE_NONE = 0,
+ ANIMATION_DND_TYPE_PANEL = 1,
+
+ GIMP_DND_TYPE_LAST = ANIMATION_DND_TYPE_PANEL
+} AnimationDndType;
+
void total_alpha_preview (guchar *drawing_data,
guint drawing_width,
guint drawing_height);
diff --git a/plug-ins/animation-play/widgets/animation-storyboard.c
b/plug-ins/animation-play/widgets/animation-storyboard.c
index 3f2c11d..8e23376 100644
--- a/plug-ins/animation-play/widgets/animation-storyboard.c
+++ b/plug-ins/animation-play/widgets/animation-storyboard.c
@@ -51,6 +51,8 @@ struct _AnimationStoryboardPrivate
GList *panel_buttons;
GList *disposal_buttons;
GList *comments;
+
+ gint dragged_panel;
};
/* GObject handlers */
@@ -89,9 +91,26 @@ static void animation_storyboard_disposal_toggled (GtkToggleButton *but
static void animation_storyboard_button_clicked (GtkWidget *widget,
AnimationStoryboard *storyboard);
+/* Drag and drop */
+static void animation_storyboard_panel_drag_begin (GtkWidget *widget,
+ GdkDragContext *drag_context,
+ AnimationStoryboard *storyboard);
+static void animation_storyboard_panel_drag_end (GtkWidget *widget,
+ GdkDragContext *drag_context,
+ AnimationStoryboard *storyboard);
+static gboolean animation_storyboard_panel_drag_drop (GtkWidget *widget,
+ GdkDragContext *drag_context,
+ gint x,
+ gint y,
+ guint time,
+ AnimationStoryboard *storyboard);
+
/* Utils */
static void animation_storyboard_jump (AnimationStoryboard *view,
gint panel);
+static void animation_storyboard_move (AnimationStoryboard *storyboard,
+ gint from_panel,
+ gint to_panel);
G_DEFINE_TYPE (AnimationStoryboard, animation_storyboard, GTK_TYPE_SCROLLED_WINDOW)
@@ -128,6 +147,7 @@ animation_storyboard_init (AnimationStoryboard *view)
view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view,
ANIMATION_TYPE_STORYBOARD,
AnimationStoryboardPrivate);
+ view->priv->dragged_panel = -1;
}
/**** Public Functions ****/
@@ -243,6 +263,12 @@ animation_storyboard_finalize (GObject *object)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+static const GtkTargetEntry target_table[] = {
+ { "application/x-gimp-animation-panel",
+ GTK_TARGET_SAME_APP,
+ ANIMATION_DND_TYPE_PANEL }
+};
+
/* animation_storyboard_load:
* @view: the #AnimationStoryboard.
*
@@ -255,13 +281,15 @@ animation_storyboard_load (Animation *animation,
{
AnimationAnimatic *animatic = ANIMATION_ANIMATIC (animation);
GtkWidget *layout;
+ gint *orig_layers;
gint *layers;
+ gint32 orig_image_id;
gint32 image_id;
gint n_images;
gint i;
- image_id = animation_get_image_id (animation);
- image_id = gimp_image_duplicate (image_id);
+ orig_image_id = animation_get_image_id (animation);
+ image_id = gimp_image_duplicate (orig_image_id);
gimp_image_undo_disable (image_id);
/* The actual layout is the grand-child. */
@@ -289,6 +317,8 @@ animation_storyboard_load (Animation *animation,
}
/* Setting new values. */
+ orig_layers = gimp_image_get_layers (orig_image_id,
+ &n_images);
layers = gimp_image_get_layers (image_id,
&n_images);
@@ -319,6 +349,8 @@ animation_storyboard_load (Animation *animation,
GTK_EXPAND | GTK_FILL,
GTK_FILL,
1, 1);
+ g_object_set_data (G_OBJECT (panel_button), "layer-tattoo",
+ GINT_TO_POINTER (gimp_item_get_tattoo (orig_layers[i])));
g_object_set_data (G_OBJECT (panel_button), "panel-num",
GINT_TO_POINTER (panel_num));
g_signal_connect (panel_button, "clicked",
@@ -333,8 +365,29 @@ animation_storyboard_load (Animation *animation,
thumbnail = gimp_drawable_get_thumbnail (layers[i], 250, 250,
GIMP_PIXBUF_SMALL_CHECKS);
image = gtk_image_new_from_pixbuf (thumbnail);
+
+ /* Make this button a drag source. */
+ gtk_drag_source_set (panel_button, GDK_BUTTON1_MASK,
+ target_table, G_N_ELEMENTS (target_table),
+ GDK_ACTION_MOVE);
+ gtk_drag_source_set_icon_pixbuf (panel_button, thumbnail);
+
g_object_unref (thumbnail);
+ gtk_drag_dest_set (panel_button, GTK_DEST_DEFAULT_ALL,
+ target_table, G_N_ELEMENTS (target_table),
+ GDK_ACTION_MOVE);
+
+ g_signal_connect (panel_button, "drag-begin",
+ G_CALLBACK (animation_storyboard_panel_drag_begin),
+ view);
+ g_signal_connect (panel_button, "drag-end",
+ G_CALLBACK (animation_storyboard_panel_drag_end),
+ view);
+ g_signal_connect (panel_button, "drag-drop",
+ G_CALLBACK (animation_storyboard_panel_drag_drop),
+ view);
+
/* Let's align top-right, in case the storyboard gets resized
* and the image grows (the thumbnail right now stays as fixed size). */
gtk_misc_set_alignment (GTK_MISC (image), 1.0, 0.0);
@@ -440,6 +493,7 @@ animation_storyboard_load (Animation *animation,
(GCallback) animation_storyboard_stopped,
view);
g_free (layers);
+ g_free (orig_layers);
gimp_image_delete (image_id);
}
@@ -577,6 +631,67 @@ animation_storyboard_button_clicked (GtkWidget *widget,
animation_playback_jump (storyboard->priv->playback, position);
}
+/**** Drag and drop ****/
+
+static void
+animation_storyboard_panel_drag_begin (GtkWidget *widget,
+ GdkDragContext *drag_context,
+ AnimationStoryboard *storyboard)
+{
+ gpointer panel_num;
+
+ panel_num = g_object_get_data (G_OBJECT (widget), "panel-num");
+ storyboard->priv->dragged_panel = GPOINTER_TO_INT (panel_num);
+}
+
+static void
+animation_storyboard_panel_drag_end (GtkWidget *widget,
+ GdkDragContext *drag_context,
+ AnimationStoryboard *storyboard)
+{
+ storyboard->priv->dragged_panel = -1;
+}
+
+static gboolean
+animation_storyboard_panel_drag_drop (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ AnimationStoryboard *storyboard)
+{
+ gpointer panel_num;
+ GtkAllocation allocation;
+ gint panel_dest;
+
+ g_return_val_if_fail (storyboard->priv->dragged_panel >= 0, FALSE);
+
+ panel_num = g_object_get_data (G_OBJECT (widget), "panel-num");
+ gtk_widget_get_allocation (widget, &allocation);
+ if (y > allocation.height / 2)
+ {
+ panel_dest = GPOINTER_TO_INT (panel_num) + 1;
+ }
+ else
+ {
+ panel_dest = GPOINTER_TO_INT (panel_num);
+ }
+ if (storyboard->priv->dragged_panel < panel_dest)
+ {
+ panel_dest--;
+ }
+ animation_storyboard_move (storyboard,
+ storyboard->priv->dragged_panel,
+ panel_dest);
+
+ gtk_drag_finish (context, TRUE,
+ gdk_drag_context_get_selected_action (context) == GDK_ACTION_MOVE,
+ time);
+ return TRUE;
+}
+
+/**** Utils ****/
+
static void
animation_storyboard_jump (AnimationStoryboard *view,
gint panel)
@@ -602,3 +717,37 @@ animation_storyboard_jump (AnimationStoryboard *view,
show_scrolled_child (GTK_SCROLLED_WINDOW (view), button);
}
}
+
+static void
+animation_storyboard_move (AnimationStoryboard *storyboard,
+ gint from_panel,
+ gint to_panel)
+{
+ Animation *animation;
+ gint32 image_id;
+
+ animation = ANIMATION (storyboard->priv->animation);
+ image_id = animation_get_image_id (animation);
+ if (from_panel != to_panel)
+ {
+ GtkWidget *button;
+ gpointer tattoo;
+ gint32 layer;
+ gint new_position;
+
+ button = g_list_nth_data (storyboard->priv->panel_buttons,
+ from_panel);
+ tattoo = g_object_get_data (G_OBJECT (button), "layer-tattoo");
+ layer = gimp_image_get_layer_by_tattoo (image_id,
+ GPOINTER_TO_INT (tattoo));
+
+ /* Layers are ordered from top to bottom in GIMP. */
+ new_position = g_list_length (storyboard->priv->panel_buttons) - to_panel - 1;
+ gimp_image_reorder_item (image_id, layer, 0, new_position);
+
+ /* For now, do a full reload. Ugly but that's a first version.
+ * TODO: implement a saner, lighter reordering of the GUI.
+ */
+ animation_load (animation);
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]