[gimp] app: create a concept of "blink scenario" to blink several widget in…



commit 60a9c9007447ed04b139fcb4cd0b60580318e753
Author: Jehan <jehan girinstud io>
Date:   Sat Mar 5 17:29:44 2022 +0100

    app: create a concept of "blink scenario" to blink several widget in…
    
    … a given order, not at the same time.
    
    This will be used for the release item notifications to show people
    where new or changed features are, but in an ordered blink scenario. For
    instance: select a tool first, then blink some tool icon, open the tool
    options and finally blink the specific new/changed option. I am hoping
    it would help awareness of changes (just words on a web news may make
    some features a bit foreign when not used to look in details in advanced
    options).

 app/tools/gimpbucketfilltool.c  |  2 +-
 app/widgets/gimpwidgets-utils.c | 84 +++++++++++++++++++++++++++++++++++------
 app/widgets/gimpwidgets-utils.h |  7 +++-
 3 files changed, 80 insertions(+), 13 deletions(-)
---
diff --git a/app/tools/gimpbucketfilltool.c b/app/tools/gimpbucketfilltool.c
index a8a279def3..aaffba4724 100644
--- a/app/tools/gimpbucketfilltool.c
+++ b/app/tools/gimpbucketfilltool.c
@@ -632,7 +632,7 @@ gimp_bucket_fill_tool_button_press (GimpTool            *tool,
     {
       gimp_tool_message_literal (tool, display,
                                  _("No valid line art source selected."));
-      gimp_blink_dockable (display->gimp, "gimp-tool-options", "line-art-source");
+      gimp_blink_dockable (display->gimp, "gimp-tool-options", "line-art-source", NULL);
       return;
     }
 
diff --git a/app/widgets/gimpwidgets-utils.c b/app/widgets/gimpwidgets-utils.c
index 51d301f545..71709c204a 100644
--- a/app/widgets/gimpwidgets-utils.c
+++ b/app/widgets/gimpwidgets-utils.c
@@ -71,8 +71,15 @@
 #define GIMP_TOOL_OPTIONS_GUI_FUNC_KEY "gimp-tool-options-gui-func"
 
 
+typedef struct
+{
+  GList       **blink_script;
+  const gchar  *widget_identifier;
+} BlinkData;
+
+
 static void         gimp_search_widget_rec         (GtkWidget            *widget,
-                                                    const gchar          *searched_id);
+                                                    BlinkData            *data);
 
 
 GtkWidget *
@@ -1400,8 +1407,10 @@ static gboolean
 gimp_widget_blink_timeout (GtkWidget *widget)
 {
   WidgetBlink *blink;
+  GList       *script;
 
-  blink = g_object_get_data (G_OBJECT (widget), "gimp-widget-blink");
+  blink  = g_object_get_data (G_OBJECT (widget), "gimp-widget-blink");
+  script = g_object_get_data (G_OBJECT (widget), "gimp-widget-blink-script");
 
   gimp_highlight_widget (widget, blink->counter % 2 == 1, blink->rect);
   blink->counter++;
@@ -1412,6 +1421,20 @@ gimp_widget_blink_timeout (GtkWidget *widget)
 
       g_object_set_data (G_OBJECT (widget), "gimp-widget-blink", NULL);
 
+      if (script)
+        {
+          GtkWidget *next_widget = script->data;
+
+          if (script->next)
+            g_object_set_data_full (G_OBJECT (next_widget), "gimp-widget-blink-script",
+                                    g_list_copy (script->next),
+                                    (GDestroyNotify) g_list_free);
+
+          gimp_widget_blink (next_widget);
+
+          g_object_set_data (G_OBJECT (widget), "gimp-widget-blink-script", NULL);
+        }
+
       return G_SOURCE_REMOVE;
     }
 
@@ -1442,6 +1465,28 @@ gimp_widget_blink (GtkWidget *widget)
     gimp_widget_blink_cancel (widget);
 }
 
+void
+gimp_widget_script_blink (GtkWidget  *widget,
+                          GList     **blink_scenario)
+{
+  *blink_scenario = g_list_append (*blink_scenario, widget);
+
+  while ((widget = gtk_widget_get_parent (widget)))
+    gimp_widget_blink_cancel (widget);
+}
+
+void
+gimp_blink_play_script (GList *blink_scenario)
+{
+  g_return_if_fail (g_list_length (blink_scenario) > 0);
+
+  g_object_set_data_full (G_OBJECT (blink_scenario->data),
+                          "gimp-widget-blink-script",
+                          g_list_copy (blink_scenario->next),
+                          (GDestroyNotify) g_list_free);
+  gimp_widget_blink (blink_scenario->data);
+}
+
 void
 gimp_widget_blink_rect (GtkWidget    *widget,
                         GdkRectangle *rect)
