Object +-- Widget +-- Container +-- CList
Le widget CList a remplacé le widget List ( qui est toujours disponible ).
Le widget CList est un widget liste Multi-colonnes qui est capable de manipuler littéralement des milliers de colonnes d'information. Chaque colonne peut optionnellement avoir un titre, qui lui-même est optionnellement actif, ce qui nous permet de relier une fonction à sa sélection.
Créer un widget CList se fait plutôt facilement quand on a compris le fonctionnement des widgets en général. Il fournit les presque standards deux méthodes : la difficile et la facile. Mais, avant de le créer, il y a une chose qu'il nous faut connaître : combien devrait-il y avoir de colonnes ?
Toues les colonnes n'ont pas besoin d'être visibles mais peuvent stocker des données qui font référence à certains cellules de la liste.
$clist = new Gtk::CList( $columns ); $clist = new_with_titles Gtk::CList( @titles );
La première méthode est très directe en revanche la seconde nécessite quelques explications. Chaque colonne peut posséder un titre associé et ce titre peut être un label ou un bouton qui réagit quand on clique dessus. Si nous utilisons la seconde forme, nous fournissons une liste de titres et le nombre d'éléments de cette liste correspond au nombre de colonnes de notre CList. Bien sûr, nous pouvons toujours utiliser la première méthode et ajouter manuellement les titres plus tard.
Note : Le widget CList ne fournit pas sa propre barre de défilement et devrait être placé dans une fenêtre défilable si vous avez besoin de cette fonctionnalité. C'est un changement par rapport à l'implémentation 1.0 de GTK.
Il y a plusieurs attributs qui peuvent être utiliser pour changer le comportement d'une CList. Tout d'abord :
$clist->set_selection_mode( $mode );
qui, comme son nom l'indique, déclare le mode de sélection de la CList. L'argument spécifie le mode de sélection d'un cellule ( ils sont définis dans le fichier header de Gtk en C gtkenum.h). Au moment ou j'écris, les modes suivants sont disponibles :
'single' - La sélection est soit vide soit sa liste ne contient qu'un
seul élément sélectionné.
'browse' - La sélection est vide si la liste ne contient aucun widget
ou seulement des insensibles, autrement il contient une liste avec un élément.
'multiple' - La sélection est vide si aucun des éléments n'est sélectionné
ou bien une liste de tous les items sélectionnés. Valeur par défaut pour
le widget CList.
'extended' - La sélection est toujours vide.
D'autres peuvent avoir été ajoutées aux dernières versions de GTK.
Vous pouvez aussi définir à quoi va ressembler le bord du widget CList, grâce à la fonction :
$clist->set_shadow_type( $border );
Les valeurs possibles de $border sont :
'none' 'in' 'out' 'etched_in' 'etched_out'
Quand vous créez un widget CList, vous récupérerez également un ensemble de boutons automatiquement. Ils sont situés en haut de la fenêtre CList, et peuvent soit se comporter comme des boutons normaux qui répondent quand on appuie dessus soit être inactifs auquel cas ils ne sont que de simples titres. Il existe quatre fonctions pour nous aider à déclarer le statut des boutons de titres :
$clist->column_title_active( $column ); $clist->column_title_passive( $column ); $clist->column_titles_active(); $clist->column_titles_passive();
Un titre actif est un titre qui réagit comme un bouton normal, un titre inactif n'est qu'un label. Les deux premiers appels ci-dessus activent/désactivent le bouton de titre au dessus de colonnes spécifiques, alors que les deux derniers activent.désactivent tous les boutons de titres du widget CList.
Mais, bien sûr, il a des cas ou vous ne les voudrez pas du tout, c'est pourquoi ils peuvent être cachés ou montrés à volonté à l'aide des fonctions :
$clist->column_titles_show(); $clist->column_titles_hide();
Pour que les titres soient vraiment utiles, nous avons besoin d'un mécanisme pour les déclarer et les changer. Cela se fait avec :
$clist->set_column_title( $column, $title );
Notez que seul le titre d'un colonne peut être déclaré à la fois, c'est pourquoi
si tous les titres sont connus dès le début, je suggère d'utiliser new_with_titles Gtk::CList().
Cela vous économise du temps et vos programmes sont plus courts. Il est des
fois ou le travail manuel est plus efficace, entre autres, quand tous les titres
ne sont pas des textes. CList nous fournit des boutons de titres qui peuvent
contenir des widgets entiers, comme par exemple un pixmap. Cela se fait avec
:
$clist->set_column_widget( $column, $widget );
qui ne nécessite aucune explication particulière.
Il est possible de modifier la justification d'une colonne avec :
$clist->set_column_justification( $column, $justification );
$justification peut prendre les valeurs suivantes :
'left' - Le texte commencera à partir du bord gauche de la colonne.
'right' - Le texte commencera à partir du bord droit de la colonne.
'center' - Le texte sera placé au centre de la colonne.
'fill' - Le texte utilisera toute la place disponible dans la colonne.
Cela se fait en insérant des espaces blancs entre les mots ( ou entre chaque
lettre s'il s'agit d'un seul mot ). Comme dans n'importe quel éditeur WYSIWYG.
La prochaine fonctionne est très importante et devrait être standard pour l'installation de tous les widgets CList. Quand la liste est créée, la largeur des diverses colonnes est choisie par rapport au titre, et comme c'est rarement la largeur qui convient, nous aurons donc à la déclarer avec :
$clist->set_column_width( $column, $width );
Notez que la largeur est donnée en pixels et non en lettres. On fait de même pour la hauteur des cellules de la colonne mais comme la valeur par défaut est fonction de la taille de la police de caractère, ce n'est pas aussi critique pour l'application. Toutefois, on peut le faire avec :
$clist->set_row_height( $height );
Encore, notez que la hauteur est donnée en pixels.
Nous pouvons également déplacer un liste sans que l'utilisateur intervienne, toutefois cela nécessite de savoir ce que nous voulons. En d'autres termes, nous avons besoin de la ligne et de la colonne de l'élément que nous voulons bouger.
$clist->moveto( $row, $column, $row_align, $col_align );
$row_align est très important à comprendre. C'est une valeur entre 0.0
et 1.0 ou 0.0 signifie que nous bougeons la ligne en faisant en sorte que la
ligne apparaisse en haut alors que la valeur de 1.0 implique la ligne apparaîtra
en bas. Toutes les autres valeurs entre 0.0 et 1.0 sont également valables et
placerons la ligne entre le haut et le bas. Le dernier argument $col_align
fonctionne de la même manière sauf que 0.0 correspond à gauche et 1.0 à droite.
En fonction des besoins de l'application, nous n'avons pas toujours à déplacer un élément qui nous est déjà visible. Oui mais comment savoir si il est visible ? Comme d'habitude, il y a une fonction qui nous permet de répondre :
$clist->row_is_visible( $row );
La valeur retournée est l'une des suivante :
'none' 'partial' 'full'
Notez que cela ne nous renseigne que sur la colonne. Pour l'instant, Il n'y
a aucun moyen de le déterminer pour la colonne. Nous pouvons cependant avoir
une information partielle parce que si la valeur de retour est partial,
alors un bout de la ligne est caché mais nous ne savons pas si la ligne est
coupé dans sa partie inférieure ou si elle possède des colonnes à l'extérieur.
Nous pouvons également changer la couleur de la police et la couleur du fond d'une ligne particulière. Cela est utile pour indiquer la ligne sélectionneée par l'utilisateur. Les deux fonctions qui le permettent sont :
$clist->set_foreground( $row, $color ); $clist->set_background( $row, $color );
Notez toutefois que les couleurs doivent avoir été préalablement allouées.
Vous pouvez ajouter des lignes de trois manières. Elles peuvent être placées avant la liste ou après à l'aide de :
$clist->prepend( @text ); $clist->append( @text );
La valeur de retour de ces deux fonctions indique la position à laquelle a été ajoutée la colonne. Vous pouvez insérer une colonne à une position donnée :
$clist->insert( $row, @text );
Avec ces appels, nous devons fournir une liste des textes que nous voulons mettre dans les colonnes. Le nombre de textes devraient être égal au nombre de colonnes de la liste. Si la liste de texte est vide alors il n'y aura pas de texte dans les colonnes de la ligne. C'est utile si vous voulez placer des pixmaps à la place (chose qui doit être faite manuellement).
Faites attention toutefois au fait que l'on commence à numéroter les lignes et les colonnes par 0.
Pour supprimer une ligne, on utilise :
$clist->remove( $row );
Il existe également un appel qui enlève toutes les lignes de la listes. C'est
un peu plus rapide que d'appeler $clist->remove( $row ) pour chaque colonne,
ce qui représente une alternative. Il suffit de faire :
$clist->clear();
Il existe également deux fonctions bien utile qui doivent être utilisées quand beaucoup de changements doivent être faits sur une liste. Cela empêche la liste de clignoter quand on la met à jour de manière répétitive ce qui peut être très ennuyeux pour l'utilisateur. C'est pourquoi c'est une bonne idée de geler la liste, de faire les mises à jour et enfin de la dégeler ainsi la liste mise à jour apparaîtra à l'écran.
$clist->freeze(); $clist->thaw();
Une cellule peut contenir un pixmap, du texte ou les deux. Pour les placer, les fonctions suivantes peuvent être utilisées :
$clist->set_text( $row, $column, $text ); $clist->set_pixmap( $row, $column, $pixmap, $mask ); $clist->set_pixtext( $row, $column, $text, $spacing, $pixmap, $mask );
C'est plutôt clair. Tous les appels possèdent la ligne et la colonne suivis
de la donnée à placer. L'argument $spacing dans set_pixtext()
est le nombre de pixels entre le pixmap et le début du texte. Dans tous les
cas la donnée est copiée dans le widget.
Pour lire les données, on utilise en revanche :
$text = $clist->get_text( $row, $column ); ( $pixmap, $mask ) = $clist->get_pixmap( $row, $column ); ( $text, $spacing, $pixmap, $mask = $clist->get_pixtext( $row, $column );
Les valeurs de retour sont toutes des références aux données stockées donc les données référencées ne devraient pas être modifiées.
Il y a un appel supplémentaire qui relate ce qui est dans une cellule de la liste :
$clist->get_cell_type( $row, $column );
qui retourne le type de donnée contenue dans la cellule. La valeur de retour peut être :
'empty' 'text' 'pixmap' 'pixtext' 'widget'
Il existe également une fonction qui permet de déclarer l'indentation à la fois verticale et horizontale d'une cellule. La valeur de l'indentation est donnée en pixels et peut être soit positive soit négative.
$clist->set_shift( $row, $column, $vertical, $horizontal );
Avec une CList il est possible de déclarer une donnée. Cette donnée ne sera pas visible de l'utilisateur mais simplement une possibilité pour le programmeur d'associer une colonne avec des données supplémentaires.
Ces fonctions sont suffisamment explicites :
$clist->set_row_data( $row, $data ); $clist->set_row_data_full( $row, $data, $destroy ); $clist->get_row_data( $row ); $clist->get_row_from_data( $data );
Il existe des fonctions qui nous permettent de forcer une sélection ou une désélection d'une ligne :
$clist->select_row( $row, $column ); $clist->unselect_row( $row, $column );
Il y a également une fonction qui lit les coordonnées X et Y ( par exemple, du pointeur de souris ) et les transcrit par rapport à la liste, retournant la ligne et la colonne correspondantes.
( $row, $column ) = $clist->get_selection_info( $x, $y );
Quand nous détectons quelque chose digne d'intérêt ( cela peut être un mouvement de la souris ou un clic quelque part dans la liste ) nous pouvons lire les coordonnées du pointeur et trouver où il se trouve dans la liste. Trop lourd ? Heureusement, il y a une méthode plus simple ...
Comme pour tous les autres widgets, quelques signaux peuvent être utilisés. Le widget CList est dérivé du widget Container donc il possède les mêmes signaux mais vous pouvez y ajouter :
'select_row' - Le signal enverra les informations suivantes dans l'ordre
: la CList, la ligne, la colonne et l'évènement.
'unselect_row' - Quand l'utilisateur désélectionne une ligne, ce signal
est activé. Il envoie les mêmes informations que 'select_row'.
'click_column' - Envoie une CList et une colonne.
Si vous voulez connecter un rappel à 'select_row', la fonction de rappel
sera déclarée comme ceci :
sub select_row_callback
{
my ( $widget, $row, $column, $event, @data ) = @_;
}
Le rappel est connecté comme d'habitude par :
$clist->signal_connect( "select_row", \&select_row_callback, @data );
#!/usr/bin/perl -wuse Gtk;
use strict;
init Gtk;
my $false = 0;
my $true = 1;
my $window;
my $vbox;
my $hbox;
my $scrolled_window;
my $clist;
my $button_add;
my $button_clear;
my $button_hide_show;
my $titles_visible = $false;
my @titles = ( "Ingredients", "Amount" );
$window = new Gtk::Window( "toplevel" );
$window->set_usize( 300, 150 );
$window->set_title( "CList Example" );
$window->signal_connect( "destroy", sub { Gtk->exit( 0 ); } );
$vbox = new Gtk::VBox( $false, 5 );
$window->add( $vbox );
$vbox->border_width( 5 );
$vbox->show();
# Crée une fenêtre défilable pour y placer la CLIst
$scrolled_window = new Gtk::ScrolledWindow( undef, undef );
$vbox->pack_start( $scrolled_window, $true, $true, 0 );
$scrolled_window->set_policy( 'automatic', 'always' );
$scrolled_window->show();
# Crée la CList. Pour cet exemple, nous utilisons 2 colonnes
$clist = new_with_titles Gtk::CList( @titles );
# Quand une sélection est faite, nous voulons le savoir. Le rappel
# utilisé est selection_made et son code peut être trouvé plus loin
$clist->signal_connect( "select_row", \&selection_made );
# Il n'est pas nécessaire qu'il y ait une ombre au bord
# mais ça a une bonne tête:)
$clist->set_shadow_type( 'out' );
# Autrement plus important, déclarer la largeur des colonnes sinon
# ce ne sera jamais bon. Noter que les colonnes sont numérotées de 0 à plus
# ( 1 dans notre cas )
$clist->set_column_width( 0, 150 );
# Ajoute la CList dans la boîte verticale et la montre
$scrolled_window->add( $clist );
$clist->show();
# Crée les boutons et les ajoute à la fenêtre
$hbox = new Gtk::HBox( $false, 0 );
$vbox->pack_start( $hbox, $false, $true, 0 );
$hbox->show();
$button_add = new Gtk::Button( "Add List" );
$button_clear = new Gtk::Button( "Clear List" );
$button_hide_show = new Gtk::Button( "Hide/Show Titles" );
$hbox->pack_start( $button_add, $true, $true, 0 );
$hbox->pack_start( $button_clear, $true, $true, 0 );
$hbox->pack_start( $button_hide_show, $true, $true, 0 );
# Connecte nos retours à nos trois boutons
$button_add->signal_connect( "clicked", \&button_add_clicked, $clist );
$button_clear->signal_connect( "clicked", sub { $clist->clear(); } );
$button_hide_show->signal_connect( "clicked", \&button_hide_show_clicked, $clist );
$button_add->show();
$button_clear->show();
$button_hide_show->show();
$window->show();
main Gtk;
exit( 0 );
### Routines
# L'utilisateur a cliqué sur le bouton ``add list'' ( ajoute une liste )
sub button_add_clicked { my ( $widget, $clist ) = @_; my $i; # Quelque chose de bête à ajouter à la liste. # 4 lignes de 2 colonnes chacune. my @drink = ( [ Milk => "3 Oz" ], [ Water => "6 l" ], [ Carrots => "2" ], [ Snakes => "55" ] ); # Ici nous ajoutons effectivement les textes. # C'est fait une fois pour chaque ligne. for ( $i = 0; $i < 4; $i++ ) { $clist->append( @{$drink[ $i ]} ); } # Pour ceux qui n'aurait pas compris ce qui précède, voici une brève # explication. @drink est une liste de référence de liste ( les références # sont des scalaires contenant une adresse mémoire, semblables aux # pointeurs). Ils sont utilisés car Perl ne supporte pas directement # les tableaux à deux dimensions. A cause de cela, $drink[i] n'est # pas une liste mais une référence à une liste, ainsi nous devons # la déréférencer en l'enfermant ainsi : @{référence} ( nous devons # utiliser @ parce ce que c'est une référence à une liste. Pour plus # d'informations sur les références, voir la page man perlref(1) # ou le chapitre 4 de Programmer en Perl. return; }
# L'utilisateur a cliqué sur le bouton ``Hide/Show titles''
# Cacher ou montrer les titres
sub button_hide_show_clicked { my ( $widget, $clist ) = @_; if ( $titles_visible ) { # Cache les titres et déclare le flag égal à 1 $clist->column_titles_hide(); $titles_visible++; } else { # Montre les titres et déclare le flag égal à 0 $clist->column_titles_show(); $titles_visible-; } return; }
# Si on arrive là, l'utilisateur a sélectionné une ligne de la liste
sub selection_made { my ( $clist, $row, $column, $event, @data ) = @_; my $text; # Récupère le texte qui est stocké à la ligne et la colonne cliquées. # Nous le recevrons comme un pointeur du texte de l'argument $text=$clist->get_text( $row, $column ); # Imprime juste quelques informations à propos de la ligne sélectionnée print( "You selected row $row. More specifically, you clicked in\n" ); print( "column $column, and the text in this cell is:\n" ); print( " $text\n\n" ); return; }