187 lines
5.9 KiB
Racket
187 lines
5.9 KiB
Racket
#lang racket/base
|
|
(require racket/class
|
|
racket/gui/base
|
|
framework
|
|
"interfaces.rkt")
|
|
|
|
(provide insert-text
|
|
ext:text%
|
|
rackunit-style-map)
|
|
|
|
;; insert-text : text% string style-delta% -> void
|
|
(define (insert-text e text style)
|
|
(let ([a (send e last-position)])
|
|
(send e insert text)
|
|
(let ([b (send e last-position)])
|
|
(send e change-style style a b))))
|
|
|
|
(define text<%> (class->interface text%))
|
|
|
|
(define ext:text-mixin
|
|
(mixin (text<%>) ()
|
|
(init-field (style-map rackunit-style-map))
|
|
(inherit last-position
|
|
change-style
|
|
set-clickback
|
|
insert
|
|
get-canvas
|
|
set-styles-sticky
|
|
set-autowrap-bitmap)
|
|
|
|
(super-new (auto-wrap #t))
|
|
(set-styles-sticky #f)
|
|
(set-autowrap-bitmap #f)
|
|
|
|
;; insert/styles : (list-of style-delta%) string ... -> void
|
|
;; A list of styles to be applied. The first style is the last applied.
|
|
(define/public (insert/styles styles . texts)
|
|
(unless (andmap (lambda (x) (or (string? x) (is-a? x snip%))) texts)
|
|
(raise-type-error 'insert/styles "list of strings" texts))
|
|
(let-values ([(a b) (put texts)])
|
|
(for-each (lambda (style) (change-style (resolve style) a b))
|
|
(reverse styles))))
|
|
|
|
;; insert/styles+click : (list-of style-delta%) (?? -> void) string ...-> void
|
|
(define/public (insert/styles+click styles clickback . texts)
|
|
(unless (andmap (lambda (x) (or (string? x) (is-a? x snip%))) texts)
|
|
(raise-type-error 'insert/styles+click "list of strings" texts))
|
|
(let-values ([(a b) (put texts)])
|
|
(for-each (lambda (style) (change-style (resolve style) a b))
|
|
(reverse styles))
|
|
(set-clickback a b clickback)))
|
|
|
|
;; put : (list-of string) -> int int
|
|
(define/private (put texts)
|
|
(let ([a (last-position)])
|
|
(let loop ([texts texts] [where a])
|
|
(if (pair? texts)
|
|
(begin (insert (car texts) where 'same #f)
|
|
(loop (cdr texts) (last-position)))
|
|
(values a where)))))
|
|
|
|
(define/private (resolve style)
|
|
(if (symbol? style)
|
|
(send style-map get-style style)
|
|
style))
|
|
|
|
;; newline : -> void
|
|
(define/public (newline)
|
|
(insert/styles '() "\n"))
|
|
|
|
;; insert-wide-box : (ext:text<%> -> void) -> void
|
|
(define/public (insert-wide-box p)
|
|
(internal-insert-box p #t)
|
|
(newline))
|
|
|
|
;; internal-insert-box : (ext:text<%> -> void) boolean? -> void
|
|
(define/private (internal-insert-box p wide?)
|
|
(let* ([seditor (new ext:text%)]
|
|
[snip (new editor-snip% (editor seditor))])
|
|
(p seditor)
|
|
(let [(canvas (get-canvas))]
|
|
(when (and (is-a? canvas canvas:wide-snip<%>) wide?)
|
|
(send canvas add-wide-snip snip)))
|
|
(insert snip)
|
|
(send seditor lock #t)))
|
|
|
|
))
|
|
|
|
(define ext:text%
|
|
(text:wide-snip-mixin
|
|
(ext:text-mixin
|
|
text:hide-caret/selection%)))
|
|
|
|
(define style:no-change (make-object style-delta% 'change-nothing))
|
|
(define style:normal (make-object style-delta% 'change-normal))
|
|
(define style:large (make-object style-delta% 'change-nothing))
|
|
(void (send style:large set-size-mult 1.5))
|
|
|
|
(define style:blue (make-object style-delta% 'change-nothing))
|
|
(void (send style:blue set-delta-foreground "Blue"))
|
|
|
|
(define style:red (make-object style-delta% 'change-nothing))
|
|
(void (send style:red set-delta-foreground "Red"))
|
|
|
|
(define style:green (make-object style-delta% 'change-nothing))
|
|
(void (send style:green set-delta-foreground "ForestGreen"))
|
|
|
|
(define style:purple (make-object style-delta% 'change-nothing))
|
|
(void (send style:purple set-delta-foreground "Purple"))
|
|
|
|
(define style:gray (make-object style-delta% 'change-nothing))
|
|
(void (send style:gray set-delta-foreground "DimGray"))
|
|
|
|
(define style:darkblue (make-object style-delta% 'change-nothing))
|
|
(void (send style:darkblue set-delta-foreground "DarkBlue"))
|
|
|
|
(define style:clickback (make-object style-delta% 'change-underline #t))
|
|
(void (send style:clickback set-delta-foreground "blue"))
|
|
|
|
(define style:bold (make-object style-delta% 'change-nothing))
|
|
(void (send style:bold set-delta 'change-weight 'bold))
|
|
|
|
(define style:italic (make-object style-delta% 'change-nothing))
|
|
(void (send style:italic set-delta 'change-style 'italic))
|
|
|
|
(define basic-styles
|
|
`([no-change . ,style:no-change]
|
|
[normal . ,style:normal]
|
|
[large . ,style:large]
|
|
[clickback . ,style:clickback]
|
|
[red . ,style:red]
|
|
[blue . ,style:blue]
|
|
[green . ,style:green]
|
|
[purple . ,style:purple]
|
|
[darkblue . ,style:darkblue]
|
|
[bold . ,style:bold]
|
|
[italic . ,style:italic]
|
|
[error . ,style:red]
|
|
[value . ,style:darkblue]))
|
|
|
|
(define rackunit-styles
|
|
`([test-unexecuted . ,style:gray]
|
|
[test-success . ,style:green]
|
|
[test-failure . ,style:red]
|
|
[test-error . ,style:red]
|
|
|
|
[exn-type . ,style:darkblue]
|
|
[exn-message . ,style:red]
|
|
[exn-value . ,style:darkblue]
|
|
[fail-type . ,style:darkblue]))
|
|
|
|
|
|
;; -- style-map classes
|
|
|
|
(define extended-style-map%
|
|
(class* object% (style-map<%>)
|
|
(init-field styles
|
|
base)
|
|
(define/public (get-style sym)
|
|
(cond [(assq sym styles) => cdr]
|
|
[else (send base get-style sym)]))
|
|
(super-new)))
|
|
|
|
(define empty-style-map%
|
|
(class* object% (style-map<%>)
|
|
(define/public (get-style sym)
|
|
(error 'get-style "unknown style: ~s" sym))
|
|
(super-new)))
|
|
|
|
;; extend-style-map : style-map<%> styles -> style-map<%>
|
|
(define (extend-style-map base styles)
|
|
(new extended-style-map% (base base) (styles styles)))
|
|
|
|
;; empty-style-map : style-map<%>
|
|
(define empty-style-map
|
|
(new empty-style-map%))
|
|
|
|
;; basic-style-map : style-map<%>
|
|
(define basic-style-map
|
|
(extend-style-map empty-style-map
|
|
basic-styles))
|
|
|
|
;; rackunit-style-map : style-map<%>
|
|
(define rackunit-style-map
|
|
(extend-style-map basic-style-map
|
|
rackunit-styles))
|