@@ -1487,6 +1532,7 @@ gimp_widget_blink_cancel (GtkWidget *widget)
  * @gimp:
  * @dockable_identifier:
  * @widget_identifier:
+ * @blink_scenario:
  *
  * This function will raise the dockable identified by
  * @dockable_identifier. The list of dockable identifiers can be found
@@ -1494,15 +1540,21 @@ gimp_widget_blink_cancel (GtkWidget *widget)
  *
  * Then it will find the widget identified by @widget_identifier. Note
  * that for propwidgets, this is usually the associated property name.
- * Finally it will blink this widget to raise attention.
+ *
+ * Finally it will either blink this widget immediately to raise
+ * attention, or add it to the @blink_scenario if not %NULL. The blink
+ * scenario must be explicitly started with gimp_blink_play_script()
+ * when ready.
  */
 void
-gimp_blink_dockable (Gimp        *gimp,
-                     const gchar *dockable_identifier,
-                     const gchar *widget_identifier)
+gimp_blink_dockable (Gimp         *gimp,
+                     const gchar  *dockable_identifier,
+                     const gchar  *widget_identifier,
+                     GList       **blink_scenario)
 {
   GtkWidget  *dockable;
   GdkMonitor *monitor;
+  BlinkData  *data;
 
   g_return_if_fail (GIMP_IS_GIMP (gimp));
 
@@ -1518,9 +1570,13 @@ gimp_blink_dockable (Gimp        *gimp,
   if (! dockable)
     return;
 
+  data = g_slice_new (BlinkData);
+  data->blink_script      = blink_scenario;
+  data->widget_identifier = widget_identifier;
   gtk_container_foreach (GTK_CONTAINER (dockable),
                          (GtkCallback) gimp_search_widget_rec,
-                         (gpointer) widget_identifier);
+                         (gpointer) data);
+  g_slice_free (BlinkData, data);
 }
 
 /**
@@ -2035,9 +2091,12 @@ gimp_widget_flush_expose (void)
 /*  private functions  */
 
 static void
-gimp_search_widget_rec (GtkWidget   *widget,
-                        const gchar *searched_id)
+gimp_search_widget_rec (GtkWidget *widget,
+                        BlinkData *data)
 {
+  GList       **blink_script = data->blink_script;
+  const gchar  *searched_id  = data->widget_identifier;
+
   if (gtk_widget_is_visible (widget))
     {
       const gchar *id;
@@ -2056,13 +2115,16 @@ gimp_search_widget_rec (GtkWidget   *widget,
            * useless when this happens.
            */
           gtk_widget_grab_focus (widget);
-          gimp_widget_blink (widget);
+          if (blink_script)
+            gimp_widget_script_blink (widget, blink_script);
+          else
+            gimp_widget_blink (widget);
         }
       else if (GTK_IS_CONTAINER (widget))
         {
           gtk_container_foreach (GTK_CONTAINER (widget),
                                  (GtkCallback) gimp_search_widget_rec,
-                                 (gpointer) searched_id);
+                                 (gpointer) data);
         }
     }
 }
diff --git a/app/widgets/gimpwidgets-utils.h b/app/widgets/gimpwidgets-utils.h
index 85a186a7bb..da70260acd 100644
--- a/app/widgets/gimpwidgets-utils.h
+++ b/app/widgets/gimpwidgets-utils.h
@@ -95,7 +95,12 @@ void              gimp_widget_blink                (GtkWidget             *widge
 void              gimp_widget_blink_cancel         (GtkWidget             *widget);
 void              gimp_blink_dockable              (Gimp                  *gimp,
                                                     const gchar           *dockable_identifier,
-                                                    const gchar           *widget_identifier);
+                                                    const gchar           *widget_identifier,
+                                                    GList               **blink_script);
+
+void              gimp_widget_script_blink         (GtkWidget            *widget,
+                                                    GList               **blink_script);
+void              gimp_blink_play_script           (GList                *blink_script);
 
 
 GtkWidget       * gimp_dock_with_window_new        (GimpDialogFactory    *factory,


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