aboutsummaryrefslogtreecommitdiffhomepage
path: root/gui/button.lisp
diff options
context:
space:
mode:
authorColin Okay <colin@cicadas.surf>2022-07-21 11:34:37 -0500
committerColin Okay <colin@cicadas.surf>2022-07-21 11:34:37 -0500
commit6d9b8b48423dba99ecdba004f260c30e6717b6a6 (patch)
tree167f0416e301a32ccfe24ee5dc3b1371a33d108a /gui/button.lisp
parent3782dddb07974f1b1b79478d2f96384498e81bf4 (diff)
[add] gui package. moved button.lisp into gui
Diffstat (limited to 'gui/button.lisp')
-rw-r--r--gui/button.lisp113
1 files changed, 113 insertions, 0 deletions
diff --git a/gui/button.lisp b/gui/button.lisp
new file mode 100644
index 0000000..7c94663
--- /dev/null
+++ b/gui/button.lisp
@@ -0,0 +1,113 @@
+;;;; button.lisp
+
+(in-package #:wheelwork)
+
+(defclass/std button (unit interactive)
+ ((up down :with
+ :std (error "UP and DOWN lots are required")
+ :doc "Any affine renderable unit")
+ (bg :with)
+ (on-press on-release :with :doc "Function accepting the button."))
+ (:documentation "A basic button class. The UP and DOWN slots should
+ be filled with renderable objects having the same size."))
+
+(defhandler button-released
+ (on-mouseup ()
+ (with-slots (up down on-release) target
+ (setf (unit-visiblep up) t
+ (unit-visiblep down) nil)
+ (when on-release
+ (funcall on-release target)))))
+
+(defhandler button-pressed
+ (on-mousedown ()
+ (with-slots (up down on-press) target
+ (setf (unit-visiblep up) nil
+ (unit-visiblep down) t)
+ (when on-press
+ (funcall on-press target)))))
+
+(defmethod (setf closer-mop:slot-value-using-class) :before
+ (newval class (button button) slot)
+ (let ((slot-name
+ (closer-mop:slot-definition-name slot)))
+ (case slot-name
+ ((up down bg)
+ (when (slot-boundp button slot-name)
+ (error "Swapping Button Faces Not Presently Supported"))))))
+
+(defmethod initialize-instance :after ((button button) &key)
+ (add-handler button #'button-pressed)
+ (add-handler button #'button-released)
+ (with-slots (up down bg) button
+ (when bg
+ (setf (unit-container bg) button
+ (unit-visiblep bg) t))
+ (setf (unit-visiblep down) nil
+ (unit-visiblep up) t
+ (unit-container up) button
+ (unit-container down) button)))
+
+(defmethod cleanup ((button button))
+ (with-slots (up down bg) button
+ (when bg (cleanup bg))
+ (cleanup up)
+ (cleanup down)))
+
+(defmethod render ((button button))
+ (with-slots (up down bg) button
+ (when bg (render bg))
+ (if (unit-visiblep up)
+ (render up)
+ (render down))))
+
+(macrolet
+ ((def-accessors (&rest accessor-names)
+ (let ((defs
+ (loop for accessor-name in accessor-names
+ collect
+ `(defmethod ,accessor-name ((button button))
+ (,accessor-name (button-up button)))
+
+ collect
+ `(defmethod (setf ,accessor-name) (newval (button button))
+ (setf (,accessor-name (button-up button)) newval
+ (,accessor-name (button-down button)) newval)
+ (when (button-bg button)
+ (setf (,accessor-name (button-bg button)) newval))))))
+ `(progn ,@defs))))
+
+ (def-accessors x y scale-x scale-y width height rotation))
+
+(defmethod get-rect ((button button))
+ (get-rect (button-up button)))
+
+(defun make-texture-button (up down &key pressed released)
+ "UP and DOWN should be strings naming assets to use as the up and
+ down images for the button."
+ (make-instance
+ 'button
+ :on-press pressed :on-release released
+ :up (make-instance 'image :texture (get-asset up))
+ :down (make-instance 'image :texture (get-asset down))))
+
+(defun make-text-button
+ (font up down
+ &key
+ pressed released
+ down-font
+ (up-color #(1.0 1.0 1.0 1.0))
+ (down-color #(1.0 1.0 1.0 1.0)))
+ (make-instance
+ 'button
+ :on-release released :on-press pressed
+ :up (make-instance
+ 'text
+ :content up
+ :color up-color
+ :font font)
+ :down (make-instance
+ 'text
+ :content down
+ :color down-color
+ :font (or down-font font))))