Vue d'ensemble des Arbres est des Listes

Vue d'ensemble des arbres et des Listes — Vue d'ensemble de  GtkTreeModel, GtkTreeView, et apparentés.

Vue d'ensemble

Pour créer un arbre ou une liste dans GTK+, utilisez l'outils GtkTreeModel associé au widget  GtkTreeView. Ce Widget est composé par l'association Magasin/Visualisateur/ Contrôleur et comporte quatre parties principales :

Le widget de visualisation de l'arbre (GtkTreeView)
Le widget de visualisation des colonnes (GtkTreeViewColumn)
Les afficheurs de cellules (GtkCellRenderer etc.)
L'outils du magasin  (GtkTreeModel)

La Vue est composée par les trois premiers objets, alors que le dernier est le magasin.Un des principaux avantages de l'association MVC est la création de multiples vues  à partir d'un seul magasin. Par exemple, un magasin décrivant un système de fichiers peut être créé pour un gestionnaire de fichiers. Des visualisations différentes peuvent être créées pour afficher des données variées du système de fichiers et ceci  à partir d'une seule copie gardée en mémoire.

Le but des afficheurs de cellule est de procurer des extensions au widget  et de fournir des possibilités multiples pour l'affichage d'un même type de donnée. Par exemple, imaginez la façon d'afficher une variable booléenne. Voudriez-vous l'afficher à l'aide d'une chaîne "True" ou "False", "On" ou "Off", ou  voudriez-vous l'afficher à l'aide d'une boîte à cocher ?

Créer un magasin pour stocker les données

GTK+ fournit deux magasins qui peuvent être utilisés :  GtkListStore et  GtkTreeStore. GtkListStore est utilisé comme magasin des widgets des listes alors que   GtkTreeStore sera le magasin des arbres. Il est possible de évelopper un nouveau type de magasin, mais les modèles existants devraient satisfaire pratiquement toutes les situations même les plus spécialisées. Créer un magasin est assez simple :

GtkListStore *magasin = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);

Cela crée un magasin pour  liste avec deux colonnes : une colonne de chaîne de caractères et une colonne booléenne. Normalement le 2 n'est jamais passé directement comme cela;  habituellement une énumération est créée où chaque colonne est énumérée, suivit par une marque représentant le nombre total de colonnes(traduction douteuse) . L'exemple qui suit illustrera cela,  il utilise seulement un magasin pour arbre à la place du magasin pour liste. La création d'un magasin d'arbre est pratiquement identique à la création de magasin pour liste.

enum
{
COLONNE_TITRE,
COLONNE_AUTEUR,
COLONNE_CHECK,
N_COLONNES,
};

GtkTreeStore *magasin = gtk_tree_store_new (N_COLONNES, /* Nombre total de colonnes*/
G_TYPE_STRING, /* Titre des livres */
G_TYPE_STRING, /* Auteurs */
G_TYPE_BOOLEAN); /* Vérifié */

On ajoute des données dans le magasin à l'aide de gtk_tree_store_set() ou gtk_list_store_set(), en fonction du type de magasin créé. Pour cela un  GtkTreeIter est requis.  L'itérateur se place là où les données seront ajoutées.

Un fois l'itérateur acquis , gtk_tree_store_set()est utilisé pour placer la donnée à l'endroit du magasin où l'itérateur pointe. Obervez l'exemple suivant :

GtkTreeIter iter;
gtk_tree_store_append (magasin, &iter, NULL); /* Acquérir un itérateur */
gtk_tree_store_set (magasin, &iter,
COLONNE_TITRE, "Le Principe de la raison",
COLONNE_AUTEUR, "Martin Heidegger",
COLONNE_CHECK, FALSE,
-1);

Notez que le dernier argument est  -1. Cela est toujours le cas parce que c'est une fonction qui comporte un nombre d'arguments variable et elle a besoin de savoir quand  s'arrête la liste des arguments. Elle peut être utilisée pour définir les données pour  certaines ou toutes les colonnes d'une ligne donnée. 

Le troisième argument de  gtk_tree_store_append()est l'itérateur parent. Il est utilisé pour ajouter une ligne enfant à une ligne d'un  GtkTreeStore. Cela signifie que la nouvelle ligne sera visible uniquement si son parent est visible est dans l'état déployé. Observez l'exemple suivant :

GtkTreeIter iter1; /* iter parent*/
GtkTreeIter iter2; /* iter enfant */
gtk_tree_store_append (magasin, &iter1, NULL); /* Acquérir un itérateur de niveau supérieur*/
gtk_tree_store_set (magasin, &iter1,
COLONNE_TITRE, "L'art de la programmation sur ordinateur",
COLONNE_AUTEUR, "Donald E. Knuth",
COLONNE_CHECK, FALSE,
-1);
gtk_tree_store_append (magasin, &iter2, &iter1); /* Acquérir un itérateur enfant */
gtk_tree_store_set (magasin, &iter2,
COLONNE_TITRE, "Volume 1: Algorithmes fondamentaux ",
-1);
gtk_tree_store_append (magasin, &iter2, &iter1);
gtk_tree_store_set (magasin, &iter2,
COLONNE_TITRE, "Volume 2: Algorithmes semi-numériques",
-1);
gtk_tree_store_append (magasin, &iter2, &iter1);
gtk_tree_store_set (magasin, &iter2,
COLONNE_TITRE, "Volume 3: Tri et recherche",
-1);

Création de l'afficheur

