[gimp/wip/animation: 102/197] plug-ins: improve progress bar's mouse interaction.



commit 114d704e44c6c8c86fec0dc8c6c591a3ff1049c9
Author: Jehan <jehan girinstud io>
Date:   Wed Nov 16 01:57:24 2016 +0100

    plug-ins: improve progress bar's mouse interaction.
    
    The preview on hover was a terrible idea because you always move the
    pointer over and then the whole UI goes crazy. Just preview on click,
    but allow for keeping the mouse button pressed so that you can still
    easily scan through the frames in a single movement.
    One has to release the mouse over the progress bar to validate the
    position change (otherwise, it reverts to the previous position).

 plug-ins/animation-play/widgets/animation-dialog.c |  168 ++++++--------------
 1 files changed, 52 insertions(+), 116 deletions(-)
---
diff --git a/plug-ins/animation-play/widgets/animation-dialog.c 
b/plug-ins/animation-play/widgets/animation-dialog.c
index 5c97786..c369f88 100755
--- a/plug-ins/animation-play/widgets/animation-dialog.c
+++ b/plug-ins/animation-play/widgets/animation-dialog.c
@@ -65,8 +65,6 @@ struct _AnimationDialogPrivate
   AnimationPlayback *playback;
   gdouble            zoom;
 
-  gint               revert_position;
-
   /* GUI */
   GtkWidget         *play_bar;
   GtkWidget         *progress_bar;
@@ -257,18 +255,10 @@ static void        reshape_from_bitmap       (AnimationDialog  *dialog,
                                               const gchar      *bitmap);
 
 /* Progress bar interactions */
-static gboolean    progress_button           (GtkWidget        *widget,
-                                              GdkEventButton   *event,
-                                              AnimationDialog  *dialog);
-static gboolean    progress_entered          (GtkWidget        *widget,
+static gboolean    on_progress_event         (GtkWidget        *widget,
                                               GdkEvent         *event,
                                               AnimationDialog  *dialog);
-static gboolean    progress_left             (GtkWidget        *widget,
-                                              GdkEventCrossing *event,
-                                              AnimationDialog  *dialog);
 
-static void        show_goto_progress        (AnimationDialog  *dialog,
-                                              gint              frame_nb);
 static void        show_playing_progress     (AnimationDialog  *dialog);
 
 /* Utils */
@@ -327,7 +317,6 @@ animation_dialog_init (AnimationDialog *dialog)
   AnimationDialogPrivate *priv = GET_PRIVATE (dialog);
 
   priv->playback = animation_playback_new ();
-  priv->revert_position = -1;
 }
 
 /**** Public Functions ****/
@@ -755,6 +744,7 @@ animation_dialog_constructed (GObject *object)
 
   /* Progress bar. */
   priv->progress = gtk_progress_bar_new ();
+  gtk_widget_add_events (priv->progress, GDK_BUTTON_RELEASE_MASK);
   gtk_box_pack_end (GTK_BOX (priv->progress_bar), priv->progress, TRUE, TRUE, 0);
   gtk_widget_show (priv->progress);
 
@@ -762,16 +752,19 @@ animation_dialog_constructed (GObject *object)
                          GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
                          GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK);
   g_signal_connect (priv->progress, "enter-notify-event",
-                    G_CALLBACK (progress_entered),
-                    dialog);
-  g_signal_connect (priv->progress, "motion-notify-event",
-                    G_CALLBACK (progress_entered),
+                    G_CALLBACK (on_progress_event),
                     dialog);
   g_signal_connect (priv->progress, "leave-notify-event",
-                    G_CALLBACK (progress_left),
+                    G_CALLBACK (on_progress_event),
                     dialog);
   g_signal_connect (priv->progress, "button-press-event",
-                    G_CALLBACK (progress_button),
+                    G_CALLBACK (on_progress_event),
+                    dialog);
+  g_signal_connect (priv->progress, "button-release-event",
+                    G_CALLBACK (on_progress_event),
+                    dialog);
+  g_signal_connect (priv->progress, "motion-notify-event",
+                    G_CALLBACK (on_progress_event),
                     dialog);
 
   /* Start frame spin button. */
