PageRenderTime 55ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/src/drawing.sc

https://bitbucket.org/bunny351/ezd
Scala | 369 lines | 323 code | 46 blank | 0 comment | 6 complexity | f29691c7d84e6c7e2c99635fe1e7a11b MD5 | raw file
  1. ;;; ezd - easy drawing for X11.
  2. ;;;
  3. ;;; A DRAWING contains a set of graphical objects. These objects are displayed
  4. ;;; by drawing them with a view into a window. The view into a window also
  5. ;;; allows events to be mapped back into the drawing.
  6. ;* Copyright 1990-1993 Digital Equipment Corporation
  7. ;* All Rights Reserved
  8. ;*
  9. ;* Permission to use, copy, and modify this software and its documentation is
  10. ;* hereby granted only under the following terms and conditions. Both the
  11. ;* above copyright notice and this permission notice must appear in all copies
  12. ;* of the software, derivative works or modified versions, and any portions
  13. ;* thereof, and both notices must appear in supporting documentation.
  14. ;*
  15. ;* Users of this software agree to the terms and conditions set forth herein,
  16. ;* and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
  17. ;* right and license under any changes, enhancements or extensions made to the
  18. ;* core functions of the software, including but not limited to those affording
  19. ;* compatibility with other hardware or software environments, but excluding
  20. ;* applications which incorporate this software. Users further agree to use
  21. ;* their best efforts to return to Digital any such changes, enhancements or
  22. ;* extensions that they make and inform Digital of noteworthy uses of this
  23. ;* software. Correspondence should be provided to Digital at:
  24. ;*
  25. ;* Director of Licensing
  26. ;* Western Research Laboratory
  27. ;* Digital Equipment Corporation
  28. ;* 250 University Avenue
  29. ;* Palo Alto, California 94301
  30. ;*
  31. ;* This software may be distributed (but not offered for sale or transferred
  32. ;* for compensation) to third parties, provided such third parties agree to
  33. ;* abide by the terms and conditions of this notice.
  34. ;*
  35. ;* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  36. ;* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  37. ;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  38. ;* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  39. ;* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  40. ;* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  41. ;* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  42. ;* SOFTWARE.
  43. (module drawing)
  44. (include "struct.sch")
  45. (include "display.sch")
  46. (include "window.sch")
  47. (include "view.sch")
  48. (include "graphic.sch")
  49. (include "events.sch")
  50. (include "commands.sch")
  51. (include "xternal.sch")
  52. ;;; A DRAWING is a structured object consisting of the following fields:
  53. ;;;
  54. ;;; NAME symbolic name of the drawing.
  55. ;;; HEAD head of the list of objects in the drawing. Since this
  56. ;;; list is in drawing order, the objects at the "bottom"
  57. ;;; of the drawing are at the head of the list.
  58. ;;; TAIL tail of the list of objects in the drawing.
  59. ;;; ADDED-HEAD head of the list of recent additions to the drawing.
  60. ;;; ADDED-TAIL tail of the list of recent additions to the drawing.
  61. ;;; ZMOTION objects have been rearranged in the drawing.
  62. ;;; DAMAGED head of the list of functions computing bounding boxes
  63. ;;; describing objects damaged in the drawing.
  64. ;;; CLEARED boolean indicating that the drawing has been cleared.
  65. ;;; IS-CLEAR boolean indicating that nothing but clear objects have
  66. ;;; been drawn in the drawing.
  67. ;;; WINDOW-WATCH list of object names that may have an object specific
  68. ;;; event handler for RESIZE, EXPOSE, OVERLAY, or VISIBLE
  69. ;;; events.
  70. ;;; EVENTS list of events that are for the object "*".
  71. (define-structure DRAWING
  72. name
  73. (head '())
  74. (tail '())
  75. (added-head '())
  76. (added-tail '())
  77. (zmotion #f)
  78. (damaged '())
  79. (cleared #f)
  80. (is-clear #t)
  81. (window-watch '())
  82. (events (let* ((name (drawing-name self))
  83. (x (assoc name *drawings*)))
  84. (if x (set! *drawings* (remove x *drawings*)))
  85. (set! *drawings* (cons (list name self) *drawings*))
  86. '())))
  87. (define-in-line-structure-access DRAWING
  88. name
  89. head
  90. tail
  91. added-head
  92. added-tail
  93. zmotion
  94. damaged
  95. cleared
  96. is-clear
  97. window-watch
  98. events)
  99. ;;; A list of lists associating the name of each drawing with the data
  100. ;;; structure is maintained in the global *DRAWINGS*.
  101. (define *DRAWINGS* '())
  102. ;;; A drawing name can be converted to the appropriate data structure by the
  103. ;;; function NAME->DRAWING.
  104. (define (NAME->DRAWING name)
  105. (let ((x (assoc name *drawings*)))
  106. (if x (cadr x) (error 'name->drawing "undefined DRAWING: ~s" name))))
  107. ;;; Boolean to test if a drawing already exists.
  108. (define (DRAWING-EXISTS? name)
  109. (if (assoc name *drawings*) #t #f))
  110. ;;; The name of an object in the current drawing is coverted to the graphic
  111. ;;; structure representing it by the following function. It is an error to
  112. ;;; look up a non-existent object.
  113. (define (NAME->GRAPHIC name)
  114. (let ((g (getprop name (drawing-name *current-drawing*))))
  115. (if g g (error 'NAME->GRAPHIC "OBJECT does not exist: ~s" name))))
  116. ;;; An object is verified to be the name of a graphic object by the following
  117. ;;; procedure.
  118. (define (NAME-OF-GRAPHIC? name)
  119. (and *current-drawing*
  120. (symbol? name)
  121. (getprop name (drawing-name *current-drawing*))))
  122. ;;; Most drawing commands have an implied argument, the current drawing. The
  123. ;;; global *CURRENT-DRAWING* represents it.
  124. (define *CURRENT-DRAWING* #f)
  125. ;;; The ezd command SET-DRAWING is used to set the current drawing. If a
  126. ;;; drawing by that name does not exist, then one is created.
  127. (define (SET-DRAWING name)
  128. (let ((drawing (if (drawing-exists? name)
  129. (name->drawing name)
  130. (make-drawing name))))
  131. (set! *current-drawing* drawing)))
  132. (define-ezd-command
  133. `(set-drawing ,symbol?)
  134. "(set-drawing drawing-name)"
  135. set-drawing)
  136. ;;; The ezd commands SAVE-DRAWING and RESTORE-DRAWING push and pop the current
  137. ;;; drawing on a stack.
  138. (define *SAVED-DRAWINGS* '())
  139. (define-ezd-command
  140. `(save-drawing)
  141. "(save-drawing)"
  142. (lambda ()
  143. (if *current-drawing*
  144. (set! *saved-drawings*
  145. (cons *current-drawing* *saved-drawings*)))))
  146. (define-ezd-command
  147. `(restore-drawing)
  148. "(restore-drawing)"
  149. (lambda ()
  150. (unless (null? *saved-drawings*)
  151. (set! *current-drawing* (car *saved-drawings*))
  152. (set! *saved-drawings* (cdr *saved-drawings*)))))
  153. ;;; A drawing is cleared by the following procedure.
  154. (define (DRAWING-CLEAR drawing)
  155. (let ((dname (drawing-name drawing)))
  156. (for-each
  157. (lambda (g)
  158. (let ((object-name (graphic-name g)))
  159. (if object-name
  160. (putprop object-name dname #f))))
  161. (drawing-head drawing))
  162. (drawing-head! drawing '())
  163. (drawing-tail! drawing '())
  164. (drawing-added-head! drawing '())
  165. (drawing-added-tail! drawing '())
  166. (drawing-zmotion! drawing #f)
  167. (drawing-damaged! drawing '())
  168. (drawing-cleared! drawing #t)
  169. (drawing-is-clear! drawing #t)
  170. (drawing-window-watch! drawing '())
  171. (drawing-events! drawing '())
  172. (set! *update-display* #t)))
  173. ;;; The currently selected drawing is cleared by the ezd command CLEAR.
  174. (define-ezd-command
  175. '(CLEAR)
  176. "(clear)"
  177. (lambda () (if *current-drawing* (drawing-clear *current-drawing*))))
  178. ;;; Graphic objects are moved to either the top or the bottom of the current
  179. ;;; drawing or relative to another object by the following procedure and
  180. ;;; commands.
  181. (define (FLOAT/SINK-OBJECT drawing obj-name ref-name float)
  182. (let ((object (name->graphic obj-name))
  183. (reference (and ref-name (name->graphic ref-name)))
  184. (prev-reference (not ref-name))
  185. (object-deleted #f))
  186. ;;; Delete object and correct pointers, find reference object.
  187. (let loop ((prev #t) (gl (drawing-head drawing)))
  188. (if (pair? gl)
  189. (let ((g (car gl)))
  190. (cond ((and (eq? g object)
  191. (not (eq? (drawing-head drawing)
  192. (drawing-tail drawing))))
  193. (let ((oh (drawing-head drawing))
  194. (ot (drawing-tail drawing))
  195. (oah (drawing-added-head drawing))
  196. (oat (drawing-added-tail drawing)))
  197. (if (eq? oh gl)
  198. (drawing-head! drawing (cdr gl)))
  199. (if (eq? ot gl)
  200. (if (eq? ot oh)
  201. (drawing-tail! drawing '())
  202. (drawing-tail! drawing prev)))
  203. (if (eq? oah gl)
  204. (drawing-added-head! drawing (cdr gl)))
  205. (if (eq? oat gl)
  206. (if (eq? oat oah)
  207. (drawing-added-tail! drawing '())
  208. (drawing-added-tail! drawing prev)))
  209. (if (pair? prev) (set-cdr! prev (cdr gl)))
  210. (set! object-deleted #t)
  211. (if (not prev-reference)
  212. (loop prev (cdr gl)))))
  213. ((eq? g reference)
  214. (set! prev-reference prev)
  215. (if (not object-deleted) (loop gl (cdr gl))))
  216. (else (loop gl (cdr gl)))))))
  217. ;;; Insert object relative to reference object and correct pointers.
  218. (let ((oh (drawing-head drawing))
  219. (ot (drawing-tail drawing))
  220. (oah (drawing-added-head drawing))
  221. (oat (drawing-added-tail drawing))
  222. (lob (list object)))
  223. (if float
  224. (cond ((pair? prev-reference)
  225. (set-cdr! lob (cddr prev-reference))
  226. (set-cdr! (cdr prev-reference) lob))
  227. ((and (eq? prev-reference #t) ref-name)
  228. (set-cdr! lob (cdr oh))
  229. (set-cdr! oh lob))
  230. (else (set-cdr! ot lob)
  231. (drawing-tail! drawing lob)))
  232. (cond ((pair? prev-reference)
  233. (set-cdr! lob (cdr prev-reference))
  234. (set-cdr! prev-reference lob))
  235. (else (drawing-head! drawing (cons object oh)))))
  236. (if (eq? oh oah)
  237. (drawing-added-head! drawing (drawing-head drawing)))
  238. (if (eq? ot oat)
  239. (drawing-added-tail! drawing (drawing-tail drawing))))
  240. ;;; Mark area contained the moved object as damaged.
  241. (if *clean-mouse-window*
  242. (for-each (lambda (v)
  243. (if (eq? (view-drawing v) drawing)
  244. (set! *clean-mouse-window* #f)))
  245. (window-views *mouse-window*)))
  246. (drawing-damaged! drawing (cons (graphic-compute-bb object)
  247. (drawing-damaged drawing)))
  248. (drawing-zmotion! drawing #t)
  249. (set! *update-display* #t)))
  250. ;;; Command parsers and definition.
  251. (define NAME-OF-GRAPHIC1? #f)
  252. (define NAME-OF-GRAPHIC2?
  253. (let ((name-of-first #f))
  254. (set! name-of-graphic1?
  255. (lambda (x)
  256. (if (name-of-graphic? x)
  257. (begin (set! name-of-first x) #t)
  258. #f)))
  259. (lambda (x) (and (name-of-graphic? x) (not (eq? x name-of-first))))))
  260. (define-ezd-command
  261. `(FLOAT ,name-of-graphic1? (optional ,name-of-graphic2?))
  262. "(float object-name [object-name])"
  263. (lambda (o-name1 o-name2)
  264. (float/sink-object *current-drawing* o-name1 o-name2 #t)))
  265. (define-ezd-command
  266. `(SINK ,name-of-graphic1? (optional ,name-of-graphic2?))
  267. "(sink object-name [object-name])"
  268. (lambda (o-name1 o-name2)
  269. (float/sink-object *current-drawing* o-name1 o-name2 #f)))
  270. ;;; A graphic object is added to a drawing by the following procedure.
  271. (define (DRAWING-ADD drawing graphic)
  272. (let ((name (drawing-name drawing))
  273. (object-name (graphic-name graphic)))
  274. (define (ADD-TO-DRAWING)
  275. (let ((tail (drawing-tail drawing))
  276. (added-tail (drawing-added-tail drawing))
  277. (graphic-list (list graphic)))
  278. (if (null? tail)
  279. (drawing-head! drawing graphic-list)
  280. (set-cdr! tail graphic-list))
  281. (drawing-tail! drawing graphic-list)
  282. (if (null? added-tail)
  283. (drawing-added-head! drawing graphic-list)
  284. (set-cdr! added-tail graphic-list))
  285. (drawing-added-tail! drawing graphic-list)))
  286. (define (GRAPHIC-DAMAGED g)
  287. (drawing-damaged! drawing
  288. (cons (graphic-compute-bb g) (drawing-damaged drawing))))
  289. (if (and (drawing-is-clear drawing)
  290. (not (eq? (graphic-xdraw graphic) draw-clear)))
  291. (drawing-is-clear! drawing #f))
  292. (if *clean-mouse-window*
  293. (for-each (lambda (v)
  294. (if (eq? (view-drawing v) drawing)
  295. (set! *clean-mouse-window* #f)))
  296. (window-views *mouse-window*)))
  297. (if object-name
  298. (let ((old-graphic (getprop object-name name)))
  299. (if old-graphic
  300. ;;; Object is being replaced by a new one.
  301. (let ((old-events (graphic-events old-graphic)))
  302. (graphic-damaged old-graphic)
  303. (graphic-damaged graphic)
  304. (set-graphic! old-graphic graphic)
  305. (graphic-events! old-graphic old-events))
  306. (begin (putprop object-name name graphic)
  307. (add-to-drawing))))
  308. (add-to-drawing))
  309. (set! *update-display* #t)))
  310. ;;; Module reset/initialization.
  311. (define (DRAWING-MODULE-INIT)
  312. (for-each
  313. (lambda (name-drawing)
  314. (for-each
  315. (lambda (graphic)
  316. (let ((name (graphic-name graphic)))
  317. (if name
  318. (putprop name (car name-drawing) #f))))
  319. (drawing-head (cadr name-drawing))))
  320. *drawings*)
  321. (set! *drawings* '())
  322. (set! *saved-drawings* '())
  323. (set! *current-drawing* #f))