diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2025-04-16 08:38:25 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2025-04-16 08:38:25 (GMT) |
commit | 597ccba5285e5423bfe63d010b23293b62b452d4 (patch) | |
tree | 73b783e0259f6609b282c7f3fdc6ab62245256a1 /src/gtkext/grid.c | |
parent | 91ff093198c22d474d3fe0fd6fa290d95dbffb79 (diff) |
Rewrite the tiling layout using widgets.
Diffstat (limited to 'src/gtkext/grid.c')
-rw-r--r-- | src/gtkext/grid.c | 1305 |
1 files changed, 629 insertions, 676 deletions
diff --git a/src/gtkext/grid.c b/src/gtkext/grid.c index 1b9c909..afc74b7 100644 --- a/src/gtkext/grid.c +++ b/src/gtkext/grid.c @@ -24,29 +24,43 @@ #include "grid.h" +#include <assert.h> +#include <malloc.h> +#include <string.h> + + #include "grid-int.h" +#include "helpers.h" +#include "bindings/grid-enums.h" + +/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */ -/* -------------------------- GESTION DES TUILES AFFICHEES -------------------------- */ +/* Liste des propriétés */ +typedef enum _TilingGridProperty { -#define IS_LEAF_TILE(t) \ - ({ \ - bool __result; \ - __result = GTK_IS_DOCK_STATION((t)->widget); \ - assert(__result || GTK_IS_PANED((t)->widget)); \ - __result; \ - }) + PROP_0, /* Réservé */ + PROP_LAYOUT, /* Disposition générale */ -/* Supprime une tuile de la mémoire. */ -static void delete_tile(grid_tile_t *); + PROP_EMPTY_TOP, /* Vide de la zone supérieure */ + PROP_EMPTY_LEFT, /* Vide de la zone de gauche */ + PROP_EMPTY_RIGHT, /* Vide de la zone de droite */ + PROP_EMPTY_BOTTOM, /* Vide de la zone inférieure */ + PROP_VISIBLE_TOP, /* Visibilité de zone sup. */ + PROP_VISIBLE_LEFT, /* Visibilité de zone de gauche*/ + PROP_VISIBLE_RIGHT, /* Visibilité de zone de droite*/ + PROP_VISIBLE_BOTTOM, /* Visibilité de zone inf. */ + N_PROPERTIES -/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */ +} TilingGridProperty; + +static GParamSpec *_tiling_grid_properties[N_PROPERTIES] = { NULL, }; /* Initialise la classe des conteneurs d'affichage en tuiles. */ @@ -56,48 +70,50 @@ static void gtk_tiling_grid_class_init(GtkTilingGridClass *); static void gtk_tiling_grid_init(GtkTilingGrid *); /* Supprime toutes les références externes. */ -static void gtk_tiling_grid_dispose(GtkTilingGrid *); +static void gtk_tiling_grid_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void gtk_tiling_grid_finalize(GtkTilingGrid *); +static void gtk_tiling_grid_finalize(GObject *); +/* Réagit à une intégration ou à un retrait de panneau. */ +static void gtk_tiling_grid_on_panel_un_docked(GtkDockStation *, GtkTiledPanel *, GtkTilingGrid *); +/* -------------------- REDIMENSIONNEMENT DE ZONES POUR PANNEAUX -------------------- */ -/* ---------------------------------------------------------------------------------- */ -/* GESTION DES TUILES AFFICHEES */ -/* ---------------------------------------------------------------------------------- */ +/* Initie un redimensionnement par drag-and-drop. */ +static void gtk_tiling_grid_on_gesture_drag_begin(GtkGestureDrag *, double, double, GtkTilingGrid *); -/****************************************************************************** -* * -* Paramètres : tile = tuile à supprimer. * -* * -* Description : Supprime une tuile de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ +/* Applique l'effet d'un redimensionnement drag-and-drop donné. */ +static void gtk_tiling_grid_on_gesture_drag_update(GtkTilingGrid *, TilingGridBorder, double, double); -static void delete_tile(grid_tile_t *tile) -{ - if (!IS_LEAF_TILE(tile)) - { - delete_tile(tile->children[0]); - delete_tile(tile->children[1]); - } +/* Actualise l'effet d'un redimensionnement drag-and-drop. */ +static void gtk_tiling_grid_on_top_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *); - else - free(tile->path); +/* Actualise l'effet d'un redimensionnement drag-and-drop. */ +static void gtk_tiling_grid_on_left_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *); - unref_object(tile->widget); +/* Actualise l'effet d'un redimensionnement drag-and-drop. */ +static void gtk_tiling_grid_on_right_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *); - free(tile); +/* Actualise l'effet d'un redimensionnement drag-and-drop. */ +static void gtk_tiling_grid_on_bottom_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *); -} +/* Clôture un drag-and-drop de redimensionnement. */ +static void gtk_tiling_grid_on_gesture_drag_end(GtkGestureDrag *, double, double, GtkTilingGrid *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Met à jour une propriété d'instance GObject. */ +static void gtk_tiling_grid_set_property(GObject *, guint, const GValue *, GParamSpec *); + +/* Fournit la valeur d'une propriété d'instance GObject. */ +static void gtk_tiling_grid_get_property(GObject *, guint, GValue *, GParamSpec *); @@ -107,12 +123,12 @@ static void delete_tile(grid_tile_t *tile) /* Détermine le type du conteneur d'affichage en tuiles nommées. */ -G_DEFINE_TYPE(GtkTilingGrid, gtk_tiling_grid, GTK_TYPE_WIDGET) +G_DEFINE_TYPE(GtkTilingGrid, gtk_tiling_grid, GTK_TYPE_GRID) /****************************************************************************** * * -* Paramètres : klass = classe GTK à initialiser. * +* Paramètres : class = classe GTK à initialiser. * * * * Description : Initialise la classe des conteneurs d'affichage en tuiles. * * * @@ -122,14 +138,101 @@ G_DEFINE_TYPE(GtkTilingGrid, gtk_tiling_grid, GTK_TYPE_WIDGET) * * ******************************************************************************/ -static void gtk_tiling_grid_class_init(GtkTilingGridClass *klass) +static void gtk_tiling_grid_class_init(GtkTilingGridClass *class) { GObjectClass *object; /* Autre version de la classe */ + GtkWidgetClass *widget; /* Classe de haut niveau */ + + object = G_OBJECT_CLASS(class); + + object->dispose = gtk_tiling_grid_dispose; + object->finalize = gtk_tiling_grid_finalize; + object->set_property = gtk_tiling_grid_set_property; + object->get_property = gtk_tiling_grid_get_property; + + _tiling_grid_properties[PROP_LAYOUT] = + g_param_spec_flags("layout", NULL, NULL, + LAYOUT_REACH_OPTIONS_TYPE, + LRO_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + _tiling_grid_properties[PROP_EMPTY_TOP] = + g_param_spec_boolean("empty-top", NULL, NULL, + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + _tiling_grid_properties[PROP_EMPTY_LEFT] = + g_param_spec_boolean("empty-left", NULL, NULL, + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + _tiling_grid_properties[PROP_EMPTY_RIGHT] = + g_param_spec_boolean("empty-right", NULL, NULL, + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + _tiling_grid_properties[PROP_EMPTY_BOTTOM] = + g_param_spec_boolean("empty-bottom", NULL, NULL, + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + /** + * La valeur initiale des champs suivants est à maintenir synchronisée avec + * les initialisations de gtk_tiling_grid_init(). + */ + + _tiling_grid_properties[PROP_VISIBLE_TOP] = + g_param_spec_boolean("visible-top", NULL, NULL, + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + _tiling_grid_properties[PROP_VISIBLE_LEFT] = + g_param_spec_boolean("visible-left", NULL, NULL, + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + _tiling_grid_properties[PROP_VISIBLE_RIGHT] = + g_param_spec_boolean("visible-right", NULL, NULL, + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + _tiling_grid_properties[PROP_VISIBLE_BOTTOM] = + g_param_spec_boolean("visible-bottom", NULL, NULL, + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + g_object_class_install_properties(object, N_PROPERTIES, _tiling_grid_properties); + + widget = GTK_WIDGET_CLASS(class); + + g_type_ensure(GTK_TYPE_DOCK_STATION); - object = G_OBJECT_CLASS(klass); + gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/grid.ui"); - object->dispose = (GObjectFinalizeFunc/* ! */)gtk_tiling_grid_dispose; - object->finalize = (GObjectFinalizeFunc)gtk_tiling_grid_finalize; + gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_panel_un_docked)); + gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_gesture_drag_begin)); + gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_top_gesture_drag_update)); + gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_left_gesture_drag_update)); + gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_right_gesture_drag_update)); + gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_bottom_gesture_drag_update)); + gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_gesture_drag_end)); + + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top_handle); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top_station); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left_handle); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left_station); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, main_station); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right_handle); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right_station); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom_handle); + gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom_station); + + + ///////////// g_signal_new("station-created", GTK_TYPE_TILING_GRID, @@ -144,7 +247,7 @@ static void gtk_tiling_grid_class_init(GtkTilingGridClass *klass) /****************************************************************************** * * -* Paramètres : tgrid = instance GTK à initialiser. * +* Paramètres : grid = instance GTK à initialiser. * * * * Description : Initialise une instance de conteneur d'affichage en tuiles. * * * @@ -154,18 +257,70 @@ static void gtk_tiling_grid_class_init(GtkTilingGridClass *klass) * * ******************************************************************************/ -static void gtk_tiling_grid_init(GtkTilingGrid *tgrid) +static void gtk_tiling_grid_init(GtkTilingGrid *grid) { - tgrid->tiles = NULL; + gtk_widget_init_template(GTK_WIDGET(grid)); + + grid->settings = g_settings_new_with_path("re.chrysalide.framework.tiledgrid", + "/re/chrysalide/framework/gui/tiles/"); + + g_settings_bind(grid->settings, "layout", + grid, "layout", + G_SETTINGS_BIND_DEFAULT); + + /** + * L'initialisation des champs suivants est à maintenir synchronisée avec + * les valeurs initiales de gtk_tiling_grid_class_init(). + */ + + grid->visible[TGB_TOP] = true; + grid->visible[TGB_LEFT] = true; + grid->visible[TGB_RIGHT] = true; + grid->visible[TGB_BOTTOM] = true; + + g_settings_bind(grid->settings, "top-request", + grid->top_station, "height-request", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind(grid->settings, "top-visibility", + grid, "visible-top", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind(grid->settings, "left-request", + grid->left_station, "width-request", + G_SETTINGS_BIND_DEFAULT); - tgrid->def_panel = NULL; + g_settings_bind(grid->settings, "left-visibility", + grid, "visible-left", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind(grid->settings, "right-request", + grid->right_station, "width-request", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind(grid->settings, "right-visibility", + grid, "visible-right", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind(grid->settings, "bottom-request", + grid->bottom_station, "height-request", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind(grid->settings, "bottom-visibility", + grid, "visible-bottom", + G_SETTINGS_BIND_DEFAULT); + + gtk_widget_set_cursor_from_name(grid->top_handle, "row-resize"); + gtk_widget_set_cursor_from_name(grid->left_handle, "col-resize"); + gtk_widget_set_cursor_from_name(grid->right_handle, "col-resize"); + gtk_widget_set_cursor_from_name(grid->bottom_handle, "row-resize"); } /****************************************************************************** * * -* Paramètres : grid = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -175,24 +330,24 @@ static void gtk_tiling_grid_init(GtkTilingGrid *tgrid) * * ******************************************************************************/ -static void gtk_tiling_grid_dispose(GtkTilingGrid *grid) +static void gtk_tiling_grid_dispose(GObject *object) { - if (grid->tiles != NULL) - { - delete_tile(grid->tiles); - grid->tiles = NULL; - } + GtkTilingGrid *grid; /* Version spécialisée */ + + gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_DOCK_STATION); + + grid = GTK_TILING_GRID(object); - g_clear_object(&grid->def_panel); + g_clear_object(&grid->settings); - G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->dispose(G_OBJECT(grid)); + G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : grid = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -202,9 +357,9 @@ static void gtk_tiling_grid_dispose(GtkTilingGrid *grid) * * ******************************************************************************/ -static void gtk_tiling_grid_finalize(GtkTilingGrid *grid) +static void gtk_tiling_grid_finalize(GObject *object) { - G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->finalize(G_OBJECT(grid)); + G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->finalize(object); } @@ -232,142 +387,80 @@ GtkWidget *gtk_tiling_grid_new(void) } - - - - -#if 0 - - -#include <assert.h> -#include <ctype.h> -#include <malloc.h> -#include <string.h> - - -#include "../core/logs.h" - - - -/* Valide un chemin d'accès à une tuile. */ -static bool is_valid_tile_path(const char *); - -/* Crée une tuile finale d'affichage de panneaux. */ -static grid_tile_t *create_leaf_tile(const char *, GtkTiledGrid *); - -/* Crée une tuile intermédiaire d'affichage de panneaux. */ -static grid_tile_t *create_inter_tile(grid_tile_t *, bool, grid_tile_t *, grid_tile_t *); - -/* Supprime une tuile de la mémoire. */ -//static void delete_tile(grid_tile_t *); - -/* Calcule la taille comme entre un chemin et celui d'une tuile. */ -static size_t compute_tile_score(const grid_tile_t *, const char *); - -/* Indique la tuile adaptée pour un chemin donné. */ -static grid_tile_t *find_suitable_tile(grid_tile_t **, const char *, GtkTiledGrid *); - -/* Découpe une tuile pour y insérer une zone. */ -static grid_tile_t *split_tile(grid_tile_t **, const char *, char, GtkTiledGrid *); - -/* Tente de mettre la main sur une station d'accueil. */ -static grid_tile_t *find_tile_for_widget(grid_tile_t *, GtkWidget *); - -/* Retire une moitié de tuile vide au plein profit de l'autre. */ -static void collapse_tile(grid_tile_t *, grid_tile_t *); - - - -/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */ - - - - - -/* ---------------------------------------------------------------------------------- */ -/* GESTION DES TUILES AFFICHEES */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : path = chemin destiné à sélectionner une tuile. * +* Paramètres : grid = zone d'affichage en tuiles à manipuler. * +* border = sélection de la zone à considérer. * +* visible = nouveau statut de visibilité à appliquer. * * * -* Description : Valide un chemin d'accès à une tuile. * +* Description : Affiche ou masque une zone du conteneur en tuiles. * * * -* Retour : true si le chemin est utilisable, false sinon. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool is_valid_tile_path(const char *path) +void gtk_tiling_grid_set_visible(GtkTilingGrid *grid, TilingGridBorder border, bool visible) { - bool result; /* Bilan à retourner */ - size_t len; /* Taille du chemin */ - size_t i; /* Boucle de parcours */ - char c; /* Caractère de chemin analysé */ - - /** - * M[NESWnesw]* - */ + GtkRevealer *revealer; /* Cible visée par l'opération */ + GtkDockStation *station; /* Apport d'une contrainte */ - len = strlen(path); - - result = (len >= 1); + if (grid->visible[border] != visible) + { + grid->visible[border] = visible; - if (result) - result = (path[0] == 'M'); + switch (border) + { + case TGB_TOP: + revealer = grid->top; + station = grid->top_station; + break; + + case TGB_LEFT: + revealer = grid->left; + station = grid->left_station; + break; + + case TGB_RIGHT: + revealer = grid->right; + station = grid->right_station; + break; + + case TGB_BOTTOM: + revealer = grid->bottom; + station = grid->bottom_station; + break; - for (i = 1; i < len && result; i++) - { - c = path[i]; + } - if (c == '\0') - break; + gtk_revealer_set_reveal_child(revealer, visible && !gtk_dock_station_is_empty(station)); - result = (c == 'N' || c == 'n' - || c == 'E' || c == 'e' - || c == 'S' || c == 's' - || c == 'W' || c == 'w'); + g_object_notify_by_pspec(G_OBJECT(grid), _tiling_grid_properties[PROP_VISIBLE_TOP + border]); } - return result; - } /****************************************************************************** * * -* Paramètres : path = chemin d'accès à la future tuile. * -* tgrid = conteneur d'affichage en tuiles à manipuler. * +* Paramètres : grid = zone d'affichage en tuiles à manipuler. * +* border = sélection de la zone à considérer. * * * -* Description : Crée une tuile finale d'affichage de panneaux. * +* Description : Fournit la visibilité d'une zone du conteneur en tuiles. * * * -* Retour : Structure mise en place. * +* Retour : Visibilité de la zone considérée. * * * * Remarques : - * * * ******************************************************************************/ -static grid_tile_t *create_leaf_tile(const char *path, GtkTiledGrid *tgrid) +bool gtk_tiling_grid_get_visible(GtkTilingGrid *grid, TilingGridBorder border) { - grid_tile_t *result; /* Structure à retourner */ - - result = (grid_tile_t *)malloc(sizeof(grid_tile_t)); - - result->parent = NULL; - - result->widget = gtk_dock_station_new(); - gtk_widget_show(result->widget); - - result->path = strdup(path); + bool result; /* Statut à retourner */ - result->children[0] = NULL; - result->children[1] = NULL; - - g_signal_emit_by_name(tgrid, "station-created", result->widget); + result = grid->visible[border]; return result; @@ -376,333 +469,278 @@ static grid_tile_t *create_leaf_tile(const char *path, GtkTiledGrid *tgrid) /****************************************************************************** * * -* Paramètres : parent = tuile parente ou NULL si aucune. * -* horiz = indique le type d'orientation désiré. * -* first = première tuile à intégrer. * -* second = seconde tuile à intégrer. * +* Paramètres : grid = zone d'affichage en tuiles à manipuler. * +* panel = nouveau panneau à afficher. * +* keep = indique si le panneau est à conserver présent. * * * -* Description : Crée une tuile intermédiaire d'affichage de panneaux. * +* Description : Ajoute un panneau à un conteneur en tuiles. * * * -* Retour : Structure mise en place. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static grid_tile_t *create_inter_tile(grid_tile_t *parent, bool horiz, grid_tile_t *first, grid_tile_t *second) +void gtk_tiling_grid_add_panel(GtkTilingGrid *grid, GtkTiledPanel *panel, bool keep) { - grid_tile_t *result; /* Structure à retourner */ - GtkWidget *container; /* Conteneur à vider */ - - result = (grid_tile_t *)malloc(sizeof(grid_tile_t)); - - result->parent = parent; - - if (horiz) - result->widget = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL); - else - result->widget = gtk_paned_new(GTK_ORIENTATION_VERTICAL); + char *path; /* Chemin visé par le panneau */ + bool static_path; /* Nature du chemin à traiter */ - gtk_widget_show(result->widget); + path = gtk_tiled_panel_get_path(panel); - result->path = NULL; + static_path = (path == NULL); - result->children[0] = first; - result->children[1] = second; + if (static_path) + path = ""; - /* Changement de propriétaire */ + switch (path[0]) + { + case 'N': + if (keep) + gtk_dock_station_keep_panel(grid->top_station, panel); + else + gtk_dock_station_add_panel(grid->top_station, panel); + break; - container = gtk_widget_get_parent(first->widget); + case 'W': + if (keep) + gtk_dock_station_keep_panel(grid->left_station, panel); + else + gtk_dock_station_add_panel(grid->left_station, panel); + break; - if (container != NULL) - gtk_container_remove(GTK_CONTAINER(container), first->widget); + case '\0': + case 'M': + if (keep) + gtk_dock_station_keep_panel(grid->main_station, panel); + else + gtk_dock_station_add_panel(grid->main_station, panel); + break; - g_object_ref(G_OBJECT(first->widget)); - gtk_paned_pack1(GTK_PANED(result->widget), first->widget, TRUE, FALSE); + case 'E': + if (keep) + gtk_dock_station_keep_panel(grid->right_station, panel); + else + gtk_dock_station_add_panel(grid->right_station, panel); + break; - container = gtk_widget_get_parent(second->widget); + case 'S': + if (keep) + gtk_dock_station_keep_panel(grid->bottom_station, panel); + else + gtk_dock_station_add_panel(grid->bottom_station, panel); + break; - if (container != NULL) - gtk_container_remove(GTK_CONTAINER(container), second->widget); + default: + break; - g_object_ref(G_OBJECT(second->widget)); - gtk_paned_pack2(GTK_PANED(result->widget), second->widget, TRUE, FALSE); + } - return result; + if (!static_path) + free(path); } - /****************************************************************************** * * -* Paramètres : tile = tuile à analyser. * -* path = chemin final complet recherché. * +* Paramètres : station = plateforme GTK ayant connu un changement. * +* widget = nouvel élément à intégrer. * +* grid = gestionnaire de placement en tuile concerné. * * * -* Description : Calcule la taille comme entre un chemin et celui d'une tuile.* +* Description : Réagit à une intégration ou à un retrait de panneau. * * * -* Retour : Quantité de caractères communs. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static size_t compute_tile_score(const grid_tile_t *tile, const char *path) +static void gtk_tiling_grid_on_panel_un_docked(GtkDockStation *station, GtkTiledPanel *panel, GtkTilingGrid *grid) { - size_t result; /* Nombre de points à renvoyer */ - size_t max; /* Taille du chemin de la tuile*/ - size_t i; /* Boucle de parcours */ - size_t score_0; /* Score du sous-élément #1 */ - size_t score_1; /* Score du sous-élément #2 */ + TilingGridBorder border; /* Aire concernée par l'action */ + GtkRevealer *revealer; /* Cible visée par l'opération */ + bool new_state; /* Nouveau statut d'affichage */ - if (IS_LEAF_TILE(tile)) + if (station == grid->top_station) { - max = strlen(tile->path); - - if (strlen(path) < max) - result = 0; - - else - { - result = 0; + border = TGB_TOP; + revealer = grid->top; + } - for (i = 0; i < max; i++) - { - if (tolower((unsigned char)tile->path[i]) == tolower((unsigned char)path[i])) - result++; - else - break; - } + else if (station == grid->left_station) + { + border = TGB_LEFT; + revealer = grid->left; + } - } + else if (station == grid->right_station) + { + border = TGB_RIGHT; + revealer = grid->right; + } + else if (station == grid->bottom_station) + { + border = TGB_BOTTOM; + revealer = grid->bottom; } + else - { - score_0 = compute_tile_score(tile->children[0], path); - score_1 = compute_tile_score(tile->children[1], path); + assert(false); - result = score_0 > score_1 ? score_0 : score_1; + new_state = grid->visible[border] && !gtk_dock_station_is_empty(station); - } + if (gtk_revealer_get_reveal_child(revealer) != new_state) + gtk_revealer_set_reveal_child(revealer, new_state); - return result; + /** + * On ne sait pas si l'état a réellement changé, mais on avertit + * d'une mise à jour quand même, au cas où. + */ + + g_object_notify_by_pspec(G_OBJECT(grid), _tiling_grid_properties[PROP_EMPTY_TOP + border]); } + +/* ---------------------------------------------------------------------------------- */ +/* REDIMENSIONNEMENT DE ZONES POUR PANNEAUX */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : tile = tuile ou NULL si aucune. [OUT] * -* path = chemin d'accès à la tuile visée. * -* tgrid = conteneur d'affichage en tuiles à manipuler. * +* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. * +* start_x = pointe de départ sur l'axe des abscisses. * +* start_y = pointe de départ sur l'axe des ordonnées. * +* grid = gestionnaire de placement en tuile concerné. * * * -* Description : Indique la tuile adaptée pour un chemin donné. * +* Description : Initie un redimensionnement par drag-and-drop. * * * -* Retour : Structure d'acceuil à disposition. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static grid_tile_t *find_suitable_tile(grid_tile_t **tile, const char *path, GtkTiledGrid *tgrid) +static void gtk_tiling_grid_on_gesture_drag_begin(GtkGestureDrag *gesture, double start_x, double start_y, GtkTilingGrid *grid) { - grid_tile_t *result; /* Structure à renvoyer */ - size_t best_len; /* Taille du chemin associé */ - size_t score_0; /* Score du sous-élément #1 */ - size_t score_1; /* Score du sous-élément #2 */ - char *sub_path; /* Nouvelle tentative d'accès */ - grid_tile_t **best; /* Direction à prendre */ - unsigned char next; /* Prochaine étape */ - - /* Cas d'école : appel initial */ - if (*tile == NULL) - { - assert(path[0] == 'M' && path[1] == '\0'); - - result = create_leaf_tile("M", tgrid); - *tile = result; - - } - - else - { - if (IS_LEAF_TILE(*tile)) - { - best_len = compute_tile_score(*tile, path); - - assert(best_len > 0); - - if (path[best_len] == '\0') - result = *tile; - - else - result = split_tile(tile, path, path[best_len], tgrid); - - } - - else - { - score_0 = compute_tile_score((*tile)->children[0], path); - score_1 = compute_tile_score((*tile)->children[1], path); - - assert(score_0 > 0 || score_0 > 0); - - if (score_0 == score_1) - { - sub_path = strndup(path, score_0); - - score_0 = compute_tile_score((*tile)->children[0], sub_path); - score_1 = compute_tile_score((*tile)->children[1], sub_path); + gtk_gesture_set_state(GTK_GESTURE(gesture), GTK_EVENT_SEQUENCE_CLAIMED); - free(sub_path); - - } - - if (score_0 == score_1) - result = split_tile(tile, path, path[score_0], tgrid); - - else - { - if (score_0 > score_1) - { - best = &(*tile)->children[0]; - best_len = score_0; - } - else - { - best = &(*tile)->children[1]; - best_len = score_1; - } - - /** - * Si on vient de tomber une feuille, trois cas de figure : - * - soit c'est elle qui est visée. - * - soit on veut la diviser. - * - soit on veut la diviser en englobant ses voisines. - */ - - if (IS_LEAF_TILE(*best)) - { - assert(best_len <= strlen(path)); - - next = path[best_len]; - - /* Premier cas */ - if (next == '\0') - result = *best; - - else - { - /* Second cas */ - if (islower(next)) - result = find_suitable_tile(best, path, tgrid); - - /* Troisième cas */ - else - result = split_tile(tile, path, next, tgrid); - - } - - } - - else - result = find_suitable_tile(best, path, tgrid); - - } - - } - - } - - assert(IS_LEAF_TILE(result)); - - return result; + grid->panning = true; } /****************************************************************************** * * -* Paramètres : tile = tuile à découper en deux. [OUT] * -* path = chemin d'accès à la future tuile. * -* endpoint = désignation de la zone représentée. * -* tgrid = conteneur d'affichage en tuiles à manipuler. * +* Paramètres : grid = zone d'affichage en tuiles à manipuler. * +* border = sélection de la zone à considérer. * +* offset_x = déplacement sur l'axe des abscisses. * +* offset_y = déplacement sur l'axe des ordonnées. * * * -* Description : Découpe une tuile pour y insérer une zone. * +* Description : Applique l'effet d'un redimensionnement drag-and-drop donné. * * * -* Retour : Structure fille mise en place. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static grid_tile_t *split_tile(grid_tile_t **tile, const char *path, char endpoint, GtkTiledGrid *tgrid) +static void gtk_tiling_grid_on_gesture_drag_update(GtkTilingGrid *grid, TilingGridBorder border, double offset_x, double offset_y) { - grid_tile_t *result; /* Création à retourner */ - GtkWidget *container; /* Conteneur à vider */ - grid_tile_t *new; /* Nouvelle tuile intermédiaire*/ + GtkDockStation *station; /* Station entière */ + int request; /* Taille requise */ + + /* Sélection de la poignée adaptée */ + + switch (border) + { + case TGB_TOP: + station = grid->top_station; + break; + + case TGB_LEFT: + station = grid->left_station; + break; - container = gtk_widget_get_parent((*tile)->widget); + case TGB_RIGHT: + station = grid->right_station; + break; - /* Création */ + case TGB_BOTTOM: + station = grid->bottom_station; + break; - result = create_leaf_tile(path, tgrid); + } - /* Encapsulation */ + /* Détermination d'une nouvelle position et application */ - switch (endpoint) + switch (border) { - case 'N': - case 'n': - new = create_inter_tile((*tile)->parent, false, result, *tile); + case TGB_TOP: + case TGB_BOTTOM: + g_object_get(G_OBJECT(station), "height-request", &request, NULL); break; - case 'E': - case 'e': - new = create_inter_tile((*tile)->parent, true, *tile, result); + case TGB_LEFT: + case TGB_RIGHT: + g_object_get(G_OBJECT(station), "width-request", &request, NULL); break; - case 'S': - case 's': - new = create_inter_tile((*tile)->parent, false, *tile, result); + } + + switch (border) + { + case TGB_TOP: + request += offset_y; break; - case 'W': - case 'w': - new = create_inter_tile((*tile)->parent, true, result, *tile); + case TGB_LEFT: + request += offset_x; break; - default: - assert(false); - new = NULL; + case TGB_RIGHT: + request += -offset_x; + break; + + case TGB_BOTTOM: + request += -offset_y; break; } - /* Connexions */ + if (request > 0) + { + switch (border) + { + case TGB_TOP: + case TGB_BOTTOM: + g_object_set(G_OBJECT(station), "height-request", request, NULL); + break; - *tile = new; + case TGB_LEFT: + case TGB_RIGHT: + g_object_set(G_OBJECT(station), "width-request", request, NULL); + break; - result->parent = new; + } - if (container != NULL) - { - g_object_ref(G_OBJECT(new->widget)); - gtk_container_add(GTK_CONTAINER(container), new->widget); } - return result; - } /****************************************************************************** * * -* Paramètres : tile = tuile parente, prochaine victime de promotion. * -* side = côté de tuile amené à disparaître. * +* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. * +* offset_x = déplacement sur l'axe des abscisses. * +* offset_y = déplacement sur l'axe des ordonnées. * +* grid = gestionnaire de placement en tuile concerné. * * * -* Description : Retire une moitié de tuile vide au plein profit de l'autre. * +* Description : Actualise l'effet d'un redimensionnement drag-and-drop. * * * * Retour : - * * * @@ -710,114 +748,65 @@ static grid_tile_t *split_tile(grid_tile_t **tile, const char *path, char endpoi * * ******************************************************************************/ -static void collapse_tile(grid_tile_t *tile, grid_tile_t *side) +static void gtk_tiling_grid_on_top_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid) { - grid_tile_t *promoted; /* Tuile à faire remonter */ - GtkWidget *container; /* Conteneur à vider */ - - assert(!IS_LEAF_TILE(tile)); - - /* Sélection du remplaçant */ - - if (side == tile->children[0]) - promoted = tile->children[1]; - else - promoted = tile->children[0]; - - /* Etablissement d'une place nette */ - - gtk_container_remove(GTK_CONTAINER(tile->widget), promoted->widget); - - container = gtk_widget_get_parent(tile->widget); - gtk_container_remove(GTK_CONTAINER(container), tile->widget); - - delete_tile(side); - - /* Promotion effective */ - - tile->widget = promoted->widget; - - tile->path = promoted->path; - - tile->children[0] = promoted->children[0]; - tile->children[1] = promoted->children[1]; - - g_object_ref(G_OBJECT(promoted->widget)); - gtk_container_add(GTK_CONTAINER(container), tile->widget); - - free(promoted); + gtk_tiling_grid_on_gesture_drag_update(grid, TGB_TOP, offset_x, offset_y); } /****************************************************************************** * * -* Paramètres : tile = point de départ des recherches locales. * -* widget = composant graphique à retrouver. * +* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. * +* offset_x = déplacement sur l'axe des abscisses. * +* offset_y = déplacement sur l'axe des ordonnées. * +* grid = gestionnaire de placement en tuile concerné. * * * -* Description : Tente de mettre la main sur une station d'accueil. * +* Description : Actualise l'effet d'un redimensionnement drag-and-drop. * * * -* Retour : Eventuelle tuile trouvée ou NULL. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static grid_tile_t *find_tile_for_widget(grid_tile_t *tile, GtkWidget *widget) +static void gtk_tiling_grid_on_left_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid) { - grid_tile_t *result; /* Tuile à retourner */ - - if (IS_LEAF_TILE(tile)) - result = tile->widget == widget ? tile : NULL; - - else - { - result = find_tile_for_widget(tile->children[0], widget); - - if (result == NULL) - result = find_tile_for_widget(tile->children[1], widget); - - } - - return result; + gtk_tiling_grid_on_gesture_drag_update(grid, TGB_LEFT, offset_x, offset_y); } - - /****************************************************************************** * * -* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. * +* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. * +* offset_x = déplacement sur l'axe des abscisses. * +* offset_y = déplacement sur l'axe des ordonnées. * +* grid = gestionnaire de placement en tuile concerné. * * * -* Description : Donne le panneau fourni par défaut pour la zone principale. * +* Description : Actualise l'effet d'un redimensionnement drag-and-drop. * * * -* Retour : Panneau d'affichage par défault ou NULL. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GPanelItem *gtk_tiled_grid_get_default_main_panel(const GtkTiledGrid *tgrid) +static void gtk_tiling_grid_on_right_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid) { - GPanelItem *result; /* Panneau à retourner */ - - result = tgrid->def_panel; - - if (result != NULL) - g_object_ref(G_OBJECT(result)); - - return result; + gtk_tiling_grid_on_gesture_drag_update(grid, TGB_RIGHT, offset_x, offset_y); } /****************************************************************************** * * -* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. * -* panel = panneau d'affichage par défault ou NULL. * +* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. * +* offset_x = déplacement sur l'axe des abscisses. * +* offset_y = déplacement sur l'axe des ordonnées. * +* grid = gestionnaire de placement en tuile concerné. * * * -* Description : Fournit le panneau par défaut pour la zone principale. * +* Description : Actualise l'effet d'un redimensionnement drag-and-drop. * * * * Retour : - * * * @@ -825,56 +814,21 @@ GPanelItem *gtk_tiled_grid_get_default_main_panel(const GtkTiledGrid *tgrid) * * ******************************************************************************/ -void gtk_tiled_grid_set_default_main_panel(GtkTiledGrid *tgrid, GPanelItem *panel) +static void gtk_tiling_grid_on_bottom_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid) { - GtkWidget *widget; /* Composant GTK à retirer */ - GtkWidget *parent; /* Conteneur à vider */ - grid_tile_t *tile; /* Première tuile d'accueil */ - - if (tgrid->def_panel != NULL) - { - widget = gtk_dockable_build_widget(GTK_DOCKABLE(tgrid->def_panel)); - - parent = gtk_widget_get_parent(widget); - - if (parent != NULL) - gtk_container_remove(GTK_CONTAINER(parent), widget); - - g_object_unref(G_OBJECT(widget)); - - g_object_unref(G_OBJECT(tgrid->def_panel)); - - } - - tgrid->def_panel = panel; - - if (panel != NULL) - { - g_object_ref(G_OBJECT(panel)); - - if (tgrid->tiles == NULL) - gtk_tiled_grid_add(tgrid, panel); - - else - { - tile = find_suitable_tile(&tgrid->tiles, "M", tgrid); - - if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(tile->widget)) == 0) - gtk_tiled_grid_add(tgrid, panel); - - } - - } + gtk_tiling_grid_on_gesture_drag_update(grid, TGB_BOTTOM, offset_x, offset_y); } /****************************************************************************** * * -* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. * -* panel = panneau d'affichage à intégrer. * +* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. * +* offset_x = déplacement final sur l'axe des abscisses. * +* offset_y = déplacement final sur l'axe des ordonnées. * +* grid = gestionnaire de placement en tuile concerné. * * * -* Description : Incorpore un nouveau panneau dans le conteneur en tuiles. * +* Description : Clôture un drag-and-drop de redimensionnement. * * * * Retour : - * * * @@ -882,66 +836,30 @@ void gtk_tiled_grid_set_default_main_panel(GtkTiledGrid *tgrid, GPanelItem *pane * * ******************************************************************************/ -void gtk_tiled_grid_add(GtkTiledGrid *tgrid, GPanelItem *panel) +static void gtk_tiling_grid_on_gesture_drag_end(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid) { - char *path; /* Chemin d'accès */ - char *name; /* Nom à donner à l'onglet */ - grid_tile_t *tile; /* Tuile d'accueil */ - - path = gtk_panel_item_class_get_path(G_PANEL_ITEM_GET_CLASS(panel)); - - if (!is_valid_tile_path(path)) - { - name = gtk_dockable_get_name(GTK_DOCKABLE(panel)); - log_variadic_message(LMT_ERROR, _("Invalid path '%s' for panel '%s'"), path, name); - free(name); - } - + if (!grid->panning) + gtk_gesture_set_state(GTK_GESTURE(gesture), GTK_EVENT_SEQUENCE_DENIED); else - { - tile = find_suitable_tile(&tgrid->tiles, path, tgrid); - assert(tile != NULL); - - gtk_dock_station_add_dockable(GTK_DOCK_STATION(tile->widget), GTK_DOCKABLE(panel)); - - g_panel_item_set_dock_at_startup(panel, true); - - /* Si c'est la toute première fois... */ - if (gtk_widget_get_parent(tile->widget) == NULL) - { - assert(tile == tgrid->tiles); - assert(tile->path[0] == 'M' && tile->path[1] == '\0'); - g_object_ref(G_OBJECT(tile->widget)); - gtk_container_add(GTK_CONTAINER(tgrid), tile->widget); - } + grid->panning = false; - /* Si on n'a plus besoin du panneau par défaut */ - if (tgrid->def_panel != NULL && tile->path[0] == 'M' && tile->path[1] == '\0') - { - /* Si ce n'est pas le panneau qu'on vient de rajouter...*/ - if (panel != tgrid->def_panel) - { - /* Enfin : si ce panneau par défaut est réellement en place */ - if (g_panel_item_is_docked(tgrid->def_panel)) - gtk_tiled_grid_remove(tgrid, tgrid->def_panel); - - } - - } +} - } - free(path); -} +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. * -* panel = panneau d'affichage à supprimer. * +* Paramètres : object = instance d'objet GLib à mamnipuler. * +* prop_id = identifiant de la propriété visée. * +* value = valeur à prendre en compte. * +* pspec = définition de la propriété. * * * -* Description : Retire un panneau dans le conteneur en tuiles. * +* Description : Met à jour une propriété d'instance GObject. * * * * Retour : - * * * @@ -949,90 +867,65 @@ void gtk_tiled_grid_add(GtkTiledGrid *tgrid, GPanelItem *panel) * * ******************************************************************************/ -void gtk_tiled_grid_remove(GtkTiledGrid *tgrid, GPanelItem *panel) +static void gtk_tiling_grid_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - GtkWidget *station; /* Support courant */ - grid_tile_t *tile; /* Tuile d'accueil */ - - assert(g_panel_item_is_docked(panel)); + GtkTilingGrid *grid; /* Version spécialisée */ - gtk_dockable_decompose(GTK_DOCKABLE(panel), &station); + grid = GTK_TILING_GRID(object); - tile = find_tile_for_widget(tgrid->tiles, station); - assert(tile != NULL); - - gtk_dock_station_remove_dockable(GTK_DOCK_STATION(station), GTK_DOCKABLE(panel)); - - g_panel_item_set_dock_at_startup(panel, false); - - if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(station)) == 0) + switch (prop_id) { - /* Si le panneau par défaut devient nécessaire */ - if (tgrid->def_panel != NULL && tile->path[0] == 'M' && tile->path[1] == '\0') - gtk_tiled_grid_add(tgrid, tgrid->def_panel); - - else - { - /* La racine est concernée ! */ - if (tile->parent == NULL) + case PROP_LAYOUT: + if (grid->layout != g_value_get_flags(value)) { - assert(tile == tgrid->tiles); + grid->layout = g_value_get_flags(value); - g_object_ref(G_OBJECT(tile->widget)); - gtk_container_remove(GTK_CONTAINER(tgrid), tile->widget); + apply_tiling_grid_layout(GTK_GRID(grid), grid->layout, (GtkWidget *[]) { + GTK_WIDGET(grid->top), GTK_WIDGET(grid->left), + GTK_WIDGET(grid->right), GTK_WIDGET(grid->bottom) + }); - delete_tile(tile); - tgrid->tiles = NULL; + g_object_notify_by_pspec(object, pspec); } + break; - else - collapse_tile(tile->parent, tile); - - } - - } - -} - + gtk_tiling_grid_set_visible(grid, TGB_TOP, g_value_get_boolean(value)); + break; -/****************************************************************************** -* * -* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. * -* station = station d'accueil à retrouver. * -* * -* Description : Indique le chemin correspondant à une station intégrée. * -* * -* Retour : Copie de chemin trouvé, à libérer ensuite, ou NULL si échec. * -* * -* Remarques : - * -* * -******************************************************************************/ + case PROP_VISIBLE_TOP: + gtk_tiling_grid_set_visible(grid, TGB_TOP, g_value_get_boolean(value)); + break; -char *gtk_tiled_grid_get_path_for_station(const GtkTiledGrid *tgrid, GtkDockStation *station) -{ - char *result; /* Chemin d'accès à renvoyer */ - grid_tile_t *tile; /* Tuile d'accueil */ + case PROP_VISIBLE_LEFT: + gtk_tiling_grid_set_visible(grid, TGB_LEFT, g_value_get_boolean(value)); + break; - tile = find_tile_for_widget(tgrid->tiles, GTK_WIDGET(station)); + case PROP_VISIBLE_RIGHT: + gtk_tiling_grid_set_visible(grid, TGB_RIGHT, g_value_get_boolean(value)); + break; - if (tile == NULL) - result = NULL; + case PROP_VISIBLE_BOTTOM: + gtk_tiling_grid_set_visible(grid, TGB_BOTTOM, g_value_get_boolean(value)); + break; - else - result = strdup(tile->path); + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; - return result; + } } /****************************************************************************** * * -* Paramètres : tgrid = conteneur d'affichage en tuiles à mettre à jour. * -* config = configuration à consulter. * +* Paramètres : object = instance d'objet GLib à mamnipuler. * +* prop_id = identifiant de la propriété visée. * +* value = valeur à transmettre. [OUT] * +* pspec = définition de la propriété. * * * -* Description : Replace les positions des séparateurs de tuiles. * +* Description : Fournit la valeur d'une propriété d'instance GObject. * * * * Retour : - * * * @@ -1040,57 +933,68 @@ char *gtk_tiled_grid_get_path_for_station(const GtkTiledGrid *tgrid, GtkDockStat * * ******************************************************************************/ -void gtk_tiled_grid_restore_positions(const GtkTiledGrid *tgrid, GGenConfig *config) +static void gtk_tiling_grid_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { + GtkTilingGrid *grid; /* Version spécialisée */ - void visit_tiles_for_restoring(grid_tile_t *tile, const char *vpath) - { - GtkOrientation orientation; /* Direction de la tuile */ - char hint; /* Inutile donc indispensable */ - char *key; /* Clef d'accès à un paramètre */ - gint position; /* Nouvelle position de barre */ - size_t i; /* Boucle de parcours */ - char *child_key; /* Clef d'accès des suivants */ - - if (!IS_LEAF_TILE(tile)) - { - orientation = gtk_orientable_get_orientation(GTK_ORIENTABLE(tile->widget)); + grid = GTK_TILING_GRID(object); - hint = orientation == GTK_ORIENTATION_HORIZONTAL ? 'h' : 'v'; + switch (prop_id) + { + case PROP_EMPTY_TOP: + g_value_set_boolean(value, gtk_dock_station_is_empty(grid->top_station)); + break; - asprintf(&key, "%s%c", vpath, hint); + case PROP_EMPTY_LEFT: + g_value_set_boolean(value, gtk_dock_station_is_empty(grid->left_station)); + break; - if (g_generic_config_get_value(config, key, &position)) - gtk_paned_set_position(GTK_PANED(tile->widget), position); + case PROP_EMPTY_RIGHT: + g_value_set_boolean(value, gtk_dock_station_is_empty(grid->right_station)); + break; - for (i = 0; i < 2; i++) - { - asprintf(&child_key, "%s%zu", key, i); + case PROP_EMPTY_BOTTOM: + g_value_set_boolean(value, gtk_dock_station_is_empty(grid->bottom_station)); + break; - visit_tiles_for_restoring(tile->children[i], child_key); + case PROP_VISIBLE_TOP: + g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_TOP)); + break; - free(child_key); + case PROP_VISIBLE_LEFT: + g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_LEFT)); + break; - } + case PROP_VISIBLE_RIGHT: + g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_RIGHT)); + break; - free(key); + case PROP_VISIBLE_BOTTOM: + g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_BOTTOM)); + break; - } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; } +} - visit_tiles_for_restoring(tgrid->tiles, "gui.panels.positions.R"); -} + +/* ---------------------------------------------------------------------------------- */ +/* FORME GENERIQUE DE MISE EN DISPOSITION */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. * -* config = configuration à mettre à jour. * +* Paramètres : grid = composant GTK dont le contenu est à arranger. * +* options = options de mise en place. * +* panels = liste organisée de composants à déplacer. * * * -* Description : Sauvegarde les positions des séparateurs de tuiles. * +* Description : Met en place une disposition particulière de panneaux. * * * * Retour : - * * * @@ -1098,49 +1002,98 @@ void gtk_tiled_grid_restore_positions(const GtkTiledGrid *tgrid, GGenConfig *con * * ******************************************************************************/ -void gtk_tiled_grid_save_positions(const GtkTiledGrid *tgrid, GGenConfig *config) +void apply_tiling_grid_layout(GtkGrid *grid, LayoutReachOptions options, GtkWidget *panels[TGB_COUNT]) { - - void visit_tiles_for_saving(grid_tile_t *tile, const char *vpath) + int top_panel_span; /* Etendue d'un composant #1 */ + int left_panel_span; /* Etendue d'un composant #2 */ + int right_panel_span; /* Etendue d'un composant #3 */ + int bottom_panel_span; /* Etendue d'un composant #4 */ + int top_panel_column; /* Position de composant #1 */ + int left_panel_row; /* Position de composant #2 */ + int right_panel_row; /* Position de composant #3 */ + int bottom_panel_column; /* Position de composant #4 */ + GtkLayoutManager *layout; /* Gestionnaire de disposition */ + GtkGridLayoutChild *top_panel_layout; /* Disposition de composant #1 */ + GtkGridLayoutChild *left_panel_layout; /* Disposition de composant #2 */ + GtkGridLayoutChild *right_panel_layout; /* Disposition de composant #3 */ + GtkGridLayoutChild *bottom_panel_layout;/* Disposition de composant #4 */ + + /* Calcul des placements */ + + top_panel_span = 3; + left_panel_span = 3; + right_panel_span = 3; + bottom_panel_span = 3; + + if (options & LRO_LEFT_TOP_REACH) { - GtkOrientation orientation; /* Direction de la tuile */ - char hint; /* Inutile donc indispensable */ - char *key; /* Clef d'accès à un paramètre */ - gint position; /* Nouvelle position de barre */ - size_t i; /* Boucle de parcours */ - char *child_key; /* Clef d'accès des suivants */ - - if (!IS_LEAF_TILE(tile)) - { - orientation = gtk_orientable_get_orientation(GTK_ORIENTABLE(tile->widget)); - - hint = orientation == GTK_ORIENTATION_HORIZONTAL ? 'h' : 'v'; + top_panel_column = 1; + top_panel_span--; + left_panel_row = 0; + } + else + { + top_panel_column = 0; + left_panel_row = 1; + left_panel_span--; + } - asprintf(&key, "%s%c", vpath, hint); + if (options & LRO_LEFT_BOTTOM_REACH) + { + bottom_panel_column = 1; + bottom_panel_span--; + } + else + { + left_panel_span--; + bottom_panel_column = 0; + } - position = gtk_paned_get_position(GTK_PANED(tile->widget)); - g_generic_config_create_or_udpdate_param(config, key, CPT_INTEGER, -1, position); + if (options & LRO_RIGHT_TOP_REACH) + { + top_panel_span--; + right_panel_row = 0; + } + else + { + right_panel_row = 1; + right_panel_span--; + } - for (i = 0; i < 2; i++) - { - asprintf(&child_key, "%s%zu", key, i); + if (options & LRO_RIGHT_BOTTOM_REACH) + bottom_panel_span--; + else + right_panel_span--; - visit_tiles_for_saving(tile->children[i], child_key); + /* Mise en application des contraintes */ - free(child_key); + layout = gtk_widget_get_layout_manager(GTK_WIDGET(grid)); - } + top_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_TOP])); + left_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_LEFT])); + right_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_RIGHT])); + bottom_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_BOTTOM])); - free(key); + g_object_set(G_OBJECT(top_panel_layout), + "column", top_panel_column, + "column-span", top_panel_span, + NULL); - } + g_object_set(G_OBJECT(left_panel_layout), + "row", left_panel_row, + "row-span", left_panel_span, + NULL); - } + g_object_set(G_OBJECT(right_panel_layout), + "row", right_panel_row, + "row-span", right_panel_span, + NULL); + g_object_set(G_OBJECT(bottom_panel_layout), + "column", bottom_panel_column, + "column-span", bottom_panel_span, + NULL); - visit_tiles_for_saving(tgrid->tiles, "gui.panels.positions.R"); + gtk_layout_manager_layout_changed(layout); } - - -#endif |