/collects/mred/private/mrcontainer.rkt

https://bitbucket.org/agocke/racket · Racket · 192 lines · 175 code · 12 blank · 5 comment · 32 complexity · a7cf06d72aabc33e3934bb457221dc2a MD5 · raw file

  1. #lang racket/base
  2. (require racket/class
  3. racket/list
  4. (prefix-in wx: "kernel.rkt")
  5. "lock.rkt"
  6. "helper.rkt"
  7. "const.rkt"
  8. "wx.rkt"
  9. "check.rkt"
  10. "wxcontainer.rkt"
  11. "mrwindow.rkt")
  12. (provide area-container<%>
  13. (protect-out internal-container<%>
  14. check-container-parent
  15. make-container%
  16. make-subwindow%)
  17. area-container-window<%>
  18. (protect-out make-area-container-window%))
  19. (define area-container<%>
  20. (interface (area<%>)
  21. reflow-container container-flow-modified begin-container-sequence end-container-sequence
  22. container-size
  23. get-children change-children place-children
  24. after-new-child
  25. add-child delete-child
  26. border spacing
  27. set-alignment get-alignment))
  28. (define internal-container<%> (interface ()))
  29. (define (check-container-parent who p)
  30. (unless (is-a? p internal-container<%>)
  31. (raise-type-error (who->name who) "built-in container<%> object" p)))
  32. (define-local-member-name
  33. has-wx-child?
  34. adopt-wx-child)
  35. (define (make-container% %) ; % implements area<%>
  36. (class* % (area-container<%> internal-container<%>)
  37. (init mk-wx get-wx-pan get-wx-outer-pan mismatches parent
  38. ;; for keyword use
  39. [border no-val]
  40. [spacing no-val]
  41. [alignment no-val])
  42. (let ([cwho '(iconstructor area-container)])
  43. (unless (eq? border no-val) (check-margin-integer cwho border))
  44. (unless (eq? spacing no-val) (check-margin-integer cwho spacing))
  45. (unless (eq? alignment no-val)
  46. (unless (and (list? alignment)
  47. (= 2 (length alignment))
  48. (memq (car alignment) '(left center right))
  49. (memq (cadr alignment) '(top center bottom)))
  50. (raise-type-error (who->name cwho) "alignment list" alignment))))
  51. (define get-wx-panel get-wx-pan)
  52. (define bdr (param get-wx-panel border))
  53. (define spc (param get-wx-panel spacing))
  54. (public [bdr border] [spc spacing])
  55. (public*
  56. [after-new-child (lambda (c)
  57. (check-instance '(method area-container<%> after-new-child) subarea<%> 'subarea<%> #f c)
  58. (void))]
  59. [reflow-container (entry-point (lambda () (send (send (get-wx-panel) get-top-level) force-redraw)))]
  60. [container-flow-modified (entry-point (lambda ()
  61. (let ([p (get-wx-panel)])
  62. (send p need-move-children)
  63. (send p force-redraw))))]
  64. [begin-container-sequence (entry-point (lambda () (send (send (get-wx-panel) get-top-level) begin-container-sequence)))]
  65. [end-container-sequence (entry-point (lambda () (send (send (get-wx-panel) get-top-level) end-container-sequence)))]
  66. [get-children (entry-point (lambda () (map wx->proxy
  67. (let ([l (send (get-wx-panel) get-children)]
  68. [h (send (get-wx-panel) get-hidden-child)])
  69. (if h (remq h l) l)))))]
  70. [set-alignment (entry-point (lambda (h v) (send (get-wx-panel) alignment h v)))]
  71. [get-alignment (entry-point (lambda () (send (get-wx-panel) get-alignment)))]
  72. [change-children (entry-point
  73. (lambda (f)
  74. (unless (and (procedure? f)
  75. (procedure-arity-includes? f 1))
  76. (raise-type-error (who->name '(method container<%> change-children))
  77. "procedure of arity 1"
  78. f))
  79. (send (get-wx-panel) change-children
  80. (lambda (kids)
  81. (let* ([hidden (send (get-wx-panel) get-hidden-child)]
  82. [mred-kids (map wx->proxy (remq hidden kids))]
  83. [l (as-exit (lambda () (f mred-kids)))])
  84. (unless (and (list? l)
  85. (andmap (lambda (x) (is-a? x internal-subarea<%>)) l))
  86. (raise-mismatch-error 'change-children
  87. "result of given procedure was not a list of subareas: "
  88. l))
  89. (append
  90. (if hidden (list hidden) null)
  91. (map mred->wx l)))))))]
  92. [container-size (entry-point
  93. (lambda (l)
  94. ; Check l, even though we don't use it
  95. (unless (and (list? l)
  96. (andmap
  97. (lambda (l)
  98. (and (list? l) (= (length l) 4)
  99. (integer? (car l)) (exact? (car l)) (<= 0 (car l) 10000)
  100. (integer? (cadr l)) (exact? (cadr l)) (<= 0 (cadr l) 10000)))
  101. l))
  102. (raise-type-error (who->name '(method area-container<%> container-size))
  103. "list of lists containing two exact integers in [0, 10000] and two booleans"
  104. l))
  105. (let ([l (send (get-wx-panel) do-get-graphical-min-size)])
  106. (apply values l))))]
  107. [place-children (entry-point (lambda (l w h) (send (get-wx-panel) do-place-children l w h)))]
  108. [add-child (entry-point
  109. (lambda (c)
  110. (check-instance '(method area-container<%> add-child) subwindow<%> 'subwindow<%> #f c)
  111. (send (get-wx-panel) add-child (mred->wx c))))]
  112. [delete-child (entry-point
  113. (lambda (c)
  114. (check-instance '(method area-container<%> delete-child) subwindow<%> 'subwindow<%> #f c)
  115. (send (get-wx-panel) delete-child (mred->wx c))))]
  116. [has-wx-child? (lambda (child-wx) ; called in atomic mode
  117. (memq child-wx (send (get-wx-panel) get-children)))]
  118. [adopt-wx-child (lambda (child-wx) ; called in atomic mode
  119. (let ([wxp (get-wx-panel)])
  120. (send child-wx set-area-parent wxp)
  121. (send wxp adopt-child child-wx)))])
  122. (super-make-object mk-wx get-wx-panel get-wx-outer-pan mismatches parent)
  123. (unless (eq? border no-val) (bdr border))
  124. (unless (eq? spacing no-val) (spc spacing))
  125. (unless (eq? alignment no-val) (set-alignment . alignment))))
  126. (define area-container-window<%>
  127. (interface (window<%> area-container<%>)))
  128. (define (make-area-container-window% %) ; % implements window<%> (and area-container<%>)
  129. (class* % (area-container-window<%>)
  130. (init mk-wx get-wx-pan get-wx-outer-pan mismatches label parent cursor)
  131. (super-make-object mk-wx get-wx-pan get-wx-outer-pan mismatches label parent cursor)))
  132. (define (make-subwindow% %)
  133. (class %
  134. (super-new)
  135. (inherit set-parent
  136. get-parent
  137. is-shown?
  138. show)
  139. (define/public (reparent new-parent)
  140. (check-container-parent '(subwindow<%> reparent) new-parent)
  141. (unless (as-entry
  142. (lambda ()
  143. (let ([p1 (send (mred->wx this) get-top-level)]
  144. [p2 (send (mred->wx new-parent) get-top-level)])
  145. (eq? (send p1 get-eventspace) (send p1 get-eventspace)))))
  146. (raise-mismatch-error
  147. (who->name '(subwindow<%> reparent))
  148. "current parent's eventspace is not the same as the eventspace of the new parent: "
  149. new-parent))
  150. (let loop ([p new-parent])
  151. (when p
  152. (when (eq? p this)
  153. (raise-mismatch-error
  154. (who->name '(subwindow<%> reparent))
  155. (if (eq? new-parent this)
  156. "cannot set parent to self: "
  157. "cannot set parent to a descedant: ")
  158. new-parent))
  159. (loop (send p get-parent))))
  160. (let* ([added? (memq this (send (get-parent) get-children))]
  161. [shown? (and added? (is-shown?))])
  162. (when added?
  163. (send (get-parent) delete-child this))
  164. (as-entry
  165. (lambda ()
  166. (let ([wx (mred->wx this)])
  167. ;; double-check that delete succeeded:
  168. (unless (send (get-parent) has-wx-child? wx)
  169. ;; double-check that we're not creating a loop at the wx level:
  170. (unless (let loop ([p (mred->wx new-parent)])
  171. (and p
  172. (or (eq? p wx)
  173. (loop (send p get-parent)))))
  174. ;; Ok --- really reparent:
  175. (send new-parent adopt-wx-child wx)
  176. (set-parent new-parent))))))
  177. (when added?
  178. (send new-parent add-child this))
  179. (when shown?
  180. (show #t))))))