From c7c3d60b1666fcd4b1dba547bb7c64e7d61447ac Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 17 Aug 2007 16:19:31 +0000 Subject: [PATCH] checkpoint new GUI toolbox docs svn: r7109 --- collects/scribble/html-render.ss | 10 + collects/scribble/manual.ss | 36 +- collects/scribblings/gui/add-color-intf.scrbl | 78 + collects/scribblings/gui/bitmap-class.scrbl | 250 ++ .../scribblings/gui/bitmap-dc-class.scrbl | 170 ++ collects/scribblings/gui/blurbs.ss | 13 +- collects/scribblings/gui/brush-class.scrbl | 213 ++ .../scribblings/gui/brush-list-class.scrbl | 40 + collects/scribblings/gui/color-class.scrbl | 70 + .../scribblings/gui/color-database-intf.scrbl | 211 ++ collects/scribblings/gui/dc-intf.scrbl | 909 +++++++ collects/scribblings/gui/dc-path-class.scrbl | 261 ++ collects/scribblings/gui/draw-classes.scrbl | 49 + collects/scribblings/gui/draw-funcs.scrbl | 11 + .../scribblings/gui/draw-list-funcs.scrbl | 36 + collects/scribblings/gui/draw-overview.scrbl | 2 +- collects/scribblings/gui/drawing.scrbl | 9 - collects/scribblings/gui/editor-classes.scrbl | 44 + collects/scribblings/gui/editor-intf.scrbl | 2361 +++++++++++++++++ .../scribblings/gui/editor-overview.scrbl | 752 ++++++ collects/scribblings/gui/font-class.scrbl | 226 ++ collects/scribblings/gui/font-funcs.scrbl | 77 + .../scribblings/gui/font-list-class.scrbl | 42 + .../gui/font-name-directory-intf.scrbl | 215 ++ .../scribblings/gui/gl-config-class.scrbl | 113 + .../scribblings/gui/gl-context-intf.scrbl | 98 + .../scribblings/gui/global-draw-funcs.scrbl | 100 + collects/scribblings/gui/gui.scrbl | 65 +- collects/scribblings/gui/guide.scrbl | 58 + collects/scribblings/gui/pen-class.scrbl | 243 ++ collects/scribblings/gui/pen-list-class.scrbl | 45 + collects/scribblings/gui/point-class.scrbl | 41 + .../gui/post-script-dc-class.scrbl | 58 + .../scribblings/gui/post-script-funcs.scrbl | 25 + .../scribblings/gui/printer-dc-class.scrbl | 33 + collects/scribblings/gui/ps-setup-class.scrbl | 273 ++ .../gui/{windowing.scrbl => reference.scrbl} | 7 +- collects/scribblings/gui/region-class.scrbl | 268 ++ collects/scribblings/gui/win-funcs.scrbl | 2 +- collects/scribblings/gui/win-overview.scrbl | 4 +- collects/tests/mzscheme/filelib.ss | 13 +- 41 files changed, 7428 insertions(+), 103 deletions(-) create mode 100644 collects/scribblings/gui/add-color-intf.scrbl create mode 100644 collects/scribblings/gui/bitmap-class.scrbl create mode 100644 collects/scribblings/gui/bitmap-dc-class.scrbl create mode 100644 collects/scribblings/gui/brush-class.scrbl create mode 100644 collects/scribblings/gui/brush-list-class.scrbl create mode 100644 collects/scribblings/gui/color-class.scrbl create mode 100644 collects/scribblings/gui/color-database-intf.scrbl create mode 100644 collects/scribblings/gui/dc-intf.scrbl create mode 100644 collects/scribblings/gui/dc-path-class.scrbl create mode 100644 collects/scribblings/gui/draw-classes.scrbl create mode 100644 collects/scribblings/gui/draw-funcs.scrbl create mode 100644 collects/scribblings/gui/draw-list-funcs.scrbl delete mode 100644 collects/scribblings/gui/drawing.scrbl create mode 100644 collects/scribblings/gui/editor-classes.scrbl create mode 100644 collects/scribblings/gui/editor-intf.scrbl create mode 100644 collects/scribblings/gui/editor-overview.scrbl create mode 100644 collects/scribblings/gui/font-class.scrbl create mode 100644 collects/scribblings/gui/font-funcs.scrbl create mode 100644 collects/scribblings/gui/font-list-class.scrbl create mode 100644 collects/scribblings/gui/font-name-directory-intf.scrbl create mode 100644 collects/scribblings/gui/gl-config-class.scrbl create mode 100644 collects/scribblings/gui/gl-context-intf.scrbl create mode 100644 collects/scribblings/gui/global-draw-funcs.scrbl create mode 100644 collects/scribblings/gui/guide.scrbl create mode 100644 collects/scribblings/gui/pen-class.scrbl create mode 100644 collects/scribblings/gui/pen-list-class.scrbl create mode 100644 collects/scribblings/gui/point-class.scrbl create mode 100644 collects/scribblings/gui/post-script-dc-class.scrbl create mode 100644 collects/scribblings/gui/post-script-funcs.scrbl create mode 100644 collects/scribblings/gui/printer-dc-class.scrbl create mode 100644 collects/scribblings/gui/ps-setup-class.scrbl rename collects/scribblings/gui/{windowing.scrbl => reference.scrbl} (52%) create mode 100644 collects/scribblings/gui/region-class.scrbl diff --git a/collects/scribble/html-render.ss b/collects/scribble/html-render.ss index f9783ba465..0aad6228ad 100644 --- a/collects/scribble/html-render.ss +++ b/collects/scribble/html-render.ss @@ -314,6 +314,16 @@ [else (error 'html-render "unrecognized style symbol: ~e" style)])] [(string? style) `((span ([class ,style]) ,@(super render-element e part ht)))] + [(and (pair? style) + (eq? (car style) 'show-color)) + `((font ((style ,(format "background-color: ~a" + (apply string-append "#" + (map (lambda (v) (let ([s (format "0~x" v)]) + (substring s (- (string-length s) 2)))) + (cdr style)))))) + (tt nbsp nbsp nbsp nbsp nbsp)) + nbsp + ,@(super render-element e part ht))] [(target-url? style) (if (current-no-links) (super render-element e part ht) diff --git a/collects/scribble/manual.ss b/collects/scribble/manual.ss index 076bb0e382..7a543152e3 100644 --- a/collects/scribble/manual.ss +++ b/collects/scribble/manual.ss @@ -480,6 +480,20 @@ (define max-proto-width 65) + (define (name-this-object type-sym) + (to-element + (string->symbol + (regexp-replace + #rx"(%|<%>|-mixin)$" + (format "_a~a-~s" + (if (member + (string-ref (symbol->string type-sym) 0) + '(#\a #\e #\i #\o #\u)) + "n" + "") + type-sym) + "")))) + (define (*defproc mode within-id stx-ids prototypes arg-contractss result-contracts content-thunk) (let ([spacer (hspace 1)] @@ -564,17 +578,7 @@ (make-element #f (list (scheme send) (hspace 1) - (to-element (string->symbol - (regexp-replace - #rx"(%|<%>|-mixin)$" - (format "a~a-~s" - (if (member - (string-ref (symbol->string (syntax-e within-id)) 0) - '(#\a #\e #\i #\o #\u)) - "n" - "") - (syntax-e within-id)) - ""))) + (name-this-object (syntax-e within-id)) (hspace 1) (if first? (let* ([mname (car prototype)] @@ -1225,6 +1229,7 @@ defmethod* methspec methimpl + this-obj include-class) (define-syntax-parameter current-class #f) @@ -1417,5 +1422,14 @@ (syntax-rules () [(_ body ...) (make-spec (lambda () (list (italic "Specification:") body ...)))])) + (define (*this-obj cname) + (name-this-object cname)) + + (define-syntax (this-obj stx) + (syntax-case stx () + [(_) + (with-syntax ([cname (syntax-parameter-value #'current-class)]) + #'(*this-obj 'cname))])) + ;; ---------------------------------------- ) diff --git a/collects/scribblings/gui/add-color-intf.scrbl b/collects/scribblings/gui/add-color-intf.scrbl new file mode 100644 index 0000000000..8640c47f17 --- /dev/null +++ b/collects/scribblings/gui/add-color-intf.scrbl @@ -0,0 +1,78 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@definterface[add-color<%> ()]{ + +An @scheme[add-color<%>] object is used to additively change the RGB + values of a @scheme[color%] object. An @scheme[add-color<%>] object + only exists within a @scheme[style-delta%] object. + +See also @method[style-delta% get-foreground-add] and + @method[style-delta% get-background-add]. + + + +@defmethod[(get [r (box/c (integer-in -1000 1000))] + [g (box/c (integer-in -1000 1000))] + [b (box/c (integer-in -1000 1000))]) + void?]{ + +Gets all of the additive values. + +@boxisfill[(scheme r) @elem{the additive value for the red component of the color}] +@boxisfill[(scheme g) @elem{the additive value for the green component of the color}] +@boxisfill[(scheme b) @elem{the additive value for the blue component of the color}] + +} + +@defmethod[(get-b) + (integer-in -1000 1000)]{ + +Gets the additive value for the blue component of the color. + +} + +@defmethod[(get-g) + (integer-in -1000 1000)]{ + +Gets the additive value for the green component of the color. + +} + +@defmethod[(get-r) + (integer-in -1000 1000)]{ + +Gets the additive value for the red component of the color. + +} + +@defmethod[(set [r (integer-in -1000 1000)] + [g (integer-in -1000 1000)] + [b (integer-in -1000 1000)]) + void?]{ + +Sets all of the additive values. + +} + +@defmethod[(set-b [v (integer-in -1000 1000)]) + void?]{ + +Sets the additive value for the blue component of the color. + +} + +@defmethod[(set-g [v (integer-in -1000 1000)]) + void?]{ + +Sets the additive value for the green component of the color. + +} + +@defmethod[(set-r [v (integer-in -1000 1000)]) + void?]{ + +Sets the additive value for the red component of the color. + +}} + diff --git a/collects/scribblings/gui/bitmap-class.scrbl b/collects/scribblings/gui/bitmap-class.scrbl new file mode 100644 index 0000000000..6a4a347089 --- /dev/null +++ b/collects/scribblings/gui/bitmap-class.scrbl @@ -0,0 +1,250 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[bitmap% object% ()]{ + +A @scheme[bitmap%] object is a pixel-based image, either + monochrome or color. + +Sometimes, a bitmap object creation fails in a low-level manner. In + that case, the @method[bitmap% ok?] method returns @scheme[#f], and + the bitmap cannot be supplied to methods that consume or operate on + bitmaps (otherwise, @|MismatchExn|). + + +@defconstructor*/make[(([width (integer-in 1 10000)] + [height (integer-in 1 10000)] + [monochrome? any/c #f]) + ([filename path-string?] + [kind (one-of/c 'unknown 'unknown/mask + 'gif 'gif/mask 'jpeg 'png 'png/mask + 'xbm 'xpm 'bmp 'pict) + 'unknown] + [bg-color (or/c (is-a?/c color%) false/c) #f]) + ([bits bytes?] + [width (integer-in 1 10000)] + [height (integer-in 1 10000)]))]{ + +When @scheme[with] and @scheme[height] are provided: Creates a new + bitmap. If @scheme[monochrome?] is @scheme[#f], the bitmap matches + the display depth of the screen. The initial content of the bitmap is + undefined. + +When @scheme[filename] is provided: Creates a bitmap from a file, + where @scheme[kind] specifies the kind of image file. See + @method[bitmap% load-file] for details. + + +When a @scheme[bits] byte string is provided: Creates a monochrome + bitmap from an array of bit values, where each byte in @scheme[bits] + specifies eight bits, and padding bits are added so that each bitmap + line starts on a character boundary. A @scheme[1] bit value indicates + black, and @scheme[0] indicates white. If @scheme[width] times + @scheme[height] is larger than 8 times the length of @scheme[bits], + @|MismatchExn|. + + +} + +@defmethod[(get-argb-pixels [x real?] + [y real?] + [width (integer-in 1 10000)] + [height (integer-in 1 10000)] + [pixels (and/c byte-string? mutable?)] + [alpha? any/c @scheme[#f]]) + void?]{ + +Produces the same result as @xmethod[bitmap-dc% get-pixel] with the +bitmap selected into the DC, but the bitmap does not have to be +selected anywhere (and this method works even if the bitmap is +selected into another DC, attached as a button label, etc.). + +} + +@defmethod[(get-depth) + nonnegative-exact-integer?]{ + +Gets the color depth of the bitmap. See also @method[bitmap% +is-color?]. + +} + +@defmethod[(get-gl-config [config (is-a?/c gl-config%)]) + void?]{ + +Returns a copy of this bitmap's requested OpenGL configuration. See + also @method[bitmap% set-gl-config]. + +} + +@defmethod[(get-height) + (integer-in 1 10000)]{ + +Gets the height of the bitmap in pixels. + +} + +@defmethod[(get-loaded-mask) + (or/c (is-a?/c bitmap%) false/c)]{ + +Returns a mask bitmap that is stored with this bitmap. + +When a GIF file is loaded with @scheme['gif/mask] or + @scheme['unknown/mask] and the file contains a transparent ``color,'' + a mask bitmap is generated to identify the transparent pixels. The + mask bitmap is monochrome, with white pixels where the loaded bitmap + is transparent and black pixels everywhere else. + +When a PNG file is loaded with @scheme['png/mask] or + @scheme['unknown/mask] and the file contains a mask or alpha channel, + a mask bitmap is generated to identify the mask or alpha channel. If + the file contains a mask or an alpha channel with only extreme + values, the mask bitmap is monochrome, otherwise it is grayscale + (representing the alpha channel inverted). + +The mast bitmap is @italic{not} used automatically by drawing + routines. The mask bitmap can be extracted and supplied explicitly as + a mask (e.g., as the sixth argument to @method[dc<%> + draw-bitmap]). The mask bitmap is used by @method[bitmap% save-file] + when saving a bitmap as @scheme['png] if the mask has the same + dimensions as the saved bitmap. The mask bitmap is also used + automatically when the bitmap is a control label. + +} + +@defmethod[(get-width) + (integer-in 1 10000)]{ + +Gets the width of the bitmap in pixels. + +} + +@defmethod[(is-color?) + boolean?]{ + +Returns @scheme[#f] if the bitmap is monochrome, @scheme[#t] otherwise. + +} + +@defmethod[(load-file [name pat-string?] + [kind (one-of/c 'unknown 'unknown/mask + 'gif 'gif/mask 'jpeg 'png 'png/mask + 'xbm 'xpm 'bmp 'pict) + 'unknown] + [bg-color (or/c (is-a?/c color%) false/c) #f]) + boolean?]{ + +Loads a bitmap from a file. If the bitmap is in use by a + @scheme[bitmap-dc%] object or a control, the bitmap file is not + loaded. The bitmap changes its size and depth to match that of + the loaded image. + +The @scheme[kind] argument specifies the file's format: + +@itemize{ +@item{@scheme['unknown] --- examine the file to determine its format} +@item{@scheme['unknown/mask] --- like @scheme['unknown], but see @method[bitmap% get-loaded-mask]} +@item{@scheme['gif] --- load a GIF bitmap file (X, Windows, Mac OS X)} +@item{@scheme['gif/mask] --- like @scheme['gif], but see @method[bitmap% get-loaded-mask] (X, Windows, Mac OS X)} +@item{@scheme['jpeg] --- load a JPEG bitmap file (X, Windows, Mac OS X)} +@item{@scheme['png] --- load a PNG bitmap file (X, Windows, Mac OS X)} +@item{@scheme['png/mask] --- like @scheme['png], but see @method[bitmap% get-loaded-mask] (X, Windows, Mac OS X)} +@item{@scheme['xbm] --- load an X bitmap file (X, Windows, Mac OS X); creates a monochrome bitmap} +@item{@scheme['xpm] --- load an XPM bitmap file (X, Windows, Mac OS X)} +@item{@scheme['bmp] --- load a Windows bitmap file (X, Windows, Mac OS X)} +@item{@scheme['pict] --- load a PICT bitmap file (Mac OS X)} +} + +An XBM image is always loaded as a monochrome bitmap. A 1-bit + grayscale PNG without a mask or alpha channel is also loaded as a + monochrome bitmap. An image in any other format is always loaded as a + bitmap that matches the depth of the screen. + +For PNG loading, if @scheme[bg-color] is not @scheme[#f], then it is + combined with the file's alpha channel or mask (if any) while loading + the image; in this case, no separate mask bitmap is generated, even + if @scheme['unknown/mask] or @scheme['png/mask] is specified for the + format. If the format is specified as @scheme['unknown] or + @scheme['png] and @scheme[bg-color] is not specified, the PNG file is + consulted for a background color to use for loading, and white is + used if no background color is indicated in the file. + +@index["gamma correction"]{In} all PNG-loading modes, gamma correction + is applied when the file provides a gamma value, otherwise gamma + correction is not applied. The current display's gamma factor is + determined by the @ResourceFirst{gamma} (see @|mrprefsdiscuss|) if it + is set, or else by the @indexed-envvar{SCREEN_GAMMA} environment + variable if it is defined. If the preference and environment variable + are both undefined, a platform-specific default is used. + +} + +@defmethod[(ok?) + boolean?]{ + +Returns @scheme[#t] if the bitmap is usable (created or changed + successfully). If @scheme[#f] is returned, the bitmap cannot be + supplied to methods that consume or operate on bitmaps (otherwise, + @|MismatchExn|). + +} + +@defmethod[(save-file [name pat-string?] + [kind (one-of/c 'png 'jpeg 'xbm 'xpm 'bmp)] + [quality (integer-in 0 100) 75]) + boolean?]{ + +Saves a bitmap in the named file. + +The @scheme[kind] argument determined the type of file that is created, + one of: + +@itemize{ + + @item{@scheme['png] --- save a PNG file (X, Windows, Mac OS X)} + + @item{@scheme['jpeg] --- save a JPEG file (X, Windows, Mac OS X)} + + @item{@scheme['xbm] --- save an X bitmap file (X, Windows, Mac OS X)} + + @item{@scheme['xpm] --- save an XPM bitmap file (X, Windows, Mac OS X)} + + @item{@scheme['bmp] --- save a Windows bitmap file (Windows)} + +} + +The @scheme[quality] argument is used only for saving as @scheme['jpeg], in + which case it specifies the trade-off between image precision (high + quality matches the content of the @scheme[bitmap%] object more + precisely) and size (low quality is smaller). + +When saving as @scheme['png], if @method[bitmap% get-loaded-mask] +returns a bitmap of the same size as this one, a grayscale version is +included in the PNG file as the alpha channel. + +A monochrome bitmap saved as @scheme['png] without a mask bitmap + produces a 1-bit grayscale PNG file (which , when read with + @method[bitmap% load-file], creates a monochrome @scheme[bitmap%] + object.) + +} + +@defmethod[(set-gl-config [config (is-a?/c gl-config%)]) + void?]{ + +Sets the requested OpenGL configuration for this bitmap. The + configuration is used when the bitmap selected into a drawing + context, and then a GL context is created for the drawing context. + +The given @scheme[gl-config%] object is copied, so that changes to + the object do not affect the bitmap's configuration. + +} + +@defmethod[(set-loaded-mask [mask (or/c (is-a?/c bitmap%) false/c)]) + void?]{ + +See @method[bitmap% get-loaded-mask]. + +}} + diff --git a/collects/scribblings/gui/bitmap-dc-class.scrbl b/collects/scribblings/gui/bitmap-dc-class.scrbl new file mode 100644 index 0000000000..9fbd64b578 --- /dev/null +++ b/collects/scribblings/gui/bitmap-dc-class.scrbl @@ -0,0 +1,170 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[bitmap-dc% object% (dc<%>)]{ + +A @scheme[bitmap-dc%] object allows drawing directly into a bitmap. A + @scheme[bitmap%] object must be supplied at initialization or + installed into a bitmap DC using @method[bitmap-dc% set-bitmap] + before any other method of the DC is called, except @method[dc<%> + get-text-extent], @method[dc<%> get-char-height], or @method[dc<%> + get-char-width]. If any other @scheme[bitmap-dc%] method is called + before a bitmap is selected, the method call is ignored. + +Drawing to a @scheme[bitmap-dc%] with a color bitmap is guaranteed to + produce the same result as drawing into a @scheme[canvas%] instance + (with appropriate clipping and offsets). Thus, a @scheme[bitmap-dc%] + can be used for offscreen staging of canvas content. + + +@defconstructor[([bitmap (or/c (is-a?/c bitmap%) false/c)])]{ + +Creates a new memory DC. If @scheme[bitmap] is not @scheme[#f], it is + installed into the DC so that drawing commands on the DC draw to + @scheme[bitmap]. Otherwise, no bitmap is installed into the DC and + @method[bitmap-dc% set-bitmap] must be called before any other method + of the DC is called. + +} + +@defmethod[(draw-bitmap-section-smooth [source (is-a?/c bitmap%)] + [dest-x real?] + [dest-y real?] + [dest-width (and/c real? (not/c negative?))] + [dest-height (and/c real? (not/c negative?))] + [src-x real?] + [src-y real?] + [src-width (and/c real? (not/c negative?))] + [src-height (and/c real? (not/c negative?))] + [mask (or/c (is-a?/c bitmap%) false/c)]) + boolean?]{ + +Display part of a bitmap with smooth scaling. For most platforms, this + method produces better results than adjusting the scale of a drawing + context before using @method[dc<%> draw-bitmap] and @method[dc<%> + draw-bitmap-section], but this method is much slower. + +} + +@defmethod[(get-argb-pixels [x real?] + [y real?] + [width (integer-in 1 10000)] + [height (integer-in 1 10000)] + [pixels (and/c bytes? (not/c immutable?))] + [alpha? any/c @scheme[#f]]) + void?]{ + +Gets a rectangle of pixels in the bitmap, subject to the same rules + and performance characteristics of @method[bitmap-dc% get-pixel], + except that the block get is likely to be faster than the sequence of + individual gets. Also, the @scheme[bitmap%] class also provides the + same method directly, so it is not necessary to select a bitmap into + a DC to extracts its pixel values. + +The pixel RGB values are copied into @scheme[pixels]. The first byte + represents an alpha value of the pixel at (@scheme[x], @scheme[y]), + the second byte represents a red value of the pixel at (@scheme[x], + @scheme[y]), the third byte is the blue value, etc. In this way, the + first @math{@scheme[width] * @scheme[height] *4} bytes of + @scheme[pixels] are set to reflect the current pixel values in the + DC. The pixels are in row-major order, left to right then top to + bottom. + +If @scheme[alpha?] is false, then the alpha value for each pixel is + set to 255. If @scheme[alpha?] is true, then @italic{only} the alpha + value is set for each pixel, based on each pixel's value. Thus, the + same @scheme[pixels] byte string is in general filled from two bitmaps: + one (the main image) for the pixel values and one (the mask) for the + alpha values. + +} + +@defmethod[(get-bitmap) + (or/c (is-a?/c bitmap%) false/c)]{ + +Gets the bitmap currently installed in the DC, or @scheme[#f] if no + bitmap is installed. See @method[bitmap-dc% set-bitmap] for more + information. + +} + +@defmethod[(get-pixel [x real?] + [y real?] + [color (is-a?/c color%)]) + boolean?]{ + +Fills @scheme[color] with the color of the current pixel at position +(@scheme[x], @scheme[y]) in the drawing context. If the color is +successfully obtained, the return value is @scheme[#t], otherwise the +result is @scheme[#f]. + +Under X, interleaving drawing commands with @method[bitmap-dc% +get-pixel] calls (for the same @scheme[bitmap-dc%] object) incurs a +substantial performance penalty, except for interleaved calls to +@method[bitmap-dc% set-pixel], @method[bitmap-dc% set-argb-pixels], +and @method[bitmap-dc% get-argb-pixels]. + +} + +@defmethod[(set-argb-pixels [x real?] + [y real?] + [width (integer-in 1 10000)] + [height (integer-in 1 10000)] + [pixels bytes?] + [alpha? any/c @scheme[#f]]) + void?]{ + + +Sets a rectangle of pixels in the bitmap, subject to the same + rules and performance characteristics of +@method[bitmap-dc% set-pixel], except that the block set is likely to be faster than the + sequence of individual sets. + +The pixel RGB values are taken from @scheme[pixels]. The first byte + represents an alpha value, the second byte represents a red value to + used for the pixel at (@scheme[x], @scheme[y]), the third byte is a blue + value, etc. In this way, the first + @math{@scheme[width] * @scheme[height] * 4} bytes of @scheme[pixels] + determine the new pixel values in the DC. The pixels are in row-major + order, left to right then top to bottom. + +If @scheme[alpha?] is false, then the alpha value for each pixel is + ignored. If @scheme[alpha?] is true, then @italic{only} the each + pixel is set based @italic{only} on the alpha value. Thus, the same + @scheme[pixels] byte string is in general used with two bitmaps, one + (the main image) for the pixel values and one (the mask) for the + alpha values. + +} + +@defmethod[(set-bitmap [bitmap (or/c (is-a?/c bitmap%) false/c)]) + void?]{ + +Installs a bitmap into the DC, so that drawing operations on the bitmap + DC draw to the bitmap. A bitmap is removed from a DC by setting the + bitmap to @scheme[#f]. + +A bitmap can be selected into at most one bitmap DC, and only when it + is not used by a control (as a label) or in a @scheme[pen%] or + @scheme[brush%] (as a stipple). If the argument to @method[bitmap-dc% + set-bitmap] is already in use by another DC, a control, a + @scheme[pen%], or a @scheme[brush%], @|MismatchExn|. + +} + +@defmethod[(set-pixel [x real?] + [y real?] + [color (is-a?/c color%)]) + void?]{ + +Sets a pixel in the bitmap. + +The current clipping region might not affect the pixel change. Under + X, interleaving drawing commands with @method[bitmap-dc% set-pixel] + calls (for the same @scheme[bitmap-dc%] object) incurs a substantial + performance penalty, except for interleaved calls to + @method[bitmap-dc% get-pixel], @method[bitmap-dc% get-argb-pixels], + and @method[bitmap-dc% set-argb-pixels]. + +}} + diff --git a/collects/scribblings/gui/blurbs.ss b/collects/scribblings/gui/blurbs.ss index 4c1fc526b0..db486c9624 100644 --- a/collects/scribblings/gui/blurbs.ss +++ b/collects/scribblings/gui/blurbs.ss @@ -52,12 +52,6 @@ @elem{The bitmap label is installed only if the control was originally created with a bitmap label.}) - (define (NotDCRelated) - @elem{A path is not connected to any particular @scheme[dc<%>] object, so - setting a @scheme[dc<%>] origin or scale does not affect path - operations. Instead, a @scheme[dc<%>]'s origin and scale apply at the - time that the path is drawn or used to set a region.}) - (define (popupmenuinfo what other more) (make-splice (list* @@ -250,7 +244,7 @@ information@|details|, even if the editor currently has delayed refreshing (see @elem{snip @techlink{position}})) (define (colorName name name2 r g b) - name) + (make-element `(show-color ,r ,g ,b) (list (to-element (bytes->string/latin-1 name))))) (define (Resource s) @elem{@to-element[`(quote ,(string->symbol (string-append "MrEd:" s)))] @@ -271,5 +265,10 @@ information@|details|, even if the editor currently has delayed refreshing (see "smaller" @elem{the editor is @|b|-aligned in the snip})) + (define (boxisfill which what) + @elem{The @|which| box is filled with @|what|.}) + (define (boxisfillnull which what) + @elem{The @|which| box is filled with @|what|, unless @|which| is @scheme[#f].}) + ) diff --git a/collects/scribblings/gui/brush-class.scrbl b/collects/scribblings/gui/brush-class.scrbl new file mode 100644 index 0000000000..2741c22878 --- /dev/null +++ b/collects/scribblings/gui/brush-class.scrbl @@ -0,0 +1,213 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[brush% object% ()]{ + +A brush is a drawing tool with a color and a style that is used for + filling in areas, such as the interior of a rectangle or ellipse. On + a monochrome display, all non-white brushes are drawn as black. + +In addition to its color and style, a brush can have a stipple bitmap. + This stipple is used only in unsmoothed mode (see @method[dc<%> + set-smoothing]) or in a PostScript drawing context. Painting with a + stipple brush is similar to calling @method[dc<%> draw-bitmap] with + the stipple bitmap in the filled region, except that the bitmap may + not be scaled in the same way (depending on the platform and device). + +A brush's style is one of the following: + +@itemize{ + + @item{@indexed-scheme['transparent] --- Draws with no effect (on the + interior of the drawn shape).} + + @item{@indexed-scheme['solid] --- Draws using the brush's color. If a + monochrome stipple is installed into the brush, black pixels + from the stipple are transferred to the destination using the + brush's color, and white pixels from the stipple are not + transferred.} + + @item{@indexed-scheme['opaque] --- Same as @scheme['solid], except when a + monochrome stipple is installed for unsmoothed or PostScript + drawing; in that case, white pixels from the stipple are + transferred to the destination using the destination's + background color.} + + @item{@indexed-scheme['xor] --- In a smoothing mode or if a color + stipple is installed, @scheme['xor] is treated as + @scheme['solid]. Otherwise, the brush's color or colored + (monochrome) stipple is xor-ed with existing destination pixel + values. The @scheme['xor] mapping is unspecified for arbitrary + color combinations, but the mapping provides two guarantees: + + @itemize{ + + @item{Black-and-white drawing to a color or monochrome + destination always works as expected: black xor white = black, + white xor black = black, black xor black = white, and white xor + white = white.} + + @item{Performing the same drawing operation twice in a row with + @scheme['xor] is equivalent to a no-op.} + + }} + + @item{@indexed-scheme['hilite] --- In unsmoothed mode, existing + destination pixels are ``highlighted'' in a platform-specific + way when the brush color is black. Under Windows and X for a + color drawing context, the inverted RGB components of + destination pixel are combined with the RGB components of the + system-wide highlight color using a bitwise ``or'', and the + combination is used. (Under X, the color is specified by the + @ResourceFirst{hiliteColor} preference; see @|mrprefsdiscuss|.) + Under Mac OS X for a color drawing context, the inverted RGB + components of the system-wide highlight color are subtracted + from the RGB components of each destination pixel, and the + difference (or 0 for a negative result) is used. For any + monochrome drawing context, @scheme['hilite] is the same as + @scheme['xor]. For PostScript output, @scheme['hilite] uses a + stipple that is an array of small dots (essentially a + halftone), otherwise @scheme['hilite] is treated like + @scheme['solid] in a smoothing mode.} + + @item{@indexed-scheme['panel] --- In unsmoothed mode, draws with the + same color and pattern as a top-level panel background, if the + brush's color is the same as the color returned by + @scheme[get-panel-background] and if the brush has no + stipple. To create a @scheme[canvas%] object that is drawn like + a control, use the @scheme['transparent] canvas style instead, + because certain kinds of nested panels have different + background colors (e.g., a @scheme[tab-panel%] under Mac OS + X). In a smoothing mode, @scheme['panel] is treated as + @scheme['solid].} + + @item{The following modes correspond to built-in stipples drawn in + @scheme['solid] mode: + + @itemize{ + @item{@indexed-scheme['bdiagonal-hatch] --- diagonal lines, top-left to bottom-right} + @item{@indexed-scheme['crossdiag-hatch] --- crossed diagonal lines} + @item{@indexed-scheme['fdiagonal-hatch] --- diagonal lines, top-right to bottom-left} + @item{@indexed-scheme['cross-hatch] --- crossed horizontal and vertical lines} + @item{@indexed-scheme['horizontal-hatch] --- horizontal lines} + @item{@indexed-scheme['vertical-hatch] --- vertical lines} + } + + However, when a specific stipple is installed into the brush + for when drawing with a smoothing mode into a non-PostScript + context, the above modes are ignored and @scheme['solid] is + used, instead.} + +} + +@index['("drawing" "outlines")]{To} draw outline shapes (such as + unfilled boxes and ellipses), use the @scheme['transparent] brush + style. See @method[brush% set-style] for more information about + styles. + +To avoid creating multiple brushes with the same characteristics, use + the global @scheme[brush-list%] object + @indexed-scheme[the-brush-list], or provide a color and style to + @xmethod[dc<%> set-brush]. + + +@defconstructor*/make[(() + ([color (is-a?/c color%)] + [style (one-of/c 'transparent 'solid 'opaque + 'xor 'hilite 'panel + 'bdiagonal-hatch 'crossdiag-hatch + 'fdiagonal-hatch 'cross-hatch + 'horizontal-hatch 'vertical-hatch)]) + ([color-name string?] + [style (one-of/c 'transparent 'solid 'opaque + 'xor 'hilite 'panel + 'bdiagonal-hatch 'crossdiag-hatch + 'fdiagonal-hatch 'cross-hatch + 'horizontal-hatch 'vertical-hatch)]))]{ + +When no argument are provided, the result is a solid black brush. + Otherwise, the result is a brush with the given color and style. For + the case that the color is specified using a name, see + @scheme[color-database<%>] for information about color names; if the + name is not known, the brush's color is black. + +} + +@defmethod[(get-color) + (is-a?/c color%)]{ + +Returns the brush's color. + +} + +@defmethod[(get-stipple) + (or/c (is-a?/c bitmap%) false/c)]{ + +Gets the stipple bitmap, or @scheme[#f] if the brush has no stipple. + +} + +@defmethod[(get-style) + (one-of/c 'transparent 'solid 'opaque + 'xor 'hilite 'panel + 'bdiagonal-hatch 'crossdiag-hatch + 'fdiagonal-hatch 'cross-hatch + 'horizontal-hatch 'vertical-hatch)]{ + +Returns the brush's style. See @scheme[brush%] for information about +brush styles. + +} + +@defmethod*[([(set-color [color (is-a?/c color%)]) + void?] + [(set-color [color-name string?]) + void?] + [(set-color [red (integer-in 0 255)] + [green (integer-in 0 255)] + [blue (integer-in 0 255)]) + void?])]{ + +Sets the brush's color. A brush cannot be modified if it was obtained + from a @scheme[brush-list%] or while it is selected into a drawing + context. + +For the case that the color is specified using a string, see + @scheme[color-database<%>] for information about color names. + +} + +@defmethod[(set-stipple [bitmap (or/c (is-a?/c bitmap%) false/c)]) + void?]{ + +Sets or removes the stipple bitmap, where @scheme[#f] removes the + stipple. See @scheme[brush%] for information about drawing with + stipples. + +A bitmap cannot be used as a stipple if it is selected into a + @scheme[bitmap-dc%] object; if the given bitmap is selected into a + @scheme[bitmap-dc%] object, @|MismatchExn|. A brush cannot be + modified if it was obtained from a @scheme[brush-list%] or while it + is selected into a drawing context. + +A pen's stipple is not used in a smoothing mode, except for a + @scheme[post-script-dc%] (which is always in a smoothing mode). + +} + +@defmethod[(set-style [style (one-of/c 'transparent 'solid 'opaque + 'xor 'hilite 'panel + 'bdiagonal-hatch 'crossdiag-hatch + 'fdiagonal-hatch 'cross-hatch + 'horizontal-hatch 'vertical-hatch)]) + void?]{ + +Sets the brush's style. See +@scheme[brush%] for information about the possible styles. + +A brush cannot be modified if it was obtained from a + @scheme[brush-list%] or while it is selected into a drawing + context. + +}} + diff --git a/collects/scribblings/gui/brush-list-class.scrbl b/collects/scribblings/gui/brush-list-class.scrbl new file mode 100644 index 0000000000..e4d4159dc0 --- /dev/null +++ b/collects/scribblings/gui/brush-list-class.scrbl @@ -0,0 +1,40 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[brush-list% object% ()]{ + +A @scheme[brush-list%] object maintains a list of @scheme[brush%] + objects to avoid creating brushes repeatedly. A @scheme[brush%] + object in a brush list cannot be mutated. + +A global brush list, @scheme[the-brush-list], is created + automatically. + + +@defconstructor/make[()]{ + +Creates an empty brush list. + +} + +@defmethod*[([(find-or-create-brush [color (is-a?/c color%)] + [style (one-of/c 'transparent 'solid 'opaque + 'xor 'hilite 'panel + 'bdiagonal-hatch 'crossdiag-hatch + 'fdiagonal-hatch 'cross-hatch + 'horizontal-hatch 'vertical-hatch)]) + (is-a?/c brush%)] + [(find-or-create-brush [color-name string?] + [style (one-of/c 'transparent 'solid 'opaque + 'xor 'hilite 'panel + 'bdiagonal-hatch 'crossdiag-hatch + 'fdiagonal-hatch 'cross-hatch + 'horizontal-hatch 'vertical-hatch)]) + (or/c (is-a?/c brush%) false/c)])]{ + +Finds a brush of the given specification, or creates one and adds it + to the list. See @scheme[brush%] for a further explanation of the + arguments, which are the same as @scheme[brush%]'s initialization + arguments. + +}} diff --git a/collects/scribblings/gui/color-class.scrbl b/collects/scribblings/gui/color-class.scrbl new file mode 100644 index 0000000000..abfd9b4b0e --- /dev/null +++ b/collects/scribblings/gui/color-class.scrbl @@ -0,0 +1,70 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[color% object% ()]{ + +A color is an object representing a red-green-blue (RGB) combination + of primary colors, and is used to determine drawing colors. Each red, + green, or blue component of the color is in the range 0 to 255, + inclusive. For example, (0, 0, 0) is black, (255, 255, 255) is + white, and (255, 0, 0) is red. + +See @scheme[color-database<%>] for information about obtaining a color +object using a color name. + + +@defconstructor*/make[(([red (integer-in 0 255)] + [green (integer-in 0 255)] + [blue (integer-in 0 255)]) + ([color-name string?]))]{ + +Creates a new color with the given RGB values, or matching the given + color name (using ``black'' if the name is not recognized). See + @scheme[color-database<%>] for more information on color names. + +} + +@defmethod[(blue) + (integer-in 0 255)]{ + +Returns the blue component of the color. + +} + +@defmethod[(copy-from [src (is-a?/c color%)]) + (is-a?/c color%)]{ + +Copies the RGB values of another color object to this one, returning + this object as the result. + +} + +@defmethod[(green) + (integer-in 0 255)]{ + +Returns the green component of the color. + +} + +@defmethod[(ok?) + boolean?]{ + +Returns @scheme[#t] if the color object is valid. + +} + +@defmethod[(red) + (integer-in 0 255)]{ + +Returns the red component of the color. + +} + +@defmethod[(set [red (integer-in 0 255)] + [green (integer-in 0 255)] + [blue (integer-in 0 255)]) + void?]{ + +Sets the three (red, green, and blue) component values of the color. +}} + diff --git a/collects/scribblings/gui/color-database-intf.scrbl b/collects/scribblings/gui/color-database-intf.scrbl new file mode 100644 index 0000000000..287ec732e4 --- /dev/null +++ b/collects/scribblings/gui/color-database-intf.scrbl @@ -0,0 +1,211 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@definterface[color-database<%> ()]{ + +The global @indexed-scheme[the-color-database] object is an instance of + @scheme[color-database<%>]. It maintains a database of standard RGB + colors for a predefined set of named colors (such as ``black'' and + ``light grey''). + +The following colors are in the database: + +@schemeblock[ +#, @colorName[#"Orange Red" #"OrangeRed" 255 69 0] +#, @colorName[#"OrangeRed" #"OrangeRed" 255 69 0] +#, @colorName[#"Tomato" #"Tomato" 255 99 71] +#, @colorName[#"DarkRed" #"DarkRed" 139 0 0] +#, @colorName[#"Red" #"Red" 255 0 0] +#, @colorName[#"Firebrick" #"Firebrick" 178 34 34] +#, @colorName[#"Crimson" #"Crimson" 220 20 60] +#, @colorName[#"DeepPink" #"DeepPink" 255 20 147] +#, @colorName[#"Maroon" #"Maroon" 176 48 96] +#, @colorName[#"Indian Red" #"IndianRed" 205 92 92] +#, @colorName[#"IndianRed" #"IndianRed" 205 92 92] +#, @colorName[#"Medium Violet Red" #"MediumVioletRed" 199 21 133] +#, @colorName[#"MediumVioletRed" #"MediumVioletRed" 199 21 133] +#, @colorName[#"Violet Red" #"VioletRed" 208 32 144] +#, @colorName[#"VioletRed" #"VioletRed" 208 32 144] +#, @colorName[#"LightCoral" #"LightCoral" 240 128 128] +#, @colorName[#"HotPink" #"HotPink" 255 105 180] +#, @colorName[#"PaleVioletRed" #"PaleVioletRed" 219 112 147] +#, @colorName[#"LightPink" #"LightPink" 255 182 193] +#, @colorName[#"RosyBrown" #"RosyBrown" 188 143 143] +#, @colorName[#"Pink" #"Pink" 255 192 203] +#, @colorName[#"Orchid" #"Orchid" 218 112 214] +#, @colorName[#"LavenderBlush" #"LavenderBlush" 255 240 245] +#, @colorName[#"Snow" #"Snow" 255 250 250] +#, @colorName[#"Chocolate" #"Chocolate" 210 105 30] +#, @colorName[#"SaddleBrown" #"SaddleBrown" 139 69 19] +#, @colorName[#"Brown" #"Brown" 132 60 36] +#, @colorName[#"DarkOrange" #"DarkOrange" 255 140 0] +#, @colorName[#"Coral" #"Coral" 255 127 80] +#, @colorName[#"Sienna" #"Sienna" 160 82 45] +#, @colorName[#"Orange" #"Orange" 255 165 0] +#, @colorName[#"Salmon" #"Salmon" 250 128 114] +#, @colorName[#"Peru" #"Peru" 205 133 63] +#, @colorName[#"DarkGoldenrod" #"DarkGoldenrod" 184 134 11] +#, @colorName[#"Goldenrod" #"Goldenrod" 218 165 32] +#, @colorName[#"SandyBrown" #"SandyBrown" 244 164 96] +#, @colorName[#"LightSalmon" #"LightSalmon" 255 160 122] +#, @colorName[#"DarkSalmon" #"DarkSalmon" 233 150 122] +#, @colorName[#"Gold" #"Gold" 255 215 0] +#, @colorName[#"Yellow" #"Yellow" 255 255 0] +#, @colorName[#"Olive" #"Olive" 128 128 0] +#, @colorName[#"Burlywood" #"Burlywood" 222 184 135] +#, @colorName[#"Tan" #"Tan" 210 180 140] +#, @colorName[#"NavajoWhite" #"NavajoWhite" 255 222 173] +#, @colorName[#"PeachPuff" #"PeachPuff" 255 218 185] +#, @colorName[#"Khaki" #"Khaki" 240 230 140] +#, @colorName[#"DarkKhaki" #"DarkKhaki" 189 183 107] +#, @colorName[#"Moccasin" #"Moccasin" 255 228 181] +#, @colorName[#"Wheat" #"Wheat" 245 222 179] +#, @colorName[#"Bisque" #"Bisque" 255 228 196] +#, @colorName[#"PaleGoldenrod" #"PaleGoldenrod" 238 232 170] +#, @colorName[#"BlanchedAlmond" #"BlanchedAlmond" 255 235 205] +#, @colorName[#"Medium Goldenrod" #"MediumGoldenrod" 234 234 173] +#, @colorName[#"MediumGoldenrod" #"MediumGoldenrod" 234 234 173] +#, @colorName[#"PapayaWhip" #"PapayaWhip" 255 239 213] +#, @colorName[#"MistyRose" #"MistyRose" 255 228 225] +#, @colorName[#"LemonChiffon" #"LemonChiffon" 255 250 205] +#, @colorName[#"AntiqueWhite" #"AntiqueWhite" 250 235 215] +#, @colorName[#"Cornsilk" #"Cornsilk" 255 248 220] +#, @colorName[#"LightGoldenrodYellow" #"LightGoldenrodYellow" 250 250 210] +#, @colorName[#"OldLace" #"OldLace" 253 245 230] +#, @colorName[#"Linen" #"Linen" 250 240 230] +#, @colorName[#"LightYellow" #"LightYellow" 255 255 224] +#, @colorName[#"SeaShell" #"SeaShell" 255 245 238] +#, @colorName[#"Beige" #"Beige" 245 245 220] +#, @colorName[#"FloralWhite" #"FloralWhite" 255 250 240] +#, @colorName[#"Ivory" #"Ivory" 255 255 240] +#, @colorName[#"Green" #"Green" 0 255 0] +#, @colorName[#"LawnGreen" #"LawnGreen" 124 252 0] +#, @colorName[#"Chartreuse" #"Chartreuse" 127 255 0] +#, @colorName[#"Green Yellow" #"GreenYellow" 173 255 47] +#, @colorName[#"GreenYellow" #"GreenYellow" 173 255 47] +#, @colorName[#"Yellow Green" #"YellowGreen" 154 205 50] +#, @colorName[#"YellowGreen" #"YellowGreen" 154 205 50] +#, @colorName[#"Medium Forest Green" #"MediumForestGreen" 107 142 35] +#, @colorName[#"OliveDrab" #"OliveDrab" 107 142 35] +#, @colorName[#"MediumForestGreen" #"MediumForestGreen" 107 142 35] +#, @colorName[#"Dark Olive Green" #"DarkOliveGreen" 85 107 47] +#, @colorName[#"DarkOliveGreen" #"DarkOliveGreen" 85 107 47] +#, @colorName[#"DarkSeaGreen" #"DarkSeaGreen" 143 188 139] +#, @colorName[#"Lime" #"Lime" 0 255 0] +#, @colorName[#"Dark Green" #"DarkGreen" 0 100 0] +#, @colorName[#"DarkGreen" #"DarkGreen" 0 100 0] +#, @colorName[#"Lime Green" #"LimeGreen" 50 205 50] +#, @colorName[#"LimeGreen" #"LimeGreen" 50 205 50] +#, @colorName[#"Forest Green" #"ForestGreen" 34 139 34] +#, @colorName[#"ForestGreen" #"ForestGreen" 34 139 34] +#, @colorName[#"Spring Green" #"SpringGreen" 0 255 127] +#, @colorName[#"SpringGreen" #"SpringGreen" 0 255 127] +#, @colorName[#"Medium Spring Green" #"MediumSpringGreen" 0 250 154] +#, @colorName[#"MediumSpringGreen" #"MediumSpringGreen" 0 250 154] +#, @colorName[#"Sea Green" #"SeaGreen" 46 139 87] +#, @colorName[#"SeaGreen" #"SeaGreen" 46 139 87] +#, @colorName[#"Medium Sea Green" #"MediumSeaGreen" 60 179 113] +#, @colorName[#"MediumSeaGreen" #"MediumSeaGreen" 60 179 113] +#, @colorName[#"Aquamarine" #"Aquamarine" 112 216 144] +#, @colorName[#"LightGreen" #"LightGreen" 144 238 144] +#, @colorName[#"Pale Green" #"PaleGreen" 152 251 152] +#, @colorName[#"PaleGreen" #"PaleGreen" 152 251 152] +#, @colorName[#"Medium Aquamarine" #"MediumAquamarine" 102 205 170] +#, @colorName[#"MediumAquamarine" #"MediumAquamarine" 102 205 170] +#, @colorName[#"Turquoise" #"Turquoise" 64 224 208] +#, @colorName[#"LightSeaGreen" #"LightSeaGreen" 32 178 170] +#, @colorName[#"Medium Turquoise" #"MediumTurquoise" 72 209 204] +#, @colorName[#"MediumTurquoise" #"MediumTurquoise" 72 209 204] +#, @colorName[#"Honeydew" #"Honeydew" 240 255 240] +#, @colorName[#"MintCream" #"MintCream" 245 255 250] +#, @colorName[#"RoyalBlue" #"RoyalBlue" 65 105 225] +#, @colorName[#"DodgerBlue" #"DodgerBlue" 30 144 255] +#, @colorName[#"DeepSkyBlue" #"DeepSkyBlue" 0 191 255] +#, @colorName[#"CornflowerBlue" #"CornflowerBlue" 100 149 237] +#, @colorName[#"Steel Blue" #"SteelBlue" 70 130 180] +#, @colorName[#"SteelBlue" #"SteelBlue" 70 130 180] +#, @colorName[#"LightSkyBlue" #"LightSkyBlue" 135 206 250] +#, @colorName[#"Dark Turquoise" #"DarkTurquoise" 0 206 209] +#, @colorName[#"DarkTurquoise" #"DarkTurquoise" 0 206 209] +#, @colorName[#"Cyan" #"Cyan" 0 255 255] +#, @colorName[#"Aqua" #"Aqua" 0 255 255] +#, @colorName[#"DarkCyan" #"DarkCyan" 0 139 139] +#, @colorName[#"Teal" #"Teal" 0 128 128] +#, @colorName[#"Sky Blue" #"SkyBlue" 135 206 235] +#, @colorName[#"SkyBlue" #"SkyBlue" 135 206 235] +#, @colorName[#"Cadet Blue" #"CadetBlue" 96 160 160] +#, @colorName[#"CadetBlue" #"CadetBlue" 95 158 160] +#, @colorName[#"Dark Slate Gray" #"DarkSlateGray" 47 79 79] +#, @colorName[#"DarkSlateGray" #"DarkSlateGray" 47 79 79] +#, @colorName[#"LightSlateGray" #"LightSlateGray" 119 136 153] +#, @colorName[#"SlateGray" #"SlateGray" 112 128 144] +#, @colorName[#"Light Steel Blue" #"LightSteelBlue" 176 196 222] +#, @colorName[#"LightSteelBlue" #"LightSteelBlue" 176 196 222] +#, @colorName[#"Light Blue" #"LightBlue" 173 216 230] +#, @colorName[#"LightBlue" #"LightBlue" 173 216 230] +#, @colorName[#"PowderBlue" #"PowderBlue" 176 224 230] +#, @colorName[#"PaleTurquoise" #"PaleTurquoise" 175 238 238] +#, @colorName[#"LightCyan" #"LightCyan" 224 255 255] +#, @colorName[#"AliceBlue" #"AliceBlue" 240 248 255] +#, @colorName[#"Azure" #"Azure" 240 255 255] +#, @colorName[#"Medium Blue" #"MediumBlue" 0 0 205] +#, @colorName[#"MediumBlue" #"MediumBlue" 0 0 205] +#, @colorName[#"DarkBlue" #"DarkBlue" 0 0 139] +#, @colorName[#"Midnight Blue" #"MidnightBlue" 25 25 112] +#, @colorName[#"MidnightBlue" #"MidnightBlue" 25 25 112] +#, @colorName[#"Navy" #"Navy" 36 36 140] +#, @colorName[#"Blue" #"Blue" 0 0 255] +#, @colorName[#"Indigo" #"Indigo" 75 0 130] +#, @colorName[#"Blue Violet" #"BlueViolet" 138 43 226] +#, @colorName[#"BlueViolet" #"BlueViolet" 138 43 226] +#, @colorName[#"Medium Slate Blue" #"MediumSlateBlue" 123 104 238] +#, @colorName[#"MediumSlateBlue" #"MediumSlateBlue" 123 104 238] +#, @colorName[#"Slate Blue" #"SlateBlue" 106 90 205] +#, @colorName[#"SlateBlue" #"SlateBlue" 106 90 205] +#, @colorName[#"Purple" #"Purple" 160 32 240] +#, @colorName[#"Dark Slate Blue" #"DarkSlateBlue" 72 61 139] +#, @colorName[#"DarkSlateBlue" #"DarkSlateBlue" 72 61 139] +#, @colorName[#"DarkViolet" #"DarkViolet" 148 0 211] +#, @colorName[#"Dark Orchid" #"DarkOrchid" 153 50 204] +#, @colorName[#"DarkOrchid" #"DarkOrchid" 153 50 204] +#, @colorName[#"MediumPurple" #"MediumPurple" 147 112 219] +#, @colorName[#"Cornflower Blue" #"CornflowerBlue" 68 64 108] +#, @colorName[#"Medium Orchid" #"MediumOrchid" 186 85 211] +#, @colorName[#"MediumOrchid" #"MediumOrchid" 186 85 211] +#, @colorName[#"Magenta" #"Magenta" 255 0 255] +#, @colorName[#"Fuchsia" #"Fuchsia" 255 0 255] +#, @colorName[#"DarkMagenta" #"DarkMagenta" 139 0 139] +#, @colorName[#"Violet" #"Violet" 238 130 238] +#, @colorName[#"Plum" #"Plum" 221 160 221] +#, @colorName[#"Lavender" #"Lavender" 230 230 250] +#, @colorName[#"Thistle" #"Thistle" 216 191 216] +#, @colorName[#"GhostWhite" #"GhostWhite" 248 248 255] +#, @colorName[#"White" #"White" 255 255 255] +#, @colorName[#"WhiteSmoke" #"WhiteSmoke" 245 245 245] +#, @colorName[#"Gainsboro" #"Gainsboro" 220 220 220] +#, @colorName[#"Light Gray" #"LightGray" 211 211 211] +#, @colorName[#"LightGray" #"LightGray" 211 211 211] +#, @colorName[#"Silver" #"Silver" 192 192 192] +#, @colorName[#"Gray" #"Gray" 190 190 190] +#, @colorName[#"Dark Gray" #"DarkGray" 169 169 169] +#, @colorName[#"DarkGray" #"DarkGray" 169 169 169] +#, @colorName[#"Dim Gray" #"DimGray" 105 105 105] +#, @colorName[#"DimGray" #"DimGray" 105 105 105] +#, @colorName[#"Black" #"Black" 0 0 0] +] + +The names are not case-sensitive. + +See also @scheme[color%]. + + + + +@defmethod[(find-color [color-name string?]) + (or/c (is-a?/c color%) false/c)]{ + +Finds a color by name (character case is ignored). If no color is + found for the name, @scheme[#f] is returned. + +}} + diff --git a/collects/scribblings/gui/dc-intf.scrbl b/collects/scribblings/gui/dc-intf.scrbl new file mode 100644 index 0000000000..7e313303fe --- /dev/null +++ b/collects/scribblings/gui/dc-intf.scrbl @@ -0,0 +1,909 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@definterface[dc<%> ()]{ + +A @scheme[dc<%>] object is a drawing context for drawing graphics and + text. It represents output devices in a generic way; e.g., a canvas + has a drawing context, as does a printer. + +The drawing methods, such as @method[dc<%> draw-rectangle], accept +real number values as arguments, but the results are only well-defined +when the drawing coordinates are in the range @scheme[-16383] to +@scheme[16383]. This restriction applies to the coordinates both +before and after offsets and scaling factors are applied. + +@defmethod[(clear) + void?]{ + +Clears the drawing region (fills it with the current background color, +as determined by @method[dc<%> get-background]). + +} + +@defmethod[(draw-arc [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))] + [start-radians real?] + [end-radians real?]) + void?]{ + +Draws a counter-clockwise circular arc, a part of the ellipse + inscribed in the rectangle specified by @scheme[x] (left), @scheme[y] + (top), @scheme[width], and @scheme[height]. The arc starts at the angle + specified by @scheme[start-radians] (@scheme[0] is three o'clock and + half-pi is twelve o'clock) and continues counter-clockwise to + @scheme[end-radians]. If @scheme[start-radians] and @scheme[end-radians] are + the same, a full ellipse is drawn. + +The current pen is used for the arc. If the current brush is not + transparent, it is used to fill the wedge bounded by the arc plus + lines (not drawn) extending to the center of the inscribed ellipse. + +If both the pen and brush are non-transparent, the wedge is filled + with the brush before the arc is drawn with the pen. The wedge and + arc meet so that no space is left between them, but the precise + overlap between the wedge and arc is platform- and size-specific. + Typically, the regions drawn by the brush and pen overlap. More + generally, the pen is centered over the outline of the arc, rounding + toward the center in unsmoothed mode. + +@|DrawSizeNote| + +} + + +@defmethod[(draw-bitmap [source (is-a?/c bitmap%)] + [dest-x real?] + [dest-y real?] + [style (one-of/c 'solid 'opaque 'xor) 'solid] + [color (is-a?/c color%) (send the-color-database find-color "black")] + [mask (or/c (is-a?/c bitmap%) false/c) #f]) + boolean?]{ + +Displays a bitmap. The @scheme[dest-x] and @scheme[dest-y] arguments + are in DC coordinates. + +For color bitmaps, the drawing style and color arguments are + ignored. For monochrome bitmaps, @method[dc<%> draw-bitmap] uses the + style and color arguments in the same way that a brush uses its style + and color settings to draw a monochrome stipple (see @scheme[brush%] + for more information). + +If a mask bitmap is supplied, it must have the same width and height + as the bitmap to display, and its @method[bitmap% ok?] must return + true, otherwise @|MismatchExn|. The bitmap to draw and the mask + bitmap can be the same object, but if the drawing context is a + @scheme[bitmap-dc%] object, both bitmaps must be distinct from the + destination bitmap, otherwise @|MismatchExn|. + +If the mask bitmap is monochrome, drawing occurs in the target + @scheme[dc<%>] only where the mask bitmap contains black pixels. + +If the mask bitmap is grayscale and the bitmap to draw is not + monochrome, then the blackness of each mask pixel controls the + opacity of the drawn pixel (i.e., the mask acts as an inverted alpha + channel), at least on most platforms. (Non-monochrome masks + are collapsed to monochrome under X when the RENDER extension is not + available, and under Windows 95 and NT when @file{msing32.dll} is not + available.) Other combinations involving a non-monochrome mask (i.e., + a non-grayscale mask or a monochrome bitmap to draw) produce + platform-specific results. + +The current brush, current pen, and current text settings for the DC + have no effect on how the bitmap is drawn, but the bitmap is scaled + if the DC has a scale. + +For @scheme[post-script-dc%] output, the mask bitmap is currently + ignored, and the @scheme['solid] style is treated the same as + @scheme['opaque]. (However, mask bitmaps and @scheme['solid] drawing + may become supported for @scheme[post-script-dc%] in the future.) + +The result is @scheme[#t] if the bitmap is successfully drawn, + @scheme[#f] otherwise (possibly because the bitmap's @method[bitmap% + ok?] method returns @scheme[#f]). + +See also @method[dc<%> draw-bitmap-section]. + +@|DrawSizeNote| + +} + +@defmethod[(draw-bitmap-section [source (is-a?/c bitmap%)] + [dest-x real?] + [dest-y real?] + [src-x real?] + [src-y real?] + [src-width (and/c real? (not/c negative?))] + [src-height (and/c real? (not/c negative?))] + [style (one-of/c 'solid 'opaque 'xor) 'solid] + [color (is-a?/c color%) (send the-color-database find-color "black")] + [mask (or/c (is-a?/c bitmap%) false/c) #f]) + boolean?]{ + +Displays part of a bitmap. + +The @scheme[src-x], @scheme[src-y], @scheme[src-width], and + @scheme[src-height] arguments specify a rectangle in the source + bitmap to copy into this drawing context. + +See @method[dc<%> draw-bitmap] for information about @scheme[dest-x], + @scheme[dest-y], @scheme[style], @scheme[color], and @scheme[mask]. + +} + +@defmethod[(draw-ellipse [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))]) + void?]{ + +Draws an ellipse contained in a rectangle with the given top-left + corner and size. The current pen is used for the outline, and the + current brush is used for filling the shape. + +If both the pen and brush are non-transparent, the ellipse is filled + with the brush before the outline is drawn with the pen. The filling + and outline meet so that no space is left between them, but the + precise overlap between the filling and outline is platform- and + size-specific. Typically, the regions drawn by the brush and pen + overlap. More generally, the pen is centered over the outline of the + ellipse, rounding toward the center in unsmoothed mode. + +@|DrawSizeNote| + +} + +@defmethod[(draw-line [x1 real?] + [y1 real?] + [x2 real?] + [y2 real?]) + void?]{ + +Draws a line from one point to another. The current pen is used for + drawing the line. + +In unsmoothed mode, the points correspond to pixels, and the line + covers both the start and end points. For a pen whose scaled width is + larger than @scheme[1], the line is drawn centered over the start and + end points. + +See also @method[dc<%> set-smoothing] for information on the +@scheme['aligned] smoothing mode. + +@|DrawSizeNote| + +} + +@defmethod[(draw-lines [points (listof (is-a?/c point%))] + [xoffset real? 0] + [yoffset real? 0]) + void?]{ + +Draws lines using a list of @scheme[points], adding @scheme[xoffset] + and @scheme[yoffset] to each point. The current pen is used for + drawing the lines. + +See also @method[dc<%> set-smoothing] for information on the + @scheme['aligned] smoothing mode. + +@|DrawSizeNote| + +} + +@defmethod[(draw-path [path (is-a?/c dc-path%)] + [xoffset real? 0] + [yoffset real? 0] + [fill-style (one-of/c 'odd-even 'winding) 'odd-even]) + void?]{ + +Draws the sub-paths of the given @scheme[dc-path%] object, adding + @scheme[xoffset] and @scheme[yoffset] to each point. The current pen + is used for drawing the path as a line, and the current brush is used + for filling the area bounded by the path. + +If both the pen and brush are non-transparent, the path is filled with + the brush before the outline is drawn with the pen. The filling and + outline meet so that no space is left between them, but the precise + overlap between the filling and outline is platform- and + size-specific. Thus, the regions drawn by the brush and pen may + overlap. More generally, the pen is centered over the path, rounding + left and down in unsmoothed mode. + +The @scheme[fill-style] argument specifies the fill rule: + @scheme['odd-even] or @scheme['winding]. In @scheme['odd-even] mode, a + point is considered enclosed within the path if it is enclosed by an + odd number of sub-path loops. In @scheme['winding] mode, a point is + considered enclosed within the path if it is enclosed by more or less + clockwise sub-path loops than counter-clockwise sub-path loops. In + unsmoothed mode, the @scheme['winding] fill rule is not supported + under Mac OS X and it is not supported when @scheme[path] contains + multiple sub-paths; the @scheme['winding] fill rules is always + supported when smoothing is enabled (see +@method[dc<%> set-smoothing]). + +See also @method[dc<%> set-smoothing] for information on the + @scheme['aligned] smoothing mode. + +@|DrawSizeNote| + +} + +@defmethod[(draw-point [x real?] + [y real?]) + void?]{ + +Plots a single point using the current pen. + +@|DrawSizeNote| + +} + +@defmethod[(draw-polygon [points (listof (is-a?/c point%))] + [xoffset real? 0] + [yoffset real? 0] + [fill-style (one-of/c 'odd-even 'winding) 'odd-even]) + void?]{ + +Draw a filled polygon using a list of @scheme[points], adding + @scheme[xoffset] and @scheme[yoffset] to each point. The polygon is + automatically closed, so the first and last point can be + different. The current pen is used for drawing the outline, and the + current brush for filling the shape. + +If both the pen and brush are non-transparent, the polygon is filled + with the brush before the outline is drawn with the pen. The filling + and outline meet so that no space is left between them, but the + precise overlap between the filling and outline is platform- and + shape-specific. Thus, the regions drawn by the brush and pen may + overlap. More generally, the pen is centered over the polygon lines, + rounding left and down in unsmoothed mode. + +The @scheme[fill-style] argument specifies the fill rule: + @scheme['odd-even] or @scheme['winding]. In @scheme['odd-even] mode, a + point is considered enclosed within the polygon if it is enclosed by + an odd number of loops. In @scheme['winding] mode, a point is + considered enclosed within the polygon if it is enclosed by more or + less clockwise loops than counter-clockwise loops. The + @scheme['winding] fill rule is not supported under Mac OS X, + except when smoothing is enabled (see +@method[dc<%> set-smoothing]). + +See also @method[dc<%> set-smoothing] for information on the + @scheme['aligned] smoothing mode. + +@|DrawSizeNote| + +} + + +@defmethod[(draw-rectangle [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))]) + void?]{ + +Draws a rectangle with the given top-left corner and size. The + current pen is used for the outline and the current brush for filling + the shape. + +If both the pen and brush are non-transparent, the rectangle is filled + with the brush before the outline is drawn with the pen. In + unsmoothed mode, when the pen is size 0 or 1, the filling precisely + overlaps the entire outline. As a result, if a rectangle is drawn + with a size-0 or size-1 @scheme['xor] @scheme[pen%] and an + @scheme['xor] @scheme[brush%], the outline is xored twice (first by + the brush, then by the pen), leaving it unchanged. More generally, + the pen is centered over the outline of the rectangle, rounding + toward the center in unsmoothed mode. + +See also @method[dc<%> set-smoothing] for information on the +@scheme['aligned] smoothing mode. + +@|DrawSizeNote| + +} + + +@defmethod[(draw-rounded-rectangle [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))] + [radius real? -0.25]) + void?]{ + +Draws a rectangle with the given top-left corner, and with the given + size. The corners are quarter-circles using the given radius. The + current pen is used for the outline and the current brush for filling + the shape. + +If @scheme[radius] is positive, the value is used as the radius of the + rounded corner. If @scheme[radius] is negative, the absolute value is + used as the @italic{proportion} of the smallest dimension of the + rectangle. + +If @scheme[radius] is less than @scheme[-0.5] or more than half of + @scheme[width] or @scheme[height], @|MismatchExn|. + +If both the pen and brush are non-transparent, the rectangle is filled + with the brush before the outline is drawn with the pen. The filling + and outline meet so that no space is left between them, but the + precise overlap between the filling and outline is platform- and + size-specific. Thus, the regions drawn by the brush and pen may + partially overlap. More generally, the pen is centered over the + outline of the rounded rectangle, rounding toward the center in + unsmoothed mode. + +See also @method[dc<%> set-smoothing] for information on the +@scheme['aligned] smoothing mode. + +@|DrawSizeNote| + +} + +@defmethod[(draw-spline [x1 real?] + [y1 real?] + [x2 real?] + [y2 real?] + [x3 real?] + [y3 real?]) + void?]{ + +Draws a spline from (@scheme[x1], @scheme[y1]) to (@scheme[x3], @scheme[y3]) + using (@scheme[x2], @scheme[y2]) as the control point. + +See also @method[dc<%> set-smoothing] for information on the +@scheme['aligned] smoothing mode. + +@|DrawSizeNote| + +} + +@defmethod[(draw-text [text string?] + [x real?] + [y real?] + [combine? any/c #f] + [offset nonnegative-exact-integer? 0] + [angle real? 0]) + void?]{ + +Draws a text string at a specified point, using the current text font, + and the current text foreground and background colors. For unrotated + text, the specified point is used as the starting top-left point for + drawing characters (e.g, if ``W'' is drawn, the point is roughly the + location of the top-left pixel in the ``W''). Rotated text is rotated + around this point. + +The @scheme[text] string is drawn starting from the @scheme[offset] + character, and continuing until the end of @scheme[text] or the first + null character. + +If @scheme[combine?] is @scheme[#t], then @scheme[text] may be + measured with adjacent characters combined to ligature glyphs, with + Unicode combining characters as a single glyph, with kerning, with + right-to-left rendering of characters, etc. If @scheme[combine?] is + @scheme[#f], then the result is the same as if each character is + measured separately, and Unicode control characters are ignored. + +The string is rotated by @scheme[angle] radians counter-clockwise. If + @scheme[angle] is not zero, then the text is always drawn in + transparent mode (see @method[dc<%> set-text-mode]). + +The current brush and current pen settings for the DC have no effect + on how the text is drawn. + +See @method[dc<%> get-text-extent] for information on the size of the + drawn text. + +See also @method[dc<%> set-text-foreground], @method[dc<%> + set-text-background], and @method[dc<%> set-text-mode]. + +@|DrawSizeNote| + +} + +@defmethod[(end-doc) + void?]{ + +Ends a document, relevant only when drawing to a printer or PostScript + device (including to a PostScript file). + +For printer or PostScript output, an exception is raised if +@scheme[end-doc] is called when the document is not started with +@method[dc<%> start-doc], when a page is currently started by +@method[dc<%> start-page] and not ended with @method[dc<%> end-page], +or when the document has been ended already. + +} + +@defmethod[(end-page) + void?]{ + +Ends a single page, relevant only when drawing to a printer or + PostScript device (including to a PostScript file). + +For printer or PostScript output, an exception is raised if +@scheme[end-page] is called when a page is not currently started by +@method[dc<%> start-page]. + +} + +@defmethod[(get-background) + (is-a?/c color%)]{ + +Gets the color used for painting the background. See also +@method[dc<%> set-background]. + +} + +@defmethod[(get-brush) + (is-a?/c brush%)]{ + +Gets the current brush. See also @method[dc<%> set-brush]. + +} + +@defmethod[(get-char-height) + (and/c real? (not/c negative?))]{ + +Gets the height of a character using the current font. + +Unlike most methods, this method can be called for a + @scheme[bitmap-dc%] object without a bitmap installed. + +} + +@defmethod[(get-char-width) + (and/c real? (not/c negative?))]{ + +Gets the average width of a character using the current font. + +Unlike most methods, this method can be called for a + @scheme[bitmap-dc%] object without a bitmap installed. + +} + +@defmethod[(get-clipping-region) + (or/c (is-a?/c region%) false/c)]{ + +Gets the current clipping region, returning @scheme[#f] if the drawing + context is not clipped (i.e., the clipping region is the entire + drawing region). + +} + +@defmethod[(get-font) + (is-a?/c font%)]{ + +Gets the current font. See also @method[dc<%> set-font]. + +} + +@defmethod[(get-gl-context) + (or/c (is-a?/c gl-context<%>) false/c)]{ + +Returns a @scheme[gl-context<%>] object for this drawing context + if it supports OpenGL, @scheme[#f] otherwise. + +See @scheme[gl-context<%>] for more information. + +} + +@defmethod[(get-origin) + (values real? real?)]{ + +Returns the device origin, i.e., the location in device coordinates of + @math{(0,0)} in logical coordinates. + +See also @method[dc<%> set-origin]. + +} + + +@defmethod[(get-pen) + (is-a?/c pen%)]{ + +Gets the current pen. See also @method[dc<%> set-pen]. + +} + +@defmethod[(get-scale) + (values real? real?)]{ + +Returns the scaling factor that maps logical coordinates to device +coordinates. + +See also @method[dc<%> set-scale]. + +} + +@defmethod[(get-size) + (values nonnegative-real? nonnegative-real?)]{ + +Gets the size of the destination drawing area. For a @scheme[dc<%>] + object obtained from a @scheme[canvas<%>], this is the (virtual + client) size of the destination window; for a @scheme[bitmap-dc%] + object, this is the size of the selected bitmap (or 0 if no bitmap is + selected); for a @scheme[post-script-dc%] or @scheme[printer-dc%] + drawing context, this gets the horizontal and vertical size of the + drawing area. + +} + +@defmethod[(get-smoothing) + (one-of/c 'unsmoothed 'smoothed 'aligned)]{ + +Returns the current smoothing mode. See @method[dc<%> set-smoothing]. + +} + +@defmethod[(get-text-background) + (is-a?/c color%)]{ + +Gets the current text background color. See also @method[dc<%> +set-text-background]. + +} + +@defmethod[(get-text-extent [string string?] + [font (or/c (is-a?/c font%) false/c) #f] + [combine? any/c #f] + [offset nonnegative-exact-integer? 0]) + (values nonnegative-real? + nonnegative-real? + nonnegative-real? + nonnegative-real?)]{ + + +Returns the size of @scheme[str] at it would be drawn in the drawing + context, starting from the @scheme[offset] character of @scheme[str], + and continuing until the end of @scheme[str] or the first null + character. The @scheme[font] argument specifies the font to use in + measuring the text; if it is @scheme[#f], the current font of the + drawing area is used. (See also @method[dc<%> set-font].) + +The result is four real numbers: + +@itemize{ + + @item{the total width of the text (depends on both the font and the + text);} + + @item{the total height of the font (depends only on the font);} + + @item{the distance from the baseline of the font to the bottom of the + descender (included in the height, depends only on the font); and} + + @item{extra vertical space added to the font by the font designer + (included in the height, and often zero; depends only on the font).} + +} + +The returned width and height define a rectangle is that guaranteed to + contain the text string when it is drawn, but the fit is not + necessarily tight. Some undefined number of pixels on the left, + right, top, and bottom of the drawn string may be ``whitespace,'' + depending on the whims of the font designer and the platform-specific + font-scaling mechanism. + +If @scheme[combine?] is @scheme[#t], then @scheme[text] may be drawn + with adjacent characters combined to ligature glyphs, with Unicode + combining characters as a single glyph, with kerning, with + right-to-left ordering of characters, etc. If @scheme[combine?] is + @scheme[#f], then the result is the same as if each character is + drawn separately, and Unicode control characters are ignored. + +Unlike most methods, this method can be called for a + @scheme[bitmap-dc%] object without a bitmap installed. + +} + + +@defmethod[(get-text-foreground) + (is-a?/c color%)]{ + +Gets the current text foreground color. See also @method[dc<%> +set-text-foreground]. + +} + +@defmethod[(get-text-mode) + (one-of/c 'solid 'transparent)]{ +Reports how text is drawn; see +@method[dc<%> set-text-mode] . + +} + +@defmethod[(glyph-exists? [c char] + [font (or/c (is-a?/c font%) false/c) #f]) + boolean?]{ + +Returns @scheme[#t] if the given character has a corresponding glyph + for this drawing context, @scheme[#f] otherwise. + +Due to automatic font substitution when drawing or measuring text, the + result of this method does not depend on the given font, which merely + provides a hint for the glyph search. If the font is @scheme[#f], the + drawing context's current font is used. The result depends on the + type of the drawing context, but the result for @scheme[canvas%] + @scheme[dc<%>] instances and @scheme[bitmap-dc%] instances is always + the same for a given platform and a given set of installed fonts. + +See also @method[font% screen-glyph-exists?] . + +} + +@defmethod[(ok?) + boolean?]{ + +Returns @scheme[#t] if the drawing context is usable. + +} + +@defmethod[(set-background [color (is-a?/c color%)]) + void?]{ + +Sets the background color for drawing in this object (e.g., using +@method[dc<%> clear] or using a stippled @scheme[brush%] with the mode +@scheme['opaque]). For monochrome drawing, all non-black colors are +treated as white. + +} + +@defmethod*[([(set-brush [brush (is-a?/c brush%)]) + void?] + [(set-brush [color (is-a?/c color%)] + [style (one-of/c 'transparent 'solid 'opaque + 'xor 'hilite 'panel + 'bdiagonal-hatch 'crossdiag-hatch + 'fdiagonal-hatch 'cross-hatch + 'horizontal-hatch 'vertical-hatch)]) + void?] + [(set-brush [color-name string?] + [style (one-of/c 'transparent 'solid 'opaque + 'xor 'hilite 'panel + 'bdiagonal-hatch 'crossdiag-hatch + 'fdiagonal-hatch 'cross-hatch + 'horizontal-hatch 'vertical-hatch)]) + void?])]{ + +Sets the current brush for drawing in this object. While a brush is + selected into a drawing context, it cannot be modified. When a color + and style are given, the arguments are as for @xmethod[brush-list% + find-or-create-brush]. + +} + + +@defmethod[(set-clipping-rect [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))]) + void?]{ + +Sets the clipping region to a rectangular region. + +See also @method[dc<%> set-clipping-region] and @method[dc<%> +get-clipping-region]. + +@|DrawSizeNote| + +} + +@defmethod[(set-clipping-region [rgn (or/c (is-a?/c region%) false/c)]) + void?]{ + +Sets the clipping region for the drawing area, turning off all + clipping within the drawing region if @scheme[#f] is provided. + +The clipping region must be reset after changing a @scheme[dc<%>] + object's origin or scale (unless it is @scheme[#f]); see + @scheme[region%] for more information. + +See also @method[dc<%> set-clipping-rect] and @method[dc<%> + get-clipping-region]. + +} + +@defmethod[(set-font [font (is-a?/c font%)]) + void?]{ + +Sets the current font for drawing text in this object. + +} + +@defmethod[(set-origin [x real?] + [y real?]) + void?]{ + +Sets the device origin, i.e., the location in device coordinates of + @math{(0,0)} in logical coordinates. + +Changing a @scheme[dc<%>] object's origin or scale does not affect + @scheme[region%] objects that were previously created. See +@scheme[region%] for more information. + + +@|DrawSizeNote| + +} + +@defmethod*[([(set-pen [pen (is-a?/c pen%)]) + void?] + [(set-pen [color (is-a?/c color%)] + [width (real-in 0 255)] + [style (one-of/c 'transparent 'solid 'xor 'hilite + 'dot 'long-dash 'short-dash 'dot-dash + 'xor-dot 'xor-long-dash 'xor-short-dash + 'xor-dot-dash)]) + void?] + [(set-pen [color-name string?] + [width (real-in 0 255)] + [style (one-of/c 'transparent 'solid 'xor 'hilite + 'dot 'long-dash 'short-dash 'dot-dash + 'xor-dot 'xor-long-dash 'xor-short-dash + 'xor-dot-dash)]) + void?])]{ + +Sets the current pen for this object. When a color, width, and style + are given, the arguments are as for @xmethod[pen-list% + find-or-create-pen]. + +The current pen does not affect text drawing; see also @method[dc<%> + set-text-foreground]. + +While a pen is selected into a drawing context, it cannot be modified. + +} + +@defmethod[(set-scale [x-scale (and/c real? (not/c negative?))] + [y-scale (and/c real? (not/c negative?))]) + void?]{ + +Sets a scaling factor that maps logical coordinates to device coordinates. + +Changing a @scheme[dc<%>] object's origin or scale does not affect + @scheme[region%] objects that were previously created. See + @scheme[region%] for more information. + +@|DrawSizeNote| + +} + +@defmethod[(set-smoothing [mode (one-of/c 'unsmoothed 'smoothed 'aligned)]) + void?]{ + +Enables or disables anti-aliased smoothing of lines, curves, + rectangles, rounded rectangles, ellipses, polygons, paths, and clear + operations. (Text smoothing is not affected by this method, and is + instead controlled through the @scheme[font%] object.) + +Smoothing is supported under Windows only when Microsoft's + @file{gdiplus.dll} is installed (which is always the case for Windows + XP). Smoothing is supported under Mac OS X always. Smoothing is + supported under X only when Cairo is installed when MrEd is compiled. + Smoothing is never supported for black-and-white contexts. Smoothing + is always supported (and cannot be disabled) for PostScript output. + +The smoothing mode is either @scheme['unsmoothed], @scheme['smoothed], + or @scheme['aligned]. Both @scheme['aligned] and @scheme['smoothed] + are smoothing modes. + +In @scheme['smoothed] mode for a canvas or bitmap drawing context, + integer drawing coordinates correspond to the boundary between + pixels, and pen-based drawing is centered over a given line or + curve. Thus, drawing with pen width @scheme[1] from @math{(0, 10)} to + @math{(10, 10)} draws a 2-pixel wide line with @math{50%} opacity. + +The @scheme['aligned] smoothing mode is like @scheme['smoothed], but + it paints pixels more like @scheme['unsmoothed] mode. Since it aligns + shapes to pixel boundaries, @scheme['aligned] mode often produces + better results than @scheme['smoothed], but the results depend on the + application. The @scheme['aligned] mode is defined in terms of + @scheme['smoothed] mode, except that drawing coordinates are rounded + down (via @scheme[floor], after scaling and origin translation). For + line drawing, coordinates are then shifted right and down by the + @scheme[floor] of half a pen width. In addition, for pen drawing + through @method[dc<%> draw-rectangle], @method[dc<%> draw-ellipse], + @method[dc<%> draw-rounded-rectangle], and @method[dc<%> draw-arc], + the given width and height are each decreased by @math{1.0}. + +In either smoothing mode, brush and pen stipples are ignored (except + for PostScript drawing), and @scheme['hilite] and @scheme['xor] + drawing modes are treated as @scheme['solid]. If smoothing is not + supported, then attempting to set the smoothing mode to + @scheme['smoothed] or @scheme['aligned] will have no effect, and + @method[dc<%> get-smoothing] will always return + @scheme['unsmoothed]. Similarly, @method[dc<%> get-smoothing] for a + @scheme[post-script-dc%] always returns @scheme['smoothed]. + +} + +@defmethod[(set-text-background [color (is-a?/c color%)]) + void?]{ + +Sets the current text background color for this object. The text + background color is painted behind text that is drawn with + @method[dc<%> draw-text], but only for the @scheme['solid] text mode + (see @method[dc<%> set-text-mode]). + +For monochrome drawing, all non-white colors are treated as black. + +} + +@defmethod[(set-text-foreground [color (is-a?/c color%)]) + void?]{ + +Sets the current text foreground color for this object, used for + drawing text with +@method[dc<%> draw-text]. + +For monochrome drawing, all non-black colors are treated as + white. + +} + +@defmethod[(set-text-mode [mode (one-of/c 'solid 'transparent)]) + void?]{ + +Determines how text is drawn: + +@itemize{ + + @item{@scheme['solid] --- Before text is drawn, the destination area + is filled with the text background color (see @method[dc<%> + set-text-background]).} + + @item{@scheme['transparent] --- Text is drawn directly over any + existing image in the destination, as if overlaying text + written on transparent film.} + +} + +} + +@defmethod[(start-doc [message string?]) + boolean?]{ + +Starts a document, relevant only when drawing to a printer or + PostScript device (including to a PostScript file). For some + platforms, the @scheme[message] string is displayed in a dialog until + @method[dc<%> end-doc] is called. + +For printer or PostScript output, an exception is raised if + @scheme[start-doc] has been called already (even if @method[dc<%> + end-doc] has been called as well). Furthermore, drawing methods raise + an exception if not called while a page is active as determined by + @method[dc<%> start-doc] and @method[dc<%> start-page]. + +} + +@defmethod[(start-page) + void?]{ + +Starts a page, relevant only when drawing to a printer or PostScript + device (including to a PostScript file). + +For printer or PostScript output, an exception is raised if + @scheme[start-doc] is called when a page is already started, or when + @method[dc<%> start-doc] has not been called, or when @method[dc<%> + end-doc] has been called already. In addition, in the case of + PostScript output, Encapsulated PostScript (EPS) cannot contain + multiple pages, so calling @scheme[start-page] a second time for a + @scheme[post-script-dc%] instance raises an exception; to create + PostScript output with multiple pages, supply @scheme[#f] as the + @scheme[as-eps] initialization argument for @scheme[post-script-dc%]. + +} + +@defmethod[(try-color [try (is-a?/c color%)] + [result (is-a?/c color%)]) + void?]{ + +Determines the actual color used for drawing requests with the given + color. The @scheme[result] color is set to the RGB values that are + actually produced for this drawing context to draw the color + @scheme[try]. + +}} diff --git a/collects/scribblings/gui/dc-path-class.scrbl b/collects/scribblings/gui/dc-path-class.scrbl new file mode 100644 index 0000000000..0d63b745d9 --- /dev/null +++ b/collects/scribblings/gui/dc-path-class.scrbl @@ -0,0 +1,261 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[dc-path% object% ()]{ + +A path is a set of figures defined by curves. A path can be used with +the @method[dc<%> draw-path] method of a @scheme[dc<%>] object to draw +the path's curves as lines, fill the region bounded by the path's +curves, or both. A path can also be used with the @method[region% +set-path] method of a @scheme[region%] object to generate a region +bounded by the path's curves. + +A path consists of zero or more @deftech{closed sub-paths}, and + possibly one @deftech{open sub-path}. Some @scheme[dc-path%] methods + extend the open sub-path, some @scheme[dc-path%] methods close the + open sub-path, and some @scheme[dc-path%] methods add closed + sub-paths. + +When a path is drawn as a line, a closed sub-path is drawn as a closed + figure, analogous to a polygon. An open sub-path is drawn with + disjoint start and end points, analogous lines drawn with + @xmethod[dc<%> draw-lines]. + +When a path is filled or used as a region, the open sub-path (if any) + is treated as if it were closed. The content of a path is determined + either through the @scheme['even-odd] rule or the @scheme['winding] + rule, as selected at the time when the path is filled or used to + generate a region. + +A path is not connected to any particular @scheme[dc<%>] object, so + setting a @scheme[dc<%>] origin or scale does not affect path + operations. Instead, a @scheme[dc<%>]'s origin and scale apply at the + time that the path is drawn or used to set a region. + +@defconstructor/make[()]{ + +Creates a new path that contains no sub-paths (and no @tech{open +sub-path}). + +} + + +@defmethod[(append [path (is-a?/c dc-path%)]) + void?]{ + +Adds the sub-paths of @scheme[path] to @this-obj[]. @tech{Closed + sub-paths} of @scheme[path] are added as @tech{closed sub-paths} to + @this-obj[]. If both paths have an @tech{open sub-path}, then this + path's sub-path is extended by the given path's @tech{open sub-path}, + adding a line from this path's current ending point to the given + path's starting point. If only one of the paths has an @tech{open + sub-path}, then it becomes (or remains) this path's @tech{open + sub-path}. + +} + +@defmethod[(arc [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))] + [start-radians real?] + [end-radians real?] + [counter-clockwise? any/c #t]) + void?]{ + +Extends or starts the path's @tech{open sub-path} with a curve that + corresponds to a section of an ellipse. The ellipse is the one + bounded by a rectangle whose top-left corner is @math{(@scheme[x], + @scheme[y])} and whose dimensions are @scheme[width] by + @scheme[height]. The ellipse section starts a the angle + @scheme[start-radians] (@scheme[0] is three o'clock and half-pi is + twelve o'clock) and continues to the angle @scheme[end-radians]; if + @scheme[counter-clockwise?] is true, then the arc runs + counter-clockwise from @scheme[start-radians] to + @scheme[end-radians], otherwise it runs clockwise. + +If the path has no @tech{open sub-path}, a new one is started with the + arc's starting point. Otherwise, the arc extends the existing + sub-path, and the existing path is connected with a line to the arc's + starting point. + +} + +@defmethod[(close) + void?]{ + +Closes the path's @tech{open sub-path}. If the path has no @tech{open + sub-path}, @|MismatchExn|. + +} + +@defmethod[(curve-to [x1 real?] + [y1 real?] + [x2 real?] + [y2 real?] + [x3 real?] + [y3 real?]) + void?]{ + +Extends the path's @tech{open sub-path} with a Bezier curve to the + given point @math{(@scheme[x3],@scheme[y3])}, using the points + @math{(@scheme[x1], @scheme[y1])}$ and @math{(@scheme[x2], + @scheme[y2])}$ as control points. If the path has no @tech{open + sub-path}, @|MismatchExn|. + +} + +@defmethod[(ellipse [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))]) + void?]{ + +Closes the @tech{open sub-path}, if any, and adds a @tech{closed + sub-path} that represents an ellipse bounded by a rectangle whose + top-left corner is @math{(@scheme[x], @scheme[y])} and whose + dimensions are @scheme[width] by @scheme[height]. (This convenience + method is implemented in terms of @method[dc-path% close] and + @method[dc-path% arc].) + +} + +@defmethod[(get-bounding-box) + (values real? real? real? real?)]{ + +Returns a rectangle that encloses the path's points. The return + values are the left, top, width, and height of the rectangle. + +For curves within the path, the bounding box enclosed the two control + points as well as the start and end points. Thus, the bounding box + does not always tightly bound the path. + +} + +@defmethod[(line-to [x real?] + [y real?]) + void?]{ + +Extends the path's @tech{open sub-path} with a line to the given + point. If the path has no @tech{open sub-path}, @|MismatchExn|. + +} + +@defmethod[(lines [points (listof (is-a?/c point%))] + [xoffset real? 0] + [yoffset real? 0]) + void?]{ + +Extends the path's @tech{open sub-path} with a sequences of lines to + the given points. If the path has no @tech{open sub-path}, + @|MismatchExn|. (This convenience method is implemented in terms of + @method[dc-path% line-to].) + +} + +@defmethod[(move-to [x real?] + [y real?]) + void?]{ + +After closing the @tech{open sub-path}, if any, starts a new + @tech{open sub-path} with the given initial point. + +} + +@defmethod[(open?) + boolean?]{ + +Returns @scheme[#t] if the path has an @tech{open sub-path}, +@scheme[#f] otherwise. + +} + +@defmethod[(rectangle [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))]) + void?]{ + +Closes the @tech{open sub-path}, if any, and adds a closed path that + represents a rectangle whose top-left corner is @math{(@scheme[x], + @scheme[y])} and whose dimensions are @scheme[width] by + @scheme[height]. (This convenience method is implemented in terms of + @method[dc-path% close], @method[dc-path% move-to], and + @method[dc-path% line-to].) + +} + +@defmethod[(reset) + void?]{ + +Removes all sub-paths of the path. + +} + +@defmethod[(reverse) + void?]{ + +Reverses the order of all points in all sub-paths. If the path has an + @tech{open sub-path}, the starting point becomes the ending point, + and extensions to the @tech{open sub-path} build on this new ending + point. Reversing a @tech{closed sub-path} affects how it combines + with other sub-paths when determining the content of a path in + @scheme['winding] mode. + +} + +@defmethod[(rotate [radians real?]) + void?]{ + +Adjusts all points within the path (including all sub-paths), rotating + them @scheme[radians] counter-clockwise around @math{(0, 0)}. Future + additions to the path are not rotated by this call. + +} + +@defmethod[(rounded-rectangle [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))] + [radius real? -0.25]) + void?]{ + +Closes the @tech{open sub-path}, if any, and adds a @tech{closed + sub-path} that represents a round-cornered rectangle whose top-left + corner is @math{(@scheme[x] @scheme[y])} and whose dimensions are + @scheme[width] by @scheme[height]. (This convenience method is + implemented in terms of @method[dc-path% close], @method[dc-path% + move-to], @method[dc-path% arc], and @method[dc-path% line-to].) + +If @scheme[radius] is positive, the value is used as the radius of the + rounded corner. If @scheme[radius] is negative, the absolute value is + used as the @italic{proportion} of the smallest dimension of the + rectangle. + +If @scheme[radius] is less than @scheme[-0.5] or more than half of + @scheme[width] or @scheme[height], @|MismatchExn|. + +} + +@defmethod[(scale [x real?] + [y real?]) + void?]{ + +@index['("paths" "flipping")]{Adjusts} all points within the path + (including all sub-paths), multiplying each x-coordinate by + @scheme[x] and each y-coordinate by @scheme[y]. Scaling by a negative + number flips the path over the corresponding axis. Future additions + to the path are not scaled by this call. + +} + +@defmethod[(translate [x real?] + [y real?]) + void?]{ + +Adjusts all points within the path (including all sub-paths), shifting + then @scheme[x] to the right and @scheme[y] down. Future additions + to the path are not translated by this call. + +}} + diff --git a/collects/scribblings/gui/draw-classes.scrbl b/collects/scribblings/gui/draw-classes.scrbl new file mode 100644 index 0000000000..4f3ec40f8e --- /dev/null +++ b/collects/scribblings/gui/draw-classes.scrbl @@ -0,0 +1,49 @@ +#reader(lib "docreader.ss" "scribble") +@require["common.ss"] +@require["diagrams.ss"] + +@title[#:style '(toc quiet)]{Drawing Class Reference} + +@local-table-of-contents[] + +@require["bitmap-class.scrbl"] +@require["bitmap-dc-class.scrbl"] +@require["brush-class.scrbl"] +@require["brush-list-class.scrbl"] +@require["color-class.scrbl"] +@require["color-database-intf.scrbl"] +@require["dc-intf.scrbl"] +@require["dc-path-class.scrbl"] +@require["font-class.scrbl"] +@require["font-list-class.scrbl"] +@require["font-name-directory-intf.scrbl"] +@require["gl-config-class.scrbl"] +@require["gl-context-intf.scrbl"] +@require["pen-class.scrbl"] +@require["pen-list-class.scrbl"] +@require["point-class.scrbl"] +@require["post-script-dc-class.scrbl"] +@require["printer-dc-class.scrbl"] +@require["ps-setup-class.scrbl"] +@require["region-class.scrbl"] + +@include-class[bitmap%] +@include-class[bitmap-dc%] +@include-class[brush%] +@include-class[brush-list%] +@include-class[color%] +@include-class[color-database<%>] +@include-class[dc<%>] +@include-class[dc-path%] +@include-class[font%] +@include-class[font-list%] +@include-class[font-name-directory<%>] +@include-class[gl-config%] +@include-class[gl-context<%>] +@include-class[pen%] +@include-class[pen-list%] +@include-class[point%] +@include-class[post-script-dc%] +@include-class[printer-dc%] +@include-class[ps-setup%] +@include-class[region%] diff --git a/collects/scribblings/gui/draw-funcs.scrbl b/collects/scribblings/gui/draw-funcs.scrbl new file mode 100644 index 0000000000..d61bfe9555 --- /dev/null +++ b/collects/scribblings/gui/draw-funcs.scrbl @@ -0,0 +1,11 @@ +#reader(lib "docreader.ss" "scribble") +@require["common.ss"] + +@title{Drawing Function Reference} + +@local-table-of-contents[] + +@include-section["global-draw-funcs.scrbl"] +@include-section["post-script-funcs.scrbl"] +@include-section["draw-list-funcs.scrbl"] +@include-section["font-funcs.scrbl"] diff --git a/collects/scribblings/gui/draw-list-funcs.scrbl b/collects/scribblings/gui/draw-list-funcs.scrbl new file mode 100644 index 0000000000..848ab10c2a --- /dev/null +++ b/collects/scribblings/gui/draw-list-funcs.scrbl @@ -0,0 +1,36 @@ +#reader(lib "docreader.ss" "scribble") +@require["common.ss"] + +@title{Drawing Object Lists} + + +@defthing[the-brush-list (is-a?/c brush-list%)]{ + +See @scheme[brush-list%]. + +} + +@defthing[the-color-database (is-a?/c color-database<%>)]{ + +See @scheme[color-database<%>]. + +} + +@defthing[the-font-list (is-a?/c font-list%)]{ + +See @scheme[font-list%]. + +} + +@defthing[the-font-name-directory (is-a?/c font-name-directory<%>)]{ + +See @scheme[font-name-directory<%>]. + + +} + +@defthing[the-pen-list (is-a?/c pen-list%)]{ + +See @scheme[pen-list%]. + +} diff --git a/collects/scribblings/gui/draw-overview.scrbl b/collects/scribblings/gui/draw-overview.scrbl index b01daf4972..1ff96d6237 100644 --- a/collects/scribblings/gui/draw-overview.scrbl +++ b/collects/scribblings/gui/draw-overview.scrbl @@ -3,7 +3,7 @@ @require["common.ss"] @require["diagrams.ss"] -@title[#:tag "mred:drawing-toolbox"]{Drawing Toolbox Overview} +@title[#:tag "mr:drawing-overview"]{Drawing Guide} Drawing in MrEd requires a @deftech{device context} (@deftech{DC}), which is an instance of the @scheme[dc<%>] interface. For example, diff --git a/collects/scribblings/gui/drawing.scrbl b/collects/scribblings/gui/drawing.scrbl deleted file mode 100644 index 67cf845ffe..0000000000 --- a/collects/scribblings/gui/drawing.scrbl +++ /dev/null @@ -1,9 +0,0 @@ -#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"] diff --git a/collects/scribblings/gui/editor-classes.scrbl b/collects/scribblings/gui/editor-classes.scrbl new file mode 100644 index 0000000000..df7386fb16 --- /dev/null +++ b/collects/scribblings/gui/editor-classes.scrbl @@ -0,0 +1,44 @@ +#reader(lib "docreader.ss" "scribble") +@require["common.ss"] +@require["diagrams.ss"] + +@title[#:style '(toc quiet)]{Editor Class Reference} + +@local-table-of-contents[] + +@require["add-color-intf.scrbl"] +@require["editor-intf.scrbl"] +@;{ +@require["editor-admin-class.scrbl"] +@require["editor-canvas-class.scrbl"] +@require["editor-data-class.scrbl"] +@require["editor-data-class-class.scrbl"] +@require["editor-data-class-list-intf.scrbl"] +@require["editor-snip-editor-admin-intf.scrbl"] +@require["editor-snip-class.scrbl"] +@require["editor-stream-in-class.scrbl"] +@require["editor-stream-in-base-class.scrbl"] +@require["editor-stream-in-bytes-base-class.scrbl"] +@require["editor-stream-out-class.scrbl"] +@require["editor-stream-out-base-class.scrbl"] +@require["editor-stream-out-bytes-base-class.scrbl"] +@require["editor-wordbreak-map-class.scrbl"] +@require["image-snip-class.scrbl"] +@require["keymap-class.scrbl"] +@require["mult-color-intf.scrbl"] +@require["pasteboard-class.scrbl"] +@require["readable-snip-intf.scrbl"] +@require["snip-class.scrbl"] +@require["snip-admin-class.scrbl"] +@require["snip-class-class.scrbl"] +@require["snip-class-list-intf.scrbl"] +@require["string-snip-class.scrbl"] +@require["style-intf.scrbl"] +@require["style-delta-class.scrbl"] +@require["style-list-class.scrbl"] +@require["tab-snip-class.scrbl"] +@require["text-class.scrbl"] +} + +@include-class[add-color<%>] +@include-class[editor<%>] diff --git a/collects/scribblings/gui/editor-intf.scrbl b/collects/scribblings/gui/editor-intf.scrbl new file mode 100644 index 0000000000..b765b3b4f2 --- /dev/null +++ b/collects/scribblings/gui/editor-intf.scrbl @@ -0,0 +1,2361 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@definterface[editor<%> ()]{ + +The @scheme[editor<%>] interface is implemented by @scheme[text%] and + @scheme[pasteboard%]. + +@defmethod[(add-canvas [canvas (is-a?/c editor-canvas%)]) + void?]{ + +Adds a canvas to this editor's list of displaying canvases. (See +@method[editor<%> get-canvases].) + +Normally, this method is called only by @xmethod[editor-canvas% + set-editor]. + +} + +@defmethod[(add-undo [undoer (-> any)]) + void?]{ + +Adds an undoer procedure to the editor's undo stack. If an undo is + currently being performed, the undoer is added to the editor's redo + stack. The undoer is called by the system when it is undoing (or + redoing) changes to an editor, and when this undoer is the first item + on the undo (or redo) stack. + +The system automatically installs undo records to undo built-in editor + operations, such as inserts, deletes, and font changes. Install an + undoer only when it is necessary to maintain state or handle + operations that are not built-in. For example, in a program where the + user can assign labels to snips in a pasteboard, the program should + install an undoer to revert a label change. Thus, when a user changes + a snip's label and then selects @onscreen{Undo} (from a standard menu + bar), the snip's label will revert as expected. In contrast, there is + no need to install an undoer when the user moves a snip by dragging + it, because the system installs an appropriate undoer automatically. + +After an undoer returns, the undoer is popped off the editor's undo + (or redo) stack; if the return value is true, then the next undoer is + also executed as part of the same undo (or redo) step. The undoer + should return true if the action being undone was originally + performed as part of a @method[editor<%> begin-edit-sequence] and + @method[editor<%> end-edit-sequence] sequence. The return value + should also be true if the undone action was implicitly part of a + sequence. To extend the previous example, if a label change is paired + with a move to realign the snip, then the label-change undoer should + be added to the editor @italic{after} the call to @method[pasteboard% + move], and it should return @scheme[#t] when it is called. As a + result, the move will be undone immediately after the label change is + undone. (If the opposite order is needed, use @method[editor<%> + begin-edit-sequence] and @method[editor<%> end-edit-sequence] to + create an explicit sequence.) + +The system adds undoers to an editor (in response to other method + calls) without calling this method. + +} + +@defmethod[(adjust-cursor [event (is-a?/c mouse-event%)]) + (or/c (is-a?/c cursor%) false/c)]{ + +@methspec{ + +Gets a cursor to be used in the editor's @techlink{display}. If the + return value is @scheme[#f], a default cursor is used. + +See also @method[editor<%> set-cursor]. + +} +@methimpl{ + +If an overriding cursor has been installed with +@method[editor<%> set-cursor], then the installed cursor is returned. + +Otherwise, if the event is a dragging event, a snip in the editor has +the focus, and the snip's +@method[snip% adjust-cursor] method returns a cursor, that cursor is returned. + +Otherwise, if the cursor is over a snip and the snip's +@method[snip% adjust-cursor] method returns a cursor, that cursor is returned. + +Otherwise, if a cursor has been installed with +@method[editor<%> set-cursor], then the installed cursor is returned. + +Otherwise, if the cursor is over a clickback region in an editor, an +arrow cursor is returned. + +Finally, if none of the above cases apply, a default cursor is +returned. For a text editor, the default cursor is an I-beam. For a +pasteboard editor, the default cursor is an arrow. + +}} + +@defmethod[#:mode 'pubment + (after-edit-sequence) + void?]{ + +@methspec{ + +Called after a top-level edit sequence completes (involving unnested +@method[editor<%> begin-edit-sequence] and @method[editor<%> +end-edit-sequence]). + +See also @method[editor<%> on-edit-sequence]. + +} + +@methimpl{ + +Does nothing. + +} + +} + +@defmethod[#:mode 'pubment + (after-load-file [success? any/c]) + void?]{ + +@methspec{ + +Called just after the editor is loaded from a file. + +The argument to the method originally specified whether the save was +successful, but failures now trigger exceptions such that the method is +not even called. Consequently, the argument is always @scheme[#t]. + +See also +@method[editor<%> can-load-file?] and +@method[editor<%> on-load-file]. + +} + +@methimpl{ + +Does nothing. + +} +} + +@defmethod[#:mode 'pubment + (after-save-file [success? any/c]) + void?]{ + +@methspec{ + +Called just after the editor is saved to a file. + +The argument to the method originally specified whether the save was +successful, but failures now trigger exceptions such that the method is +not even called. Consequently, the argument is always @scheme[#t]. + +See also +@method[editor<%> can-save-file?] and +@method[editor<%> on-save-file]. + +} +@methimpl{ + +Does nothing. + +} +} + +@defmethod*[([(auto-wrap) + boolean?] + [(auto-wrap [auto-wrap? any/c]) + void?])]{ + +Enables or disables automatically calling @method[editor<%> +set-max-width] in response to @method[editor<%> on-display-size], or +gets the state of auto-wrapping. For text editors, this has the effect +of wrapping the editor's contents to fit in a canvas displaying the +editor (the widest one if multiple canvases display the editor). For +pasteboard editors, ``auto-wrapping'' merely truncates the area of the +pasteboard to match its canvas @techlink{display}. + +When the wrapping mode is changed, the @method[editor<%> +on-display-size] method is called immediately to update the editor's +maximum width. + +Auto-wrapping is initially disabled. + +} + +@defmethod[(begin-edit-sequence [undoable? any/c #t] + [interrupt-streak? any/c #t]) + void?]{ + +@methspec{ + +The @method[editor<%> begin-edit-sequence] and @method[editor<%> + end-edit-sequence] methods are used to bracket a set of editor + modifications so that the results are all displayed at once. The + commands may be nested arbitrarily deep. Using these functions can + greatly speed up displaying the changes. + +When an editor contains other editors, using @method[editor<%> + begin-edit-sequence] and @method[editor<%> end-edit-sequence] on the + main editor brackets some changes to the sub-editors as well, but it + is not as effective when a sub-editor changes as calling + @method[editor<%> begin-edit-sequence] and @method[editor<%> + end-edit-sequence] for the sub-editor. + +See also @method[editor<%> refresh-delayed?] and @method[editor<%> + in-edit-sequence?], and see @secref["mr:editorthreads"] for + information about edit sequences and refresh requests. + +If the @scheme[undoable?] flag is @scheme[#f], then the changes made + in the sequence cannot be reversed through the @method[editor<%> + undo] method. This flag is only effective for the outermost + @method[editor<%> begin-edit-sequence] when nested sequences are + used. Note that, for a @scheme[text%] object, the character-inserting + version of @method[text% insert] interferes with sequence-based undo + groupings. + +If the @scheme[interrupt-streak?] flag is @scheme[#f] and the sequence is + outermost, then special actions before and after the sequence count + as consecutive actions. For example, kills just before and after the + sequence are appended in the copy buffer. + +} +@methimpl{ + +Starts a sequence. + +}} + +@defmethod[(begin-write-header-footer-to-file [f (is-a?/c editor-stream-out%)] + [name string?] + [buffer (box/c (and/c exact? integer?))]) + void?]{ + +This method must be called before writing any special header data to a +stream. See @|filediscuss| and @method[editor<%> +write-headers-to-file] for more information. + +The @scheme[name] string must be a unique name that can be used by a + header reader to recognize the data. This method will store a value + in @scheme[buffer] that should be passed on to @method[editor<%> + end-write-header-footer-to-file]. + +} + +@defmethod[(blink-caret) + void?]{ + +@methspec{ + +Tells the editor to blink the selection caret. This method is +called periodically when the editor's @techlink{display} has the keyboard +focus. + +} +@methimpl{ + +Propagates the request to any snip with the editor-local focus. + +}} + +@defmethod[(can-do-edit-operation? [op (one-of/c 'undo 'redo 'clear 'cut 'copy 'paste + 'kill 'select-all 'insert-text-box + 'insert-pasteboard-box 'insert-image)] + [recursive? any/c #t]) + boolean?]{ +@methspec{ + +Checks whether a generic edit command would succeed for the editor. + This check is especially useful for enabling and disabling menus on + demand. See @method[editor<%> do-edit-operation] for information + about the @scheme[op] and @scheme[recursive?] arguments. + +} +@methimpl{ + +Allows the operation depending on the selection, whether the editor is +locked, etc. + +}} + +@defmethod[#:mode 'pubment + (can-load-file? [filename path?] + [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy)]) + boolean?]{ +@methspec{ + +Called just before the editor is loaded from a file. If the return +value is @scheme[#f], the file is not loaded. See also +@method[editor<%> on-load-file] and @method[editor<%> +after-load-file]. + +The @scheme[filename] argument is the name the file will be loaded + from. See @method[editor<%> load-file] for information about + @scheme[format]. + +Note that the @scheme[filename] argument cannot be a string; it must +be a path value. + +} +@methimpl{ + +Returns @scheme[#t]. + +}} + +@defmethod[#:mode 'pubment + (can-save-file? [filename path?] + [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy)]) + boolean?]{ +@methspec{ + +Called just before the editor is saved to a file. If the return value +is @scheme[#f], the file is not saved. See also @method[editor<%> +on-save-file] and @method[editor<%> after-save-file]. + +The @scheme[filename] argument is the name the file will be saved + to. See @method[editor<%> load-file] for information about + @scheme[format]. + +Note that the @scheme[filename] argument cannot be a string; it must + be a path value. + +} + +@methimpl{ + +Returns @scheme[#t]. + +}} + +@defmethod*[([(change-style [delta (or/c (is-a?/c style-delta%) false/c)]) + void?] + [(change-style [style (or/c (is-a?/c style<%>) false/c)]) + void?])]{ + +Changes the style for @techlink{items} in the editor, either by +applying a style delta or using a specific style. + +To change a large collection of snips from one style to another style, + consider providing a @scheme[style<%>] instance rather than a + @scheme[style-delta%] instance. Otherwise, @method[editor<%> + change-style] must convert the @scheme[style-delta%] instance to the + @scheme[style<%>] instance for every snip; this conversion consumes + both time and (temporary) memory. + +@MonitorMethod[@elem{The style within an editor} @elem{the + system (in response to other method calls)} @elem{@xmethod[text% on-change-style]} @elem{style}] + +} + +@defmethod[(clear) + void?]{ + +Deletes the currently selected @techlink{item}s. + +@|OnDeleteNote| + +} + +@defmethod[(clear-undos) + void?]{ + +Destroys the undo history of the editor. + +} + +@defmethod[(copy [extend? any/c #f] + [time (and/c exact? integer?) 0]) + void?]{ + +Copies @techlink{item}s into the clipboard. If @scheme[extend?] is not + @scheme[#f], the old clipboard contents are appended. + +The system may execute a copy (in response to other method calls) + without calling this method. To extend or re-implement copying, + override the @xmethod[text% do-copy] or @xmethod[pasteboard% do-copy] + method of an editor. + +See @|timediscuss| for a discussion of the @scheme[time] argument. If + @scheme[time] is outside the platform-specific range of times, + @|MismatchExn|. + + +} + +@defmethod[(copy-self) + (or/c (is-a?/c text%) (is-a?/c pasteboard%))]{ + +Creates a new editor with the same properties as this one. After an + editor is created (either a @scheme[text%] or @scheme[pasteboard%] + instance, as appropriate), the new editor is passed to + @method[editor<%> copy-self-to]. + +} + + +@defmethod[(copy-self-to [dest (or/c (is-a?/c text%) (is-a?/c pasteboard%))]) + void?]{ + +Copies the properties of @this-obj[] to @scheme[dest]. + +Each snip in @this-obj[] is copied and inserted into @scheme[dest]. +In addition, @this-obj[]'s filename, maximum undo history setting, +keymap, interactive caret threshold, and overwrite-styles-on-load +settings are installed into @scheme[dest]. Finally, @this-obj[]'s +style list is copied and the copy is installed as the style list for +@scheme[dest]. + +} + +@defmethod[(cut [extend? any/c #f] + [time (and/c exact? integer?) 0]) + void?]{ + +Copies and then deletes the currently selected @techlink{item}s. If + @scheme[extend?] is not @scheme[#f], the old clipboard contents are + appended. + +The system may execute a cut (in response to other method calls) + without calling this method. To extend or re-implement the copying + portion of the cut, override the @xmethod[text% do-copy] or + @xmethod[pasteboard% do-copy] method of an editor. To monitor + deletions in an editor, override @xmethod[text% on-delete] or + @xmethod[pasteboard% on-delete]. + +See @|timediscuss| for a discussion of the @scheme[time] argument. If + @scheme[time] is outside the platform-specific range of times, + @|MismatchExn|. + +} + +@defmethod[(dc-location-to-editor-location [x real?] + [y real?]) + (values real? real?)]{ + +Converts the given coordinates from top-level @techlink{display} + coordinates (usually canvas coordinates) to editor + @techlink{location} coordinates. The same calculation is performed + by @method[editor<%> global-to-local]. + +@|OVD| + +See also @method[editor<%> editor-location-to-dc-location]. + +} + +@defmethod[(default-style-name) + string?]{ + +Returns the name of a style to be used for newly inserted text, + etc. The default is @scheme["Standard"]. + +} + +@defmethod[(do-edit-operation [op (one-of/c 'undo 'redo 'clear 'cut 'copy 'paste + 'kill 'select-all 'insert-text-box + 'insert-pasteboard-box 'insert-image)] + [recursive? any/c #t] + [time (and/c exact? integer?) 0]) + void?]{ + +Performs a generic edit command. The @scheme[op] argument must be a +valid edit command, one of: + +@itemize{ +@item{@scheme['undo] --- undoes the last operation} +@item{@scheme['redo] --- undoes the last undo} +@item{@scheme['clear] --- deletes the current selection} +@item{@scheme['cut] --- cuts} +@item{@scheme['copy] --- copies} +@item{@scheme['paste] --- pastes} +@item{@scheme['kill] --- cuts to the end of the current line, or cuts a newline if there is only whitespace between the selection and end of line} +@item{@scheme['select-all] --- selects everything in the editor} +@item{@scheme['insert-text-box] --- inserts a text editor as an @techlink{item} in this editor; see also +@method[editor<%> on-new-box] .} +@item{@scheme['insert-pasteboard-box] --- inserts a pasteboard editor as an @techlink{item} in this editor; see also +@method[editor<%> on-new-box] .} +@item{@scheme['insert-image] --- gets a filename from the user and inserts the image as an @techlink{item} in this editor; see also +@method[editor<%> on-new-image-snip] .} +} + +If @scheme[recursive?] is not @scheme[#f], then the command is passed on to + any active snips of this editor (i.e., snips which own the caret). + +See @|timediscuss| for a discussion of the @scheme[time] argument. If + @scheme[time] is outside the platform-specific range of times, + @|MismatchExn|. + +} + +@defmethod[(editor-location-to-dc-location [x real?] + [y real?]) + (values real? real?)]{ + +Converts the given coordinates from editor @techlink{location} + coordinates to top-level @techlink{display} coordinates (usually + canvas coordinates). The same calculation is performed by + @method[editor<%> local-to-global]. + +@|OVD| + +See also @method[editor<%> dc-location-to-editor-location]. + +} + +@defmethod[(end-edit-sequence) + void?]{ + +See @method[editor<%> begin-edit-sequence]. + +} + +@defmethod[(end-write-header-footer-to-file [f (is-a?/c editor-stream-out%)] + [buffer-value (and/c exact? integer?)]) + void?]{ + +This method must be called after writing any special header data to a +stream. The @scheme[buffer-value] argument must be the value put in +the @scheme[buffer] argument box by @method[editor<%> +begin-write-header-footer-to-file]. + +See @|filediscuss| and @method[editor<%> write-headers-to-file] for +more information. + +} + + +@defmethod[(find-first-snip) + (or/c (is-a?/c snip%) false/c)]{ + +Returns the first snip in the editor, or @scheme[#f] if the editor is + empty. To get all of the snips in the editor, use the @xmethod[snip% + next] on the resulting snip. + +The first snip in a text editor is the one at @techlink{position} + 0. The first snip in a pasteboard is the frontmost + snip. (@|seesniporderdiscuss|) + +} + +@defmethod[(find-scroll-line [location real?]) + nonnegative-exact-integer?]{ + +Maps a vertical @techlink{location} within the editor to a vertical + scroll position. + +For @scheme[text%] objects: @|FCA| @|OVD| + +} + +@defmethod[(get-active-canvas) + (or/c (is-a?/c editor-canvas%) false/c)]{ + +If the editor is displayed in a canvas, this method returns the canvas + that most recently had the keyboard focus (while the editor was + displayed). If no such canvas exists, @scheme[#f] is returned. + +} + +@defmethod[(get-admin) + (or/c (is-a?/c editor-admin%) false/c)]{ + +Returns the @scheme[editor-admin%] object currently managing this + editor or @scheme[#f] if the editor is not displayed. + +} + +@defmethod[(get-canvas) + (or/c (is-a?/c editor-canvas%) false/c)]{ + +If @method[editor<%> get-active-canvas] returns a canvas, that canvas + is also returned by this method. Otherwise, if @method[editor<%> + get-canvases] returns a non-empty list, the first canvas in the list + is returned, otherwise @scheme[#f] is returned. + +} + +@defmethod[(get-canvases) + (listof (is-a?/c editor-canvas%))]{ + +Returns a list of canvases displaying the editor. An editor may be + displayed in multiple canvases and no other kind of @techlink{display}, or one + instance of another kind of @techlink{display} and no canvases. If the editor is + not displayed or the editor's current @techlink{display} is not a canvas, + @scheme[null] is returned. + +} + +@defmethod[(get-dc) + (or/c (is-a?/c dc<%>) false/c)]{ + +Typically used (indirectly) by snip objects belonging to the + editor. Returns a destination drawing context which is suitable for + determining display sizing information, or @scheme[#f] if the editor + is not displayed. + +} + +@defmethod[(get-descent) + (and/c real? (not/c negative?))]{ + +Returns the font descent for the editor. This method is primarily used + when an editor is an @techlink{item} within another editor. + +@|OVD| @FCAME[] + +} + +@defmethod[(get-extent [w (or/c (box/c (and/c real? (not/c negative?))) false/c)] + [h (or/c (box/c (and/c real? (not/c negative?))) false/c)]) + void?]{ + +Gets the current extent of the editor's graphical representation. +@boxisfillnull[(scheme w) @elem{the editor's width}] +@boxisfillnull[(scheme h) @elem{the editor's height}] + +@|OVD| @FCAME[] + +} + +@defmethod[(get-file [directory (or/c path? false/c)]) + (or/c path-string? false/c)]{ +@methspec{ + +Called when the user must be queried for a filename to load an + editor. A starting-directory path is passed in, but is may be + @scheme[#f] to indicate that any directory is fine. + +Note that the @scheme[directory] argument cannot be a string; it must + be a path value or @scheme[#f]. + +} +@methimpl{ + +Calls the global @scheme[get-file] procedure. + +If the editor is displayed in a single canvas, then the canvas's + top-level frame is used as the parent for the file dialog. Otherwise, + the file dialog will have no parent. + +}} + +@defmethod[(get-filename [temp (box/c (or/c any/c false/c)) #f]) + (or/c path-string? false/c)]{ + +Returns the path name of the last file saved from or loaded into this + editor, @scheme[#f] if the editor has no filename. + +@boxisfill[(scheme temp) @elem{@scheme[#t] if the filename is temporary or @scheme[#f] +otherwise}] + +} + +@defmethod[(get-flattened-text) + string?]{ + +Returns the contents of the editor in text form. See @|textdiscuss| for +a discussion of flattened vs. non-flattened text. + +} + + +@defmethod[(get-focus-snip) + (or/c (is-a?/c snip%) false/c)]{ + +@index['("keyboard focus" "snips")]{Returns} the snip within the + editor that gets the keyboard focus when the editor has the focus, or + @scheme[#f] if the editor does not delegate the focus. + +The returned snip might be an @scheme[editor-snip%] object. In that + case, the embedded editor might delegate the focus to one of its own + snips. However, the @method[editor<%> get-focus-snip] method returns + only the @scheme[editor-snip%] object, because it is the focus-owning + snip within the immediate editor. + +See also @method[editor<%> set-caret-owner]. + +} + + +@defmethod[(get-inactive-caret-threshold) + (one-of/c 'no-caret 'show-inactive-caret 'show-caret)]{ + +Returns the threshold for painting an inactive selection. This + threshold is compared with the @scheme[draw-caret] argument to + @method[editor<%> refresh] and if the argument is as least as large + as the threshold (but larger than @indexed-scheme['show-caret]), the + selection is drawn as inactive. + +See also @method[editor<%> set-inactive-caret-threshold] and + @|drawcaretdiscuss|. + +} + + +@defmethod[(get-keymap) + (or/c (is-a?/c keymap%) false/c)]{ + +Returns the main keymap currently used by the editor. + +} + + +@defmethod[(get-load-overwrites-styles) + boolean?]{ + +Reports whether named styles in the current style list are replaced by + @method[editor<%> load-file] when the loaded file contains style + specifications. + +See also @method[editor<%> set-load-overwrites-styles]. + +} + +@defmethod[(get-max-height) + (or/c (and/c real? (not/c negative?)) (one/of 'none))]{ + +Gets the maximum display height for the contents of the editor; zero or + @scheme['none] indicates that there is no maximum. + +} + +@defmethod[(get-max-undo-history) + (integer-in 0 100000)]{ + +Returns the maximum number of undoables that will be remembered by the + editor. Note that undoables are counted by insertion, deletion, + etc. events, not by the number of times that @method[editor<%> undo] + can be called; a single @method[editor<%> undo] call often reverses + multiple events at a time (such as when the user types a stream of + characters at once). + +} + +@defmethod[(get-max-view-size) + (values real? real?)]{ + +Returns the maximum visible area into which the editor is currently + being displayed, according to the editor's administrators. If the + editor has only one @techlink{display}, the result is the same as for + @method[editor<%> get-view-size]. Otherwise, the maximum width and + height of all the editor's displaying canvases is returned. + +@|OVD| + +If the @techlink{display} is an editor canvas, see also + @method[area-container<%> reflow-container]. + +} + +@defmethod[(get-max-width) + (or/c (and/c real? (not/c negative?)) (one/of 'none))]{ + +Gets the maximum display width for the contents of the editor; zero or + @scheme['none] indicates that there is no maximum. In a text editor, + zero of @scheme['none] disables automatic line breaking. + +} + +@defmethod[(get-min-height) + (or/c (and/c real? (not/c negative?)) (one/of 'none))]{ + +Gets the minimum display height for the contents of the editor; zero + or @scheme['none] indicates that there is no minimum. + +} + + +@defmethod[(get-min-width) + (or/c (and/c real? (not/c negative?)) (one/of 'none))]{ + +Gets the minimum display width for the contents of the editor; zero or + @scheme['none] indicates that there is no minimum. + +} + +@defmethod[(get-paste-text-only) + boolean?]{ + +If the result is @scheme[#t], then the editor accepts only plain-text + data from the clipboard. If the result is @scheme[#f], the editor + accepts both text and snip data from the clipboard. + +} + +@defmethod[(get-snip-data [thesnip (is-a?/c snip%)]) + (or/c (is-a?/c editor-data%) false/c)]{ + +@methspec{ + +Gets extra data associated with a snip (e.g., @techlink{location} + information in a pasteboard) or returns @scheme[#f] is there is no + information. See @|editordatadiscuss| for more information. + +} +@methimpl{ + +Returns @scheme[#f]. + +}} + + +@defmethod[(get-snip-location [thesnip (is-a?/c snip%)] + [x (or/c (box/c real?) false/c) #f] + [y (or/c (box/c real?) false/c) #f] + [bottom-right? any/c #f]) + boolean?]{ + +Gets the @techlink{location} of the given snip. If the snip is found in + the editor, @scheme[#t] is returned; otherwise, @scheme[#f] is returned. + +@boxisfillnull[(scheme x) @elem{the x-coordinate of the snip's @techlink{location}}] +@boxisfillnull[(scheme y) @elem{the y-coordinate of the snip's @techlink{location}}] + +If @scheme[bottom-right?] is not @scheme[#f], the values in the + @scheme[x] and @scheme[y] boxes are for the snip's bottom right + corner instead of its top-left corner. + +Obtaining the @techlink{location} if the bottom-right corner may + trigger delayed size calculations (including snips other than + the one whose @techlink{location} was requested). + +@|OVD| As a special case, however, a @scheme[pasteboard%] object + always reports valid answers when @scheme[bottom-right?] is @scheme[#f]. + @FCAME[] + +} + + +@defmethod[(get-space) + (and/c real? (not/c negative?))]{ + +Returns the maximum font space for the editor. This method is + primarily used when an editor is an @techlink{item} within another + editor. + +@|OVD| @FCAME[] + +} + +@defmethod[(get-style-list) + (is-a?/c style-list%)]{ + +Returns the style list currently in use by the editor. + +} + + +@defmethod[(get-view-size [w (or/c (box/c (and/c real? (not/c negative?))) false/c)] + [h (or/c (box/c (and/c real? (not/c negative?))) false/c)]) + void?]{ + +Returns the visible area into which the editor is currently being + displayed (according to the editor's administrator). See also + @method[editor-admin% get-view] . + +@boxisfillnull[(scheme w) @elem{the visible area width}] +@boxisfillnull[(scheme h) @elem{the visible area height}] + +@|OVD| + +If the @techlink{display} is an editor canvas, see also +@method[area-container<%> reflow-container]. + +} + +@defmethod[(global-to-local [x (or/c (box/c real?) false/c)] + [y (or/c (box/c real?) false/c)]) + void?]{ + +Converts the given coordinates from top-level @techlink{display} coordinates + (usually canvas coordinates) to editor @techlink{location} coordinates. The + same calculation is performed by +@method[editor<%> dc-location-to-editor-location]. + +@boxisfillnull[(scheme x) @elem{the translated x-coordinate of the value initially +in @scheme[x]}] +@boxisfillnull[(scheme y) @elem{the translated x-coordinate of the value initially +in @scheme[y]}] + +@|OVD| + +See also @method[editor<%> local-to-global]. + +} + +@defmethod[(in-edit-sequence?) + boolean?]{ + +Returns @scheme[#t] if updating on this editor is currently delayed + because @method[editor<%> begin-edit-sequence] has been called for + this editor. + +See also @method[editor<%> refresh-delayed?]. + +} + + +@defmethod[(insert [snip (is-a?/c snip%)]) + void?]{ + +Inserts data into the editor. A snip cannot be inserted into multiple + editors or multiple times within a single editor. + +@|OnInsertNote| + +} + + +@defmethod[(insert-box [type (one-of/c 'text 'pasteboard) 'text]) + void?]{ + +Inserts a box (a sub-editor) into the editor by calling +@method[editor<%> on-new-box], then passing along @scheme[type] and +inserts the resulting snip into the editor. + +@|OnInsertNote| + +} + + +@defmethod*[([(insert-file [filename path-string?] + [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'guess] + [show-errors? any/c #t]) + boolean?] + [(insert-file [port input-port] + [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'guess] + [show-errors? any/c #t]) + boolean?])]{ + +Inserts the content of a file or port into the editor (at the current + selection @techlink{position} in @scheme[text%] editors). The result + is @scheme[#t]; if an error occurs, an exception is raised. + +If @scheme[port] is supplied, it must support position setting with +@scheme[file-position]. + +For information on @scheme[format], see @method[editor<%> load-file]. +The @scheme[show-errors?] argument is no longer used. + +@|OnInsertNote| + +} + + +@defmethod[(insert-image [filename (or/c path-string? false/c) #f] + [type (one-of/c 'unknown 'gif 'jpeg 'xbm 'xpm 'bmp 'pict) 'unknown] + [relative-path? any/c #f] + [inline? any/c #t]) + void?]{ + +Inserts an image into the editor. + +If @scheme[filename] is @scheme[#f], then the +user is queried for a filename. The @scheme[kind] must one of +the symbols that can be passed to +@method[bitmap% load-file]. + +After the filename has been determined, an image is created by +calling +@method[editor<%> on-new-image-snip]. See also +@scheme[image-snip%]. + +@|OnInsertNote| + +} + +@defmethod[(insert-port [port input-port] + [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'guess] + [show-errors? any/c #t]) + (one-of/c 'standard 'text 'text-force-cr)]{ + +Use @method[editor<%> insert-file], instead. + +Inserts the content of a port into the editor (at the current + selection @techlink{position} in @scheme[text%] editors) without wrapping + the insert operations as an edit sequence. The result is the actual + format of the loaded content (which is different from the given + format type if the given format is @scheme['guess], @scheme['same], or + @scheme['copy]). + +The @scheme[port] must support position setting with @scheme[file-position]. + +For information on @scheme[format], see +@method[editor<%> load-file]. + +The @scheme[show-errors?] argument is no longer used. + +} + +@defmethod[(invalidate-bitmap-cache [x real? 0.0] + [y real? 0.0] + [width (or/c (and/c real? (not/c negative?)) (one/of 'end)) 'end] + [height (or/c (and/c real? (not/c negative?)) (one/of 'end)) 'end]) + void?]{ + +When @method[editor<%> on-paint] is overridden, call this method when + the state of @method[editor<%> on-paint]'s drawing changes. + +The @scheme[x], @scheme[y], @scheme[width], and @scheme[height] + arguments specify the area that needs repainting in editor + coordinates. If @scheme[width]/@scheme[height] is @scheme['end], then + the total height/width of the editor (as reported by + @method[editor<%> get-extent]) is used. Note that the editor's size + can be smaller than the visible region of its @techlink{display}. + +The default implementation triggers a redraw of the editor, either + immediately or at the end of the current edit sequence (if any) + started by @method[editor<%> begin-edit-sequence]. + +} + + +@defmethod[(is-locked?) + boolean?]{ + +Returns @scheme[#t] if the editor is currently locked, @scheme[#f] + otherwise. See @method[editor<%> lock] for more information. + +} + + +@defmethod[(is-modified?) + boolean?]{ + +Returns @scheme[#t] is the editor has been modified since the last + save or load (or the last call to @method[editor<%> set-modified] + with @scheme[#f]), @scheme[#f] otherwise. + +} + + +@defmethod[(kill [time (and/c exact? integer?) 0]) + void?]{ + +In a text editor, cuts to the end of the current line, or cuts a + newline if there is only whitespace between the selection and end of + line. Multiple consecutive kills are appended. In a pasteboard + editor, cuts the current selection. + +See @|timediscuss| for a discussion of the @scheme[time] argument. If + @scheme[time] is outside the platform-specific range of times, + @|MismatchExn|. + +See also @method[editor<%> cut]. + +@|OnDeleteNote| + +} + + +@defmethod[(load-file [filename (or/c path-string? false/c) #f] + [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'guess] + [show-errors? any/c #t]) + boolean?]{ + + +Loads a file into the editor and returns @scheme[#t]. If an error + occurs, an exception is raised. + +If @scheme[filename] is @scheme[#f], then the +internally stored filename will be used; if @scheme[filename] is @scheme[""] or +if the internal name is unset or temporary, then the user will be +prompted for a name. + +The possible values for @scheme[format] are listed below. A single set of +@scheme[format] values are used for loading and saving files: +@itemize{ + +@item{@scheme['guess] --- guess the format based on +extension and/or contents; when saving a file, this is the same as +@scheme['standard]} + +@item{@scheme['standard] --- read/write a standard file (binary format)} + +@item{@scheme['text] --- read/write a text file (@scheme[text%] only)} + +@item{@scheme['text-force-cr] --- read/write a text +file (@scheme[text%] only); when writing, change automatic +newlines (from word-wrapping) into real carriage returns} + +@item{@scheme['same] --- read in whatever format was last loaded or saved} + +@item{@scheme['copy] --- write using whatever +format was last loaded or saved, but do not change the modification +flag or remember @scheme[filename] (saving only)} + +} + +In a @scheme[text%] instance, the format returned from +@method[text% get-file-format] is always one of @scheme['standard], +@scheme['text], or +@scheme['text-force-cr]. + +The @scheme[show-errors?] argument is no longer used. + +The filename used to load the file can be retrieved with + @method[editor<%> get-filename]. For a @scheme[text%] instance, the + format can be retrieved with @method[text% get-file-format]. However, + if an error occurs while loading the file, the filename is set to + @scheme[#f]. + +See also @method[editor<%> on-load-file], @method[editor<%> + after-load-file], @method[editor<%> can-load-file?], and + @method[editor<%> set-load-overwrites-styles]. + +} + +@defmethod[(local-to-global [x (box/c real?)] + [y (box/c real?)]) + void?]{ + +Converts the given coordinates from editor @techlink{location} + coordinates to top-level @techlink{display} coordinates (usually + canvas coordinates). The same calculation is performed by + @method[editor<%> editor-location-to-dc-location]. + +@boxisfillnull[(scheme x) @elem{the translated x-coordinate of the value initially +in @scheme[x]}] +@boxisfillnull[(scheme y) @elem{the translated x-coordinate of the value initially +in @scheme[y]}] + +@|OVD| + +See also @method[editor<%> global-to-local]. + +} + + +@defmethod[(locations-computed?) + boolean?]{ + +Returns @scheme[#t] if all @techlink{location} information has been + computed after recent changes to the editor's content or to its + snips, @scheme[#f] otherwise. + +Location information is often computed on demand, and + @method[editor<%> begin-edit-sequence] tends to delay the + computation. + +When the editor is locked for reflowing, location information cannot + be recomputed. See also @|lockdiscuss|. + +} + + +@defmethod[(lock [lock? any/c]) + void?]{ + +Locks or unlocks the editor for modifications. If an editor is locked, + @italic{all} modifications are blocked, not just user modifications. + +See also @method[editor<%> is-locked?]. + +This method does not affect internal locks, as discussed in + @|lockdiscuss|. + +} + +@defmethod[(locked-for-flow?) + boolean?]{ + +Reports whether the editor is internally locked for flowing. See + @|lockdiscuss| for more information. + +} + + +@defmethod[(locked-for-read?) + boolean?]{ + +Reports whether the editor is internally locked for reading. See + @|lockdiscuss| for more information. + +} + + +@defmethod[(locked-for-write?) + boolean?]{ + +Reports whether the editor is internally locked for writing. See + @|lockdiscuss| for more information. + +} + + +@defmethod[(needs-update [snip (is-a?/c snip%)] + [localx real?] + [localy real?] + [w (and/c real? (not/c negative?))] + [h (and/c real? (not/c negative?))]) + void?]{ + +Typically called (indirectly) by a snip within the editor to force the +editor to be redrawn. + +The @scheme[localx], @scheme[localy], @scheme[width], and @scheme[height] + arguments specify the area that needs repainting in the coordinate + system of @scheme[snip]. + +@FCAME[] + +} + + +@defmethod[(num-scroll-lines) + nonnegative-exact-integer?]{ + +Reports the number of scroll positions available within the editor. + +For @scheme[text%] objects: @|FCA| @|EVD| + +} + + +@defmethod[#:mode 'pubment + (on-change) + void?]{ + +@methspec{ + +Called whenever any change is made to the editor that affects the way + the editor is drawn or the values reported for the + @techlink{location}/size of some snip in the editor. The + @method[editor<%> on-change] method is called just before the editor + calls its administrator's @method[editor-admin% needs-update] method + to refresh the editor's @techlink{display}, and it is also called + just before and after printing an editor. + +The editor is locked for writing and reflowing during the call to +@method[editor<%> on-change]. + +} +@methimpl{ + +Does nothing. + +}} + + +@defmethod[(on-char [event (is-a?/c key-event%)]) + void?]{ +@methspec{ + +Handles keyboard input to the editor. + +Consider overriding @method[editor<%> on-local-char] or +@method[editor<%> on-default-char] instead of this method. + +} +@methimpl{ + +Either passes this event on to a caret-owning snip or calls + @method[editor<%> on-local-char]. In the latter case, @scheme[text%] + first calls @scheme[hide-cursor-until-moved]. + +}} + +@defmethod[(on-default-char [event (is-a?/c key-event%)]) + void?]{ +@methspec{ + +Called by @method[editor<%> on-local-char] when the event is + @italic{not} handled by a caret-owning snip or by the keymap. + +} +@methimpl{ + +Does nothing. + +}} + +@defmethod[(on-default-event [event (is-a?/c mouse-event%)]) + void?]{ + +@methspec{ + +Called by @method[editor<%> on-local-event] when the event is + @italic{not} handled by a caret-owning snip or by the keymap. + +} +@methimpl{ + +Does nothing. See also @xmethod[text% on-default-event] and + @xmethod[pasteboard% on-default-event]. + +}} + + +@defmethod[#:mode 'pubment + (on-display-size) + void?]{ + +@methspec{ + +This method is called by the editor's @techlink{display} whenever the + display's size (as reported by @method[editor<%> get-view-size]) + changes, but it is called indirectly through @method[editor<%> + on-display-size-when-ready]. + +} +@methimpl{ + +If automatic wrapping is enabled (see @method[editor<%> auto-wrap] ) + then @method[editor<%> set-max-width] is called with the maximum + width of all of the editor's canvases (according to the + administrators; @xmethod[editor-canvas% call-as-primary-owner] is + used with each canvas to set the administrator and get the view + size). If the editor is displayed but not in a canvas, the unique + width is obtained from the editor's administrator (there is only + one). If the editor is not displayed, the editor's maximum width is + not changed. + +}} + + +@defmethod[(on-display-size-when-ready) + void?]{ + +Calls @method[editor<%> on-display-size] unless the editor is + currently in an edit sequence or currently being refreshed. In the + latter cases, the call to @method[editor<%> on-display-size] is + delegated to another thread; see @secref["mr:editorthreads"] for more + information. + +} + + +@defmethod[#:mode 'pubment + (on-edit-sequence) + void?]{ + +@methspec{ + +Called just after a top-level (i.e., unnested) edit sequence starts. + +During an edit sequence, all callbacks methods are invoked normally, + but it may be appropriate for these callbacks to delay computation + during an edit sequence. The callbacks must manage this delay + manually. Thus, when overriding other callback methods, such as + @xmethod[text% on-insert], @xmethod[pasteboard% on-insert], + @xmethod[text% after-insert], or @xmethod[pasteboard% after-insert], + consider overriding @method[editor<%> on-edit-sequence] and + @method[editor<%> after-edit-sequence] as well. + +``Top-level edit sequence'' refers to an outermost pair of + @method[editor<%> begin-edit-sequence] and @method[editor<%> + end-edit-sequence] calls. The embedding of an editor within another + editor does not affect the timing of calls to @method[editor<%> + on-edit-sequence], even if the embedding editor is in an edit + sequence. + +Pairings of @method[editor<%> on-edit-sequence] and @method[editor<%> + after-edit-sequence] can be nested if an @method[editor<%> + after-edit-sequence] starts a new edit sequence, since + @method[editor<%> after-edit-sequence] is called after an edit + sequence ends. However, @method[editor<%> on-edit-sequence] can never + start a new top-level edit sequence (except through an unpaired + @method[editor<%> end-edit-sequence]), because it is called after a + top-level edit sequence starts. + +} +@methimpl{ + +Does nothing. + +}} + + +@defmethod[(on-event [event (is-a?/c mouse-event%)]) + void?]{ + +@methspec{ + +Handles mouse input to the editor. The event's x and y coordinates + are in the @techlink{display}'s co-ordinate system; use the + administrator's @method[editor-admin% get-dc] method to obtain + translation arguments (or use @method[editor<%> + dc-location-to-editor-location]). + +Consider overriding @method[editor<%> on-local-event] or + @method[editor<%> on-default-event] instead of this method. + +} +@methimpl{ + +Either passes this event on to a caret-owning snip, selects a new + caret-owning snip (@scheme[text%] only) and passes the event on to + the selected snip, or calls @method[editor<%> on-local-event]. A new + caret-owning snip is selected in a @scheme[text%] object when the + click is on an event-handling snip, and not too close to the space + between snips (see @method[text% get-between-threshold] ). + +}} + + +@defmethod[(on-focus [on? any/c]) + void?]{ + +@index['("keyboard focus" "notification")]{Called} when the keyboard + focus changes into or out of this editor (and not to/from a snip + within the editor) with @scheme[#t] if the focus is being turned on, + @scheme[#f] otherwise. + +} + + +@defmethod[#:mode 'pubment + (on-load-file [filename path?] + [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy)]) + void?]{ +@methspec{ + +Called just before the editor is loaded from a file, after calling + @method[editor<%> can-load-file?] to verify that the load is + allowed. See also @method[editor<%> after-load-file]. + +The @scheme[filename] argument is the name the file will be loaded + from. See @method[editor<%> load-file] for information about + @scheme[format]. + +Note that the @scheme[filename] argument cannot be a string; it must + be a path value. + +} +@methimpl{ + +Does nothing. + +}} + +@defmethod[(on-local-char [event (is-a?/c key-event%)]) + void?]{ +@methspec{ + +Called by @method[editor<%> on-char] when the event is @italic{not} + handled by a caret-owning snip. + +Consider overriding @method[editor<%> on-default-char] instead of this + method. + +} +@methimpl{ + +Either lets the keymap handle the event or calls @method[editor<%> + on-default-char]. + +}} + + +@defmethod[(on-local-event [event (is-a?/c mouse-event%)]) + void?]{ +@methspec{ + +Called by @method[editor<%> on-event] when the event is @italic{not} + handled by a caret-owning snip. + +Consider overriding @method[editor<%> on-default-event] instead of + this method. + +} +@methimpl{ + +Either lets the keymap handle the event or calls + @method[editor<%> on-default-event]. + +}} + + +@defmethod[(on-new-box [type (one-of/c 'text 'pasteboard)]) + (is-a?/c snip%)]{ +@methspec{ + +Creates and returns a new snip for an embedded editor. This method is + called by @method[editor<%> insert-box]. + +} +@methimpl{ + +Creates a @scheme[editor-snip%] with either a sub-editor from + @scheme[text%] or sub-pasteboard from @scheme[pasteboard%], depending + on whether @scheme[type] is @scheme['text] or + @scheme['pasteboard]. The keymap (see @scheme[keymap%]) and style + list (see @scheme[style-list%]) for of the new sub-editor are set to + the keymap and style list of this editor. + +}} + + +@defmethod[(on-new-image-snip [filename (or/c path? false/c)] + [kind (one-of/c 'unknown 'gif 'jpeg 'xbm 'xpm 'bmp 'pict)] + [relative-path? any/c] + [inline? any/c]) + (is-a?/c image-snip%)]{ +@methspec{ + +Creates and returns a new instance of @scheme[image-snip%] for + @method[editor<%> insert-image]. + +Note that the @scheme[filename] argument cannot be a string; it must be a + path value. + +} +@methimpl{ + +Returns @scheme[(make-object image-snip% filename kind relative-path? inline?)]. + +}} + + +@defmethod[(on-paint [before? any/c] + [dc (is-a?/c dc<%>)] + [left real?] + [top real?] + [right real?] + [bottom real?] + [dx real?] + [dy real?] + [draw-caret (one-of/c 'no-caret 'show-inactive-caret 'show-caret)]) + void?]{ +@methspec{ + +Provides a way to add arbitrary graphics to an editor's @techlink{display}. This + method is called just before and just after every painting of the + editor. + +The @scheme[before?] argument is @scheme[#t] when the method is called just + before a painting the contents of the editor or @scheme[#f] when it is + called after painting. The @scheme[left], @scheme[top], @scheme[right], and + @scheme[bottom] arguments specify which region of the editor is being + repainted, in editor coordinates. To get the coordinates for + @scheme[dc], offset editor coordinates by adding (@scheme[dx], @scheme[dy]). + See @|drawcaretdiscuss| for information about @scheme[draw-caret]. + +The @method[editor<%> on-paint] method, together with the snips' + @method[snip% draw] methods, must be able to draw the entire state of + an editor. Never paint directly into an editor's @techlink{display} + canvas except from within @method[editor<%> on-paint] or + @method[snip% draw]. Instead, put all extra drawing code within + @method[editor<%> on-paint] and call @method[editor<%> + invalidate-bitmap-cache] when part of the @techlink{display} needs to + be repainted. + +If an @method[editor<%> on-paint] method uses cached + @techlink{location} information, then the cached information should + be recomputed in response to a call of @method[editor<%> + invalidate-bitmap-cache]. + +The @method[editor<%> on-paint] method must not make any assumptions + about the state of the drawing context (e.g., the current pen), + except that the clipping region is already set to something + appropriate. Before @method[editor<%> on-paint] returns, it must + restore any drawing context settings that it changes. + +The editor is internally locked for writing and reflowing during a + call to this method (see also @|lockdiscuss|). + +See also @method[editor<%> invalidate-bitmap-cache]. + +} +@methimpl{ + +Does nothing. + +}} + +@defmethod[#:mode 'pubment + (on-save-file [filename path?] + [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy)]) + void?]{ +@methspec{ + +Called just before the editor is saved to a file, after calling +@method[editor<%> can-save-file?] to verify that the save is +allowed. See also @method[editor<%> after-save-file]. + +The @scheme[filename] argument is the name the file will be saved +to. See @method[editor<%> load-file] for information about +@scheme[format]. + +Note that the @scheme[filename] argument cannot be a string; it must + be a path value. + + +} +@methimpl{ + +Does nothing. + +}} + + +@defmethod[#:mode 'pubment + (on-snip-modified [snip (is-a?/c snip%)] + [modified? any/c]) + void?]{ +@methspec{ + +This method is called whenever a snip within the editor reports that + it has been modified (by calling its adminstrator's + @method[snip-admin% modified] method). The method arguments are the + snip that reported a modification-state change, and the snip's new + modification state. + +See also @method[editor<%> set-modified]. + +} +@methimpl{ + +If @scheme[modified?] is true and the editor was not already modified + (i.e., its @method[editor<%> is-modified?] method reports + @scheme[#f]), then the @method[editor<%> set-modified] method is + called with @scheme[#t]. If the editor was already modified, then the + internal modify-counter is incremented. + +If @scheme[modified?] is @scheme[#f], and if the modify-counter is + @scheme[1], then the @method[editor<%> set-modified] method is called + with @scheme[#f] (on the assumption that the modify-counter was set + to @scheme[1] by an earlier call to this method for the same snip). + +}} + +@defmethod[(own-caret [own? any/c]) + void?]{ +@methspec{ + +Tells the editor to display or not display the caret or selection. + +@MonitorMethod[@elem{The focus state of an editor} @elem{by the system} @elem{@method[editor<%> on-focus]} @elem{focus}] + +} +@methimpl{ + +Propagates the flag to any snip with the editor-local focus. If no + sub-editors are active, the editor assumes the caret ownership. + +}} + + +@defmethod[(paste [time (and/c exact? integer?) 0]) + void?]{ + +Pastes the current contents of the clipboard into the editor. + +See @|timediscuss| for a discussion of the @scheme[time] argument. If + @scheme[time] is outside the platform-specific range of times, + @|MismatchExn|. + +The system may execute a paste (in response to other method calls) + without calling this method. To extend or re-implement copying, + override the @xmethod[text% do-paste] or @xmethod[pasteboard% + do-paste] method. + +See also @method[editor<%> get-paste-text-only]. + +} + + +@defmethod[(paste-x-selection [time (and/c exact? integer?) 0]) + void?]{ + +Like @method[editor<%> paste], but under X, uses the X selection +instead of the X clipboard. + +See @|timediscuss| for a discussion of the @scheme[time] argument. If + @scheme[time] is outside the platform-specific range of times, + @|MismatchExn|. + +To extend or re-implement copying, override the @xmethod[text% + do-paste-x-selection] or @xmethod[pasteboard% do-paste-x-selection] + method. + +} + + +@defmethod[(print [interactive? any/c #t] + [fit-on-page? any/c #t] + [output-mode (one-of/c 'standard 'postscript) 'standard] + [parent (or/c (or/c @scheme[frame%] (is-a?/c dialog%)) false/c) #f] + [force-ps-page-bbox? any/c #t] + [as-eps? any/c #f]) + void?]{ + +Prints the editor. + +If @scheme[interactive?] is true and a PostScript file is created, the + is given a dialog for adjusting printing parameters; see also + @scheme[get-ps-setup-from-user]. Otherwise, if a PostScript file is + created, the settings returned by @scheme[current-ps-setup] are + used. (The user may still get a dialog to select an output file name; + see @scheme[post-script-dc%] for more details.) + +If @scheme[fit-on-page?] is a true value, then during printing for a + @scheme[text%] editor, the editor's maximum width is set to the width + of the page (less margins) and the autowrapping bitmap is removed. + +The @scheme[output-mode] setting is used for Windows and + Mac OS X. It determines whether the output is generated + directly as a PostScript file (using MrEd's built-in PostScript + system) or generated using the platform-specific standard printing + mechanism. The possible values are + +@itemize{ + + @item{@scheme['standard] --- print using the platform-standard + mechanism (via a @scheme[printer-dc%]) under Windows and + Mac OS X, PostScript for Unix (via a @scheme[post-script-dc%])} + + @item{@scheme['postscript] --- print to a PostScript file (via a + @scheme[post-script-dc%])} + +} + +If @scheme[parent] is not @scheme[#f], it is used as the parent window + for configuration dialogs (for either PostScript or platform-standard + printing). If @scheme[parent] is @scheme[#f] and if the editor is + displayed in a single canvas, then the canvas's top-level frame is + used as the parent for configuration dialogs. Otherwise, + configuration dialogs will have no parent. + +The @scheme[force-ps-page-bbox?] argument is used for PostScript + printing, and is used as the third initialization argument when + creating the @scheme[post-script-dc%] instance. Unless it is + @scheme[#f], the bounding-box of the resulting PostScript file is set + to the current paper size. + +The @scheme[as-eps?] argument is used for PostScript printing, and is + used as the fourth initialization argument when creating the + @scheme[post-script-dc%] instance. Unless it is @scheme[#f], the + resulting PostScript file is identified as Encapsulated PostScript + (EPS). + +The printing margins are determined by @method[ps-setup% + get-editor-margin] in the current @scheme[ps-setup%] object (as + determined by @scheme[current-ps-setup]). + +} + + +@defmethod[(print-to-dc [dc (is-a?/c dc<%>)]) + void?]{ + +Prints the editor into the given drawing context. See also + @method[editor<%> print]. + +} + + +@defmethod[(put-file [directory (or/c path? false/c)] + [default-name (or/c path? false/c)]) + (or/c path-string? false/c)]{ +@methspec{ + +Called when the user must be queried for a filename to save an + editor. Starting-directory and default-name paths are passed in, + but either may be @scheme[#f] to indicate that any directory is fine or + there is no default name. + +Note that the @scheme[directory] and @scheme[filename] arguments + cannot be strings; each must be a path value. + +} +@methimpl{ + +Calls the global @scheme[put-file] procedure. + +If the editor is displayed in a single canvas, then the canvas's + top-level frame is used as the parent for the file dialog. Otherwise, + the file dialog will have no parent. + +}} + + +@defmethod[(read-footer-from-file [stream (is-a?/c editor-stream-in%)] + [name string?]) + boolean?]{ + +See @method[editor<%> read-header-from-file]. + +} + + +@defmethod[(read-from-file [stream (is-a?/c editor-stream-in%)] + [overwrite-styles? any/c #t]) + boolean?]{ + +Reads new contents for the editor from a stream. The return value is + @scheme[#t] if there are no errors, @scheme[#f] otherwise. See also + @|filediscuss|. + +The stream provides either new mappings for names in the editor's + style list, or it indicates that the editor should share a + previously-read style list (depending on how style lists were shared + when the editor was written to the stream; see also @method[editor<%> + write-to-file]). + +@itemize{ + + @item{In the former case, if the @scheme[overwrite-styles?] argument + is @scheme[#f], then each style name in the loaded file that is already + in the current style list keeps its current style. Otherwise, + existing named styles are overwritten with specifications from the + loaded file.} + + @item{In the latter case, the editor's style list will be changed to + the previously-read list.} + +} +} + + +@defmethod[(read-header-from-file [stream (is-a?/c editor-stream-in%)] + [name string?]) + boolean?]{ + +Called to handle a named header that is found when reading editor data + from a stream. The return value is @scheme[#t] if there are no errors, + @scheme[#f] otherwise. + +Override this method only to embellish the file format with new header + information. Always call the inherited method if the derived reader + does not recognize the header. + +See also @|filediscuss|. +} + + +@defmethod[(redo) + void?]{ + +Undoes the last undo, if no other changes have been made since. See + @method[editor<%> undo] for information about Emacs-style undo. If + the editor is currently performing an undo or redo, the method call + is ignored. + +The system may perform a redo without calling this method in response + to other method calls. Use methods such as + @method[editor<%> on-change] to monitor editor content changes. + +See also @method[editor<%> add-undo]. + +} + + +@defmethod[(refresh [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))] + [draw-caret (one-of/c 'no-caret 'show-inactive-caret 'show-caret)] + [background (or/c (is-a?/c color%) false/c)]) + void?]{ + +Repaints a region of the editor, generally called by an editor + administrator. See @secref["mr:editorthreads"] for information about + edit sequences and refresh requests. + +The @scheme[x], @scheme[y], @scheme[width], and @scheme[height] arguments specify + the area that needs repainting in editor coordinates. + +See @|drawcaretdiscuss| for information about @scheme[draw-caret]. + +The @scheme[background] color corresponds to the background of the + @techlink{display}; if it is @scheme[#f], then the display is transparent. + An editor should use the given background color as its own + background (or not paint the background of @scheme[background] is + @scheme[#f]). + +} + + +@defmethod[(refresh-delayed?) + boolean?]{ + +Returns @scheme[#t] if updating on this editor is currently + delayed. Updating may be delayed because @method[editor<%> + begin-edit-sequence] has been called for this editor, or because the + editor has no administrator, or because the editor's administrator + returns @scheme[#t] from its @method[editor-admin% refresh-delayed?] + method. (The administrator might return @scheme[#t] because an + enclosing editor's refresh is delayed.) + +See also @method[editor<%> in-edit-sequence?]. + +} + + +@defmethod[(release-snip [snip (is-a?/c snip%)]) + void?]{ + +Requests that the specified snip be deleted and released from the + editor. If this editor is not the snip's owner or if the snip cannot + be released, then @scheme[#f] is returned. Otherwise, @scheme[#t] is + returned and the snip is no longer owned. + +See also @xmethod[snip-admin% release-snip] . + +} + + +@defmethod[(remove-canvas [canvas (is-a?/c editor-canvas%)]) + void?]{ + +Removes a canvas from this editor's list of displaying canvases. (See + @method[editor<%> get-canvases].) + +Normally, this method is called only by @xmethod[editor-canvas% + set-editor]. + +} + + +@defmethod[(resized [snip (is-a?/c snip%)] + [redraw-now? any/c]) + void?]{ + +Called (indirectly) by snips within the editor: it forces a + recalculation of the display information in which the specified snip + has changed its size. + +If @scheme[redraw-now?] is @scheme[#f], the editor will require + another message to repaint itself. (See also @method[editor<%> + needs-update].) + +} + + +@defmethod[(save-file [filename (or/c path-string? false/c) #f] + [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'same] + [show-errors? any/c #t]) + boolean?]{ + +Saves the editor into a file and returns @scheme[#t]. If an error + occurs, an exception is raised. + +If @scheme[filename] is @scheme[#f], then the internally stored filename + will be used; if @scheme[filename] is @scheme[""] or if the internal name + is unset or temporary, then the user will be prompted for a name. + The possible values for @scheme[format] are described at +@method[editor<%> load-file]. + +The filename and format used to save the file can be retrieved with + @method[editor<%> get-filename]. In a @scheme[text%] instance, the + format can be retrieved with @method[text% get-file-format]. + +See also @method[editor<%> on-save-file], @method[editor<%> + after-save-file], and @method[editor<%> can-save-file?]. + +Under Mac OS X, the file's type signature is set to @scheme["TEXT"] + for a text-format file or @scheme["WXME"] for a standard-format + (binary) file. + +The @scheme[show-errors?] argument is no longer used. + +} + + +@defmethod[(save-port [port output-port] + [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'same] + [show-errors? any/c #t]) + boolean?]{ + +Saves the editor into a port and returns @scheme[#t]. If an error + occurs, an exception is raised. + +The possible values for @scheme[format] are described at +@method[editor<%> load-file]. + +The @scheme[show-errors?] argument is no longer used. + +} + + +@defmethod[(scroll-line-location [pos (and/c exact? integer?)]) + (and/c real? (not/c negative?))]{ + +Maps a vertical scroll position to a vertical @techlink{location} + within the editor. + +For @scheme[text%] objects: @|FCA| @|EVD| + +} + + +@defmethod[(scroll-to [snip (is-a?/c snip%)] + [localx real?] + [localy real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))] + [refresh? any/c] + [bias (one-of/c 'start 'end 'none) 'none]) + boolean?]{ + +Called (indirectly) by snips within the editor: it causes the editor + to be scrolled so that a given @techlink{location} range within a + given snip is visible. If the editor is scrolled, @scheme[#t] is + returned, otherwise @scheme[#f] is returned. + +The @scheme[localx], @scheme[localy], @scheme[width], and @scheme[height] + arguments specify the area that needs to be visible in @scheme[snip]'s + coordinate system. + +When the specified region cannot fit in the visible area, @scheme[bias] + indicates which end of the region to display. When @scheme[bias] is + @scheme['start], then the top-left of the region is + displayed. When @scheme[bias] is @scheme['end], then the + bottom-right of the region is displayed. Otherwise, @scheme[bias] must + be @scheme['none]. + +} + + +@defmethod[(select-all) + void?]{ + +Selects all data in the editor + +} + +@defmethod[(set-active-canvas [canvas (is-a?/c editor-canvas%)]) + void?]{ + +Sets the active canvas for this editor. (See @method[editor<%> + get-active-canvas].) + +Normally, this method is called only by @xmethod[editor-canvas% + on-focus] in an editor canvas that is displaying an editor. + +} + +@defmethod[(set-admin [admin (or/c (is-a?/c editor-admin%) false/c)]) + void?]{ + +Sets the editor's administrator. This method is only called by an + administrator. + +@Unmonitored[@elem{The administrator of an editor} @elem{by the +system} @elem{the administrator changes} @elem{@method[editor<%> +get-admin]}] + +} + + +@defmethod[(set-caret-owner [snip (or/c (is-a?/c snip%) false/c)] + [domain (one-of/c 'immediate 'display 'global) 'immediate]) + void?]{ + +Attempts to give the keyboard focus to @scheme[snip]. If @scheme[snip] is + @scheme[#f], then the caret is taken away from any snip in the editor + that currently has the caret and restored to this editor. + +If the keyboard focus is moved to @scheme[snip] and the editor has the + real keyboard focus, the @method[snip% own-caret] method of the snip + will be called. + +If @scheme[#f] is provided as the new owner, then the local focus is + moved to the editor itself. Otherwise, the local focus is moved to + the specified snip. + +The domain of focus-setting is one of: + +@itemize{ + + @item{@scheme['immediate] --- only set the focus owner within the + editor} + + @item{@scheme['display] --- make this editor or the new focus + owner get the keyboard focus among the editors in this editor's + @techlink{display} (if this is an embedded editor)} + + @item{@scheme['global] --- make this editor or the new focus + owner get the keyboard focus among all elements in the editor's frame} + +} + +@MonitorMethod[@elem{The focus state of an editor} @elem{by the +system} @elem{@method[editor<%> on-focus]} @elem{focus}] + +See also @method[editor<%> get-focus-snip]. + +} + + +@defmethod[(set-cursor [cursor (or/c (is-a?/c cursor%) false/c)] + [override? any/c @scheme[#t]]) + void?]{ + +Sets the custom cursor for the editor to @scheme[cursor]. If + @scheme[override?] is a true value and @scheme[cursor] is not + @scheme[#f], then this cursor overrides cursor settings in embedded + editors. + +If the custom cursor is @scheme[#f], the current cursor is removed, + and a cursor is selected automatically by the editor (depending on + whether the cursor is pointing at a clickback). See @method[editor<%> + adjust-cursor] for more information about the default selection. + +An embedding editor's custom cursor can override the cursor of an + embedded editor---even if the embedded editor has the caret---if + the cursor is specified as an overriding cursor. + +} + + +@defmethod[(set-filename [filename (or/c path-string? false/c)] + [temporary? any/c #f]) + void?]{ + +Sets the filename to @scheme[filename]. If @scheme[filename] is + @scheme[#f] or @scheme[temporary?] is a true value, then the user + will still be prompted for a name on future calls to + @method[editor<%> save-file] and @method[editor<%> load-file]. + +This method is also called when the filename changes through any + method (such as @method[editor<%> load-file]). + +} + + +@defmethod[(set-inactive-caret-threshold [threshold (one-of/c 'no-caret 'show-inactive-caret 'show-caret)]) + void?]{ + +Sets the threshold for painting an inactive selection. See + @method[editor<%> get-inactive-caret-threshold] for more information. + +} + + +@defmethod[(set-keymap [keymap (or/c (is-a?/c keymap%) false/c) #f]) + void?]{ + +Sets the current keymap for the editor. A @scheme[#f] argument removes + all key mapping. + +} + + +@defmethod[(set-load-overwrites-styles [overwrite? any/c]) + void?]{ + +Determines whether named styles in the current style list are replaced + by @method[editor<%> load-file] when the loaded file contains style + specifications. + +See also @method[editor<%> get-load-overwrites-styles] and + @method[editor<%> read-from-file]. + +} + + +@defmethod[(set-max-height [width (or/c (and/c real? (not/c negative?)) (one/of 'none))]) + void?]{ + +Sets the maximum display height for the contents of the editor. A + value less or equal to @scheme[0] indicates that there is no maximum. + +Setting the height is disallowed when the editor is internally locked + for reflowing (see also @|lockdiscuss|). + +} + + +@defmethod[(set-max-undo-history [count (or/c nonnegative-exact-integer? (one/of 'forever))]) + void?]{ + +Sets the maximum number of undoables that will be remembered by the + editor. The default is @scheme[0], which disables undo. The symbol + @indexed-scheme['forever] is accepted as a synonym for a very large + number. + +} + + +@defmethod[(set-max-width [width (or/c (and/c real? (not/c negative?)) (one/of 'none))]) + void?]{ + +Sets the maximum display width for the contents of the editor; + zero or @scheme['none] indicates that there is no maximum. In a + text editor, having no maximum disables automatic line breaking, + and the minimum (positive) maximum width depends on the width of the + autowrap bitmap. + +Setting the width is disallowed when the editor is internally locked + for reflowing (see also @|lockdiscuss|). + +See also @method[text% set-autowrap-bitmap]. + +} + +@defmethod[(set-min-height [width (or/c (and/c real? (not/c negative?)) (one/of 'none))]) + void?]{ + +Sets the minimum display height for the contents of the editor; zero + or @scheme['none] indicates that there is no minimum. + +Setting the height is disallowed when the editor is internally locked + for reflowing (see also @|lockdiscuss|). + +} + +@defmethod[(set-min-width [width (or/c (and/c real? (not/c negative?)) (one/of 'none))]) + void?]{ + +Sets the minimum display width for the contents of the editor; zero or + @scheme['none] indicates that there is no minimum. + +Setting the width is disallowed when the editor is internally locked +for reflowing (see also @|lockdiscuss|). + +} + +@defmethod[(set-modified [modified? any/c]) + void?]{ + +Sets the modified state of the editor. Usually, the state is changed + automatically after an insertion, deletion, or style change by + calling this method. (This method is also called when the + modification state changes through @italic{any} method.) This method + is usually not called when the state of the flag is not changing. + +See also @method[editor<%> is-modified?] and @method[editor<%> +on-snip-modified]. + +When @scheme[modified?] is true, then an internal modify-counter is + set to @scheme[1]. + +When @scheme[modified?] is @scheme[#f] and the editor's undo or redo + stack contains a system-created undoer that resets the modified state + (because the preceding undo or redo action puts the editor back to a + state where the modification state was @scheme[#f]), the undoer is + disabled. + +Regardless of the value of @scheme[modified?], the editor's + adminstrator's @method[editor-admin% modified] method is called. + +Finally, if @scheme[modified?] is @scheme[#f] and the internal + modify-counter is set to @scheme[0], then the @method[snip% + set-unmodified] method is called on every snip within the editor. + +} + + +@defmethod[(set-paste-text-only [text-only? any/c]) + void?]{ + +Sets whether the editor accepts only text from the clipboard, or both + text and snips. By default, an editor accepts both text and + snips. + +See also @method[editor<%> get-paste-text-only]. + +} + +@defmethod[(set-snip-data [thesnip (is-a?/c snip%)] + [data (is-a?/c editor-data%)]) + void?]{ + +Sets extra data associated with the snip (e.g., @techlink{location} + information in a pasteboard). See @|editordatadiscuss| for more + information. + +} + + +@defmethod[(set-style-list [style-list (is-a?/c style-list%)]) + void?]{ + +Sets the editor's style list. Styles currently in use with the old + style list will be ``moved'' to the new style list. In this ``move,'' + if a named style already exists in the new style list, then the new + style with the same name will be used in place of the old style. + +Setting the style list is disallowed when the editor is internally + locked for reflowing (see also @|lockdiscuss|). + +} + + +@defmethod[(style-has-changed [style (or/c (is-a?/c style<%>) false/c)]) + void?]{ + +Notifies the editor that a style in its style list has changed. This + method is automatically registered with the editor's style list using + @xmethod[style-list% notify-on-change] and automatically deregistered + when the style list is removed from the editor. + +See @xmethod[style-list% notify-on-change] for more information. + +} + + +@defmethod[(undo) + void?]{ + +Undoes the last editor change, if undos have been enabled by calling + @method[editor<%> set-max-undo-history] with a non-zero integer. + +If the editor is currently performing an undo or redo, the method call + is ignored. + +The user may enable Emacs-style undo for editors; see + @|mrprefsdiscuss|. Normally, undo operations add to the redo stack + (see @method[editor<%> redo]), and any undoable (non-undo) operation + clears the redo stack. With Emacs-style undo, the redo stack is added + back to the undo stack, along with the original undos, so that a + complete history is kept in the undo stack. + +The system may perform an undo without calling this method in response + to other method calls. Use methods such as + @method[editor<%> on-change] to monitor editor content changes. + +See also @method[editor<%> add-undo] . + +} + + +@defmethod[(write-footers-to-file [stream (is-a?/c editor-stream-out%)]) + boolean?]{ + +See @method[editor<%> write-headers-to-file]. + +} + + +@defmethod[(write-headers-to-file [stream (is-a?/c editor-stream-out%)]) + boolean?]{ + +@methspec{ + +Called when the editor is being saved to a file. The return value is + @scheme[#t] if there are no errors, @scheme[#f] otherwise. Override + this method to add custom header data to a file, but always call the + inherited method so that it can write its own extra headers. + +To write a header item, call @method[editor<%> + begin-write-header-footer-to-file], passing a box for an + integer. Then write the header data and end by calling + @method[editor<%> end-write-header-footer-to-file], passing back the + integer that was put into the box. Follow this procedure correctly + or the file will be corrupted. + +} +@methimpl{ + +Does nothing. + +}} + +@defmethod[(write-to-file [stream (is-a?/c editor-stream-out%)]) + boolean?]{ + +Writes the current editor contents to the given stream. The return + value is @scheme[#t] if there are no errors, @scheme[#f] otherwise. See + also @|filediscuss|. + +If the editor's style list has already been written to the stream, it + is not re-written. Instead, the editor content indicates that the + editor shares a previously-written style list. This sharing will be + recreated when the stream is later read. +}} diff --git a/collects/scribblings/gui/editor-overview.scrbl b/collects/scribblings/gui/editor-overview.scrbl new file mode 100644 index 0000000000..7771b6d4d7 --- /dev/null +++ b/collects/scribblings/gui/editor-overview.scrbl @@ -0,0 +1,752 @@ +#reader(lib "docreader.ss" "scribble") +@require[(lib "bnf.ss" "scribble")] +@require["common.ss"] + +@title[#:tag "mr:editor-overview"]{Editor Guide} + +The editor toolbox provides a foundation for two common kinds of + applications: + +@itemize{ + + @item{@italic{Programs that need a sophisticated text editor} --- + The simple text field control is inadequate for text-intensive + applications. Many programs need editors that can handle multiple + fonts and non-text items.} + + @item{@italic{Programs that need a canvas with dragable objects} --- + The drawing toolbox provides a generic drawing surface for plotting + lines and boxes, but many applications need an interactive canvas, + where the user can drag and resize individual objects.} + +} + +Both kinds of applications need an extensible editor that can handle + text, images, programmer-defined items, and even embedded + editors. The difference between them is the layout of items. MrEd + therefore provides two kinds of editors via two classes: + +@itemize{ + + @item{@scheme[text%] --- in a @deftech{text editor}, items are + automatically positioned in a paragraph flow.} + + @item{@scheme[pasteboard%] --- in a @deftech{pasteboard editor}, + items are explicitly positioned and dragable.} + +} + +MrEd's editor architecture addresses the full range of real-world + issues for an editor---including cut-and-paste, extensible file + formats, and layered text styles---while supporting a high level of + extensibility. Unfortunately, the system is fairly complex as a + result, and using the editor classes effectively requires a solid + understanding of the structure and terminology of the editor + toolbox. Nevertheless, enough applications fit one (or both) of the + descriptions above to justify the depth and complexity of the toolbox + and the learning investment required to use it. + +A brief example illustrates how MrEd editors work. To start, an editor + needs an @scheme[editor-canvas%] to display its contents. Then, we + can create a text editor and install it into the canvas: + +@schemeblock[ +(define f (new frame% [label "Simple Edit"] + [width 200] + [height 200])) +(define c (new editor-canvas% [parent f])) +(define t (new text%)) +(send c #,(:: editor-canvas% set-editor) t) +(send f #,(:: top-level-window<%> show) #t) +] + +At this point, the editor is fully functional: the user can type text + into the editor, but no cut-and-paste operations are available. We + can support all of the standard operations on an editor via the + menu bar: + +@schemeblock[ +(define mb (new menu-bar% [parent f])) +(define m-edit (new menu% [label "Edit"] [parent mb])) +(define m-font (new menu% [label "Font"] [parent mb])) +(append-editor-operation-menu-items m-edit #f) +(append-editor-font-menu-items m-font) +] + +Now, the standard cut and paste operations work, and the user can even + set font styles. The user can also insert an embedded editor by + selecting @onscreen{Insert Text} from the @onscreen{Edit} menu; after + selecting the menu item, a box appears in the editor with the caret + inside. Typing with the caret in the box stretches the box as text is + added, and font operations apply wherever the caret is active. Text + on the outside of the box is rearranged as the box changes + sizes. Note that the box itself can be copied and pasted. + +The content of an editor is made up of @deftech{snips}. An embedded + editor is a single snip from the embedding editor's point-of-view. To + encode immediate text, a snip can be a single character, but more + often a snip is a sequence of adjacent characters on the same + line. The @method[text% find-snip] method extracts a snip + from a text editor: + +@schemeblock[ +(send t #,(:: text% find-snip) 0 'after) +] + +The above expression returns the first snip in the editor, which may + be a string snip (for immediate text) or an editor snip (for an + embedded editor). + +An editor is not permanently attached to any display. We can take the + text editor out of our canvas and put a pasteboard editor in the + canvas, instead: + +@schemeblock[ +(define pb (new pasteboard%)) +(send c #,(:: editor-canvas% set-editor) pb) +] + +With the pasteboard editor installed, the user can no longer type + characters directly into the editor (because a pasteboard does not + support directly entered text). However, the user can cut text from + elsewhere and paste it into pasteboard, or select one of the + @onscreen{Insert} menu items in the @onscreen{Edit} menu. Snips are + clearly identifiable in a pasteboard editor (unlike a text editor) + because each snip is separately dragable. + +We can insert the old text editor (which we recently removed from the + canvas) as an embedded editor in the pasteboard by explicitly + creating an editor snip: + +@schemeblock[ +(define s (make-object editor-snip% t)) (code:comment #, @t{@scheme[t] is the old text editor}) +(send pb #,(:: editor:<%> insert) s) +] + +An individual snip cannot be inserted into different editors at the + same time, or inserted multiple times in the same editor: + +@schemeblock[ +(send pb #,(:: editor<%> insert) s) (code:comment #, @t{no effect}) +] + +However, we can make a deep copy of the snip and insert the copy into + the pasteboard: + +@schemeblock[ +(send pb #,(:: editor<%> insert) (send s #,(:: snip% copy))) +] + +Applications that use the editor classes typically derive new versions + of the @scheme[text%] and @scheme[pasteboard%] classes. For + example, to implement an append-only editor (which allows insertions + only at the end and never allows deletions), derive a new class from + @scheme[text%] and override the + @method[text% can-insert?] and + @method[text% can-delete?] methods: + +@schemeblock[ +(define append-only-text% + (class text% + (inherit #,(:: text% last-position)) + (define/override (#,(:: text% can-insert?) s l) (= s #,(:: text% last-position))) + (define/override (#,(:: text% can-delete?) s l) #f) + (super-new))) +] + +@section[#:tag "mr:tb:miaoverview"]{Editor Structure and Terminology} + +MrEd supports extensible and nestable editors by decomposing an editor + assembly into three functional parts: + +@itemize{ + + @item{The @deftech{editor} itself stores the state of the text or + pasteboard and handles most events and editing operations. The + @scheme[editor<%>] interface defines the core editor functionality, + but editors are created as instances of @scheme[text%] or + @scheme[pasteboard%].} + + @item{A @deftech{snip} is a segment of information within the + editor. Each snip can contain a sequence of characters, a picture, + or an interactive object (such as an embedded editor). In a text + editor, snips are constrained to fit on a single line and generally + contain data of a single type. The @scheme[snip%] class implements a + basic snip. Other snip classes include @scheme[string-snip%] for + managing text, @scheme[image-snip%] for managing pictures, and + @scheme[editor-snip%] for managing embedded editors.} + + @item{A @deftech{display} presents the editor on the screen. The + display lets the user scroll around an editor or change editors. Most + displays are instances of the @scheme[editor-canvas%] class, but the + @scheme[editor-snip%] class also acts as a display for embedded + editors.} + +} + +These three parts are illustrated by a simple word processor. The + editor corresponds to the text document. The editor object receives + keyboard and mouse commands for editing the text. The text itself is + distributed among snips. Each character could be a separate snip, or + multiple characters on a single line could be grouped together into a + snip. The display roughly corresponds to the window in which the + text is displayed. While the editor manages the arrangement of the + text as it is displayed into a window, the display determines which + window to draw into and which part of the editor to display. + +Each selectable entity in an editor is an @deftech{item}. In a + pasteboard, all selection and dragging operations work on snips, so + there is a one-to-one correspondence between snips and items. In an + editor, one snip contains one or more consecutive items, and every + item belongs to some snip. For example, in a simple text editor, each + character is an item, but multiple adjacent characters may be grouped + into a single snip. The number of items in a snip is the snip's + @deftech{count}. + +Each place where the insertion point can appear in a text editor is a + @deftech{position}. A text editor with $n$ items contains $n+1$ + positions: one position before each item, and one position after the + last item. + +The order of snips within a pasteboard determines each snip's drawing + plane. When two snips overlap within the pasteboard, the snip that is + earlier in the order is in front of the other snip (i.e., the former + is drawn after the latter, such that the former snip may cover part + of the latter snip). + +When an editor is drawn into a display, each snip and position has a + @deftech{location}. The location of a position or snip is specified + in coordinates relative to the top-left corner of the + editor. Locations in an editor are only meaningful when the editor is + displayed. + + +@subsection[#:tag "mr:editoradministrators"]{Administrators} + +Two extra layers of administration manage the @techlink{display}-editor and + editor-snip connections. An editor never communicates directly with + a @techlink{display}; instead, it always communicates with an @deftech{editor + administrator}, an instance of the @scheme[editor-admin%] class, + which relays information to the @techlink{display}. Similarly, a snip + communicates with a @deftech{snip administrator}, an instance of the + @scheme[snip-admin%] class. + +The administrative layers make the editor hierarchy flexible without + forcing every part of an editor assembly to contain the functionality + of several parts. For example, a text editor can be a single + @techlink{item} within another editor; without administrators, the + @scheme[text%] class would also have to contain all the functionality + of a @techlink{display} (for the containing editor) and a snip (for + the embedded editor). Using administrators, an editor class can serve + as both a containing and an embedded editor without directly + implementing the @techlink{display} and snip functionality. + +A snip belongs to at most one editor via a single administrator. An + editor also has only one administrator at a time. However, the + administrator that connects the an editor to the standard + @techlink{display} (i.e., an editor canvas) can work with other such + administrators. In particular, the administrator of an + @scheme[editor-canvas%] (each one has its own administrator) can work + with other @scheme[editor-canvas%] administrators, allowing an editor + to be displayed in multiple @scheme[editor-canvas%] windows at the + same time. + +When an editor is displayed by multiple canvases, one of the canvases' + administrators is used as the editor's primary administrator. To + handle user and update events for other canvases, the editor's + administrator is temporarily changed and then restored through the + editor's @method[editor<%> set-admin] method. The return value of the + editor's @method[editor<%> get-admin] method thus depends on the + context of the call. + +@subsection[#:tag "mr:editorstyles"]{Styles} + +A @deftech{style}, an instance of the @scheme[style<%>] interface, + parameterizes high-level display information that is common to all + snip classes. This includes the font, color, and alignment for + drawing the item. A single style is attached to each snip. + +Styles are hierarchical: each style is defined in terms of another + style. @index*['("Basic style") (list @elem{@scheme["Basic"] + style})]{There} is a single @deftech{root style}, named + @scheme["Basic"], from which all other styles in an editor are + derived. The difference between a base style and each of its derived + style is encoded in a @deftech{style delta} (or simply + @deftech{delta}). A delta encodes changes such as + +@itemize{ + + @item{change the font family to @italic{X};} + + @item{enlarge the font by adding @italic{Y} to the point size;} + + @item{toggle the boldness of the font; or} + + @item{change everything to match the style description @italic{Z}.} + +} + +Style objects are never created separately; rather, they are always + created through a @deftech{style list}, an instance of the + @scheme[style-list%] class. A style list manages the styles, + servicing external requests to find a particular style, and it + manages the hierarchical relationship between styles. A global style + list is available, @indexed-scheme[the-style-list], but new style + lists can be created for managing separate style hierarchies. For + example, each editor will typically have its own style list. + +Each new style is defined in one of two ways: + +@itemize{ + + @item{A @deftech{derived style} is defined in terms of a base style + and a delta. Every style (except for the root style) has a base + style, even if it does not depend on the base style in any way (i.e., + the delta describes a fixed style rather than extensions to an + existing style). (This is the usual kind of style inheritance, as + found in word processors such as Microsoft Word.)} + + @item{A @deftech{join style} is defined in terms of two other styles: + a base style and a @deftech{shift style}. The meaning of a join style + is determined by reinterpreting the shift style; in the + reinterpretation, the base style is used as the {\em root\/} style + for the shift style. (This is analogous to multi-level + styles, like the paragraph and character styles in FrameMaker. In + this analogy, the paragraph style is the base style, and the + character style is the shift style. However, FrameMaker allows only + those two levels; with join styles support any number of levels.)} + +} + +@index*['("Standard style") (list @elem{@scheme["Standard"] + style})]{Usually}, when text is inserted into a text editor, it + inherits the style of the preceding snip. If text is inserted into an + empty editor, the text is usually assigned a style called + @scheme["Standard"]. By default, the @scheme["Standard"] style is + unmodified from the root style. The default style name can be changed + by overriding @method[editor<%> default-style-name]. + +The exception to the above is when @xmethod[text% change-style] is + called with the current selection @techlink{position} (when the + selection is a @techlink{position} and not a range). In that case, + the style is remembered, and if the next editor-modifying action is a + text insertion, the inserted text gets the remembered style. + +See @xmethod[text% get-styles-sticky] for more information about the + style of inserted text. + + +@section[#:tag "mr:editorfileformat"]{File Format} + +To allow editor content to be saved to a file, the editor classes + implement a special file format. (The format is used when cutting and + pasting between applications or eventspaces, too). The file format is + not documented, except that it begins + @litchar{WXME01}@nonterm{digit}@nonterm{digit} ## }. Otherwise, the + @method[editor<%> load-file] and @method[editor<%> save-file] methods + define the format internally. The file format is the same for text + and pasteboard editors. When a pasteboard saves its content to a + file, it saves the snips from front to back, and also includes extra + location information. + +Editor data is read and written using @scheme[editor-stream-in%] and + @scheme[editor-stream-out%] objects. Editor information can only be + read from or written to one stream at a time. To write one or more + editors to a stream, first call the function + @scheme[write-editor-global-header] to write initialization data into + an output stream. When all editors are written to the stream, call + @scheme[write-editor-global-footer]. Similarly, reading editors from + a stream is initialized with @scheme[read-editor-global-header] and + finalized with @scheme[read-editor-global-footer]. Optionally, to + support streams that span versions of MrEd, use + @scheme[write-editor-version] and @scheme[read-editor-version] before + the header operations. + +The editor file data format can be embedded within another file, and + it can be extended with new kinds of data. The editor file format can + be extended in two ways: with snip- or content-specific data, and + with editor-specific global data. These are described in the + remainder of this section. + +@subsection{Encoding Snips} + +@index['("snips" "saving")]{@index['("snips" "cut and paste")]{The}} + generalized notion of a snip allows new snip types to be defined and + immediately used in any editor class. Also, when two applications + support the same kinds of snips, snip data can easily be cut and + pasted between them, and the same data files will be readable by each + program. This interoperability is due to a consistent encoding + mechanism that is built into the snip system. + +Graceful and extensible encoding of snips requires that + two issues are addressed: + +@itemize{ + + @item{The encoding function for a snip can be associated with the snip + itself. To convert a snip from an encoded representation (e.g., as + bytes in a file) to a memory object, a decoding function must be + provided for each type of snip. Furthermore, a list of such decoders + must be available to the high-level decoding process. This decoding + mapping is defined by associating a @deftech{snip class} object to + every snip. A snip class is an instance of the @scheme[snip-class%] + class.} + + @item{Some editors may require additional information to be stored + about a snip; this information is orthogonal to the type-specific + information stored by the snip itself. For example, a pasteboard + needs to remember a snip's @techlink{location}, while a text editor does not + need this information. If data is being cut and pasted from one + pasteboard to another, then information about relative @techlink{location}s + needs to be maintained, but this information should not inhibit + pasting into an editor. Extra data is associated with a snip through + @deftech{editor data} objects, instances of the + @scheme[editor-data%] class; decoding requires that each editor data + object has an @deftech{editor data class}, an instance of the + @scheme[editor-data-class%] class.} + +} + +Snip classes, snip data, and snip data classes solve problems related + to encoding and decoding snips. In an application that has no need + for saving files or cut-and-paste, these issues can be safely + ignored. + +@subsubsection[#:tag "mr:editorsnipclasses"]{Snip Classes} + +Each snip can be associated to a @deftech{snip class}. This ``class'' + is not a class description in the programmer's language; it is an + object which provides a way to create new snips of the appropriate + type from an encoded snip specification. + +Snip class objects can be added to the eventspace-specific + @deftech{snip class list}, which is returned by + @scheme[get-the-snip-class-list]. When a snip is encoded, the snip's + class name is associated with the encoding; when the snip needs to be + decoded, then the snip class list is searched by name to find the + snip's class. The snip class will then provide a decoding function + that can create a new snip from the encoding. + +If a snip class's name is of the form @scheme["(lib ...)"], then the + snip class implementation can be loaded on demand. The name is parsed + using @scheme[read]; if the result has the form @scheme[(libKW string + ...)], then it is supplied to @scheme[dynamic-require] along with + @scheme['snip-class]. If the result is a @scheme[snip-class%] object, + it is inserted into the current eventspace's snip class list, and + loading or saving continues using the new class. + +@subsubsection[#:tag "mr:editordata"]{Editor Data} + +While a snip belongs to an editor, the editor may store extra + information about a snip in some specialized way. When the snip is to + be encoded, this extra information needs to be put into an + @deftech{editor data} object so that the extra information can be + encoded as well. In a text editor, extra information can be + associated with ranges of @techlink{item}s, as well as snips. + +Just as a snip must be associated with a snip class to be decoded (see + @|snipclassdiscuss|), an editor data object needs an @deftech{editor + data class} for decoding. Every editor data class object can be added + to the eventspace-specific @deftech{editor data class list}, returned + by @scheme[get-the-editor-data-class-list]. Alternatively, like snip + classes, editor data class names can use the form @scheme["(lib ...)"] + to enable on-demand loading. The corresponding module should export an + @scheme[editor-data-class%] object named + @scheme['editor-data-class]. + +To store and load information about a snip or region in an editor: + +@itemize{ + + @item{derive new classes from @scheme[editor-data%] and + @scheme[editor-data-class%].} + +@item{derive a new class from the @scheme[text%] or + @scheme[pasteboard%] class, and override the @method[editor<%> + get-snip-data] and @method[editor<%> set-snip-data] methods and/or the + @method[text% get-region-data] and @method[text% set-region-data] + methods. + + Note: the @method[text% get-region-data] and @method[text% + set-region-data] methods are called for cut-and-paste encoding, but + not for file-saving encoding; see @|globaleditordatadiscuss| for + information on extending the file format.} + +} + + +@subsection[#:tag "mr:globaleditordata"]{Global Data: Headers and Footers} + +The editor file format provides for adding extra global data in + special header and footer sections. To save and load special header + and/or footer records: + +@itemize{ + + @item{Pick a name for each header/footer record. This name should not + conflict with any other header/footer record name in use, and no one + else should use these names. All names beginning with ``wx'' are + reserved for internal use. By tagging extra header and footer records + with a unique name, the file can be safely loaded under a system that + does not support the records.} + + @item{Derive a new class from the @scheme[text%] or + @scheme[pasteboard%] class, and override the @method[editor<%> + write-headers-to-file], @method[editor<%> write-footers-to-file], + @method[editor<%> read-header-from-file] and/or @method[editor<%> + read-footer-from-file] methods.} + +} + +When an editor is saved, the methods @method[editor<%> + write-headers-to-file] and @method[editor<%> write-footers-to-file] + are invoked; at this time, the derived @scheme[text%] or + @scheme[pasteboard%] object has a chance to save records. To write a + header/footer record, first invoke the @method[editor<%> + begin-write-header-footer-to-file] method, at which point the record + name is provided. Once the record is written, call @method[editor<%> + end-write-header-footer-to-file]. + +When an editor is loaded and a header/footer record is encountered, + the @method[editor<%> read-header-from-file] or @method[editor<%> + read-footer-from-file] method is invoked, with the record name as the + argument. If the name matches a known record type, then the data can + be loaded. + +See also @method[editor<%> write-headers-to-file] and + @method[editor<%> write-headers-to-file]. + + +@section[#:tag "mr:editoreol"]{End of Line Ambiguity} + +Because an editor can force a line break even when there is no + carriage return item, a @techlink{position} alone does not always + specify a @techlink{location} for the caret. Consider the last + @techlink{position} of a line that is soft-broken (i.e., no carriage + return is present): there is no @techlink{item} between the last + @techlink{item} of the line and the first @techlink{item} of the next + line, so two @techlink{location}s (one end-of-line and one + start-of-line) map to the same @techlink{position}. + +For this reason, @techlink{position}-setting and + @techlink{position}-getting methods often have an extra argument. In + the case of a @techlink{position}-setting method, the argument + specifies whether the caret should be drawn at the left or right side + of the page (in the event that the @techlink{location} is doubly + defined); @scheme[#t] means that the caret should be drawn on the + right side. Similarly, methods which calculate a @techlink{position} + from a @techlink{location} will take an extra boxed boolean; the box + is filled with @scheme[#t] if the position is ambiguous and it came + from a right-side location, or @scheme[#f] otherwise. + +@section[#:tag "mr:editorflattened"]{Flattened Text} + +In plain text editors, there is a simple correlation between + @techlink{position}s and characters. In an @scheme[editor<%>] object, + this is not true much of the time, but it is still sometimes useful + to just ``get the text'' of an editor. + +Text can be extracted from an editor in either of two forms: + +@itemize{ + + @item{@deftech{Simple text}, where there is one character per + @techlink{item}. @techlink{Item}s that are characters are mapped to + themselves, and all other @techlink{item}s are mapped to a + period. Line breaks are represented by carriage-return characters + (ASCII 13).} + + @item{@deftech{Flattened text}, where each @techlink{item} can map to + an arbitrary string. @techlink{Item}s that are characters are still + mapped to themselves, but more complicated @techlink{item}s can be + represented with a useful string determined by the @techlink{item}'s + snip. Newlines are mapped to platform-specific character sequences + (linefeed under X, carriage return under Mac OS X, and + linefeed-carriage return under Windows). This form is called + ``flattened'' because the editor's @techlink{item}s have been reduced + to a linear sequence of characters.} + +} + +@section[#:tag "mr:drawcaretinfo"]{Caret Ownership} + +Within a frame, only one object can contain the keyboard focus. This + property must be maintained when a frame contains multiple editors in + multiple @techlink{display}s, and when a single editor contains other + editors as @techlink{item}s. + +When an editor has the keyboard focus, it will usually display the + current selection or a line indicating the insertion point; the line + is called the @deftech{caret}. + +When an editor contains other editors, it keeps track of caret + ownership among the contained sub-editors. When the caret is taken + away from the main editor, it will revoke caret ownership from the + appropriate sub-editor. + +When an editor or snip is drawn, an argument to the drawing method + specifies whether the caret should be drawn with the data. This + argument can be any of (in increasing order): + +@itemize{ + + @item{@indexed-scheme['no-caret] --- The caret should not be drawn at + all.} + + @item{@indexed-scheme['show-inactive-caret] --- The caret should be drawn + as inactive; items may be identified as the local current selection, + but the keyboard focus is elsewhere.} + + @item{@indexed-scheme['show-caret] --- The caret should be drawn to show + keyboard focus ownership.} + +} + +The @scheme['show-inactive-caret] display mode is useful for showing + selection ranges in text editors that do not have the focus. This + @scheme['show-inactive-caret] mode is distinct from @scheme['no-caret] + mode; when editors are embedded, only the locally-active editor shows + its selection. + + +@section[#:tag "mr:editorcutandpastetime"]{Cut and Paste Time Stamps} + +Methods of @scheme[editor<%>] that use the clipboard --- including + @method[editor<%> copy], @method[editor<%> cut], @method[editor<%> + paste], and @method[editor<%> do-edit-operation] --- consume a time + stamp argument. This time stamp is generally extracted from the + @scheme[mouse-event%] or @scheme[key-event%] object that triggered + the clipboard action. X uses the time stamp to synchronize clipboard + operations among the clipboard clients. + +All instances of @scheme[event%] include a time stamp, which can be + obtained using @method[event% get-time-stamp]. + +If the time stamp is 0, it defaults to the current time. Using 0 as the + time stamp almost always works fine, but it is considered bad manners + under X. + + +@section[#:tag "mr:editorclickback"]{Clickbacks} + +@deftech{Clickbacks} in a @scheme[text%] editor facilitate the + creation of simple interactive objects, such as hypertext. A + clickback is defined by associating a callback function with a range + of @techlink{item}s in the editor. When a user clicks on the + @techlink{item}s in that range, the callback function is invoked. For + example, a hypertext clickback would associate a range to a callback + function that changes the selection range in the editor. + +By default, the callback function is invoked when the user releases + the mouse button. The @method[text% set-clickback] method accepts + an optional argument that causes the callback function to be invoked + on the button press, instead. This behavior is useful, for example, + for a clickback that creates a popup menu. + +Note that there is no attempt to save clickback information when a + file is saved, since a clickback will have an arbitrary procedure + associated with it. + +@section[#:tag "mr:lockinfo"]{Internal Editor Locks} + +Instances of @scheme[editor<%>] have three levels of internal + locking: + +@itemize{ + + @item{write locking --- When an editor is internally locked for + writing, the abstract content of the editor cannot be changed (e.g., + insertion attempts fail silently). However, snips in a text editor + can still be split and merged, and the text editor can be changed in + ways that affect the flow of lines. The + @method[editor<%> locked-for-write?] method reports whether an + editor is currently locked for writing.} + + @item{flow locking --- When a text editor is internally locked for + reflowing, it is locked for writing, the snip content of the editor + cannot change, the @techlink{location} of a snip cannot be computed if it + is not already known (see + @xmethod[editor% locations-computed?]), and the editor cannot + be drawn to a @techlink{display}. A request for uncomputed location + information during a flow lock produces undefined results. The + @method[editor<%> locked-for-flow?] method reports whether an + editor is currently locked for flowing.} + + @item{read locking --- When an editor is internally locked for + reading, no operations can be performed on the editor (e.g., a + request for the current selection position returns an undefined + value). This extreme state is used only during callbacks to its snips + for setting the snip's administrator, splitting the snip, or merging + snips. The @method[editor<%> locked-for-read?] method reports + whether an editor is currently locked for reading.} + +} + +The internal lock for an editor is {\em not\/} affected by calls to + @method[editor<%> lock]. + +Methods that report @techlink{location}-independent information about an + editor never trigger a lock. A method that reports @techlink{location} + information may trigger a flow lock or write lock if the relevant + information has not been computed since the last modification to the + editor (see @xmethod[editor% locations-computed?]). A method + that modifies the editor in any way, even setting the selection + position, can trigger a read lock, flow lock, or write lock. + +@section[#:tag "mr:editorthreads"]{Editors and Threads} + +An editor is not tied to any particular thread or eventspace, except + to the degree that it is displayed in a canvas (which has an + eventspace). Concurrent access of an editor is always safe, in the + sense that the editor will not become corrupted. However, because + editor access can trigger locks, and because lock-rejected operations + tend to fail silently, concurrent access can produce unexpected + results. + +Nevertheless, the editor supports certain concurrent patterns + reliably. One relevant pattern is updating an editor in one thread + while the editor is displayed in a canvas that is managed by a + different (handler) thread. To ensure that canvas refreshes are not + performed while the editor is locked for flowing, and to ensure that + refreshes do not prevent editor modifications, the following are + guaranteed: + +@itemize{ + + @item{When an editor's @method[editor<%> refresh] method is + called during an edit sequence (which is started by + @method[editor<%> begin-edit-sequence] and ended with + @method[editor<%> end-edit-sequence]), the requested refresh + region is recorded, but the refresh is not performed. Instead, the + refresh is delayed until the end of the edit sequence.} + + @item{Attempting to start an edit sequence while a refresh is in + progress blocks until the refresh is complete.} + + @item{The @method[editor<%> on-display-size-when-ready] method + calls @method[editor<%> on-display-size] only when the editor + is not being refreshed and only when an edit sequence is not in + progress. In the first case, the + @method[editor<%> on-display-size] call is delegated to the + refreshing thread to be called after the refresh completes. In the + second case, the @method[editor<%> on-display-size] call is + delegated to the edit-sequence thread, to be called when the edit + sequence is complete.} + +} + +Thus, disabling an @scheme[editor-canvas%] object (using + @method[window<%> enable]) is sufficient to ensure that a + background thread can modify an editor displayed by the canvas, as + long as all modifications are in edit sequences. The background + modifications will impair canvas refreshes minimally and temporarily, + and refreshes will not impair modifications in the background thread. + +A second supported pattern is reading an editor in a background thread + while the editor may be manipulated in other threads. Since no + @techlink{location}-independent reads introduce locks, the such reads in + the background thread will not impair other threads. However, other + threads may interfere with the background thread, causing it to + receive erroneous or out-of-date content information. This one-sided + guarantee is useful if the background thread's work can be discarded + when the editor is modified. diff --git a/collects/scribblings/gui/font-class.scrbl b/collects/scribblings/gui/font-class.scrbl new file mode 100644 index 0000000000..b2d0a57888 --- /dev/null +++ b/collects/scribblings/gui/font-class.scrbl @@ -0,0 +1,226 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[font% object% ()]{ + +A @defterm{font} is an object which determines the appearance of text, + primarily when drawing text to a device context. A font is determined + by seven properties: + +@itemize{ + + @item{size --- The size of the text, either in points (the default) + or logical drawing units, depending on the + ``size-in-pixels?''\ property (see below).} + + @item{family --- A platform- and device-independent font + designation. The families are: + + @itemize{ + @item{@indexed-scheme['default]} + @item{@indexed-scheme['decorative]} + @item{@indexed-scheme['roman]} + @item{@indexed-scheme['script]} + @item{@indexed-scheme['swiss]} + @item{@indexed-scheme['modern] (fixed width)} + @item{@indexed-scheme['symbol] (Greek letters and more)} + @item{@indexed-scheme['system] (used to draw control labels)} + } + + The @scheme['modern] designation is special under Mac OS X and X with + fontconfig/Xft; characters in the ASCII range 0-255 are converted to + Unicode characters that match Adobe symbols. For example, @litchar{a} is + converted to @litchar["\u03B1"].} + + @item{face --- A string face name, such as @scheme["Courier"] (under + Windows and Mac OS X), @scheme["-*-courier"] (under + X), or @scheme[" Luxi Sans"] (under X with + fontconfig/Xft; note the leading space). The format + and meaning of a face name is platform- and + device-specific. If a font's face name is @scheme[#f], + then the font's appearance depends only on the + family. If a face is provided but no mapping is + available for the face name (for a specific platform + or device), then the face name is ignored and the + family is used. See @scheme[font-name-directory<%>] + for information about how face names are mapped for + drawing text.} + +@item{style --- The slant style of the font, one of: + @itemize{ + @item{@indexed-scheme['normal]} + @item{@indexed-scheme['slant] (Windows, Mac OS X: same as @scheme['italic]; X: tries @scheme['italic] if @scheme['slant] font does not exist)} + @item{@indexed-scheme['italic] (X: tries @scheme['slant] if @scheme['italic] font does not exist)} + }} + +@item{weight --- The weight of the font, one of: + @itemize{ + @item{@indexed-scheme['normal]} + @item{@indexed-scheme['light]} + @item{@indexed-scheme['bold]} + }} + +@item{underline? --- @scheme[#t] for underlined, @scheme[#f] for plain.} + +@item{smoothing --- Amount of anti-alias smoothing, one of: + @itemize{ + @item{@indexed-scheme['default] (platform-specific, sometimes user-configurable)} + @item{@indexed-scheme['partly-smoothed] (Windows: TrueType when available; + Mac OS X: 4-bit, pixel-aligned smoothing; + X: fontconfig/Xft when available)} + @item{@indexed-scheme['smoothed] (Windows: ClearType when available, XP and up; + Mac OS X: Quartz smoothing; + X: fontconfig/Xft when available)} + @item{@indexed-scheme['unsmoothed]} + } + Special case: @scheme['default] corresponds to + @scheme['partly-smoothed] when used with the @scheme['modern] family + and a font size between 9 and 13 (inclusive).} + +@item{size-in-pixels? --- @scheme[#t] if the size of the font + is in logical drawing units (i.e., pixels for an unscaled screen or + bitmap drawing context), @scheme[#f] if the size of the font is in + points (which can depend on screen resolution).} + +} + +To avoid creating multiple fonts with the same characteristics, use + the global @scheme[font-list%] object @indexed-scheme[the-font-list]. + +See also +@scheme[font-name-directory<%>]. + + + +@defconstructor*/make[(() + ([size (integer-in 1 255)] + [family (one-of/c 'default 'decorative 'roman 'script + 'swiss 'modern 'symbol 'system)] + [style (one-of/c 'normal 'italic 'slant) 'normal] + [weight (one-of/c 'normal 'bold 'light) 'normal] + [underline? any/c #f] + [smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default] + [size-in-pixels? any/c #f]) + ([size (integer-in 1 255)] + [face string?] + [family (one-of/c 'default 'decorative 'roman 'script + 'swiss 'modern 'symbol 'system)] + [style (one-of/c 'normal 'italic 'slant) 'normal] + [weight (one-of/c 'normal 'bold 'light) 'normal] + [underline? any/c #f] + [smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default] + [size-in-pixels? any/c #f]))]{ + +When no arguments are provided, creates an instance of the default + font. If no face name is provided, the font is created without a face + name. Otherwise, see @scheme[font-name-directory<%>] for information + about the way @scheme[face] is interpreted for drawing text on + various platforms and devices; when a platform- or device-specific + interpretation of @scheme[face] is not available, the @scheme[family] + is used to draw text. + +See @scheme[font%] for information about @scheme[family], + @scheme[style], and @scheme[weight]. @scheme[font-name-directory<%>]. + +} + +@defmethod[(get-face) + (or/c string? false/c)]{ + +Gets the font's face name, or @scheme[#f] if none is specified. + +} + +@defmethod[(get-family) + (one-of/c 'default 'decorative 'roman 'script + 'swiss 'modern 'symbol 'system)]{ + +Gets the font's family. See @scheme[font%] for information about +families. + +} + +@defmethod[(get-font-id) + (and/c exact? integer?)]{ + +Gets the font's ID, for use with a +@scheme[font-name-directory<%>]. The ID is determined by the font's +face and family specifications, only. + +} + +@defmethod[(get-point-size) + (integer-in 1 255)]{ + +Gets the font's size (roughly the height). Despite the method name, + the size may be in logical units instead of points, depending on the + result of @method[font% get-size-in-pixels]. + +Due to space included in a font by a font designer, a font tends to + generate text that is slightly taller than the nominal size. + +} + +@defmethod[(get-size-in-pixels) + boolean?]{ + +Returns @scheme[#t] if the size reported by @method[font% + get-point-size] is in logical drawing units, @scheme[#f] if it is in + points. + +For a size in points and a screen or bitmap drawing context, the + logical height depends on the resolution of the screen. + +} + +@defmethod[(get-smoothing) + (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed)]{ + +Gets the font's anti-alias smoothing mode. See @scheme[font%] for + information about smoothing. + +} + +@defmethod[(get-style) + (one-of/c 'normal 'italic 'slant)]{ + +Gets the font's slant style. See @scheme[font%] for information about + styles. + +} + +@defmethod[(get-underlined) + boolean?]{ + +Returns @scheme[#t] if the font is underlined or @scheme[#f] +otherwise. + +} + +@defmethod[(get-weight) + (one-of/c 'normal 'bold 'light)]{ + +Gets the font's weight. See @scheme[font%] for information about + weights. + +} + +@defmethod[(screen-glyph-exists? [c char] + [for-label? any/c #f]) + boolean?]{ + +Returns @scheme[#t] if the given character has a corresponding glyph + when drawing to the screen or a bitmap, @scheme[#f] otherwise. + +If the second argument is true, the result indicates whether the glyph + is available for control labels. Otherwise, it indicates whether the + glyph is available for @scheme[dc<%>] drawing. + +For @scheme[dc<%>] drawing, due to automatic font substitution when + drawing or measuring text, the result of this method does not depend + on this font's attributes (size, face, etc.). The font's attributes + merely provide a hint for the glyph search. + +See also @method[dc<%> glyph-exists?] . + +}} diff --git a/collects/scribblings/gui/font-funcs.scrbl b/collects/scribblings/gui/font-funcs.scrbl new file mode 100644 index 0000000000..c43ffc55a6 --- /dev/null +++ b/collects/scribblings/gui/font-funcs.scrbl @@ -0,0 +1,77 @@ +#reader(lib "docreader.ss" "scribble") +@require["common.ss"] + +@title{Fonts} + + +@defproc[(get-face-list [family (one-of/c 'mono 'all) 'all]) + (listof string?)]{ + +Returns a list of font face names available on the current system. If + @scheme['mono] is provided as the argument, then only faces that are + known to correspond to monospace fonts are included in the list. + +} + +@defproc[(get-family-builtin-face [family (one-of/c 'default 'decorative 'roman 'script + 'swiss 'modern 'symbol 'system)]) + string?]{ + +Returns the built-in default face mapping for a particular font + family. The built-in default can be overridden via preferences, as + described in @secref["mr:fontresources"]. + +See @scheme[font%] for information about @scheme[family]. + +} + +@defthing[menu-control-font (is-a?/c font%)]{ + +This font is the default for @scheme[popup-menu%] objects. + +Under Mac OS X, this font is slightly larger than + @scheme[normal-control-font]. Under Windows and X, it is the same + size as @scheme[normal-control-font]. + +} + +@defthing[normal-control-font (is-a?/c font%)]{ + +This font is the default for most controls, except + @scheme[list-box%] and @scheme[group-box-panel%] objects. + + +} + +@defthing[small-control-font (is-a?/c font%)]{ + +This font is the default for @scheme[group-box-panel%] objects, and it is + a suitable for controls in a floating window and other contexts that + need smaller controls. + +Under Windows, this font is the same size as + @scheme[normal-control-font], since the Windows control font is + already relatively small. Under X and Mac OS X, this font is slightly + smaller than @scheme[normal-control-font]. + + +} + +@defthing[tiny-control-font (is-a?/c font%)]{ + +This font is for tiny controls, and it is smaller than + @scheme[small-control-font] on all platforms. + +} + +@defthing[view-control-font (is-a?/c font%)]{ + +This font is the default for @scheme[list-box%] objects (but not + list box labels, which use @scheme[normal-control-font]). + +Under Mac OS X, this font is slightly smaller than + @scheme[normal-control-font], and slightly larger than + @scheme[small-control-font]. Under Windows and X, it is the same size + as @scheme[normal-control-font]. + +} diff --git a/collects/scribblings/gui/font-list-class.scrbl b/collects/scribblings/gui/font-list-class.scrbl new file mode 100644 index 0000000000..0b362bfc34 --- /dev/null +++ b/collects/scribblings/gui/font-list-class.scrbl @@ -0,0 +1,42 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[font-list% object% ()]{ + +A @scheme[font-list%] object maintains a list of @scheme[font%] + objects to avoid repeatedly creating fonts. + +A global font list, @scheme[the-font-list], is created automatically. + + +@defconstructor/make[()]{ + +Creates an empty font list. + +} + +@defmethod*[([(find-or-create-font [size (integer-in 1 255)] + [family (one-of/c 'default 'decorative 'roman 'script + 'swiss 'modern 'symbol 'system)] + [style (one-of/c 'normal 'italic 'slant)] + [weight (one-of/c 'normal 'bold 'light)] + [underline? any/c #f] + [smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default] + [size-in-pixels? any/c #f]) + (is-a?/c font%)] + [(find-or-create-font [size (integer-in 1 255)] + [face string?] + [family (one-of/c 'default 'decorative 'roman 'script + 'swiss 'modern 'symbol 'system)] + [style (one-of/c 'normal 'italic 'slant)] + [weight (one-of/c 'normal 'bold 'light)] + [underline any/c #f] + [smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default] + [size-in-pixels? any/c #f]) + void?])]{ + +Finds an existing font in the list or creates a new one (that is + automatically added to the list). The arguments are the same as for + creating a @scheme[font%] instance. + +}} diff --git a/collects/scribblings/gui/font-name-directory-intf.scrbl b/collects/scribblings/gui/font-name-directory-intf.scrbl new file mode 100644 index 0000000000..9a4a5bcb09 --- /dev/null +++ b/collects/scribblings/gui/font-name-directory-intf.scrbl @@ -0,0 +1,215 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] +@require[(lib "bnf.ss" "scribble")] + +@definterface[font-name-directory<%> ()]{ + +There is one @scheme[font-name-directory<%>] object: + @scheme[the-font-name-directory]. It implements the mapping from font + specifications (face, family, style, and weight) to information for + rendering text on a specific device. The mapping is different for + each platform. For example, when drawing to a bitmap in Windows, the + rendering information is simply the name of a Windows font. When + drawing to a PostScript file, the rendering information is a + PostScript font name, which encapsulates the style and weight. When + drawing to a bitmap in X, the rendering information is an X font + string, which encapsulates the style and weight, parameterized over + the size (using a ``\%d'' placeholder). + +Programmers rarely need to directly invoke methods of + @scheme[the-font-name-directory]. It is used automatically when + drawing text to a @scheme[dc<%>] object. Nevertheless, + @scheme[the-font-name-directory] is available so that programmers can + query or modify the mapping manually. A programmer may also need to + understand how the face-and-family mapping works. + +To extract mapping information from @scheme[the-font-name-directory], + first obtain a @defterm{font ID}, which is an index based on a family + and optional face string. Font IDs are returned by + @method[font-name-directory<%> find-or-create-font-id] and + @method[font-name-directory<%> get-font-id] . A Font ID can be + combined with a weight and style to obtain a specific mapping value + via @method[font-name-directory<%> get-screen-name] or + @method[font-name-directory<%> get-post-script-name]. + +For a family without a face string, the corresponding font ID has a + useful built-in mapping for every platform and device. (The built-in + mapping can be overridden through the user's preferences; see + @secref["mr:fontresources"] for information.) For a family with a + face string, @scheme[the-font-name-directory] interprets the string + (in a platform-specific way) to generate a mapping for ``screen'' + drawing (to a canvas's @scheme[dc<%>], a @scheme[bitmap-dc%], or a + @scheme[printer-dc%]). When drawing to a @scheme[post-script-dc%] + object, the face-specific mapping defaults to the family's mapping. + +Under Windows and Mac OS X, a face name is interpreted simply as a + system font name for drawing to the screen, bitmap, or printer. The + mapping succeeds if the system provides a font with the given name, + and fails otherwise. For example, under Windows, @scheme["MS Sans + Serif"] maps to the font that is typically used for button + labels. Under X, a face name has a more complex interpretation: + +@itemize{ + + @item{If the string begins with a space, then the remainder of the + string is interpreted as a fontconfig/Xft font name, but only + if fontconfig/Xft support is enabled at compile time (which is + the default when available), and only if the RENDER extension + is available at run time. Multiple fontconfig/Xft font names + can appear after the initial space, separated by commas; the + first available font is used to draw text, and later fonts are + substituted for missing characters in earlier fonts.} + + @item{If the string begins with @litchar["+"], then the remainder of the + string is interpreted as an X font name. These names are + usually long, such as + @litchar["+-b&h-lucidatypewriter-medium-r-normal-sans-24-240-75-75-m-140-iso8859-1"]. + As usual for X font names, asterisks may appear in the string + as wildcards. Furthermore, the size of the font can be + parameterized by using @litchar["%d"] in the place of a specific + point size; if an asterisk appears in place of the pixel size, + the asterisk and @litchar["%d"] are swapped when the font size is + specified in pixels (otherwise the size is always interpreted + as points). For rotated text, @litchar["%d"] will be replaced by + a transformation matrix.} + + @item{A string of the form + @litchar["-"]@nonterm{provider}@litchar{-}@nonterm{font} is + equivalent to + @litchar["+-"]@nonterm{provider}@litchar{-}@nonterm{font}@litchar{-}@nonterm{weight}@litchar{-}@nonterm{style}@litchar{-normal-*-*-%d-*-*-*-*-*-*}, + where @nonterm{weight} is either @litchar{medium}, + @litchar{light}, or @litchar{bold} (depending on the requested + weight mapping) and @nonterm{style} is either @litchar{r}, + @litchar{i}, or @litchar{i} (depending on the requested style + mapping).} + + @item{A string of the form @litchar["-"]@nonterm{font} is + equivalent to @litchar{-*-}@nonterm{font}.} + + @item{A string of any other format is interpreted as an X font name, + optionally parameterized with @litchar{%d}.} + +} + +The mapping for face names can be overridden (on all platforms) + through the user's preferences, as described in + @secref["mr:fontresources"]. + + + +@defmethod[(find-family-default-font-id [family (one-of/c 'default 'decorative 'roman 'script + 'swiss 'modern 'symbol 'system)]) + (and/c exact? integer?)]{ + +Gets the font ID representing the default font for a family. See +@scheme[font%] for information about font families. + +} + +@defmethod[(find-or-create-font-id [name string?] + [family (one-of/c 'default 'decorative 'roman 'script + 'swiss 'modern 'symbol 'system)]) + (and/c exact? integer?)]{ + +Gets the face name for a font ID, initializing the mapping for + the face name if necessary. + +Font ID are useful only as mapping indices for + @indexed-scheme[the-font-name-directory]. + +} + +@defmethod[(get-face-name [font-id (and/c exact? integer?)]) + (or/c string? false/c)]{ + +Gets the face name for a font ID. If the font ID corresponds to + the default font for a particular family, @scheme[#f] is returned. + +} + +@defmethod[(get-family [font-id (and/c exact? integer?)]) + (one-of/c 'default 'decorative 'roman 'script + 'swiss 'modern 'symbol 'system)]{ + +Gets the family for a font ID. See +@scheme[font%] for information about font families. + +} + +@defmethod[(get-font-id [name string?] + [family (one-of/c 'default 'decorative 'roman 'script + 'swiss 'modern 'symbol 'system)]) + (and/c exact? integer?)]{ + +Gets the font ID for a face name paired with a default family. If the + mapping for the given pair is not already initialized, @scheme[0] is + returned. See also @method[font-name-directory<%> + find-or-create-font-id]. + +Font ID are useful only as mapping indices for + @indexed-scheme[the-font-name-directory]. + +} + +@defmethod[(get-post-script-name [font-id (and/c exact? integer?)] + [weight (one-of/c 'normal 'bold 'light)] + [style (one-of/c 'normal 'italic 'slant)]) + (or/c string? false/c)]{ + +Gets a PostScript font name for a font ID, weight, and style + combination. The PostScript font name is used both for the font name + in PostScript output (sans character set) and as the @|AFM| file + name; see also @secref["mr:postscriptfonts"]. + +See @scheme[font%] for information about @scheme[weight] and + @scheme[style]. + +} + +@defmethod[(get-screen-name [font-id (and/c exact? integer?)] + [weight (one-of/c 'normal 'bold 'light)] + [style (one-of/c 'normal 'italic 'slant)]) + (or/c string? false/c)]{ + +Gets a platform-dependent screen font name (used for drawing to a + canvas's @scheme[dc<%>], a @scheme[bitmap-dc%], or a + @scheme[printer-dc%]) for a font ID, weight, and style combination. + +See @scheme[font%] for information about @scheme[weight] and +@scheme[style]. + +} + +@defmethod[(set-post-script-name [font-id (and/c exact? integer?)] + [weight (one-of/c 'normal 'bold 'light)] + [style (one-of/c 'normal 'italic 'slant)] + [name string?]) + void?]{ + +Sets a PostScript font name for a font ID, weight, and style + combination. See also @method[font-name-directory<%> + get-post-script-name]. + +See @scheme[font%] for information about @scheme[weight] and @scheme[style]. + +} + +@defmethod[(set-screen-name [font-id (and/c exact? integer?)] + [weight (one-of/c 'normal 'bold 'light)] + [style (one-of/c 'normal 'italic 'slant)] + [name string?]) + void?]{ + +Sets a platform-dependent screen font name (used for drawing to a + canvas's @scheme[dc<%>], a @scheme[bitmap-dc%], or a + @scheme[printer-dc%]) for a font ID, weight, and style combination. + +Under X, if the screen name contains @litchar{%d}, it is replaced by + the size of the font (point size times 10) to obtain the full screen + font name. + +See @scheme[font%] for information about @scheme[weight] and + @scheme[style]. + +}} + diff --git a/collects/scribblings/gui/gl-config-class.scrbl b/collects/scribblings/gui/gl-config-class.scrbl new file mode 100644 index 0000000000..a8525ca1c8 --- /dev/null +++ b/collects/scribblings/gui/gl-config-class.scrbl @@ -0,0 +1,113 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[gl-config% object% ()]{ + +A @scheme[gl-config%] object encapsulates configuration information + for an OpenGL drawing context. Use a @scheme[gl-config%] object as an + initialization argument for @scheme[canvas%], or provide it to + @xmethod[bitmap% set-gl-config]. + + +@defconstructor[()]{ + +Creates a GL configuration that indicates double buffering, a depth + buffer of size one, no stencil buffer, no accumulation buffer, no + multisampling, and not stereo. + +} + +@defmethod[(get-accum-size) + (integer-in 0 256)]{ + +Reports the accumulation-buffer size (for each of red, green, blue, + and alpha) that the configuration requests, where zero means no + accumulation buffer is requested. + +} + +@defmethod[(get-depth-size) + (integer-in 0 256)]{ + +Reports the depth-buffer size that the configuration requests, where + zero means no depth buffer is requested. + +} + +@defmethod[(get-double-buffered) + boolean?]{ + +Reports whether the configuration requests double buffering or not. + +} + +@defmethod[(get-multisample-size) + (integer-in 0 256)]{ + +Reports the multisampling size that the configuration requests, where + zero means no multisampling is requested. + +} + +@defmethod[(get-stencil-size) + (integer-in 0 256)]{ + +Reports the stencil-buffer size that the configuration requests, where + zero means no stencil buffer is requested. + +} + +@defmethod[(get-stereo) + boolean?]{ + +Reports whether the configuration requests stereo or not. + +} + +@defmethod[(set-accum-size [on? (integer-in 0 256)]) + void?]{ + +Adjusts the configuration to request a particular accumulation-buffer + size for every channel (red, green, blue, and alpha), where zero + means no accumulation buffer is requested. + +} + +@defmethod[(set-depth-size [on? (integer-in 0 256)]) + void?]{ + +Adjusts the configuration to request a particular depth-buffer size, + where zero means no depth buffer is requested. + +} + +@defmethod[(set-double-buffered [on? any/c]) + void?]{ + +Adjusts the configuration to request double buffering or not. + +} + +@defmethod[(set-multisample-size [on? (integer-in 0 256)]) + void?]{ + +Adjusts the configuration to request a particular multisample size, + where zero means no multisampling is requested. If a multisampling + context is not available, this request will be ignored. + +} + +@defmethod[(set-stencil-size [on? (integer-in 0 256)]) + void?]{ + +Adjusts the configuration to request a particular stencil-buffer size, + where zero means no stencil buffer is requested. + +} + +@defmethod[(set-stereo [on? any/c]) + void?]{ + +Adjusts the configuration to request stereo or not. + +}} diff --git a/collects/scribblings/gui/gl-context-intf.scrbl b/collects/scribblings/gui/gl-context-intf.scrbl new file mode 100644 index 0000000000..b7f5ca947e --- /dev/null +++ b/collects/scribblings/gui/gl-context-intf.scrbl @@ -0,0 +1,98 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@definterface[gl-context<%> ()]{ + +A @scheme[gl-context<%>] object represents a context for drawing with + @as-index{OpenGL} to a specific @scheme[dc<%>] instance. To obtain a + @scheme[gl-context<%>] object, call @method[dc<%> get-gl-context] of + the target drawing context. + +Only canvas @scheme[dc<%>] and @scheme[bitmap-dc%] objects support + OpenGL (always under Windows and Mac OS X, sometimes under X), and in + the case of a @scheme[bitmap-dc%], the context is usable only when + the target bitmap is non-monochrome. When the target bitmap for a + @scheme[bitmap-dc%] context is changed via @method[bitmap-dc% + set-bitmap], the associated OpenGL context is reset, but the + @scheme[gl-context<%>] keeps its identity. Canvas contexts are double + buffered, and bitmap contexts are single buffered. + +MrEd provides no OpenGL routines. Instead, they must be obtained from + a separate library, such as @scheme[(lib "sgl.ss" "sgl")]. MrEd + merely manages the current OpenGL context, connecting it to windows + and bitmaps. + +Only one OpenGL context can be active at a time across all threads and + eventspaces. Except under Mac OS X, OpenGL contexts are not protected + against interference among threads; that is, if a thread selects one + of its OpenGL contexts, then other threads can write into the context + via OpenGL commands. However, if all threads issue OpenGL commands + only within a thunk passed to @method[gl-context<%> call-as-current], + then drawing from the separate threads will not interfere, because + @method[gl-context<%> call-as-current] uses a lock to serialize + context selection across all threads in MrEd. + + +@defmethod[(call-as-current [thunk (-> any)] + [alternate evt? never-evt] + [enable-breaks? any/c #f]) + any/c]{ + +Calls a thunk with this OpenGL context as the current context for + OpenGL commands. + +The method blocks to obtain a lock that protects the global OpenGL + context, and it releases the lock when the thunk returns or + escapes. The lock is re-entrant, so a nested use of the method in the + same thread with the same OpenGL context does not obtain or release + the lock. + +The lock prevents interference among OpenGL-using threads. If a + thread is terminated while holding the context lock, the lock is + released. Continuation jumps into the thunk do not grab the lock or + set the OpenGL context. See @scheme[gl-context<%>] for more + information on interference. + +The method accepts an alternate @tech{synchronizable event} for use + while blocking for the context lock; see also @scheme[sync]. + +The result of the method call is the result of the thunk if it is + called, or the result of the alternate event if it is chosen instead + of the context lock. + +If @method[gl-context<%> ok?] returns @scheme[#f] at the time that + this method is called, then @|MismatchExn|. + +If @scheme[enable-breaks?] is true, then the method uses + @scheme[sync/enable-break] while blocking for the context-setting + lock instead of @scheme[sync]. + +} + +@defmethod[(ok?) + boolean?]{ + +Returns @scheme[#t] if this context is available OpenGL drawing, + @scheme[#f] otherwise. + +A context is unavailable if OpenGL support is disabled at compile time + or run time, if the context is associated with a + @scheme[bitmap-dc%] with no selected bitmap or with a monochrome + selected bitmap, if the context is for a canvas that no longer + exists, or if there was a low-level error when preparing the context. + +} + +@defmethod[(swap-buffers) + void?]{ + +Swaps the front (visible) and back (OpenGL-drawing) buffer for a + context associated with a canvas, and has no effect on a bitmap + context. + +This method implicitly uses @method[gl-context<%> call-as-current] to + obtain the context lock. Since the lock is re-entrant, however, the + @method[gl-context<%> swap-buffers] method can be safely used within + a @method[gl-context<%> call-as-current] thunk. + +}} diff --git a/collects/scribblings/gui/global-draw-funcs.scrbl b/collects/scribblings/gui/global-draw-funcs.scrbl new file mode 100644 index 0000000000..f04d7e19d0 --- /dev/null +++ b/collects/scribblings/gui/global-draw-funcs.scrbl @@ -0,0 +1,100 @@ +#reader(lib "docreader.ss" "scribble") +@require["common.ss"] + +@title{Global Graphics} + +@defproc[(flush-display) + void?]{ + +Under X and Mac OS X, flushes pending display messages such that the + user's display reflects the actual state of the windows. Under + Windows, the procedure has no effect. + +} + +@defproc[(get-display-depth) + nonnegative-exact-integer?]{ + +Returns the depth of the main display (a value of 1 denotes a monochrome display). + +} + +@defproc[(get-display-left-top-inset [avoid-bars? bool @scheme[#f]]) + (values nonnegative-exact-integer? nonnegative-exact-integer?)]{ + +When the optional argument is @scheme[#f] (the default), this function + returns the offset of the main screen's origin from the + top-left of the physical screen. Under X and Windows, the result is + always @scheme[0] and @scheme[0]; under Mac OS X, the result is + @scheme[0] and the height of the menu bar. + +When the optional argument is true, this function returns the amount + space at the left and top of the main screen that is occupied by the + task bar (Windows) or menu bar and dock (Mac OS X). Under X, the + result is always @scheme[0] and @scheme[0]. + +} + +@defproc[(get-display-size [full-screen? bool @scheme[#f]]) + (values nonnegative-exact-integer? nonnegative-exact-integer?)]{ + +@index["screen resolution"]{Gets} the physical size of the display in + pixels. Under Windows, this size does not include the task bar by + default. Under Mac OS X, this size does not include the menu bar or + dock area by default. + +Under Windows and Mac OS X, if the optional argument is true, then + the task bar, menu bar, and dock area are included in the result. + +Returns the screen's width and height. + +} + +@defproc[(is-color-display?) + boolean?]{ + +Returns @scheme[#t] if the main display has color, @scheme[#f] +otherwise. + +} + +@defproc[(register-collecting-blit [canvas (is-a?/c canvas%)] + [x real?] + [y real?] + [w (and/c real? (not/c negative?))] + [h (and/c real? (not/c negative?))] + [on (is-a?/c bitmap%)] + [off (is-a?/c bitmap%)] + [on-x real? 0] + [on-y real? 0] + [off-x real? 0] + [off-y real? 0]) + void?]{ + +Registers a blit to occur when garbage collection starts or ends. + +When garbage collection starts, @scheme[(send (send canvas #,(:: + canvas<%> get-dc)) #,(:: dc<%> draw-bitmap-section) on on-x on-y x y w + h)] is called. When garbage collection ends, @scheme[(send (send + canvas #,(:: canvas<%> get-dc)) #,(:: dc<%> draw-bitmap-section) off + off-x off-y x y w h)] is called. If @scheme[canvas]'s device context + has a scale, the scale may or may not be temporarily disabled during + the bitmap drawing. + +The @scheme[canvas] is registered weakly, so it will be automatically + unregistered if the canvas becomes invisible and inaccessible. + Multiple registrations can be installed for the same canvas. + +See also @scheme[unregister-collecting-blit]. + +} + +@defproc[(unregister-collecting-blit [canvas (is-a?/c canvas%)]) + void?]{ + +Unregisters a blit request installed with See also + @scheme[register-collecting-blit]. + +Unregisters all blits for @scheme[canvas]. + +} diff --git a/collects/scribblings/gui/gui.scrbl b/collects/scribblings/gui/gui.scrbl index 66582644e7..60cc47a548 100644 --- a/collects/scribblings/gui/gui.scrbl +++ b/collects/scribblings/gui/gui.scrbl @@ -1,7 +1,7 @@ #reader(lib "docreader.ss" "scribble") @require["common.ss"] -@title{PLT Scheme GUI Reference} +@title{PLT Scheme GUI Toolbox} This manual describes MrEd. @@ -12,67 +12,8 @@ This manual describes MrEd. @;------------------------------------------------------------------------ -@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"] +@include-section["guide.scrbl"] +@include-section["reference.scrbl"] @;------------------------------------------------------------------------ diff --git a/collects/scribblings/gui/guide.scrbl b/collects/scribblings/gui/guide.scrbl new file mode 100644 index 0000000000..48b287f252 --- /dev/null +++ b/collects/scribblings/gui/guide.scrbl @@ -0,0 +1,58 @@ +#reader(lib "docreader.ss" "scribble") +@require["common.ss"] + +@title[#:style 'toc]{Guide} + +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 described in + @secref["mr:windowing-overview"].} + + @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 + described in @secref["mr:drawing-overview"].} + + @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 described in + @secref["mr:editor-overview"].} + +} + +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). + +@local-table-of-contents[] + +@;------------------------------------------------------------------------ + +@include-section["win-overview.scrbl"] + +@;------------------------------------------------------------------------ + +@include-section["draw-overview.scrbl"] + +@;------------------------------------------------------------------------ + +@include-section["editor-overview.scrbl"] diff --git a/collects/scribblings/gui/pen-class.scrbl b/collects/scribblings/gui/pen-class.scrbl new file mode 100644 index 0000000000..3699e884c2 --- /dev/null +++ b/collects/scribblings/gui/pen-class.scrbl @@ -0,0 +1,243 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[pen% object% ()]{ + +A pen is a drawing tool with a color, width, and style. A pen draws + lines and outlines, such as the outline of a rectangle. On a + monochrome display, all non-white pens are drawn as black. + +In addition to its color, width, and style, a pen can have a stipple + bitmap that is a 8 x 8 monochrome bitmap. This stipple is used only + in unsmoothed mode (see @method[dc<%> set-smoothing]) or in a + PostScript drawing context. Painting with a stipple pen is similar to + calling @method[dc<%> draw-bitmap] with the stipple bitmap in region + painted by the pen. + +A pen's style is one of the following: + +@itemize{ + + @item{@indexed-scheme['transparent] --- Draws with no effect (on the + outline of the drawn shape).} + + @item{@indexed-scheme['solid] --- Draws using the pen's color. If a + (monochrome) stipple is installed into the pen, black pixels + from the stipple are transferred to the destination using the + brush's color, and white pixels from the stipple are not + transferred.} + + @item{@indexed-scheme['xor] --- In unsmoothed mode, the pen's color + or colored stipple is xor-ed with existing destination pixel + values. The @scheme['xor] mapping is unspecified for arbitrary + color combinations, but the mapping provides two guarantees: + @itemize{ + + @item{Black-and-white drawing to a color or monochrome + destination always works as expected: black xor white = black, + white xor black = black, black xor black = white, and white xor + white = white.} + + @item{Performing the same drawing operation twice in a row with + @scheme['xor] is equivalent to a no-op.} + + } + In a smoothing mode, @scheme['xor] is equivalent to @scheme['solid].} + + @item{@indexed-scheme['hilite] --- In unsmoothed mode, existing + destination pixels are ``highlighted'' in a platform-specific + way when the pen color is black. Under Windows for a color + drawing context, the inverted RGB components of destination + pixel are combined with the RGB components of the system-wide + highlight color using a bitwise ``or'', and the combination is + used. Under Mac OS X for a color drawing context, the + inverted RGB components of the system-wide highlight color are + subtracted from the RGB components of each destination pixel, + and the difference (or 0 for a negative result) is used. Under + X or for any monochrome drawing context, @scheme['hilite] is the + same as @scheme['xor]. In a smoothing mode, @scheme['hilite] is + treated like @scheme['solid].} + + @item{The following special pen modes use the pen's color, and they only + apply when a stipple is not used: + @itemize{ + @item{@indexed-scheme['dot]} + @item{@indexed-scheme['long-dash]} + @item{@indexed-scheme['short-dash]} + @item{@indexed-scheme['dot-dash]} + @item{@indexed-scheme['xor-dot]} + @item{@indexed-scheme['xor-long-dash]} + @item{@indexed-scheme['xor-short-dash]} + @item{@indexed-scheme['xor-dot-dash]} + }} + +} + +To avoid creating multiple pens with the same characteristics, use the + global @scheme[pen-list%] object @indexed-scheme[the-pen-list], or + provide a color, width, and style to @xmethod[dc<%> set-pen]. + +A pen of size @scheme[0] uses the minimum line size for the + destination drawing context. In (unscaled) canvases and bitmaps in + unsmoothed mode, a zero-width pen behaves the nearly same as a pen of + size @scheme[1]. In a smoothing mode (including all + @scheme[post-script-dc%] drawing), a pen of size @scheme[0] draws a + line thinner than a pen of size @scheme[1]. If the pen's width is not + an integer, then the width is truncated to an integer (even before + scaling) in unsmoothed mode. + + + + +@defconstructor*/make[(() + ([color (is-a?/c color%)] + [width (real-in 0 255)] + [style (one-of/c 'transparent 'solid 'xor 'hilite + 'dot 'long-dash 'short-dash 'dot-dash + 'xor-dot 'xor-long-dash 'xor-short-dash + 'xor-dot-dash)]) + ([color-name string?] + [width (real-in 0 255)] + [style (one-of/c 'transparent 'solid 'xor 'dot 'hilite + 'long-dash 'short-dash 'dot-dash + 'xor-dot 'xor-long-dash 'xor-short-dash + 'xor-dot-dash)]))]{ + +When no argument are provided, the result is a solid black pen of + width @scheme[0]. Otherwise, the result is a pen with the given + color, width, and style. For the case that the color is specified + using a name, see @scheme[color-database<%>] for information about + color names; if the name is not known, the pen's color is black. + +} + +@defmethod[(get-cap) + (one-of/c 'round 'projecting 'butt)]{ + +Returns the pen cap style (Windows unsmoothed, X unsmoothed, all + smoothing). The default is @scheme['round]. + +} + +@defmethod[(get-color) + (is-a?/c color%)]{ + +Returns the pen's color object. + +} + +@defmethod[(get-join) + (one-of/c 'round 'bevel 'miter)]{ + +Returns the pen join style (Windows unsmoothed, X unsmoothed, all + smoothing). The default is @scheme['round]. + +} + +@defmethod[(get-stipple) + (or/c (is-a?/c bitmap%) false/c)]{ + +Gets the current stipple bitmap, or returns @scheme[#f] if no stipple + bitmap is installed. + +} + +@defmethod[(get-style) + (one-of/c 'transparent 'solid 'xor 'hilite + 'dot 'long-dash 'short-dash 'dot-dash + 'xor-dot 'xor-long-dash 'xor-short-dash + 'xor-dot-dash)]{ + +Returns the pen style. See @scheme[pen%] for information about +possible styles. + +} + +@defmethod[(get-width) + (real-in 0 255)]{ + +Returns the pen width. + +} + +@defmethod[(set-cap [cap-style (one-of/c 'round 'projecting 'butt)]) + void?]{ + +Sets the pen cap style (Windows unsmoothed, X unsmoothed, all + smoothing). See @method[pen% get-cap] for information about cap + styles. + +A pen cannot be modified if it was obtained from a @scheme[pen-list%] + or while it is selected into a drawing context. + +} + +@defmethod*[([(set-color [color (is-a?/c color%)]) + void?] + [(set-color [color-name string?]) + void?] + [(set-color [red (integer-in 0 255)] + [green (integer-in 0 255)] + [blue (integer-in 0 255)]) + void?])]{ + +Sets the pen color. + +A pen cannot be modified if it was obtained from a + @scheme[pen-list%] or while it is selected into a drawing context. + +} + +@defmethod[(set-join [join-style (one-of/c 'round 'bevel 'miter)]) + void?]{ + +Sets the pen join style (Windows unsmoothed, X unsmoothed, all + smoothing). See @method[pen% get-join] for information about join + styles. + +A pen cannot be modified if it was obtained from a + @scheme[pen-list%] or while it is selected into a drawing context. + +} + +@defmethod[(set-stipple [stipple (or/c (is-a?/c bitmap%) false/c)]) + void?]{ + +Sets the pen stipple bitmap, which must be an 8 x 8 monochrome bitmap + or @scheme[#f], which turns off the stipple bitmap. + +A bitmap cannot be used as a stipple if it is selected into a + @scheme[bitmap-dc%] object; if the given bitmap is selected into a + @scheme[bitmap-dc%] object, @|MismatchExn|. A pen cannot be modified + if it was obtained from a @scheme[pen-list%] or while it is selected + into a drawing context. + +A pen's stipple is not used in a smoothing mode, except for a + @scheme[post-script-dc%] (which is always in smoothed mode). + +} + +@defmethod[(set-style [style (one-of/c 'transparent 'solid 'xor 'hilite + 'dot 'long-dash 'short-dash 'dot-dash + 'xor-dot 'xor-long-dash 'xor-short-dash + 'xor-dot-dash)]) + void?]{ + +Sets the pen style. See @scheme[pen%] for information about the + possible styles. + +A pen cannot be modified if it was obtained from a + @scheme[pen-list%] or while it is selected into a drawing context. + +} + +@defmethod[(set-width [width (real-in 0 255)]) + void?]{ + +Sets the pen width. + +A pen cannot be modified if it was obtained from a + @scheme[pen-list%] or while it is selected into a drawing context. + +}} + diff --git a/collects/scribblings/gui/pen-list-class.scrbl b/collects/scribblings/gui/pen-list-class.scrbl new file mode 100644 index 0000000000..f7eb602f31 --- /dev/null +++ b/collects/scribblings/gui/pen-list-class.scrbl @@ -0,0 +1,45 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[pen-list% object% ()]{ + +A @scheme[pen-list%] object maintains a list of @scheme[pen%] + objects to avoid repeatedly creating pen objects. A @scheme[pen%] + object in a pen list cannot be mutated. + +A global pen list @indexed-scheme[the-pen-list] is created automatically. + + + + + +@defconstructor/make[()]{ + +Creates an empty pen list. + + +} + +@defmethod*[([(find-or-create-pen [color (is-a?/c color%)] + [width (real-in 0 255)] + [style (one-of/c 'transparent 'solid 'xor 'hilite + 'dot 'long-dash 'short-dash 'dot-dash + 'xor-dot 'xor-long-dash 'xor-short-dash + 'xor-dot-dash)]) + (is-a?/c pen%)] + [(find-or-create-pen [color-name string?] + [width (real-in 0 255)] + [style (one-of/c 'transparent 'solid 'xor 'hilite + 'dot 'long-dash 'short-dash 'dot-dash + 'xor-dot 'xor-long-dash 'xor-short-dash + 'xor-dot-dash)]) + (or/c (is-a?/c pen%) false/c)])]{ + +Finds a pen of the given specification, or creates one and adds it to +the list. The arguments are the same as for creating a @scheme[pen%] +instance. When @scheme[color-name] is provided, however, the return +value is @scheme[#f] when no color matching @scheme[color-name] can be +found in @scheme[the-color-database]. + +}} + diff --git a/collects/scribblings/gui/point-class.scrbl b/collects/scribblings/gui/point-class.scrbl new file mode 100644 index 0000000000..10565cdc03 --- /dev/null +++ b/collects/scribblings/gui/point-class.scrbl @@ -0,0 +1,41 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[point% object% ()]{ + +A @scheme[point%] is used for certain drawing commands. It + encapsulates two real numbers. + +@defconstructor*/make[(() + ([x real?] + [y real?]))]{ + +Creates a point. If @scheme[x] and @scheme[y] are not supplied, they + are set to @scheme[0]. +} + +@defmethod[(get-x) + real?]{ +Gets the point x-value. + +} + +@defmethod[(get-y) + real?]{ +Gets the point y-value. + +} + +@defmethod[(set-x [x real?]) + void?]{ +Sets the point x-value. + +} + +@defmethod[(set-y [y real?]) + void?]{ + +Sets the point y-value. + +}} + diff --git a/collects/scribblings/gui/post-script-dc-class.scrbl b/collects/scribblings/gui/post-script-dc-class.scrbl new file mode 100644 index 0000000000..783e0df89b --- /dev/null +++ b/collects/scribblings/gui/post-script-dc-class.scrbl @@ -0,0 +1,58 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[post-script-dc% object% (dc<%>)]{ + +A @scheme[post-script-dc%] object is a PostScript device context, that + can write PostScript files on any platform. See also + @scheme[ps-setup%]. + +@|PrintNote| + +See also @scheme[printer-dc%]. + + +@defconstructor[([interactive any/c #t] + [parent (or/c (is-a?/c frame%) (is-a?/c dialog%) false/c) #f] + [use-paper-bbox any/c #f] + [as-eps any/c #t])]{ + +If @scheme[interactive] is true, the user is given a dialog for + setting printing parameters (see @scheme[get-ps-setup-from-user]); + the resulting configuration is installed as the current + configuration). If the user chooses to print to a file (the only + possibility under Windows and Mac OS X), another dialog is given to + select the filename. If the user hits cancel in either of these + dialogs, then @method[dc<%> ok?] returns @scheme[#f]. + +If @scheme[parent] is not @scheme[#f], it is used as the parent window of + the configuration dialog. + +If @scheme[interactive] is @scheme[#f], then the settings returned by + @scheme[current-ps-setup] are used. A file dialog is still presented + to the user if the @method[ps-setup% get-file] method returns + @scheme[#f], and the user may hit cancel in that case so that + @method[dc<%> ok?] returns @scheme[#f]. + +If @scheme[use-paper-bbox] is @scheme[#f], then the PostScript + bounding box for the output is determined by drawing commands issued + to the object; such a bounding box encloses all parts of the drawing + @italic{ignoring} clipping regions (so the bounding box may be + approximate). If @scheme[use-paper-bbox] is not @scheme[#f], then the + bounding box is determined by the current paper size (as specified by + @scheme[current-ps-setup]), and the bounding box does not include the + margin (also specified by @scheme[current-ps-setup]). + +@index["Encapsulated PostScript (EPS)"]{If} @scheme[as-eps] is + @scheme[#f], then the generated PostScript does not include an + Encapsulated PostScript (EPS) header, and instead includes a generic + PostScript header. Otherwise, the generated PostScript includes a + header that identifiers it as EPS. + +See also @scheme[ps-setup%] and @scheme[current-ps-setup]. The +settings for a particular @scheme[post-script-dc%] object are fixed to +the values in the current configuration when the object is created +(after the user has interactively adjusted them when +@scheme[interactive] is true). + +}} diff --git a/collects/scribblings/gui/post-script-funcs.scrbl b/collects/scribblings/gui/post-script-funcs.scrbl new file mode 100644 index 0000000000..ebef3e979e --- /dev/null +++ b/collects/scribblings/gui/post-script-funcs.scrbl @@ -0,0 +1,25 @@ +#reader(lib "docreader.ss" "scribble") +@require["common.ss"] + +@title{PostScript} + +@defparam[current-ps-afm-file-paths paths (listof path?)]{ + +A parameter determines the list of paths that is used to find AFM + files. See @secref["mr:postscriptfonts"] for more information. + +} + +@defparam[current-ps-cmap-file-paths paths (listof path?)]{ + +A parameter that determines the list of paths that is used to find + CMap files. See @secref["mr:postscriptfonts"] for more information. + +} + +@defparam[current-ps-setup pss (is-a?/c ps-setup%)]{ + +A parameter that determines the current PostScript configuration + settings. See @scheme[post-script-dc%] and @scheme[printer-dc%]. + +} diff --git a/collects/scribblings/gui/printer-dc-class.scrbl b/collects/scribblings/gui/printer-dc-class.scrbl new file mode 100644 index 0000000000..49b8abfb5c --- /dev/null +++ b/collects/scribblings/gui/printer-dc-class.scrbl @@ -0,0 +1,33 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[printer-dc% object% (dc<%>)]{ + +A @scheme[printer-dc%] object is a Windows or Mac OS X printer + device context. The class cannot be instantiated under X (an + @scheme[exn:misc:unsupported] exception is raised). + +Under Mac OS X, a newly created @scheme[printer-dc%] object obtains + orientation (portrait versus landspace) and scaling information from + the current @scheme[ps-setup%] object, as determined by the + @scheme[current-ps-setup] parameter. This information can be + configured by the user through a dialog shown by + @scheme[get-page-setup-from-user]. + +@|PrintNote| + +See also @scheme[post-script-dc%]. + +When a @scheme[printer-dc%] object is created, the user gets + platform-specific modal dialogs for configuring the output. + If the user cancels the dialog, the @method[dc<%> ok?] method + of the object returns @scheme[#f]. + +@defconstructor[([parent (or/c (is-a?/c frame%) (is-a?/c dialog%) false/c) #f])]{ + +If @scheme[parent] is not @scheme[#f], it is used as the parent window + of the configuration dialog. + + +}} + diff --git a/collects/scribblings/gui/ps-setup-class.scrbl b/collects/scribblings/gui/ps-setup-class.scrbl new file mode 100644 index 0000000000..eaf4462122 --- /dev/null +++ b/collects/scribblings/gui/ps-setup-class.scrbl @@ -0,0 +1,273 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[ps-setup% object% ()]{ + +A @scheme[ps-setup%] object contains configuration information for + producing PostScript files using a @scheme[post-script-dc%] object. + To a lesser extent, it contains information for printing with a + @scheme[printer-dc%] object. + +When a @scheme[post-script-dc%] object is created, its configuration + is determined by the @scheme[current-ps-setup] parameter's + @scheme[ps-setup%] value. After a @scheme[post-script-dc%] object is + created, it is unaffected by changes to the @scheme[current-ps-setup] + parameter or mutations to the @scheme[ps-setup%] object. + + +@defconstructor[()]{ + +Creates a new @scheme[ps-setup%] object with the (platform-specific) + default configuration. + +} + +@defmethod[(copy-from [source (is-a?/c ps-setup%)]) + void?]{ + +Copies the settings @scheme[copy-from] to @this-obj[]. + +} + +@defmethod[(get-command) + string?]{ + +Gets the printer command used to print a file in X. The default is + @scheme["lpr"]. This value is not used by other platforms. + +} + +@defmethod[(get-editor-margin [h-margin (box/c nonnegative-real?)] + [v-margin (box/c nonnegative-real?)]) + void?]{ + +Returns the current settings for horizontal and vertical margins when + printing an @scheme[editor<%>]. See also @method[ps-setup% + set-editor-margin]. + +} + +@defmethod[(get-file) + (or/c path-string? false/c)]{ + +Gets the PostScript output filename. A @scheme[#f] value (the default) + indicates that the user should be prompted for a filename when a + @scheme[post-script-dc%] object is created. + +} + +@defmethod[(get-level-2) + boolean?]{ + +Reports whether Level 2 commands are output in PostScript files. + +Currently, Level 2 commands are only needed to include color bitmap + images in PostScript output (drawn with @method[dc<%> draw-bitmap]), + or bitmap pen and brush stipples. When Level 2 commands are disabled, + bitmaps are converted to grayscale images and stipples are not + supported. + +} + +@defmethod[(get-margin [h-margin (box/c nonnegative-real?)] + [v-margin (box/c nonnegative-real?)]) + void?]{ + +Returns the current settings for horizontal and vertical PostScript + margins. See also @method[ps-setup% set-margin]. + +} + +@defmethod[(get-mode) + (one-of/c 'preview 'file 'printer)]{ + +Gets the printing mode that determines where output is sent: + @scheme['preview], @scheme['file], or @scheme['printer]. The default + for X is @scheme['preview]. The value in Windows and Mac OS X is + always @scheme['file]. + +} + +@defmethod[(get-orientation) + (one-of/c 'portrait 'landscape)]{ + +Gets the orientation: @scheme['portrait] or @scheme['landscape]. The + default is @scheme['portrait]. Unlike most other settings, this one + affects native printing (via @scheme[printer-dc%]) as well as + PostScript output. + +Landscaped orientation affects the size of the drawing area as + reported by @method[dc<%> get-size]: the horizontal and vertical + sizes determined by the selected paper type are transposed and then + scaled. + +} + +@defmethod[(get-paper-name) + string?]{ + +Returns the name of the current paper type: @scheme["A4 210 x 297 + mm"], @scheme["A3 297 x 420 mm"], @scheme["Letter 8 1/2 x 11 in"], or + @scheme["Legal 8 1/2 x 14 in"]. The default is @scheme["Letter 8 1/2 + x 11 in"]. + +The paper name determines the size of the drawing area as reported by + @method[dc<%> get-size] (along with landscape transformations from + @method[ps-setup% get-orientation] and/or the scaling factors of + @method[ps-setup% get-scaling]). It also determines the bounding box + of PostScript output when a @scheme[post-script-dc%] context is + created with a true value for the @scheme[use-paper-bbox?] + initialization argument. + +} + +@defmethod[(get-preview-command) + string?]{ + +Gets the command used to view a PostScript file for X. The default is + @scheme["gv"]. This value is not used by other platforms. + +} + +@defmethod[(get-scaling [x (box/c nonnegative-real?)] + [y (box/c nonnegative-real?)]) + void?]{ + +Gets the scaling factor for PostScript output. @boxisfill[(scheme x) + @elem{the horizontal scaling factor}] @boxisfill[(scheme y) @elem{the + vertical scaling factor}] The default is @scheme[0.8] by + @scheme[0.8]. + +This scale is in addition to a scale that can be set by @method[dc<%> + set-scale] in a @scheme[post-script-dc%] context. The size reported + by @method[dc<%> get-size] is the size of the selected paper type + (transposed for landscaped mode) divided by this scale. + +} + +@defmethod[(get-translation [x (box/c nonnegative-real?)] + [y (box/c nonnegative-real?)]) + void?]{ + +Gets the translation (from the bottom left corner) for PostScript + output. @boxisfill[@scheme[x] @elem{the horizontal offset}] + @boxisfill[@scheme[y] @elem{the vertical offset}] The default is + @scheme[0.0] and @scheme[0.0]. + +The translation is not scaled by the numbers returned from + @method[ps-setup% get-scaling] and the translation does not affect + the size of the drawing area. + +} + +@defmethod[(set-command [command string?]) + void?]{ + +Sets the printer command used to print a file under X. See + @method[ps-setup% get-command]. + +} + +@defmethod[(set-editor-margin [h nonnegative-exact-integer?] + [v nonnegative-exact-integer?]) + void?]{ + +Sets the horizontal and vertical margins used when printing an editor + with the @method[editor<%> print] method. These margins are always + used for printing, whether the drawing destination is a + @scheme[post-script-dc%] or @scheme[printer-dc%]. The margins are in + the units of the destination @scheme[printer-dc%] or + @scheme[post-script-dc%]. In the case of @scheme[post-script-dc%] + printing, the editor margin is in addition to the PostScript margin + that is determined by @method[ps-setup% set-margin]. + +} + +@defmethod[(set-file [filename (or/c path-string? false/c)]) + void?]{ + +Sets the PostScript output filename. See + @method[ps-setup% get-file]. + +} + +@defmethod[(set-level-2 [on? any/c]) + void?]{ + +Sets whether Level 2 commands are output in PostScript files. See + @method[ps-setup% get-level-2]. + +} + +@defmethod[(set-margin [h (and/c real? (not/c negative?))] + [v (and/c real? (not/c negative?))]) + void?]{ + +Sets the horizontal and vertical PostScript margins. When drawing to a + @scheme[post-script-dc%], the page size reported by @method[dc<%> + get-size] subtracts these margins from the normal page area (before + taking into account scaling affects). In addition, drawing into the + @scheme[post-script-dc%] produces PostScript output that is offset by + the margins. + +When using the output of a @scheme[post-script-dc%] as + Encapsulated PostScript, the margin values are effectively + irrelevant. Changing the margins moves the PostScript image in + absolute coordinates, but it also moves the bounding box. + +The margins are in unscaled @scheme[post-script-dc%] units, which + are points. The default margins are 16 points. + +} + +@defmethod[(set-mode [mode (one-of/c 'preview 'file 'printer)]) + void?]{ + +Sets the printing mode controlling where output is sent. See + @method[ps-setup% get-mode]. + +Under Windows and Mac OS X, if @scheme['preview] or @scheme['printer] + is provided, @|MismatchExn|. + +} + +@defmethod[(set-orientation [orientation (one-of/c 'portrait 'landscape)]) + void?]{ + +Sets the orientation. See @method[ps-setup% get-orientation]. + +} + +@defmethod[(set-paper-name [type string?]) + void?]{ + +Sets the name of the current paper type. See @method[ps-setup% + get-paper-name]. + +} + +@defmethod[(set-preview-command [command string?]) + void?]{ + +Sets the command used to view a PostScript file under X. See +@method[ps-setup% get-preview-command]. + +} + +@defmethod[(set-scaling [x (and/c real? (not/c negative?))] + [y (and/c real? (not/c negative?))]) + void?]{ + +Sets the scaling factor for PostScript output. See + @method[ps-setup% get-scaling]. + +} + +@defmethod[(set-translation [x real?] + [y real?]) + void?]{ + +Sets the translation (from the bottom left corner) for PostScript + output. See @method[ps-setup% get-translation]. + +}} diff --git a/collects/scribblings/gui/windowing.scrbl b/collects/scribblings/gui/reference.scrbl similarity index 52% rename from collects/scribblings/gui/windowing.scrbl rename to collects/scribblings/gui/reference.scrbl index 259b682527..de750d2c8f 100644 --- a/collects/scribblings/gui/windowing.scrbl +++ b/collects/scribblings/gui/reference.scrbl @@ -1,11 +1,12 @@ #reader(lib "docreader.ss" "scribble") @require["common.ss"] -@require["diagrams.ss"] -@title[#:tag "mr:windowing" #:style 'toc]{Windowing Toolbox} +@title[#:style 'toc]{Reference} @local-table-of-contents[] -@include-section["win-overview.scrbl"] @include-section["win-classes.scrbl"] @include-section["win-funcs.scrbl"] +@include-section["draw-classes.scrbl"] +@include-section["draw-funcs.scrbl"] +@include-section["editor-classes.scrbl"] diff --git a/collects/scribblings/gui/region-class.scrbl b/collects/scribblings/gui/region-class.scrbl new file mode 100644 index 0000000000..380330b6d2 --- /dev/null +++ b/collects/scribblings/gui/region-class.scrbl @@ -0,0 +1,268 @@ +#reader(lib "defreader.ss" "scribble") +@require["common.ss"] + +@defclass[region% object% ()]{ + +A @scheme[region%] object specifies a portion of a drawing area + (possibly discontinuous). It is normally used for clipping drawing + operations. + +Each @scheme[region%] object is associated to a particular + @scheme[dc<%>] object, specified when the region is created. A region + can only be used with its associated @scheme[dc<%>] object. The origin + and scale of a drawing context determine the bounding box and drawing + location of a region at the time that a region is created (or set); a + region is independent of the current scale and origin when the region + is used. For an auto-scrolled canvas, the canvas's current scrolling + applies when the region is used (and it does not affect the region's + bounding box). + +See also @xmethod[dc<%> set-clipping-region] and @xmethod[dc<%> + get-clipping-region]. + + +@defconstructor[([dc (is-a?/c dc<%>)])]{ + +Creates an empty region. + +} + +@defmethod[(get-bounding-box) + (values real? real? real? real?)]{ + +Returns a rectangle that encloses the region. The return values are + the left, top, width, and height of the rectangle. The bounding box + is precisely correct for unsmoothed drawing, but it is only + approximate for smoothed drawing. + +} + +@defmethod[(get-dc) + (is-a?/c dc<%>)]{ + +Returns the region's drawing context. + +} + +@defmethod[(in-region? [x real?] + [y real?]) + boolean?]{ + +Returns @scheme[#t] if the given point is approximately within the + region, @scheme[#f] otherwise. The given point is scaled and + translated according to the region's @scheme[dc<%>]'s current scale + and translation. + +The approximate in-region test represents the true result for + unsmoothed drawing, but it not necessarily for smoothed drawing. + +} + +@defmethod[(intersect [rgn (is-a?/c region%)]) + void?]{ + +Sets the region to the intersection of itself with the given region. + +The DC of @scheme[rgn] and @this-obj[] must be the same. + +The result is always reliable for unsmoothed and smoothed drawing. For + smoothed drawing, an intersect corresponds to clipping with this + region's path, and then clipping with the given region's path. + Further combining sends to this region correspond to combination with + the original path before initial clip, and further combination with + this region as an argument correspond to a combination with the given + path after the initial clip. Thus, an intersecting region is a poor + input for @method[region% union], @method[region% subtract], or + @method[region% xor], but it intersects properly in further calls to + @method[region% intersect]. + +} + +@defmethod[(is-empty?) + boolean?]{ + +Returns @scheme[#t] if the region is approximately empty, @scheme[#f] + otherwise. An approximately empty region is truly empty for + unsmoothed drawing, but it may contain points for smoothed drawing. + +} + +@defmethod[(set-arc [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))] + [start-radians real?] + [end-radians real?]) + void?]{ + +Sets the region to the interior of the specified wedge. + +See also @xmethod[dc<%> draw-ellipse], since the region content is + determined the same way as brush-based filling in a @scheme[dc<%>]. + +The result is reliable for both unsmoothed and smoothed drawing. For + smoothed drawing, the region corresponds to a clockwise path with a + @scheme['winding] fill. The region is also @defterm{atomic} for the + purposes of region combination. + +} + +@defmethod[(set-ellipse [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))]) + void?]{ + +Sets the region to the interior of the specified ellipse. + +See also @xmethod[dc<%> draw-ellipse], since the region content is + determined the same way as brush-based filling in a @scheme[dc<%>]. + +The result is reliable for both unsmoothed and smoothed drawing. For + smoothed drawing, the region corresponds to a clockwise path with a + @scheme['winding] fill. The region is also @defterm{atomic} for the + purposes of region combination. + +@|DrawSizeNote| + +} + +@defmethod[(set-path [path (is-a?/c dc-path%)] + [xoffset real? 0] + [yoffset real? 0] + [fill-style (one-of/c 'odd-even 'winding) 'odd-even]) + void?]{ + +Sets the region to the content of the given path. + +See also @xmethod[dc<%> draw-path], since the region content is + determined the same way as brush-based filling in a @scheme[dc<%>]. + +The result is reliable for both unsmoothed and smoothed drawing. For + smoothed drawing, the fill style affects how well the region reliably + combines with other regions (via @method[region% union], + @method[region% xor], and @method[region% subtract]). The region is + also @defterm{atomic} for the purposes of region combination. + +} + +@defmethod[(set-polygon [points (listof (is-a?/c point%))] + [xoffset real? 0] + [yoffset real? 0] + [fill-style (one-of/c 'odd-even 'winding) 'odd-even]) + void?]{ +Sets the region to the interior of the specified polygon. + +See also @xmethod[dc<%> draw-polygon], since the region content is + determined the same way as brush-based filling in a @scheme[dc<%>]. + +The result is reliable for both unsmoothed and smoothed drawing. For + smoothed drawing, the fill style affects how well the region reliably + combines with other regions (via @method[region% union], + @method[region% xor], and @method[region% subtract]). The region is + also @defterm{atomic} for the purposes of region combination. + +} + +@defmethod[(set-rectangle [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))]) + void?]{ + +Sets the region to the interior of the specified rectangle. + +See also @xmethod[dc<%> draw-rectangle], since the region content is + determined the same way as brush-based filling in a @scheme[dc<%>]. + +The result is reliable for both unsmoothed and smoothed drawing. For + smoothed drawing, the region corresponds to a clockwise path with a + @scheme['winding] fill. The region is also @defterm{atomic} for the + purposes of region combination. + +@|DrawSizeNote| + +} + +@defmethod[(set-rounded-rectangle [x real?] + [y real?] + [width (and/c real? (not/c negative?))] + [height (and/c real? (not/c negative?))] + [radius real? -0.25]) + void?]{ + +Sets the region to the interior of the specified rounded rectangle. + +See also @xmethod[dc<%> draw-rounded-rectangle], since the region + content is determined the same way as brush-based filling in a + @scheme[dc<%>]. + +The result is reliable for both unsmoothed and smoothed drawing. For + smoothed drawing, the region corresponds to a clockwise path with a + @scheme['winding] fill. The region is also @defterm{atomic} for the + purposes of region combination. + +@|DrawSizeNote| + +} + +@defmethod[(subtract [rgn (is-a?/c region%)]) + void?]{ + +Sets the region to the subtraction of itself minus the given region. + In other words, a point is removed from the region if it is included + in the given region. (The given region may contain points that are + not in the current region; such points are ignored.) + +This region's DC and given region's DC must be the same. + +The result is always reliable for unsmoothed drawing. For smoothed + drawing, the result is consistent across platforms and devices, but + it is never a true subtraction. A subtraction corresponds to + combining the sub-paths of this region with the reversed sub-paths of + the given region, then intersecting the result with this region. This + fails as a true subtraction, because the boundary of loops (with + either @scheme['odd-even] or @scheme['winding] filling) is ambiguous. + +} + +@defmethod[(union [rgn (is-a?/c region%)]) + void?]{ + +Sets the region to the union of itself with the given region. + +This region's DC and given region's DC must be the same. + +The result is always reliable for unsmoothed drawing. For smoothed + drawing, a union corresponds to combining the sub-paths of each + region into one path, using an @scheme['odd-even] fill if either of + the region uses an @scheme['odd-even] fill (otherwise using a + @scheme['winding] fill). Consequently, while the result is consistent + across platforms and devices, it is a true union only for certain + input regions. For example, it is a true union for non-overlapping + atomic and union regions. It is also a true union for atomic and + union regions (potentially overlapping) that are all clockwise and + use @scheme['winding] fill. + +} + +@defmethod[(xor [rgn (is-a?/c region%)]) + void?]{ + +Sets the region to the xoring of itself with the given region (i.e., + contains points that are enclosed by exactly one of the two regions). + +This region's DC and given region's DC must be the same. + +The result is always reliable for unsmoothed drawing. For smoothed + drawing, the result is consistent across platforms and devices, but + it is not necessarily a true xoring. An xoring corresponds to + combining the sub-paths of this region with the reversed sub-paths of + the given region. The result uses an @scheme['odd-even] fill if either + of the region uses an @scheme['odd-even] fill (otherwise using a + @scheme['winding] fill). Consequently, the result is a reliable xoring + only for certain input regions. For example, it is reliable for + atomic and xoring regions that all use @scheme['even-odd] fill. + +}} + diff --git a/collects/scribblings/gui/win-funcs.scrbl b/collects/scribblings/gui/win-funcs.scrbl index c671b756e6..88ae8af9eb 100644 --- a/collects/scribblings/gui/win-funcs.scrbl +++ b/collects/scribblings/gui/win-funcs.scrbl @@ -1,7 +1,7 @@ #reader(lib "docreader.ss" "scribble") @require["common.ss"] -@title[#:style 'toc]{Windowing Function Reference} +@title{Windowing Function Reference} @local-table-of-contents[] diff --git a/collects/scribblings/gui/win-overview.scrbl b/collects/scribblings/gui/win-overview.scrbl index 0f6a0bf06d..1668159975 100644 --- a/collects/scribblings/gui/win-overview.scrbl +++ b/collects/scribblings/gui/win-overview.scrbl @@ -3,9 +3,7 @@ @require["common.ss"] @require["diagrams.ss"] -@title[#:tag "mr:windowing-overview" #:style 'toc]{Windowing Toolbox Overview} - -@local-table-of-contents[] +@title[#:tag "mr:windowing-overview"]{Windowing Guide} @section{Basic GUI Building Blocks} diff --git a/collects/tests/mzscheme/filelib.ss b/collects/tests/mzscheme/filelib.ss index fa83b2c688..511ebac9d6 100644 --- a/collects/tests/mzscheme/filelib.ss +++ b/collects/tests/mzscheme/filelib.ss @@ -21,9 +21,9 @@ (current-directory)) (let ([rel2 (fold-files (lambda (name kind accum) - (test kind values (if (file-exists? name) - 'file - 'dir)) + (test kind name (if (file-exists? name) + 'file + 'dir)) (cons name accum)) null)] [sort (lambda (l) @@ -41,9 +41,10 @@ (test kind values (cond [(link-exists? name) 'link] [(file-exists? name) 'file] - [else 'dir])) + [(dir-exists? name) 'dir] + [else '???])) (when (member name '("filelib-link.ss" "loop-link")) - (test kind values 'link)) + (test kind name 'link)) (add1 accum)) 0 #f @@ -58,7 +59,7 @@ [(file-exists? name) 'file] [else 'dir])) (when (member name '("filelib-link.ss")) - (test kind values 'file)) + (test kind name 'file)) (add1 accum)) 0 #f