From: Kenny Tilton
Subject: Semaphors: radio group example
Date: 
Message-ID: <39ED0F5B.E46DBB68@nyc.rr.com>
The following example shows a complete loop of what I characterize as a
working model acting causally in the world outside the model.

Information enters the model when glue code which handles OS events sets
semaphoric variables, in this case indirectly since the mouseDown gets
some sophisticated handling before the action (here 'turn-to) associated
with a control gets dispatched.

Information leaves the model via echo functions, in this case actually
re-tuning some imagined FM radio peripheral and redrawing the screen to
illustrate the buttons new state.

kenny

;-----------------------------------------------------

(in-package :model)


(defmodel Radio (Family)
  ((frequency :semaphor t
              :initform nil
              :initarg :frequency
              :accessor frequency)))

(def-sm-echo (frequency) ()
  (trc "echo> radio now set to" newvalue)
  ;
  ; also tune actual radio via API
  ;
  )

;----------------------------

(defmodel RadioButton ()
  ((frequency :initarg :frequency :accessor frequency)
   (pushed :semaphor t
             :initform (sm? (eql (frequency self)
                                 (^frequency (upper self Radio))))))) ;;
upper searches up family tree for type

(def-sm-echo (pushed) ()
  ;
  ; Within a GUI, we would also trigger a screen redraw, and the draw
  ; function for the button would draw the button appropriately to
  ; its 'pushed state
  ;
  (trc "echo> radiobutton frequency" (frequency self) (if newValue :on
:off)))

;----------------------------------

(defun turn-to (radioButton)
  ;
  ; Within the GUI, this function gets triggered
  ; as the eventual consequence of a mouseDown. Thus
  ; this is where the model gets inputs from the
  ; world outside.
  ;
  (setf (frequency (upper radioButton Radio))
          (frequency radioButton)))

;----------------------------

(defun test-radio ()
  (let ((r (to-be (make-instance 'Radio
                    :frequency (smv 100.3)
                    :kids (list (mkPart :hiphop (RadioButton) :frequency
97.1)
                                (mkPart :top40 (RadioButton) :frequency
100.3)
                                (mkPart :ezlisten (RadioButton)
:frequency 106.7))))))
    (dolist (k (kids r))
      (trc "top> turning to" (mdname k)) ;; all models have an 'mdname
      (turn-to k))))

#| Output:

0> echo> radio now set to 100.3
0> echo> radiobutton frequency 97.1 :OFF
0> echo> radiobutton frequency 100.3 :ON
0> echo> radiobutton frequency 106.7 :OFF
0> top> turning to :HIPHOP
0> echo> radio now set to 97.1
0> echo> radiobutton frequency 100.3 :OFF
0> echo> radiobutton frequency 97.1 :ON
0> top> turning to :TOP40
0> echo> radio now set to 100.3
0> echo> radiobutton frequency 100.3 :ON
0> echo> radiobutton frequency 97.1 :OFF
0> top> turning to :EZLISTEN
0> echo> radio now set to 106.7
0> echo> radiobutton frequency 106.7 :ON
0> echo> radiobutton frequency 100.3 :OFF

|#