Alors qu'il existe plusieurs magasins différents, on utilisera qu'un seul widget de visualisation. Il focntionne aussi bien avec un magasin de  liste qu'avec un magasin d'arbre. La création d'un  GtkTreeView n'est pas compliquée. Il aura besoin d'un GtkTreeModel pour savoir où trouver les données qui le composeront.

GtkWidget *arbre;
arbre = gtk_tree_view_new_with_model (GTK_TREE_MODEL (magasin));

Afficheurs de colonnes et de cellules

Une fois qu'un magasin a été attribué au widget GtkTreeView, il aura besoin de savoir comment afficher ce magasin. Il le fera à l'aide des colonnes et des cellules.

Les afficheurs de cellules sont utilisés pour dessiner les données dans le magasin d'un arbre d'une certaine façon. Plusieurs sortes d'afficheurs de cellules sont arrivés avec GTK+ 2.x, ce sont  GtkCellRendererText, GtkCellRendererPixbuf et  GtkCellRendererToggle. Il est relativement facile d'écrire un affichage préfabriqué.

Un GtkTreeViewColumn est un objet que  GtkTreeView utilise pour organiser les colonnes dans une vue en arbre. Il aura besoin de connaître le nom de la colonne qui sera affichée pour l'utilisateur, le type d'afficheur de cellule utilisé et  la partie des données du magasin à rechercher pour une ligne donnée.


GtkCellRenderer *afficheur;
GtkTreeViewColumn *colonne;
afficheur = gtk_cell_renderer_text_new (); /*afficheur de texte*/
colonne = gtk_tree_view_column_new_with_attributes ("Auteur",
afficheur,
"text", COLONNE_AUTEUR,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (arbre), colonne);

A ce stade ,toutes les étapes de la création d'un arbre ont été vues. Le magasin est créé, les données y sont stockées, un arbre a été créé et des colonnes lui ont été ajoutées.




Manipulation de la sélection

En plus d'afficher de simples données, beaucoup d'applications ont besoin de recevoir des événements envoyés par l'utilisateur.Pour cela,  il suffit d'avoir un référent de l'objet sélection et de le connecter au signal "changed".
/* Prototype du callback de traitement de la sélection */
static void selection_arbre_change_cb (GtkTreeSelection *selection, gpointer data);

/* Définir le traitement de la sélection */

GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (arbre));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);

g_signal_connect (G_OBJECT (selection), "changed",
G_CALLBACK (tree_selection_changed_cb),
NULL);

Ensuite pour trouver les données d'une ligne sélectionnée :


static void
selection_arbre_change_cb (GtkTreeSelection *selection, gpointer data)
{
GtkTreeIter iter;
GtkTreeModel *magasin;
gchar *auteur;
if (gtk_tree_selection_get_selected (selection, &magasin, &iter))
{
gtk_tree_model_get (magasin, &iter, COLONNE_AUTEUR, &auteur, -1);
g_print ("Vous avez sélectionné un livre de %s\n", auteur);
g_free (auteur);
}
}

Exemple Simple

Maintenant voici un simple exemple d'utilisation du widget  GtkTreeView en association avec les autres widgets. Cet exemple crée simplement un magasin et un vue en les associant. Notez que ce magasin  ne contiendra aucune donnée — ce sera un bon exercice pour le lecteur. Vous pourrez trouver plus d'informations à ce sujet dans la section GtkTreeModel.

enum
{
COLONNE_TITRE,
COLONNE_AUTEUR,
COLONNE_CHECK,
N_COLONNES,
};

void
configurer_arbre(void)
{
GtkTreeStore *magasin;
GtkWidget *arbre;
GtkTreeViewColumn *colonne;
GtkCellRenderer *afficheur;

/* Création d'un magasin. Nous allons utiliser la magasin pour arbre, mais nous
aurions pu utiliser un autre type de GtkTreeModel */
magasin = gtk_tree_store_new (N_COLONNES,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_BOOLEAN);

/* Fonction préfabriquée pour remplir le magasin de données */
populate_tree_model (magasin);

/* Créer un visionneur */
arbre = gtk_tree_view_new_with_model (GTK_TREE_MODEL (magasin));

/* Le visionneur maintenant prend une référence. Nous pouvons nous débarasser
de notre propre référence */
g_object_unref (G_OBJECT (magasin));

/* Créer un afficheur de cellule et la colorier en rouge par exemple
pour la démontration.*/
afficheur = gtk_cell_renderer_text_new ();
g_object_set (G_OBJECT (afficheur),
"foreground", "red",
NULL);

/* Créer une colonne, l'associer à l'attribut "text" de
* m'afficheur de cellules pour la première colonne du magasin */
colonne = gtk_tree_view_column_new_with_attributes ("Auteur", afficheur,
"text", COLONNE_AUTEUR,
NULL);

/* Ajouter la colonne au visualiseur. */
gtk_tree_view_append_column (GTK_TREE_VIEW (arbre), colonne);

/* Deuxième colonne.. titre du livre. */
afficheur = gtk_cell_renderer_text_new ();
colonne = gtk_tree_view_column_new_with_attributes ("Titre",
afficher,
"text", COLONNE_TITRE,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (arbre), colonne);

/*Dernière colonne.. si un livre a été vérifié. */
afficheur = gtk_cell_renderer_toggle_new ();
colonne = gtk_tree_view_column_new_with_attributes ("Vérifié",
afficher,
"active", COLONNE_CHECK,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (arbre), colonne);

/* Maintenant nous pouvons manipuler le visuamisateur comme tout autre widget GTK */
...
}