From 738daf23eec2c114d456d13e88c51029f891fbc2 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 18 Feb 2018 23:14:12 +0100
Subject: Hidden transitions when updating panel content.

---
 ChangeLog                  |  10 +++
 src/gui/panels/errors.c    |   4 +
 src/gui/panels/errors.ui   |  45 ++++++++---
 src/gui/panels/panel-int.h |  18 +++++
 src/gui/panels/panel.c     | 183 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 250 insertions(+), 10 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b1e2410..616debb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 18-02-18  Cyrille Bagard <nocbos@gmail.com>
 
+	* src/gui/panels/errors.c:
+	* src/gui/panels/errors.ui:
+	Update code.
+
+	* src/gui/panels/panel-int.h:
+	* src/gui/panels/panel.c:
+	Hide transitions when updating panel content.
+
+18-02-18  Cyrille Bagard <nocbos@gmail.com>
+
 	* src/gui/panels/bintree.c:
 	* src/gui/panels/errors.c:
 	Update code.
diff --git a/src/gui/panels/errors.c b/src/gui/panels/errors.c
index 5b996e5..2bfe250 100644
--- a/src/gui/panels/errors.c
+++ b/src/gui/panels/errors.c
@@ -1054,6 +1054,8 @@ static void g_error_panel_introduce(const GErrorPanel *panel, unsigned int uid,
 
     /* Basculement de l'affichage hors ligne */
 
+    g_panel_item_switch_to_updating_mask(G_PANEL_ITEM(panel));
+
     builder = G_PANEL_ITEM(panel)->builder;
 
     treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
@@ -1135,4 +1137,6 @@ static void g_error_panel_conclude(GErrorPanel *panel, unsigned int uid, error_u
 
     g_object_unref(G_OBJECT(data->model));
 
+    g_panel_item_switch_to_updated_content(G_PANEL_ITEM(panel));
+
 }
diff --git a/src/gui/panels/errors.ui b/src/gui/panels/errors.ui
index 82a1a05..e5f06ac 100644
--- a/src/gui/panels/errors.ui
+++ b/src/gui/panels/errors.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
+<!-- Generated with glade 3.21.0 -->
 <interface>
   <requires lib="gtk+" version="3.20"/>
   <object class="GtkListStore" id="store">
@@ -102,22 +102,44 @@
           </packing>
         </child>
         <child>
-          <object class="GtkScrolledWindow">
+          <object class="GtkStack" id="stack">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="shadow_type">in</property>
+            <property name="can_focus">False</property>
             <child>
-              <object class="GtkTreeView" id="treeview">
+              <object class="GtkScrolledWindow" id="content">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="model">filter</property>
-                <property name="headers_visible">False</property>
-                <child internal-child="selection">
-                  <object class="GtkTreeSelection">
-                    <signal name="changed" handler="on_error_selection_changed" swapped="no"/>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="treeview">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="model">filter</property>
+                    <property name="headers_visible">False</property>
+                    <property name="search_column">1</property>
+                    <child internal-child="selection">
+                      <object class="GtkTreeSelection">
+                        <signal name="changed" handler="on_error_selection_changed" swapped="no"/>
+                      </object>
+                    </child>
                   </object>
                 </child>
               </object>
+              <packing>
+                <property name="name">page0</property>
+                <property name="title" translatable="yes">page0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinner" id="mask">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="name">page1</property>
+                <property name="title" translatable="yes">page1</property>
+                <property name="position">1</property>
+              </packing>
             </child>
           </object>
           <packing>
@@ -128,5 +150,8 @@
         </child>
       </object>
     </child>
+    <child type="titlebar">
+      <placeholder/>
+    </child>
   </object>
 </interface>
diff --git a/src/gui/panels/panel-int.h b/src/gui/panels/panel-int.h
index 0543829..98c8b79 100644
--- a/src/gui/panels/panel-int.h
+++ b/src/gui/panels/panel-int.h
@@ -37,6 +37,9 @@
 
 
 
+/* ------------------------- COEUR DES PANNEAUX D'AFFICHAGE ------------------------- */
+
+
 /* Place un panneau dans l'ensemble affiché. */
 typedef void (* ack_dock_process_fc) (GPanelItem *item);
 
@@ -74,6 +77,10 @@ struct _GPanelItem
 
     GtkBuilder *builder;                    /* Constructeur utilisé        */
 
+    cairo_surface_t *surface;               /* Copie d'écran préalable     */
+    gdouble hadj_value;                     /* Sauvegarde de défilement #1 */
+    gdouble vadj_value;                     /* Sauvegarde de défilement #2 */
+
 };
 
 /* Elément réactif pour panneaux de l'éditeur (classe) */
