From be1f2f147e8ce15f20ec4de439088714ffa50e8a Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 10 Sep 2014 21:02:04 +0000
Subject: Fixed and improved the rendering of view panels.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@401 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                     |   8 +
 src/gtkext/gtkbufferview.c    | 227 +++++++-----------------
 src/gtkext/gtkgraphview.c     | 159 ++++++-----------
 src/gtkext/gtkviewpanel-int.h |  21 ++-
 src/gtkext/gtkviewpanel.c     | 399 +++++++++++++++++++++++++++++++++++++-----
 5 files changed, 499 insertions(+), 315 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index fe15323..790dbc6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+14-09-10  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/gtkext/gtkbufferview.c:
+	* src/gtkext/gtkgraphview.c:
+	* src/gtkext/gtkviewpanel.c:
+	* src/gtkext/gtkviewpanel-int.h:
+	Fix and improve the rendering of view panels.
+
 14-09-08  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/core/params.c:
diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c
index 032fcf9..8e1a9c7 100644
--- a/src/gtkext/gtkbufferview.c
+++ b/src/gtkext/gtkbufferview.c
@@ -46,21 +46,15 @@ static gboolean gtk_buffer_view_focus(GtkWidget *, GtkDirectionType);
 /* Assure la gestion des clics de souris sur le composant. */
 static gboolean gtk_buffer_view_button_press(GtkWidget *, GdkEventButton *);
 
-/* Fournit la hauteur de composant requise pour un plein rendu. */
-static void gtk_buffer_view_get_preferred_height(GtkWidget *, gint *, gint *);
-
-/* Fournit la largeur de composant requise pour un plein rendu. */
-static void gtk_buffer_view_get_preferred_width(GtkWidget *, gint *, gint *);
-
-/* S'adapte à la surface concédée par le composant parent. */
-static void gtk_buffer_view_size_allocate(GtkWidget *, GtkAllocation *);
-
 /* Met à jour l'affichage de la visualisation de code buffer. */
 static gboolean gtk_buffer_view_draw(GtkWidget *, cairo_t *);
 
 /* Prend en compte une frappe de touche sur le composant. */
 static gboolean gtk_buffer_view_key_press(GtkWidget *, GdkEventKey *);
 
+/* Indique les dimensions de travail du composant d'affichage. */
+static void gtk_buffer_view_compute_requested_size(GtkBufferView *, gint *, gint *);
+
 /* Indique la position d'affichage d'une adresse donnée. */
 static bool gtk_buffer_view_get_address_coordinates(const GtkBufferView *, const vmpa2t *, gint *, gint *);
 
