El widget
Notebook
(bloc de notas) es una colección de "páginas" que
se superponen. Cada página es diferente, y sólo una es visible en cada
momento. Las páginas contienen otros widgets que el programador suministra.
Para crear un nuevo widget Notebook:
NotebookNew :: IO Notebook
Una vez que el bloc de notas ha sido creado, dispones de funciones y atributos para ajustarlo a tus necesidades o gustos. Los siguientes atributos determinan la posición de las pestañas (tabs), y si son visibles o no.
notebookTabPos :: NotebookClass self => Attr self PositionType notebookShowTabs :: NotebookClass self => Attr self Bool
PositionType (tipo de posición) tiene los siguientes cosntructores :
PosLeft
,
PosRight
,
PosTop
(por defecto) y
PosBottom.
A continuación echaremos un vistazo a la manera de añadir páginas al notebook. Hay tres modos, append (añadir detrás), prepend (añadir delante) e insert (insertar).
noteBookAppendPage :: (NotebookClass self, WidgetClass child) => self -> child -- El widget que tiene los contenidos de la página -> String -- la etiqueta de texto -> IO Int -- el índice (número de página) de la nueva página (empieza en 0)
La función
notebookPrependPage
tiene la misma signatura.
Y, por supuesto, devuelve 0 como valor del índice. La función
notebookInsertPage
toma el índice (lugar donde quieres insertar
la página) como un parámetro adicional. Se pueden eliminar páginas
con
notebookRemovePage.
Un
Notebook
es un widget contenedor y puedes usar otros contenedores como
hijos, incluyendo cajas horizontales y verticales. Esto te permite crear páginas
bastante complejas, y establecer su distribución con las funciones de empaquetado
habituales.
Las funciones listadas para añadir, pre-añadir e insertar páginas, sólo sirven con etiquetas de texto. Las tres tienen versiones que permiten que aparezca un menú emergente (popup), y en los cuales puedes usar cualquier widget como etiqueta.
notebookAppendPageMenu :: (NotebookClass self, WidgetClass child, WidgetClass tabLabel, WidgetClass menuLabel) => self -> child -- el widget contenido en la página -> tabLabel -- el widget para usar como etiqueta de la página -> menuLabel -- el widget para usar como etiqueta del menú emergente -> IO Int -- el índice (número de página) de la nueva página (empieza en 0)
notebookPrependPageMenu
y
notebookInsertPageMenu
colocarán la página en primer lugar o en
la posición indicada por el índice respectivamente.
Algunos atributos interesantes son: (consulta la docuemntación de la API (en inglés) para verlos todos):
notebookScrollable :: NotebookClass self => Attr self Bool notebookCurrentPage :: NotebookClass self => Attr self Int notebookEnablePopup :: NotebookClass self => Attr self Bool
Si hay muchas páginas puedes usar
notebookScrollable
. Usa
notebookCurrentPage
o la función
notebookSetCurrentPage
para abrir el notebook en una página diferente
que la primera (valor por defecto). El atributo
notebookEnablePopup
determina si la pulsación del botón derecho
del ratón en una pestaña mostrará un menú emergente de todas las páginas disponibles,
siempre que las funciones de menú hayan sido definidas.
Un widget
Notebook
tiene su propia función de manejo de la señal:
onSwitchPage :: NotebookClass nb => nb -> (Int -> IO ()) -> IO (ConnectId nb)
La función, que tú debes suministrar, emplea un índice de página devuelto por
onSwitchPage
y debe realizar alguna salida.
Los ejemplos muestran un catálogo StockItem
de conjuntos de iconos
de maneras diversas.
Vimos los Stock items en el capítulo 4.5. Recuerda
que un StockItem
se conoce a partir de GTK+ (y Gtk2Hs).
La siguiente función produce una lista de todos los identificadores de Stock Items.
stockListIds :: IO [StockId]
Un
StockId
es una
String
y en Gtk2Hs tiene la forma:
stockCopy
,
stockDialogError
etc. En GTK+ la forma correspondiente
es: gtk-copy, gtk-dialog-error y así sucesivamente. El ejemplo
define una función tabName para convertir los identificadores GTK+ en
la lista de StockId a nombres para las solapas del notebook. La función
myNewPage
usa
imageNewFromStock
para poner el icono en un widget
Image
, que será después añadido a la página. Devuelve
el índice de la página, pero no lo usa. Para conseguir una lista de todas las
páginas puedes usar sequence
en vez de
sequence_
Fíjate en que el tamaño del icono, en píxeles debe ser limitado. El valor por defecto es 4, el valor usado aquí, 6, también está permitido pero un tamaño de 8 produce un error de ejecución con GHCi.
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
Otra manera de mostrar el catálogo es poner los iconos en las solapas del notebook.
Para hacer esto necesitamos el estilo de menú para añadir páginas, y también
hemos definido un menú de solapas que consta de la primera letra de la cadena
nombre. El resultado es un menú emergente de 98 letras, con desplazamiento.
Esto puede ser inhabilitado de un modo sencillo
a través del atributo notebookEnablePopup
. El contenido de cada
página es el identificador de icono de Gtk2Hs (mira
Graphics.UI.Gtk.General.StockItems).
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