PageRenderTime 48ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/src/buttons.sc

https://bitbucket.org/bunny351/ezd
Scala | 409 lines | 374 code | 35 blank | 0 comment | 5 complexity | 3141cb120245b19ea74bc9f4d1083171 MD5 | raw file
  1. ;;; ezd - easy drawing for X11 displays.
  2. ;;;
  3. ;;; The procedures in this module provide some basic interactive elements
  4. ;;; to provide event logging, keyboard input, clicks on objects, and popup
  5. ;;; menus.
  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 buttons)
  44. (include "commands.sch")
  45. (include "ginfo.sch")
  46. (include "interact.sch")
  47. (include "events.sch")
  48. (include "match.sch")
  49. (include "ezd.sch")
  50. ;;; The CHECK-BUTTON command makes a check button in the current drawing. The
  51. ;;; button is a circle drawn in the foreground color (default is black) that
  52. ;;; is filled with the background color (default is white) when the value is
  53. ;;; false, or the foreground color when the value is true. The button text is
  54. ;;; written to the right of the button in the foreground color and the
  55. ;;; indicated font (default is the default X font).
  56. ;;;
  57. ;;; The button's value is complemented by clicking the mouse within either the
  58. ;;; circle or the button text. The button action is taken when the button
  59. ;;; comes up.
  60. ;;;
  61. ;;; If the button is a member of a radio button set, then clicking on it when
  62. ;;; it is set will have no effect. Clicking an unset button will set it and
  63. ;;; clear the set value.
  64. ;;;
  65. ;;; Button information can be accessed via the following attributes.
  66. ;;;
  67. ;;; X
  68. ;;; Y
  69. ;;; WIDTH
  70. ;;; HEIGHT
  71. ;;; ACTION
  72. ;;; TEXT
  73. ;;; FONT
  74. ;;; FOREGROUND
  75. ;;; BACKGROUND
  76. ;;; VALUE
  77. ;;; RADIO-BUTTON-SET
  78. ;;;
  79. ;;; ATTRIBUTES
  80. ;;; DELETE-OBJECT
  81. (define (MAKE-CHECK-BUTTON button-name x y width height text value action
  82. opt-foreground opt-background font)
  83. (define FOREGROUND (or opt-foreground 'black))
  84. (define BACKGROUND (or opt-background 'white))
  85. (define DY 2)
  86. (define RADIO-BUTTON-SET '())
  87. (define DRAWING-NAME (current-drawing-name))
  88. (define READY #f)
  89. (define (EXIT)
  90. (when ready
  91. (set! value (not value))
  92. (set! ready #f)
  93. (draw-button)))
  94. (define (BUTTON-DOWN)
  95. (unless (and value (pair? radio-button-set))
  96. (set! ready #t)
  97. (set! value (not value))
  98. (draw-button)))
  99. (define (BUTTON-UP)
  100. (if ready
  101. (let ((drawing *user-event-drawing*))
  102. (set! ready #f)
  103. (set! *user-event-misc* (list value))
  104. (ezd '(draw-now))
  105. (if (procedure? action) (action) (eval action))
  106. (for-each
  107. (lambda (button)
  108. (if (not (eq? button button-name))
  109. (set-attributes drawing button
  110. '(value #f))))
  111. radio-button-set))
  112. (draw-button)))
  113. (define (DRAW-BUTTON)
  114. (ezd '(save-drawing)
  115. `(set-drawing ,drawing-name)
  116. `(object ,button-name
  117. (fill-arc ,x ,y ,(- height dy dy)
  118. ,(- height dy dy) 0 360
  119. ,(if value foreground background))
  120. (arc ,x ,y ,(- height dy dy)
  121. ,(- height dy dy) 0 360 ,foreground)
  122. (text ,(+ x height dy dy) ,y ,width ,height left
  123. center ,text ,foreground
  124. ,@(if font (list font) '())))
  125. '(restore-drawing)))
  126. (define (GETATTRIBUTES)
  127. (map (lambda (a)
  128. (case a
  129. ((X) x)
  130. ((Y) y)
  131. ((WIDTH) width)
  132. ((HEIGHT) height)
  133. ((TEXT) text)
  134. ((ACTION) action)
  135. ((FONT) font)
  136. ((FOREGROUND) foreground)
  137. ((BACKGROUND) background)
  138. ((VALUE) value)
  139. ((RADIO-BUTTON-SET) radio-button-set)
  140. ((ATTRIBUTES) '(x y width height text action
  141. font foreground background
  142. value radio-button-set
  143. attributes delete-object))
  144. (else (ezd-error 'check-button
  145. "Illegal attribute: ~s" a))))
  146. *user-event-misc*))
  147. (define (OBJECT-LIST? x)
  148. (or (null? x) (and (symbol? (car x)) (object-list? (cdr x)))))
  149. (define (SETATTRIBUTES)
  150. (let ((delete #f)
  151. (redraw #f)
  152. (drawing *user-event-drawing*))
  153. (define (SET-RADIO-BUTTON-SET new-buttons)
  154. (for-each
  155. (lambda (button)
  156. (if (and (not (memq button new-buttons))
  157. (not (eq? button button-name)))
  158. (set-attributes drawing button
  159. '(RADIO-BUTTON-SET-VALUE))))
  160. radio-button-set)
  161. (for-each
  162. (lambda (button)
  163. (if (not (eq? button button-name))
  164. (set-attributes drawing button
  165. `(RADIO-BUTTON-SET-VALUE
  166. ,@new-buttons))))
  167. new-buttons)
  168. (set! radio-button-set new-buttons))
  169. (for-each
  170. (lambda (a)
  171. (cond ((match? (X number?) a)
  172. (set! redraw #t)
  173. (set! x (cadr a)))
  174. ((match? (Y number?) a)
  175. (set! redraw #t)
  176. (set! y (cadr a)))
  177. ((match? (WIDTH positive-number?) a)
  178. (set! redraw #t)
  179. (set! width (cadr a)))
  180. ((match? (HEIGHT positive-number?) a)
  181. (set! redraw #t)
  182. (set! height (cadr a)))
  183. ((match? (TEXT string?) a)
  184. (set! redraw #t)
  185. (set! text (cadr a)))
  186. ((match? (ACTION any?) a)
  187. (set! action (cadr a)))
  188. ((match? (FONT string?) a)
  189. (set! redraw #t)
  190. (set! font (cadr a)))
  191. ((match? (FOREGROUND color?) a)
  192. (set! redraw #t)
  193. (set! foreground (cadr a)))
  194. ((match? (BACKGROUND color?) a)
  195. (set! redraw #t)
  196. (set! background (cadr a)))
  197. ((match? (VALUE boolean?) a)
  198. (if (not (equal? value (cadr a)))
  199. (set! redraw #t))
  200. (set! value (cadr a)))
  201. ((and (eq? (car a) 'RADIO-BUTTON-SET)
  202. (object-list? (cdr a)))
  203. (set-radio-button-set (cdr a)))
  204. ((and (eq? (car a) 'RADIO-BUTTON-SET-VALUE))
  205. (set! radio-button-set (cdr a)))
  206. ((equal? '(DELETE-OBJECT) a)
  207. (set! delete #t))
  208. (else (ezd-error 'check-button
  209. "Illegal attribute: ~s" a))))
  210. *user-event-misc*)
  211. (if delete
  212. (begin (set-radio-button-set
  213. (remq button-name radio-button-set))
  214. (ezd `(object ,button-name)
  215. `(when ,button-name * #f)))
  216. (if redraw (draw-button)))))
  217. (draw-button)
  218. (ezd `(when ,button-name get-attributes ,getattributes)
  219. `(when ,button-name set-attributes ,setattributes)
  220. `(when ,button-name exit ,exit)
  221. `(when ,button-name button1down ,button-down)
  222. `(when ,button-name button1up ,button-up)))
  223. (define-ezd-command
  224. `(check-button ,symbol? ,number? ,number? ,positive-number?
  225. ,positive-number? ,string? ,boolean?
  226. ,any? (optional ,color?) (optional ,color?) (optional ,string?))
  227. "(check-button name x y width height text value action [foreground [background]] [\"font\"])"
  228. make-check-button)
  229. ;;; The PUSH-BUTTON command makes a simple button in the current drawing. The
  230. ;;; button is drawn as a filled rectangle in the background color (default is
  231. ;;; white) with a foreground colored (default is black) border. The button
  232. ;;; text is written in the center of the button in the foreground color and
  233. ;;; font (default is X's). If several button text's are provided, then each
  234. ;;; time the button action is taken, the "next" button text is displayed.
  235. ;;;
  236. ;;; When the mouse enters a button with an action not equal to #f, the
  237. ;;; rectangle border is thickened. When mouse button 1 is pressed, the button
  238. ;;; colors are reversed. When button 1 is released, the button action is taken
  239. ;;; and then the button is drawn normally. When the button action is taken,
  240. ;;; the button event type is BUTTON1UP and the miscellaneous information is a
  241. ;;; list containing the button text when the button was pressed and the button
  242. ;;; text that will next be displayed. Note that in order for the button
  243. ;;; action to be taken, the mouse must remain within the button while the
  244. ;;; mouse button is pressed.
  245. ;;;
  246. ;;; Button information can be accessed via the following attributes.
  247. ;;;
  248. ;;; X
  249. ;;; Y
  250. ;;; WIDTH
  251. ;;; HEIGHT
  252. ;;; ACTION
  253. ;;; TEXT
  254. ;;; FONT
  255. ;;; FOREGROUND
  256. ;;; BACKGROUND
  257. ;;;
  258. ;;; ATTRIBUTES
  259. ;;; DELETE-OBJECT
  260. (define (MAKE-PUSH-BUTTON button-name x y width height text-list action
  261. opt-foreground opt-background font)
  262. (define FOREGROUND (or opt-foreground 'black))
  263. (define BACKGROUND (or opt-background 'white))
  264. (define DRAWING-NAME (current-drawing-name))
  265. (define BOLD #f)
  266. (define INVERT #f)
  267. (define (ENTER) (if (not *mouse-button1*) (draw-button #t #f)))
  268. (define (EXIT) (draw-button #f #f))
  269. (define (BUTTON-DOWN) (draw-button #t #t))
  270. (define (BUTTON-UP)
  271. (when invert
  272. (set! *user-event-misc*
  273. (list (car text-list)
  274. (if (pair? (cdr text-list))
  275. (cadr text-list)
  276. (car text-list))))
  277. (ezd '(draw-now))
  278. (if (procedure? action) (action) (eval action))
  279. (set! text-list
  280. (append (cdr text-list) (list (car text-list)))))
  281. (draw-button #t #f))
  282. (define (DRAW-BUTTON b i)
  283. (set! bold b)
  284. (set! invert i)
  285. (ezd '(save-drawing)
  286. `(set-drawing ,drawing-name)
  287. `(object ,button-name
  288. (fill-rectangle ,x ,y ,width ,height
  289. ,(if invert foreground background))
  290. (rectangle ,x ,y ,width ,height ,(if bold 3 0)
  291. ,foreground)
  292. (text ,x ,y ,width ,height center center
  293. ,(car text-list)
  294. ,(if invert background foreground)
  295. ,@(if font (list font) '())))
  296. '(restore-drawing)))
  297. (define (STRING-LIST? x)
  298. (if (null? x)
  299. #f
  300. (let loop ((x x))
  301. (if (pair? x)
  302. (loop (cdr x))
  303. (null? x)))))
  304. (define (GET-ATTRIBUTES)
  305. (map (lambda (a)
  306. (case a
  307. ((X) x)
  308. ((Y) y)
  309. ((WIDTH) width)
  310. ((HEIGHT) height)
  311. ((TEXT) text-list)
  312. ((ACTION) action)
  313. ((FONT) font)
  314. ((FOREGROUND) foreground)
  315. ((BACKGROUND) background)
  316. ((ATTRIBUTES) '(x y width height text action
  317. font foreground background
  318. attributes delete-object))
  319. (else (ezd-error 'push-button
  320. "Illegal attribute: ~s" a))))
  321. *user-event-misc*))
  322. (define (SET-ATTRIBUTES)
  323. (define (TEXT-LIST? x)
  324. (or (null? x)
  325. (and (string? (car x)) (text-list? (cdr x)))))
  326. (define DELETE #f)
  327. (for-each
  328. (lambda (a)
  329. (cond ((match? (X number?) a)
  330. (set! x (cadr a)))
  331. ((match? (Y number?) a)
  332. (set! y (cadr a)))
  333. ((match? (WIDTH positive-number?) a)
  334. (set! width (cadr a)))
  335. ((match? (HEIGHT positive-number?) a)
  336. (set! height (cadr a)))
  337. ((and (eq? (car a) 'TEXT) (text-list? (cdr a))
  338. (> (length a) 1))
  339. (set! text-list (cdr a)))
  340. ((match? (ACTION any?) a)
  341. (set! action (cadr a)))
  342. ((match? (FONT string?) a)
  343. (set! font (cadr a)))
  344. ((match? (FOREGROUND color?) a)
  345. (set! foreground (cadr a)))
  346. ((match? (BACKGROUND color?) a)
  347. (set! background (cadr a)))
  348. ((equal? '(DELETE-OBJECT) a)
  349. (set! delete #t))
  350. (else (ezd-error 'push-button
  351. "Illegal attribute: ~s" a))))
  352. *user-event-misc*)
  353. (if delete
  354. (ezd `(object ,button-name) `(when ,button-name * #f))
  355. (make-push-button button-name x y width height text-list action
  356. foreground background font)))
  357. (draw-button #f #f)
  358. (ezd `(when ,button-name get-attributes ,get-attributes)
  359. `(when ,button-name set-attributes ,set-attributes))
  360. (if action
  361. (ezd `(when ,button-name enter ,enter)
  362. `(when ,button-name exit ,exit)
  363. `(when ,button-name button1down ,button-down)
  364. `(when ,button-name button1up ,button-up))
  365. (ezd `(when ,button-name enter #f)
  366. `(when ,button-name exit #f)
  367. `(when ,button-name button1down #f)
  368. `(when ,button-name button1up #f))))
  369. (define-ezd-command
  370. `(push-button ,symbol? ,number? ,number? ,positive-number?
  371. ,positive-number? (repeat ,string?) ,any? (optional, color?)
  372. (optional ,color?) (optional ,string?))
  373. "(push-button name x y width height text ... action [foreground [background]] [\"font\"])"
  374. make-push-button)