@c -----------------------------------------------------------------------------
@c File     : gtk-container-widgets.texi
@c License  : GNU General Public License (GPL)
@c Language : German
@c Author   : Dieter Kaiser
@c Date     : 09.02.2012
@c Revision : 01.08.2013
@c
@c Copyright (C) 2012, 2013 by Dieter Kaiser
@c -----------------------------------------------------------------------------

@menu
* Alignment Widget::
* Fixed Container::
* Layout Container::
* Frames::
* Aspect Frames::
* Paned Window Widgets::
* Viewports::
* Scrolled Windows::
* Button Boxes::
* Toolbar::
* Notebook::
@end menu

@c -----------------------------------------------------------------------------
@node Alignment Widget, Fixed Container, Top, Top
@section Alignment Widget

@findex GtkAlignment
@findex gtk-alignment
@findex alignment, gtk-alignment

@findex gtk-alignment-new
@findex gtk-alignment-set

@findex alignment-new, gtk-alignment-new
@findex alignment-set, gtk-alignment-set

@ifnotinfo
@float Figure, figure-alignment
@caption{Alignment Widget}
@center @image{figures/alignment302x329, 201pt}
@end float
@end ifnotinfo

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

The @xurl{gtk-alignment} container has the four properties @code{xalign},
@code{yalign}, @code{xscale}, and @code{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 @code{0.0} (top or left) to @code{1.0}
(bottom or right).  Of course, if the scale settings are both set to
@code{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 @xurl{gtk-alignment}.  The values can range from @code{0.0} (meaning the
child doesn't expand at all) to @code{1.0} (meaning the child expands to fill
all of the available space).

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

@findex gtk-alignment-set-padding
@findex gtk-alignment-get-padding

@findex alignment-set-padding, gtk-alignment-set-padding
@findex alignment-get-padding, gtk-alignment-get-padding

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

@noindent
@emph{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
@xurl{gtk-alignment} should not be used in new code.

@float Example, example-alignment
@caption{Alignment Widget}
@end float
@verbatim
(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))))
@end verbatim

@c -----------------------------------------------------------------------------
@node Fixed Container, Layout Container, Alignment Widget, Top
@section Fixed Container

@findex GtkFixed
@findex gtk-fixed
@findex fixed, gtk-fixed

@findex gtk-fixed-new
@findex gtk-fixed-put
@findex gtk-fixed-move

@findex fixed-new, gtk-fixed-new
@findex fixed-put, gtk-fixed-put
@findex fixed-move, gtk-fixed-move

@ifnotinfo
@float Figure, figure-fixed
@caption{Fixed Container}
@center @image{figures/fixed302x254, 201pt}
@end float
@end ifnotinfo

The @xurl{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 @xurl{gtk-fixed} widget
like @xurl{gtk-fixed-new}, @xurl{gtk-fixed-put}, and @xurl{gtk-fixed-move}.

The function @xurl{gtk-fixed-new} creates a new @xurl{gtk-fixed} widget.  The
function @xurl{gtk-fixed-put} places a widget in the container fixed at the
position specified by the arguments @code{x} and @code{y}.  The function
@xurl{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 @xurl{gtk-fixed}, the following things will result in
truncated text, overlapping widgets, and other display bugs:

@itemize
@item Themes, which may change widget sizes.
@item Fonts other than the one you used to write the application will of course
      change the size of widgets containing text; keep in mind that users may
      use a larger font because of difficulty reading the default, or they
      may be using Windows or the framebuffer port of GTK+, where different
      fonts are available.
@item Translation of text into other languages changes its size.  Also,
      display of non-English text will use a different font in many cases.
@end itemize

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 @xurl{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 @xurl{gtk-fixed}, by all means use the widget. But you
should be aware of the tradeoffs.

@findex GdkRectangle
@findex gdk-rectangle
@findex rectangle, gdk-rectangle

@findex gdk-rectangle-width
@findex gdk-rectangle-height

@findex rectangle-width, gdk-rectangle-width
@findex rectangle-height, gdk-rectangle-height

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 @xurl{gtk-widget-get-allocation} is used, which
returns a rectangle of type @xurl{gdk-rectangle}.  The width and the height of
the fixed widget are then get with the functions @xurl{gdk-rectangle-width} and
@xurl{gdk-rectangle-height}.

@float Example, example-fixed
@caption{Fixed Container}
@end float
@verbatim
(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))))
@end verbatim

@c -----------------------------------------------------------------------------
@node Layout Container, Frames, Fixed Container, Top
@section Layout Container

@findex GtkLayout
@findex gtk-layout
@findex layout, gtk-layout

@findex gtk-layout-new
@findex gtk-layout-put
@findex gtk-layout-move
@findex gtk-layout-get-size
@findex gtk-layout-set-size

@findex layout-new, gtk-layout-new
@findex layout-put, gtk-layout-put
@findex layout-move, gtk-layout-move
@findex layout-get-size, gtk-layout-get-size
@findex layout-set-size, gtk-layout-set-size

