gui/gui-doc/scribblings/framework/panel.scrbl
2014-12-02 02:33:07 -05:00

284 lines
12 KiB
Racket

#lang scribble/doc
@(require scribble/manual scribble/extract)
@(require (for-label framework mrlib/switchable-button racket/gui))
@title{Panel}
@definterface[panel:single<%> (area-container<%>)]{
See @racket[panel:single-mixin%].
@defmethod*[(((active-child (child (is-a?/c area<%>))) void?) ((active-child) (is-a?/c area<%>)))]{
Sets the active child to be @racket[child]
Returns the current active child.
}
}
@defmixin[panel:single-mixin (area-container<%>) (panel:single<%>)]{
This mixin adds single panel functionality to an implementation of the
@racket[area-container<%>] interface.
Single panels place all of the children in the center of the panel, and allow
make one child to be visible at a time. The
@method[panel:single<%> active-child] method controls which panel is
currently active.
The @method[window<%> show] method is used to hide and show the children of a
single panel.
@defmethod*[#:mode override (((after-new-child (child (is-a?/c subarea<%>))) void?))]{
Hides this child by calling @racket[(send child show #f)], unless this is
the first child in which case it does nothing.
}
@defmethod*[#:mode override (((container-size) (values exact-integer? exact-integer?)))]{
Returns the maximum width of all the children and the maximum height of all
of the children.
}
@defmethod*[#:mode override (((place-children) (listof (list/c exact-integer? exact-integer? exact-integer? exact-integer?))))]{
Returns the positions for single panels and panes.
}
}
@definterface[panel:single-window<%> (panel:single<%> window<%>)]{
}
@defmixin[panel:single-window-mixin (panel:single<%> window<%>) (panel:single-window<%>)]{
@defmethod*[#:mode override
(((container-size (info (listof (list/c exact-integer?
exact-integer?
boolean?
boolean?))))
(values exact-integer? exact-integer?)))]{
Factors the border width into the size calculation.
}
}
@defclass[panel:single% (panel:single-window-mixin (panel:single-mixin panel%)) ()]{}
@defclass[panel:single-pane% (panel:single-mixin pane%) ()]{}
@definterface[panel:dragable<%> (window<%> area-container<%>)]{
Classes matching this interface implement a panel where the user can adjust
the percentage of the space that each takes up. The user adjusts the size by
clicking and dragging the empty space between the children.
@defmethod*[(((after-percentage-change) void?))]{
This method is called when the user changes the percentage by dragging the
bar between the children, or when a new child is added to the frame, but
not when @method[panel:dragable<%> set-percentages] is called.
Use @method[panel:dragable<%> get-percentages] to find the current
percentages.
}
@defmethod[(get-default-percentages [subwindow-count exact-positive-integer?])
(listof (and/c real? (between/c 0 1)))]{
Called when the number of children in the panel changes;
the result is used as the initial percentages for each of the new
windows.
The numbers in the result list must sum to @racket[1].
}
@defmethod[(right-click-in-gap [evt (is-a?/c mouse-event%)]
[before (is-a?/c subarea<%>)]
[after (is-a?/c subarea<%>)])
void?]{
This method is called when the user right-clicks in the space
between two children. It receives the mouse event and the
child before and after the gap where the user clicked.
}
@defmethod*[(((set-percentages (new-percentages (listof number?))) void?))]{
Call this method to set the percentages that each window takes up of the
panel.
The argument, @racket[new-percentages] must be a list of numbers that sums
to 1. It's length must be equal to the number of children of the panel (see
@method[area-container<%> get-children]) and each percentage must
correspond to a number of pixels that is equal to or larger than the
minimum with of the child, as reported by @method[area<%> min-width].
}
@defmethod*[(((get-percentages) (listof number?)))]{
Return the current percentages of the children.
}
@defmethod*[(((get-vertical?) boolean?))]{
This method controls the behavior of the other overridden methods in mixins
that implement this interface.
If it returns @racket[#t], the panel will be vertically aligned and if it
returns @racket[#f], they will be horizontally aligned.
}
@defmethod[(set-orientation [horizontal? boolean?]) void?]{
Sets the orientation of the panel, switching it from behaving like a
@racket[panel:horizontal-dragable<%>] and
@racket[panel:vertical-dragable<%>].
}
}
@definterface[panel:vertical-dragable<%> (panel:dragable<%>)]{
A panel that implements @racket[panel:vertical-dragable<%>]. It aligns its
children vertically.
}
@definterface[panel:horizontal-dragable<%> (panel:dragable<%>)]{
A panel that implements @racket[panel:horizontal-dragable<%>]. It aligns its
children horizontally.
}
@defmixin[panel:dragable-mixin (window<%> area-container<%>) (panel:dragable<%>)]{
This mixin adds the @racket[panel:dragable<%>] functionality to a
@racket[panel%].
It is not useful unless the @method[panel:dragable<%> get-vertical?] method
is overridden.
@defmethod*[#:mode override (((after-new-child (child (is-a?/c subarea<%>))) void?))]{
Updates the number of percentages to make sure that it matches the number
of children and calls @method[panel:dragable<%> after-percentage-change].
}
@defmethod*[#:mode override (((on-subwindow-event (receiver (is-a?/c window<%>)) (event (is-a?/c mouse-event%))) boolean?))]{
When the cursor is dragging the middle bar around, this method handles the
resizing of the two panes.
}
@defmethod*[#:mode override
(((place-children (info (listof (list/c exact-integer? exact-integer?)))
(w exact-integer?)
(h exact-integer?))
(listof (list/c exact-integer? exact-integer? exact-integer? exact-integer?))))]{
Places the children vertically in the panel, based on the percentages
returned from @method[panel:dragable<%> get-percentages]. Also leaves a
little gap between each pair of children.
}
@defmethod*[#:mode override (((container-size (info (listof (list/c exact-integer? exact-integer? any/c any/c))))
(values exact-integer? exact-integer?)))]{
Computes the minimum size the panel would have to be in order to have the
current percentages (see @method[panel:dragable<%> get-percentages]).
}
}
@defmixin[panel:vertical-dragable-mixin (panel:dragable<%>) (panel:vertical-dragable<%>)]{
This mixin merely overrides the @method[panel:dragable<%> get-vertical?]
method of the @racket[panel:dragable-mixin] to return @racket[#t].
@defmethod*[#:mode override (((get-vertical?) boolean?))]{
Returns @racket[#t].
}
}
@defmixin[panel:horizontal-dragable-mixin (panel:dragable<%>) (panel:vertical-dragable<%>)]{
This mixin merely overrides the @method[panel:dragable<%> get-vertical?]
method of the @racket[panel:dragable-mixin] to return @racket[#f].
@defmethod*[#:mode override (((get-vertical?) boolean?))]{
Returns @racket[#f].
}
}
@defclass[panel:vertical-dragable% (panel:vertical-dragable-mixin (panel:dragable-mixin panel%)) ()]{}
@defclass[panel:horizontal-dragable% (panel:horizontal-dragable-mixin (panel:dragable-mixin panel%)) ()]{}
@definterface[panel:splitter<%> ()]{
A panel that implements @racket[panel:splitter<%>]. Children can be split
horizonally or vertically.
}
@defmixin[panel:splitter-mixin (area-container<%> panel:dragable<%>) (panel:splitter<%>)]{
This mixin allows panels to split their children either horizontally or
vertically. Children that are split can be further split independant of any
other splitting.
@defmethod[(split-vertical (canvas (is-a?/c canvas<%>))
(maker (-> (is-a?/c panel:splitter<%>)
(is-a?/c canvas<%>))))
(is-a?/c canvas<%>)]{
Splits the @racket[canvas] vertically by creating a new instance using
@racket[maker]. This splitter object is passed as the argument to
@racket[maker] and should be used as the @racket[parent] field of the newly
created canvas.
}
@defmethod[(split-horizontal (canvas (is-a?/c canvas<%>))
(maker (-> (is-a?/c panel:splitter<%>)
(is-a?/c canvas<%>))))
(is-a?/c canvas<%>)]{
Similar to @racket[split-vertical] but splits horizontally.
}
@defmethod[(collapse (canvas (is-a?/c canvas<%>))) void]{
Removes the given @racket[canvas] from the splitter hierarchy and collapses
any split panes as necessary.
}
}
@definterface[panel:discrete-sizes<%> ()]{
Classes implementing this interface support children
with multiple fixed sizes. As the panel is resized,
it calculates a set of sizes of its children
that fills its available size and approtions the space accordingly
using only one of the fixed sizes.
The strategy it uses is to try to give the largest of
the sizes to children that appear later in
the list of children (to the right horizontal and lower
vertically). It does not try all possible combinations.
Each child that supports minimum sizes is expected to
implement the @racket[panel:discrete-child<%>] interface.
Children that do not implement this interface are just
treated like @racket[horizontal-panel%] or @racket[vertical-panel%]
would treat them, with the exception of
@racket[switchable-button%]. In that case, the
results of
@method[switchable-button% get-small-width] and
@method[switchable-button% get-large-width] are
treated as the two fixed sizes for instances of that class.
Also note that, the orientation of the panel determines whether
or not it treats heights or widths as described above. That is,
when a panel is in vertical mode, it ignores the horizontal
discrete sizes, and vice-versa.
@defmethod[(set-orientation [horizontal? boolean?]) void?]{
Changes the orientation of the panel.
}
@defmethod[(get-orientation) boolean?]{
Returns the current orientation of the panel.
}
}
@definterface[panel:discrete-child<%> ()]{
Classes that implement this method collaborate with
@racket[panel:discrete-sizes<%>] to indicate
which fixed sizes they support.
@defmethod[(get-discrete-widths) (listof exact-nonnegative-integer?)]{
Return a list of widths this class supports.
}
@defmethod[(get-discrete-heights) (listof exact-nonnegative-integer?)]{
Return a list of heights this class supports.
}
}
@defmixin[panel:discrete-sizes-mixin (panel%) (panel:discrete-sizes<%> panel:discrete-child<%>)]{
Provides an implementation of @racket[panel:discrete-sizes<%>].
It uses the sizes of its children to implement the @racket[panel:discrete-child<%>] interface.
}
@defclass[panel:horizontal-discrete-sizes% (panel:discrete-sizes-mixin panel%) ()]{}
@defclass[panel:vertical-discrete-sizes% (panel:discrete-sizes-mixin panel%) ()]{
Calls @method[panel:discrete-sizes<%> set-orientation] with @racket[#f] during
initialization.
}
@(include-previously-extracted "main-extracts.rkt" #rx"^panel:")