summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2024-05-24 04:41:11 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2024-05-24 04:41:11 (GMT)
commit4da5e662a7544e8ec0b440c322f934dd8c5e4058 (patch)
tree936894dd8344348224c023dc4caab00bdcf0c306
parent6decc8c40dfaf7cb04156f1ab233cd856ed06b37 (diff)
Measure and allocate space from the GtkHexView widget code.
-rw-r--r--src/gtkext/hexview.c349
-rw-r--r--src/gtkext/hexview.css10
-rw-r--r--src/gtkext/hexview.ui2
3 files changed, 249 insertions, 112 deletions
diff --git a/src/gtkext/hexview.c b/src/gtkext/hexview.c
index 56a167d..7acf131 100644
--- a/src/gtkext/hexview.c
+++ b/src/gtkext/hexview.c
@@ -28,6 +28,7 @@
+/* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */
/* Composant d'affichage générique (instance) */
@@ -35,9 +36,23 @@ struct _GtkHexView
{
GtkWidget parent; /* A laisser en premier */
- GtkWidget *offsets; /* Affichage des positions */
- GtkWidget *hex; /* Affichage des octets brut */
- GtkWidget *ascii; /* Affichage des imprimables */
+ union
+ {
+#define _CHILDREN_COUNT 4
+
+ GtkWidget *children[_CHILDREN_COUNT];/* Sous-composants d'affichage*/
+
+ struct
+ {
+ GtkWidget *offsets; /* Affichage des positions */
+ GtkWidget *hex; /* Affichage des octets brut */
+ GtkWidget *ascii; /* Affichage des imprimables */
+ GtkWidget *vscroll; /* Barre de défilement */
+ };
+
+ };
+
+ bool need_vscrolling; /* Besoin de défilement ? */
};
@@ -63,17 +78,28 @@ static void gtk_hex_view_finalize(GtkHexView *);
-void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot);
+void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent);
+
+
+
-void demo_measure (GtkWidget *widget,
- GtkOrientation orientation,
- int for_size,
- int *minimum_size,
- int *natural_size,
- int *minimum_baseline,
- int *natural_baseline);
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Prend acte de la taille allouée au composant d'affichage. */
+static void gtk_hex_view_size_allocate(GtkWidget *, int, int, int);
+
+/* Fournit le mode de calcul pour déterminer la taille. */
+static GtkSizeRequestMode gtk_hex_view_get_request_mode(GtkWidget *);
+
+/* Fournit les mesures mainimale et idéale du composant. */
+static void gtk_hex_view_measure(GtkWidget *, GtkOrientation, int, int *, int *, int *, int *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* BASES D'UN COMPOSANT GRAPHIQUE */
+/* ---------------------------------------------------------------------------------- */
/* Détermine le type du composant d'affichage générique. */
@@ -106,8 +132,6 @@ static void gtk_hex_view_class_init(GtkHexViewClass *class)
gtk_widget_class_set_css_name(widget, "GtkHexView");
- gtk_widget_class_set_layout_manager_type(widget, GTK_TYPE_BOX_LAYOUT);
-
g_type_ensure(GTK_TYPE_COMPOSING_AREA);
gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/hexview.ui");
@@ -115,31 +139,11 @@ static void gtk_hex_view_class_init(GtkHexViewClass *class)
gtk_widget_class_bind_template_child(widget, GtkHexView, offsets);
gtk_widget_class_bind_template_child(widget, GtkHexView, hex);
gtk_widget_class_bind_template_child(widget, GtkHexView, ascii);
+ gtk_widget_class_bind_template_child(widget, GtkHexView, vscroll);
-
-
- //widget->snapshot = demo_snapshot;
-
- //widget->measure = demo_measure;
-
-
- /*
-
-
-
-
-
-
- */
-
-
- /*
- widget->destroy = gtk_hex_view_destroy;
- widget->realize = gtk_hex_view_realize;
widget->size_allocate = gtk_hex_view_size_allocate;
- widget->get_preferred_height = gtk_hex_view_get_preferred_height;
- widget->get_preferred_width = gtk_hex_view_get_preferred_width;
- */
+ widget->get_request_mode = gtk_hex_view_get_request_mode;
+ widget->measure = gtk_hex_view_measure;
}
@@ -160,24 +164,13 @@ static void gtk_hex_view_init(GtkHexView *view)
{
gtk_widget_init_template(GTK_WIDGET(view));
-
-
-
-
- g_object_set(G_OBJECT(view->offsets), "width-request", 30, NULL);
-
- g_object_set(G_OBJECT(view->ascii), "width-request", 230, NULL);
-
-
g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->offsets), demo_snapshot, GTK_WIDGET(view));
g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->hex), demo_snapshot, GTK_WIDGET(view));
g_raw_scan_cache_register_snapshot(GTK_COMPOSING_AREA(view->ascii), demo_snapshot, GTK_WIDGET(view));
-
-
-
+ view->need_vscrolling = true;
}
@@ -225,25 +218,11 @@ static void gtk_hex_view_finalize(GtkHexView *view)
-void demo_measure (GtkWidget *widget,
- GtkOrientation orientation,
- int for_size,
- int *minimum_size,
- int *natural_size,
- int *minimum_baseline,
- int *natural_baseline)
-{
- printf("set size\n");
-
- *minimum_size = 100;
- *natural_size = 200;
-}
-
-void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot)
+void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent)
{
GdkRGBA red, green, yellow, blue;
float w, h;
@@ -280,14 +259,82 @@ void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot)
-#if 0
+
+
+
+
+
+bool g_buffer_view_allocate_widths(void *ptr, int width, int height, int fill, int *out);
+
+bool g_buffer_view_allocate_widths(void *ptr, int width, int height, int fill, int *out)
+{
+
+ int i; /* Boucle de parcours */
+
+
+ for (i = 0; i < fill; i++)
+ {
+
+ if (i == 0)
+ {
+ out[0] = 40;
+ }
+
+ else if ((i + 1) == fill)
+ {
+ out[i] = width;
+ }
+
+ else
+ {
+ out[i] = 230;
+ }
+
+
+ width -= out[i];
+
+
+
+ }
+
+ return false;
+
+
+}
+
+int g_buffer_view_measure_height(void *ptr, int width);
+
+int g_buffer_view_measure_height(void *ptr, int width)
+{
+ int result; /* Mesure à retourner */
+
+ if (width == -1)
+ result = 1;
+
+ else
+ result = 5000 / width;
+
+ result *= 16;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : widget = composant GTK à examiner. *
-* minimum = largeur minimale à préciser ou NULL. [OUT] *
-* natural = largeur idéale à préciser ou NULL. [OUT] *
+* Paramètres : widget = composant GTK à examiner. *
+* width = largeur affectée au composant graphique. *
+* height = hauteur affectée au composant graphique. *
+* baseline = ligne de base affectée au composant graphique. *
* *
-* Description : Fournit la largeur idéale pour le composant d'affichage. *
+* Description : Prend acte de la taille allouée au composant d'affichage. *
* *
* Retour : - *
* *
@@ -295,82 +342,166 @@ void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot)
* *
******************************************************************************/
-static void gtk_hex_view_get_preferred_width(GtkWidget *widget, gint *minimum, gint *natural)
+static void gtk_hex_view_size_allocate(GtkWidget *widget, int width, int height, int baseline)
{
- GtkHexView *panel; /* Autre version du composant */
- gint req; /* Dimension requise */
+ GtkHexView *view; /* Version spécialisée */
+ int vscroll_width; /* Largeur idéale de la barre */
- panel = GTK_HEX_VIEW(widget);
+ GtkAllocation allocated; /* Zone allouée */
+ size_t i; /* Boucle de parcours */
+ int sub_widths[_CHILDREN_COUNT - 1]; /* Sous-largeurs calculées */
- GTK_HEX_VIEW_GET_CLASS(widget)->compute_size(panel, &req, NULL);
+ view = GTK_HEX_VIEW(widget);
- req *= panel->scale;
+ allocated.y = 0;
+ allocated.height = height;
- if (minimum != NULL) *minimum = req;
- if (natural != NULL) *natural = req;
+ /* Barre de défilement ? */
-}
+ view->need_vscrolling = g_buffer_view_allocate_widths(NULL, width, height, _CHILDREN_COUNT - 1, sub_widths);
+
+ gtk_widget_set_visible(view->vscroll, view->need_vscrolling);
+
+ if (view->need_vscrolling)
+ {
+ gtk_widget_remove_css_class(widget, "without_vscroll");
+ gtk_widget_add_css_class(widget, "with_vscroll");
+ }
+ else
+ {
+ gtk_widget_remove_css_class(widget, "with_vscroll");
+ gtk_widget_add_css_class(widget, "without_vscroll");
+ }
+
+ /**
+ * Validité de la consistence des feuilles CSS : le changement de classe
+ * ne doit pas faire évoluer les tailles.
+ */
+ assert(view->need_vscrolling == g_buffer_view_allocate_widths(NULL, width, height, _CHILDREN_COUNT - 1, sub_widths));
+
+ if (view->need_vscrolling)
+ {
+ gtk_widget_measure(view->vscroll, GTK_ORIENTATION_HORIZONTAL, height, &vscroll_width, NULL, NULL, NULL);
+
+ allocated.x = width - vscroll_width;
+ allocated.width = vscroll_width;
+
+ gtk_widget_size_allocate(view->vscroll, &allocated, baseline);
+
+ width -= vscroll_width;
+
+ }
+ /* Placement des composants d'affichage */
+ g_buffer_view_allocate_widths(NULL, width, height, _CHILDREN_COUNT - 1, sub_widths);
+
+ allocated.x = 0;
+
+ for (i = 0; i < (_CHILDREN_COUNT - 1); i++)
+ {
+ allocated.width = sub_widths[i];
+
+ gtk_widget_size_allocate(view->children[i], &allocated, baseline);
+
+ allocated.x += sub_widths[i];
+
+ }
+
+}
/******************************************************************************
* *
-* Paramètres : panel = composant GTK à venir consulter. *
-* cr = contexte graphique associé à l'événement. *
+* Paramètres : widget = composant GTK à consulter. *
* *
-* Description : Dessine si besoin est une bordure autour du composant. *
+* Description : Fournit le mode de calcul pour déterminer la taille. *
* *
-* Retour : - *
+* Retour : Mode de calcul adapté au composant graphique. *
* *
* Remarques : - *
* *
******************************************************************************/
-void gtk_hex_view_draw_border(GtkHexView *panel, cairo_t *cr)
+static GtkSizeRequestMode gtk_hex_view_get_request_mode(GtkWidget *widget)
{
- GtkWidget *widget; /* Autre version du composant */
- GtkStyleContext *context; /* Contexte du thème actuel */
- GdkRGBA color; /* Couleur de thème récupérée */
- GtkRequisition req; /* Taille allouée à l'élément */
- GtkAllocation area; /* Emplacement à considérer */
+ GtkSizeRequestMode result; /* Configuration à remonter */
- if (panel->show_border)
- {
- widget = GTK_WIDGET(panel);
+ result = GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
- gtk_widget_get_preferred_size(widget, NULL, &req);
+ return result;
- context = gtk_widget_get_style_context(widget);
+}
- gtk_style_context_save(context);
- gtk_style_context_add_class(context, GTK_STYLE_CLASS_FRAME);
+/******************************************************************************
+* *
+* Paramètres : widget = composant GTK à examiner. *
+* orientation = direction à observer pour les calculs. *
+* for_size = taille de la direction opposée. *
+* minimum = taille minimale pour le composant. [OUT] *
+* natural = taille idéale pour le composant. [OUT] *
+* min_baseline = ligne de base minimale. [OUT] *
+* nat_baseline = ligne de base idéale. [OUT] *
+* *
+* Description : Fournit les mesures mainimale et idéale du composant. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_hex_view_measure(GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *min_baseline, int *nat_baseline)
+{
+ GtkHexView *view; /* Version spécialisée */
+ int requested; /* Taille requise à priori */
+ size_t i; /* Boucle de parcours */
+ int min; /* Valeur minimale locale */
+ int nat; /* Valeur idéale locale */
- gtk_style_context_get(gtk_widget_get_style_context(widget),
- gtk_widget_get_state_flags(widget),
- GTK_STYLE_PROPERTY_COLOR, &color, NULL);
+ view = GTK_HEX_VIEW(widget);
- cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha);
+ /* Demande de hauteur minimale / idéale */
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ requested = g_buffer_view_measure_height(NULL, for_size);
- cairo_set_line_width(cr, 1.0);
+ if (minimum != NULL) *minimum = requested;
+ if (natural != NULL) *natural = requested;
- gtk_widget_get_preferred_size(GTK_WIDGET(panel), NULL, &req);
+ for (i = 0; i < _CHILDREN_COUNT; i++)
+ {
+ gtk_widget_measure(view->children[i], GTK_ORIENTATION_VERTICAL, -1, &min, &nat, NULL, NULL);
- area.x = 0;
- area.y = 0;
- area.width = req.width;
- area.height = req.height;
+ if (minimum != NULL && min > *minimum)
+ *minimum = min;
- gtk_hex_view_define_border_path(panel, cr, &area);
- cairo_stroke(cr);
+ if (natural != NULL && nat > *natural)
+ *natural = nat;
- gtk_style_context_restore(context);
+ }
}
-}
+ /* Demande de largeur minimale / idéale */
+ else
+ {
+ if (minimum != NULL) *minimum = 0;
+ if (natural != NULL) *natural = 0;
+ for (i = 0; i < _CHILDREN_COUNT; i++)
+ {
+ gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min, &nat, NULL, NULL);
+ if (minimum != NULL) *minimum += min;
+ if (natural != NULL) *natural += nat;
-#endif
+ }
+
+ }
+
+ if (min_baseline != NULL) *min_baseline = -1;
+ if (nat_baseline != NULL) *nat_baseline = -1;
+
+}
diff --git a/src/gtkext/hexview.css b/src/gtkext/hexview.css
index fdde1cc..9725509 100644
--- a/src/gtkext/hexview.css
+++ b/src/gtkext/hexview.css
@@ -17,13 +17,19 @@ GtkHexView > :not(scrollbar) {
}
-GtkHexView > :nth-last-child(2) {
+/* ASCII */
+
+GtkHexView.with_vscroll > :nth-last-child(2),
+GtkHexView.without_vscroll > :nth-last-child(1) {
padding-right: 4px;
}
-GtkHexView > :nth-last-child(4) {
+/* Offset */
+
+GtkHexView.with_vscroll > :nth-last-child(4),
+GtkHexView.without_vscroll > :nth-last-child(3) {
border-right: 1px solid @borders;
diff --git a/src/gtkext/hexview.ui b/src/gtkext/hexview.ui
index f0dd8b0..d2f6849 100644
--- a/src/gtkext/hexview.ui
+++ b/src/gtkext/hexview.ui
@@ -1,6 +1,6 @@
<interface>
<template class="GtkHexView" parent="GtkWidget">
- <property name="css-name">GtkHexView</property>
+ <property name="css-name">GtkHexView</property>
<child>
<object class="GtkComposingArea" id="offsets">
<style>