[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8. Layout Widgets


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.1 Alignment Widget

figures/alignment302x329

Figure 8.1: Alignment Widget

The alignment container gtk-alignment allows to place a widget within its window at a position and size relative to the size of the gtk-alignment container itself. For example, it can be very useful for centering a widget within the window.

The gtk-alignment container has the four properties xalign, yalign, xscale, and yscale. The properties are floating point numbers. The align settings are used to place the child widget within the available area. The values range from 0.0 (top or left) to 1.0 (bottom or right). Of course, if the scale settings are both set to 1.0, the alignment settings have no effect. The scale settings are used to specify how much the child widget should expand to fill the space allocated to the gtk-alignment. The values can range from 0.0 (meaning the child doesn't expand at all) to 1.0 (meaning the child expands to fill all of the available space).

The properties are set when creating the gtk-alignment container with the function gtk-alignment-new. For an existing gtk-alignment container the properties can be set with the function gtk-alignment-set. A child widget can be added to the gtk-alignment container using the function gtk-container-add.

In addition, the gtk-alignment container has the properties top-padding, bottom-padding, left-padding, and right-padding. These properties control how many space is added to the sides of the widget. The functions gtk-alignment-set-padding and gtk-alignment-get-padding are used to set or to retrieve the values of the padding properties.

Note:

Note that the desired effect can in most cases be achieved by using the "halign", "valign" and "margin" properties on the child widget, so gtk-alignment should not be used in new code.

Example 8.1: Alignment Widget

(defun example-alignment ()
  (within-main-loop
    (let ((window (make-instance 'gtk-window
                                 :type :toplevel
                                 :title "Example Alignment"
                                 :border-width 12
                                 :width-request 300
                                 :height-request 300))
          (grid (make-instance 'gtk-grid
                                :column-spacing 12
                                :column-homogeneous t
                                :row-spacing 12
                                :row-homogeneous t)))
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      (let ((frame (make-instance 'gtk-frame
                                  :label "xalign: 0, yalign: 0"))
            (button (make-instance 'gtk-button
                                   :label "Button"))
            (alignment (make-instance 'gtk-alignment
                                      :xalign 0.00
                                      :yalign 0.00
                                      :xscale 0.50
                                      :yscale 0.25)))
        (gtk-alignment-set-padding alignment 6 6 6 6)
        (gtk-container-add alignment button)
        (gtk-container-add frame alignment)
        (gtk-grid-attach grid frame 0 1 1 1))
      (let ((frame (make-instance 'gtk-frame
                                  :label "xalign: 0, yalign: 1"))
            (button (make-instance 'gtk-button
                                   :label "Button"))
            (alignment (make-instance 'gtk-alignment
                                      :xalign 0.00
                                      :yalign 1.00
                                      :xscale 0.50
                                      :yscale 0.25)))
        (gtk-alignment-set-padding alignment 6 6 6 6)
        (gtk-container-add alignment button)
        (gtk-container-add frame alignment)
        (gtk-grid-attach grid frame 1 1 1 1))
      (let ((frame (make-instance 'gtk-frame
                                  :label "xalign: 1, yalign: 0"))
            (button (make-instance 'gtk-button
                                   :label "Button"))
            (alignment (make-instance 'gtk-alignment
                                      :xalign 1.00
                                      :yalign 0.00
                                      :xscale 0.50
                                      :yscale 0.25)))
        (gtk-alignment-set-padding alignment 6 6 6 6)
        (gtk-container-add alignment button)
        (gtk-container-add frame alignment)
        (gtk-grid-attach grid frame 0 2 1 1))
      (let ((frame (make-instance 'gtk-frame
                                  :label "xalign: 1, yalign: 1"))
            (button (make-instance 'gtk-button
                                   :label "Button"))
            (alignment (make-instance 'gtk-alignment
                                      :xalign 1.00
                                      :yalign 1.00
                                      :xscale 0.50
                                      :yscale 0.25)))
        (gtk-alignment-set-padding alignment 6 6 6 6)
        (gtk-container-add alignment button)
        (gtk-container-add frame alignment)
        (gtk-grid-attach grid frame 1 2 1 1))
      (gtk-container-add window grid)
      (gtk-widget-show-all window))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.2 Fixed Container

figures/fixed302x254

Figure 8.2: Fixed Container

The gtk-fixed widget is a container widget which allows to place child widgets at a fixed position within the container, relative to the upper left hand corner. The position of the child widgets can be changed dynamically. Only a few functions are associated with the gtk-fixed widget like gtk-fixed-new, gtk-fixed-put, and gtk-fixed-move.

The function gtk-fixed-new creates a new gtk-fixed widget. The function gtk-fixed-put places a widget in the container fixed at the position specified by the arguments x and y. The function gtk-fixed-move allows the specified widget to be moved to a new position.

For most applications, you should not use this container. It keeps you from having to learn about the other GTK+ containers, but it results in broken applications. With gtk-fixed, the following things will result in truncated text, overlapping widgets, and other display bugs:

In addition, the fixed widget can not properly be mirrored in right-to-left languages such as Hebrew and Arabic. i.e. normally GTK+ will flip the interface to put labels to the right of the thing they label, but it can't do that with gtk-fixed. So your application will not be usable in right-to-left languages.

Finally, fixed positioning makes it kind of annoying to add/remove GUI elements, since you have to reposition all the other elements. This is a long-term maintenance problem for your application.

If you know none of these things are an issue for your application, and prefer the simplicity of gtk-fixed, by all means use the widget. But you should be aware of the tradeoffs.

The following example illustrates how to use a fixed container. In this example three buttons are put into the fixed widget at random positions. A click on a button moves the button to a new random position. To retrieve the size of the fixed widget the function gtk-widget-get-allocation is used, which returns a rectangle of type gdk-rectangle. The width and the height of the fixed widget are then get with the functions gdk-rectangle-width and gdk-rectangle-height.

Example 8.2: Fixed Container

(defun move-button (button fixed)
  (let* ((allocation (gtk-widget-get-allocation fixed))
         (width (- (gdk-rectangle-width allocation) 20))
         (height (- (gdk-rectangle-height allocation) 10)))
    (gtk-fixed-move fixed button (random width) (random height))))

(defun example-fixed ()
  (within-main-loop
    (let ((window (make-instance 'gtk-window
                                 :type :toplevel
                                 :title "Example Fixed Container"
                                 :default-width 300
                                 :default-height 200
                                 :border-width 12))
          (fixed (make-instance 'gtk-fixed)))
      (g-signal-connect window "destroy"
                        (lambda (window)
                          (declare (ignore window))
                          (leave-gtk-main)))
      (gtk-container-add window fixed)
      (dotimes (i 3)
        (let ((button (gtk-button-new-with-label "Press me")))
          (g-signal-connect button "clicked"
                            (lambda (widget)
                              (move-button widget fixed)))
          (gtk-fixed-put fixed button (random 250) (random 150))))
      (gtk-widget-show window))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3 Layout Container

The layout container gtk-layout is similar to the fixed container gtk-fixed except that it implements an infinite (where infinity is less than 2^32) scrolling area. The X window system has a limitation where windows can be at most 32767 pixels wide or tall. The layout container gets around this limitation by doing some exotic stuff using window and bit gravities, so that you can have smooth scrolling even when you have many child widgets in your scrolling area.

A layout container is created using gtk-layout-new which accepts the optional arguments hadjustment and vadjustment to specify adjustment objects that the layout widget will use for its scrolling.

Widgets can be added and moved in the Layout container using the functions gtk-layout-put and gtk-layout-move. The size of the layout container can be set using the function gtk-layout-set-size.

gtk-layout implements the interface gtk-scrollable. Therefore, for manipulating the horizontal and vertical adjustment widgets the functions gtk-scrollable-get-hadjustment, gtk-scrollable-get-vadjustment, gtk-scrollable-set-hadjustment, and gtk-scrollable-set-vadjustment are available.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4 Frames

figures/frame252x229

Figure 8.3: Frame Widget

Frames can be used to enclose one or a group of widgets with a box which can optionally be labelled. The position of the label and the style of the box can be altered to suit.

A frame can be created with (make-instance 'gtk-frame) or the function gtk-frame-new. The label is by default placed in the upper left hand corner of the frame. A value of NIL for the label argument will result in no label being displayed. The text of the label can be changed using the function gtk-frame-set-label.

The position of the label can be changed using the function gtk-frame-set-label-align which has the arguments xalign and yalign which take values between 0.0 and 1.0. xalign indicates the position of the label along the top horizontal of the frame. yalign indicates the vertival position of the label. With a value of 0.5 of yalign the label is positioned in the middle of the line of the frame. The default value of xalign is 0.0 which places the label at the left hand end of the frame.

The function gtk-frame-set-shadow-type alters the style of the box that is used to outline the frame. The second argument is a keyword of the enumeration type gtk-shadow-type.

example-frame illustrates the use of the frame widget. The code of this example is shown in example-frame.

Example 8.3: Frame Widget

(defun example-frame ()
  (within-main-loop
    (let ((window (make-instance 'gtk-window
                                 :type :toplevel
                                 :title "Example Frame"
                                 :default-width 250
                                 :default-height 200
                                 :border-width 12))
          (frame (make-instance 'gtk-frame
                                :label "Gtk Frame Widget"
                                :label-xalign 1.0
                                :label-yalign 0.5
                                :shadow-type :etched-in)))
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      (gtk-container-add window frame)
      (gtk-widget-show window))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.5 Aspect Frames

figures/aspect-frame302x279

Figure 8.4: Aspect Frame Container

The gtk-aspect-frame aspect frame container is like a frame container, except that it also enforces the aspect ratio (that is, the ratio of the width to the height) of the child widget to have a certain value, adding extra space if necessary. This is useful, for instance, if you want to preview a larger image. The size of the preview should vary when the user resizes the window, but the aspect ratio needs to always match the original image.

To create a new aspect frame use (make-instance 'gtk-aspect-frame) or the function gtk-aspect-frame-new. The arguments xalign and yalign specify alignment as with alignment containers. If the property obey-child is true, the aspect ratio of a child widget will match the aspect ratio of the ideal size it requests. Otherwise, it is given by ratio.

The options of an existing aspect frame can be changed with the function gtk-aspect-frame-set.

As an example, the following program uses an aspect frame widget to present a drawing area whose aspect ratio will always be 2:1, no matter how the user resizes the top-level window.

Example 8.4: Aspect Frame Container

(defun example-aspect-frame ()
  (within-main-loop
    (let ((window (make-instance 'gtk-window
                                 :type :toplevel
                                 :title "Example Aspect Frame"
                                 :default-width 300
                                 :default-height 250
                                 :border-width 12))
          (frame (make-instance 'gtk-aspect-frame
                                :label "2 x 1"
                                :xalign 0.5
                                :yalign 0.5
                                :ratio 2
                                :obey-child nil))
          (area (make-instance 'gtk-drawing-area
                               :width-request 200
                               :hight-request 200)))
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      (gtk-container-add window frame)
      (gtk-container-add frame area)
      (gtk-widget-show window))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.6 Paned Window Widgets

figures/paned-window302x279

Figure 8.5: Paned Window Widgets

gtk-paned has two panes, arranged either horizontally or vertically. The division between the two panes is adjustable by the user by dragging a handle.

A paned window can be created with the function gtk-paned-new, which takes as an argument a value of type gtk-orientation. With the value :horizontal a horizontal paned window is created, and with the value :vertical a vertical paned window.

Child widgets are added to the panes of the widget with the functions gtk-paned-pack1 and gtk-paned-pack2 or the functions gtk-paned-add1 and gtk-paned-add2. The division between the two children is set by default from the size requests of the children, but it can be adjusted by the user.

A paned widget draws a separator between the two child widgets and a small handle that the user can drag to adjust the division. It does not draw any relief around the children or around the separator. (The space in which the separator is called the gutter.) Often, it is useful to put each child inside a gtk-frame with the shadow type set to :in so that the gutter appears as a ridge. No separator is drawn if one of the children is missing.

Each child has two options that can be set, resize and shrink. If resize is T, then when the GtkPaned is resized, that child will expand or shrink along with the paned widget. If shrink is T, then that child can be made smaller than its requisition by the user. Setting shrink to NIL allows the application to set a minimum size. If resize is NIL for both children, then this is treated as if resize is T for both children.

The application can set the position of the slider as if it were set by the user, by calling gtk-paned-set-position.

figure-paned-window shows a simple example. The corresponding code is shown in example-paned-window

Example 8.5: Paned Window Widgets

(defun example-paned-window ()
  (within-main-loop
    (let ((window (make-instance 'gtk-window
                                 :type :toplevel
                                 :title "Example Paned Window"
                                 :border-width 12))
          (paned (make-instance 'gtk-paned
                                :orientation :vertical))
          (frame1 (make-instance 'gtk-frame :label "Window 1"))
          (frame2 (make-instance 'gtk-frame :label "Window 2")))
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      (setf (gtk-widget-size-request window) '(300 250))
      (gtk-container-add window paned)
      (gtk-paned-add1 paned frame1)
      (gtk-paned-add2 paned frame2)
      (gtk-widget-show-all window))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.7 Viewports

The gtk-viewport widget acts as an adaptor class, implementing scrollability for child widgets that lack their own scrolling capabilities. Use gtk-viewport to scroll child widgets such as gtk-grid, gtk-box, and so on.

If a widget has native scrolling abilities, such as gtk-text-view, gtk-tree-view or gtk-icon-view, it can be added to a gtk-scrolled-window with gtk-container-add. If a widget does not, you must first add the widget to a gtk-viewport, then add the viewport to the scrolled window. The convenience function gtk-scrolled-window-add-with-viewport does exactly this, so you can ignore the presence of the viewport.

The gtk-viewport will start scrolling content only if allocated less than the child widget's minimum size in a given orientation.

A viewport is created with the function gtk-viewport-new. The function takes two arguments to specify the horizontal and vertical adjustments that the widget is to use when you create the widget. It will create its own if you pass NIL as the value of the arguments.

gtk-viewport implement the interface gtk-scrollable. Therefore, the you can get and set the adjustments after the widget has been created using the one of the four functions gtk-scrollable-get-hadjustment, gtk-scrollable-get-vadjustment, gtk-scrollable-set-hadjustment, and gtk-scrollable-set-vadjustment.

The only other viewport function is gtk-viewport-set-shadow-type used to alter its appearance. The second argument is of type gtk-shadow-type.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.8 Scrolled Windows

figures/scrolled-window352x329

Figure 8.6: Scrolled Window

gtk-scrolled-window is a gtk-bin subclass: it is a container that accepts a single child widget. gtk-scrolled-window adds scrollbars to the child widget and optionally draws a beveled frame around the child widget.

The scrolled window can work in two ways. Some widgets have native scrolling support; these widgets implement the gtk-scrollable interface. Widgets with native scroll support include gtk-tree-view, gtk-text-view, and gtk-layout.

For widgets that lack native scrolling support, the gtk-viewport widget acts as an adaptor class, implementing scrollability for child widgets that lack their own scrolling capabilities. Use gtk-viewport to scroll child widgets such as gtk-grid, gtk-box, and so on.

If a widget has native scrolling abilities, it can be added to the gtk-scrolled-window with gtk-container-add. If a widget does not, you must first add the widget to a gtk-viewport, then add the gtk-viewport to the scrolled window. The convenience function gtk-scrolled-window-add-with-viewport does exactly this, so you can ignore the presence of the viewport.

The position of the scrollbars is controlled by the scroll adjustments. See gtk-adjustment for the fields in an adjustment - for gtk-scrollbar, used by gtk-scrolled-window, the "value" field represents the position of the scrollbar, which must be between the "lower" field and "upper - page-size". The "page-size" field represents the size of the visible scrollable area. The "step-increment" and "page-increment" fields are used when the user asks to step down (using the small stepper arrows) or page down (using for example the PageDown key).

If a gtk-scrolled-window does not behave quite as you would like, or does not have exactly the right layout, it is very possible to set up your own scrolling with gtk-scrollbar and for example a gtk-grid.

The function gtk-scrolled-window-new is used to create a new scrolled window, where the first argument is the adjustment for the horizontal direction, and the second, the adjustment for the vertical direction. These are almost always set to NIL.

The function gtk-scrolled-window-set-policy sets the policy to be used with respect to the scrollbars. The first argument is the scrolled window you wish to change. The second sets the policy for the horizontal scrollbar, and the third the policy for the vertical scrollbar.

The policy is of the enumeration type gtk-policy-type and may be one of :automatic or :always. :automatic will automatically decide whether you need scrollbars, whereas :always will always leave the scrollbars there. All possible values of gtk-policy-type are listed in table-gtk-policy-type.

Table 8.1: The values of the enumeration type GtkPolicyType determines when a scroll bar will be visible.

:always

The scrollbar is always visible.

:automatic

The scrollbar will appear and disappear as necessary. For example, when all of a GtkCList can not be seen.

:never

The scrollbar will never appear.

example-scrolled-window is a simple example that packs a table with 100 toggle buttons into a scrolled window. Try playing with resizing the window. You will notice how the scrollbars react. You may also wish to use the gtk-widget-size-request call to set the default size of the window or other widgets.

Example 8.6: Scrolled Window

(defun example-scrolled-window ()
  (within-main-loop
    (let ((window (make-instance 'gtk-dialog
                                 :type :toplevel
                                 :title "Example Scrolled Window"
                                 :border-width 0
                                 :width-request 350
                                 :height-request 300))
          (scrolled (make-instance 'gtk-scrolled-window
                                   :border-width 12
                                   :hscrollbar-policy :automatic
                                   :vscrollbar-policy :always))
          (table (make-instance 'gtk-table
                                :n-rows 10
                                :n-columns 10
                                :row-spacing 10
                                :column-spacing 10
                                :homogeneous nil)))
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      (gtk-box-pack-start (gtk-dialog-get-content-area window) scrolled)
      (gtk-scrolled-window-add-with-viewport scrolled table)
      (dotimes (i 10)
        (dotimes (j 10)
          (gtk-table-attach table
                            (make-instance 'gtk-button
                                           :label
                                           (format nil "(~d, ~d)" i j))
                            i (+ i 1) j (+ j 1))))
      (let ((button (make-instance 'gtk-button
                                   :label "Close"
                                   :can-default t)))
        (g-signal-connect button "clicked"
                          (lambda (widget)
                            (declare (ignore widget))
                            (gtk-widget-destroy window)))
        (gtk-box-pack-start (gtk-dialog-get-action-area window) button)
        (gtk-widget-grab-default button))
      (gtk-widget-show window))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.9 Button Boxes

figures/button-box576x603

Figure 8.7: Button Boxes

A button box should be used to provide a consistent layout of buttons throughout your application. The layout/spacing can be altered by the programmer, or if desired, by the user to alter the 'feel' of a program to a small degree.

gtk-button-box-get-layout and gtk-button-box-set-layout retrieve and alter the method used to spread the buttons in a button box across the container, respectively.

The main purpose of gtk-button-box is to make sure the children have all the same size. gtk-button-box gives all children the same size, but it does allow 'outliers' to keep their own larger size. To force all children to be strictly the same size without exceptions, you can set the "homogeneous" property to T.

To excempt individual children from homogeneous sizing regardless of their 'outlier' status, you can set the "non-homogeneous" child property.

You can create a new button box with the function gtk-button-box-new, which creates a horizontal or vertical box depending on the argument orientation which takes the values :horizontal or :vertical, respectively.

Buttons are added to a Button Box using the usual function gtk-container-add.

example-button-box is an example that illustrates all the different layout settings for button boxes.

Example 8.7: Button Boxes

(defun create-bbox (orientation title spacing layout)
  (let ((frame (make-instance 'gtk-frame
                              :label title))
        (bbox (make-instance 'gtk-button-box
                             :orientation orientation
                             :border-width 6
                             :layout-style layout
                             :spacing spacing)))
  (gtk-container-add bbox (gtk-button-new-from-stock "gtk-ok"))
  (gtk-container-add bbox (gtk-button-new-from-stock "gtk-cancel"))
  (gtk-container-add bbox (gtk-button-new-from-stock "gtk-help"))
  (gtk-container-add frame bbox)
  frame))

(defun example-button-box ()
  (within-main-loop
    (let ((window (make-instance 'gtk-window
                                 :type :toplevel
                                 :title "Example Button Box"
                                 :border-width 12))
          (vbox1 (make-instance 'gtk-box
                                :orientation :vertical
                                :homogeneous nil
                                :spacing 12))
          (vbox2 (make-instance 'gtk-box
                                :orientation :vertical
                                :homogeneous nil
                                :spacing 12))
          (hbox (make-instance 'gtk-box
                               :orientation :horizontal
                               :homogeneous nil
                               :spacing 12)))
      ;; Set gtk-button-images to T. This allows buttons with text and image.
      (setf (gtk-settings-gtk-button-images (gtk-settings-get-default)) t)
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      ;; Create Horizontal Button Boxes
      (gtk-box-pack-start vbox1
                          (make-instance 'gtk-label
                                         :ypad 6
                                         :xalign 0
                                         :use-markup t
                                         :label
                                         "<b>Horizontal Button Boxes</b>")
                          :expand nil
                          :fill nil)
      ;; Create the first Horizontal Box
      (gtk-box-pack-start vbox2
                          (create-bbox :horizontal
                                       "Spread (spacing 12)"
                                       12
                                       :spread))
      ;; Create the second Horizontal Box
      (gtk-box-pack-start vbox2
                          (create-bbox :horizontal
                                       "Edge (spacing 12)"
                                       12
                                       :edge))
      ;; Create the third Horizontal Box
      (gtk-box-pack-start vbox2
                          (create-bbox :horizontal
                                       "Start (spacing 6)"
                                       6
                                       :start))
      ;; Create the fourth Horizontal Box
      (gtk-box-pack-start vbox2
                          (create-bbox :horizontal
                                       "End (spacing 6)"
                                       6
                                       :end))
      (gtk-box-pack-start vbox1 vbox2)
      ;; Create Vertical Button Boxes
      (gtk-box-pack-start vbox1
                          (make-instance 'gtk-label
                                         :ypad 12
                                         :xalign 0
                                         :use-markup t
                                         :label
                                         "<b>Vertical Button Boxes</b>")
                          :expand nil
                          :fill nil)
      ;; Create the first Vertical Box
      (gtk-box-pack-start hbox
                          (create-bbox :vertical
                                       "Spread (spacing 12)"
                                       12
                                       :spread))
      ;; Create the second Vertical Box
      (gtk-box-pack-start hbox
                          (create-bbox :vertical
                                       "Edge (spacing 12)"
                                       12
                                       :edge))
      ;; Create the third Vertical Box
      (gtk-box-pack-start hbox
                          (create-bbox :vertical
                                       "Start (spacing 6)"
                                       6
                                       :start))
      ;; Create the fourth Vertical Box
      (gtk-box-pack-start hbox
                          (create-bbox :vertical
                                       "End (spacing 6)"
                                       6
                                       :end))
      (gtk-box-pack-start vbox1 hbox)
      (gtk-container-add window vbox1)
      (gtk-widget-show-all window))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.10 Toolbar

A toolbar is created with a call to gtk-toolbar-new.

A toolbar can contain instances of a subclass of gtk-tool-item. To add a gtk-tool-item to the a toolbar, use gtk-toolbar-insert. To remove an item from the toolbar use gtk-container-remove. To add a button to the toolbar, add an instance of gtk-tool-button.

Toolbar items can be visually grouped by adding instances of gtk-separator-tool-item to the toolbar. If the gtk-toolbar child property "expand" is true and the property "draw" is set to nil, the effect is to force all following items to the end of the toolbar.

Creating a context menu for the toolbar can be done by connecting to the "popup-context-menu" signal.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.11 Notebook

figures/notebook347x229

Figure 8.8: Notebook

The gtk-notebook widget is a gtk-container whose children are pages that can be switched between using tab labels along one edge.

There are many configuration options for gtk-notebook. Among other things, you can choose on which edge the tabs appear (see gtk-notebook-set-tab-pos), whether, if there are too many tabs to fit the notebook should be made bigger or scrolling arrows added (see gtk-notebook-set-scrollable), and whether there will be a popup menu allowing the users to switch pages (see gtk-notebook-popup-enable, gtk-notebook-popup-disable).

Example 8.8: Notebook

(defun example-notebook ()
  (within-main-loop
    (let ((window (make-instance 'gtk-window
                                 :title "Example Notebook"
                                 :type :toplevel
                                 :default-width 250
                                 :default-height 200))
          (expander (make-instance 'gtk-expander
                                   :expanded t
                                   :label "Notebook"))
          (notebook (make-instance 'gtk-notebook
                                   :enable-popup t)))
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      (dotimes (i 5)
        (let ((page (make-instance 'gtk-label
                                   :label
                                   (format nil
                                           "Text for page ~A" i)))
              (tab-label (make-instance 'gtk-label
                                        :label (format nil "Tab ~A" i)))
              (tab-button (make-instance 'gtk-button
                                         :image
                                         (make-instance 'gtk-image
                                                        :stock
                                                        "gtk-close"
                                                        :icon-size 1)
                                         :relief :none)))
          (g-signal-connect tab-button "clicked"
             (let ((page page))
               (lambda (button)
                 (declare (ignore button))
                 (format t "Removing page ~A~%" page)
                 (gtk-notebook-remove-page notebook page))))
          (let ((tab-hbox (make-instance 'gtk-box
                                         :orientation :horizontal)))
            (gtk-box-pack-start tab-hbox tab-label)
            (gtk-box-pack-start tab-hbox tab-button)
            (gtk-widget-show-all tab-hbox)
            (gtk-notebook-add-page notebook page tab-hbox))))
      (gtk-container-add expander notebook)
      (gtk-container-add window expander)
      (gtk-widget-show-all window))))

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Crategus on January, 10 2016 using texi2html 1.76.