The layout container @xurl{gtk-layout} is similar to the fixed container
@xurl{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 @xurl{gtk-layout-new} which accepts the
optional arguments @code{hadjustment} and @code{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
@xurl{gtk-layout-put} and @xurl{gtk-layout-move}.  The size of the layout
container can be set using the function @xurl{gtk-layout-set-size}.

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

@c -----------------------------------------------------------------------------
@node Frames, Aspect Frames, Layout Container, Top
@section Frames

@findex GtkFrame
@findex gtk-frame
@findex frame, gtk-frame

@findex gtk-frame-new
@findex gtk-frame-set-label

@findex frame-new, gtk-frame-new
@findex frame-set-label, gtk-frame-set-label

@ifnotinfo
@float Figure, figure-frame
@caption{Frame Widget}
@center @image{figures/frame252x229, 168pt}
@end float
@end ifnotinfo

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 @code{(make-instance 'gtk-frame)} or the function
@xurl{gtk-frame-new}.  The label is by default placed in the upper left hand
corner of the frame. A value of @code{NIL} for the label argument will result in
no label being displayed.  The text of the label can be changed using the
function @xurl{gtk-frame-set-label}.

@findex gtk-frame-set-label-align
@findex frame-set-label-align, gtk-frame-set-label-align

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

@findex GtkShadowType
@findex gtk-shadow-type
@findex shadow-type, gtk-shadow-type

@findex gtk-frame-set-shadow-type
@findex frame-set-shadow-type, gtk-frame-set-shadow-type

The function @xurl{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 @xurl{gtk-shadow-type}.

@ref{example-frame} illustrates the use of the frame widget.  The code of this
example is shown in @ref{example-frame}.

@float Example, example-frame
@caption{Frame Widget}
@end float
@verbatim
(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))))
@end verbatim

@c -----------------------------------------------------------------------------
@node Aspect Frames, Paned Window Widgets, Frames, Top
@section Aspect Frames

@findex GtkAspectFrame
@findex gtk-aspect-frame
@findex aspect-frame, gtk-aspect-frame

@findex gtk-aspect-frame-new
@findex aspect-frame-new, gtk-aspect-frame-new

@ifnotinfo
@float Figure, figure-aspect-frame
@caption{Aspect Frame Container}
@center @image{figures/aspect-frame302x279, 201pt}
@end float
@end ifnotinfo

The @xurl{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 @code{(make-instance 'gtk-aspect-frame)} or the
function @xurl{gtk-aspect-frame-new}.  The arguments @code{xalign} and
@code{yalign} specify alignment as with alignment containers.  If the property
@code{obey-child} is @emph{true}, the aspect ratio of a child widget will match
the aspect ratio of the ideal size it requests.  Otherwise, it is given by
@code{ratio}.

The options of an existing aspect frame can be changed with the function
@xurl{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.

@float Example, example-aspect-frame
@caption{Aspect Frame Container}
@end float
@verbatim
(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))))
@end verbatim

@c -----------------------------------------------------------------------------
@node Paned Window Widgets, Viewports, Aspect Frames, Top
@section Paned Window Widgets

@findex GtkPaned
@findex gtk-paned
@findex paned, gtk-paned

@ifnotinfo
@float Figure, figure-paned-window
@caption{Paned Window Widgets}
@center @image{figures/paned-window302x279, 201pt}
@end float
@end ifnotinfo

@xurl{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.

@findex gtk-paned-new
@findex paned-new, gtk-paned-new

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

@findex gtk-paned-pack1
@findex gtk-paned-pack2
@findex gtk-paned-add1
@findex gtk-paned-add2

@findex paned-pack1, gtk-paned-pack1
@findex paned-pack2, gtk-paned-pack2
@findex paned-add1, gtk-paned-add1
@findex paned-add2, gtk-paned-add2

Child widgets are added to the panes of the widget with the functions
@xurl{gtk-paned-pack1} and @xurl{gtk-paned-pack2} or the functions
@xurl{gtk-paned-add1} and @xurl{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 @xurl{gtk-frame} with the shadow type set to @code{: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, @code{resize} and @code{shrink}.
If @code{resize} is @code{T}, then when the @code{GtkPaned} is resized, that
child will expand or shrink along with the paned widget. If @code{shrink} is
@code{T}, then that child can be made smaller than its requisition by the user.
Setting @code{shrink} to @code{NIL} allows the application to set a minimum
size.  If @code{resize} is @code{NIL} for both children, then this is treated as
if resize is @code{T} for both children.

@findex gtk-paned-set-position
@findex paned-set-position, gtk-paned-set-position

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

@ref{figure-paned-window} shows a simple example.   The corresponding code is
shown in @ref{example-paned-window}

@c TODO: The example is very simple. It is not taken from the GTK+ 2.0 Tutorial.

@float Example, example-paned-window
@caption{Paned Window Widgets}
@end float
@verbatim
(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))))
@end verbatim

@c -----------------------------------------------------------------------------
@node Viewports, Scrolled Windows, Paned Window Widgets, Top
@section Viewports

@findex GtkViewport
@findex gtk-viewport
@findex viewport, gtk-viewport

@findex gtk-viewport-new
@findex viewport-new, gtk-viewport-new

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

@findex gtk-scrolled-window-add-with-viewport
@findex scrolled-window-add-with-viewport, gtk-scrolled-window-add-with-viewport

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

The @xurl{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 @xurl{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 @code{NIL} as the value of the arguments.

@findex gtk-scrollable-get-hadjustment
@findex gtk-scrollable-set-hadjustment
@findex gtk-scrollable-get-vadjustment
@findex gtk-scrollable-set-vadjustment

@findex scrollable-get-hadjustment, gtk-scrollable-get-hadjustment
@findex scrollable-set-hadjustment, gtk-scrollable-set-hadjustment
@findex scrollable-get-vadjustment, gtk-scrollable-get-vadjustment
@findex scrollable-set-vadjustment, gtk-scrollable-set-vadjustment

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

@findex gtk-viewport-set-shadow-type
@findex viewport-set-shadow-type, gtk-viewport-set-shadow-type

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

@c -----------------------------------------------------------------------------
@node Scrolled Windows, Button Boxes, Viewports, Top
@section Scrolled Windows

@ifnotinfo
@float Figure, figure-scrolled-window
@caption{Scrolled Window}
@center @image{figures/scrolled-window352x329, 235pt}
@end float
@end ifnotinfo

@xurl{gtk-scrolled-window} is a @xurl{gtk-bin} subclass: it is a container that
accepts a single child widget.  @xurl{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 @xurl{gtk-scrollable} interface. Widgets
with native scroll support include @xurl{gtk-tree-view}, @xurl{gtk-text-view},
and @code{gtk-layout}.

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

If a widget has native scrolling abilities, it can be added to the
@xurl{gtk-scrolled-window} with @xurl{gtk-container-add}.  If a widget does not,
you must first add the widget to a @xurl{gtk-viewport}, then add the
@xurl{gtk-viewport} to the scrolled window.  The convenience function
@xurl{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
@xurl{gtk-adjustment} for the fields in an adjustment - for
@xurl{gtk-scrollbar}, used by @xurl{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 @xurl{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 @xurl{gtk-scrollbar} and for example a @xurl{gtk-grid}.

The function @xurl{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 @code{NIL}.

The function @xurl{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 @xurl{gtk-policy-type} and may be one of
@code{:automatic} or @code{:always}.  @code{:automatic} will automatically
decide whether you need scrollbars, whereas @code{:always} will always leave
the scrollbars there. All possible values of @xurl{gtk-policy-type} are listed
in @ref{table-gtk-policy-type}.

@float Table, table-gtk-policy-type
@caption{The values of the enumeration type @code{GtkPolicyType} determines
when a scroll bar will be visible.}
@shortcaption{Values of the type @code{GtkPolicyType}}
@end float
@table @code
@item :always
      The scrollbar is always visible.
@item :automatic
      The scrollbar will appear and disappear as necessary. For example,
      when all of a GtkCList can not be seen.
@item :never
      The scrollbar will never appear.
@end table

@ref{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
@code{gtk-widget-size-request} call to set the default size of the window or
other widgets.

@float Example, example-scrolled-window
@caption{Scrolled Window}
@end float
@verbatim
(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))))
@end verbatim

@c -----------------------------------------------------------------------------
@node Button Boxes, Toolbar, Scrolled Windows
@section Button Boxes

@ifnotinfo
@float Figure, figure-button-box
@caption{Button Boxes}
@center @image{figures/button-box576x603, 384pt}
@end float
@end ifnotinfo

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.

@xurl{gtk-button-box-get-layout} and @xurl{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 @xurl{gtk-button-box} is to make sure the children have all
the same size.  @xurl{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 @code{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 @xurl{gtk-button-box-new},
which creates a horizontal or vertical box depending on the argument
@code{orientation} which takes the values @code{:horizontal} or
@code{:vertical}, respectively.

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

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

@float Example, example-button-box
@caption{Button Boxes}
@end float
@verbatim
(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))))
@end verbatim

@c -----------------------------------------------------------------------------
@node Toolbar, Notebook, Button Boxes, Top
@section Toolbar

A toolbar is created with a call to @xurl{gtk-toolbar-new}.

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

Toolbar items can be visually grouped by adding instances of
@xurl{gtk-separator-tool-item} to the toolbar. If the @xurl{gtk-toolbar} child
property "expand" is @emph{true} and the property @code{"draw"} is set to
@code{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.


@c -----------------------------------------------------------------------------
@node Notebook, , Button Boxes, Top
@section Notebook

@ifnotinfo
@float Figure, figure-notebook
@caption{Notebook}
@center @image{figures/notebook347x229, 231pt}
@end float
@end ifnotinfo

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

There are many configuration options for @xurl{gtk-notebook}.  Among other
things, you can choose on which edge the tabs appear (see
@xurl{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
@xurl{gtk-notebook-set-scrollable}), and whether there will be a popup menu
allowing the users to switch pages (see @xurl{gtk-notebook-popup-enable},
@xurl{gtk-notebook-popup-disable}).

@float Example, example-notebook
@caption{Notebook}
@end float
@verbatim
(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))))
@end verbatim

