(module toolbar mzscheme (require (prefix mred: mred) mzlib/class mzlib/file mzlib/pretty mzlib/etc mzlib/list "utils.ss") ;; These modules implement snips for the various ;; kinds of windows and controls. (require "base.ss" "panel.ss" "simple-control.ss" "text-field.ss" "multiple-choice.ss" "slider-guage.ss" "canvas.ss") ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Frame ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define-struct tool (icon callback active?)) (define lg-pen (send mred:the-pen-list find-or-create-pen (make-object mred:color% 200 200 200) 0 'solid)) (define dg-pen (send mred:the-pen-list find-or-create-pen (make-object mred:color% 140 140 140) 0 'solid)) (define icons (make-hash-table)) (define toolbar% (class mred:canvas% (inherit min-height stretchable-height get-dc) (init [style '()]) (private-field [margin 2] [icon-size 16] [tools null] [active-tool #f]) (private* [deactivate-tool (lambda () (when active-tool (set-tool-active?! active-tool #f) (set! active-tool #f) (on-paint)))] [activate-tool (lambda (mx my only) (let ([y 0] [h (+ icon-size (* 2 margin))] [w (+ icon-size (* 2 margin))]) (let loop ([l tools][x 0]) (unless (null? l) (if (and (<= x mx (+ x w)) (<= y my (+ y h)) (or (not only) (eq? (car l) only))) (begin (set! active-tool (car l)) (set-tool-active?! active-tool #t) (on-paint)) (loop (cdr l) (+ x w)))))))]) (private-field [can-drag #f]) (override* [on-paint (lambda () (let ([dc (get-dc)] [y 0] [h (+ icon-size (* 2 margin))] [w (+ icon-size (* 2 margin))]) (let loop ([l tools][x 0]) (unless (null? l) (let ([tool (car l)]) (let ([p (send dc get-pen)] [on? (tool-active? tool)]) (send dc set-pen (if on? dg-pen lg-pen)) (send dc draw-line x y (+ x w -1) y) (send dc draw-line x y x (+ y h -1)) (send dc draw-line x (add1 y) (+ x w -2) (add1 y)) (send dc draw-line (add1 x) y (add1 x) (+ y h -2)) (send dc set-pen (if on? lg-pen dg-pen)) (send dc draw-line (+ x 1) (+ y h -1) (+ x w -1) (+ y h -1)) (send dc draw-line (+ x w -1) (+ y 1) (+ x w -1) (+ y h -1)) (send dc draw-line (+ x 2) (+ y h -2) (+ x w -2) (+ y h -2)) (send dc draw-line (+ x w -2) (+ y 2) (+ x w -2) (+ y h -2)) (send dc set-pen p)) (if (tool-icon tool) (send dc draw-bitmap (tool-icon tool) (+ x margin) margin) (send dc draw-rectangle (+ x margin) margin icon-size icon-size))) (loop (cdr l) (+ x w))))))] [on-event (lambda (e) (cond [(send e button-down?) (deactivate-tool) (activate-tool (send e get-x) (send e get-y) #f) (set! can-drag active-tool)] [(send e button-up?) (set! can-drag #f) (when active-tool (let ([cb (tool-callback active-tool)]) (deactivate-tool) (cb #f #f)))] [(send e dragging?) (when can-drag (let ([old-active active-tool]) (set! active-tool #f) (activate-tool (send e get-x) (send e get-y) can-drag) (when (and (not active-tool) old-active) (set-tool-active?! old-active #f) (on-paint))))] [else (set! can-drag #f) (deactivate-tool)]))]) (public* [append-tool (lambda (icon-name cb) (let* ([name (string->symbol icon-name)] [icon (hash-table-get icons name (lambda () (let* ([icon (make-object mred:bitmap% (build-path (collection-path "guibuilder") icon-name))]) (if (send icon ok?) icon #f))))]) (hash-table-put! icons name icon) (set! tools (append tools (list (make-tool icon cb #f))))))]) (super-new [style (cons 'no-focus style)]) (min-height (+ icon-size (* margin 2))) (stretchable-height #f))) (define (add-tools toolbar emenu insert-element) (let* ([append-element-type (lambda (name icon c%) (let ([maker (lambda (i e) (insert-element c%))]) (when toolbar (send toolbar append-tool icon maker)) (when emenu (make-object mred:menu-item% name emenu maker))))]) (append-element-type "New Vertical Panel" "vpanel.xpm" gb:vertical-panel-snip%) (append-element-type "New Horizontal Panel" "hpanel.xpm" gb:horizontal-panel-snip%) (append-element-type "New Message Label" "message.xpm" gb:message-snip%) (append-element-type "New Button" "button.xpm" gb:button-snip%) (append-element-type "New Checkbox" "checkbox.xpm" gb:check-box-snip%) (append-element-type "New Text Field" "text.xpm" gb:text-snip%) (append-element-type "New List" "list.xpm" gb:list-box-snip%) (append-element-type "New Radiobox" "radiobox.xpm" gb:radio-box-snip%) (append-element-type "New Choice" "choice.xpm" gb:choice-snip%) (append-element-type "New Slider" "slider.xpm" gb:slider-snip%) (append-element-type "New Gauge" "gauge.xpm" gb:gauge-snip%) (append-element-type "New Canvas" "canvas.xpm" gb:canvas-snip%) (append-element-type "New Editor Canvas" "mcanvas.xpm" gb:editor-canvas-snip%))) (provide toolbar% add-tools))