new gui reference work
svn: r7106
This commit is contained in:
parent
fcf31d7086
commit
33d7e3ded3
|
@ -296,7 +296,9 @@
|
|||
(let ([number (collected-info-number (part-collected-info part))])
|
||||
(let ([subs
|
||||
(if (quiet (and (styled-part? part)
|
||||
(eq? 'quiet (styled-part-style part))
|
||||
(let ([st(styled-part-style part)])
|
||||
(or (eq? 'quiet st)
|
||||
(and (list? st) (memq 'quiet st))))
|
||||
(not (= base-len (sub1 (length number))))))
|
||||
(apply
|
||||
append
|
||||
|
|
|
@ -22,17 +22,17 @@
|
|||
(let ([content (decode-content str)])
|
||||
(make-title-decl (or tag (gen-tag content)) style content)))
|
||||
|
||||
(define (section #:tag [tag #f] . str)
|
||||
(define (section #:tag [tag #f] #:style [style #f] . str)
|
||||
(let ([content (decode-content str)])
|
||||
(make-part-start 0 (or tag (gen-tag content)) content)))
|
||||
(make-part-start 0 (or tag (gen-tag content)) style content)))
|
||||
|
||||
(define (subsection #:tag [tag #f] . str)
|
||||
(let ([content (decode-content str)])
|
||||
(make-part-start 1 (or tag (gen-tag content)) content)))
|
||||
(make-part-start 1 (or tag (gen-tag content)) #f content)))
|
||||
|
||||
(define (subsubsection #:tag [tag #f] . str)
|
||||
(let ([content (decode-content str)])
|
||||
(make-part-start 2 (or tag (gen-tag content)) content)))
|
||||
(make-part-start 2 (or tag (gen-tag content)) #f content)))
|
||||
|
||||
(define (subsubsub*section #:tag [tag #f] . str)
|
||||
(let ([content (decode-content str)])
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
[content list?])]
|
||||
[part-start ([depth integer?]
|
||||
[tag (or/c false/c string?)]
|
||||
[style any/c]
|
||||
[title list?])]
|
||||
[splice ([run list?])]
|
||||
[part-index-decl ([plain-seq (listof string?)]
|
||||
|
@ -136,10 +137,11 @@
|
|||
((part-start-depth (car l)) . <= . part-depth))
|
||||
(part? (car l))))
|
||||
(let ([para (decode-accum-para accum)]
|
||||
[s (decode-part (reverse s-accum)
|
||||
(part-start-tag s)
|
||||
(part-start-title s)
|
||||
(add1 part-depth))]
|
||||
[s (decode-styled-part (reverse s-accum)
|
||||
(part-start-tag s)
|
||||
(part-start-style s)
|
||||
(part-start-title s)
|
||||
(add1 part-depth))]
|
||||
[part (decode-flow* l keys tag style title part-depth)])
|
||||
(make-styled-part (part-tags part)
|
||||
(part-title-content part)
|
||||
|
@ -179,6 +181,9 @@
|
|||
(define (decode-part l tag title depth)
|
||||
(decode-flow* l null tag #f title depth))
|
||||
|
||||
(define (decode-styled-part l tag style title depth)
|
||||
(decode-flow* l null tag style title depth))
|
||||
|
||||
(define (decode-flow l)
|
||||
(part-flow (decode-flow* l null #f #f #f #f)))
|
||||
|
||||
|
|
|
@ -454,7 +454,9 @@
|
|||
|
||||
(define/private (toc-part? d)
|
||||
(and (styled-part? d)
|
||||
(eq? 'toc (styled-part-style d))))
|
||||
(let ([st (styled-part-style d)])
|
||||
(or (eq? 'toc st)
|
||||
(and (list? st) (memq 'toc st))))))
|
||||
|
||||
(define/override (collect-part d parent ht number)
|
||||
(let ([prev-sub (collecting-sub)])
|
||||
|
|
|
@ -84,10 +84,14 @@
|
|||
#f
|
||||
(map (lambda (s)
|
||||
(list (make-flow (list (make-paragraph
|
||||
(let ([spaces (cdar (regexp-match-positions #rx"^ *" s))])
|
||||
(list
|
||||
(hspace spaces)
|
||||
(make-element 'tt (list (substring s spaces))))))))))
|
||||
(let loop ([s s])
|
||||
(let ([spaces (regexp-match-positions #rx"(?:^| ) +" s)])
|
||||
(if spaces
|
||||
(append
|
||||
(loop (substring s 0 (caar spaces)))
|
||||
(list (hspace (- (cdar spaces) (caar spaces))))
|
||||
(loop (substring s (cdar spaces))))
|
||||
(list (make-element 'tt (list s)))))))))))
|
||||
strs))))
|
||||
|
||||
(define-syntax indexed-scheme
|
||||
|
|
|
@ -9,31 +9,34 @@ A @scheme[checkable-menu-item%] is a string-labelled menu item that
|
|||
item's check mark is toggled and its callback procedure is called.
|
||||
|
||||
|
||||
@defconstructor[([label label-string?]
|
||||
[parent (or/c (is-a?/c menu% popup-menu%))]
|
||||
[callback ((is-a?/c checkable-menu-item%) (is-a?/c control-event%) . -> . any)
|
||||
(lambda (i e) (void))]
|
||||
[shortcut (or/c char? false/c) #f]
|
||||
[help-string (or/c label-string? false/c) #f]
|
||||
[demand-callback ((is-a?/c menu-item%) . -> . any)
|
||||
(lambda (i) (void))]
|
||||
[checked any/c #f]
|
||||
[shortcut-prefix (listof (one-of/c 'alt 'cmd 'meta 'ctl
|
||||
'shift 'option))
|
||||
(get-default-shortcut-prefix)])] {
|
||||
|
||||
Creates a new menu item in @scheme[parent]. The item is initially
|
||||
shown, appended to the end of its parent, and unchecked. The
|
||||
@scheme[callback] procedure is called (with the event type
|
||||
@indexed-scheme['menu]) when the menu item is selected (either via a
|
||||
menu bar, @xmethod[window<%> popup-menu], or @xmethod[editor-admin%
|
||||
popup-menu]).
|
||||
|
||||
@defconstructor[[label label-string?]
|
||||
[parent @scheme[menu%] or @scheme[popup-menu%] object]
|
||||
[callback procedure of two arguments: a @scheme[menu-item%] object and a @scheme[control-event%] object]
|
||||
[shortcut (or/c character false/c) #f]
|
||||
[help-string (or/c label-string? false/c) #f]
|
||||
[demand-callback procedure of one argument: a @scheme[checkable-menu-item%] object @scheme[void]]
|
||||
[checked any/c #f]
|
||||
[shortcut-prefix (symbols/c option shift ctl meta cmd alt) @scheme[(\iscmprocedure{get-default-shortcut-prefix])}]]{
|
||||
|
||||
Creates a new menu item in @scheme[parent]. The item is initially shown,
|
||||
appended to the end of its parent, and unchecked. The @scheme[callback]
|
||||
procedure is called (with the event type @indexed-scheme['menu]) when the
|
||||
menu item is selected (either via a menu bar,
|
||||
@xmethod[window<%> popup-menu], or
|
||||
@xmethod[editor-admin% popup-menu]).
|
||||
|
||||
See
|
||||
@method[labelled-menu-item<%> set-label] for information about mnemonic ampersands (``\&'') in @scheme[label].
|
||||
See @method[labelled-menu-item<%> set-label] for information about
|
||||
mnemonic @litchar{&}s in @scheme[label].
|
||||
|
||||
If @scheme[shortcut] is not @scheme[#f], the item has a shortcut. See
|
||||
@method[selectable-menu-item<%> get-shortcut] for more information. The @scheme[shortcut-prefix] argument determines the
|
||||
set of modifier keys for the shortcut; see
|
||||
@method[selectable-menu-item<%> get-shortcut-prefix].
|
||||
@method[selectable-menu-item<%> get-shortcut] for more information.
|
||||
The @scheme[shortcut-prefix] argument determines the set of modifier
|
||||
keys for the shortcut; see @method[selectable-menu-item<%>
|
||||
get-shortcut-prefix].
|
||||
|
||||
If @scheme[help] is not @scheme[#f], the item has a help string. See
|
||||
@method[labelled-menu-item<%> get-help-string] for more information.
|
||||
|
@ -41,34 +44,25 @@ If @scheme[help] is not @scheme[#f], the item has a help string. See
|
|||
The @scheme[demand-callback] procedure is called by the default
|
||||
@method[labelled-menu-item<%> on-demand] method with the object itself.
|
||||
|
||||
By default, the menu item is initially unchecked. If @scheme[checked] is
|
||||
true, then
|
||||
@method[checkable-menu-item% check] is called so that the menu item is initially checked.
|
||||
|
||||
|
||||
By default, the menu item is initially unchecked. If @scheme[checked]
|
||||
is true, then @method[checkable-menu-item% check] is called so that
|
||||
the menu item is initially checked.
|
||||
|
||||
}
|
||||
|
||||
@defmethod[(check [check? any/c])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Checks or unchecks the menu item.
|
||||
|
||||
@MonitorCallbackX[@elem{A menu item's check state} @elem{the user selecting the item} @elem{check state} @elem{menu item}]
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
@defmethod[(is-checked?)
|
||||
boolean?]{
|
||||
@spec{
|
||||
|
||||
Returns @scheme[#t] if the item is checked, {\#f} otherwise.
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
|
||||
|
||||
}}}
|
||||
}}
|
||||
|
||||
|
|
106
collects/scribblings/gui/diagrams.ss
Normal file
106
collects/scribblings/gui/diagrams.ss
Normal file
|
@ -0,0 +1,106 @@
|
|||
(module diagrams mzscheme
|
||||
(require (lib "string.ss")
|
||||
(lib "struct.ss" "scribble")
|
||||
(lib "scheme.ss" "scribble")
|
||||
(lib "manual.ss" "scribble"))
|
||||
|
||||
(provide diagram->table
|
||||
short-windowing-diagram
|
||||
windowing-diagram
|
||||
event-diagram
|
||||
menu-diagram)
|
||||
|
||||
(define (diagram->table d)
|
||||
(make-table
|
||||
#f
|
||||
(map (lambda (line)
|
||||
(list (make-flow
|
||||
(list (make-paragraph
|
||||
(let loop ([line line])
|
||||
(cond
|
||||
[(regexp-match #rx"(.*)( +)(.*)" line)
|
||||
=> (lambda (m)
|
||||
(append (loop (cadr m))
|
||||
(list (hspace (string-length (caddr m))))
|
||||
(loop (cadddr m))))]
|
||||
[(regexp-match #rx"([^-a-zA-Z0-9]*)([-a-zA-Z0-9<%>]+)(.*)" line)
|
||||
=> (lambda (m)
|
||||
(append (loop (cadr m))
|
||||
(list (to-element (string->symbol (caddr m))))
|
||||
(loop (cadddr m))))]
|
||||
[else (list (make-element 'tt (list line)))])))))))
|
||||
(regexp-split #rx"[\r\n]+" d))))
|
||||
|
||||
(define short-windowing-diagram
|
||||
#<<DIAG
|
||||
area<%>
|
||||
______________________|_______________
|
||||
| | |
|
||||
subarea<%> window<%> area-container<%>
|
||||
|____ _______|__________ |
|
||||
| | | |
|
||||
subwindow<%> area-container-window<%>
|
||||
________|________ |
|
||||
| | |
|
||||
control<%> canvas<%> top-level-window<%>
|
||||
DIAG
|
||||
)
|
||||
|
||||
(define windowing-diagram
|
||||
#<<DIAG
|
||||
area<%>
|
||||
_____________________|_______________
|
||||
| | |
|
||||
subarea<%> window<%> area-container<%>
|
||||
<<<____|____ _____|__________ __|___ ___________________<<<
|
||||
| | | | | |
|
||||
subwindow<%> | | | |
|
||||
<<<______________|___________ | | | | _<<<
|
||||
| | | | pane% |
|
||||
control<%> | | | |- horizontal-pane% |
|
||||
|- message% | | | |- vertical-pane% |
|
||||
|- button% | | | |
|
||||
|- check-box% | area-container-window<%> |
|
||||
|- slider% | | |
|
||||
|- gauge% | | __________________|
|
||||
|- text-field% | | |
|
||||
|- combo-field% | |-------- panel%
|
||||
|- radio-box% | | |- horizontal-panel%
|
||||
|- list-control<%> | | |- vertical-panel%
|
||||
|- choice% | | |- tab-panel%
|
||||
|- list-box% | | |- group-box-panel%
|
||||
| |
|
||||
| |- top-level-window<%>
|
||||
| |- frame%
|
||||
canvas<%> |- dialog%
|
||||
|- canvas%
|
||||
|- editor-canvas%
|
||||
DIAG
|
||||
)
|
||||
|
||||
|
||||
(define event-diagram
|
||||
#<<DIAG
|
||||
event% timer%
|
||||
|- key-event% cursor%
|
||||
|- mouse-event%
|
||||
|- scroll-event% clipboard<%>
|
||||
|- control-event% clipboard-client%
|
||||
DIAG
|
||||
)
|
||||
|
||||
(define menu-diagram
|
||||
#<<DIAG
|
||||
menu-item<%> menu-item-container<%>
|
||||
| |
|
||||
|- separator-menu-item% _____|___
|
||||
|- labelled-menu-item<%> | |- menu-bar%
|
||||
_________|_________ | |- popup-menu%
|
||||
| | |
|
||||
| menu%
|
||||
|
|
||||
|- selectable-menu-item<%>
|
||||
|- menu-item%
|
||||
|- checkable-menu-item%
|
||||
DIAG
|
||||
))
|
276
collects/scribblings/gui/draw-overview.scrbl
Normal file
276
collects/scribblings/gui/draw-overview.scrbl
Normal file
|
@ -0,0 +1,276 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require[(lib "eval.ss" "scribble")]
|
||||
@require["common.ss"]
|
||||
@require["diagrams.ss"]
|
||||
|
||||
@title[#:tag "mred:drawing-toolbox"]{Drawing Toolbox Overview}
|
||||
|
||||
Drawing in MrEd requires a @deftech{device context} (@deftech{DC}),
|
||||
which is an instance of the @scheme[dc<%>] interface. For example,
|
||||
the @method[canvas<%> get-dc] method of a canvas returns a
|
||||
@scheme[dc<%>] instance for drawing into the canvas window. Other
|
||||
kinds of DCs draw to different kinds of devices:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@scheme[bitmap-dc%] --- a @deftech{bitmap DC} draws to an
|
||||
offscreen bitmap.}
|
||||
|
||||
@item{@scheme[post-script-dc%] --- a @deftech{PostScript DC}
|
||||
records drawing commands to a PostScript file.}
|
||||
|
||||
@item{@scheme[printer-dc%] --- a @deftech{printer DC} draws to a
|
||||
platform-specific printer device (Windows, Mac OS X).}
|
||||
|
||||
}
|
||||
|
||||
Tools that are used for drawing include the following: @scheme[pen%]
|
||||
objects for drawing lines and shape outlines, @scheme[brush%]
|
||||
objects for filling shapes, @scheme[bitmap%] objects for storing
|
||||
bitmaps, and @scheme[dc-path%] objects for describing paths to draw
|
||||
and fill.
|
||||
|
||||
The following example creates a frame with a drawing canvas, and then
|
||||
draws a round, blue face with square, yellow eyes and a smiling, red
|
||||
mouth:
|
||||
|
||||
@schemeblock[
|
||||
(code:comment #, @t{Make a 300 x 300 frame})
|
||||
(define frame (new frame% [label "Drawing Example"]
|
||||
[width 300]
|
||||
[height 300]))
|
||||
(code:comment #, @t{Make the drawing area})
|
||||
(define canvas (new canvas% [parent frame]))
|
||||
(code:comment #, @t{Get the canvas's drawing context})
|
||||
(define dc (send canvas #,(:: canvas% get-dc)))
|
||||
|
||||
(code:comment #, @t{Make some pens and brushes})
|
||||
(define no-pen (make-object pen% "BLACK" 1 'transparent))
|
||||
(define no-brush (make-object brush% "BLACK" 'transparent))
|
||||
(define blue-brush (make-object brush% "BLUE" 'solid))
|
||||
(define yellow-brush (make-object brush% "YELLOW" 'solid))
|
||||
(define red-pen (make-object pen% "RED" 2 'solid))
|
||||
|
||||
(code:comment #, @t{Define a procedure to draw a face})
|
||||
(define (draw-face dc)
|
||||
(send dc #,(:: dc<%> set-pen) no-pen)
|
||||
(send dc #,(:: dc<%> set-brush) blue-brush)
|
||||
(send dc #,(:: dc<%> draw-ellipse) 50 50 200 200)
|
||||
|
||||
(send dc #,(:: dc<%> set-brush) yellow-brush)
|
||||
(send dc #,(:: dc<%> draw-rectangle) 100 100 10 10)
|
||||
(send dc #,(:: dc<%> draw-rectangle) 200 100 10 10)
|
||||
|
||||
(send dc #,(:: dc<%> set-brush) no-brush)
|
||||
(send dc #,(:: dc<%> set-pen) red-pen)
|
||||
(let ([-pi (atan 0 -1)])
|
||||
(send dc #,(:: dc<%> draw-arc) 75 75 150 150 (* 5/4 -pi) (* 7/4 -pi))))
|
||||
|
||||
(code:comment #, @t{Show the frame})
|
||||
(send frame top-level-window::show #t)
|
||||
(code:comment #, @t{Wait a second to let the window get ready})
|
||||
(sleep/yield 1)
|
||||
(code:comment #, @t{Draw the face})
|
||||
(draw-face dc)
|
||||
]
|
||||
|
||||
The @scheme[sleep/yield] call is necessary under X because
|
||||
drawing to the canvas has no effect when the canvas is not
|
||||
shown. Although the @scheme[(send frame top-level-window::show #t)]
|
||||
expression queues a show request for the frame, the actual display of
|
||||
the frame and its canvas requires handling several events. The
|
||||
@scheme[sleep/yield] procedure pauses for a specified number
|
||||
of seconds, handling events while it pauses.
|
||||
|
||||
One second is plenty of time for the frame to show itself, but a
|
||||
better solution is to create a canvas with a paint callback function
|
||||
(or overriding @method[canvas<%> on-paint]). Using a paint
|
||||
callback function is better for all platforms; when the canvas in the
|
||||
above example is resized or temporarily covered by another window,
|
||||
the face disappears. To ensure that the face is redrawn whenever the
|
||||
canvas itself is repainted, we provide a paint callback when creating
|
||||
the canvas:
|
||||
|
||||
@schemeblock[
|
||||
(code:comment #, @t{Make a 300 x 300 frame})
|
||||
(define frame (new frame% [label "Drawing Example"]
|
||||
[width 300]
|
||||
[height 300]))
|
||||
|
||||
(code:comment #, @t{Make the drawing area with a paint callback})
|
||||
(define canvas
|
||||
(new canvas% [parent frame]
|
||||
[paint-callback
|
||||
(lambda (canvas dc) (draw-face dc))]))
|
||||
|
||||
(code:comment #, @t{... pens, brushes, and @scheme[draw-face] are the same as above ...})
|
||||
|
||||
(code:comment #, @t{Show the frame})
|
||||
(send frame top-level-window::show #t)
|
||||
]
|
||||
|
||||
Suppose that @scheme[draw-face] creates a particularly complex face that
|
||||
takes a long time to draw. We might want to draw the face once into
|
||||
an offscreen bitmap, and then have the paint callback copy the cached
|
||||
bitmap image onto the canvas whenever the canvas is updated. To draw
|
||||
into a bitmap, we first create a @scheme[bitmap%] object, and then
|
||||
we create a @scheme[bitmap-dc%] to direct drawing commands into the
|
||||
bitmap:
|
||||
|
||||
@schemeblock[
|
||||
(code:comment #, @t{... pens, brushes, and @scheme[draw-face] are the same as above ...})
|
||||
|
||||
(code:comment #, @t{Create a 300 x 300 bitmap})
|
||||
(define face-bitmap (make-object bitmap% 300 300))
|
||||
(code:comment #, @t{Create a drawing context for the bitmap})
|
||||
(define bm-dc (make-object bitmap-dc% face-bitmap))
|
||||
(code:comment #, @t{A bitmap's initial content is undefined; clear it before drawing})
|
||||
(send bm-dc #,(:: dc<%> clear))
|
||||
|
||||
(code:comment #, @t{Draw the face into the bitmap})
|
||||
(draw-face bm-dc)
|
||||
|
||||
(code:comment #, @t{Make a 300 x 300 frame})
|
||||
(define frame (new frame% [label "Drawing Example"]
|
||||
[width 300]
|
||||
[height 300]))
|
||||
|
||||
(code:comment #, @t{Make the drawing area with a paint callback that copies the bitmap})
|
||||
(define canvas
|
||||
(new canvas% [parent frame]
|
||||
[paint-callback
|
||||
(lambda (canvas dc)
|
||||
(send dc #,(:: dc<%> draw-bitmap) face-bitmap 0 0))]))
|
||||
|
||||
(code:comment #, @t{Show the frame})
|
||||
(send frame #,(:: top-level-window<%> show) #t)
|
||||
]
|
||||
|
||||
For all types of DCs, the drawing origin is the top-left corner of the
|
||||
DC. When drawing to a window or bitmap, DC units initially correspond
|
||||
to pixels, but the @method[dc<%> set-scale] method changes the
|
||||
scale. When drawing to a PostScript or printer device, DC units
|
||||
initially correspond to points (1/72 of an inch).
|
||||
|
||||
More complex shapes are typically best implemented with
|
||||
@deftech{paths}. The following example uses paths to draw the PLT
|
||||
Scheme logo. It also enables smoothing, so that the logo's curves are
|
||||
anti-aliased when smoothing is available. (Smoothing is always
|
||||
available under Mac OS X, smoothing is available under Windows XP or
|
||||
when @file{gdiplus.dll} is installed, and smoothing is available
|
||||
under X when Cairo is installed before MrEd is compiled.)
|
||||
|
||||
@begin[
|
||||
#reader(lib "comment-reader.ss" "scribble")
|
||||
[schemeblock
|
||||
(require (lib "math.ss")) ; for @scheme[pi]
|
||||
|
||||
;; Construct paths for a 630 x 630 logo
|
||||
|
||||
(define left-lambda-path ;; left side of the lambda
|
||||
(let ([p (new dc-path%)])
|
||||
(send p #,(:: dc-path% move-to) 153 44)
|
||||
(send p #,(:: dc-path% line-to) 161.5 60)
|
||||
(send p #,(:: dc-path% curve-to) 202.5 49 230 42 245 61)
|
||||
(send p #,(:: dc-path% curve-to) 280.06 105.41 287.5 141 296.5 186)
|
||||
(send p #,(:: dc-path% curve-to) 301.12 209.08 299.11 223.38 293.96 244)
|
||||
(send p #,(:: dc-path% curve-to) 281.34 294.54 259.18 331.61 233.5 375)
|
||||
(send p #,(:: dc-path% curve-to) 198.21 434.63 164.68 505.6 125.5 564)
|
||||
(send p #,(:: dc-path% line-to) 135 572)
|
||||
p))
|
||||
|
||||
(define left-logo-path ;; left side of the lambda and circle
|
||||
(let ([p (new dc-path%)])
|
||||
(send p #,(:: dc-path% append) left-lambda-path)
|
||||
(send p #,(:: dc-path% arc) 0 0 630 630 (* 235/360 2 pi) (* 121/360 2 pi) #f)
|
||||
p))
|
||||
|
||||
(define bottom-lambda-path
|
||||
(let ([p (new dc-path%)])
|
||||
(send p #,(:: dc-path% move-to) 135 572)
|
||||
(send p #,(:: dc-path% line-to) 188.5 564)
|
||||
(send p #,(:: dc-path% curve-to) 208.5 517 230.91 465.21 251 420)
|
||||
(send p #,(:: dc-path% curve-to) 267 384 278.5 348 296.5 312)
|
||||
(send p #,(:: dc-path% curve-to) 301.01 302.98 318 258 329 274)
|
||||
(send p #,(:: dc-path% curve-to) 338.89 288.39 351 314 358 332)
|
||||
(send p #,(:: dc-path% curve-to) 377.28 381.58 395.57 429.61 414 477)
|
||||
(send p #,(:: dc-path% curve-to) 428 513 436.5 540 449.5 573)
|
||||
(send p #,(:: dc-path% line-to) 465 580)
|
||||
(send p #,(:: dc-path% line-to) 529 545)
|
||||
p))
|
||||
|
||||
(define bottom-logo-path
|
||||
(let ([p (new dc-path%)])
|
||||
(send p #,(:: dc-path% append) bottom-lambda-path)
|
||||
(send p #,(:: dc-path% arc) 0 0 630 630 (* 314/360 2 pi) (* 235/360 2 pi) #f)
|
||||
p))
|
||||
|
||||
(define right-lambda-path
|
||||
(let ([p (new dc-path%)])
|
||||
(send p #,(:: dc-path% move-to) 153 44)
|
||||
(send p #,(:: dc-path% curve-to) 192.21 30.69 233.21 14.23 275 20)
|
||||
(send p #,(:: dc-path% curve-to) 328.6 27.4 350.23 103.08 364 151)
|
||||
(send p #,(:: dc-path% curve-to) 378.75 202.32 400.5 244 418 294)
|
||||
(send p #,(:: dc-path% curve-to) 446.56 375.6 494.5 456 530.5 537)
|
||||
(send p #,(:: dc-path% line-to) 529 545)
|
||||
p))
|
||||
|
||||
(define right-logo-path
|
||||
(let ([p (new dc-path%)])
|
||||
(send p #,(:: dc-path% append) right-lambda-path)
|
||||
(send p #,(:: dc-path% arc) 0 0 630 630 (* 314/360 2 pi) (* 121/360 2 pi) #t)
|
||||
p))
|
||||
|
||||
(define lambda-path ;; the lambda by itself (no circle)
|
||||
(let ([p (new dc-path%)])
|
||||
(send p #,(:: dc-path% append) left-lambda-path)
|
||||
(send p #,(:: dc-path% append) bottom-lambda-path)
|
||||
(let ([t (make-object dc-path%)])
|
||||
(send t #,(:: dc-path% append) right-lambda-path)
|
||||
(send t #,(:: dc-path% reverse))
|
||||
(send p #,(:: dc-path% append) t))
|
||||
(send p #,(:: dc-path% close))
|
||||
p))
|
||||
|
||||
;; This function draws the paths with suitable colors:
|
||||
(define (paint-plt dc)
|
||||
;; Paint white lambda, no outline:
|
||||
(send dc #,(:: dc<%> set-pen) "BLACK" 0 'transparent)
|
||||
(send dc #,(:: dc<%> set-brush) "WHITE" 'solid)
|
||||
(send dc #,(:: dc<%> draw-path) lambda-path)
|
||||
;; Paint outline and colors...
|
||||
(send dc #,(:: dc<%> set-pen) "BLACK" 0 'solid)
|
||||
;; Draw red regions
|
||||
(send dc #,(:: dc<%> set-brush) "RED" 'solid)
|
||||
(send dc #,(:: dc<%> draw-path) left-logo-path)
|
||||
(send dc #,(:: dc<%> draw-path) bottom-logo-path)
|
||||
;; Draw blue region
|
||||
(send dc #,(:: dc<%> set-brush) "BLUE" 'solid)
|
||||
(send dc #,(:: dc<%> draw-path) right-logo-path))
|
||||
|
||||
;; Create a frame to display the logo on a light-purple background:
|
||||
(define f (new frame% [label "PLT Logo"]))
|
||||
(define c
|
||||
(new canvas%
|
||||
[parent f]
|
||||
[paint-callback
|
||||
(lambda (c dc)
|
||||
(send dc #,(:: dc<%> set-background) (make-object color\% 220 200 255))
|
||||
(send dc #,(:: dc<%> clear))
|
||||
(send dc #,(:: dc<%> set-smoothing) 'smoothed)
|
||||
(send dc #,(:: dc<%> set-origin) 5 5)
|
||||
(send dc #,(:: dc<%> set-scale) 0.5 0.5)
|
||||
(paint-plt dc))]))
|
||||
(send c canvas::min-client-width (/ 650 2))
|
||||
(send c canvas::min-client-height (/ 650 2))
|
||||
(send f show #t)
|
||||
]]
|
||||
|
||||
Drawing effects are not completely portable across platforms or across
|
||||
types of DC. Drawing in smoothed mode tends to produce more reliable
|
||||
and portable results than in unsmoothed mode, and drawing with paths
|
||||
tends to produce more reliable results even in unsmoothed
|
||||
mode. Drawing with a pen of width 0 or 1 in unsmoothed mode in an
|
||||
unscaled DC produces relatively consistent results for all platforms,
|
||||
but a pen width of 2 or drawing to a scaled DC looks significantly
|
||||
different in unsmoothed mode on different platforms and destinations.
|
9
collects/scribblings/gui/drawing.scrbl
Normal file
9
collects/scribblings/gui/drawing.scrbl
Normal file
|
@ -0,0 +1,9 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require["common.ss"]
|
||||
@require["diagrams.ss"]
|
||||
|
||||
@title[#:tag "mr:drawing" #:style 'toc]{Drawing Toolbox}
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@include-section["draw-overview.scrbl"]
|
|
@ -1,11 +1,7 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require["common.ss"]
|
||||
|
||||
@title{Eventspaces}
|
||||
|
||||
|
||||
|
||||
|
||||
@title[#:tag "mr:eventspace-funcs"]{Eventspaces}
|
||||
|
||||
@defproc[(make-eventspace)
|
||||
eventspace]{
|
||||
|
|
|
@ -10,8 +10,70 @@ This manual describes MrEd.
|
|||
|
||||
@table-of-contents[]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
|
||||
@section{GUI Toolbox Organization}
|
||||
|
||||
For documentation purposes, the MrEd toolbox is organized into three
|
||||
parts:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{The @deftech{windowing} toolbox, for implementing form-filling
|
||||
GUI programs (such as a database query window) using buttons, menus,
|
||||
text fields, and events. The windowing toolbox is documented in
|
||||
@secref["mr:windowing"].}
|
||||
|
||||
@item{The @deftech{drawing} toolbox, for drawing pictures or
|
||||
implementing dynamic GUI programs (such as a video game) using
|
||||
drawing canvases, pens, and brushes. The drawing toolbox is
|
||||
documented in @secref["mr:drawing"].}
|
||||
|
||||
@item{The @deftech{editor} toolbox, for developing traditional text
|
||||
editors, editors that mix text and graphics, or free-form layout
|
||||
editors (such as a word processor, HTML editor, or icon-based file
|
||||
browser). The editor toolbox is documented in @secref["mr:editor"].}
|
||||
|
||||
}
|
||||
|
||||
These three parts roughly represent layers of increasing
|
||||
sophistication. Simple GUI programs access only the windowing toolbox
|
||||
directly, more complex programs use both the windowing and drawing
|
||||
toolboxes, and large-scale applications rely on all three
|
||||
toolboxes. This three-layer view of the toolbox breaks down under
|
||||
close scrutiny, because the windowing, drawing, and editor toolboxes
|
||||
are actually interdependent and intertwined. Nevertheless, the
|
||||
layered separation is a good approximation.
|
||||
|
||||
All three parts are immediately available when MrEd is started, as
|
||||
well as the base class system from MzLib. The @indexed-file{mred.ss}
|
||||
library module of the @file{mred} collection provides all of the
|
||||
class, interface, and procedure names defined in this manual. When
|
||||
MrEd starts up, it imports the @file{mred.ss} module and MzLib's
|
||||
@indexed-file{class.ss} module into the initial namespace (so no
|
||||
knowledge about modules is required to understand this manual).
|
||||
|
||||
The module @indexed-scheme[#%mred-kernel] is built into the MrEd
|
||||
executable, and intended for use only by @file{mred.ss}. Attempting
|
||||
to require @file{mred.ss} in a plain MzScheme executable will result
|
||||
in a run-time error, because @scheme[#%mred-kernel] will not be
|
||||
available.
|
||||
|
||||
To create a namespace in which the @file{mred.ss} module will be used,
|
||||
call the @scheme[make-namespace-with-mred] procedure. That
|
||||
procedure attaches the @file{mred.ss} instance of the current
|
||||
namespace to the created namespace. Otherwise, different namespaces
|
||||
create different instances of the @file{mred.ss} module, which in
|
||||
turn generate distinct classes.
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
|
||||
@include-section["windowing.scrbl"]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
|
||||
@include-section["drawing.scrbl"]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
|
||||
@index-section["mred-index"]
|
||||
|
|
|
@ -3,32 +3,30 @@
|
|||
|
||||
@defclass[popup-menu% object% (menu-item-container<%>)]{
|
||||
|
||||
A @scheme[popup-menu%] object is created without a
|
||||
parent. Dynamically display a @scheme[popup-menu%] with
|
||||
,
|
||||
@xmethod[window<%> popup-menu], or
|
||||
@xmethod[editor-admin% popup-menu].
|
||||
A @scheme[popup-menu%] object is created without a parent. Dynamically
|
||||
display a @scheme[popup-menu%] with @xmethod[window<%> popup-menu]
|
||||
or @xmethod[editor-admin% popup-menu].
|
||||
|
||||
A popup menu is {\em not} a control. A @scheme[choice%] control,
|
||||
however, displays a single value that the user selects from a popup
|
||||
A popup menu is @italic{not} a control. A @scheme[choice%] control,
|
||||
however, displays a single value that the user selects from a popup
|
||||
menu. A @scheme[choice%] control's popup menu is built into the
|
||||
control, and it is not accessible to the programmer.
|
||||
|
||||
|
||||
@defconstructor[([title (or/c label-string? false/c) #f]
|
||||
[popdown-callback ((is-a?/c popup-menu%) (is-a?/c control-event%)
|
||||
. -> . any)
|
||||
(lambda (p e) (void))]
|
||||
[demand-callback ((is-a?/c popup-menu%) . -> . any)
|
||||
(lambda (p) (void))]
|
||||
[font (is-a?/c font%) normal-control-font])]{
|
||||
|
||||
If @scheme[title] is not @scheme[#f], it is used as a displayed title
|
||||
at the top of the popup menu.
|
||||
|
||||
@defconstructor[[title (or/c label-string? false/c) #f]
|
||||
[popdown-callback procedure of two arguments: a @scheme[popup-menu%] object and a @scheme[control-event%] object @scheme[(\scmk{lambda] (@scheme[m] @scheme[e]) (void))}]
|
||||
[demand-callback procedure of one argument: a @scheme[popup-menu%] object @scheme[void]]
|
||||
[font (is-a?/c font%) @scheme[normal-control-font]]]{
|
||||
|
||||
If @scheme[title] is not @scheme[#f], it is used as a displayed title at
|
||||
the top of the popup menu.
|
||||
|
||||
If @scheme[title] contains an ampersand (``\&''), it is handled
|
||||
specially, the same as for @scheme[menu%] titles. A popup menu
|
||||
mnemonic is not useful, but it is supported for consistency with
|
||||
other menu labels.
|
||||
If @scheme[title] contains @litchar{&}, it is handled specially, the
|
||||
same as for @scheme[menu%] titles. A popup menu mnemonic is not
|
||||
useful, but it is supported for consistency with other menu labels.
|
||||
|
||||
The @scheme[popdown-callback] procedure is invoked when a popup menu is
|
||||
dismissed. If the popup menu is dismissed without an item being
|
||||
|
@ -44,44 +42,36 @@ The @scheme[demand-callback] procedure is called by the default
|
|||
|
||||
The @scheme[font] argument determines the font for the popup menu's
|
||||
items.
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@defmethod[(get-popup-target)
|
||||
(or/c (or/c (is-a?/c window<%>) (is-a?/c editor<%>)) false/c)]{
|
||||
@spec{
|
||||
|
||||
Returns the context in which the popup menu is currently displayed, or
|
||||
@scheme[#f] if it is not popped up in any window.
|
||||
|
||||
The context is set before the
|
||||
@method[menu-item-container<%> on-demand] method is called, and it is not removed until after the popup-menu's
|
||||
callback is invoked. (Consequently, it is also set while an item
|
||||
callback is invoked, if the user selected an item.)
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(get-font)
|
||||
(is-a?/c font%)]{
|
||||
@spec{
|
||||
|
||||
Returns the font used for the popup menu's items, which is optionally
|
||||
supplied when a popup menu is created.
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
@defmethod[(get-popup-target)
|
||||
(or/c (is-a?/c window<%>) (is-a?/c editor<%>) false/c)]{
|
||||
|
||||
Returns the context in which the popup menu is currently displayed, or
|
||||
@scheme[#f] if it is not popped up in any window.
|
||||
|
||||
The context is set before the @method[menu-item-container<%>
|
||||
on-demand] method is called, and it is not removed until after the
|
||||
popup-menu's callback is invoked. (Consequently, it is also set while
|
||||
an item callback is invoked, if the user selected an item.)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@defmethod[(set-min-width [width (integer-in 0 10000)])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Sets the popup menu's minimum width in pixels.
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
|
||||
|
||||
}}}
|
||||
}}
|
||||
|
||||
|
|
|
@ -17,20 +17,26 @@ Whenever the user changes the selected radio button, the radio box's
|
|||
|
||||
|
||||
|
||||
@defconstructor[[label (or/c label-string? false/c)]
|
||||
[choices list of {\labelstrings} or @scheme[bitmap%] objects]
|
||||
[parent (or/c (is-a?/c frame%) (is-a?/c dialog%) (is-a?/c panel%) (is-a?/c pane%))]
|
||||
[callback procedure of two arguments: a @scheme[radio-box%] object and a @scheme[control-event%] object @scheme[(\scmk{lambda] (@scheme[rb] @scheme[e]) (void))}]
|
||||
[style (symbols/c deleted horizontal-label vertical-label vertical horizontal) '(vertical)]
|
||||
[selection nonnegative-exact-integer? 0]
|
||||
[font (is-a?/c font%) @scheme[normal-control-font]]
|
||||
[enabled any/c #t]
|
||||
[vert-margin (integer-in 0 1000) 2]
|
||||
[horiz-margin (integer-in 0 1000) 2]
|
||||
[min-width (integer-in 0 10000) {\rm graphical minimum width}]
|
||||
[min-height (integer-in 0 10000) {\rm graphical minimum height}]
|
||||
[stretchable-width any/c #f]
|
||||
[stretchable-height any/c #f]]{
|
||||
@defconstructor[([label (or/c label-string? false/c)]
|
||||
[choices (or/c (listof label-string?) (listof (is-a?/c bitmap%)))]
|
||||
[parent (or/c (is-a?/c frame%) (is-a?/c dialog%)
|
||||
(is-a?/c panel%) (is-a?/c pane%))]
|
||||
[callback ((is-a?/c radio-box%) (is-a?/c control-event%)
|
||||
. -> . any)
|
||||
(lambda (r e) (void))]
|
||||
[style (listof (one-of/c 'horizontal 'vertical
|
||||
'vertical-label 'horizontal-label
|
||||
'deleted))
|
||||
'(vertical)]
|
||||
[selection nonnegative-exact-integer? 0]
|
||||
[font (is-a?/c font%) normal-control-font]
|
||||
[enabled any/c #t]
|
||||
[vert-margin (integer-in 0 1000) 2]
|
||||
[horiz-margin (integer-in 0 1000) 2]
|
||||
[min-width (integer-in 0 10000) _graphical-minimum-width]
|
||||
[min-height (integer-in 0 10000) _graphical-minimum-height]
|
||||
[stretchable-width any/c #f]
|
||||
[stretchable-height any/c #f])]{
|
||||
|
||||
Creates a radio button set with string or bitmap labels. The
|
||||
@scheme[choices] list specifies the radio button labels; the list of
|
||||
|
@ -38,10 +44,9 @@ Creates a radio button set with string or bitmap labels. The
|
|||
|
||||
@labelstripped[(scheme label) @elem{} @elem{move the keyboard focus to the radio box}]
|
||||
|
||||
Each string in @scheme[choices] can also contain an ampersand, which
|
||||
Each string in @scheme[choices] can also contain a @litchar{&}, which
|
||||
creates a mnemonic for clicking the corresponding radio button. As
|
||||
for @scheme[label], a double ampersand is converted to a single
|
||||
ampersand.
|
||||
for @scheme[label], a @litchar{&&} is converted to a @litchar{&}.
|
||||
|
||||
@bitmaplabelusearray[choices]
|
||||
|
||||
|
@ -56,141 +61,93 @@ The @scheme[callback] procedure is called (with the event type
|
|||
The @scheme[style] argument must include either @scheme['vertical] for a
|
||||
collection of radio buttons vertically arranged, or
|
||||
@scheme['horizontal] for a horizontal arrangement.
|
||||
\HVLabelNote{radio box} \DeletedStyleNote{radio box}
|
||||
@HVLabelNote{radio box} @DeletedStyleNote{radio box}
|
||||
|
||||
By default, the first radio button is initially selected. If
|
||||
@scheme[selection] is positive, it is passed to
|
||||
@method[radio-box% set-selection] to set the initial radio button selection.
|
||||
@scheme[selection] is positive, it is passed to @method[radio-box%
|
||||
set-selection] to set the initial radio button selection.
|
||||
|
||||
@FontKWs[] @WindowKWs[] @SubareaKWs[] @AreaKWs[]
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@defmethod*[#:mode 'override
|
||||
([(enable [enable? any/c])
|
||||
void?]
|
||||
[(enable [n nonnegative-exact-integer?]
|
||||
[enable? any/c])
|
||||
void?])]{
|
||||
@impl{
|
||||
First case:
|
||||
|
||||
If a single argument is provided, the entire radio box is enabled or disabled.
|
||||
|
||||
If two arguments are provided, then if @scheme[enable?] is
|
||||
@scheme[#f], the @scheme[n]th radio button is disabled, otherwise it
|
||||
is enabled (assuming the entire radio box is enabled). Radio buttons
|
||||
are numbered from @scheme[0]. If @scheme[n] is equal to or larger
|
||||
than the number of radio buttons in the radio box, @|MismatchExn|.
|
||||
|
||||
}
|
||||
|
||||
|
||||
If @scheme[enable?] is @scheme[#f], the entire radio box is disabled,
|
||||
otherwise it is enabled.
|
||||
@defmethod[(get-item-label [n nonnegative-exact-integer?])
|
||||
string?]{
|
||||
|
||||
Gets the label of a radio button by position. Radio buttons are
|
||||
numbered from @scheme[0]. If @scheme[n] is equal to or larger than
|
||||
the number of radio buttons in the radio box, @|MismatchExn|.
|
||||
|
||||
}
|
||||
|
||||
Second case:
|
||||
@defmethod[(get-item-plain-label [n nonnegative-exact-integer?])
|
||||
string?]{
|
||||
|
||||
Like @method[radio-box% get-item-label], except that the label must be
|
||||
a string and @litchar{&}s in the label are removed.
|
||||
|
||||
If @scheme[enable?] is @scheme[#f], the @scheme[n]th radio button is disabled,
|
||||
otherwise it is enabled (assuming the entire radio box is
|
||||
enabled). Radio buttons are numbered from @scheme[0].
|
||||
If @scheme[n] is equal to or larger than the number of radio buttons in
|
||||
the radio box, @|MismatchExn|}.
|
||||
}
|
||||
|
||||
@defmethod[(get-number)
|
||||
nonnegative-exact-integer?]{
|
||||
|
||||
Returns the number of radio buttons in the radio box.
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
@defmethod[(get-selection)
|
||||
nonnegative-exact-integer?]{
|
||||
|
||||
Gets the position of the selected radio button. Radio buttons are
|
||||
numbered from @scheme[0].
|
||||
|
||||
}
|
||||
|
||||
@defmethod*[#:mode 'override
|
||||
([(is-enabled?)
|
||||
boolean?]
|
||||
[(is-enabled? [n nonnegative-exact-integer?])
|
||||
boolean?])]{
|
||||
@impl{
|
||||
First case:
|
||||
|
||||
If no arguments are provided, the enable state of the entire radio box
|
||||
is reported.
|
||||
|
||||
Returns @scheme[#f] if the entire radio box is disabled,
|
||||
@scheme[#t] otherwise.
|
||||
Otherwise, returns @scheme[#f] if @scheme[n]th radio button is
|
||||
disabled (independent of disabling the entire radio box), @scheme[#t]
|
||||
otherwise. Radio buttons are numbered from @scheme[0]. If @scheme[n]
|
||||
is equal to or larger than the number of radio buttons in the radio
|
||||
box, @|MismatchExn|.
|
||||
|
||||
|
||||
|
||||
Second case:
|
||||
|
||||
|
||||
Returns @scheme[#f] if @scheme[n]th radio button is disabled (independent of
|
||||
disabling the entire radio box), @scheme[#t] otherwise. Radio buttons
|
||||
are numbered from @scheme[0]. If @scheme[n] is equal to or larger than the
|
||||
number of radio buttons in the radio box, @|MismatchExn|}.
|
||||
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(get-selection)
|
||||
nonnegative-exact-integer?]{
|
||||
@spec{
|
||||
|
||||
Gets the position of the selected radio button. Radio buttons are
|
||||
numbered from @scheme[0].
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(get-number)
|
||||
nonnegative-exact-integer?]{
|
||||
@spec{
|
||||
|
||||
Returns the number of radio buttons in the radio box.
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
@defmethod[(set-selection [n nonnegative-exact-integer?])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Sets the selected radio button by position. (The control's callback
|
||||
procedure is {\em not} invoked.) Radio buttons are numbered from
|
||||
@scheme[0].
|
||||
@scheme[0]. If @scheme[n] is equal to or larger than the number of
|
||||
radio buttons in the radio box, @|MismatchExn|.
|
||||
|
||||
@MonitorCallback[@elem{A radio box's selection} @elem{the user clicking the control} @elem{selection}]
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
If @scheme[n] is equal to or larger than the number of radio buttons in
|
||||
the radio box, @|MismatchExn|}.
|
||||
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(get-item-label [n nonnegative-exact-integer?])
|
||||
string]{
|
||||
@spec{
|
||||
|
||||
Gets the label of a radio button by position. Radio buttons are
|
||||
numbered from @scheme[0].
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
If @scheme[n] is equal to or larger than the number of radio buttons in
|
||||
the radio box, @|MismatchExn|}.
|
||||
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(get-item-plain-label [n nonnegative-exact-integer?])
|
||||
string]{
|
||||
@spec{
|
||||
|
||||
Like
|
||||
@method[radio-box% get-item-label], except that the label must be a string and ampersands in the label
|
||||
are removed.
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
If @scheme[n] is equal to or larger than the number of radio buttons in
|
||||
the radio box, @|MismatchExn|}.
|
||||
|
||||
|
||||
|
||||
}}}
|
||||
|
||||
|
|
|
@ -13,24 +13,34 @@ See
|
|||
|
||||
|
||||
|
||||
@defconstructor[[event-type (symbols/c thumb page-down page-up line-down line-up bottom top) 'thumb]
|
||||
[direction (symbols/c vertical horizontal) 'vertical]
|
||||
[position (integer-in 0 10000) 0]
|
||||
[time-stamp (and/c exact? integer?) 0]]{
|
||||
@defconstructor[([event-type (one-of/c 'top 'bottom 'line-up 'line-down
|
||||
'page-up 'page-down 'thumb)
|
||||
'thumb]
|
||||
[direction (one-of/c 'horizontal 'vertical) 'vertical]
|
||||
[position (integer-in 0 10000) 0]
|
||||
[time-stamp (and/c exact? integer?) 0])]{
|
||||
|
||||
See the corresponding @scheme[get-] and @scheme[set-] methods for
|
||||
information about @scheme[event-type], @scheme[direction], @scheme[position],
|
||||
and @scheme[time-stamp].
|
||||
|
||||
}
|
||||
|
||||
@defmethod[(get-direction)
|
||||
(one-of/c 'horizontal 'vertical)]{
|
||||
|
||||
Gets the identity of the scrollbar that was modified by the event,
|
||||
either the horizontal scrollbar or the vertical scrollbar, as
|
||||
@scheme['horizontal] or @scheme['vertical], respectively. See also
|
||||
@method[scroll-event% set-direction].
|
||||
|
||||
}
|
||||
|
||||
@defmethod[(get-event-type)
|
||||
(symbols/c thumb page-down page-up line-down line-up bottom top)]{
|
||||
@spec{
|
||||
(one-of/c 'top 'bottom 'line-up 'line-down 'page-up 'page-down 'thumb)]{
|
||||
|
||||
Returns the type of the event, one of the following:
|
||||
|
||||
@itemize{
|
||||
@item{@scheme['top] --- user clicked a scroll-to-top button}
|
||||
@item{@scheme['bottom] --- user clicked a scroll-to-bottom button}
|
||||
|
@ -41,64 +51,41 @@ Returns the type of the event, one of the following:
|
|||
@item{@scheme['thumb] --- user dragged the scroll position indicator}
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(set-event-type [type (symbols/c thumb page-down page-up line-down line-up bottom top)])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Sets the type of the event. See
|
||||
@method[scroll-event% get-event-type] for information about each event type.
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
@defmethod[(get-position)
|
||||
(integer-in 0 10000)]{
|
||||
@spec{
|
||||
|
||||
Returns the position of the scrollbar after the action triggering the
|
||||
event. See also
|
||||
@method[scroll-event% set-position].
|
||||
event. See also @method[scroll-event% set-position].
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
@defmethod[(set-position [position (integer-in 0 10000)])
|
||||
@defmethod[(set-direction [direction (one-of/c 'horizontal 'vertical)])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Records the position of the scrollbar after the action triggering the
|
||||
event. (The scrollbar itself is unaffected). See also
|
||||
@method[scroll-event% get-position].
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(get-direction)
|
||||
(symbols/c vertical horizontal)]{
|
||||
@spec{
|
||||
|
||||
Gets the identity of the scrollbar that was modified by the event,
|
||||
either the horizontal scrollbar or the vertical scrollbar, as
|
||||
@scheme['horizontal] or @scheme['vertical], respectively. See
|
||||
also
|
||||
@method[scroll-event% set-direction].
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(set-direction [direction (symbols/c vertical horizontal)])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Sets the identity of the scrollbar that was modified by the event,
|
||||
either the horizontal scrollbar or the vertical scrollbar, as
|
||||
@scheme['horizontal] or @scheme['vertical], respectively. See
|
||||
also
|
||||
@method[scroll-event% get-direction].
|
||||
@scheme['horizontal] or @scheme['vertical], respectively. See also
|
||||
@method[scroll-event% get-direction].
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
@defmethod[(set-event-type [type (one-of/c 'top 'bottom 'line-up 'line-down
|
||||
'page-up 'page-down 'thumb)])
|
||||
void?]{
|
||||
|
||||
Sets the type of the event. See @method[scroll-event% get-event-type]
|
||||
for information about each event type.
|
||||
|
||||
}
|
||||
|
||||
}}}
|
||||
@defmethod[(set-position [position (integer-in 0 10000)])
|
||||
void?]{
|
||||
|
||||
Records the position of the scrollbar after the action triggering the
|
||||
event. (The scrollbar itself is unaffected). See also
|
||||
@method[scroll-event% get-position].
|
||||
|
||||
}}
|
||||
|
||||
|
|
|
@ -6,50 +6,45 @@
|
|||
A @scheme[selectable-menu-item<%>] object is a
|
||||
@scheme[labelled-menu-item<%>] that the user can select. It may also
|
||||
have a keyboard shortcut; the shortcut is displayed in the menu, and
|
||||
the default
|
||||
@method[frame% on-subwindow-char] method in the menu's frame dispatches to the menu item when the
|
||||
shortcut key combination is pressed.
|
||||
the default @method[frame% on-subwindow-char] method in the menu's
|
||||
frame dispatches to the menu item when the shortcut key combination
|
||||
is pressed.
|
||||
|
||||
|
||||
@defmethod[(command [event (is-a?/c control-event%)])
|
||||
void?]{
|
||||
|
||||
Invoke's the menu item's callback procedure, which is supplied when an
|
||||
instance of
|
||||
@scheme[menu-item%] or
|
||||
@scheme[checkable-menu-item%] is created.
|
||||
|
||||
}
|
||||
|
||||
@defmethod[(get-shortcut)
|
||||
character, symbol, @scheme[#f]]{
|
||||
@spec{
|
||||
(or/c char? symbol? false/c)]{
|
||||
|
||||
Gets the keyboard shortcut character or virtual key for the menu
|
||||
item. This character or key is combined with the shortcut prefix,
|
||||
which is reported by
|
||||
@method[selectable-menu-item<%> get-shortcut-prefix].
|
||||
which is reported by @method[selectable-menu-item<%>
|
||||
get-shortcut-prefix].
|
||||
|
||||
If the menu item has no shortcut, @scheme[#f] is returned.
|
||||
|
||||
The shortcut part of a menu item name is not included in the label
|
||||
returned by
|
||||
@method[labelled-menu-item<%> get-label].
|
||||
returned by @method[labelled-menu-item<%> get-label].
|
||||
|
||||
For a list of allowed key symbols, see
|
||||
@xmethod[key-event% get-key-code] .
|
||||
For a list of allowed key symbols, see @xmethod[key-event%
|
||||
get-key-code].
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(set-shortcut [shortcut (or/c character, symbol, false/c)])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Sets the keyboard shortcut character for the menu item. See
|
||||
@method[selectable-menu-item<%> get-shortcut] for more information.
|
||||
|
||||
If the shortcut character is set to @scheme[#f], then menu item has no
|
||||
keyboard shortcut.
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
@defmethod[(get-shortcut-prefix)
|
||||
(symbols/c option shift ctl meta cmd alt)]{
|
||||
@spec{
|
||||
(listof (one-of/c 'alt 'cmd 'meta 'ctl 'shift 'option))]{
|
||||
|
||||
Returns a list of symbols that indicates the keyboard prefix used for the menu
|
||||
item's keyboard shortcut. The allowed symbols for the list are the following:
|
||||
|
||||
@itemize{
|
||||
@item{@scheme['alt] --- Meta (Windows and X only)}
|
||||
@item{@scheme['cmd] --- Command (Mac OS X only)}
|
||||
|
@ -58,59 +53,57 @@ Returns a list of symbols that indicates the keyboard prefix used for the menu
|
|||
@item{@scheme['shift] --- Shift}
|
||||
@item{@scheme['opt] --- Option (Mac OS X only)}
|
||||
}
|
||||
|
||||
Under X, at most one of @scheme['alt] and @scheme['meta] can be
|
||||
supplied; the only difference between @scheme['alt] and @scheme['meta]
|
||||
is the key combination's display in a menu.
|
||||
supplied; the only difference between @scheme['alt] and
|
||||
@scheme['meta] is the key combination's display in a menu.
|
||||
|
||||
The default shortcut prefix is available from
|
||||
@scheme[get-default-shortcut-prefix] .
|
||||
@scheme[get-default-shortcut-prefix].
|
||||
|
||||
The shortcut key, as determined by
|
||||
@method[selectable-menu-item<%> get-shortcut], matches a key event using either the normally reported key code or
|
||||
the other-Shift/AltGr key code (as produced by
|
||||
@xmethod[key-event% get-other-shift-key-code], etc.). When the shortcut key is a key-code symbol or an ASCII letter or
|
||||
digit, then the shortcut matches only the exact combination of
|
||||
modifier keys listed in the prefix. For character shortcuts other than
|
||||
ASCII letters and digits, however, then the shortcut prefix merely
|
||||
determines a minimum set of modifier keys, because additional
|
||||
modifiers may be needed to access the character; an exception is that,
|
||||
under Windows or X, the Alt/Meta key press must match the prefix
|
||||
exactly (i.e., included or not). In all
|
||||
cases, the most precise match takes precedence; see
|
||||
@xmethod[keymap% map-function] for more information on match ranking.
|
||||
The shortcut key, as determined by @method[selectable-menu-item<%>
|
||||
get-shortcut], matches a key event using either the normally reported
|
||||
key code or the other-Shift/AltGr key code (as produced by
|
||||
@xmethod[key-event% get-other-shift-key-code], etc.). When the
|
||||
shortcut key is a key-code symbol or an ASCII letter or digit, then
|
||||
the shortcut matches only the exact combination of modifier keys
|
||||
listed in the prefix. For character shortcuts other than ASCII
|
||||
letters and digits, however, then the shortcut prefix merely
|
||||
determines a minimum set of modifier keys, because additional
|
||||
modifiers may be needed to access the character; an exception is
|
||||
that, under Windows or X, the Alt/Meta key press must match the
|
||||
prefix exactly (i.e., included or not). In all cases, the most
|
||||
precise match takes precedence; see @xmethod[keymap% map-function]
|
||||
for more information on match ranking.
|
||||
|
||||
An empty list can be used for a shortcut prefix. However, the default
|
||||
@xmethod[frame% on-menu-char] method checks for menu shortcuts only when the key event includes
|
||||
either a non-Shift modifer or a Function key. Thus, an empty shortcut
|
||||
prefix is normally useful only if the shortcut key is a Function key.
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(set-shortcut-prefix [prefix (symbols/c option shift ctl meta cmd alt)])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Sets a list of symbols to indicates the keyboard prefix used for the menu
|
||||
item's keyboard shortcut.
|
||||
|
||||
See
|
||||
@method[selectable-menu-item<%> get-shortcut-prefix] for more information.
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(command [event (is-a?/c control-event%)])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Invoke's the menu item's callback procedure, which is supplied when an
|
||||
instance of
|
||||
@scheme[menu-item%] or
|
||||
@scheme[checkable-menu-item%] is created.
|
||||
@xmethod[frame% on-menu-char] method checks for menu shortcuts only
|
||||
when the key event includes either a non-Shift modifer or a Function
|
||||
key. Thus, an empty shortcut prefix is normally useful only if the
|
||||
shortcut key is a Function key.
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
|
||||
@defmethod[(set-shortcut [shortcut (or/c char? symbol? false/c)])
|
||||
void?]{
|
||||
|
||||
}}}
|
||||
Sets the keyboard shortcut character for the menu item. See
|
||||
@method[selectable-menu-item<%> get-shortcut] for more information.
|
||||
|
||||
If the shortcut character is set to @scheme[#f], then menu item has no
|
||||
keyboard shortcut.
|
||||
|
||||
}
|
||||
|
||||
@defmethod[(set-shortcut-prefix [prefix (listof (one-of/c 'alt 'cmd 'meta 'ctl 'shift 'option))])
|
||||
void?]{
|
||||
|
||||
Sets a list of symbols to indicates the keyboard prefix used for the
|
||||
menu item's keyboard shortcut.
|
||||
|
||||
See @method[selectable-menu-item<%> get-shortcut-prefix] for more
|
||||
information.
|
||||
|
||||
}}
|
||||
|
||||
|
|
|
@ -7,13 +7,9 @@ A separator is an unselectable line in a menu. Its parent must be a
|
|||
@scheme[menu%] or @scheme[popup-menu%].
|
||||
|
||||
|
||||
|
||||
|
||||
@defconstructor[[parent @scheme[menu%] or @scheme[popup-menu%] object]]{
|
||||
@defconstructor[([parent (or/c (is-a?/c menu%) (is-a?/c popup-menu%))])]{
|
||||
|
||||
Creates a new separator in the menu.
|
||||
|
||||
|
||||
|
||||
}}
|
||||
|
||||
|
|
|
@ -14,74 +14,66 @@ Whenever the user changes the value of a slider, its callback
|
|||
|
||||
|
||||
|
||||
@defconstructor[[label (or/c label-string? false/c)]
|
||||
[min-value (integer-in -10000 10000)]
|
||||
[max-value (integer-in -10000 10000)]
|
||||
[parent (or/c (is-a?/c frame%) (is-a?/c dialog%) (is-a?/c panel%) (is-a?/c pane%))]
|
||||
[callback procedure of two arguments: a @scheme[slider%] object and a @scheme[control-event%] object @scheme[(\scmk{lambda] (@scheme[s] @scheme[e]) (void))}]
|
||||
[init-value (integer-in -10000 10000) @scheme[min-value]]
|
||||
[style (symbols/c deleted horizontal-label vertical-label plain vertical horizontal) '(horizontal)]
|
||||
[font (is-a?/c font%) @scheme[normal-control-font]]
|
||||
[enabled any/c #t]
|
||||
[vert-margin (integer-in 0 1000) 2]
|
||||
[horiz-margin (integer-in 0 1000) 2]
|
||||
[min-width (integer-in 0 10000) {\rm graphical minimum width}]
|
||||
[min-height (integer-in 0 10000) {\rm graphical minimum height}]
|
||||
[stretchable-width any/c \#t {\rm for} @scheme['horizontal] {\rm style}, \#f {\rm for} @scheme['vertical]]
|
||||
[stretchable-height any/c \#t {\rm for} @scheme['vertical] {\rm style}, \#f {\rm for} @scheme['horizontal]]]{
|
||||
@defconstructor[([label (or/c label-string? false/c)]
|
||||
[min-value (integer-in -10000 10000)]
|
||||
[max-value (integer-in -10000 10000)]
|
||||
[parent (or/c (is-a?/c frame%) (is-a?/c dialog%)
|
||||
(is-a?/c panel%) (is-a?/c pane%))]
|
||||
[callback ((is-a?/c slider%) (is-a?/c control-event%) . -> . any) (lambda (b e) (void))]
|
||||
[init-value (integer-in -10000 10000) min-value]
|
||||
[style (listof (one-of/c 'horizontal 'vertical 'plain
|
||||
'vertical-label 'horizontal-label
|
||||
'deleted))
|
||||
'(horizontal)]
|
||||
[font (is-a?/c font%) normal-control-font]
|
||||
[enabled any/c #t]
|
||||
[vert-margin (integer-in 0 1000) 2]
|
||||
[horiz-margin (integer-in 0 1000) 2]
|
||||
[min-width (integer-in 0 10000) _graphical-minimum-width]
|
||||
[min-height (integer-in 0 10000) _graphical-minimum-height]
|
||||
[stretchable-width any/c (memq 'horizontal style)]
|
||||
[stretchable-height any/c (memq 'vertical style)])]{
|
||||
|
||||
If @scheme[label] is a string, it is used as the label for the slider.
|
||||
Otherwise, the slider does not display its
|
||||
label.
|
||||
Otherwise, the slider does not display its label.
|
||||
|
||||
@labelstripped[(scheme label) @elem{} @elem{move the keyboard focus to the slider}]
|
||||
|
||||
The @scheme[min-value] and @scheme[max-value] arguments specify the range of
|
||||
the slider, inclusive. The @scheme[init-value] argument optionally
|
||||
specifies the slider's initial value. If the sequence
|
||||
[@scheme[min-value], @scheme[initial-value], @scheme[maximum-value]] is not
|
||||
increasing, @|MismatchExn|}.
|
||||
The @scheme[min-value] and @scheme[max-value] arguments specify the
|
||||
range of the slider, inclusive. The @scheme[init-value] argument
|
||||
optionally specifies the slider's initial value. If the sequence
|
||||
[@scheme[min-value], @scheme[initial-value], @scheme[maximum-value]]
|
||||
is not increasing, @|MismatchExn|.
|
||||
|
||||
The @scheme[callback] procedure is called (with the event type
|
||||
@indexed-scheme['slider]) when the user changes the slider's value.
|
||||
|
||||
The @scheme[style] argument must include either @scheme['vertical] for a
|
||||
vertical slider, or @scheme['horizontal] for a horizontal slider. If
|
||||
@scheme[style] includes @scheme['plain], the slider does not display
|
||||
numbers for its range and current value to the user.
|
||||
\HVLabelNote{slider} \DeletedStyleNote{slider}
|
||||
The @scheme[style] argument must include either @scheme['vertical] for
|
||||
a vertical slider, or @scheme['horizontal] for a horizontal
|
||||
slider. If @scheme[style] includes @scheme['plain], the slider does
|
||||
not display numbers for its range and current value to the user.
|
||||
@HVLabelNote{slider} @DeletedStyleNote{slider}
|
||||
|
||||
@FontKWs[] @WindowKWs[] @SubareaKWs[] @AreaKWs[]
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@defmethod[(get-value)
|
||||
(integer-in -10000 10000)]{
|
||||
@spec{
|
||||
|
||||
Gets the current slider value.
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
@defmethod[(set-value [value (integer-in -10000 10000)])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Sets the value (and displayed position) of the slider. (The control's
|
||||
callback procedure is {\em not} invoked.)
|
||||
callback procedure is @italic{not} invoked.) If @scheme[value] is
|
||||
outside the slider's minimum and maximum range, @|MismatchExn|.
|
||||
|
||||
@MonitorCallback[@elem{A slider's value} @elem{the user clicking the control} @elem{value}]
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
If @scheme[value] is outside the slider's minimum and maximum range,
|
||||
@|MismatchExn|}.
|
||||
|
||||
|
||||
|
||||
|
||||
}}}
|
||||
}}
|
||||
|
||||
|
|
|
@ -15,24 +15,29 @@ The @scheme[tab-panel%] class does not implement the virtual
|
|||
|
||||
|
||||
|
||||
@defconstructor[[choices list of {\labelstrings}]
|
||||
[parent (or/c (is-a?/c frame%) (is-a?/c dialog%) (is-a?/c panel%) (is-a?/c pane%))]
|
||||
[callback procedure of two arguments: a @scheme[tab-panel%] object and a @scheme[control-event%] object @scheme[(\scmk{lambda] (@scheme[tp] @scheme[e]) (void))}]
|
||||
[style (symbols/c deleted no-border) null]
|
||||
[font (is-a?/c font%) @scheme[normal-control-font]]
|
||||
[enabled any/c #t]
|
||||
[vert-margin (integer-in 0 1000) 0]
|
||||
[horiz-margin (integer-in 0 1000) 0]
|
||||
[border (integer-in 0 1000) 0]
|
||||
[spacing (integer-in 0 1000) 0]
|
||||
[alignment two-element list: @scheme['left], @scheme['center], or @scheme['right] and @scheme['top], @scheme['center], or @scheme['bottom] '(center top)]
|
||||
[min-width (integer-in 0 10000) {\rm graphical minimum width}]
|
||||
[min-height (integer-in 0 10000) {\rm graphical minimum height}]
|
||||
[stretchable-width any/c #t]
|
||||
[stretchable-height any/c #t]]{
|
||||
@defconstructor[([choices (listof label-string?)]
|
||||
[parent (or/c (is-a?/c frame%) (is-a?/c dialog%)
|
||||
(is-a?/c panel%) (is-a?/c pane%))]
|
||||
[callback ((is-a?/c tab-panel%) (is-a?/c control-event%)
|
||||
. -> . any)
|
||||
(lambda (b e) (void))]
|
||||
[style (listof (one-of/c 'no-border 'deleted)) null]
|
||||
[font (is-a?/c font%) normal-control-font]
|
||||
[enabled any/c #t]
|
||||
[vert-margin (integer-in 0 1000) 0]
|
||||
[horiz-margin (integer-in 0 1000) 0]
|
||||
[border (integer-in 0 1000) 0]
|
||||
[spacing (integer-in 0 1000) 0]
|
||||
[alignment (list/c (one-of/c 'left 'center 'right)
|
||||
(one-of/c 'top 'center 'bottom))
|
||||
'(center top)]
|
||||
[min-width (integer-in 0 10000) _graphical-minimum-width]
|
||||
[min-height (integer-in 0 10000) _graphical-minimum-height]
|
||||
[stretchable-width any/c #t]
|
||||
[stretchable-height any/c #t])]{
|
||||
|
||||
Creates a tab pane, where the
|
||||
@scheme[choices] list specifies the tab labels.
|
||||
Creates a tab pane, where the @scheme[choices] list specifies the tab
|
||||
labels.
|
||||
|
||||
Each string in @scheme[choices] can contain an ampersand, which (in the
|
||||
future) may create a mnemonic for clicking the corresponding tab. A
|
||||
|
@ -42,7 +47,7 @@ The @scheme[callback] procedure is called (with the event type
|
|||
@indexed-scheme['tab-panel]) when the user changes the tab selection.
|
||||
|
||||
If the @scheme[style] list includes @scheme['no-border], no border is
|
||||
drawn around the panel content. \DeletedStyleNote{tab panel}
|
||||
drawn around the panel content. @DeletedStyleNote{tab panel}
|
||||
|
||||
@FontKWs[] @WindowKWs[] @SubareaKWs[] @AreaKWs[]
|
||||
|
||||
|
@ -52,115 +57,70 @@ If the @scheme[style] list includes @scheme['no-border], no border is
|
|||
|
||||
@defmethod[(append [choice label-string?])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Adds a tab to the right end of panel's top row of tabs.
|
||||
|
||||
The label string @scheme[choice] can contain @litchar{&}, which (in
|
||||
the future) may create a mnemonic for clicking the new tab. A
|
||||
@litchar{&&} is converted to @litchar{&}.
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
The label string @scheme[choice] can contain an ampersand, which (in the
|
||||
future) may create a mnemonic for clicking the new tab. A double
|
||||
ampersand is converted to a single ampersand.
|
||||
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(delete [n nonnegative-exact-integer?])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Deletes an existing tab.
|
||||
Deletes an existing tab. If @scheme[n] is equal to or larger than the
|
||||
number of tabs on the panel, @|MismatchExn|.
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
If @scheme[n] is equal to or larger than the number of tabs on the panel,
|
||||
@|MismatchExn|}.
|
||||
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(get-selection)
|
||||
(or/c nonnegative-exact-integer? false/c)]{
|
||||
@spec{
|
||||
|
||||
Returns the index (counting from 0) of the currently selected tab.
|
||||
If the panel has no tabs, the result is @scheme[#f].
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(set-selection [n nonnegative-exact-integer?])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Sets the currently selected tab by index (counting from 0).
|
||||
|
||||
}
|
||||
@impl{
|
||||
@defmethod[(get-item-label [n nonnegative-exact-integer?])
|
||||
string?]{
|
||||
|
||||
Gets the label of a tab by position. Tabs are numbered from @scheme[0].
|
||||
If @scheme[n] is equal to or larger than the number of tabs in the panel,
|
||||
@|MismatchExn|}.
|
||||
@|MismatchExn|.
|
||||
|
||||
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
@defmethod[(get-number)
|
||||
nonnegative-exact-integer?]{
|
||||
@spec{
|
||||
|
||||
Returns the number of tabs on the panel.
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
@defmethod[(get-item-label [n nonnegative-exact-integer?])
|
||||
string]{
|
||||
@spec{
|
||||
@defmethod[(get-selection)
|
||||
(or/c nonnegative-exact-integer? false/c)]{
|
||||
|
||||
Gets the label of a tab by position. Tabs are numbered from @scheme[0].
|
||||
Returns the index (counting from 0) of the currently selected tab. If
|
||||
the panel has no tabs, the result is @scheme[#f].
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
If @scheme[n] is equal to or larger than the number of tabs in the panel,
|
||||
@|MismatchExn|}.
|
||||
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(set-item-label [n nonnegative-exact-integer?]
|
||||
[label label-string?])
|
||||
string]{
|
||||
@spec{
|
||||
|
||||
Sets the label of a tab by position. Tabs are numbered from @scheme[0].
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
Set the label for tab @scheme[n] to @scheme[label]. If @scheme[n] is equal to
|
||||
or larger than the number of tabs in the panel, @|MismatchExn|}.
|
||||
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(set [choices list of {\labelstrings}])
|
||||
@defmethod[(set [choices (listof label-string?)])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Removes all tabs from the panel and installs tabs with the given
|
||||
labels.
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
@defmethod[(set-item-label [n nonnegative-exact-integer?]
|
||||
[label label-string?])
|
||||
string?]{
|
||||
|
||||
Set the label for tab @scheme[n] to @scheme[label]. If @scheme[n] is equal to
|
||||
or larger than the number of tabs in the panel, @|MismatchExn|.
|
||||
|
||||
}
|
||||
|
||||
}}}
|
||||
@defmethod[(set-selection [n nonnegative-exact-integer?])
|
||||
void?]{
|
||||
|
||||
Sets the currently selected tab by index (counting from 0).
|
||||
If @scheme[n] is equal to or larger than the number of tabs in the panel,
|
||||
@|MismatchExn|.
|
||||
|
||||
}}
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
A @scheme[text-field%] object is an editable text field with an
|
||||
optional label displayed in front of it. There are two text field
|
||||
styles:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{A single line of text is visible, and a special control event
|
||||
is generated when the user presses Enter (when the text field has the
|
||||
focus) and the event is not handled by the text field's frame or
|
||||
dialog (see
|
||||
@xmethod[top-level-window<%> on-traverse-char] ).}
|
||||
dialog (see @xmethod[top-level-window<%> on-traverse-char] ).}
|
||||
|
||||
@item{Multiple lines of text are visible, and Enter is not handled
|
||||
specially.}
|
||||
|
@ -25,93 +25,77 @@ Whenever the user changes the content of a text field, its callback
|
|||
|
||||
The text field is implemented using a @scheme[text%] editor (with an
|
||||
inaccessible display). Thus, whereas @scheme[text-field%] provides
|
||||
only
|
||||
@method[text-field% get-value] and
|
||||
@method[text-field% set-value] to manipulate the text in a text field, the
|
||||
@method[text-field% get-editor] returns the field's editor, which provides a vast collection of
|
||||
methods for more sophisticated operations on the text.
|
||||
only @method[text-field% get-value] and @method[text-field%
|
||||
set-value] to manipulate the text in a text field, the
|
||||
@method[text-field% get-editor] returns the field's editor, which
|
||||
provides a vast collection of methods for more sophisticated
|
||||
operations on the text.
|
||||
|
||||
The keymap for the text field's editor is initialized by calling the
|
||||
current keymap initializer procedure, which is determined by the
|
||||
@scheme[current-text-keymap-initializer] parameter.
|
||||
@scheme[current-text-keymap-initializer] parameter.
|
||||
|
||||
|
||||
@defconstructor[([label (or/c label-string? false/c)]
|
||||
[parent (or/c (is-a?/c frame%) (is-a?/c dialog%)
|
||||
(is-a?/c panel%) (is-a?/c pane%))]
|
||||
[callback ((is-a?/c text-field%) (is-a?/c control-event%)
|
||||
. -> . any)
|
||||
(lambda (t e) (void))]
|
||||
[init-value string? ""]
|
||||
[style (listof (one-of/c 'single 'multiple 'hscroll 'password
|
||||
'vertical-label 'horizontal-label
|
||||
'deleted))
|
||||
'(single)]
|
||||
[font (is-a?/c font%) @scheme[normal-control-font]]
|
||||
[enabled any/c #t]
|
||||
[vert-margin (integer-in 0 1000) 2]
|
||||
[horiz-margin (integer-in 0 1000) 2]
|
||||
[min-width (integer-in 0 10000) _graphical-minimum-width]
|
||||
[min-height (integer-in 0 10000) _graphical-minimum-height]
|
||||
[stretchable-width any/c #t]
|
||||
[stretchable-height any/c (memq 'multiple style)])]{
|
||||
|
||||
|
||||
@defconstructor[[label (or/c label-string? false/c)]
|
||||
[parent (or/c (is-a?/c frame%) (is-a?/c dialog%) (is-a?/c panel%) (is-a?/c pane%))]
|
||||
[callback procedure of two arguments: a @scheme[text-field%] object and a @scheme[control-event%] object @scheme[(\scmk{lambda] (@scheme[tf] @scheme[e]) (void))}]
|
||||
[init-value string ""]
|
||||
[style (symbols/c deleted horizontal-label vertical-label password hscroll multiple single) '(single)]
|
||||
[font (is-a?/c font%) @scheme[normal-control-font]]
|
||||
[enabled any/c #t]
|
||||
[vert-margin (integer-in 0 1000) 2]
|
||||
[horiz-margin (integer-in 0 1000) 2]
|
||||
[min-width (integer-in 0 10000) {\rm graphical minimum width}]
|
||||
[min-height (integer-in 0 10000) {\rm graphical minimum height}]
|
||||
[stretchable-width any/c #t]
|
||||
[stretchable-height any/c \#t {\rm for} @scheme['multiple] {\rm style}, \#f {\rm otherwise}]]{
|
||||
|
||||
If @scheme[label] is not @scheme[#f], it is used as the text field label.
|
||||
Otherwise, the text field does not display its
|
||||
label.
|
||||
If @scheme[label] is not @scheme[#f], it is used as the text field
|
||||
label. Otherwise, the text field does not display its label.
|
||||
|
||||
@labelstripped[(scheme label) @elem{} @elem{move the keyboard focus to the text field}]
|
||||
|
||||
The @scheme[callback] procedure is called when the user changes the text
|
||||
in the text field or presses the Enter key (and Enter is not handled by
|
||||
the text field's frame or dialog; see
|
||||
@xmethod[top-level-window<%> on-traverse-char] ). If the user presses Enter, the type of event passed to the callback
|
||||
is @indexed-scheme['text-field-enter], otherwise it is
|
||||
The @scheme[callback] procedure is called when the user changes the
|
||||
text in the text field or presses the Enter key (and Enter is not
|
||||
handled by the text field's frame or dialog; see
|
||||
@xmethod[top-level-window<%> on-traverse-char]). If the user presses
|
||||
Enter, the type of event passed to the callback is
|
||||
@indexed-scheme['text-field-enter], otherwise it is
|
||||
@indexed-scheme['text-field].
|
||||
|
||||
If @scheme[init-value] is not @scheme[""], the minimum width of the text item
|
||||
is made wide enough to show @scheme[init-value]. Otherwise, a built-in
|
||||
default width is selected. For a text field in single-line mode, the
|
||||
minimum height is set to show one line and only the control's width
|
||||
is stretchable. For a multiple-line text field, the minimum height
|
||||
shows three lines of text and is stretchable in both directions.
|
||||
If @scheme[init-value] is not @scheme[""], the minimum width of the
|
||||
text item is made wide enough to show @scheme[init-value]. Otherwise,
|
||||
a built-in default width is selected. For a text field in single-line
|
||||
mode, the minimum height is set to show one line and only the
|
||||
control's width is stretchable. For a multiple-line text field, the
|
||||
minimum height shows three lines of text and is stretchable in both
|
||||
directions.
|
||||
|
||||
The style must contain exactly one of @scheme['single] or
|
||||
@scheme['multiple]; the former specifies a single-line field and
|
||||
the latter specifies a multiple-line field. The @scheme['hscroll]
|
||||
style applies only to multiple-line fields; when
|
||||
@scheme['hscroll] is specified, the field has a horizontal
|
||||
scrollbar and autowrapping is disabled; otherwise, the field has no
|
||||
horizontal scrollbar and autowrapping is enabled. A multiple-line text
|
||||
field always has a vertical scrollbar. The @scheme['password]
|
||||
style indicates that the field should draw each character of
|
||||
its content using a generic symbol instead of the actual character.
|
||||
\HVLabelNote{text field} \DeletedStyleNote{text field}.
|
||||
@scheme['multiple]; the former specifies a single-line field and the
|
||||
latter specifies a multiple-line field. The @scheme['hscroll] style
|
||||
applies only to multiple-line fields; when @scheme['hscroll] is
|
||||
specified, the field has a horizontal scrollbar and autowrapping is
|
||||
disabled; otherwise, the field has no horizontal scrollbar and
|
||||
autowrapping is enabled. A multiple-line text field always has a
|
||||
vertical scrollbar. The @scheme['password] style indicates that the
|
||||
field should draw each character of its content using a generic
|
||||
symbol instead of the actual character. @HVLabelNote{text field}
|
||||
@DeletedStyleNote{text field}.
|
||||
|
||||
@FontKWs[] @WindowKWs[] @SubareaKWs[] @AreaKWs[]
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@defmethod[(get-value)
|
||||
string]{
|
||||
@spec{
|
||||
|
||||
Returns the text currently in the text field.
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(set-value [val string])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Sets the text currently in the text field. (The control's callback
|
||||
procedure is {\em not} invoked.)
|
||||
|
||||
@MonitorCallback[@elem{A text field's value} @elem{the user typing into the control} @elem{value}]
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(get-editor)
|
||||
(is-a?/c text%)]{
|
||||
@spec{
|
||||
|
||||
Returns the editor used to implement the text field.
|
||||
|
||||
|
@ -119,21 +103,33 @@ For a text field, the most useful methods of a @scheme[text%] object
|
|||
are the following:
|
||||
@itemize{
|
||||
|
||||
@item{@scheme[(send @scheme[a-text] @method[text% get-text])] returns
|
||||
@item{@scheme[(send a-text @method[text% get-text])] returns
|
||||
the current text of the editor.}
|
||||
|
||||
@item{@scheme[(send @scheme[a-text] @method[text% erase])] deletes all text from
|
||||
@item{@scheme[(send a-text @method[text% erase])] deletes all text from
|
||||
the editor.}
|
||||
|
||||
@item{@scheme[(send @scheme[a-text] @method[text% insert] \var{string])}
|
||||
inserts @scheme[str] into the editor at the current caret position.}
|
||||
@item{@scheme[(send a-text @method[text% insert] _str)] inserts
|
||||
@scheme[_str] into the editor at the current caret position.}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@defmethod[(get-value)
|
||||
string?]{
|
||||
|
||||
Returns the text currently in the text field.
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
@defmethod[(set-value [val string?])
|
||||
void?]{
|
||||
|
||||
Sets the text currently in the text field. (The control's callback
|
||||
procedure is @italic{not} invoked.)
|
||||
|
||||
}}}
|
||||
@MonitorCallback[@elem{A text field's value} @elem{the user typing into the control} @elem{value}]
|
||||
|
||||
}}
|
||||
|
|
|
@ -4,106 +4,86 @@
|
|||
@defclass[timer% object% ()]{
|
||||
|
||||
A @scheme[timer%] object encapsulates an event-based alarm. To use a
|
||||
timer, either instantiate it with a @scheme[timer-callback] thunk to perform the alarm-based action, to derive a new class and override the
|
||||
@method[timer% notify] method to perform the alarm-based action. Start a timer with
|
||||
@method[timer% start] and stop it with
|
||||
@method[timer% stop]. Supplying an initial @scheme[interval] (in milliseconds) when creating
|
||||
a timer also starts the timer.
|
||||
timer, either instantiate it with a @scheme[timer-callback] thunk to
|
||||
perform the alarm-based action, to derive a new class and override
|
||||
the @method[timer% notify] method to perform the alarm-based
|
||||
action. Start a timer with @method[timer% start] and stop it with
|
||||
@method[timer% stop]. Supplying an initial @scheme[interval] (in
|
||||
milliseconds) when creating a timer also starts the timer.
|
||||
|
||||
Timers have a relatively high priority in the event queue. Thus, if
|
||||
the timer delay is set low enough, repeated notification for a timer
|
||||
can preempt user activities (which might be directed at stopping the
|
||||
timer). For timers with relatively short delays, call
|
||||
@scheme[yield] within the
|
||||
@method[timer% notify] procedure to allow guaranteed event processing.
|
||||
timer). For timers with relatively short delays, call @scheme[yield]
|
||||
within the @method[timer% notify] procedure to allow guaranteed event
|
||||
processing.
|
||||
|
||||
See @secref["mr:eventspaceinfo"] for more information
|
||||
about event priorities.
|
||||
See @secref["mr:eventspaceinfo"] for more information about event
|
||||
priorities.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@defconstructor[[notify-callback (-> any) @scheme[void]]
|
||||
[interval (or/c (integer-in 0 1000000000) false/c) #f]
|
||||
[just-once? any/c #f]]{
|
||||
|
||||
Creates a timer.
|
||||
@defconstructor[([notify-callback (-> any) @scheme[void]]
|
||||
[interval (or/c (integer-in 0 1000000000) false/c) #f]
|
||||
[just-once? any/c #f])]{
|
||||
|
||||
The @scheme[notify-callback] thunk is called by the default
|
||||
@method[timer% notify] method when the timer expires.
|
||||
|
||||
If @scheme[interval] is @scheme[#f] (the default), the timer is not
|
||||
started; in that case,
|
||||
@method[timer% start] must be called explicitly. If @scheme[interval] is a number (in
|
||||
milliseconds), then
|
||||
@method[timer% start] is called with @scheme[interval] and @scheme[just-once?].
|
||||
started; in that case, @method[timer% start] must be called
|
||||
explicitly. If @scheme[interval] is a number (in milliseconds), then
|
||||
@method[timer% start] is called with @scheme[interval] and
|
||||
@scheme[just-once?].
|
||||
|
||||
}
|
||||
|
||||
|
||||
@defmethod[(interval)
|
||||
(integer-in 0 1000000000)]{
|
||||
|
||||
Returns the number of milliseconds between each timer expiration (when
|
||||
the timer is running).
|
||||
|
||||
}
|
||||
|
||||
@defmethod[(notify)
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
@methspec{
|
||||
|
||||
Called (on an event boundary) when the timer's alarm expires.
|
||||
|
||||
}
|
||||
@impl{
|
||||
@methimpl{
|
||||
|
||||
Calls the @scheme[notify-callback] procedure that was provided when the
|
||||
object was created.
|
||||
|
||||
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(interval)
|
||||
(integer-in 0 1000000000)]{
|
||||
@spec{
|
||||
|
||||
Returns the number of milliseconds between each timer expiration
|
||||
(when the timer is running).
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(start [msec (integer-in 0 1000000000)]
|
||||
[just-once? any/c #f])
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Starts (or restarts) the timer. If the timer is already running, its
|
||||
alarm time is not changed.
|
||||
|
||||
The timer's alarm expires after @scheme[msec] milliseconds, at which
|
||||
point @method[timer% notify] is called (on an event boundary). If
|
||||
@scheme[just-once?]\ is @scheme[#f], the timer expires {\em every}
|
||||
@scheme[msec] milliseconds until the timer is explicitly
|
||||
stopped;\footnote{More precisely, the timer expires @scheme[msec]
|
||||
milliseconds after @method[timer% notify] returns each time}
|
||||
otherwise, the timer expires only once.
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
The timer's alarm expires after @scheme[msec] milliseconds, at which point
|
||||
@method[timer% notify] is called (on an event boundary). If @scheme[just-once?]\ is @scheme[#f],
|
||||
the timer expires {\em every} @scheme[msec] milliseconds until the timer is
|
||||
explicitly stopped;\footnote{More precisely, the timer expires @scheme[msec]
|
||||
milliseconds after
|
||||
@method[timer% notify] returns each time} otherwise, the timer expires only once.
|
||||
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@defmethod[(stop)
|
||||
void?]{
|
||||
@spec{
|
||||
|
||||
Stops the timer. A stopped timer never calls
|
||||
@method[timer% notify]. If the timer has expired but the call to
|
||||
@method[timer% notify] has not yet been dispatched, the call is removed from the event queue.
|
||||
|
||||
}
|
||||
@impl{
|
||||
|
||||
|
||||
|
||||
|
||||
}}}
|
||||
}}
|
||||
|
||||
|
|
125
collects/scribblings/gui/win-classes.scrbl
Normal file
125
collects/scribblings/gui/win-classes.scrbl
Normal file
|
@ -0,0 +1,125 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require["common.ss"]
|
||||
@require["diagrams.ss"]
|
||||
|
||||
@title[#:style '(toc quiet)]{Windowing Class Reference}
|
||||
|
||||
Windows and controls:
|
||||
|
||||
@diagram->table[windowing-diagram]
|
||||
|
||||
Menus:
|
||||
|
||||
@diagram->table[menu-diagram]
|
||||
|
||||
Events and other:
|
||||
|
||||
@diagram->table[event-diagram]
|
||||
|
||||
Alphabetical:
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@require["area-intf.scrbl"]
|
||||
@require["area-container-intf.scrbl"]
|
||||
@require["area-container-window-intf.scrbl"]
|
||||
@require["button-class.scrbl"]
|
||||
@require["canvas-intf.scrbl"]
|
||||
@require["canvas-class.scrbl"]
|
||||
@require["check-box-class.scrbl"]
|
||||
@require["checkable-menu-item-class.scrbl"]
|
||||
@require["choice-class.scrbl"]
|
||||
@require["clipboard-client-class.scrbl"]
|
||||
@require["clipboard-intf.scrbl"]
|
||||
@require["combo-field-class.scrbl"]
|
||||
@require["control-intf.scrbl"]
|
||||
@require["control-event-class.scrbl"]
|
||||
@require["cursor-class.scrbl"]
|
||||
@require["dialog-class.scrbl"]
|
||||
@require["event-class.scrbl"]
|
||||
@require["frame-class.scrbl"]
|
||||
@require["gauge-class.scrbl"]
|
||||
@require["group-box-panel-class.scrbl"]
|
||||
@require["grow-box-spacer-pane-class.scrbl"]
|
||||
@require["horizontal-pane-class.scrbl"]
|
||||
@require["horizontal-panel-class.scrbl"]
|
||||
@require["key-event-class.scrbl"]
|
||||
@require["labelled-menu-item-intf.scrbl"]
|
||||
@require["list-box-class.scrbl"]
|
||||
@require["list-control-intf.scrbl"]
|
||||
@require["menu-class.scrbl"]
|
||||
@require["menu-bar-class.scrbl"]
|
||||
@require["menu-item-intf.scrbl"]
|
||||
@require["menu-item-class.scrbl"]
|
||||
@require["menu-item-container-intf.scrbl"]
|
||||
@require["message-class.scrbl"]
|
||||
@require["mouse-event-class.scrbl"]
|
||||
@require["pane-class.scrbl"]
|
||||
@require["panel-class.scrbl"]
|
||||
@require["popup-menu-class.scrbl"]
|
||||
@require["radio-box-class.scrbl"]
|
||||
@require["selectable-menu-item-intf.scrbl"]
|
||||
@require["separator-menu-item-class.scrbl"]
|
||||
@require["scroll-event-class.scrbl"]
|
||||
@require["slider-class.scrbl"]
|
||||
@require["subarea-intf.scrbl"]
|
||||
@require["subwindow-intf.scrbl"]
|
||||
@require["tab-panel-class.scrbl"]
|
||||
@require["text-field-class.scrbl"]
|
||||
@require["timer-class.scrbl"]
|
||||
@require["top-level-window-intf.scrbl"]
|
||||
@require["vertical-pane-class.scrbl"]
|
||||
@require["vertical-panel-class.scrbl"]
|
||||
@require["window-intf.scrbl"]
|
||||
|
||||
@include-class[area<%>]
|
||||
@include-class[area-container<%>]
|
||||
@include-class[area-container-window<%>]
|
||||
@include-class[button%]
|
||||
@include-class[canvas<%>]
|
||||
@include-class[canvas%]
|
||||
@include-class[check-box%]
|
||||
@include-class[checkable-menu-item%]
|
||||
@include-class[choice%]
|
||||
@include-class[clipboard<%>]
|
||||
@include-class[clipboard-client%]
|
||||
@include-class[combo-field%]
|
||||
@include-class[control<%>]
|
||||
@include-class[control-event%]
|
||||
@include-class[cursor%]
|
||||
@include-class[dialog%]
|
||||
@include-class[event%]
|
||||
@include-class[frame%]
|
||||
@include-class[gauge%]
|
||||
@include-class[group-box-panel%]
|
||||
@include-class[grow-box-spacer-pane%]
|
||||
@include-class[horizontal-pane%]
|
||||
@include-class[horizontal-panel%]
|
||||
@include-class[key-event%]
|
||||
@include-class[labelled-menu-item<%>]
|
||||
@include-class[list-box%]
|
||||
@include-class[list-control<%>]
|
||||
@include-class[menu%]
|
||||
@include-class[menu-bar%]
|
||||
@include-class[menu-item<%>]
|
||||
@include-class[menu-item%]
|
||||
@include-class[menu-item-container<%>]
|
||||
@include-class[message%]
|
||||
@include-class[mouse-event%]
|
||||
@include-class[pane%]
|
||||
@include-class[panel%]
|
||||
@include-class[popup-menu%]
|
||||
@include-class[radio-box%]
|
||||
@include-class[scroll-event%]
|
||||
@include-class[selectable-menu-item<%>]
|
||||
@include-class[separator-menu-item%]
|
||||
@include-class[slider%]
|
||||
@include-class[subarea<%>]
|
||||
@include-class[subwindow<%>]
|
||||
@include-class[tab-panel%]
|
||||
@include-class[text-field%]
|
||||
@include-class[timer%]
|
||||
@include-class[top-level-window<%>]
|
||||
@include-class[vertical-pane%]
|
||||
@include-class[vertical-panel%]
|
||||
@include-class[window<%>]
|
11
collects/scribblings/gui/win-funcs.scrbl
Normal file
11
collects/scribblings/gui/win-funcs.scrbl
Normal file
|
@ -0,0 +1,11 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require["common.ss"]
|
||||
|
||||
@title[#:style 'toc]{Windowing Function Reference}
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@include-section["dialog-funcs.scrbl"]
|
||||
@include-section["eventspace-funcs.scrbl"]
|
||||
@include-section["system-menu-funcs.scrbl"]
|
||||
@include-section["miscwin-funcs.scrbl"]
|
950
collects/scribblings/gui/win-overview.scrbl
Normal file
950
collects/scribblings/gui/win-overview.scrbl
Normal file
|
@ -0,0 +1,950 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require[(lib "eval.ss" "scribble")]
|
||||
@require["common.ss"]
|
||||
@require["diagrams.ss"]
|
||||
|
||||
@title[#:tag "mr:windowing-overview" #:style 'toc]{Windowing Toolbox Overview}
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@section{Basic GUI Building Blocks}
|
||||
|
||||
MrEd's windowing toolbox provides the basic building blocks of GUI
|
||||
programs, including frames (top-level windows), modal dialogs, menus,
|
||||
buttons, check boxes, text fields, and radio buttons. The toolbox
|
||||
provides these building blocks via built-in classes, such as the
|
||||
@scheme[frame%] class:
|
||||
|
||||
@schemeblock[
|
||||
(code:comment #, @t{Make a frame by instantiating the @scheme[frame%] class})
|
||||
(define frame (new frame% [label "Example"]))
|
||||
|
||||
(code:comment #, @t{Show the frame by calling its @method[top-level-window<%> show] method})
|
||||
(send frame top-level-window::show #t)
|
||||
]
|
||||
|
||||
The built-in classes provide various mechanisms for handling GUI
|
||||
events. For example, when instantiating the @scheme[button%] class,
|
||||
the programmer supplies an event callback procedure to be invoked
|
||||
when the user clicks the button. The following example program
|
||||
creates a frame with a text message and a button; when the user
|
||||
clicks the button, the message changes:
|
||||
|
||||
@schemeblock[
|
||||
(code:comment #, @t{Make a frame by instantiating the @scheme[frame%] class})
|
||||
(define frame (new frame% [label "Example"]))
|
||||
|
||||
(code:comment #, @t{Make a static text message in the frame})
|
||||
(define msg (new message% [parent frame]
|
||||
[label "No events so far..."]))
|
||||
|
||||
(code:comment #, @t{Make a button in the frame})
|
||||
(new button% [parent frame]
|
||||
[label "Click Me"]
|
||||
(code:comment #, @t{Callback procedure for a button click:})
|
||||
(callback (lambda (button event)
|
||||
(send msg #,(method message% set-label) "Button click"))))
|
||||
|
||||
(code:comment #, @t{Show the frame by calling its @scheme[show] method})
|
||||
(send frame top-level-window::show #t)
|
||||
]
|
||||
|
||||
Programmers never implement the GUI event loop directly. Instead, the
|
||||
system automatically pulls each event from an internal queue and
|
||||
dispatches the event to an appropriate window. The dispatch invokes
|
||||
the window's callback procedure or calls one of the window's
|
||||
methods. In the above program, the system automatically invokes the
|
||||
button's callback procedure whenever the user clicks @onscreen{Click
|
||||
Me}.
|
||||
|
||||
If a window receives multiple kinds of events, the events are
|
||||
dispatched to methods of the window's class instead of to a callback
|
||||
procedure. For example, a drawing canvas receives update events,
|
||||
mouse events, keyboard events, and sizing events; to handle them, a
|
||||
programmer must derive a new class from the built-in
|
||||
@scheme[canvas%] class and override the event-handling methods. The
|
||||
following expression extends the frame created above with a canvas
|
||||
that handles mouse and keyboard events:
|
||||
|
||||
@schemeblock[
|
||||
(code:comment #, @t{Derive a new canvas (a drawing window) class to handle events})
|
||||
(define my-canvas%
|
||||
(class canvas% (code:comment #, @t{The base class is @scheme[canvas%]})
|
||||
(code:comment #, @t{Define overriding method to handle mouse events})
|
||||
(define/override (#,(:: canvas<%> on-event) event)
|
||||
(send msg #,(:: message% set-label) "Canvas mouse"))
|
||||
(code:comment #, @t{Define overriding method to handle keyboard events})
|
||||
(define/override (#,(:: canvas<%> on-char) event)
|
||||
(send msg #,(:: message% set-label) "Canvas keyboard"))
|
||||
(code:comment #, @t{Call the superclass initialization (and pass on all init args)})
|
||||
(super-new)))
|
||||
|
||||
(code:comment #, @t{Make a canvas that handles events in the frame})
|
||||
(new my-canvas% [parent frame])
|
||||
]
|
||||
|
||||
After running the above code, manually resize the frame to see the
|
||||
new canvas. Moving the cursor over the canvas calls the canvas's
|
||||
@method[canvas<%> on-event] method with an object representing a
|
||||
motion event. Clicking on the canvas calls @method[canvas<%>
|
||||
on-event]. While the canvas has the keyboard focus, typing on the
|
||||
keyboard invokes the canvas's @method[canvas<%> on-char] method.
|
||||
|
||||
The system dispatches GUI events sequentially; that is, after invoking
|
||||
an event-handling callback or method, the system waits until the
|
||||
handler returns before dispatching the next event. To illustrate the
|
||||
sequential nature of events, we extend the frame again, adding a
|
||||
@onscreen{Pause} button:
|
||||
|
||||
@schemeblock[
|
||||
(new button% [parent frame]
|
||||
[label "Pause"]
|
||||
[callback (lambda (button event) (sleep 5))])
|
||||
]
|
||||
|
||||
After the user clicks @onscreen{Pause}, the entire frame becomes
|
||||
unresponsive for five seconds; the system cannot dispatch more events
|
||||
until the call to @scheme[sleep] returns. For more information about
|
||||
event dispatching, see @secref["mr:eventspaceinfo"].
|
||||
|
||||
In addition to dispatching events, the GUI classes also handle the
|
||||
graphical layout of windows. Our example frame demonstrates a simple
|
||||
layout; the frame's elements are lined up top-to-bottom. In general,
|
||||
a programmer specifies the layout of a window by assigning each GUI
|
||||
element to a parent @deftech{container}. A vertical container, such
|
||||
as a frame, arranges its children in a column, and a horizontal
|
||||
container arranges its children in a row. A container can be a child
|
||||
of another container; for example, to place two buttons side-by-side
|
||||
in our frame, we create a horizontal panel for the new buttons:
|
||||
|
||||
@schemeblock[
|
||||
(define panel (new horizontal-panel% [parent frame]))
|
||||
(new button% [parent panel]
|
||||
[label "Left"]
|
||||
[callback (lambda (button event)
|
||||
(send msg #,(:: message% set-label) "Left click"))])
|
||||
(new button% [parent panel]
|
||||
[label "Right"]
|
||||
[callback (lambda (button event)
|
||||
(send msg #,(:: message% set-label) "Right click"))])
|
||||
]
|
||||
|
||||
For more information about window layout and containers, see
|
||||
@secref["mr:containeroverview"].
|
||||
|
||||
@section{Core Windowing Classes}
|
||||
|
||||
The fundamental graphical element in MrEd's windowing toolbox is an
|
||||
@deftech{area}. The following classes implement the different types
|
||||
of areas in the windowing toolbox:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@deftech{Containers} --- areas that can
|
||||
contain other areas:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@scheme[frame%] --- a @deftech{frame} is a top-level window
|
||||
that the user can move and resize.}
|
||||
|
||||
@item{@scheme[dialog%] --- a @deftech{dialog} is a modal top-level
|
||||
window; when a dialog is shown, other top-level windows are disabled
|
||||
until the dialog is dismissed.}
|
||||
|
||||
@item{@scheme[panel%] --- a @deftech{panel} is a subcontainer
|
||||
within a container. The toolbox provides three subclasses of
|
||||
@scheme[panel%]: @scheme[vertical-panel%],
|
||||
@scheme[horizontal-panel%], and @scheme[tab-panel%].}
|
||||
|
||||
@item{@scheme[pane%] --- a @deftech{pane} is a lightweight panel.
|
||||
It has no graphical representation or event-handling capabilities.
|
||||
The @scheme[pane%] class has three subclasses:
|
||||
@scheme[vertical-pane%], @scheme[horizontal-pane%], and
|
||||
@scheme[grow-box-spacer-pane%].}
|
||||
|
||||
}}
|
||||
|
||||
@item{@deftech{Containees} --- areas that must be
|
||||
contained within other areas:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@scheme[panel%] --- a panel is a containee as well as
|
||||
a container.}
|
||||
|
||||
@item{@scheme[pane%] --- a pane is a containee as well as a
|
||||
container.}
|
||||
|
||||
@item{@scheme[canvas%] --- a @deftech{canvas} is a subwindow for
|
||||
drawing on the screen.}
|
||||
|
||||
@item{@scheme[editor-canvas%] --- an @deftech{editor canvas} is a
|
||||
subwindow for displaying a text editor or pasteboard editor. The
|
||||
@scheme[editor-canvas%] class is documented with the editor classes
|
||||
in @secref["mr:editoredit"].}
|
||||
|
||||
@item{@deftech{Controls} --- containees that the user can manipulate:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@scheme[message%] --- a @deftech{message} is a static
|
||||
text field or bitmap with no user interaction.}
|
||||
|
||||
@item{@scheme[button%] --- a @deftech{button} is a clickable
|
||||
control.}
|
||||
|
||||
@item{@scheme[check-box%] --- a @deftech{check box} is a
|
||||
clickable control; the user clicks the control to set or remove
|
||||
its check mark.}
|
||||
|
||||
@item{@scheme[radio-box%] --- a @deftech{radio box} is a
|
||||
collection of mutually exclusive @deftech{radio buttons}; when the
|
||||
user clicks a radio button, it is selected and the radio box's
|
||||
previously selected radio button is deselected.}
|
||||
|
||||
@item{@scheme[choice%] --- a @deftech{choice item} is a pop-up
|
||||
menu of text choices; the user selects one item in the control.}
|
||||
|
||||
@item{@scheme[list-box%] --- a @deftech{list box} is a
|
||||
scrollable lists of text choices; the user selects one or more
|
||||
items in the list (depending on the style of the list box).}
|
||||
|
||||
@item{@scheme[text-field%] --- a @deftech{text field} is a box
|
||||
for simple text entry.}
|
||||
|
||||
@item{@scheme[combo-field%] --- a @deftech{combo field} combines
|
||||
a text field with a pop-up menu of choices.}
|
||||
|
||||
@item{@scheme[slider%] --- a @deftech{slider} is a dragable
|
||||
control that selects an integer value within a fixed range.}
|
||||
|
||||
@item{@scheme[gauge%] --- a @deftech{gauge} is an output-only
|
||||
control (the user cannot change the value) for reporting an integer
|
||||
value within a fixed range.}
|
||||
|
||||
}}
|
||||
|
||||
}}
|
||||
|
||||
}
|
||||
|
||||
As suggested by the above listing, certain @tech{areas}, called
|
||||
@tech{containers}, manage certain other areas, called
|
||||
@tech{containees}. Some areas, such as panels, are both
|
||||
@tech{containers} and @tech{containees}.
|
||||
|
||||
Most areas are @deftech{windows}, but some are
|
||||
@deftech{non-windows}. A @tech{window}, such as a @tech{panel}, has a
|
||||
graphical representation, receives keyboard and mouse events, and can
|
||||
be disabled or hidden. In contrast, a @tech{non-window}, such as a
|
||||
@tech{pane}, is useful only for geometry management; a
|
||||
@tech{non-window} does not receive mouse events, and it cannot be
|
||||
disabled or hidden.
|
||||
|
||||
Every @tech{area} is an instance of the @scheme[area<%>]
|
||||
interface. Each @tech{container} is also an instance of the
|
||||
@scheme[area-container<%>] interface, whereas each @tech{containee}
|
||||
is an instance of @scheme[subarea<%>]. @tech{Windows} are instances
|
||||
of @scheme[window<%>]. The @scheme[area-container<%>],
|
||||
@scheme[subarea<%>], and @scheme[window<%>] interfaces are
|
||||
subinterfaces of @scheme[area<%>].
|
||||
|
||||
The following diagram shows more of the type hierarchy under
|
||||
@scheme[area<%>]:
|
||||
|
||||
@diagram->table[short-windowing-diagram]
|
||||
|
||||
The diagram below extends the one above to show the complete type
|
||||
hierarchy under @scheme[area<%>]. (Some of the types are represented
|
||||
by interfaces, and some types are represented by classes. In
|
||||
principle, every area type should be represented by an interface, but
|
||||
whenever the windowing toolbox provides a concrete implementation,
|
||||
the corresponding interface is omitted from the toolbox.) To avoid
|
||||
intersecting lines, the hierarchy is drawn for a cylindrical surface;
|
||||
lines from @scheme[subarea<%>] and @scheme[subwindow<%>] wrap from
|
||||
the left edge of the diagram to the right edge.
|
||||
|
||||
@diagram->table[windowing-diagram]
|
||||
|
||||
Menu bars, menus, and menu items are graphical elements, but not areas
|
||||
(i.e., they do not have all of the properties that are common to
|
||||
areas, such as an adjustable graphical size). Instead, the menu
|
||||
classes form a separate container--containee hierarchy:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@deftech{Menu Item Containers}
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@scheme[menu-bar%] --- a @deftech{menu bar} is a top-level
|
||||
collection of menus that are associated with a frame.}
|
||||
|
||||
@item{@scheme[menu%] --- a @deftech{menu} contains a set of menu
|
||||
items. The menu can appear in a menu bar, in a popup menu, or as a
|
||||
submenu in another menu.}
|
||||
|
||||
@item{@scheme[popup-menu%] --- a @deftech{popup menu} is a
|
||||
top-level menu that is dynamically displayed in a canvas or
|
||||
editor canvas.}
|
||||
|
||||
}}
|
||||
|
||||
@item{@deftech{Menu Items}
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@scheme[separator-menu-item%] --- a @deftech{separator} is
|
||||
an unselectable line in a menu or popup menu.}
|
||||
|
||||
@item{@scheme[menu-item%] --- a @deftech{menu item} is a selectable
|
||||
text item in a menu. When the item is selected, its callback procedure
|
||||
is invoked.}
|
||||
|
||||
@item{@scheme[checkable-menu-item%] --- a @deftech{checkable menu
|
||||
item} is a text item in a menu; the user selects a checkable menu
|
||||
item to toggle a check mark next to the item.}
|
||||
|
||||
@item{@scheme[menu%] --- a menu is a menu item as well as a menu
|
||||
item container.}
|
||||
|
||||
}}
|
||||
|
||||
}
|
||||
|
||||
The following diagram shows the complete type hierarchy for the menu
|
||||
system:
|
||||
|
||||
@diagram->table[menu-diagram]
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
|
||||
@section[#:tag "mr:containeroverview"]{Geometry Management}
|
||||
|
||||
MrEd's geometry management makes it easy to design windows that look
|
||||
right on all platforms, despite different graphical representations
|
||||
of GUI elements. Geometry management is based on containers; each
|
||||
container arranges its children based on simple constraints, such as
|
||||
the current size of a frame and the natural size of a button.
|
||||
|
||||
The built-in container classes include horizontal panels (and panes),
|
||||
which align their children in a row, and vertical panels (and panes),
|
||||
which align their children in a column. By nesting horizontal and
|
||||
vertical containers, a programmer can achieve most any layout. For
|
||||
example, we can construct a dialog with the following shape:
|
||||
|
||||
@verbatim[
|
||||
#<<IMG
|
||||
------------------------------------------------------
|
||||
| ------------------------------------- |
|
||||
| Your name: | | |
|
||||
| ------------------------------------- |
|
||||
| -------- ---- |
|
||||
| ( Cancel ) ( OK ) |
|
||||
| -------- ---- |
|
||||
------------------------------------------------------
|
||||
IMG
|
||||
]
|
||||
|
||||
with the following program:
|
||||
|
||||
@schemeblock[
|
||||
(code:comment #, @t{Create a dialog})
|
||||
(define dialog (instantiate dialog\% ("Example")))
|
||||
|
||||
(code:comment #, @t{Add a text field to the dialog})
|
||||
(new text-field% [parent dialog] [label "Your name"])
|
||||
|
||||
(code:comment #, @t{Add a horizontal panel to the dialog, with centering for buttons})
|
||||
(define panel (new horizontal-panel% [parent dialog]
|
||||
[alignment '(center center)]))
|
||||
|
||||
(code:comment #, @t{Add @onscreen{Cancel} and @onscreen{Ok} buttons to the horizontal panel})
|
||||
(new button% [parent parent] [label "Cancel"])
|
||||
(new button% [parent parent] [label "Ok"])
|
||||
|
||||
(code:comment #, @t{Show the dialog})
|
||||
(send dialog #,(:: dialog% show) #t)
|
||||
]
|
||||
|
||||
Each container arranges its children using the natural size of each
|
||||
child, which usually depends on instantiation parameters of the
|
||||
child, such as the label on a button or the number of choices in a
|
||||
radio box. In the above example, the dialog stretches horizontally to
|
||||
match the minimum width of the text field, and it stretches
|
||||
vertically to match the total height of the field and the
|
||||
buttons. The dialog then stretches the horizontal panel to fill the
|
||||
bottom half of the dialog. Finally, the horizontal panel uses the sum
|
||||
of the buttons' minimum widths to center them horizontally.
|
||||
|
||||
As the example demonstrates, a stretchable container grows to fill its
|
||||
environment, and it distributes extra space among its stretchable
|
||||
children. By default, panels are stretchable in both directions,
|
||||
whereas buttons are not stretchable in either direction. The
|
||||
programmer can change whether an individual GUI element is
|
||||
stretchable.
|
||||
|
||||
The following subsections describe the container system in detail,
|
||||
first discussing the attributes of a containee in
|
||||
@secref["mr:containees"], and then describing
|
||||
the attributes of a container in
|
||||
@secref["mr:containers"]. In addition to the
|
||||
built-in vertical and horizontal containers, programmers can define
|
||||
new types of containers as discussed in the final subsection,
|
||||
@secref["mr:new-containers"].
|
||||
|
||||
|
||||
@subsection[#:tag "mr:containees"]{Containees}
|
||||
|
||||
Each @tech{containee}, or child, has the following properties:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{a @deftech{graphical minimum width} and a @deftech{graphical minimum height};}
|
||||
|
||||
@item{a @deftech{requested minimum width} and a @deftech{requested minimum height};}
|
||||
|
||||
@item{horizontal and vertical @deftech{stretchability} (on or off); and}
|
||||
|
||||
@item{horizontal and vertical @deftech{margins}.}
|
||||
|
||||
}
|
||||
|
||||
A @tech{container} arranges its children based on these four
|
||||
properties of each @tech{containee}. A @tech{containee}'s parent
|
||||
container is specified when the @tech{containee} is created, and the
|
||||
parent cannot be changed. However, a @tech{containee} can be
|
||||
@tech{hidden} or @tech{deleted} within its parent, as described in
|
||||
@secref["mr:containers"].
|
||||
|
||||
The @deftech{graphical minimum size} of a particular containee, as
|
||||
reported by @method[area<%> get-graphical-min-size], depends on the
|
||||
platform, the label of the containee (for a control), and style
|
||||
attributes specified when creating the containee. For example, a
|
||||
button's minimum graphical size ensures that the entire text of the
|
||||
label is visible. The graphical minimum size of a control (such as a
|
||||
button) cannot be changed; it is fixed at creation time. (A control's
|
||||
minimum size is @italic{not} recalculated when its label is changed.)
|
||||
The graphical minimum size of a panel or pane depends on the total
|
||||
minimum size of its children and the way that they are arranged.
|
||||
|
||||
To select a size for a containee, its parent container considers the
|
||||
containee's @deftech{requested minimum size} rather than its
|
||||
graphical minimum size (assuming the requested minimum is larger than
|
||||
the graphical minimum). Unlike the graphical minimum, the requested
|
||||
minimum size of a containee can be changed by a programmer at any
|
||||
time using the @method[area<%> min-width] and
|
||||
@method[area<%> min-height] methods.
|
||||
|
||||
Unless a containee is stretchable (in a particular direction), it
|
||||
always shrinks to its minimum size (in the corresponding
|
||||
direction). Otherwise, containees are stretched to fill all available
|
||||
space in a container. Each containee begins with a default
|
||||
stretchability. For example, buttons are not initially stretchable,
|
||||
whereas a one-line text field is initially stretchable in the
|
||||
horizontal direction. A programmer can change the stretchability of a
|
||||
containee at any time using the @method[area<%> stretchable-width]
|
||||
and @method[area<%> stretchable-height] methods.
|
||||
|
||||
A @deftech{margin} is space surrounding a containee. Each containee's
|
||||
margin is independent of its minimum size, but from the container's
|
||||
point of view, a margin effectively increases the minimum size of the
|
||||
containee. For example, if a button has a vertical margin of
|
||||
@scheme[2], then the container must allocate enough room to leave two
|
||||
pixels of space above and below the button, in addition to the space
|
||||
that is allocated for the button's minimum height. A programmer can
|
||||
adjust a containee's margin with @method[subarea<%> horiz-margin] and
|
||||
@method[subarea<%> vert-margin]. The default margin is @scheme[2] for
|
||||
a control, and @scheme[0] for any other type of containee.
|
||||
|
||||
In practice, the @tech{requested minimum size} and @tech{margin} of a
|
||||
control are rarely changed, although they are often changed for a
|
||||
canvas. @tech{Stretchability} is commonly adjusted for any type of
|
||||
containee, depending on the visual effect desired by the programmer.
|
||||
|
||||
|
||||
@subsection[#:tag "mr:containers"]{Containers}
|
||||
|
||||
A container has the following properties:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{a list of (non-deleted) children containees;}
|
||||
|
||||
@item{a requested minimum width and a requested minimum height;}
|
||||
|
||||
@item{a spacing used between the children;}
|
||||
|
||||
@item{a border margin used around the total set of children;}
|
||||
|
||||
@item{horizontal and vertical stretchability (on or off); and}
|
||||
|
||||
@item{an alignment setting for positioning leftover space.}
|
||||
|
||||
}
|
||||
|
||||
These properties are factored into the container's calculation of its
|
||||
own size and the arrangement of its children. For a container that is
|
||||
also a containee (e.g., a panel), the container's requested minimum
|
||||
size and stretchability are the same as for its containee aspect.
|
||||
|
||||
A containee's parent container is specified when the containee is
|
||||
created, and the parent cannot be changed. However, a containee
|
||||
window can be @tech{hidden} or @tech{deleted} within its parent
|
||||
container (but a non-window containee cannot be @tech{hidden} or
|
||||
@tech{deleted}):
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{A @deftech{hidden} child is invisible to the user, but space is
|
||||
still allocated for each hidden child within a container. To hide or
|
||||
show a child, call the child's @method[window<%> show] method.}
|
||||
|
||||
@item{A @deftech{deleted} child is hidden @italic{and} ignored by
|
||||
container as it arranges its other children, so no space is reserved
|
||||
in the container for a deleted child. To make a child deleted or
|
||||
non-deleted, call the container's @method[area-container<%>
|
||||
delete-child] or @method[area-container<%> add-child] method (which
|
||||
calls the child's @method[window<%> show] method).}
|
||||
|
||||
}
|
||||
|
||||
When a child is created, it is initially shown and non-deleted. A
|
||||
deleted child is subject to garbage collection when no external
|
||||
reference to the child exists. A list of non-deleted children (hidden
|
||||
or not) is available from a container through its
|
||||
@method[area-container<%> get-children] method.
|
||||
|
||||
The order of the children in a container's non-deleted list is
|
||||
significant. For example, a vertical panel puts the first child in
|
||||
its list at the top of the panel, and so on. When a new child is
|
||||
created, it is put at the end of its container's list of
|
||||
children. The order of a container's list can be changed dynamically
|
||||
via the @method[area-container<%> change-children] method. (The
|
||||
@method[area-container<%> change-children] method can also be used to
|
||||
activate or deactivate children.)
|
||||
|
||||
The @tech{graphical minimum size} of a container, as reported by
|
||||
@method[area<%> get-graphical-min-size], is calculated by combining
|
||||
the minimum sizes of its children (summing them or taking the
|
||||
maximum, as appropriate to the layout strategy of the container)
|
||||
along with the spacing and border margins of the container. A larger
|
||||
minimum may be specified by the programmer using @method[area<%>
|
||||
min-width] and @method[area<%> min-height] methods; when the computed
|
||||
minimum for a container is larger than the programmer-specified
|
||||
minimum, then the programmer-specified minimum is ignored.
|
||||
|
||||
A container's spacing determines the amount of space left between
|
||||
adjacent children in the container, in addition to any space required
|
||||
by the children's margins. A container's border margin determines the
|
||||
amount of space to add around the collection of children; it
|
||||
effectively decreases the area within the container where children
|
||||
can be placed. A programmer can adjust a container's border and
|
||||
spacing dynamically via the @method[area-container<%> border] and
|
||||
@method[area-container<%> spacing] methods. The default border and
|
||||
spacing are @scheme[0] for all container types.
|
||||
|
||||
Because a panel or pane is a containee as well as a container, it has
|
||||
a containee margin in addition to its border margin. For a panel,
|
||||
these margins are not redundant because the panel can have a
|
||||
graphical border; the border is drawn inside the panel's containee
|
||||
margin, but outside the panel's border margin.
|
||||
|
||||
For a top-level-window container, such as a frame or dialog, the
|
||||
container's stretchability determines whether the user can resize the
|
||||
window to something larger than its minimum size. Thus, the user
|
||||
cannot resize a frame that is not stretchable. For other types of
|
||||
containers (i.e., panels and panes), the container's stretchability
|
||||
is its stretchability as a containee in some other container. All
|
||||
types of containers are initially stretchable in both
|
||||
directions---except instances of @scheme[grow-box-spacer-pane%],
|
||||
which is intended as a lightweight spacer class rather than a useful
|
||||
container class---but a programmer can change the stretchability of
|
||||
an area at any time via the @method[area<%> stretchable-width] and
|
||||
@method[area<%> stretchable-height] methods.
|
||||
|
||||
The alignment specification for a container determines how it
|
||||
positions its children when the container has leftover space. (A
|
||||
container can only have leftover space in a particular direction when
|
||||
none of its children are stretchable in that direction.) For example,
|
||||
when the container's horizontal alignment is @indexed-scheme['left],
|
||||
the children are left-aligned in the container and leftover space is
|
||||
accumulated to the right. When the container's horizontal alignment
|
||||
is @indexed-scheme['center], each child is horizontally centered in
|
||||
the container. A container's alignment is changed with the
|
||||
@method[area-container<%> set-alignment] method.
|
||||
|
||||
@subsection[#:tag "mr:new-containers"]{Defining New Types of Containers}
|
||||
|
||||
Although nested horizontal and vertical containers can express most
|
||||
layout patterns, a programmer can define a new type of container with
|
||||
an explicit layout procedure. A programmer defines a new type of
|
||||
container by deriving a class from @scheme[panel%] or @scheme[pane%]
|
||||
and overriding the @method[area-container<%> container-size] and
|
||||
@method[area-container<%> place-children] methods. The
|
||||
@method[area-container<%> container-size] method takes a list of size
|
||||
specifications for each child and returns two values: the minimum
|
||||
width and height of the container. The @method[area-container<%>
|
||||
place-children] method takes the container's size and a list of size
|
||||
specifications for each child, and returns a list of sizes and
|
||||
placements (in parallel to the original list).
|
||||
|
||||
An input size specification is a list of four values:
|
||||
|
||||
@itemize{
|
||||
@item{the child's minimum width;}
|
||||
@item{the child's minimum height;}
|
||||
@item{the child's horizontal stretchability (@scheme[#t] means stretchable, @scheme[#f] means not stretchable); and}
|
||||
@item{the child's vertical stretchability.}
|
||||
}
|
||||
|
||||
For @method[area-container<%> place-children], an output
|
||||
position and size specification is a list of four values:
|
||||
|
||||
@itemize{
|
||||
@item{the child's new horizontal position (relative to the parent);}
|
||||
@item{the child's new vertical position;}
|
||||
@item{the child's new actual width;}
|
||||
@item{the child's new actual height.}
|
||||
}
|
||||
|
||||
The widths and heights for both the input and output include the
|
||||
children's margins. The returned position for each child is
|
||||
automatically incremented to account for the child's margin in
|
||||
placing the control.
|
||||
|
||||
|
||||
@section[#:tag "mr:mouseandkey"]{Mouse and Keyboard Events}
|
||||
|
||||
Whenever the user moves the mouse, clicks or releases a mouse button,
|
||||
or presses a key on the keyboard, an event is generated for some
|
||||
window. The window that receives the event depends on the current
|
||||
state of the graphic display:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@index['("mouse events" "overview")]{The} receiving window of a
|
||||
mouse event is usually the window under the cursor when the mouse is
|
||||
moved or clicked. If the mouse is over a child window, the child
|
||||
window receives the event rather than its parent.
|
||||
|
||||
When the user clicks in a window, the window ``grabs'' the mouse, so
|
||||
that @italic{all} mouse events go to that window until the mouse
|
||||
button is released (regardless of the location of the cursor). As a
|
||||
result, a user can click on a scrollbar thumb and drag it without
|
||||
keeping the cursor strictly inside the scrollbar control.
|
||||
|
||||
A mouse button-release event is normally generated for each mouse
|
||||
button-down event, but a button-release event might get dropped. For
|
||||
example, a modal dialog might appear and take over the mouse. More
|
||||
generally, any kind of mouse event can get dropped in principle, so
|
||||
avoid algorithms that depend on precise mouse-event sequences. For
|
||||
example, a mouse tracking handler should reset the tracking state
|
||||
when it receives an event other than a dragging event.}
|
||||
|
||||
@item{@index['("keyboard focus" "overview")]{@index['("keyboard
|
||||
events" "overview")]{The}} receiving window of a keyboard event is
|
||||
the window that owns the @deftech{keyboard focus} at the time of the
|
||||
event. Only one window owns the focus at any time, and focus
|
||||
ownership is typically displayed by a window in some manner. For
|
||||
example, a text field control shows focus ownership by displaying a
|
||||
blinking caret.
|
||||
|
||||
Within a top-level window, only certain kinds of subwindows can have
|
||||
the focus, depending on the conventions of the platform. Furthermore,
|
||||
the subwindow that initially owns the focus is platform-specific. A
|
||||
user can moves the focus in various ways, usually by clicking the
|
||||
target window. A program can use the @method[window<%> focus] method
|
||||
to move the focus to a subwindow or to set the initial focus.
|
||||
|
||||
Under X, a @indexed-scheme['wheel-up] or @indexed-scheme['wheel-down]
|
||||
event may be sent to a window other than the one with the keyboard
|
||||
focus, because X generates wheel events based on the location of the
|
||||
mouse pointer.
|
||||
|
||||
A key-press event may correspond to either an actual key press or an
|
||||
auto-key repeat. Multiple key-press events without intervening
|
||||
key-release events normally indicate an auto-key. Like any input
|
||||
event, however, key-release events sometimes get dropped (e.g., due
|
||||
to the appearance of a modal dialog).}
|
||||
|
||||
}
|
||||
|
||||
Controls, such as buttons and list boxes, handle keyboard and mouse
|
||||
events automatically, eventually invoking the callback procedure that
|
||||
was provided when the control was created. A canvas propagates mouse
|
||||
and keyboard events to its @method[canvas<%> on-event] and
|
||||
@method[canvas<%> on-char] methods, respectively.
|
||||
|
||||
@index['("events" "delivery")]{A} mouse and keyboard event is
|
||||
delivered in a special way to its window. Each ancestor of the
|
||||
receiving window gets a chance to intercept the event through the
|
||||
@method[window<%> on-subwindow-event] and @method[window<%>
|
||||
on-subwindow-char] methods. See the method descriptions for more
|
||||
information.
|
||||
|
||||
@index['("keyboard focus" "navigation")]{The} default
|
||||
@method[window<%> on-subwindow-char] method for a top-level window
|
||||
intercepts keyboard events to detect menu-shortcut events and
|
||||
focus-navigation events. See @xmethod[frame% on-subwindow-char] and
|
||||
@xmethod[dialog% on-subwindow-char] for details. Certain OS-specific
|
||||
key combinations are captured at a low level, and cannot be
|
||||
overridden. For example, under Windows and X, pressing and releasing
|
||||
Alt always moves the keyboard focus to the menu bar. Similarly,
|
||||
Alt-Tab switches to a different application under Windows. (Alt-Space
|
||||
invokes the system menu under Windows, but this shortcut is
|
||||
implemented by @method[top-level-window<%> on-system-menu-char],
|
||||
which is called by @xmethod[frame% on-subwindow-char] and
|
||||
@xmethod[dialog% on-subwindow-char].)
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
|
||||
@section[#:tag "mr:eventspaceinfo"]{Event Dispatching and Eventspaces}
|
||||
|
||||
@section-index['("events" "dispatching")]
|
||||
|
||||
A graphical user interface is an inherently multi-threaded system: one
|
||||
thread is the program managing windows on the screen, and the other
|
||||
thread is the user moving the mouse and typing at the keyboard. GUI
|
||||
programs typically use an @deftech{event queue} to translate this
|
||||
multi-threaded system into a sequential one, at least from the
|
||||
programmer's point of view. Each user action is handled one at a
|
||||
time, ignoring further user actions until the previous one is
|
||||
completely handled. The conversion from a multi-threaded process to a
|
||||
single-threaded one greatly simplifies the implementation of GUI
|
||||
programs.
|
||||
|
||||
Despite the programming convenience provided by a purely sequential
|
||||
event queue, certain situations require a less rigid dialog with
|
||||
the user:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@italic{Nested event handling:} In the process of handling an
|
||||
event, it may be necessary to obtain further information from the
|
||||
user. Usually, such information is obtained via a modal dialog; in
|
||||
whatever fashion the input is obtained, more user events must be
|
||||
received and handled before the original event is completely
|
||||
handled. To allow the further processing of events, the handler for
|
||||
the original event must explicitly @deftech{yield} to the
|
||||
system. Yielding causes events to be handled in a nested manner,
|
||||
rather than in a purely sequential manner.}
|
||||
|
||||
@item{@italic{Asynchronous event handling:} An application may
|
||||
consist of windows that represent independent dialogs with the
|
||||
user. For example, a drawing program might support multiple drawing
|
||||
windows, and a particularly time-consuming task in one window (e.g.,
|
||||
a special filter effect on an image) should not prevent the user from
|
||||
working in a different window. Such an application needs sequential
|
||||
event handling for each individual window, but asynchronous
|
||||
(potentially parallel) event handling across windows. In other words,
|
||||
the application needs a separate event queue for each window, and a
|
||||
separate event-handling thread for each event queue.}
|
||||
|
||||
}
|
||||
|
||||
In MrEd, an @deftech{eventspace} is a context for processing GUI
|
||||
events. Each eventspace maintains its own queue of events, and events
|
||||
in a single eventspace are dispatched sequentially by a designated
|
||||
@deftech{handler thread}. An event-handling procedure running in this
|
||||
handler thread can yield to the system by calling @scheme[yield], in
|
||||
which case other event-handling procedures may be called in a nested
|
||||
(but single-threaded) manner within the same handler thread. Events
|
||||
from different eventspaces are dispatched asynchronously by separate
|
||||
handler threads.
|
||||
|
||||
@index['("dialogs" "modal")]{When} a frame or dialog is created
|
||||
without a parent, it is associated with the @tech{current eventspace}
|
||||
as described in @secref["mr:currenteventspace"]. Events for a
|
||||
top-level window and its descendants are always dispatched in the
|
||||
window's eventspace. Every dialog is modal; a dialog's
|
||||
@method[dialog% show] method implicitly calls @scheme[yield] to
|
||||
handle events while the dialog is shown. (See also
|
||||
@secref["mr:espacethreads"] for information about threads and modal
|
||||
dialogs.) Furthermore, when a modal dialog is shown, the system
|
||||
disables all other top-level windows in the dialog's eventspace, but
|
||||
windows in other eventspaces are unaffected by the modal dialog.
|
||||
(Disabling a window prevents mouse and keyboard events from reaching
|
||||
the window, but other kinds of events, such as update events, are
|
||||
still delivered.)
|
||||
|
||||
|
||||
@subsection{Event Types and Priorities}
|
||||
|
||||
@section-index['("events" "timer")]
|
||||
@section-index['("events" "explicitly queued")]
|
||||
|
||||
In addition to events corresponding to user and windowing actions,
|
||||
such as button clicks, key presses, and updates, the system
|
||||
dispatches two kinds of internal events: @tech{timer events} and
|
||||
@tech{explicitly queued events}.
|
||||
|
||||
@tech{Timer events} are created by instances of @scheme[timer%]. When
|
||||
a timer is started and then expires, the timer queues an event to
|
||||
call the timer's @method[timer% notify] method. Like a top-level
|
||||
window, each timer is associated with a particular eventspace (the
|
||||
@tech{current eventspace} as described in
|
||||
@secref["mr:currenteventspace"]) when it is created, and the timer
|
||||
queues the event in its eventspace.
|
||||
|
||||
@deftech{Explicitly queued} events are created with
|
||||
@scheme[queue-callback], which accepts a callback procedure to handle
|
||||
the event. The event is enqueued in the current eventspace at the
|
||||
time of the call to @scheme[queue-callback], with either a high or
|
||||
low priority as specified by the (optional) second argument to
|
||||
@scheme[queue-callback].
|
||||
|
||||
An eventspace's event queue is actually a priority queue with events
|
||||
sorted according to their kind, from highest-priority (dispatched
|
||||
first) to lowest-priority (dispatched last):
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{The highest-priority events are high-priority events installed
|
||||
with @scheme[queue-callback].}
|
||||
|
||||
@item{Timer events have the second-highest priority.}
|
||||
|
||||
@item{Graphical events, such as mouse clicks or window updates, have
|
||||
the second-lowest priority.}
|
||||
|
||||
@item{The lowest-priority events are low-priority events installed
|
||||
with @scheme[queue-callback].}
|
||||
|
||||
}
|
||||
|
||||
Although a programmer has no direct control over the order in which
|
||||
events are dispatched, a programmer can control the timing of
|
||||
dispatches by setting the event dispatch handler via the
|
||||
@scheme[event-dispatch-handler] parameter. This parameter and other
|
||||
eventspace procedures are described in more detail in
|
||||
@secref["mr:eventspace-funcs"].
|
||||
|
||||
|
||||
@subsection[#:tag "mr:espacethreads"]{Eventspaces and Threads}
|
||||
|
||||
When a new eventspace is created, a corresponding @deftech{handler
|
||||
thread} is created for the eventspace. When the system dispatches an
|
||||
event for an eventspace, it always does so in the eventspace's
|
||||
handler thread. A handler procedure can create new threads that run
|
||||
indefinitely, but as long as the handler thread is running a handler
|
||||
procedure, no new events can be dispatched for the corresponding
|
||||
eventspace.
|
||||
|
||||
When a handler thread shows a dialog, the dialog's @method[dialog%
|
||||
show] method implicitly calls @scheme[yield] for as long as the
|
||||
dialog is shown. When a non-handler thread shows a dialog, the
|
||||
non-handler thread simply blocks until the dialog is
|
||||
dismissed. Calling @scheme[yield] with no arguments from a
|
||||
non-handler thread has no effect. Calling @scheme[yield] with a
|
||||
semaphore from a non-handler thread is equivalent to calling
|
||||
@scheme[semaphore-wait].
|
||||
|
||||
|
||||
@subsection[#:tag "mr:currenteventspace"]{Creating and Setting the Eventspace}
|
||||
|
||||
Whenever a frame, dialog, or timer is created, it is associated with
|
||||
the eventspace specified by the @scheme[current-eventspace] parameter
|
||||
@|SeeMzParam|. When the @scheme[current-eventspace] procedure is
|
||||
called with no arguments, it returns the current eventspace value.
|
||||
When @scheme[current-eventspace] is called with an eventspace value,
|
||||
it changes the current eventspace to the provided one.
|
||||
|
||||
The @scheme[make-eventspace] procedure creates a new
|
||||
eventspace. The following example creates a new eventspace and a new
|
||||
frame in the eventspace (the @scheme[parameterize] syntactic form
|
||||
temporary sets a parameter value):
|
||||
|
||||
@schemeblock[
|
||||
(let ([new-es (make-eventspace)])
|
||||
(parameterize ([current-eventspace new-es])
|
||||
(new frame% [label "Example"])))
|
||||
]
|
||||
|
||||
When an eventspace is created, it is placed under the management of
|
||||
the @tech{current custodian}. When a custodian shuts down an
|
||||
eventspace, all frames and dialogs associated with the eventspace are
|
||||
destroyed (without calling @method[top-level-window<%> can-close?]
|
||||
or @xmethod[top-level-window% on-close]), all timers in the
|
||||
eventspace are stopped, and all enqueued callbacks are removed.
|
||||
Attempting to create a new window, timer, or explicitly queued event
|
||||
in a shut-down eventspace raises the @scheme[exn:misc] exception.
|
||||
|
||||
An eventspace is a @techlink{synchronizable event} (not to be confused
|
||||
with a GUI event), so it can be used with @scheme[sync]. As a
|
||||
synchronizable event, an eventspace is in a blocking state when a
|
||||
frame is visible, a timer is active, a callback is queued, or a
|
||||
@scheme[menu-bar%] is created with a @scheme['root] parent. (Note
|
||||
that the blocking state of an eventspace is unrelated to whether an
|
||||
event is ready for dispatching.)
|
||||
|
||||
@subsection[#:tag "mr:evtcontjump"]{Exceptions and Continuation Jumps}
|
||||
|
||||
Whenever the system dispatches an event, the call to the handler
|
||||
procedure is wrapped so that full continuation jumps are not allowed
|
||||
to escape from the dispatch, and escape continuation jumps are
|
||||
blocked at the dispatch site. The following @scheme[block] procedure
|
||||
illustrates how the system blocks escape continuation jumps:
|
||||
|
||||
@def+int[
|
||||
(define (block f)
|
||||
(code:comment #, @t{calls @scheme[f] and returns void if @scheme[f] tries to escape})
|
||||
(let ([done? #f])
|
||||
(let/ec k
|
||||
(dynamic-wind
|
||||
void
|
||||
(lambda () (begin0 (f) (set! done? #t)))
|
||||
(lambda () (unless done? (k (void))))))))
|
||||
|
||||
(block (lambda () 5))
|
||||
(let/ec k (block (lambda () (k 10))))
|
||||
(let/ec k ((lambda () (k 10))) 11)
|
||||
(let/ec k (block (lambda () (k 10))) 11)
|
||||
]
|
||||
|
||||
Calls to the event dispatch handler are also protected with
|
||||
@scheme[block].
|
||||
|
||||
This blocking of continuation jumps complicates the interaction
|
||||
between @scheme[with-handlers] and @scheme[yield] (or the default
|
||||
event dispatch handler). For example, in evaluating the expression
|
||||
|
||||
@schemeblock[
|
||||
(with-handlers ([(lambda (x) #t)
|
||||
(lambda (x) (error "error during yield"))])
|
||||
(yield))
|
||||
]
|
||||
|
||||
the @scheme["error during yield"] handler is @italic{never} called,
|
||||
even if a callback procedure invoked by @scheme[yield] raises an
|
||||
exception. The @scheme[with-handlers] expression installs an
|
||||
exception handler that tries to jump back to the context of the
|
||||
@scheme[with-handlers] expression before invoking a handler
|
||||
procedure; this jump is blocked by the dispatch within
|
||||
@scheme[yield], so @scheme["error during yield"] is never
|
||||
printed. Exceptions during @scheme[yield] are ``handled'' in the
|
||||
sense that control jumps out of the event handler, but @scheme[yield]
|
||||
may dispatch another event rather than escaping or returning.
|
||||
|
||||
The following expression demonstrates a more useful way to handle
|
||||
exceptions within @scheme[yield], for the rare cases where
|
||||
such handling is useful:
|
||||
|
||||
@schemeblock[
|
||||
(let/ec k
|
||||
(call-with-exception-handler
|
||||
(lambda (x)
|
||||
(error "error during yield")
|
||||
(k))
|
||||
(lambda ()
|
||||
(yield))))
|
||||
]
|
||||
|
||||
This expression installs an exception handler that prints an error
|
||||
message @italic{before} trying to escape. Like the continuation escape
|
||||
associated with @scheme[with-handlers], the escape to @scheme[k] never
|
||||
succeeds. Nevertheless, if an exception is raised by an event
|
||||
handler during the call to @scheme[yield], an error message is
|
||||
printed before control returns to the event dispatcher within
|
||||
@scheme[yield].
|
|
@ -1,151 +1,11 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require["common.ss"]
|
||||
@require["diagrams.ss"]
|
||||
|
||||
@title[#:tag "mr:windowing" #:style 'toc]{Windowing Toolbox}
|
||||
|
||||
The windowing toolbox.
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@require["area-intf.scrbl"]
|
||||
@require["area-container-intf.scrbl"]
|
||||
@require["area-container-window-intf.scrbl"]
|
||||
@require["button-class.scrbl"]
|
||||
@require["canvas-intf.scrbl"]
|
||||
@require["canvas-class.scrbl"]
|
||||
@require["check-box-class.scrbl"]
|
||||
@require["choice-class.scrbl"]
|
||||
@require["clipboard-client-class.scrbl"]
|
||||
@require["clipboard-intf.scrbl"]
|
||||
@require["combo-field-class.scrbl"]
|
||||
@require["control-intf.scrbl"]
|
||||
@require["control-event-class.scrbl"]
|
||||
@require["cursor-class.scrbl"]
|
||||
@require["dialog-class.scrbl"]
|
||||
@require["event-class.scrbl"]
|
||||
@require["frame-class.scrbl"]
|
||||
@require["gauge-class.scrbl"]
|
||||
@require["group-box-panel-class.scrbl"]
|
||||
@require["grow-box-spacer-pane-class.scrbl"]
|
||||
@require["horizontal-pane-class.scrbl"]
|
||||
@require["horizontal-panel-class.scrbl"]
|
||||
@require["key-event-class.scrbl"]
|
||||
@require["labelled-menu-item-intf.scrbl"]
|
||||
@require["list-box-class.scrbl"]
|
||||
@require["list-control-intf.scrbl"]
|
||||
@require["menu-class.scrbl"]
|
||||
@require["menu-bar-class.scrbl"]
|
||||
@require["menu-item-intf.scrbl"]
|
||||
@require["menu-item-class.scrbl"]
|
||||
@require["menu-item-container-intf.scrbl"]
|
||||
@require["message-class.scrbl"]
|
||||
@require["mouse-event-class.scrbl"]
|
||||
@require["pane-class.scrbl"]
|
||||
@require["panel-class.scrbl"]
|
||||
@require["subarea-intf.scrbl"]
|
||||
@require["subwindow-intf.scrbl"]
|
||||
@require["top-level-window-intf.scrbl"]
|
||||
@require["vertical-pane-class.scrbl"]
|
||||
@require["vertical-panel-class.scrbl"]
|
||||
@require["window-intf.scrbl"]
|
||||
|
||||
@include-class[area<%>]
|
||||
@include-class[area-container<%>]
|
||||
@include-class[area-container-window<%>]
|
||||
@include-class[button%]
|
||||
@include-class[canvas<%>]
|
||||
@include-class[canvas%]
|
||||
@include-class[check-box%]
|
||||
@include-class[choice%]
|
||||
@include-class[clipboard-client%]
|
||||
@include-class[clipboard<%>]
|
||||
@include-class[combo-field%]
|
||||
@include-class[control<%>]
|
||||
@include-class[control-event%]
|
||||
@include-class[cursor%]
|
||||
@include-class[dialog%]
|
||||
@include-class[event%]
|
||||
@include-class[frame%]
|
||||
@include-class[gauge%]
|
||||
@include-class[group-box-panel%]
|
||||
@include-class[grow-box-spacer-pane%]
|
||||
@include-class[horizontal-pane%]
|
||||
@include-class[horizontal-panel%]
|
||||
@include-class[key-event%]
|
||||
@include-class[labelled-menu-item<%>]
|
||||
@include-class[list-control<%>]
|
||||
@include-class[list-box%]
|
||||
@include-class[menu%]
|
||||
@include-class[menu-bar%]
|
||||
@include-class[menu-item<%>]
|
||||
@include-class[menu-item%]
|
||||
@include-class[menu-item-container<%>]
|
||||
@include-class[message%]
|
||||
@include-class[mouse-event%]
|
||||
@include-class[pane%]
|
||||
@include-class[panel%]
|
||||
@include-class[subarea<%>]
|
||||
@include-class[subwindow<%>]
|
||||
@include-class[top-level-window<%>]
|
||||
@include-class[vertical-pane%]
|
||||
@include-class[vertical-panel%]
|
||||
@include-class[window<%>]
|
||||
|
||||
@include-section["dialog-funcs.scrbl"]
|
||||
@include-section["eventspace-funcs.scrbl"]
|
||||
@include-section["system-menu-funcs.scrbl"]
|
||||
@include-section["miscwin-funcs.scrbl"]
|
||||
|
||||
@;{
|
||||
@require["button-class.scrbl"]
|
||||
@require["canvas-intf.scrbl"]
|
||||
@require["canvas-class.scrbl"]
|
||||
@require["check-box-class.scrbl"]
|
||||
@require["list-control-intf.scrbl"]
|
||||
@require["choice-class.scrbl"]
|
||||
@require["control-event-class.scrbl"]
|
||||
@require["scroll-event-class.scrbl"]
|
||||
@require["cursor-class.scrbl"]
|
||||
@require["dialog-class.scrbl"]
|
||||
@require["event-class.scrbl"]
|
||||
@require["top-level-window-intf.scrbl"]
|
||||
@require["frame-class.scrbl"]
|
||||
@require["gauge-class.scrbl"]
|
||||
@require["control-intf.scrbl"]
|
||||
@require["key-event-class.scrbl"]
|
||||
@require["list-box-class.scrbl"]
|
||||
@require["menu-item-intf.scrbl"]
|
||||
@require["separator-menu-item-class.scrbl"]
|
||||
@require["labelled-menu-item-intf.scrbl"]
|
||||
@require["selectable-menu-item-intf.scrbl"]
|
||||
@require["menu-item-class.scrbl"]
|
||||
@require["checkable-menu-item-class.scrbl"]
|
||||
@require["menu-item-container-intf.scrbl"]
|
||||
@require["menu-class.scrbl"]
|
||||
@require["popup-menu-class.scrbl"]
|
||||
@require["menu-bar-class.scrbl"]
|
||||
@require["message-class.scrbl"]
|
||||
@require["mouse-event-class.scrbl"]
|
||||
@require["panel-class.scrbl"]
|
||||
@require["horizontal-panel-class.scrbl"]
|
||||
@require["vertical-panel-class.scrbl"]
|
||||
@require["tab-panel-class.scrbl"]
|
||||
@require["group-box-panel-class.scrbl"]
|
||||
@require["pane-class.scrbl"]
|
||||
@require["horizontal-pane-class.scrbl"]
|
||||
@require["vertical-pane-class.scrbl"]
|
||||
@require["grow-box-spacer-pane-class.scrbl"]
|
||||
@require["area-container-window-intf.scrbl"]
|
||||
@require["radio-box-class.scrbl"]
|
||||
@require["slider-class.scrbl"]
|
||||
@require["text-field-class.scrbl"]
|
||||
@require["combo-field-class.scrbl"]
|
||||
@require["timer-class.scrbl"]
|
||||
@require["area-intf.scrbl"]
|
||||
@require["area-container-intf.scrbl"]
|
||||
@require["subarea-intf.scrbl"]
|
||||
@require["window-intf.scrbl"]
|
||||
@require["subwindow-intf.scrbl"]
|
||||
@require["clipboard-intf.scrbl"]
|
||||
@require["clipboard-client-class.scrbl"]
|
||||
}
|
||||
@include-section["win-overview.scrbl"]
|
||||
@include-section["win-classes.scrbl"]
|
||||
@include-section["win-funcs.scrbl"]
|
||||
|
|
Loading…
Reference in New Issue
Block a user