diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/gtkext/hexview.c | 349 | ||||
| -rw-r--r-- | src/gtkext/hexview.css | 10 | ||||
| -rw-r--r-- | src/gtkext/hexview.ui | 2 | 
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> | 
