diff options
Diffstat (limited to 'src/gtkext')
| -rw-r--r-- | src/gtkext/Makefile.am | 6 | ||||
| -rw-r--r-- | src/gtkext/bindings/Makefile.am | 42 | ||||
| -rw-r--r-- | src/gtkext/bindings/generated-enums.c.template | 41 | ||||
| -rw-r--r-- | src/gtkext/bindings/generated-enums.h.template | 23 | ||||
| -rw-r--r-- | src/gtkext/dockstation-int.h | 18 | ||||
| -rw-r--r-- | src/gtkext/dockstation.c | 427 | ||||
| -rw-r--r-- | src/gtkext/dockstation.h | 7 | ||||
| -rw-r--r-- | src/gtkext/dockstation.ui | 80 | ||||
| -rw-r--r-- | src/gtkext/gresource.xml | 2 | ||||
| -rw-r--r-- | src/gtkext/grid-int.h | 42 | ||||
| -rw-r--r-- | src/gtkext/grid.c | 1305 | ||||
| -rw-r--r-- | src/gtkext/grid.h | 43 | ||||
| -rw-r--r-- | src/gtkext/grid.ui | 217 | ||||
| -rw-r--r-- | src/gtkext/panel-int.h | 6 | ||||
| -rw-r--r-- | src/gtkext/panel.c | 31 | ||||
| -rw-r--r-- | src/gtkext/panel.h | 5 | ||||
| -rw-r--r-- | src/gtkext/statusstack-int.h | 2 | ||||
| -rw-r--r-- | src/gtkext/statusstack.c | 116 | ||||
| -rw-r--r-- | src/gtkext/statusstack.ui | 3 | 
19 files changed, 1660 insertions, 756 deletions
| diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am index 839ee8f..c6908dd 100644 --- a/src/gtkext/Makefile.am +++ b/src/gtkext/Makefile.am @@ -29,6 +29,8 @@ libgtkext_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)  IMG_PATH = ../../data/images  RES_FILES =									\ +	grid.ui									\ +	dockstation.ui							\  	hexview.css								\  	hexview.ui								\  	launcher.ui								\ @@ -64,6 +66,9 @@ libgtkext4_la_SOURCES =						\  libgtkext4_la_CFLAGS = $(LIBGTK4_CFLAGS) +libgtkext4_la_LIBADD = 						\ +	bindings/libgtkextbindings.la +  devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) @@ -71,6 +76,7 @@ dev_HEADERS = $(libgtkext4_la_SOURCES:%c=)  #SUBDIRS = graph +SUBDIRS = bindings  resources.c: gresource.xml $(RES_FILES) diff --git a/src/gtkext/bindings/Makefile.am b/src/gtkext/bindings/Makefile.am new file mode 100644 index 0000000..71e770d --- /dev/null +++ b/src/gtkext/bindings/Makefile.am @@ -0,0 +1,42 @@ + +EXTRA_DIST = \ +	generated-enums.c.template \ +	generated-enums.h.template + + +noinst_LTLIBRARIES  = libgtkextbindings.la + + +nodist_libgtkextbindings_la_SOURCES = \ +	grid-enums.h grid-enums.c + +libgtkextbindings_la_CFLAGS = $(LIBGTK4_CFLAGS) + + +BUILT_SOURCES = $(nodist_libgtkextbindings_la_SOURCES) +CLEANFILES = $(nodist_libgtkextbindings_la_SOURCES) + + +devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) + +dev_HEADERS = $(nodist_libgtkextbindings_la_SOURCES:%c=) + + +grid-enums.c: ../../gtkext/grid.h generated-enums.c.template +	$(AM_V_GEN)$(GLIB_MKENUMS) \ +		--fhead "#include \"$(subst .c,.h,$@)\"\n" \ +		--template=$(srcdir)/generated-enums.c.template \ +		--output=$(srcdir)/$@ \ +		$< + +grid-enums.h: ../../gtkext/grid.h generated-enums.h.template +	$(AM_V_GEN)$(GLIB_MKENUMS) \ +		--fhead "#ifndef _GTKEXT_BINDINGS_GRID_ENUM_H\n" \ +		--fhead "#define _GTKEXT_BINDINGS_GRID_ENUM_H\n" \ +		--fhead "\n" \ +		--fhead "#include \"$<\"\n" \ +		--fhead "\n" \ +		--ftail "#endif  /* _GTKEXT_BINDINGS_GRID_ENUM_H */\n" \ +		--template=$(srcdir)/generated-enums.h.template \ +		--output=$(srcdir)/$@ \ +		$< diff --git a/src/gtkext/bindings/generated-enums.c.template b/src/gtkext/bindings/generated-enums.c.template new file mode 100644 index 0000000..8f54149 --- /dev/null +++ b/src/gtkext/bindings/generated-enums.c.template @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// SPDX-FileCopyrightText: 2023 Bartosz Golaszewski <bartosz.golaszewski@linaro.org> + +/*** BEGIN file-header ***/ + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* Enumerations de "@filename@" */ + +/*** END file-production ***/ + +/*** BEGIN value-header ***/ + +GType @enum_name@_get_type(void) +{ +	static gsize static_g_@type@_type_id; + +	if (g_once_init_enter(&static_g_@type@_type_id)) { +		static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ +			{@VALUENAME@, "@VALUENAME@", "@valuenick@"}, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ +			{ 0, NULL, NULL } +		}; + +		GType g_@type@_type_id = g_@type@_register_static( +				g_intern_static_string("@EnumName@"), values); + +		g_once_init_leave (&static_g_@type@_type_id, g_@type@_type_id); +	} + +	return static_g_@type@_type_id; +} + +/*** END value-tail ***/ diff --git a/src/gtkext/bindings/generated-enums.h.template b/src/gtkext/bindings/generated-enums.h.template new file mode 100644 index 0000000..58c772d --- /dev/null +++ b/src/gtkext/bindings/generated-enums.h.template @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// SPDX-FileCopyrightText: 2023-2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org> + +/*** BEGIN file-header ***/ + +G_BEGIN_DECLS + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType @enum_name@_get_type(void) G_GNUC_CONST; +#define @ENUMPREFIX@_@ENUMSHORT@_TYPE (@enum_name@_get_type()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ + +G_END_DECLS + +/*** END file-tail ***/ diff --git a/src/gtkext/dockstation-int.h b/src/gtkext/dockstation-int.h index a44371a..17ed828 100644 --- a/src/gtkext/dockstation-int.h +++ b/src/gtkext/dockstation-int.h @@ -32,19 +32,29 @@  /* Station de réception pour concentration d'éléments (instance) */  struct _GtkDockStation  { -    GtkWidget parent;                       /* A laisser en premier        */ +    GtkBox parent;                          /* A laisser en premier        */ + +    GtkOrientation orientation;             /* Spécification d'orientation */ + +    GtkWidget *tabs;                        /* Bascule entre panneaux      */ +    GtkWidget *toolbar;                     /* Boutons d'action            */ +    GtkWidget *sep1;                        /* Séparateur #1               */ +    GtkStack *stack;                        /* Pile de panneaux affichés   */ +    GtkWidget *sep2;                        /* Séparateur #2               */ + +    GtkTiledPanel *def_panel;               /* Eventuel panneau à maintenir*/  };  /* Station de réception pour concentration d'éléments (classe) */  struct _GtkDockStationClass  { -    GtkWidgetClass parent;                  /* A laisser en premier        */ +    GtkBoxClass parent;                     /* A laisser en premier        */      /* Signaux */ -    void (* dock_widget) (GtkDockStation *, GtkWidget *); -    void (* undock_widget) (GtkDockStation *, GtkWidget *); +    void (* panel_docked) (GtkDockStation *, GtkTiledPanel *); +    void (* panel_undocked) (GtkDockStation *, GtkTiledPanel *);      void (* switch_widget) (GtkDockStation *, GtkWidget *); diff --git a/src/gtkext/dockstation.c b/src/gtkext/dockstation.c index 093f120..359e3a1 100644 --- a/src/gtkext/dockstation.c +++ b/src/gtkext/dockstation.c @@ -28,6 +28,25 @@ +/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */ + + +/* Liste des propriétés */ + +typedef enum _DockStationProperty { + +    PROP_0,                                 /* Réservé                     */ + +    /* Interface GtkOrientable */ +    PROP_ORIENTATION, + +    N_PROPERTIES = PROP_ORIENTATION + +} DockStationProperty; + +//static GParamSpec *_dock_station_properties[N_PROPERTIES] = { NULL, }; + +  /* Procède à l'initialisation de l'afficheur concentré. */  static void gtk_dock_station_class_init(GtkDockStationClass *); @@ -35,16 +54,31 @@ static void gtk_dock_station_class_init(GtkDockStationClass *);  static void gtk_dock_station_init(GtkDockStation *);  /* Supprime toutes les références externes. */ -static void gtk_dock_station_dispose(GtkDockStation *); +static void gtk_dock_station_dispose(GObject *);  /* Procède à la libération totale de la mémoire. */ -static void gtk_dock_station_finalize(GtkDockStation *); +static void gtk_dock_station_finalize(GObject *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + +/* Met à jour une propriété d'instance GObject. */ +static void gtk_dock_station_set_property(GObject *, guint, const GValue *, GParamSpec *); +/* Fournit la valeur d'une propriété d'instance GObject. */ +static void gtk_dock_station_get_property(GObject *, guint, GValue *, GParamSpec *); + + + +/* ---------------------------------------------------------------------------------- */ +/*                             INTERFACE DU COMPOSANT GTK                             */ +/* ---------------------------------------------------------------------------------- */  /* Détermine le type du composant d'affichage concentré. */ -G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_WIDGET) +G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_GRID)  /****************************************************************************** @@ -62,28 +96,47 @@ G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_WIDGET)  static void gtk_dock_station_class_init(GtkDockStationClass *class)  {      GObjectClass *object;                   /* Autre version de la classe  */ +    GtkWidgetClass *widget;                 /* Classe de haut niveau       */      object = G_OBJECT_CLASS(class); -    object->dispose = (GObjectFinalizeFunc/* ! */)gtk_dock_station_dispose; -    object->finalize = (GObjectFinalizeFunc)gtk_dock_station_finalize; +    object->dispose = gtk_dock_station_dispose; +    object->finalize = gtk_dock_station_finalize; +    object->set_property = gtk_dock_station_set_property; +    object->get_property = gtk_dock_station_get_property; -    g_signal_new("dock-widget", +    //g_object_class_install_properties(object, N_PROPERTIES, _dock_station_properties); +    g_object_class_override_property(object, PROP_ORIENTATION, "orientation"); + +    widget = GTK_WIDGET_CLASS(class); + +    gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/dockstation.ui"); + +    //gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_status_stack_on_zoom_icon_press)); + +    gtk_widget_class_bind_template_child(widget, GtkDockStation, tabs); +    gtk_widget_class_bind_template_child(widget, GtkDockStation, toolbar); +    gtk_widget_class_bind_template_child(widget, GtkDockStation, sep1); +    gtk_widget_class_bind_template_child(widget, GtkDockStation, stack); +    gtk_widget_class_bind_template_child(widget, GtkDockStation, sep2); + +    g_signal_new("panel-docked",                   GTK_TYPE_DOCK_STATION,                   G_SIGNAL_RUN_LAST, -                 G_STRUCT_OFFSET(GtkDockStationClass, dock_widget), +                 G_STRUCT_OFFSET(GtkDockStationClass, panel_docked),                   NULL, NULL,                   g_cclosure_marshal_VOID__OBJECT,                   G_TYPE_NONE, 1, GTK_TYPE_WIDGET); -    g_signal_new("undock-widget", +    g_signal_new("panel-undocked",                   GTK_TYPE_DOCK_STATION,                   G_SIGNAL_RUN_LAST, -                 G_STRUCT_OFFSET(GtkDockStationClass, undock_widget), +                 G_STRUCT_OFFSET(GtkDockStationClass, panel_undocked),                   NULL, NULL,                   g_cclosure_marshal_VOID__OBJECT,                   G_TYPE_NONE, 1, GTK_TYPE_WIDGET); +    /*      g_signal_new("switch-widget",                   GTK_TYPE_DOCK_STATION,                   G_SIGNAL_RUN_LAST, @@ -107,6 +160,7 @@ static void gtk_dock_station_class_init(GtkDockStationClass *class)                   NULL, NULL,                   g_cclosure_marshal_VOID__OBJECT,                   G_TYPE_NONE, 1, GTK_TYPE_WIDGET); +    */  } @@ -125,57 +179,66 @@ static void gtk_dock_station_class_init(GtkDockStationClass *class)  static void gtk_dock_station_init(GtkDockStation *station)  { -#if 0 +    gtk_widget_init_template(GTK_WIDGET(station)); -    GtkNotebook *notebook;                  /* Autre version du composant  */ -    GtkWidget *hbox;                        /* Division supérieure         */ -    GtkWidget *button;                      /* Bouton de contrôle          */ +    station->orientation = GTK_ORIENTATION_HORIZONTAL; -    notebook = GTK_NOTEBOOK(station); +    station->def_panel = NULL; -    gtk_notebook_set_show_border(notebook, FALSE); -    gtk_notebook_set_scrollable(notebook, TRUE); +} -    /* Définition de la zone de contrôle */ -    hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); -    gtk_widget_set_valign(hbox, GTK_ALIGN_CENTER); -    gtk_widget_set_margin_end(hbox, 8); -    gtk_widget_show(hbox); +/****************************************************************************** +*                                                                             * +*  Paramètres  : object = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ -    button = qck_create_toggle_button_with_named_img(G_OBJECT(station), "search", -                                                     "edit-find-symbolic", GTK_ICON_SIZE_MENU, NULL, -                                                     G_CALLBACK(on_toggle_revealer), station); -    gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); -    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); +static void gtk_dock_station_dispose(GObject *object) +{ +    GtkDockStation *station;                /* Version spécialisée         */ -    button = qck_create_button_with_named_img(G_OBJECT(station), "menu", -                                              "go-down-symbolic", GTK_ICON_SIZE_MENU, NULL, -                                              G_CALLBACK(on_click_for_menu), station); -    gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); -    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); +    station = GTK_DOCK_STATION(object); -    button = qck_create_button_with_named_img(G_OBJECT(station), "close", -                                              "window-close-symbolic", GTK_ICON_SIZE_MENU, NULL, -                                              G_CALLBACK(on_click_for_close), station); -    gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); -    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); +    gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_DOCK_STATION); -    gtk_notebook_set_action_widget(notebook, hbox, GTK_PACK_END); +    g_clear_object(&station->def_panel); -    g_signal_connect(notebook, "switch-page", -                     G_CALLBACK(gtk_dock_station_switch_panel), station); +    G_OBJECT_CLASS(gtk_dock_station_parent_class)->dispose(object); + +} -#endif + +/****************************************************************************** +*                                                                             * +*  Paramètres  : object = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void gtk_dock_station_finalize(GObject *object) +{ +    G_OBJECT_CLASS(gtk_dock_station_parent_class)->finalize(object);  }  /******************************************************************************  *                                                                             * -*  Paramètres  : station = instance d'objet GLib à traiter.                   * +*  Paramètres  : -                                                            *  *                                                                             * -*  Description : Supprime toutes les références externes.                     * +*  Description : Crée un nouveau composant pour support d'affichage concentré.*  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -183,18 +246,23 @@ static void gtk_dock_station_init(GtkDockStation *station)  *                                                                             *  ******************************************************************************/ -static void gtk_dock_station_dispose(GtkDockStation *station) +GtkWidget *gtk_dock_station_new(void)  { -    G_OBJECT_CLASS(gtk_dock_station_parent_class)->dispose(G_OBJECT(station)); +    GtkWidget *result;                      /* Instance à retourner        */ + +    result = g_object_new(GTK_TYPE_DOCK_STATION, NULL); + +    return result;  }  /******************************************************************************  *                                                                             * -*  Paramètres  : station = instance d'objet GLib à traiter.                   * +*  Paramètres  : station = station d'accueil pour panneau à compléter.        * +*                panel   = nouveau panneau à afficher.                        *  *                                                                             * -*  Description : Procède à la libération totale de la mémoire.                * +*  Description : Ajoute un panneau à un groupe de tuiles.                     *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -202,18 +270,33 @@ static void gtk_dock_station_dispose(GtkDockStation *station)  *                                                                             *  ******************************************************************************/ -static void gtk_dock_station_finalize(GtkDockStation *station) +void gtk_dock_station_add_panel(GtkDockStation *station, GtkTiledPanel *panel)  { -    G_OBJECT_CLASS(gtk_dock_station_parent_class)->finalize(G_OBJECT(station)); +    GtkStackPage *page;                     /* Nouvelle page insérée       */ + +    page = gtk_stack_add_child(station->stack, GTK_WIDGET(panel)); + +    if (0)  // TODO +        gtk_stack_page_set_title(page, "settings"); + +    else +        gtk_stack_page_set_icon_name(page, "logs-symbolic"); + +    gtk_stack_set_visible_child(station->stack, GTK_WIDGET(panel)); + + +    g_signal_emit_by_name(station, "panel-docked", panel); +  }  /******************************************************************************  *                                                                             * -*  Paramètres  : -                                                            * +*  Paramètres  : station = station d'accueil pour panneau à compléter.        * +*                panel   = nouveau panneau à afficher.                        *  *                                                                             * -*  Description : Crée un nouveau composant pour support d'affichage concentré.* +*  Description : Ajoute un panneau à conserver à un groupe de tuiles.         *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -221,17 +304,255 @@ static void gtk_dock_station_finalize(GtkDockStation *station)  *                                                                             *  ******************************************************************************/ -GtkWidget *gtk_dock_station_new(void) +void gtk_dock_station_keep_panel(GtkDockStation *station, GtkTiledPanel *panel)  { -    GtkWidget *result;                      /* Instance à retourner        */ +    bool visible;                           /* Visibilité des barres       */ + +    g_clear_object(&station->def_panel); + +    if (panel != NULL) +    { +        station->def_panel = panel; +        ref_object(panel); + +        if (gtk_stack_get_page(station->stack, GTK_WIDGET(panel)) == NULL) +            gtk_dock_station_add_panel(station, panel); + +    } + +    visible = (station->def_panel == NULL); + +    gtk_widget_set_visible(station->tabs, visible); +    gtk_widget_set_visible(station->toolbar, visible); +    gtk_widget_set_visible(station->sep1, visible); +    gtk_widget_set_visible(station->sep2, visible && station->orientation == GTK_ORIENTATION_HORIZONTAL); + +} -    result = g_object_new(GTK_TYPE_DOCK_STATION, NULL); + +/****************************************************************************** +*                                                                             * +*  Paramètres  : station = station d'accueil pour panneau à consulter.        * +*                                                                             * +*  Description : Indique si la station d'accueil contient au moins un panneau.* +*                                                                             * +*  Retour      : true si aucun panneau n'est intégré, false sinon.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool gtk_dock_station_is_empty(const GtkDockStation *station) +{ +    bool result;                            /* Bilan à retourner           */ +    GtkSelectionModel *model;               /* Modèle pour la pile         */ +    guint count;                            /* Nombre de panneaux présents */ + +    model = gtk_stack_get_pages(station->stack); + +    count = g_list_model_get_n_items(G_LIST_MODEL(model)); + +    result = (count == 0); + +    unref_object(model);      return result;  } +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  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 : Met à jour une propriété d'instance GObject.                 * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void gtk_dock_station_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ +    GtkDockStation *station;                /* Version spécialisée         */ +    GtkOrientation orientation;             /* Spécification d'orientation */ +    GtkLayoutManager *layout;               /* Gestionnaire de disposition */ +    GtkLayoutChild *child_layout;           /* Disposition de composant    */ + +    station = GTK_DOCK_STATION(object); + +    switch (prop_id) +    { +        case PROP_ORIENTATION: + +            orientation = g_value_get_enum(value); + +            if (station->orientation != orientation) +            { +                station->orientation = orientation; + +                gtk_orientable_set_orientation(GTK_ORIENTABLE(station->tabs), orientation); +                gtk_orientable_set_orientation(GTK_ORIENTABLE(station->toolbar), orientation); + +                layout = gtk_widget_get_layout_manager(GTK_WIDGET(object)); + +                if (orientation == GTK_ORIENTATION_VERTICAL) +                { +                    g_object_set(G_OBJECT(station->tabs), +                                 "halign", GTK_ALIGN_START, +                                 "valign", GTK_ALIGN_CENTER, +                                 NULL); + +                    g_object_set(G_OBJECT(station->toolbar), +                                 "halign", GTK_ALIGN_END, +                                 "valign", GTK_ALIGN_CENTER, +                                 NULL); + +                    child_layout = gtk_layout_manager_get_layout_child(layout, station->toolbar); + +                    g_object_set(G_OBJECT(child_layout), +                                 "column", 1, +                                 "row", 0, +                                 NULL); + +                    child_layout = gtk_layout_manager_get_layout_child(layout, station->sep1); + +                    g_object_set(G_OBJECT(child_layout), +                                 "column", 0, +                                 "row", 1, +                                 "column-span", 2, +                                 NULL); + +                    gtk_widget_set_visible(station->sep2, FALSE); + +                    child_layout = gtk_layout_manager_get_layout_child(layout, GTK_WIDGET(station->stack)); + +                    g_object_set(G_OBJECT(child_layout), +                                 "column", 0, +                                 "row", 2, +                                 "column-span", 2, +                                 NULL); + +                } +                else +                { +                    g_object_set(G_OBJECT(station->tabs), +                                 "halign", GTK_ALIGN_START, +                                 "valign", GTK_ALIGN_START, +                                 NULL); + +                    g_object_set(G_OBJECT(station->toolbar), +                                 "halign", GTK_ALIGN_END, +                                 "valign", GTK_ALIGN_START, +                                 NULL); + +                    child_layout = gtk_layout_manager_get_layout_child(layout, station->sep1); + +                    g_object_set(G_OBJECT(child_layout), +                                 "column", 1, +                                 "row", 0, +                                 "column-span", 1, +                                 NULL); + +                    child_layout = gtk_layout_manager_get_layout_child(layout, GTK_WIDGET(station->stack)); + +                    g_object_set(G_OBJECT(child_layout), +                                 "column", 2, +                                 "row", 0, +                                 "column-span", 1, +                                 NULL); + +                    gtk_widget_set_visible(station->sep2, TRUE); + +                    child_layout = gtk_layout_manager_get_layout_child(layout, station->sep2); + +                    g_object_set(G_OBJECT(child_layout), +                                 "column", 3, +                                 "row", 0, +                                 NULL); + +                    child_layout = gtk_layout_manager_get_layout_child(layout, station->toolbar); + +                    g_object_set(G_OBJECT(child_layout), +                                 "column", 4, +                                 "row", 0, +                                 NULL); + +                } + +                g_object_notify_by_pspec(object, pspec); + +            } + +            break; + +        default: +            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); +            break; + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  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 : Fournit la valeur d'une propriété d'instance GObject.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void gtk_dock_station_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ +    GtkDockStation *station;                /* Version spécialisée         */ + +    station = GTK_DOCK_STATION(object); + +    switch (prop_id) +    { +        case PROP_ORIENTATION: +            g_value_set_enum(value, station->orientation); +            break; + +        default: +            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); +            break; + +    } + +} + + + + + + + + + + + + + + + diff --git a/src/gtkext/dockstation.h b/src/gtkext/dockstation.h index a857626..3106dae 100644 --- a/src/gtkext/dockstation.h +++ b/src/gtkext/dockstation.h @@ -28,6 +28,7 @@  #include <gtk/gtk.h> +#include "panel.h"  #include "../glibext/helpers.h" @@ -40,8 +41,14 @@ DECLARE_GTYPE(GtkDockStation, gtk_dock_station, GTK, DOCK_STATION);  /* Crée un nouveau composant pour support d'affichage concentré. */  GtkWidget *gtk_dock_station_new(void); +/* Ajoute un panneau à un groupe de tuiles. */ +void gtk_dock_station_add_panel(GtkDockStation *, GtkTiledPanel *); +/* Ajoute un panneau à conserver à un groupe de tuiles. */ +void gtk_dock_station_keep_panel(GtkDockStation *, GtkTiledPanel *); +/* Indique si la station d'accueil contient au moins un panneau. */ +bool gtk_dock_station_is_empty(const GtkDockStation *); diff --git a/src/gtkext/dockstation.ui b/src/gtkext/dockstation.ui new file mode 100644 index 0000000..4d25134 --- /dev/null +++ b/src/gtkext/dockstation.ui @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> +    <template class="GtkDockStation" parent="GtkGrid"> +        <property name="orientation">horizontal</property> + +        <child> +            <object class="GtkStackSwitcher" id="tabs"> +                <property name="orientation">horizontal</property> +                <property name="halign">start</property> +                <property name="valign">start</property> +                <property name="margin-start">2</property> +                <property name="margin-top">2</property> +                <property name="margin-end">2</property> +                <property name="margin-bottom">2</property> +                <property name="stack">stack</property> +                <layout> +                    <property name="column">0</property> +                    <property name="row">0</property> +                </layout> +            </object> +        </child> + +        <child> +            <object class="GtkBox" id="toolbar"> +                <property name="orientation">horizontal</property> +                <property name="halign">end</property> +                <property name="valign">start</property> + +                <child> +                    <object class="GtkButton"> +                        <property name="icon-name">window-close-symbolic</property> +                        <style> +                            <class name="circular"/> +                            <class name="flat"/> +                            <class name="control-button"/> +                        </style> +                    </object> +                </child> + +                <layout> +                    <property name="column">4</property> +                    <property name="row">0</property> +                </layout> +            </object> +        </child> + +        <child> +            <object class="GtkSeparator" id="sep1"> +                <property name="orientation">horizontal</property> +                <layout> +                    <property name="column">1</property> +                    <property name="row">0</property> +                    <property name="column-span">1</property> +                </layout> +            </object> +        </child> + +        <child> +            <object class="GtkStack" id="stack"> +                <property name="hexpand">true</property> +                <layout> +                    <property name="column">2</property> +                    <property name="row">0</property> +                    <property name="column-span">1</property> +                </layout> +            </object> +        </child> + +        <child> +            <object class="GtkSeparator" id="sep2"> +                <property name="orientation">horizontal</property> +                <layout> +                    <property name="column">3</property> +                    <property name="row">0</property> +                </layout> +            </object> +        </child> + +    </template> +</interface> diff --git a/src/gtkext/gresource.xml b/src/gtkext/gresource.xml index 640985f..26943a6 100644 --- a/src/gtkext/gresource.xml +++ b/src/gtkext/gresource.xml @@ -1,6 +1,8 @@  <?xml version="1.0" encoding="UTF-8"?>  <gresources>      <gresource prefix="/re/chrysalide/framework/gtkext"> +        <file compressed="true">dockstation.ui</file> +        <file compressed="true">grid.ui</file>          <file compressed="true">hexview.css</file>          <file compressed="true">hexview.ui</file>          <file compressed="true">launcher.ui</file> diff --git a/src/gtkext/grid-int.h b/src/gtkext/grid-int.h index 5ae48ad..8a2702b 100644 --- a/src/gtkext/grid-int.h +++ b/src/gtkext/grid-int.h @@ -25,46 +25,50 @@  #define _GTKEXT_GRID_INT_H +#include "dockstation.h"  #include "grid.h" -/* -------------------------- GESTION DES TUILES AFFICHEES -------------------------- */ - - -/* Informations concernant une tuile */ -typedef struct _grid_tile_t +/* Conteneur pour un affichage en tuiles nommées (instance) */ +struct _GtkTilingGrid  { -    struct _grid_tile_t *parent;            /* Tuile parente               */ +    GtkGrid parent;                         /* A laisser en premier        */ -    GtkWidget *widget;                      /* Support d'affichage         */ +    GSettings *settings;                    /* Configuration du conteneur  */ -    char *path;                             /* Chemin d'accès              */ +    LayoutReachOptions layout;              /* Disposition générale        */ -    struct _grid_tile_t *children[2];       /* Tuiles encastrées ou 2xNULL */ +    bool visible[TGB_COUNT];                /* Visibilités souhaitées      */ -} grid_tile_t; +    GtkRevealer *top;                       /* Zone d'accueil #1           */ +    GtkWidget *top_handle;                  /* Poignée de redimensionnement*/ +    GtkDockStation *top_station;            /* Station entière             */ +    GtkRevealer *left;                      /* Zone d'accueil #2           */ +    GtkWidget *left_handle;                 /* Poignée de redimensionnement*/ +    GtkDockStation *left_station;           /* Station entière             */ +    GtkDockStation *main_station;           /* Zone d'accueil #3           */ -/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */ +    GtkRevealer *right;                     /* Zone d'accueil #4           */ +    GtkWidget *right_handle;                /* Poignée de redimensionnement*/ +    GtkDockStation *right_station;          /* Station entière             */ +    GtkRevealer *bottom;                    /* Zone d'accueil #5           */ +    GtkWidget *bottom_handle;               /* Poignée de redimensionnement*/ +    GtkDockStation *bottom_station;         /* Station entière             */ -/* Conteneur pour un affichage en tuiles nommées (instance) */ -struct _GtkTilingGrid -{ -    GtkWidget parent;                       /* A laisser en premier        */ - -    grid_tile_t *tiles;                     /* Tuiles représentées         */ +    GtkGesture *tpad_gesture[TGB_COUNT];    /* Gestionnaires du touchpad   */ -    GtkTiledPanel *def_panel;               /* Panneau principal par défaut*/ +    bool panning;                           /* Redimensionnement en cours  */  };  /* Conteneur pour un affichage en tuiles nommées (classe) */  struct _GtkTilingGridClass  { -    GtkWidgetClass parent;                  /* A laisser en premier        */ +    GtkGridClass parent;                    /* A laisser en premier        */      /* Signaux */ 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 diff --git a/src/gtkext/grid.h b/src/gtkext/grid.h index d9b7ef1..f02cf38 100644 --- a/src/gtkext/grid.h +++ b/src/gtkext/grid.h @@ -25,10 +25,10 @@  #define _GTKEXT_GRID_H +#include <stdbool.h>  #include <gtk/gtk.h> -#include "dockstation.h"  #include "panel.h"  #include "../glibext/helpers.h" @@ -42,7 +42,48 @@ DECLARE_GTYPE(GtkTilingGrid, gtk_tiling_grid, GTK, TILING_GRID);  /* Crée une nouvelle instance de conteneur avec tuiles. */  GtkWidget *gtk_tiling_grid_new(void); +/* Liste des zones de bordure */ +typedef enum _TilingGridBorder              /*< skip (glib-mkenums)       >*/ +{ +    TGB_TOP,                                /* Zone supérieure             */ +    TGB_LEFT,                               /* Zone de gauche              */ +    TGB_RIGHT,                              /* Zone de droite              */ +    TGB_BOTTOM,                             /* Zone inférieure             */ +} TilingGridBorder; + +/** + * Fixe le nombre de combinaisons sans le rendre visible dans l'énumération. + */ +#define TGB_COUNT (TGB_BOTTOM + 1) + +/* Affiche ou masque une zone du conteneur en tuiles. */ +void gtk_tiling_grid_set_visible(GtkTilingGrid *, TilingGridBorder, bool); + +/* Fournit la visibilité d'une zone du conteneur en tuiles. */ +bool gtk_tiling_grid_get_visible(GtkTilingGrid *, TilingGridBorder); + +/* Ajoute un panneau à un conteneur en tuiles. */ +void gtk_tiling_grid_add_panel(GtkTilingGrid *, GtkTiledPanel *, bool); + + + +/* --------------------- FORME GENERIQUE DE MISE EN DISPOSITION --------------------- */ + + +/* Options de dispositions cumulables */ +typedef enum _LayoutReachOptions            /*< flags (glib-mkenums)      >*/ +{ +    LRO_NONE                = (0 << 0),     /* Aucune atteinte des bords   */ +    LRO_LEFT_TOP_REACH      = (1 << 0),     /* Atteinte du bord haut à G.  */ +    LRO_LEFT_BOTTOM_REACH   = (1 << 1),     /* Atteinte du bord bas à G.   */ +    LRO_RIGHT_TOP_REACH     = (1 << 2),     /* Atteinte du bord haut à D.  */ +    LRO_RIGHT_BOTTOM_REACH  = (1 << 3),     /* Atteinte du bord bas à D.   */ + +} LayoutReachOptions; + +/* Met en place une disposition particulière de panneaux. */ +void apply_tiling_grid_layout(GtkGrid *, LayoutReachOptions, GtkWidget *[TGB_COUNT]); diff --git a/src/gtkext/grid.ui b/src/gtkext/grid.ui new file mode 100644 index 0000000..b14ced2 --- /dev/null +++ b/src/gtkext/grid.ui @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> +    <template class="GtkTilingGrid" parent="GtkGrid"> + +        <!-- Zone supérieure --> + +        <child> +            <object class="GtkRevealer" id="top"> +                <property name="transition-type">slide-up</property> +                <property name="reveal-child">false</property> + +                <child> +                    <object class="GtkBox"> +                        <property name="orientation">vertical</property> + +                        <child> +                            <object class="GtkDockStation" id="top_station"> +                                <property name="orientation">vertical</property> +                                <property name="hexpand">true</property> +                                <property name="vexpand">false</property> +                                <property name="height-request">30</property> +                                <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/> +                                <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/> +                            </object> +                        </child> + +                        <child> +                            <object class="GtkSeparator" id="top_handle"> +                                <property name="orientation">vertical</property> +                                <property name="height-request">5</property> + +                                <child> +                                    <object class="GtkGestureDrag"> +                                        <property name="propagation-phase">capture</property> +                                        <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/> +                                        <signal name="drag-update" handler="gtk_tiling_grid_on_top_gesture_drag_update"/> +                                        <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/> +                                    </object> +                                </child> + +                            </object> +                        </child> + +                    </object> +                </child> + +                <layout> +                    <property name="column">0</property> +                    <property name="row">0</property> +                    <property name="column-span">3</property> +                </layout> +            </object> +        </child> + +        <!-- Zone de gauche --> + +        <child> +            <object class="GtkRevealer" id="left"> +                <property name="transition-type">slide-right</property> +                <property name="reveal-child">false</property> + +                <child> +                    <object class="GtkBox"> +                        <property name="orientation">horizontal</property> + +                        <child> +                            <object class="GtkDockStation" id="left_station"> +                                <property name="orientation">vertical</property> +                                <property name="hexpand">false</property> +                                <property name="vexpand">true</property> +                                <property name="width-request">300</property> +                                <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/> +                                <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/> +                            </object> +                        </child> + +                        <child> +                            <object class="GtkSeparator" id="left_handle"> +                                <property name="orientation">horizontal</property> +                                <property name="width-request">5</property> + +                                <child> +                                    <object class="GtkGestureDrag"> +                                        <property name="propagation-phase">capture</property> +                                        <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/> +                                        <signal name="drag-update" handler="gtk_tiling_grid_on_left_gesture_drag_update"/> +                                        <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/> +                                    </object> +                                </child> + +                            </object> +                        </child> + +                    </object> +                </child> + +                <layout> +                    <property name="column">0</property> +                    <property name="row">1</property> +                </layout> +            </object> +        </child> + +        <!-- Zone centrale --> + +        <child> +            <object class="GtkDockStation" id="main_station"> +                <property name="hexpand">true</property> +                <property name="vexpand">true</property> +                <layout> +                    <property name="column">1</property> +                    <property name="row">1</property> +                </layout> +            </object> +        </child> + +        <!-- Zone de droite --> + +        <child> +            <object class="GtkRevealer" id="right"> +                <property name="transition-type">slide-left</property> +                <property name="reveal-child">false</property> + +                <child> +                    <object class="GtkBox"> +                        <property name="orientation">horizontal</property> + +                        <child> +                            <object class="GtkSeparator" id="right_handle"> +                                <property name="orientation">horizontal</property> +                                <property name="width-request">5</property> + +                                <child> +                                    <object class="GtkGestureDrag"> +                                        <property name="propagation-phase">capture</property> +                                        <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/> +                                        <signal name="drag-update" handler="gtk_tiling_grid_on_right_gesture_drag_update"/> +                                        <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/> +                                    </object> +                                </child> + +                            </object> +                        </child> + +                        <child> +                            <object class="GtkDockStation" id="right_station"> +                                <property name="orientation">vertical</property> +                                <property name="hexpand">false</property> +                                <property name="vexpand">true</property> +                                <property name="width-request">300</property> +                                <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/> +                                <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/> +                            </object> +                        </child> + +                    </object> +                </child> + +                <layout> +                    <property name="column">2</property> +                    <property name="row">1</property> +                </layout> +            </object> +        </child> + +        <!-- Zone inférieure --> + +        <child> +            <object class="GtkRevealer" id="bottom"> +                <property name="transition-type">slide-up</property> +                <property name="reveal-child">false</property> + +                <child> +                    <object class="GtkBox"> +                        <property name="orientation">vertical</property> + +                        <child> +                            <object class="GtkSeparator" id="bottom_handle"> +                                <property name="orientation">vertical</property> +                                <property name="height-request">5</property> + +                                <child> +                                    <object class="GtkGestureDrag"> +                                        <property name="propagation-phase">capture</property> +                                        <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/> +                                        <signal name="drag-update" handler="gtk_tiling_grid_on_bottom_gesture_drag_update"/> +                                        <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/> +                                    </object> +                                </child> + +                            </object> +                        </child> + +                        <child> +                            <object class="GtkDockStation" id="bottom_station"> +                                <property name="orientation">horizontal</property> +                                <property name="hexpand">true</property> +                                <property name="vexpand">false</property> +                                <property name="height-request">250</property> +                                <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/> +                                <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/> +                            </object> +                        </child> + +                    </object> +                </child> + +                <layout> +                    <property name="column">0</property> +                    <property name="row">2</property> +                    <property name="column-span">3</property> +                </layout> +            </object> +        </child> + +    </template> +</interface> diff --git a/src/gtkext/panel-int.h b/src/gtkext/panel-int.h index 07ade20..cb210d9 100644 --- a/src/gtkext/panel-int.h +++ b/src/gtkext/panel-int.h @@ -30,8 +30,11 @@ +/* Indique l'emplacement par défaut pour un affichage. */ +typedef char * (* get_tiled_panel_path) (const GtkTiledPanel *); +  /* Fournit les composants adaptés pour la barre de titre. */ -typedef GListStore * (* get_tiled_panel_widgets_cb) (GtkTiledPanel *, bool); +typedef GListStore * (* get_tiled_panel_widgets_cb) (const GtkTiledPanel *, bool); @@ -47,6 +50,7 @@ struct _GtkTiledPanelClass  {      GtkBoxClass parent;                     /* A laisser en premier        */ +    get_tiled_panel_path get_default_path;  /* Localisation de l'affichage */      get_tiled_panel_widgets_cb get_widgets; /* Récupération de composants  */  }; diff --git a/src/gtkext/panel.c b/src/gtkext/panel.c index de55917..48019dc 100644 --- a/src/gtkext/panel.c +++ b/src/gtkext/panel.c @@ -137,6 +137,35 @@ static void gtk_tiled_panel_finalize(GtkTiledPanel *panel)  /******************************************************************************  *                                                                             *  *  Paramètres  : panel = panneau graphique à consulter.                       * +*                                                                             * +*  Description : Indique l'emplacement attendu pour un affichage.             * +*                                                                             * +*  Retour      : Chemin représenté ou NULL pour l'emplacement "M" par défaut. * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +char *gtk_tiled_panel_get_path(const GtkTiledPanel *panel) +{ +    char *result;                           /* Chemin à retourner          */ +    GtkTiledPanelClass *class;              /* Classe à actionner          */ + +    class = GTK_TILED_PANEL_GET_CLASS(panel); + +    if (class->get_default_path != NULL) +        result = class->get_default_path(panel); +    else +        result = NULL; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : panel = panneau graphique à consulter.                       *  *                left  = indication quant au côté ciblé.                      *  *                                                                             *  *  Description : Fournit les composants adaptés pour la barre de titre.       * @@ -147,7 +176,7 @@ static void gtk_tiled_panel_finalize(GtkTiledPanel *panel)  *                                                                             *  ******************************************************************************/ -GListStore *gtk_tiled_panel_get_title_widgets(GtkTiledPanel *panel, bool left) +GListStore *gtk_tiled_panel_get_title_widgets(const GtkTiledPanel *panel, bool left)  {      GListStore *result;                     /* Composant(s) à retourner    */      GtkTiledPanelClass *class;              /* Classe à actionner          */ diff --git a/src/gtkext/panel.h b/src/gtkext/panel.h index d2259ef..3b0361e 100644 --- a/src/gtkext/panel.h +++ b/src/gtkext/panel.h @@ -38,8 +38,11 @@  DECLARE_GTYPE(GtkTiledPanel, gtk_tiled_panel, GTK, TILED_PANEL); +/* Indique l'emplacement attendu pour un affichage. */ +char *gtk_tiled_panel_get_path(const GtkTiledPanel *); +  /* Fournit les composants adaptés pour la barre de titre. */ -GListStore *gtk_tiled_panel_get_title_widgets(GtkTiledPanel *, bool); +GListStore *gtk_tiled_panel_get_title_widgets(const GtkTiledPanel *, bool); diff --git a/src/gtkext/statusstack-int.h b/src/gtkext/statusstack-int.h index 2a9e99e..df9db35 100644 --- a/src/gtkext/statusstack-int.h +++ b/src/gtkext/statusstack-int.h @@ -84,6 +84,8 @@ struct _GtkStatusStack      guint network_update_tag;               /* Identifiant de mise à jour  */ +    GtkToggleButton *bottom_toggler;        /* Bascule de panneaux inf.    */ +  };  /* Gestion de barre de statut adaptable (classe) */ diff --git a/src/gtkext/statusstack.c b/src/gtkext/statusstack.c index 76dbee8..492d888 100644 --- a/src/gtkext/statusstack.c +++ b/src/gtkext/statusstack.c @@ -41,6 +41,21 @@  /* -------------------------- GESTION GENERALE DES STATUTS -------------------------- */ +/* Liste des propriétés */ + +typedef enum _StatusStackProperty { + +    PROP_0,                                 /* Réservé                     */ + +    PROP_SHOW_BOTTOM,                       /* Affichage de la zone inf.   */ + +    N_PROPERTIES + +} StatusStackProperty; + +static GParamSpec *_status_stack_properties[N_PROPERTIES] = { NULL, }; + +  /* Initialise la classe des barres de statut améliorées. */  static void gtk_status_stack_class_init(GtkStatusStackClass *); @@ -61,6 +76,17 @@ static gboolean gtk_status_stack_update_network_stats(GtkStatusStack *); +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Met à jour une propriété d'instance GObject. */ +static void gtk_status_stack_set_property(GObject *, guint, const GValue *, GParamSpec *); + +/* Fournit la valeur d'une propriété d'instance GObject. */ +static void gtk_status_stack_get_property(GObject *, guint, GValue *, GParamSpec *); + + +  /* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */ @@ -173,6 +199,15 @@ static void gtk_status_stack_class_init(GtkStatusStackClass *class)      object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose;      object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize; +    object->set_property = gtk_status_stack_set_property; +    object->get_property = gtk_status_stack_get_property; + +    _status_stack_properties[PROP_SHOW_BOTTOM] = +        g_param_spec_boolean("show-bottom", NULL, NULL, +                             TRUE, +                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + +    g_object_class_install_properties(object, N_PROPERTIES, _status_stack_properties);      widget = GTK_WIDGET_CLASS(class); @@ -198,6 +233,8 @@ static void gtk_status_stack_class_init(GtkStatusStackClass *class)      gtk_widget_class_bind_template_child(widget, GtkStatusStack, net_recv_speed);      gtk_widget_class_bind_template_child(widget, GtkStatusStack, net_send_speed); +    gtk_widget_class_bind_template_child(widget, GtkStatusStack, bottom_toggler); +  } @@ -497,6 +534,85 @@ static gboolean gtk_status_stack_update_network_stats(GtkStatusStack *stack) + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  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 : Met à jour une propriété d'instance GObject.                 * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void gtk_status_stack_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ +    GtkStatusStack *stack;                  /* Version spécialisée         */ + +    stack = GTK_STATUS_STACK(object); + +    switch (prop_id) +    { +        case PROP_SHOW_BOTTOM: +            gtk_toggle_button_set_active(stack->bottom_toggler, g_value_get_boolean(value)); +            break; + +        default: +            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); +            break; + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  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 : Fournit la valeur d'une propriété d'instance GObject.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void gtk_status_stack_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ +    GtkStatusStack *stack;                  /* Version spécialisée         */ + +    stack = GTK_STATUS_STACK(object); + +    switch (prop_id) +    { +        case PROP_SHOW_BOTTOM: +            g_value_set_boolean(value, gtk_toggle_button_get_active(stack->bottom_toggler)); +            break; + +        default: +            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); +            break; + +    } + +} + + +  /* ---------------------------------------------------------------------------------- */  /*                      STATUT DES INFORMATIONS DE DESASSEMBLAGE                      */  /* ---------------------------------------------------------------------------------- */ diff --git a/src/gtkext/statusstack.ui b/src/gtkext/statusstack.ui index a9dae28..2a6e256 100644 --- a/src/gtkext/statusstack.ui +++ b/src/gtkext/statusstack.ui @@ -2,6 +2,8 @@  <interface>      <template class="GtkStatusStack" parent="GtkBox"> +        <!--property name="show-bottom" bind-source="bottom_toggler" bind-property="active" bind-flags="bidirectional|sync-create"/--> +          <child>              <object class="GtkStack" id="main">                  <property name="margin-start">8</property> @@ -201,6 +203,7 @@              <object class="GtkToggleButton" id="bottom_toggler">                  <property name="has-frame">false</property>                  <property name="icon-name">dock-station-bottom-symbolic</property> +                <property name="action-name">win.toggle-bottom</property>              </object>          </child> | 