@@ -104,17 +98,18 @@ G_DEFINE_TYPE(GtkBufferView, gtk_buffer_view, GTK_TYPE_VIEW_PANEL)
 static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
 {
     GtkWidgetClass *widget_class;           /* Classe version Widget       */
+    GtkViewPanelClass *panel_class;         /* Classe parente              */
 
     widget_class = GTK_WIDGET_CLASS(class);
+    panel_class = GTK_VIEW_PANEL_CLASS(class);
 
     widget_class->focus = gtk_buffer_view_focus;
     widget_class->button_press_event = gtk_buffer_view_button_press;
-    widget_class->get_preferred_height = gtk_buffer_view_get_preferred_height;
-    widget_class->get_preferred_width = gtk_buffer_view_get_preferred_width;
-    widget_class->size_allocate = gtk_buffer_view_size_allocate;
     widget_class->draw = gtk_buffer_view_draw;
     widget_class->key_press_event = gtk_buffer_view_key_press;
 
+    panel_class->compute_size = (compute_requested_size)gtk_buffer_view_compute_requested_size;
+
     g_signal_new("caret-moved",
                  GTK_TYPE_BUFFER_VIEW,
                  G_SIGNAL_RUN_LAST,
@@ -325,145 +320,6 @@ void gtk_buffer_view_compute_real_coord(GtkBufferView *view, gint *x, gint *y)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : widget  = composant GTK à consulter.                         *
-*                minimal = taille minimale. [OUT]                             *
-*                natural = taille idéale. [OUT]                               *
-*                                                                             *
-*  Description : Fournit la hauteur de composant requise pour un plein rendu. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_buffer_view_get_preferred_height(GtkWidget *widget, gint *minimal, gint *natural)
-{
-    GtkBufferView *view;                    /* Autre version du composant  */
-
-    view = GTK_BUFFER_VIEW(widget);
-
-    if (view->buffer_view != NULL)
-        *minimal = g_buffer_view_get_height(view->buffer_view);
-    else
-        *minimal = 0;
-
-    *natural = *minimal;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : widget  = composant GTK à consulter.                         *
-*                minimal = taille minimale. [OUT]                             *
-*                natural = taille idéale. [OUT]                               *
-*                                                                             *
-*  Description : Fournit la largeur de composant requise pour un plein rendu. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_buffer_view_get_preferred_width(GtkWidget *widget, gint *minimal, gint *natural)
-{
-    GtkBufferView *view;                    /* Autre version du composant  */
-
-    view = GTK_BUFFER_VIEW(widget);
-
-    if (view->buffer_view != NULL)
-        *minimal = g_buffer_view_get_width(view->buffer_view,
-                                           *GTK_VIEW_PANEL(view)->display_phys,
-                                           *GTK_VIEW_PANEL(view)->display_addr,
-                                           *GTK_VIEW_PANEL(view)->display_code);
-    else
-        *minimal = 0;
-
-    *natural = *minimal;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : view       = composant GTK à mettre à jour.                  *
-*                allocation = étendue accordée à la vue.                      *
-*                                                                             *
-*  Description : S'adapte à la surface concédée par le composant parent.      *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_buffer_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
-{
-    GtkViewPanel *panel;                    /* Autre version du composant  */
-    GtkBufferView *view;                    /* Encore une autre version    */
-    gint width;                             /* Largeur de l'objet actuelle */
-    gint height;                            /* Hauteur de l'objet actuelle */
-    GtkAllocation valloc;                   /* Surface utilisable          */
-    gboolean changed;                       /* Changement de valeur ?      */
-
-    /* Mise à jour GTK */
-
-    gtk_widget_set_allocation(widget, allocation);
-
-    if (gtk_widget_get_realized(widget))
-        gdk_window_move_resize(gtk_widget_get_window(widget),
-                               allocation->x, allocation->y,
-                               allocation->width, allocation->height);
-
-    panel = GTK_VIEW_PANEL(widget);
-
-    if (panel->hadjustment == NULL || panel->vadjustment == NULL)
-        return;
-
-    view = GTK_BUFFER_VIEW(widget);
-
-    width = g_buffer_view_get_width(view->buffer_view, *panel->display_phys, *panel->display_addr, *panel->display_code);
-    height = g_buffer_view_get_height(view->buffer_view);
-
-    gtk_view_panel_compute_allocation(panel, &valloc);
-
-    /* Défilement horizontal */
-
-    gtk_adjustment_set_page_size(panel->hadjustment, valloc.width);
-    gtk_adjustment_set_step_increment(panel->hadjustment, valloc.width * 0.1);
-    gtk_adjustment_set_page_increment(panel->hadjustment, valloc.width * 0.9);
-
-    gtk_adjustment_set_upper(panel->hadjustment, MAX(width, valloc.width));
-
-    gtk_view_panel_reclamp_adjustment(panel->hadjustment, &changed);
-
-    gtk_adjustment_changed(panel->hadjustment);
-
-    if (changed)
-        gtk_adjustment_value_changed(panel->hadjustment);
-
-    /* Défilement vertical */
-
-    gtk_adjustment_set_page_size(panel->vadjustment, valloc.height);
-    gtk_adjustment_set_step_increment(panel->vadjustment, view->line_height);
-    gtk_adjustment_set_page_increment(panel->vadjustment, view->line_height * 10.0);
-
-    gtk_adjustment_set_upper(panel->vadjustment, MAX(height, valloc.height));
-
-    gtk_view_panel_reclamp_adjustment(panel->vadjustment, &changed);
-
-    gtk_adjustment_changed(panel->vadjustment);
-
-    if (changed)
-        gtk_adjustment_value_changed(panel->vadjustment);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : widget = composant GTK à redessiner.                         *
 *                cr     = contexte graphique associé à l'événement.           *
 *                                                                             *
@@ -479,38 +335,38 @@ static gboolean gtk_buffer_view_draw(GtkWidget *widget, cairo_t *cr)
 {
     GtkBufferView *view;                    /* Autre version du composant  */
     GtkViewPanel *pview;                    /* Autre version du composant  */
+    GdkWindow *window;                      /* Fenêtre à redessiner        */
     cairo_region_t *region;                 /* Région visible à redessiner */
     cairo_rectangle_int_t area;             /* Surface correspondante      */
+    GtkStyleContext *context;               /* Contexte du thème actuel    */
     gint fake_x;                            /* Abscisse virtuelle          */
     gint fake_y;                            /* Ordonnée virtuelle          */
-    GtkStyleContext *context;               /* Contexte du thème actuel    */
-    GdkRGBA color;                          /* Couleur du curseur          */
 
     view = GTK_BUFFER_VIEW(widget);
     widget = GTK_WIDGET(view);
     pview = GTK_VIEW_PANEL(widget);
 
-    region = gdk_window_get_visible_region(gtk_widget_get_window(widget));
+    window = gtk_widget_get_window(widget);
+
+    cairo_save(cr);
+    gtk_cairo_transform_to_window(cr, widget, window);
+
+    region = gdk_window_get_clip_region(window);
     cairo_region_get_extents(region, &area);
     cairo_region_destroy(region);
 
-    fake_x = 0;
-    fake_y = 0;
-    gtk_buffer_view_compute_fake_coord(view, &fake_x, &fake_y);
-
     /* Dessin de la marge gauche */
 
     context = gtk_widget_get_style_context(widget);
 
     gtk_style_context_save(context);
+
     gtk_style_context_add_class(context, GTK_STYLE_CLASS_TROUGH);
-    gtk_style_context_get_color(context, GTK_STATE_FLAG_BACKDROP | GTK_STATE_FLAG_DIR_LTR, &color);
-    gtk_style_context_restore(context);
 
-    cairo_set_source_rgb(cr, color.red, color.green, color.blue);
+    gtk_render_background (context, cr, 0, area.y, view->left_margin, 300000);
+    gtk_render_frame (context, cr, 0, area.y - 10, view->left_margin, area.height + 20);
 
-    cairo_rectangle(cr, fake_x, area.y, view->left_margin, area.y + area.height);
-    cairo_fill(cr);
+    gtk_style_context_restore(context);
 
     /* Eventuelle bordure globale */
 
@@ -519,9 +375,18 @@ static gboolean gtk_buffer_view_draw(GtkWidget *widget, cairo_t *cr)
     /* Impression du désassemblage */
 
     if (view->buffer_view != NULL)
+    {
+        fake_x = 0;
+        fake_y = 0;
+        gtk_buffer_view_compute_fake_coord(view, &fake_x, &fake_y);
+
         g_buffer_view_draw(view->buffer_view, cr, fake_x, fake_y, &area,
                            *pview->display_phys, *pview->display_addr, *pview->display_code);
 
+    }
+
+    cairo_restore(cr);
+
     return TRUE;
 
 }
@@ -574,6 +439,42 @@ static gboolean gtk_buffer_view_key_press(GtkWidget *widget, GdkEventKey *event)
 }
 
 
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view   = composant GTK à consulter.                          *
+*                width  = largeur requise à renseigner ou NULL. [OUT]         *
+*                height = hauteur requise à renseigner ou NULL. [OUT]         *
+*                                                                             *
+*  Description : Indique les dimensions de travail du composant d'affichage.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_buffer_view_compute_requested_size(GtkBufferView *view, gint *width, gint *height)
+{
+    if (width != NULL && view->buffer_view != NULL)
+        *width = g_buffer_view_get_width(view->buffer_view,
+                                         *GTK_VIEW_PANEL(view)->display_phys,
+                                         *GTK_VIEW_PANEL(view)->display_addr,
+                                         *GTK_VIEW_PANEL(view)->display_code);
+
+    if (height != NULL && view->buffer_view != NULL)
+        *height = g_buffer_view_get_height(view->buffer_view);
+
+}
+
+
+
+
+
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : view = composant GTK à consulter.                            *
diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c
index f34cf21..7919b32 100644
--- a/src/gtkext/gtkgraphview.c
+++ b/src/gtkext/gtkgraphview.c
@@ -69,18 +69,17 @@ static void gtk_graph_view_class_init(GtkGraphViewClass *);
 /* Initialise une instance d'afficheur de code en graphique. */
 static void gtk_graph_view_init(GtkGraphView *);
 
-/* Fournit la hauteur de composant requise pour un plein rendu. */
-static void gtk_graph_view_get_preferred_height(GtkWidget *, gint *, gint *);
-
-/* Fournit la largeur de composant requise pour un plein rendu. */
-static void gtk_graph_view_get_preferred_width(GtkWidget *, gint *, gint *);
-
 /* S'adapte à la surface concédée par le composant parent. */
 static void gtk_graph_view_size_allocate(GtkWidget *, GtkAllocation *);
 
 /*  Met à jour l'affichage de la vue sous forme graphique. */
 static gboolean gtk_graph_view_draw(GtkWidget *, cairo_t *, GtkGraphView *);
 
+
+/* Indique les dimensions de travail du composant d'affichage. */
+static void gtk_graph_view_compute_requested_size(GtkGraphView *, gint *, gint *);
+
+
 /* Réagit à la sélection externe d'une adresse. */
 static void gtk_graph_view_define_main_address(GtkGraphView *, vmpa_t);
 
@@ -109,7 +108,7 @@ G_DEFINE_TYPE(GtkGraphView, gtk_graph_view, GTK_TYPE_VIEW_PANEL)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : klass = classe GTK à initialiser.                            *
+*  Paramètres  : class = classe GTK à initialiser.                            *
 *                                                                             *
 *  Description : Initialise la classe générique des graphiques de code.       *
 *                                                                             *
@@ -119,16 +118,18 @@ G_DEFINE_TYPE(GtkGraphView, gtk_graph_view, GTK_TYPE_VIEW_PANEL)
 *                                                                             *
 ******************************************************************************/
 
-static void gtk_graph_view_class_init(GtkGraphViewClass *klass)
+static void gtk_graph_view_class_init(GtkGraphViewClass *class)
 {
     GtkWidgetClass *widget_class;           /* Classe version Widget       */
+    GtkViewPanelClass *panel_class;         /* Classe parente              */
 
-    widget_class = (GtkWidgetClass *)klass;
+    widget_class = GTK_WIDGET_CLASS(class);
+    panel_class = GTK_VIEW_PANEL_CLASS(class);
 
-    widget_class->get_preferred_height = gtk_graph_view_get_preferred_height;
-    widget_class->get_preferred_width = gtk_graph_view_get_preferred_width;
     widget_class->size_allocate = gtk_graph_view_size_allocate;
 
+    panel_class->compute_size = (compute_requested_size)gtk_graph_view_compute_requested_size;
+
 }
 
 
@@ -191,95 +192,6 @@ static void gtk_graph_view_init(GtkGraphView *view)
 
 
 
-
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : widget  = composant GTK à consulter.                         *
-*                minimal = taille minimale. [OUT]                             *
-*                natural = taille idéale. [OUT]                               *
-*                                                                             *
-*  Description : Fournit la hauteur de composant requise pour un plein rendu. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_graph_view_get_preferred_height(GtkWidget *widget, gint *minimal, gint *natural)
-{
-    GtkGraphView *view;                     /* Autre vision du composant   */
-    GtkRequisition requisition;             /* Taille requise              */
-    gpointer fixed_class;                   /* Classe parente              */
-
-    view = GTK_GRAPH_VIEW(widget);
-
-    if (view->layout != NULL)
-    {
-        g_graph_layout_size_request(view->layout, &requisition);
-
-        *minimal = requisition.height;
-        *natural = *minimal;
-
-    }
-
-    else
-    {
-        fixed_class = g_type_class_peek_parent(GTK_GRAPH_VIEW_GET_CLASS(widget));
-        fixed_class = g_type_class_peek_parent(fixed_class);
-
-        GTK_WIDGET_CLASS(fixed_class)->get_preferred_height(widget, minimal, natural);
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : widget  = composant GTK à consulter.                         *
-*                minimal = taille minimale. [OUT]                             *
-*                natural = taille idéale. [OUT]                               *
-*                                                                             *
-*  Description : Fournit la largeur de composant requise pour un plein rendu. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void gtk_graph_view_get_preferred_width(GtkWidget *widget, gint *minimal, gint *natural)
-{
-    GtkGraphView *view;                     /* Autre vision du composant   */
-    GtkRequisition requisition;             /* Taille requise              */
-    gpointer fixed_class;                   /* Classe parente              */
-
-    view = GTK_GRAPH_VIEW(widget);
-
-    if (view->layout != NULL)
-    {
-        g_graph_layout_size_request(view->layout, &requisition);
-
-        *minimal = requisition.width;
-        *natural = *minimal;
-
-    }
-
-    else
-    {
-        fixed_class = g_type_class_peek_parent(GTK_GRAPH_VIEW_GET_CLASS(widget));
-        fixed_class = g_type_class_peek_parent(fixed_class);
-
-        GTK_WIDGET_CLASS(fixed_class)->get_preferred_width(widget, minimal, natural);
-
-    }
-
-}
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : view       = composant GTK à mettre à jour.                  *
@@ -303,6 +215,8 @@ static void gtk_graph_view_size_allocate(GtkWidget *widget, GtkAllocation *alloc
     GdkWindow *window;                      /* Fenêtre associée au support */
     gboolean changed;                       /* Changement de valeur ?      */
 
+    return;
+
     /* Mise à jour GTK */
 
     fixed_class = g_type_class_peek_parent(GTK_GRAPH_VIEW_GET_CLASS(widget));
@@ -315,7 +229,7 @@ static void gtk_graph_view_size_allocate(GtkWidget *widget, GtkAllocation *alloc
     if (panel->hadjustment == NULL || panel->vadjustment == NULL)
         return;
 
-    gtk_view_panel_compute_allocation(panel, &valloc);
+    // !!!! moved !!! gtk_view_panel_compute_allocation(panel, &valloc);
 
     gtk_widget_get_preferred_size(widget, NULL, &req);
 
@@ -335,7 +249,7 @@ static void gtk_graph_view_size_allocate(GtkWidget *widget, GtkAllocation *alloc
 
     gtk_adjustment_set_upper(panel->hadjustment, MAX(req.width, valloc.width));
 
-    gtk_view_panel_reclamp_adjustment(panel->hadjustment, &changed);
+    // !!!! moved !!! gtk_view_panel_reclamp_adjustment(panel->hadjustment, &changed);
 
     gtk_adjustment_changed(panel->hadjustment);
 
@@ -350,7 +264,7 @@ static void gtk_graph_view_size_allocate(GtkWidget *widget, GtkAllocation *alloc
 
     gtk_adjustment_set_upper(panel->vadjustment, MAX(req.height, valloc.height));
 
-    gtk_view_panel_reclamp_adjustment(panel->vadjustment, &changed);
+    // !!!! moved !!! gtk_view_panel_reclamp_adjustment(panel->vadjustment, &changed);
 
     gtk_adjustment_changed(panel->vadjustment);
 
@@ -360,6 +274,45 @@ static void gtk_graph_view_size_allocate(GtkWidget *widget, GtkAllocation *alloc
 }
 
 
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view   = composant GTK à consulter.                          *
+*                width  = largeur requise à renseigner ou NULL. [OUT]         *
+*                height = hauteur requise à renseigner ou NULL. [OUT]         *
+*                                                                             *
+*  Description : Indique les dimensions de travail du composant d'affichage.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_graph_view_compute_requested_size(GtkGraphView *view, gint *width, gint *height)
+{
+    GtkRequisition requisition;             /* Taille requise              */
+
+    if (width != NULL && view->layout != NULL)
+    {
+        g_graph_layout_size_request(view->layout, &requisition);
+        *width = requisition.height;
+    }
+
+    if (height != NULL && view->layout != NULL)
+    {
+        g_graph_layout_size_request(view->layout, &requisition);
+        *height = requisition.height;
+    }
+
+}
+
+
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : widget = composant GTK à redessiner.                         *
diff --git a/src/gtkext/gtkviewpanel-int.h b/src/gtkext/gtkviewpanel-int.h
index 1970402..1d55bf2 100644
--- a/src/gtkext/gtkviewpanel-int.h
+++ b/src/gtkext/gtkviewpanel-int.h
@@ -33,6 +33,9 @@
 
 
 
+/* Indique les dimensions de travail du composant d'affichage. */
+typedef void (* compute_requested_size) (GtkViewPanel *, gint *, gint *);
+
 /* Prend acte de l'association d'un binaire chargé. */
 typedef void (* attach_binary_fc) (GtkViewPanel *, GLoadedBinary *, bool *, bool *);
 
@@ -57,6 +60,8 @@ struct _GtkViewPanel
 
     GtkAdjustment *hadjustment;             /* Barre de défilement horiz.  */
     GtkAdjustment *vadjustment;             /* Barre de défilement vert.   */
+    GtkScrollablePolicy hscroll_policy;     /* Politique horizontale       */           
+    GtkScrollablePolicy vscroll_policy;     /* Politique verticale         */           
 
     bool show_border;                       /* Affichage d'une bordure ?   */
 
@@ -79,14 +84,20 @@ struct _GtkViewPanelClass
 {
     GtkFixedClass parent;                   /* A laisser en premier        */
 
-};
+    compute_requested_size compute_size;    /* Calcul de la taille requise */
 
+};
 
-/* S'assure que la valeur de défilement actuelle est valable. */
-void gtk_view_panel_reclamp_adjustment(GtkAdjustment *, gboolean *);
+/* Propriétés propres au composant d'affichage */
+typedef enum _ViewPanelProps
+{
+    VPP_0,
+    VPP_HADJUSTMENT,
+    VPP_VADJUSTMENT,
+    VPP_HSCROLL_POLICY,
+    VPP_VSCROLL_POLICY
 
-/* Calcule la surface pleine utilisable pour le panneau. */
-void gtk_view_panel_compute_allocation(GtkViewPanel *, GtkAllocation *);
+} ViewPanelProps;
 
 
 
diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c
index e4e73a4..353022a 100644
--- a/src/gtkext/gtkviewpanel.c
+++ b/src/gtkext/gtkviewpanel.c
@@ -35,16 +35,46 @@ static void gtk_view_panel_class_init(GtkViewPanelClass *);
 /* Procède à l'initialisation de l'afficheur générique. */
 static void gtk_view_panel_init(GtkViewPanel *);
 
+/* Définit une propriété du composant d'affichage. */
+static void gtk_view_panel_set_property(GObject *, guint, const GValue *, GParamSpec *);
+
+/* Fournit une propriété du composant d'affichage. */
+static void gtk_view_panel_get_property(GObject *, guint, GValue *, GParamSpec *);
+
+/* Détruit un composant d'affichage. */
+static void gtk_view_panel_destroy(GtkWidget *);
+
 /* Encadre la construction graphique initiale de l'affichage. */
 static void gtk_view_panel_realize(GtkWidget *);
 
+/* S'adapte à la surface concédée par le composant parent. */
+static void gtk_view_panel_size_allocate(GtkWidget *, GtkAllocation *);
+
 /* Met à jour l'affichage du composant d'affichage. */
 static gboolean gtk_view_panel_draw(GtkWidget *, cairo_t *);
 
+/* Détermine la taille allouée pour le contenu. */
+static void gtk_view_panel_compute_allocation(GtkViewPanel *, GtkAllocation *);
+
+/* Se débarrsse d'un ajustement pour un défilement donné. */
+static void gtk_view_panel_disconnect_adjustment(GtkViewPanel *, GtkOrientation);
+
+/* S'associe à un ajustement pour un défilement donné. */
+static void gtk_view_panel_set_adjustment(GtkViewPanel *, GtkOrientation, GtkAdjustment *);
+
+/* Ajuste les paramètres de défilement du composant. */
+static void gtk_view_panel_update_adjustment(GtkViewPanel *, GtkOrientation);
+
+/* Réagit à un défilement chez une barre associée au composant.*/
+static void gtk_view_panel_adjustment_value_changed(GtkAdjustment *, GtkViewPanel *);
+
+
+
 
 
 /* Détermine le type du composant d'affichage générique. */
-G_DEFINE_TYPE(GtkViewPanel, gtk_view_panel, GTK_TYPE_FIXED)
+G_DEFINE_TYPE_WITH_CODE(GtkViewPanel, gtk_view_panel, GTK_TYPE_FIXED,
+                        G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, NULL))
 
 
 /******************************************************************************
@@ -61,11 +91,24 @@ G_DEFINE_TYPE(GtkViewPanel, gtk_view_panel, GTK_TYPE_FIXED)
 
 static void gtk_view_panel_class_init(GtkViewPanelClass *class)
 {
+    GObjectClass *gobject_class;            /* Plus haut niveau équivalent */
     GtkWidgetClass *widget_class;           /* Classe de haut niveau       */
 
+    gobject_class = G_OBJECT_CLASS(class);
     widget_class = GTK_WIDGET_CLASS(class);
 
+    gobject_class->set_property = gtk_view_panel_set_property;
+    gobject_class->get_property = gtk_view_panel_get_property;
+
+    /* Implémentation de l'interface "GtkScrollable" */
+    g_object_class_override_property(gobject_class, VPP_HADJUSTMENT, "hadjustment");
+    g_object_class_override_property(gobject_class, VPP_VADJUSTMENT, "vadjustment");
+    g_object_class_override_property(gobject_class, VPP_HSCROLL_POLICY, "hscroll-policy");
+    g_object_class_override_property(gobject_class, VPP_VSCROLL_POLICY, "vscroll-policy");
+
+    widget_class->destroy = gtk_view_panel_destroy;
     widget_class->realize = gtk_view_panel_realize;
+    widget_class->size_allocate = gtk_view_panel_size_allocate;
     widget_class->draw = gtk_view_panel_draw;
 
 }
@@ -93,10 +136,12 @@ static void gtk_view_panel_init(GtkViewPanel *panel)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : adj     = valeurs de défilement à consulter.                 *
-*                changed = note une mise à jour de valeur. [OUT]              *
+*  Paramètres  : object  = instance de composant GTK à manipuler.             *
+*                prop_id = identifiant de la propriété concernée.             *
+*                value   = valeur attribuée.                                  *
+*                pspec   = spécification de la propriété visée.               *
 *                                                                             *
-*  Description : S'assure que la valeur de défilement actuelle est valable.   *
+*  Description : Définit une propriété du composant d'affichage.              *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -104,30 +149,44 @@ static void gtk_view_panel_init(GtkViewPanel *panel)
 *                                                                             *
 ******************************************************************************/
 
-void gtk_view_panel_reclamp_adjustment(GtkAdjustment *adj, gboolean *changed)
+static void gtk_view_panel_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
-    gdouble value;                          /* Valeur actuelle             */
+    GtkViewPanel *panel;                    /* Autre vision de l'instance  */
 
-    value = gtk_adjustment_get_value(adj);
-  
-    value = CLAMP(value, 0, gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj));
+    panel = GTK_VIEW_PANEL(object);
 
-    if (value != gtk_adjustment_get_value(adj))
+    switch (prop_id)
     {
-        gtk_adjustment_set_value(adj, value);
-        *changed = TRUE;
+        case VPP_HADJUSTMENT:
+            gtk_view_panel_set_adjustment(panel, GTK_ORIENTATION_HORIZONTAL, g_value_get_object(value));
+            break;
+        case VPP_VADJUSTMENT:
+            gtk_view_panel_set_adjustment(panel, GTK_ORIENTATION_VERTICAL, g_value_get_object(value));
+            break;
+        case VPP_HSCROLL_POLICY:
+            //viewport->priv->hscroll_policy = g_value_get_enum (value);
+            //gtk_widget_queue_resize (GTK_WIDGET (viewport));
+            break;
+        case VPP_VSCROLL_POLICY:
+            //viewport->priv->vscroll_policy = g_value_get_enum (value);
+            //gtk_widget_queue_resize (GTK_WIDGET (viewport));
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+            break;
     }
-    else *changed = FALSE;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : panel = composant GTK à consulter.                           *
-*                alloc = étendue à accorder à la vue.                         *
+*  Paramètres  : object  = instance de composant GTK à manipuler.             *
+*                prop_id = identifiant de la propriété concernée.             *
+*                value   = valeur à renvoyer.                                 *
+*                pspec   = spécification de la propriété visée.               *
 *                                                                             *
-*  Description : Calcule la surface pleine utilisable pour le panneau.        *
+*  Description : Fournit une propriété du composant d'affichage.              *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -135,29 +194,56 @@ void gtk_view_panel_reclamp_adjustment(GtkAdjustment *adj, gboolean *changed)
 *                                                                             *
 ******************************************************************************/
 
-void gtk_view_panel_compute_allocation(GtkViewPanel *panel, GtkAllocation *alloc)
+static void gtk_view_panel_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
-    GtkWidget *widget;                      /* Autre version de la vue     */
-    GtkAllocation allocation;               /* Raccourci d'utilisation #1  */
-    gint border_width;                      /* Raccourci d'utilisation #2  */
-
-    widget = GTK_WIDGET(panel);
-    gtk_widget_get_allocation(widget, &allocation);
-    border_width = gtk_container_get_border_width(GTK_CONTAINER(panel));
+    GtkViewPanel *panel;                    /* Autre vision de l'instance  */
 
-    alloc->x = 0;
-    alloc->y = 0;
+    panel = GTK_VIEW_PANEL(object);
 
-    /*
-    if (viewport->shadow_type != GTK_SHADOW_NONE)
+    switch (prop_id)
     {
-        alloc->x = widget->style->xthickness;
-        alloc->y = widget->style->ythickness;
+        case VPP_HADJUSTMENT:
+            g_value_set_object(value, panel->hadjustment);
+            break;
+        case VPP_VADJUSTMENT:
+            g_value_set_object(value, panel->vadjustment);
+            break;
+        case VPP_HSCROLL_POLICY:
+            g_value_set_enum(value, panel->hscroll_policy);
+            break;
+        case VPP_VSCROLL_POLICY:
+            g_value_set_enum(value, panel->vscroll_policy);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+            break;
     }
-    */
 
-    alloc->width = MAX(1, allocation.width - alloc->x * 2 - border_width * 2);
-    alloc->height = MAX(1, allocation.height - alloc->y * 2 - border_width * 2);
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : widget = composant GTK à détruire.                           *
+*                                                                             *
+*  Description : Détruit un composant d'affichage.                            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_view_panel_destroy(GtkWidget *widget)
+{
+    GtkViewPanel *panel;                    /* Autre version du composant  */
+
+    panel = GTK_VIEW_PANEL(widget);
+
+    gtk_view_panel_disconnect_adjustment(panel, GTK_ORIENTATION_HORIZONTAL);
+    gtk_view_panel_disconnect_adjustment(panel, GTK_ORIENTATION_VERTICAL);
+
+    GTK_WIDGET_CLASS(gtk_view_panel_parent_class)->destroy(widget);
 
 }
 
@@ -180,7 +266,6 @@ static void gtk_view_panel_realize(GtkWidget *widget)
     GdkWindowAttr attributes;               /* Propriétés du composant     */
     guint attributes_mask;                  /* Masque de prise en compte   */
     GdkWindow *window;                      /* Fenêtre du composant        */
-    GdkRGBA white;                          /* Couleur de fond normale     */
 
     gtk_widget_get_allocation(widget, &allocation);
 
@@ -202,21 +287,35 @@ static void gtk_view_panel_realize(GtkWidget *widget)
                             &attributes, attributes_mask);
 
     gtk_widget_set_window(widget, window);
+    gtk_widget_register_window(widget, window);
 
-    gdk_window_set_user_data(window, widget);
+}
 
-    gdk_rgba_parse(&white, "white");
-    gtk_widget_override_background_color(widget, GTK_STATE_FLAG_NORMAL, &white);
 
-    /*
 
-    widget->style = gtk_style_attach(widget->style, widget->window);
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : view       = composant GTK à mettre à jour.                  *
+*                allocation = étendue accordée à la vue.                      *
+*                                                                             *
+*  Description : S'adapte à la surface concédée par le composant parent.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_view_panel_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
+{
+    GtkViewPanel *panel;                    /* Autre version du composant  */
+
+    GTK_WIDGET_CLASS(gtk_view_panel_parent_class)->size_allocate(widget, allocation);
 
-    gdk_color_white(gtk_widget_get_colormap(widget), &white);
-    gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &white);
+    panel = GTK_VIEW_PANEL(widget);
 
-    GTK_VIEW_PANEL(widget)->gc = gdk_gc_new(GDK_DRAWABLE(widget->window));
-    */
+    gtk_view_panel_update_adjustment(panel, GTK_ORIENTATION_HORIZONTAL);
+    gtk_view_panel_update_adjustment(panel, GTK_ORIENTATION_VERTICAL);
 
 }
 
@@ -265,6 +364,218 @@ static gboolean gtk_view_panel_draw(GtkWidget *widget, cairo_t *cr)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : panel = composant GTK à consulter.                           *
+*                alloc = emplacement à déterminer. [OUT]                      *
+*                                                                             *
+*  Description : Détermine la taille allouée pour le contenu.                 *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_view_panel_compute_allocation(GtkViewPanel *panel, GtkAllocation *alloc)
+{
+    GtkWidget *widget;                      /* Autre vision du composant   */
+    GtkAllocation allocation;               /* Emplacement du composant    */
+    GtkStyleContext *context;               /* Contexte du style           */
+    GtkStateFlags state;                    /* Etat du composant           */
+    GtkBorder padding;                      /* Espace d'un espacement      */
+    GtkBorder border;                       /* Espace d'une bordure        */
+
+    widget = GTK_WIDGET(panel);
+
+    gtk_widget_get_allocation(widget, &allocation);
+
+    context = gtk_widget_get_style_context(widget);
+    state = gtk_widget_get_state_flags(widget);
+
+    gtk_style_context_save(context);
+    gtk_style_context_add_class(context, GTK_STYLE_CLASS_FRAME);
+
+    gtk_style_context_get_padding(context, state, &padding);
+    gtk_style_context_get_border(context, state, &border);
+
+    gtk_style_context_restore(context);
+
+    /* Positions */
+
+    if (panel->show_border)
+    {
+        alloc->x = border.left;
+        alloc->y = border.top;
+    }
+    else
+    {
+        alloc->x = 0;
+        alloc->y = 0;
+    }
+
+    alloc->x += padding.left;
+    alloc->y += padding.top;
+
+    /* Dimensions */
+
+    if (panel->show_border)
+    {
+        alloc->width = MAX (1, allocation.width - alloc->x - padding.right - border.right);
+        alloc->height = MAX (1, allocation.height - alloc->y - padding.bottom - border.bottom);
+    }
+    else
+    {
+        alloc->width = MAX (1, allocation.width - alloc->x - padding.right);
+        alloc->height = MAX (1, allocation.height - alloc->y - padding.bottom);
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel       = composant GTK d'affichage à mettre à jour.     *
+*                orientation = indication sur le défilement à traiter.        *
+*                                                                             *
+*  Description : Se débarrsse d'un ajustement pour un défilement donné.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_view_panel_disconnect_adjustment(GtkViewPanel *panel, GtkOrientation orientation)
+{
+    GtkAdjustment **adjp;                   /* Ajustement à manipuler      */
+
+    adjp = orientation == GTK_ORIENTATION_HORIZONTAL ? &panel->hadjustment : &panel->vadjustment;
+
+    if (*adjp != NULL)
+    {
+        g_signal_handlers_disconnect_by_func(*adjp, gtk_view_panel_adjustment_value_changed, panel);
+        g_object_unref(G_OBJECT(*adjp));
+        *adjp = NULL;
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel       = composant GTK d'affichage à mettre à jour.     *
+*                orientation = indication sur le défilement à traiter.        *
+*                adj         = nouvel ajustement à prendre en compte.         *
+*                                                                             *
+*  Description : S'associe à un ajustement pour un défilement donné.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_view_panel_set_adjustment(GtkViewPanel *panel, GtkOrientation orientation, GtkAdjustment *adj)
+{
+    GtkAdjustment **adjp;                   /* Ajustement à manipuler      */
+
+    adjp = orientation == GTK_ORIENTATION_HORIZONTAL ? &panel->hadjustment : &panel->vadjustment;
+
+    /* S'il n'y a rien à faire... */
+    if (adj != NULL && adj == *adjp)
+        return;
+
+    if (!adj)
+        adj = gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+    gtk_view_panel_disconnect_adjustment(panel, orientation);
+
+    *adjp = adj;
+    g_object_ref_sink(adj);
+
+    gtk_view_panel_update_adjustment(panel, orientation);
+
+    g_signal_connect(adj, "value-changed", G_CALLBACK(gtk_view_panel_adjustment_value_changed), panel);
+
+    gtk_view_panel_adjustment_value_changed(adj, panel);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : panel       = composant GTK d'affichage à mettre à jour.     *
+*                orientation = indication sur le défilement à traiter.        *
+*                                                                             *
+*  Description : Ajuste les paramètres de défilement du composant.            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_view_panel_update_adjustment(GtkViewPanel *panel, GtkOrientation orientation)
+{
+    GtkAllocation allocation;               /* Emplacement du contenu      */
+    GtkAdjustment *adj;                     /* Ajustement à manipuler      */
+    gint req;                               /* Dimension requise           */
+    gint allocated;                         /* Dimension allouée           */
+
+    gtk_view_panel_compute_allocation(panel, &allocation);
+
+    if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+        adj = panel->hadjustment;
+
+        GTK_VIEW_PANEL_GET_CLASS(panel)->compute_size(panel, &req, NULL);
+        allocated = allocation.width;
+
+    }
+    else
+    {
+        adj = panel->vadjustment;
+
+        GTK_VIEW_PANEL_GET_CLASS(panel)->compute_size(panel, NULL, &req);
+        allocated = allocation.height;
+
+    }
+
+    gtk_adjustment_configure(adj, gtk_adjustment_get_value(adj),
+                             0, MAX(req, allocated),
+                             allocated * 0.1,
+                             allocated * 0.9,
+                             allocated);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : adj   = défilement dont une valeur a changé.                 *
+*                panel = panneau d'affichage concerné.                        *
+*                                                                             *
+*  Description : Réagit à un défilement chez une barre associée au composant. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_view_panel_adjustment_value_changed(GtkAdjustment *adj, GtkViewPanel *panel)
+{
+    GtkWidget *widget;                      /* Autre vision du composant   */
+
+    widget = GTK_WIDGET(panel);
+
+    if (gtk_widget_get_realized(widget))
+        gdk_window_invalidate_rect(gtk_widget_get_window(widget), NULL, false);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : panel = composant GTK à mettre à jour.                       *
 *                show  = état de l'affichage auquel parvenir.                 *
 *                                                                             *
@@ -483,7 +794,7 @@ void gtk_view_panel_scroll_to_address(GtkViewPanel *panel, const vmpa2t *addr)
     */
 
 
-    if (panel->get_coordinates(panel, addr, &x, &y))
+    if (panel->get_coordinates(panel, addr, &x, &y) && 0 /* ARG */)
     {
         viewport = gtk_widget_get_parent(GTK_WIDGET(panel));
 
-- 
cgit v0.11.2-87-g4458