@@ -1216,13 +1209,7 @@ animation_dialog_set_animation (AnimationDialog *dialog,
                                    dialog);
 
   g_signal_handlers_block_by_func (priv->progress,
-                                   G_CALLBACK (progress_entered),
-                                   dialog);
-  g_signal_handlers_block_by_func (priv->progress,
-                                   G_CALLBACK (progress_left),
-                                   dialog);
-  g_signal_handlers_block_by_func (priv->progress,
-                                   G_CALLBACK (progress_button),
+                                   G_CALLBACK (on_progress_event),
                                    dialog);
 
   g_object_set (dialog,
@@ -1275,13 +1262,7 @@ animation_dialog_set_animation (AnimationDialog *dialog,
 
   /* Progress bar. */
   g_signal_handlers_unblock_by_func (priv->progress,
-                                     G_CALLBACK (progress_entered),
-                                     dialog);
-  g_signal_handlers_unblock_by_func (priv->progress,
-                                     G_CALLBACK (progress_left),
-                                     dialog);
-  g_signal_handlers_unblock_by_func (priv->progress,
-                                     G_CALLBACK (progress_button),
+                                     G_CALLBACK (on_progress_event),
                                      dialog);
 
   /* The right panel. */
@@ -2568,112 +2549,67 @@ reshape_from_bitmap (AnimationDialog *dialog,
 }
 
 static gboolean
-progress_button (GtkWidget       *widget,
-                 GdkEventButton  *event,
-                 AnimationDialog *dialog)
-{
-  AnimationDialogPrivate *priv = GET_PRIVATE (dialog);
-
-  /* ignore double and triple click */
-  if (event->type == GDK_BUTTON_PRESS)
-    {
-      GtkAllocation  allocation;
-      gdouble        duration;
-      gint           frame;
-
-      gtk_widget_get_allocation (widget, &allocation);
-      duration = (gdouble) animation_get_duration (priv->animation);
-
-      frame = (gint) (event->x /
-                      ((gdouble) allocation.width /
-                       ((gdouble) duration - 0.99)));
-
-      animation_playback_jump (priv->playback, frame);
-      /* Clicking set this position as the new fixed one. */
-      priv->revert_position = frame;
-    }
-
-  return FALSE;
-}
-
-static gboolean
-progress_entered (GtkWidget        *widget,
-                  GdkEvent         *event,
-                  AnimationDialog  *dialog)
+on_progress_event (GtkWidget        *widget,
+                   GdkEvent         *event,
+                   AnimationDialog  *dialog)
 {
-  AnimationDialogPrivate *priv = GET_PRIVATE (dialog);
-  GtkAllocation           allocation;
-  gdouble                 duration;
-  gint                    frame;
+  static gint             revert_position = -1;
+  static gboolean         in_progress     = FALSE;
+  AnimationDialogPrivate *priv            = GET_PRIVATE (dialog);
+  gboolean                jump;
   gint                    x;
 
+  jump = FALSE;
   switch (event->type)
     {
+    case GDK_LEAVE_NOTIFY:
+      in_progress = FALSE;
+      break;
+    case GDK_ENTER_NOTIFY:
+      in_progress = TRUE;
+      break;
     case GDK_MOTION_NOTIFY:
       x = ((GdkEventMotion*) event)->x;
+      if (revert_position >= 0)
+        jump = TRUE;
       break;
-    case GDK_ENTER_NOTIFY:
-      x = ((GdkEventCrossing*) event)->x;
-      priv->revert_position = animation_playback_get_position (priv->playback);
+    case GDK_BUTTON_PRESS:
+      x = ((GdkEventButton*) event)->x;
+      revert_position = animation_playback_get_position (priv->playback);
+      jump = TRUE;
+      break;
+    case GDK_BUTTON_RELEASE:
+      x = ((GdkEventButton*) event)->x;
+      if (in_progress)
+        jump = TRUE;
+      else
+        animation_playback_jump (priv->playback, revert_position);
+      revert_position = -1;
       break;
     default:
       /* Should not happen. */
       return FALSE;
     }
-  gtk_widget_get_allocation (widget, &allocation);
-  duration = (gdouble) animation_get_duration (priv->animation);
-
-  frame = (gint) (x / ((gdouble) allocation.width /
-                       ((gdouble) duration - 0.99)));
-
-  animation_playback_jump (priv->playback, frame);
-  show_goto_progress (dialog, frame);
 
-  return FALSE;
-}
+  if (jump)
+    {
+      GtkAllocation  allocation;
+      gdouble        duration;
+      gint           frame;
 
-static gboolean
-progress_left (GtkWidget        *widget,
-               GdkEventCrossing *event,
-               AnimationDialog  *dialog)
-{
-  AnimationDialogPrivate *priv = GET_PRIVATE (dialog);
+      gtk_widget_get_allocation (widget, &allocation);
+      duration = (gdouble) animation_get_duration (priv->animation);
 
-  if (priv->revert_position >= 0)
-    animation_playback_jump (priv->playback,
-                             priv->revert_position);
-  priv->revert_position = -1;
+      frame = (gint) (x / ((gdouble) allocation.width /
+                           ((gdouble) duration - 0.99)));
 
-  show_playing_progress (dialog);
+      animation_playback_jump (priv->playback, frame);
+    }
 
   return FALSE;
 }
 
 static void
-show_goto_progress (AnimationDialog *dialog,
-                    gint             frame)
-{
-  AnimationDialogPrivate *priv = GET_PRIVATE (dialog);
-  gchar                  *text;
-  gdouble                 framerate;
-
-  framerate = animation_get_framerate (priv->animation);
-
-  /* update the dialog's progress bar */
-  gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progress),
-                                 ((gfloat) frame /
-                                  (gfloat) (animation_get_duration (priv->animation) - 0.999)));
-
-  text = g_strdup_printf (_("Go to frame %d of %d (%.2f seconds)"),
-                          frame + 1,
-                          animation_get_duration (priv->animation),
-                          frame / framerate);
-
-  gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progress), text);
-  g_free (text);
-}
-
-static void
 show_playing_progress (AnimationDialog *dialog)
 {
   AnimationDialogPrivate *priv = GET_PRIVATE (dialog);


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