1 (in-package #:clnl-gltk)
4 ; - check logic when min is greater than max
5 ; - check logic when value is outside of bounds
6 ; - should make the handle disappear
7 ; - check logic when min or max updates
9 ; - have a hover for handle, when mousedown, do mousedown like the others
10 ; - have a hover for the bar
12 ; - handle "Units" from netlogo sliders
13 ; - have display be dependent on significant digits of min/max/step
15 ; - handle vertical sliders - this is really just the same slider just rotated, nothing special
17 ; Height is constant for slideres in netlogo
18 (defvar *slider-height* 33
31 The default slider height.")
33 (defstruct slider x y width text callback min max increment value dragging)
35 (defun slider (x y width text callback min max increment value)
36 "SLIDER X Y WIDTH TEXT CALLBACK MIN MAX INCREMENT VALUE => SLIDER
40 X: x offset, in pixels
41 Y: y offset, in pixels
42 WIDTH: width, in pixels
43 TEXT: string for the textual display
47 INCREMENT: increment when moving the slider
49 SLIDER: a slider that can later be rendered
53 SLIDER creates a button widget.
55 TODO: The rest of this description needs to be updated!"
57 :x x :y y :width width :text text :callback callback
58 :min min :max max :value value :increment increment :dragging nil))
60 (defun slider-bar-left (slider)
61 (with-slots (min max value width) slider
62 (+ 4 (if (and value min max (/= min max)) (floor (* (- width 12) (/ value (- max min)))) 0))))
64 (defun set-min (slider min)
65 (setf (slider-min slider) min))
67 (defun set-max (slider max)
68 (setf (slider-max slider) max))
70 (defun set-value (slider value)
71 (setf (slider-value slider) value))
73 (defun update-slider-value-from-click (slider x)
75 (< x (+ (slider-x slider) (slider-bar-left slider)))
76 (setf (slider-value slider) (max (slider-min slider) (- (slider-value slider) (slider-increment slider))))
77 (setf (slider-value slider) (min (slider-max slider) (+ (slider-value slider) (slider-increment slider))))))
79 (defun update-slider-value-from-move (slider m-x)
80 (with-slots (x width value min max increment) slider
83 (right (+ x width -8))
84 (portion-left (/ (- m-x left) (- right left)))
91 (* portion-left (- max min))
93 (when (/= value new-value)
94 (setf (slider-value slider) new-value)))))
96 (defun in-slider (m-x m-y slider)
97 (with-slots (x y width) slider
98 (and (< x m-x (+ x width)) (< y m-y (+ y *slider-height*)))))
100 (defun in-slider-handle (m-x m-y slider)
102 (in-slider-bar m-y slider)
104 ((left (+ (slider-x slider) (slider-bar-left slider))))
105 (< left m-x (+ left 6)))))
107 (defun in-slider-bar (m-y slider)
108 (with-slots (y) slider
109 (< (+ y 18) m-y (+ y 30))))
111 ; Uhm, this is currently just pulled from switch, and needs to be changed to slider looking stuffs
112 (defmethod render ((slider slider))
113 (gl:color 1f0 1f0 1f0)
114 (with-slots (x y width text min max value) slider
115 (gl:with-pushed-matrix
118 (gl:color 1f0 1f0 1f0)
120 (gl:vertex 3 26) (gl:vertex (- width 5) 26) (gl:vertex (- width 5) 24) (gl:vertex 3 24)
124 ((left (slider-bar-left slider)))
125 (gl:color 0f0 0f0 0f0)
127 (gl:vertex left 30) (gl:vertex (+ left 4) 30) (gl:vertex (+ left 4) 20) (gl:vertex left 20)
129 (gl:color 1f0 1f0 1f0)
130 (draw-border left 20 (+ left 4) 30))
132 (gl:color 1f0 1f0 1f0)
133 ;(gl:with-pushed-matrix (gl:translate 14 15 0) (font-print "On"))
134 ;(gl:with-pushed-matrix (gl:translate 14 1 0) (font-print "Off"))
136 (draw-border 0 0 width *slider-height*)
138 ; when the value is large enough, value takes precidence and clips off the text, then makes the text disappear
141 ; It also clips off text if too long, and replaces with elipses, so we can do similar
142 ; (this is true for slider and switch!)
143 ; - WE HAVEN"T DONE THIS YET
146 (if (< (* *font-width* (length text)) (- width 46))
148 (format nil "~A..." (subseq text 0 (- (truncate (- width 46) *font-width*) 3))))))
149 (gl:with-pushed-matrix
153 ; Technically netlogo does not clip numbers that are too large, and just draws what it can.
154 ; It's a rare edge case, but maybe we should have something to do with it
155 ; - WE HAVEN"T DONE THIS YET
157 ((value-text (format nil "~A" (or value 0))))
158 (gl:with-pushed-matrix
159 (gl:translate (- width 4 (* (length value-text) *font-width*)) 2 0)
160 (font-print value-text))))))
162 (defmethod reposition ((slider slider) x y)
163 (setf (slider-x slider) x)
164 (setf (slider-y slider) y))
166 (defmethod resize ((slider slider) width height)
167 (declare (ignore height))
168 (setf (slider-width slider) width))
170 (defmethod mousemove ((slider slider) m-x m-y)
172 (and (slider-dragging slider) (update-slider-value-from-move slider m-x))
173 (funcall (slider-callback slider) (slider-value slider))))
175 (defmethod mouseup ((slider slider) m-x m-y)
176 (when (slider-dragging slider)
177 (setf (slider-dragging slider) nil)
178 (funcall (slider-callback slider) (slider-value slider))))
180 (defmethod mousedown ((slider slider) m-x m-y)
182 ((not (in-slider m-x m-y slider)) nil)
183 ((in-slider-handle m-x m-y slider) (setf (slider-dragging slider) t))
185 ; Netlogo recognizes the click even if outside the bar horizontally
186 ((in-slider-bar m-y slider)
187 (update-slider-value-from-click slider m-x)
188 (funcall (slider-callback slider) (slider-value slider)))))