;; The first three lines of this file were inserted by DrRacket. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(lib "htdp-beginner-reader.ss" "lang")((modname textbox-demo-v2-after) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f () #f))) (require 2htdp/image) (require 2htdp/universe) ; Datatype def'n: (define-struct textbox (contents cursor)) ; make-textbox : string, natural -> textbox ; cursor: the #of chars of `contents` which precede the cursor-location ; must be in 0..(string-length contents). ; racket auto-creates constructr as above, getters, and a predicate: ; textbox-contents : textbox -> string ; textbox-cursor : textbox -> natural ; textbox? : ANY -> boolean ; examples of data (make-textbox "hello" 0) ; cursor before entire word (make-textbox "hello" 1) (make-textbox "hello" 5) (make-textbox "hello" 3) (make-textbox "h" 0) (make-textbox "h" 1) (define EMPTY-TEXTBOX (make-textbox "" 0)) ; template: ; (define (func-for-textbox a-textbox) ;(-> textbox? ...) (... (textbox-contents a-textbox) (textbox-cursor a-textbox))) ;=========== (check-expect (handle-key (make-textbox "hello" 5) "right") (make-textbox "hello" 5)) (check-expect (handle-key (make-textbox "hello" 0) "left") (make-textbox "hello" 0)) (check-expect (handle-key (make-textbox "hello" 0) "\b") (make-textbox "hello" 0)) (check-expect (handle-key (make-textbox "hello" 3) "x") (make-textbox "helxlo" 4)) (check-expect (handle-key (make-textbox "hello" 3) "right") (make-textbox "hello" 4)) (check-expect (handle-key (make-textbox "hello" 3) "left") (make-textbox "hello" 2)) (check-expect (handle-key (make-textbox "hello" 3) "\b") (make-textbox "helo" 2)) ; Update `a-textbox` to incorporate `key`. ; (define (handle-key a-textbox key) ;(-> textbox? key-event? textbox?) (cond [(key=? key "right") (make-textbox (textbox-contents a-textbox) (min (add1 (textbox-cursor a-textbox)) (string-length (textbox-contents a-textbox))))] [(key=? key "left") (make-textbox (textbox-contents a-textbox) (max 0 (sub1 (textbox-cursor a-textbox))))] [(key=? key "\b") (make-textbox (string-append (substring (textbox-contents a-textbox) 0 (max 0 (sub1 (textbox-cursor a-textbox)))) (substring (textbox-contents a-textbox) (textbox-cursor a-textbox))) (max 0 (sub1 (textbox-cursor a-textbox))))] [else (make-textbox (string-append (substring (textbox-contents a-textbox) 0 (textbox-cursor a-textbox)) key (substring (textbox-contents a-textbox) (textbox-cursor a-textbox))) (add1 (textbox-cursor a-textbox)))])) (check-expect (draw (make-textbox "hello" 3)) (overlay/align "left" "center" (beside (text "hel" 20 'blue) (rectangle 1 17 'solid 'orange) (text "lo" 20 'blue)) (rectangle 200 20 'outline 'green))) (check-expect (draw (make-textbox "hello" 0)) (overlay/align "left" "center" (beside (rectangle 1 17 'solid 'orange) (text "hello" 20 'blue)) (rectangle 200 20 'outline 'green))) (check-expect (draw (make-textbox "hello" 5)) (overlay/align "left" "center" (beside (text "hello" 20 'blue) (rectangle 1 17 'solid 'orange)) (rectangle 200 20 'outline 'green))) (check-expect (draw (make-textbox "" 0)) (overlay/align "left" "center" (rectangle 1 17 'solid 'orange) (rectangle 200 20 'outline 'green))) (define TEXT-HEIGHT 80) ; use 20 to pass tests (they're hard-coded, boo! Hmm, maybe 20 should be a *parameter*, not a global?) (define TEXTBOX-WIDTH (* TEXT-HEIGHT 10)) ; draw : textbox? -> image? ; Create an image corresponding to the textbox. ; (define (draw a-textbox) (overlay/align "left" "center" (beside (text (substring (textbox-contents a-textbox) 0 (textbox-cursor a-textbox)) TEXT-HEIGHT 'blue) (rectangle 1 (* 17/20 TEXT-HEIGHT) 'solid 'orange) (text (substring (textbox-contents a-textbox) (textbox-cursor a-textbox)) TEXT-HEIGHT 'blue)) (rectangle TEXTBOX-WIDTH TEXT-HEIGHT 'outline 'green))) (big-bang (make-textbox "" 0) [on-draw draw] [on-key handle-key])