File: graph3.lsp

package info (click to toggle)
xlispstat 3.52.0-3
  • links: PTS
  • area: main
  • in suites: hamm, slink
  • size: 7,472 kB
  • ctags: 12,480
  • sloc: ansic: 89,534; lisp: 21,690; sh: 1,525; makefile: 520; csh: 1
file content (239 lines) | stat: -rw-r--r-- 8,783 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
(provide "graph3")
(require "graphics")

;;;
;;; Options dialog stuff
;;;

(defproto graph-toggle-item-proto '(graph message) () toggle-item-proto)

(defmeth graph-toggle-item-proto :isnew (title graph message)
  (setf (slot-value 'graph) graph)
  (setf (slot-value 'message) message)
  (call-next-method title :value (send graph message)))

(defmeth graph-toggle-item-proto :set-value ()
  (let* ((message (slot-value 'message))
         (graph (slot-value 'graph))
         (old (if (send graph message) t nil))
         (new (if (send self :value) t nil)))
    (unless (eq old new) (send graph message new))))

(defproto graph-backcolor-choice-item-proto '(graph) () choice-item-proto)

(defmeth graph-backcolor-choice-item-proto :isnew (graph)
  (setf (slot-value 'graph) graph)
  (call-next-method (list "White Background" "Black Background") 
                    :value (if (eq (send graph :back-color) 'white) 0 1)))

(defmeth graph-backcolor-choice-item-proto :set-value ()
  (let ((graph (slot-value 'graph)))
    (case (send self :value)
      (0 (send graph :back-color 'white)
         (send graph :draw-color 'black))
      (1 (send graph :back-color 'black)
         (send graph :draw-color 'white)))))

(defproto graph-scaling-choice-item-proto '(graph) () choice-item-proto)

(defmeth graph-scaling-choice-item-proto :isnew (graph)
  (setf (slot-value 'graph) graph)
  (call-next-method (list "Variable Scaling" "Fixed Scaling" "No Scaling")
                    :value (case (send graph :scale-type) 
                                 (variable 0)
                                 (fixed 1) 
                                 (t 2))))

(defmeth graph-scaling-choice-item-proto :set-value ()
  (let ((graph (slot-value 'graph)))
    (send graph :scale-type
          (case (send self :value)
                (0 'variable)
                (1 'fixed)
                (2 nil)))))

(defmeth graph-proto :set-options ()
"Method args: ()
Opens dialog to set plot options. Items are obtained using the
:make-options-dialog-items message."
  (let* ((items (send self :make-options-dialog-items))
         (d (send ok-or-cancel-dialog-proto :new items :title "Options"
                  :ok-action #'(lambda ()
                                 (dolist (i items) 
                                         (send i :set-value))
                                 (send self :redraw)))))
    (unwind-protect (send d :modal-dialog)
                    (send d :remove))))

(defmeth graph-proto :make-options-dialog-items ()
  (remove
   nil
   (list
    (send graph-backcolor-choice-item-proto :new self)
    (send graph-toggle-item-proto :new "Vertical Scroll" self :has-v-scroll)
    (send graph-toggle-item-proto :new "Horizontal Scroll" self :has-h-scroll)
    (send graph-toggle-item-proto :new "Fixed Aspect Ratio" self :fixed-aspect)
    (if (screen-has-color)
	(send graph-toggle-item-proto :new "Use color" self :use-color)))))

(defmeth scatmat-proto :make-options-dialog-items ()
  (remove
   nil
   (list
    (send graph-backcolor-choice-item-proto :new self)
    (send graph-toggle-item-proto :new "Vertical Scroll" self :has-v-scroll)
    (send graph-toggle-item-proto :new "Horizontal Scroll" self :has-h-scroll)
    (if (screen-has-color)
	(send graph-toggle-item-proto :new "Use color" self :use-color)))))

(defmeth spin-proto :make-options-dialog-items ()
  (remove
   nil
   (list 
    (send graph-backcolor-choice-item-proto :new self)
    (send graph-scaling-choice-item-proto :new self)
    (if (screen-has-color)
	(send graph-toggle-item-proto :new "Use color" self :use-color)))))

;;;;
;;;;
;;;; Plot Sliders and Slicers
;;;;
;;;;

;;; Graph dialogs

(defproto graph-dialog-proto '(plot))

(defmeth graph-dialog-proto :install (plot)
  (setf (slot-value 'plot) plot)
  (send plot :add-subordinate self))

(defmeth graph-dialog-proto :clobber ()
  (let ((plot (slot-value 'plot)))
    (if plot (send plot :delete-subordinate self)))
  (setf (slot-value 'plot) nil))

;;; Graph slicers

(defmeth graph-proto :add-slicer (s)
  (setf (slot-value 'slicers) (adjoin s (slot-value 'slicers)))
  (if (send self :allocated-p) (send self :adjust-slices)))
  
(defmeth graph-proto :remove-slicer (s)
  (setf (slot-value 'slicers) (remove s (slot-value 'slicers)))
  (when (send self :allocated-p)
        (if (eq 'show (send s :type)) (send self :show-all-points))
        (send self :adjust-slices)))

(defproto graph-slicer-proto
          '(variable delta selecting)
          () 
          (list graph-dialog-proto interval-slider-dialog-proto))

(defmeth graph-slicer-proto :isnew (plot var delta range
                                         &rest args
                                         &key select)
  (setf (slot-value 'variable) var)
  (setf (slot-value 'delta) delta)
  (setf (slot-value 'selecting) select)
  (apply #'call-next-method range 
         :action #'(lambda (x) (send plot :adjust-slices)) args)
  (send self :install plot))

(defmeth graph-slicer-proto :install (plot)
  (call-next-method plot)
  (send plot :add-slicer self))
  
(defmeth graph-slicer-proto :clobber ()
  (let ((plot (slot-value 'plot)))
    (if plot (send plot :remove-slicer self)))
  (call-next-method))

(defmeth graph-slicer-proto :selection ()
  (let ((x (send self :value))
        (var (slot-value 'variable))
        (d (slot-value 'delta)))
    (which (< (- x d) var (+ x d)))))

(defmeth graph-slicer-proto :type ()
  (if (slot-value 'selecting) 'select 'show))
  
(defmeth graph-proto :adjust-slices ()
  (cond
    ((slot-value 'slicers)
     (let ((indices (reduce #'intersection 
                            (mapcar #'(lambda (x) (send x :selection))
                                    (slot-value 'slicers))))
            (show (some #'(lambda (x) (eq 'show (send x :type))) 
                        (slot-value 'slicers))))
       (cond
         (show (send self :points-showing indices))
         (t (send self :points-selected indices)))))
    (t (send self :unselect-all-points) (send self :show-all-points))))   

;; Installing graph slicers

(defmeth graph-proto :slicer (var &rest args 
                                  &key 
                                  (fraction 0.25)
                                  title
                                  (points 20))
  (unless title (setq title "Slicer"))
  (let* ((range (list (min var) (max var)))
         (p (* 0.5  fraction (- (nth 1 range) (nth 0 range))))
         (plot self)
         (slicer (apply #'send graph-slicer-proto :new self var p
                        (list (+ (nth 0 range) p) (- (nth 1 range) p))
                        :title title
                        :points points
                        args)))
    (send slicer :value (/ (+ (nth 0 range) (nth 1 range)) 2))
    slicer))
    
(defmeth graph-proto :make-slicer-dialog ()
  (let* ((fractions (list 0.1 0.2 0.3))
         (var-item (send edit-text-item-proto :new 
                         (format nil "(iseq 0 ~d)          " 
                                 (- (send self :num-points) 1))))
         (fraction-item (send choice-item-proto :new 
                              (mapcar #'(lambda (x) (format nil "~a" x))
                                      fractions) 
                              :value 1))
         (type-item (send choice-item-proto :new 
                          (list "Select Slice"
                                "Show Only Slice")))
         expr
         title
         var
         fraction
         select
         ok)
    (flet ((ok-action ()
                      (setq expr (read (make-string-input-stream 
                                        (send var-item :text))))
                      (setq title (format nil "~a" expr))
                      (setq var (eval expr))
                      (setq fraction (nth (send fraction-item :value)
                                          fractions))
                      (setq select (= 0 (send type-item :value)))
                      t))
      (let* ((d (send ok-or-cancel-dialog-proto :new 
                      (list (send text-item-proto :new "Variable")
                            var-item
                            (list (list 
                                   (send text-item-proto :new "Fraction")
                                   fraction-item)
                                  (list 
                                   (send text-item-proto :new "Slicer Type")
                                   type-item)))
                      :ok-action #'ok-action)))
        (unwind-protect (setq ok (send d :modal-dialog))
                        (send d :remove))))
    (if ok 
        (send self :slicer var 
              :title title 
              :fraction fraction 
              :select select))))