Tutoriel Gtk2Hs

5.4 Bloc-notes

Le widget Notebook est un ensemble de qui se superposent l’une sur l’autre. Chaque page est différente mais une seule sera visible à la fois. Les pages contiennent d’autres widget que vous devez spécifier.

Pour créer un widget bloc-notes:

NotebookNew :: IO Notebook

Une fois que le bloc-notes a été créé, il y a un certain nombre de fonctions et d’attributs qu’on peut utiliser pour le personnaliser. Les attributs suivant définissent la position des touches et si elles sont visibles ou non.

notebookTabPos :: NotebookClass self => Attr self PositionType
notebookShowTabs :: NotebookClass self => Attr self Bool

PositionType possède les constructeurs suivant: PosLeft, PosRight, PosTop (par défaut) et PosBottom.

Maintenant intéressons-nous à la façon d’ajouter des pages au bloc-notes. Il y a trois façon d’ajouter: Ajouter au début (prepend), ajouter à la fin (append) et l’insertion.

noteBookAppendPage :: (NotebookClass self, WidgetClass child)
  => self
  -> child         -- the widget to use as the contents of the page
  -> String        -- the label text
  -> IO Int        -- the index (page number) of the new page (starting at 0)

La fonction notebookPrependPage a exactement le même type. Bien sur il retournera 0 comme index. La fonction notebookInsertPage prend comme paramètre additionnel, l’index ou placer la page. Vous pouvez supprimer des pages avec notebookRemovePage.

Un Notebook est un widget conteneur qui peut contenir d’autres widgets comme par exemple des boites horizontales et verticales. De cette façon, on peut construire des pages assez complexes et les remplir avec les fonctions standards de remplissage.

Les fonctions listées pour ajouter et insérer des pages fonctionnent seulement pour des onglets à texte. Toutes les trois ont des versions qui permettent d’utiliser un menu déroulant et avec lesquelles on peut utiliser n’importe quel widget comme étiquette.

notebookAppendPageMenu ::
  (NotebookClass self, WidgetClass child, WidgetClass tabLabel, WidgetClass menuLabel)
  => self
  -> child           -- the widget to use as the contents of the page
  -> tabLabel        -- the widget to use as the label of the page
  -> menuLabel       -- the widget to use as the label of the popup menu
  -> IO Int          -- the index (page number) of the new page (starting at 0)

notebookPrependPageMenu et notebookInsertPageMenu placent la nouvelle page en premier ou à la place indiquée.

Certains attributs utiles sont :

notebookScrollable :: NotebookClass self => Attr self Bool
notebookCurrentPage :: NotebookClass self => Attr self Int
notebookEnablePopup :: NotebookClass self => Attr self Bool

Si il y a un grand nombre de pages, vous pouvez utiliser notebookScrollable. Utilisez notebookCurrentPage ou la fonction notebookSetCurrentPage pour ouvrir le bloc-note à une autre page que la première. L’attribut notebookEnablePopup détermine si l’utilisateur, en cliquant sur le bouton droit de la souris sur un onglet, verra un menu déroulant de toutes les pages disponibles.

Un widget Notebook a son propre signal:

onSwitchPage :: NotebookClass nb => nb -> (Int -> IO ()) -> IO (ConnectId nb)

La fonction que vous devez fournir prend un index de page (renvoyé par onSwitchPage) et doit exécuter quelques opérations.

Les exemples montre un catalogue d’icônes StockItem.

Gtk Gtk2Hs Notebook Example 1

Les StockItem ont été abordés sommairement dans le chapitre 4.5. Rappelons que un StockItem est reconnu par GTK+ (et Gtk2Hs). La fonction suivante produit une liste de tous les identifiants reconnus.

stockListIds :: IO [StockId]

Un StockId est une chaîne de caractères String et dans Gtk2Hs a la forme stockCopy , stockDialogError, etc… L’exemple définit une fonction tabName pour convertir les identifiants GTK+ dans la liste des identifiants StockId pour les onglets du bloc-note. La fonction myNewPage utilise imageNewFromStock pour passer de l’icône à un widget Image qui est ensuite ajouté à la page. Elle retourne l’index de la page (Mais cela ne sert pas dans le programme). Pour obtenir une liste de toutes les pages utilisez séquence au lieu de séquence_

Notez que la taille de l’icône, en pixels, peut être restreinte. La valeur par défaut est 4 et la valeur utilisée ici est 6.

import Graphics.UI.Gtk
import Data.Char (toUpper)

main :: IO ()
main= do
     initGUI
     window <- windowNew
     set window [windowTitle := "Notebook Example 1", windowDefaultWidth := 300,
                 windowDefaultHeight := 200 ]
     
     ntbk <- notebookNew
     containerAdd window ntbk
     set ntbk [notebookScrollable := True, notebookTabPos := PosBottom]

     stls <- stockListIds
     sequence_ (map (myNewPage ntbk) stls)

     onSwitchPage ntbk (putStrLn . ((++)"Page: ") . show)

     widgetShowAll window
     onDestroy window mainQuit
     mainGUI

tabName :: StockId -> String
tabName st = (drop 3) (conv st) where
                  conv (x:[]) = x:[]
                  conv (x:y:ys) | x == '-' = (toUpper y):(conv ys)
                                | otherwise = x: (conv (y:ys))

myNewPage :: Notebook -> StockId -> IO Int
myNewPage noteb stk = 
          do img <- imageNewFromStock stk 6
             pagenum <- notebookAppendPage noteb img (tabName stk)
             return pagenum  

Une deuxième façon de montrer le catalogue est de mettre les icônes dans les onglets du bloc-note.

Gtk Gtk2Hs Notebook Example 2
import Graphics.UI.Gtk
import Data.Char (toUpper)

main :: IO ()
main= do
     initGUI
     window <- windowNew
     set window [windowTitle := "Notebook Example 2", windowDefaultWidth := 300,
                 windowDefaultHeight := 200 ]
     
     ntbk <- notebookNew
     containerAdd window ntbk
     set ntbk [notebookScrollable := True, notebookEnablePopup := True,
                    notebookTabPos := PosRight ]

     stls <- stockListIds
     sequence_ (map (myNewPage ntbk) stls)

     onSwitchPage ntbk (putStrLn . ((++)"Page: ") . show)

     widgetShowAll window
     onDestroy window mainQuit
     mainGUI

tabName :: StockId -> String
tabName st = (drop 3) (conv st) where
                  conv (x:[]) = x:[]
                  conv (x:y:ys) | x == '-' = (toUpper y):(conv ys)
                                | otherwise = x: (conv (y:ys))

myNewPage :: Notebook -> StockId -> IO Int
myNewPage noteb stk = 
          do img <- imageNewFromStock stk 4
             let nmstr = tabName stk
             men <- labelNew (Just ((take 1) nmstr))
             cont <- labelNew (Just ("stock" ++ nmstr))
             pagenum <- notebookAppendPageMenu noteb cont img men
             return pagenum