6.4 Paned Windows and Aspect Frames

The paned window widgets are useful when you want to divide an area into two parts, with the relative size of the two parts controlled by the user. A groove is drawn between the two portions, with a handle that the user can drag to change the ratio. The division can either be horizontal, HPaned, or vertical, VPaned.

To create a new paned window, use one of:

hPanedNew :: IO HPaned
vPanedNew :: IO VPaned 

Set the position of the divider with:

panedSetPosition :: PanedClass self => self -> Int -> IO ()

After creating the paned window widget, you need to add child widgets to its two halves.

panedAdd1 :: (PanedClass self, WidgetClass child) => self -> child -> IO ()
panedAdd2 :: (PanedClass self, WidgetClass child) => self -> child -> IO ()

The first adds to the top (right) , the second to the bottom (left) half of the paned window. If you don't want the children to expand or resize with the paned widget use panedPack1 and panedPack2 instead.

An Aspect Frame is a frame for which you can define a constant width/height ratio. This so called aspect ratio will not change when the frame is resized. You create one with:

aspectFrameNew :: Float -> Float -> Maybe Float -> IO AspectFrame

The first parameter sets the horizontal alignment of the child within the frame (between 0.0 and 1.0). The second does the same for the vertical alignment. Optionally, you set the desired aspect ratio with the third parameter. Since an AspectFrame widget is a Frame widget, you can also add a label.

In the following example we've created a vertical paned window with an aspect frame in the top half.

Paned Window

We've created a DrawingArea widget in the AspectFrame. A DrawingArea is a blank widget, which can be used to draw on, but here we just set the background color to demonstrate the use of the AspectFrame. In the lower half of the VPaned widget we've created a TextView widget. This is a multi-line text viewer and editor with many powerful features. Here, however, we just take the associated text buffer and count the characters whenever the user edits some text.

import Graphics.UI.Gtk

main :: IO ()
main = do
     initGUI
     window <- windowNew
     set window [windowTitle := "Paned Window", containerBorderWidth := 10,
                 windowDefaultWidth := 400, windowDefaultHeight := 400 ]

     pw <- vPanedNew
     panedSetPosition pw 250
     containerAdd window pw
     af <- aspectFrameNew 0.5 0.5 (Just 3.0)
     frameSetLabel af "Aspect Ratio: 3.0"
     frameSetLabelAlign af 1.0 0.0
     panedAdd1 pw af

     da <- drawingAreaNew
     containerAdd af da
     widgetModifyBg da StateNormal (Color 65535 0 0)
   
     tv <- textViewNew
     panedAdd2 pw tv
     buf <- textViewGetBuffer tv

     onBufferChanged buf $ do cn <- textBufferGetCharCount buf
                              putStrLn (show cn)   

     widgetShowAll window 
     onDestroy window mainQuit
     mainGUI