5.3 Font and Color Selection

Font and color selection are much like file selection. There are three ways to implement them, as widgets, dialogs and buttons. The user selected values are obtained through the appropriate attributes or functions. We'll discuss font selection first. You can use:

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

The String parameter is the title of the dialog window. There are a host of attributes and functions to manage the display of these widgets, all pretty straightforward. With a dialog you use the appropriate ResponseId types; with the FontButton you use:

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

Then you use the following function to get the name of the user selected font:

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

The font name will be something like "Courier Italic 10" or "URW Gothic L Semi-Bold Oblique 16", whatever is available on your system. As you can see from the image below, the user can select a family, a style and a size.

Font Select Window

Finding and querying information about fonts is documented in Graphics.UI.Gtk.Pango.Font. Many advanced features are supported, but the general user will only need to know how to get a FontDescription from a font name.

fontDescriptionFromString :: String -> IO FontDescription

Once you have a FontDescription you can use:

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

Color selection is analogous to font selection. You have three choices:

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

With a ColorButton use:

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

and then:

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

There is also a function (and an attribute) to get the Alpha value (opacity) if this feature has been enabled.

The default color selection window looks like this:

Color Selection Window

Color is a data type of three Ints , ranging from 0 to 65535, specifying the red, green and blue components. There are functions to set the foreground, background, text and base colors of a widget, and these functions take a StateType parameter. These are: StateNormal, StateActive, StatePreLight, StateSelected and StateInsensitive and they depend on whether a widget is active, the mouse pointer is over a widget, a widget is selected and such. Display of widgets has many features, but to change the color of a label text, for example, you just use StateNormal and the Color the user has selected.

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

When in doubt what StateType the widget has, there is the following function:

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

Here is an example of font and color selection.

FontButton and ColorButton Example

The window automatically resizes to accommodate the larger font.

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)