Tutoriel Gtk2Hs

4.6 Zone de saisie de texte et barres d’état

Le widget Entry permet de taper du texte et de l’afficher sur une seule ligne. Un grand nombre de choses peuvent être faites par défaut comme insérer ou remplacer du texte, …

On crée un nouveau widget Entry avec la fonction:

entryNew :: IO Entry

Pour remplacer ou récupérer le texte en cours d’édition dans le widget Entry:

entrySetText :: EntryClass self => self -> String -> IO ()

entryGetText :: EntryClass self => self -> IO String

Si on veut empêcher que le contenu de Entry soit modifié par l’utilisateur, on change sont état . On peut aussi définir: la (pour les mots de passe), le nombre maximum de caractères (0 si illimité), si la zone a un cadre ou non, l’espace à laisser et d’autres attributs. L’autoremplissage du texte est également possible (Voir la documentation de EntryCompletion dans l’API pour son utilisation). Les attributs de Entry qui peuvent évidemment être accessibles avec get et set sont:

entryEditable :: EntryClass self => Attr self Bool  -- default True

entryVisibility :: EntryClass self => Attr self Bool  -- default True

entryMaxLength :: EntryClass self => Attr self Int -- 0 if no maximum, limit 66535

entryHasFrame :: EntryClass self => Attr self Bool -- default False

entryWidthChars :: EntryClass self => Attr self Int -- default -1, no space set

Le type Entry est une instance de EditableClass et certains attributs et méthodes sont définis ici. Les plus utiles sont:

editableInsertText :: EditableClass self => self -> String -> Int -> IO Int

editableDeleteText :: EditableClass self -> Int -> Int -> IO ()

editableSelectRegion :: EditableClass self => self -> Int -> Int -> IO ()

editableDeleteSelection :: EditableClass self -> IO ()

Les arguments de type Int indiquent la position de départ ou de fin. L’utilisateur peut aussi copier, coller et couper depuis et vers le presse-papier.

editableCutClipboard :: EditableClass self => self -> IO ()

editableCopyClipboard :: EditableClass self => self -> IO ()

editablePasteClipboard :: EditableClass self => self -> IO ()

Elles prennent toutes la position courante du curseur. Vous pouvez obtenir et définir cette position avec:

editableGetPosition :: EditableClass self => self -> IO Int

editableSetPosition :: EditableClass self => self -> Int

Le curseur est affiché avant le caractère indexé (début à 0) dans le widget. La valeur doit être inférieure ou égale au nombre de caractères dans le widget. Une valeur de -1 indique que la position doit être définie après le dernier caractère de la zone de saisie.

La classe Editable a un certain nombre de signaux qui utilisent des fonctions de haut niveau (que nous n’aborderons pas ici). Le widget Entry lui-même a un signal qui est envoyé après que l’utilisateur ait appuyé sur la touche Enter:

onEntryActivate :: EntryClass ec => ec -> IO () -> IO (ConnectId ec)

Il y a aussi des signaux envoyés quand le texte est copié, coupé, collé vers le presse-papier et quand l’utilisateur bascule entre le mode insertion et remplacement.

Les barres d’état sont de simples widgets utilisés pour afficher un message. Elles gardent une liste des messages qui leur sont envoyés de telle sorte que afficher le message courant ré-affichera le précédent message texte. Une barre d’état possède une poignée de redimensionnement par défaut de sorte que l’utilisateur peut la redimensionner.

Afin de permettre aux différents composants d’une application d’utiliser la même barre d’état pour afficher les messages, le widget barre d’état utilise les ContextId qui sont utilisés pour identifier les différents . Le message au dessus de la pile est celui qui est affiché quelque soit le contexte qui l’utilise. Les messages sont empilés suivant un processus dernier-entré, premier sorti. Une barre d’état se crée avec:

statusbarNew :: IO Statusbar

Un nouveau ContextId est généré avec la fonction suivante avec une chaîne de caractères String utilisée comme description du contexte:

statusbarGetContextId :: StatusbarClass self => self -> String -> IO ContextId

Il y a trois fonctions qui permettent d’intervenir sur les barres d’état.

statusbarPush :: StatusbarClass self => self -> ContextId -> String -> IO MessageId

statusbarPop :: StatusbarClass self => self -> ContextId -> IO ()

statusbarRemove :: StatusbarClass self => self -> ContextId -> MessageId -> IO ()

La première, statusbarPush, est utilisée pour ajouter un nouveau message à la barre d’état. Elle retourne un MessageId qui peut par la suite être passé à statusbarRemove pour supprimer le message avec le ContextId et le MessageId de la pile de la barre d’état. La fonction statusbarPop enlève le message au dessus de la pile avec l’identifiant de contexte donné.

Les barres d’état, comme les barres de progression sont utilisées pour afficher des messages à l’utilisateur sur les opérations en cours. Dans l’exemple qui suit, nous allons simuler une telle opération en testant si le texte que l’utilisateur soumet (en pressant la touche Enter) est le même que son inverse, et en renvoyant le résultat dans la pile. L’utilisateur peut voir les résultats en appuyant sur le bouton information qui affiche alors les messages de la pile. La première fois, la pile est vide et le bouton est grisé avec:

widgetSetSensitivity :: WidgetClass self => self -> Bool -> IO ()
Gtk Gtk2Hs Status bar example
import Graphics.UI.Gtk

main :: IO ()
main= do
  initGUI
  window <- windowNew
  set window [windowTitle := "Text Entry", containerBorderWidth := 10]

  vb <- vBoxNew False 0
  containerAdd window vb

  hb <- hBoxNew False 0
  boxPackStart vb hb PackNatural 0

  txtfield <- entryNew
  boxPackStart hb txtfield PackNatural 5
  button <- buttonNewFromStock stockInfo
  boxPackStart hb button PackNatural 0

  txtstack <- statusbarNew
  boxPackStart vb txtstack PackNatural 0
  id <- statusbarGetContextId txtstack "Line"

  widgetShowAll window
  widgetSetSensitivity button False

  onEntryActivate txtfield (saveText txtfield button txtstack id)
  onPressed button (statusbarPop txtstack id)
  onDestroy window mainQuit
  mainGUI

saveText :: Entry -> Button -> Statusbar -> ContextId -> IO ()
saveText fld b stk id = do
    txt <- entryGetText fld
    let mesg | txt == reverse txt = "\"" ++ txt ++ "\""  ++
                                    " is equal to its reverse"
             | otherwise =  "\"" ++ txt ++ "\""  ++
                            " is not equal to its reverse"
    widgetSetSensitivity b True
    msgid <- statusbarPush stk id mesg
    return ()