button.scm 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. ;; Buttons: Knöpfe mit Beschriftung
  2. ;; ,open threads rendezvous rendezvous-channels rendezvous-async-channels \
  3. ;; toy-geometry toy-display-system toy-window-system
  4. (define (make-button label action-thunk widget-env)
  5. (let* ((bitmap (widget-env-bitmap widget-env))
  6. (rectangle (bitmap-rectangle bitmap))
  7. (button-width (rectangle-width rectangle))
  8. (button-height (rectangle-height rectangle)))
  9. (call-with-values
  10. (lambda () (bitmap-text-size bitmap label))
  11. (lambda (height width ascent)
  12. (let* ((text-origin
  13. (make-point (max 0
  14. (quotient (- button-width
  15. width)
  16. 2))
  17. (min (- button-height 1)
  18. (+ (quotient (- button-height
  19. height)
  20. 2)
  21. ascent)))))
  22. (bitmap-draw-rectangle bitmap 'copy
  23. (make-rectangle 0 0
  24. (- button-width 1)
  25. (- button-height 1)))
  26. (bitmap-draw-text bitmap 'copy text-origin label)
  27. (make-channel-sink (widget-env-keyboard-channel widget-env))
  28. (spawn
  29. (lambda ()
  30. (let loop ((was-in-and-up? #f))
  31. (define (mouse-state message)
  32. (values (mouse-message-down? message)
  33. (point-in-rectangle? (mouse-message-position message)
  34. rectangle)))
  35. (define (handle-mouse message)
  36. (call-with-values
  37. (lambda () (mouse-state message))
  38. (lambda (down? in?)
  39. (if (and was-in-and-up? down? in?)
  40. (begin
  41. (action-thunk)
  42. (loop #f))
  43. (loop (and (not down?) in?))))))
  44. (define (handle-control message)
  45. (case (control-message-type message)
  46. ((delete)
  47. (send-async (widget-env-control-out-channel widget-env)
  48. message))
  49. (else
  50. (loop was-in-and-up?))))
  51. (select
  52. (wrap (receive-rv (widget-env-mouse-channel widget-env))
  53. handle-mouse)
  54. (wrap (receive-rv (widget-env-control-in-channel widget-env))
  55. handle-control)))))
  56. widget-env)))))
  57. ;; Tests
  58. (define (test-button)
  59. (let* ((root-widget-env
  60. (make-window-system "Button Test" 320 200))
  61. (button-bitmap
  62. (make-bitmap (widget-env-bitmap root-widget-env)
  63. (make-rectangle 10 10 100 50)))
  64. (button-widget-env
  65. (make-widget-env button-bitmap
  66. (widget-env-mouse-channel root-widget-env)
  67. (widget-env-keyboard-channel root-widget-env)
  68. (widget-env-control-in-channel root-widget-env)
  69. (widget-env-control-out-channel root-widget-env))))
  70. (make-button "Click me!"
  71. (lambda ()
  72. (display "Click!")
  73. (newline))
  74. button-widget-env)))