5.3 Seleción de Fuente (tipo de letra)

La selección del color y del tipo de letra son muy parecidas a la selección de ficheros. Hay tres maneras de implantarlas, como widgets, como diálogos y como botones. Los valores seleccionados por el usuario se obtienen a partir de atributos y funciones, como ya va resultando habitual. Primero discutiremos la selección de tipo de letra (font). Puedes usar:

fontSelectionNew :: IO FontSelection
fontSelectionDialogNew :: String -> IO FontSelectionDialog
fontButtonNew :: IO FontButton

El parámetro String es el título de la ventana de diálogo. Hay un puñado de atributos y funciones para gestionar la presentación de estos widgets, todos bastante sencillos. Con un diálogo debes usar los tipos ResponseId adecuados; con el FontButton debes usar:

onFontSet:: FontButtonClass self => self -> IO () -> IO (ConnectId self)

Después puedes usar la siguiente función para conseguir el nombre de la fuente seleccionada por el usuario:

fontButtonGetFontName :: FontButtonClass self => self -> IO String

El nombre de la fuente debe ser algo así como "Courier Italic 10" o "URW Gothic L Semi-Bold Oblique 16", dependiendo de lo que esté disponible en tu sistema. Como puedes ver en la imagen, el usuario puede seleccionar una familia, un estilo y un tamaño.

Font Select Window

La documentación sobre fonts está en Graphics.UI.Gtk.Pango.Font. Se soportan diversas características avanzadas, pero el usuario normal sólo necesita saber como conseguir una FontDescription (descripción de fuente) a partir de un nombre de fuente.

fontDescriptionFromString :: String -> IO FontDescription

Una vez que tienes la FontDescription (descripción de una fuente), puedes usar:

widgetModifyFont:: WidgetClass self => self -> Maybe FontDescription -> IO ()

La selección de color es parecida a la selección de fuentes. Tienes tres posibilidades:

colorSelectionNew :: IO Color Selection
colorSelectionDialogNew: :: String -> IO ColorSelectionDialog
colorButtonNew :: IO Color Button

Con un ColorButton usa:

onColorSet :: ColorButtonClass self => self -> IO () -> IO (ConnectId self)

y después:

colorButtonGetColor :: ColorButtonClass self => self -> IO Color

También hay una función (y un atributo) para conseguir el valor Alpha (opacidad), si esta característica ha sido activada.

La ventana de selección de color que aparece por defecto tiene esta forma:

Color Selection Window

Color es un tipo de datos de tres Ints , en un rango de 0 A 65535, que especifican los valores de los componentes rojo, verde y azul. Aquí hay funciones que permiten establecer los colores del foreground, background, texto y base de un widget, y estas funciones usan un parámetro de tipo StateType. Estos son sus valores: StateNormal, StateActive, StatePreLight, StateSelected y StateInsensitive y dependen de si el widget está activo, el puntero del ratón está sobre un widget, se selecciona un widget y cosas así. Hay muchos parámetros que gobiernan la presentación de los widgets, por ejemplo, para cambiar el color de una etiqueta de texto simplemente debes usar StateNormal y el Color que haya sido seleccionado por el usuario.

widgetModifyFg :: WidgetClass self => self -> StateType -> Color -> IO ()

Si tienes dudas sobre cual es el StateType que tiene el widget, puedes usar la siguiente función:

widgetGetState :: WidgetClass w => w -> IO StateType

Aquí hay un ejemplo de selección de fuente y color.

FontButton and ColorButton Example

La ventana automáticamente cambia de tamaño para que quepa la fuente mayor.

Window

import Graphics.UI.Gtk

main :: IO ()
main = do
     initGUI
     window <- windowNew
     set window [windowTitle := "Font and Color Selection",
containerBorderWidth := 10 ]
     vb <- vBoxNew False 0
     containerAdd window vb

     qtlab <- labelNew (Just "How poor are they that have not
patience!\nWhat wound did ever heal but by degrees?\nThou know'st
we work by wit, and not by witchcraft;\nAnd wit depends on dilatory
time.")
     boxPackStart vb qtlab PackGrow 0

     srclab <- labelNew (Just "From Othello (II, iii, 376-379)")
     srcfont <- fontDescriptionFromString "Courier Italic 10"
     widgetModifyFont srclab (Just srcfont)
     miscSetAlignment srclab 1.0 0.5
     boxPackStart vb srclab PackNatural 10

     sep <- hSeparatorNew
     boxPackStart vb sep PackGrow 10
     
     fntb <- fontButtonNew
     boxPackStart vb fntb PackGrow 0

     colb <- colorButtonNew
     boxPackStart vb colb PackGrow 0

     onFontSet fntb $ do name <- fontButtonGetFontName fntb
                         fdesc <- fontDescriptionFromString name
                         widgetModifyFont qtlab (Just fdesc)
                         putStrLn name

     onColorSet colb $ do colour <- colorButtonGetColor colb
                          widgetModifyFg qtlab StateNormal colour
                          putStrLn (show  colour)

     widgetShowAll window
     onDestroy window mainQuit
     mainGUI

instance Show Color where
         show (Color r g b) = "Red: " ++ (show r) ++ 
                              " Green: " ++ (show g) ++ 
                              " Blue: " ++ (show b)