/collects/mred/private/wx/cocoa/slider.rkt

http://github.com/gmarceau/PLT · Racket · 177 lines · 149 code · 23 blank · 5 comment · 21 complexity · 1204bdb6f13773c7021b86ad07e062e7 MD5 · raw file

  1. #lang racket/base
  2. (require racket/class
  3. ffi/unsafe
  4. ffi/unsafe/objc
  5. "../../syntax.rkt"
  6. "item.rkt"
  7. "types.rkt"
  8. "const.rkt"
  9. "utils.rkt"
  10. "window.rkt"
  11. "queue.rkt"
  12. "../common/event.rkt"
  13. "../common/queue.rkt"
  14. "../common/freeze.rkt"
  15. "../../lock.rkt")
  16. (provide
  17. (protect-out slider%))
  18. ;; ----------------------------------------
  19. (import-class NSSlider NSTextField NSView)
  20. (define-objc-class MySlider NSSlider
  21. #:mixins (FocusResponder KeyMouseResponder CursorDisplayer)
  22. [wxb]
  23. (-a _void (changed: [_id sender])
  24. (let ([wx (->wx wxb)])
  25. (when wx
  26. (send wx update-message)
  27. (queue-window-event wx (lambda () (send wx changed)))
  28. (constrained-reply
  29. (send wx get-eventspace)
  30. (lambda () (let loop () (pre-event-sync #t) (when (yield/no-sync) (loop))))
  31. (void))))))
  32. (defclass slider% item%
  33. (init parent cb
  34. label
  35. val lo hi
  36. x y w
  37. style
  38. font)
  39. (inherit get-cocoa register-as-child
  40. init-font)
  41. (define vert? (memq 'vertical style))
  42. (define slider-lo lo)
  43. (define slider-hi hi)
  44. (define slider-cocoa
  45. (let ([cocoa (as-objc-allocation
  46. (tell (tell MySlider alloc) init))])
  47. (tellv cocoa setMinValue: #:type _double* lo)
  48. (tellv cocoa setMaxValue: #:type _double* hi)
  49. (tellv cocoa setDoubleValue: #:type _double* (flip val))
  50. ;; heuristic: show up to tick marks:
  51. (when ((- hi lo) . < . 64)
  52. (tellv cocoa setNumberOfTickMarks: #:type _NSUInteger (add1 (- hi lo)))
  53. (tellv cocoa setAllowsTickMarkValuesOnly: #:type _BOOL #t))
  54. (tellv cocoa setFrame: #:type _NSRect (make-NSRect
  55. (make-NSPoint 0 0)
  56. (make-NSSize (if vert? 24 32)
  57. (if vert? 64 24))))
  58. (tellv cocoa setContinuous: #:type _BOOL #t)
  59. ;; (tellv cocoa sizeToFit)
  60. cocoa))
  61. (define-values (message-cocoa message-w message-h)
  62. (if (memq 'plain style)
  63. (values #f #f #f)
  64. (let ([cocoa (as-objc-allocation
  65. (tell (tell NSTextField alloc) init))])
  66. (init-font cocoa font)
  67. (tellv cocoa setSelectable: #:type _BOOL #f)
  68. (tellv cocoa setEditable: #:type _BOOL #f)
  69. (tellv cocoa setBordered: #:type _BOOL #f)
  70. (tellv cocoa setDrawsBackground: #:type _BOOL #f)
  71. (tellv cocoa setTitleWithMnemonic: #:type _NSString (format "~a" hi))
  72. (tellv cocoa sizeToFit)
  73. (let ([r1 (tell #:type _NSRect cocoa frame)])
  74. (tellv cocoa setTitleWithMnemonic: #:type _NSString (format "~a" lo))
  75. (tellv cocoa sizeToFit)
  76. (let ([r2 (tell #:type _NSRect cocoa frame)])
  77. (tellv cocoa setTitleWithMnemonic: #:type _NSString (format "~a" val))
  78. (values cocoa
  79. (max (NSSize-width (NSRect-size r1))
  80. (NSSize-width (NSRect-size r2)))
  81. (max (NSSize-height (NSRect-size r1))
  82. (NSSize-height (NSRect-size r2)))))))))
  83. (define cocoa
  84. (if message-cocoa
  85. (let* ([f (tell #:type _NSRect slider-cocoa frame)]
  86. [w (+ (if vert?
  87. message-w
  88. 0)
  89. (NSSize-width (NSRect-size f)))]
  90. [h (+ (if vert?
  91. 0
  92. message-h)
  93. (NSSize-height (NSRect-size f)))])
  94. (let ([cocoa (as-objc-allocation
  95. (tell (tell NSView alloc)
  96. initWithFrame: #:type _NSRect (make-NSRect
  97. (make-init-point x y)
  98. (make-NSSize w h))))])
  99. (tellv cocoa addSubview: slider-cocoa)
  100. (tellv cocoa addSubview: message-cocoa)
  101. (arrange-parts w h)
  102. cocoa))
  103. slider-cocoa))
  104. (define/private (arrange-parts w h)
  105. (tellv slider-cocoa setFrame: #:type _NSRect (make-NSRect
  106. (make-NSPoint 0
  107. (if vert? 0 message-h))
  108. (make-NSSize (- w (if vert? message-w 0))
  109. (- h (if vert? 0 message-h)))))
  110. (tellv message-cocoa setFrame: #:type _NSRect (make-NSRect
  111. (make-NSPoint (if vert?
  112. (- w message-w)
  113. (/ (- w message-w) 2))
  114. (if vert?
  115. (/ (- h message-h) 2)
  116. 0))
  117. (make-NSSize message-w message-h))))
  118. (define/override (set-size x y w h)
  119. (super set-size x y w h)
  120. (when message-cocoa
  121. (arrange-parts w h)))
  122. (when message-cocoa
  123. (set-ivar! slider-cocoa wxb (->wxb this)))
  124. (super-new [parent parent]
  125. [cocoa cocoa]
  126. [callback cb]
  127. [no-show? (memq 'deleted style)])
  128. (define/override (get-cocoa-control) slider-cocoa)
  129. (tellv slider-cocoa setTarget: slider-cocoa)
  130. (tellv slider-cocoa setAction: #:type _SEL (selector changed:))
  131. (define callback cb)
  132. (define/public (changed)
  133. (callback this (new control-event%
  134. [event-type 'slider]
  135. [time-stamp (current-milliseconds)])))
  136. (define/private (flip v)
  137. (if vert?
  138. (+ slider-lo (- slider-hi v))
  139. v))
  140. (define/public (set-value v)
  141. (atomically
  142. (tellv slider-cocoa setDoubleValue: #:type _double* (flip v))
  143. (update-message v)))
  144. (define/public (get-value)
  145. (flip (inexact->exact (floor (tell #:type _double slider-cocoa doubleValue)))))
  146. (define/public (update-message [val (get-value)])
  147. (tellv message-cocoa setTitleWithMnemonic: #:type _NSString (format "~a" val)))
  148. (inherit get-cocoa-window)
  149. (define/override (post-mouse-down)
  150. ;; For some reason, dragging a slider disabled mouse-moved
  151. ;; events for the window, so turn them back on:
  152. (tellv (get-cocoa-window) setAcceptsMouseMovedEvents: #:type _BOOL #t))
  153. (define/override (maybe-register-as-child parent on?)
  154. (register-as-child parent on?)))