Added unstable/gui/snip (provides snip-canvas%) and docs
Changed plot-frame to use snip-canvas%, so resizing the frame resizes the plot; added Escape handler (closes the frame)
This commit is contained in:
parent
bf97780eda
commit
610280225c
|
@ -1,44 +1,34 @@
|
|||
#lang racket/base
|
||||
|
||||
;; Extra GUI classes.
|
||||
;; GUI helpers
|
||||
|
||||
(require racket/gui/base racket/class)
|
||||
(require racket/gui/base racket/class unstable/gui/snip)
|
||||
|
||||
(provide (all-defined-out))
|
||||
|
||||
(define read-only-text%
|
||||
(class text%
|
||||
(define snip-frame%
|
||||
(class frame%
|
||||
(super-new)
|
||||
|
||||
(send this hide-caret #t)
|
||||
|
||||
(define writable? #t)
|
||||
(define/public (set-writable w?) (set! writable? w?))
|
||||
|
||||
(define/augment (can-change-style? start len) writable?)
|
||||
(define/augment (can-delete? start len) writable?)
|
||||
(define/augment (can-insert? start len) writable?)
|
||||
(define/augment (can-load-file? filename format) writable?)
|
||||
(define/augment (can-save-file? filename format) writable?)
|
||||
(define/override (can-do-edit-operation? op [recursive? #t])
|
||||
(case op
|
||||
[(copy select-all) #t]
|
||||
[else writable?]))
|
||||
(define/override (on-traverse-char event)
|
||||
(define key-code (send event get-key-code))
|
||||
(case key-code
|
||||
[(escape) (send this show #f)]
|
||||
[else (super on-traverse-char event)]))
|
||||
))
|
||||
|
||||
(define (make-snip-frame snip width height label)
|
||||
(define frame (new frame% [width width] [height height] [label label]))
|
||||
(define text (new read-only-text%))
|
||||
(define canvas (new editor-canvas% [parent frame] [editor text]
|
||||
[horizontal-inset 0] [vertical-inset 0] [horiz-margin 0] [vert-margin 0]
|
||||
[enabled #t] [style '(no-hscroll no-vscroll no-border)]))
|
||||
(send text insert snip)
|
||||
(send text set-writable #f)
|
||||
(define (make-snip w h)
|
||||
(send snip resize w h)
|
||||
snip)
|
||||
|
||||
(define frame
|
||||
(new snip-frame% [label label] [width (+ 10 width)] [height (+ 10 height)]))
|
||||
|
||||
(new snip-canvas%
|
||||
[parent frame]
|
||||
[make-snip make-snip]
|
||||
[horiz-margin 5] [vert-margin 5]
|
||||
[horizontal-inset 5] [vertical-inset 5])
|
||||
|
||||
frame)
|
||||
|
||||
(define (snip->canvas snip)
|
||||
(let/ec return
|
||||
(define admin (send snip get-admin))
|
||||
(when (not admin) (return #f))
|
||||
(define editor (send admin get-editor))
|
||||
(send editor get-active-canvas)))
|
||||
|
|
|
@ -84,7 +84,7 @@ Use @(racket plot-bitmap) to create a @(racket bitmap%).
|
|||
|
||||
Use @(racket plot-frame) to create a @(racket frame%) regardless of the value of @(racket plot-new-window?). The frame is initially hidden.
|
||||
|
||||
Use @(racket plot-snip) to create an @(racket image-snip%) regardless of the value of @(racket plot-new-window?).
|
||||
Use @(racket plot-snip) to create an interactive @(racket image-snip%) regardless of the value of @(racket plot-new-window?).
|
||||
}
|
||||
|
||||
@doc-apply[plot/dc]{
|
||||
|
|
81
collects/unstable/gui/snip.rkt
Normal file
81
collects/unstable/gui/snip.rkt
Normal file
|
@ -0,0 +1,81 @@
|
|||
#lang racket/base
|
||||
|
||||
(require racket/gui/base racket/class)
|
||||
|
||||
(provide snip-canvas%)
|
||||
|
||||
(define snip-canvas%
|
||||
(class editor-canvas%
|
||||
(init parent
|
||||
make-snip
|
||||
[style null]
|
||||
[label #f]
|
||||
[horizontal-inset 5]
|
||||
[vertical-inset 5]
|
||||
[enabled #t]
|
||||
[vert-margin 0]
|
||||
[horiz-margin 0]
|
||||
[min-width 0]
|
||||
[min-height 0]
|
||||
[stretchable-width #t]
|
||||
[stretchable-height #t])
|
||||
|
||||
(define snip #f)
|
||||
(define text (new read-only-text%))
|
||||
(send text set-writable #f)
|
||||
|
||||
(super-new [parent parent]
|
||||
[editor text]
|
||||
[horizontal-inset horizontal-inset]
|
||||
[vertical-inset vertical-inset]
|
||||
[label label]
|
||||
[enabled enabled]
|
||||
[style (list* 'no-hscroll 'no-vscroll style)]
|
||||
[vert-margin vert-margin]
|
||||
[horiz-margin horiz-margin]
|
||||
[min-width min-width]
|
||||
[min-height min-height]
|
||||
[stretchable-width stretchable-width]
|
||||
[stretchable-height stretchable-height])
|
||||
|
||||
(define/public (get-snip) snip)
|
||||
|
||||
(define/override (on-size w h)
|
||||
(update-snip w h)
|
||||
(super on-size w h))
|
||||
|
||||
(define (update-snip w h)
|
||||
(define snip-w (max 0 (- w (* 2 horizontal-inset))))
|
||||
(define snip-h (max 0 (- h (* 2 vertical-inset))))
|
||||
(cond [snip (send snip resize snip-w snip-h)]
|
||||
[else (set-snip (make-snip snip-w snip-h))]))
|
||||
|
||||
(define (set-snip s)
|
||||
(unless (is-a? s snip%)
|
||||
(raise-type-error 'set-snip "snip%" s))
|
||||
(set! snip s)
|
||||
(send text set-writable #t)
|
||||
(send text erase)
|
||||
(send text insert snip)
|
||||
(send text set-writable #f))
|
||||
))
|
||||
|
||||
(define read-only-text%
|
||||
(class text%
|
||||
(super-new)
|
||||
|
||||
(send this hide-caret #t)
|
||||
|
||||
(define writable? #t)
|
||||
(define/public (set-writable w?) (set! writable? w?))
|
||||
|
||||
(define/augment (can-change-style? start len) writable?)
|
||||
(define/augment (can-delete? start len) writable?)
|
||||
(define/augment (can-insert? start len) writable?)
|
||||
(define/augment (can-load-file? filename format) writable?)
|
||||
(define/augment (can-save-file? filename format) writable?)
|
||||
(define/override (can-do-edit-operation? op [recursive? #t])
|
||||
(case op
|
||||
[(copy select-all) #t]
|
||||
[else writable?]))
|
||||
))
|
|
@ -12,3 +12,4 @@
|
|||
@include-section["gui/pict.scrbl"]
|
||||
@include-section["gui/slideshow.scrbl"]
|
||||
@include-section["gui/pslide.scrbl"]
|
||||
@include-section["gui/snip.scrbl"]
|
||||
|
|
95
collects/unstable/scribblings/gui/snip.scrbl
Normal file
95
collects/unstable/scribblings/gui/snip.scrbl
Normal file
|
@ -0,0 +1,95 @@
|
|||
#lang scribble/manual
|
||||
|
||||
@(require "../utils.rkt"
|
||||
(for-label racket/base
|
||||
racket/class
|
||||
racket/gui/base
|
||||
unstable/gui/snip
|
||||
racket/contract
|
||||
plot))
|
||||
|
||||
@title[#:tag "snip"]{Snip Utilities}
|
||||
@unstable[@author+email["Neil Toronto" "neil.toronto@gmail.com"]]
|
||||
|
||||
@defmodule[unstable/gui/snip]
|
||||
|
||||
@defclass[snip-canvas% editor-canvas% ()]{
|
||||
A canvas that contains a single snip.
|
||||
|
||||
Snips cannot be placed directly on dialogs, frames and panels.
|
||||
To use an interactive snip (such as one returned by @racket[plot-snip]) in a GUI,
|
||||
it must be inserted into an editor, which itself must be placed on a special canvas, which can be placed in a GUI container.
|
||||
To provide a seamless user experience, the editor should be enabled but not writable,
|
||||
not be able to receive focus, not have scrollbars, and other small details.
|
||||
|
||||
The @racket[snip-canvas%] class handles these details, making it easy to use interactive snips as normal GUI elements.
|
||||
|
||||
@defconstructor[([parent (or/c (is-a?/c frame%) (is-a?/c dialog%)
|
||||
(is-a?/c panel%) (is-a?/c pane%))]
|
||||
[make-snip ((integer-in 0 10000) (integer-in 0 10000) . -> . snip%)]
|
||||
[style (listof (one-of/c 'no-border 'control-border 'combo
|
||||
'resize-corner 'no-focus 'deleted
|
||||
'transparent)) null]
|
||||
[label (or/c label-string? false/c) #f]
|
||||
[horizontal-inset (integer-in 0 1000) 5]
|
||||
[vertical-inset (integer-in 0 1000) 5]
|
||||
[enabled any/c #t]
|
||||
[vert-margin (integer-in 0 1000) 0]
|
||||
[horiz-margin (integer-in 0 1000) 0]
|
||||
[min-width (integer-in 0 10000) 0]
|
||||
[min-height (integer-in 0 10000) 0]
|
||||
[stretchable-width any/c #t]
|
||||
[stretchable-height any/c #t])]{
|
||||
Unlike instances of @racket[editor-canvas%], each instance of this class creates and manages its own editor.
|
||||
The editor contains one object: a @racket[snip%] instance created by @racket[make-snip].
|
||||
|
||||
The @racket[make-snip] function receives the requested width and height of the snip, which are calculated from the size of the snip canvas.
|
||||
It is called the first time the snip canvas is resized, which most likely coincides with the first time the snip canvas is shown.
|
||||
The snip is thus created @italic{lazily}: only when needed, at the size needed.
|
||||
See @method[snip-canvas% on-size] for more details and an example.
|
||||
|
||||
The @racket[style] list is prepended with @racket['no-hscroll] and @racket['no-vscroll] before being passed to the @racket[editor-canvas%] constructor.
|
||||
The other constructor arguments are passed untouched.
|
||||
}
|
||||
|
||||
@defmethod[(get-snip) (or/c (is-a?/c snip%) #f)]{
|
||||
Returns the wrapped snip, or @racket[#f] if @racket[make-snip] has not been called yet.
|
||||
}
|
||||
|
||||
@defmethod[#:mode override
|
||||
(on-size [width (integer-in 0 10000)]
|
||||
[height (integer-in 0 10000)])
|
||||
void?]{
|
||||
This is called when the snip canvas is resized.
|
||||
|
||||
On the first call, @method[snip-canvas% on-size] calls @racket[make-snip] with width and height arguments
|
||||
respectively @racket[(max 0 (- width (* 2 horizontal-inset)))] and @racket[(max 0 (- height (* 2 vertical-inset)))].
|
||||
It then inserts the resulting snip into its editor.
|
||||
|
||||
On subsequent calls, @method[snip-canvas% on-size] calls the snip's @method[snip% resize] method, calculating the width and height arguments the same way.
|
||||
|
||||
When a @racket[snip-canvas%] instance is intended to wrap an existing @racket[snip%] instance, @racket[make-snip] should simply resize it and return it.
|
||||
|
||||
Example: @racket[plot-frame] and @racket[plot3d-frame] create snips and call a function similar to the following to place them in a frame:
|
||||
@racketblock[
|
||||
(define (make-snip-frame snip w h label)
|
||||
(define (make-snip width height)
|
||||
(send snip resize width height)
|
||||
snip)
|
||||
|
||||
(define frame
|
||||
(new frame%
|
||||
[label label]
|
||||
[width (+ 5 5 5 5 w)]
|
||||
[height (+ 5 5 5 5 h)]))
|
||||
|
||||
(new snip-canvas%
|
||||
[parent frame]
|
||||
[make-snip make-snip]
|
||||
[horiz-margin 5] [vert-margin 5]
|
||||
[horizontal-inset 5] [vertical-inset 5])
|
||||
|
||||
frame)]
|
||||
}
|
||||
|
||||
} @; defclass snip-canvas%
|
Loading…
Reference in New Issue
Block a user