@@ -104,4 +111,15 @@ GtkBuilder *g_panel_item_build(GPanelItem *, const char *);
 
 
 
+/* ---------------------- MECANISMES DE MISE A JOUR DE PANNEAU ---------------------- */
+
+
+/* Bascule l'affichage d'un panneau avant sa mise à jour. */
+void g_panel_item_switch_to_updating_mask(GPanelItem *);
+
+/* Bascule l'affichage d'un panneau après sa mise à jour. */
+void g_panel_item_switch_to_updated_content(GPanelItem *);
+
+
+
 #endif  /* _GUI_PANELS_PANEL_INT_H */
diff --git a/src/gui/panels/panel.c b/src/gui/panels/panel.c
index 80de791..2a2d603 100644
--- a/src/gui/panels/panel.c
+++ b/src/gui/panels/panel.c
@@ -36,6 +36,9 @@
 
 
 
+/* ------------------------- COEUR DES PANNEAUX D'AFFICHAGE ------------------------- */
+
+
 /* Initialise la classe des éléments réactifs de l'éditeur. */
 static void g_panel_item_class_init(GPanelItemClass *);
 
@@ -65,6 +68,19 @@ static char *gtk_panel_item_build_configuration_key(const GPanelItem *, const ch
 
 
 
+/* ---------------------- MECANISMES DE MISE A JOUR DE PANNEAU ---------------------- */
+
+
+/* Présente une copie de l'affichage du composant rafraîchi. */
+static gboolean g_panel_item_draw_mask(GtkWidget *, cairo_t *, GPanelItem *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           COEUR DES PANNEAUX D'AFFICHAGE                           */
+/* ---------------------------------------------------------------------------------- */
+
+
 /* Indique le type défini pour un élément destiné à un panneau. */
 G_DEFINE_TYPE_WITH_CODE(GPanelItem, g_panel_item, G_TYPE_EDITOR_ITEM,
                         G_IMPLEMENT_INTERFACE(GTK_TYPE_DOCKABLE, g_panel_item_dockable_interface_init))
@@ -194,6 +210,9 @@ static void g_panel_item_finalize(GPanelItem *item)
 {
     free(item->path);
 
+    if (item->surface != NULL)
+        cairo_surface_destroy(item->surface);
+
     G_OBJECT_CLASS(g_panel_item_parent_class)->finalize(G_OBJECT(item));
 
 }
@@ -646,3 +665,167 @@ void g_panel_item_undock(GPanelItem *item)
         G_PANEL_ITEM_GET_CLASS(item)->ack_undock(item);
 
 }
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                        MECANISMES DE MISE A JOUR DE PANNEAU                        */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : widget = composant graphique sur lequel dessiner.            *
+*                cr     = contexte graphique pour le dessin.                  *
+*                panel = panneau ciblé par une mise à jour.                   *
+*                                                                             *
+*  Description : Présente une copie de l'affichage du composant rafraîchi.    *
+*                                                                             *
+*  Retour      : FALSE afin de poursuivre les traitements.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gboolean g_panel_item_draw_mask(GtkWidget *widget, cairo_t *cr, GPanelItem *item)
+{
+    int width;                              /* Largeur du composant actuel */
+    int height;                             /* Hauteur du composant actuel */
+
+    width = gtk_widget_get_allocated_width(widget);
+    height = gtk_widget_get_allocated_height(widget);
+
+    cairo_save(cr);
+
+    cairo_set_source_surface(cr, item->surface, 0, 0);
+    cairo_rectangle(cr, 0, 0, width, height);
+
+    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+    cairo_fill(cr);
+
+    cairo_restore(cr);
+
+    return FALSE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau ciblé par une mise à jour.                   *
+*                                                                             *
+*  Description : Bascule l'affichage d'un panneau avant sa mise à jour.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_panel_item_switch_to_updating_mask(GPanelItem *item)
+{
+    GtkWidget *content;                     /* Composant à faire évoluer   */
+    int width;                              /* Largeur du composant actuel */
+    int height;                             /* Hauteur du composant actuel */
+    cairo_t *cr;                            /* Pinceau pour les dessins    */
+    GtkAdjustment *adj;                     /* Défilement éventuel         */
+    GtkStack *stack;                        /* Pile de composants GTK      */
+    GtkWidget *mask;                        /* Masque des travaux          */
+
+    /* Copie de l'affichage courant */
+
+    content = GTK_WIDGET(gtk_builder_get_object(item->builder, "content"));
+
+    width = gtk_widget_get_allocated_width(content);
+    height = gtk_widget_get_allocated_height(content);
+
+    assert(item->surface == NULL);
+
+    item->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+
+    cr = cairo_create(item->surface);
+
+    gdk_cairo_set_source_window(cr, gtk_widget_get_window(content), 0, 0);
+
+    cairo_paint(cr);
+
+    cairo_destroy(cr);
+
+    /* Sauvegarde de l'éventuelle position */
+
+    if (GTK_IS_SCROLLED_WINDOW(content))
+    {
+        adj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(content));
+        item->hadj_value = gtk_adjustment_get_value(adj);
+
+        adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(content));
+        item->vadj_value = gtk_adjustment_get_value(adj);
+
+    }
+
+    /* Opération de basculement effectif */
+
+    stack = GTK_STACK(gtk_builder_get_object(item->builder, "stack"));
+
+    mask = GTK_WIDGET(gtk_builder_get_object(item->builder, "mask"));
+
+    gtk_spinner_start(GTK_SPINNER(mask));
+
+    g_signal_connect(mask, "draw", G_CALLBACK(g_panel_item_draw_mask), item);
+
+    gtk_stack_set_visible_child(stack, mask);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel = panneau ciblé par une mise à jour.                   *
+*                                                                             *
+*  Description : Bascule l'affichage d'un panneau après sa mise à jour.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_panel_item_switch_to_updated_content(GPanelItem *item)
+{
+    GtkWidget *content;                     /* Composant à faire évoluer   */
+    GtkAdjustment *adj;                     /* Défilement éventuel         */
+    GtkStack *stack;                        /* Pile de composants GTK      */
+    GtkWidget *mask;                        /* Masque des travaux          */
+
+    /* Restauration d'une éventuelle position */
+
+    content = GTK_WIDGET(gtk_builder_get_object(item->builder, "content"));
+
+    if (GTK_IS_SCROLLED_WINDOW(content))
+    {
+        adj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(content));
+        gtk_adjustment_set_value(adj, item->hadj_value);
+
+        adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(content));
+        gtk_adjustment_set_value(adj, item->vadj_value);
+
+    }
+
+    /* Opération de basculement effectif */
+
+    stack = GTK_STACK(gtk_builder_get_object(item->builder, "stack"));
+
+    gtk_stack_set_visible_child(stack, content);
+
+    mask = GTK_WIDGET(gtk_builder_get_object(item->builder, "mask"));
+
+    g_signal_handlers_disconnect_by_func(mask, G_CALLBACK(g_panel_item_draw_mask), item);
+
+    gtk_spinner_stop(GTK_SPINNER(mask));
+
+    /* Supression de la copie d'affichage */
+
+    cairo_surface_destroy(item->surface);
+    item->surface = NULL;
+
+}
-- 
cgit v0.11.2-87-g4458