(DEFINE-FILE-INFO PACKAGE "IL" READTABLE "INTERLISP" BASE 10)
(FILECREATED "15-Aug-90 16:36:54" {DSK}<usr>local>lde>SOURCES>loops>LIBRARY>GAUGEMETERS.;2 12226  

      changes to%:  (VARS GAUGEMETERSCOMS)

      previous date%: "23-Feb-88 23:06:01" {DSK}<usr>local>lde>SOURCES>loops>LIBRARY>GAUGEMETERS.;1
)


(* ; "
Copyright (c) 1986, 1987, 1988, 1990 by Venue & Xerox Corporation.  All rights reserved.
")

(PRETTYCOMPRINT GAUGEMETERSCOMS)

(RPAQQ GAUGEMETERSCOMS ((DECLARE%: DONTCOPY (PROP MAKEFILE-ENVIRONMENT GAUGEMETERS))
                            (FILES (FROM VALUEOF LOOPSLIBRARYDIRECTORY)
                                   GAUGEINSTRUMENTS)
                            (CLASSES Meter)
                            (METHODS Meter.ComputeScale Meter.DrawInstrument Meter.Set 
                                   Meter.SetParameters Meter.Shape Meter.ShowLabels Meter.ShowTicks)))
(DECLARE%: DONTCOPY 

(PUTPROPS GAUGEMETERS MAKEFILE-ENVIRONMENT (:PACKAGE "IL" :READTABLE "INTERLISP" :BASE 10))
)

(FILESLOAD (FROM VALUEOF LOOPSLIBRARYDIRECTORY)
       GAUGEINSTRUMENTS)

(DEFCLASSES Meter)
(DEFCLASS Meter
   (MetaClass Class doc "A circular instrument that will wrap around any number of times" Edited%: 
                                                             (* RBGMartin " 2-May-86 13:06"))
   (Supers RoundScale)
   (InstanceVariables (ticks 10 doc 
      "ticks on the instrument; value is number or NIL; smallTicks is number between each large tick"
                             )
          (lower 90 doc "lower bound for internal displayVal")
          (displayVal 90 doc "Internal value relative to instrument")
          (range -360 doc "range for internal displayVal")
          (inputRange 10 doc "range for external reading")
          (labels (0 1 2 3 4 5 6 7 8 9)
                 doc "labels for the instrument")
          (height 10)
          (width 10)))


(\BatchMethodDefs)
(METH Meter  ComputeScale (newReading)
      "Meters always have 0 to 9 scale. This computes the proper label scale." (category (Instrument)
                                                                                      ))


(METH Meter  DrawInstrument NIL
      "I" (category (Meter)))


(METH Meter  Set (newReading)
      "Move the setting on a RoundScale instrument from current setting to that specified by input."
      (category (Meter)))


(METH Meter  SetParameters NIL
      "Compute width, height, center and radius etc. for meters" (category (Internal)))


(METH Meter  Shape (newRegion noUpdateFlg ExtraSpaceFlg)
      "Shapes outside of region to specified shape. if ExtraSpaceFlg is T and newRegion is NIL, then the meter is interactively shaped to have extra white space. Shaping from the window menu will keep the meter square except for the space at the bottom for the label."
      (category (Public)))


(METH Meter  ShowLabels NIL
      "If there are any labels, show thenm on the dial" (category (Meter)))


(METH Meter  ShowTicks NIL
      "Draw ticks at even intervals around the circle starting from 90" (category (Meter)))



(Method ((Meter ComputeScale) self newReading)           (* ; "RBGMartin 29-Apr-86 18:57")
   "Meters always have 0 to 9 scale. This computes the proper label scale."
   (PROG (tempScale)
         [SETQ tempScale (COND
                            ((ZEROP newReading)
                             0)
                            (T (FloorOfLog (ABS newReading]
         (_@ inputRange (TIMES 10 (EXPT 10 tempScale)))
         (_@ labelScale (CONS (COND
                                 ((MINUSP newReading)
                                  -1)
                                 (T 1))
                              tempScale))                    (* labelScale is a dotted pair.
                                                           CAR is sign; CDR is exponent.)
     )
   (_ self PrintLabelScale))

(Method ((Meter DrawInstrument) self)                    (* ; "edited: 22-May-86 13:07")
   "I"
   (DRAWCIRCLE (@ xc)
          (@ yc)
          (@ radius)
          (@ brushWidth)
          NIL
          (@ window)))

(Method ((Meter Set) self newReading)                    (* ; "edited: 22-May-86 13:19")
   "Move the setting on a RoundScale instrument from current setting to that specified by input."
   [PROG [(ABSnewReading (ABS newReading))
          (EXPO (CDR (@ labelScale)]
         (COND
            ((MINUSP (TIMES newReading (@ reading)))         (* readings are different signs.
                                                           Set Meter to 0, change scale, and 
                                                           move needle.)
             (_ self ShowReading)                            (* erase the needle)
             (_@ reading 0)
             (_ self ShowReading)                            (* display needle at 0)
             (_ self ComputeScale newReading)
             (_@ reading newReading)
             (RotateLine (@ xc)
                    (@ yc)
                    (@ needleLength)
                    (@ displayVal)
                    (_@ displayVal (_ self ComputeDisplayVal ABSnewReading))
                    (@ window)
                    (@ brushWidth)))
            (T                                               (* newReading and reading are same 
                                                           sign.)
               (PROG NIL
                     (COND
                        ((LESSP ABSnewReading (EXPT 10 EXPO))

         (* new reading is between 0 and 1 on the current scale.
       Rotate the needle, then rescale.)

                         (RotateLine (@ xc)
                                (@ yc)
                                (@ needleLength)
                                (@ displayVal)
                                (_@ displayVal (_ self ComputeDisplayVal ABSnewReading))
                                (@ window)
                                (@ brushWidth))
                         (_@ reading newReading)
                         (_ self ShowReading)                (* erase the needle)
                         (_ self ComputeScale newReading)    (* rescale)
                         (_ self ShowReading)                (* draw the needle)
                         )
                        ((GREATERP ABSnewReading (TIMES 10 (EXPT 10 EXPO)))
                                                             (* new reading is higher than 
                                                           current gauge scale)
                         (_ self ShowReading)                (* erase the needle)
                         (_ self ComputeScale newReading)    (* rescale)
                         (_ self ShowReading)                (* draw the needle)
                         (_@ reading newReading)
                         (RotateLine (@ xc)
                                (@ yc)
                                (@ needleLength)
                                (@ displayVal)
                                (_@ displayVal (_ self ComputeDisplayVal ABSnewReading))
                                (@ window)
                                (@ brushWidth)))
                        (T                                   (* the new reading is on the current 
                                                           scale.)
                           (_@ reading newReading)
                           (RotateLine (@ xc)
                                  (@ yc)
                                  (@ needleLength)
                                  (@ displayVal)
                                  (_@ displayVal (_ self ComputeDisplayVal ABSnewReading))
                                  (@ window)
                                  (@ brushWidth)])

(Method ((Meter SetParameters) self)                     (* ; "edited: 27-Jan-87 09:59")
   "Compute width, height, center and radius etc. for meters"
   [LET ((MaxStrWidth (MAXSTRINGWIDTH (@ labels)
                             (@ font)))
         (FontHeight (FONTHEIGHT (@ font)))
         meterSize maxFontDimension)
        (_Super )
        (SETQ maxFontDimension (MAX FontHeight MaxStrWidth))
        [SETQ meterSize (MAX (TIMES 6 maxFontDimension)
                             (TIMES 2 (PLUS 3 (ShowRayLabelLength self (TIMES 2 (@ ticks%:,tickLength)
                                                                              ))
                                            (IQUOTIENT maxFontDimension 2]

         (* there are 6 numbers on a side of the meter.
       This gaurantees the numbers will not overlap.
       Also, check to make sure that this is not smaller than two numbers on either 
       side of a circle with a diameter 4 times the tickLength.
       Refer to ShowRayLabel.)

        (_@ height%:,min (HEIGHTIFWINDOW (PLUS (@ spaceForLabelScale)
                                               meterSize)
                                (@ title)))
        (_@ width%:,min (WIDTHIFWINDOW meterSize))
        (_@ height (MAX (@ height)
                        (@ height%:,min)))                   (* need this in case the font is 
                                                           bigger)
        (_@ width (MAX (@ width)
                       (@ width%:,min)))
        (_@ yc (PLUS (@ spaceForLabelScale)
                     (_@ xc (IQUOTIENT (IMIN (InteriorWidth self)
                                             (DIFFERENCE (InteriorHeight self)
                                                    (@ spaceForLabelScale)))
                                   2))))
        (_@ radius (IDIFFERENCE (@ xc)
                          (PLUS 3 maxFontDimension)))        (* radius leaves room for labels 
                                                           around sides)
        (_@ needleLength (IDIFFERENCE (@ radius)
                                (@ ticks%:,tickLength)))])

(Method ((Meter Shape) self newRegion noUpdateFlg ExtraSpaceFlg)
                                                             (* ; "RBGMartin 28-Jan-87 17:11")
   "Shapes outside of region to specified shape. if ExtraSpaceFlg is T and newRegion is NIL, then the meter is interactively shaped to have extra white space. Shaping from the window menu will keep the meter square except for the space at the bottom for the label."
   (COND
      ((NOT ExtraSpaceFlg)
       (_Super self Shape (if newRegion
                              then (GetMinRegion newRegion self)
                            else (GETREGION (@ width%:,min)
                                            (@ height%:,min)
                                            (WINDOWPROP (@ window)
                                                   'REGION)
                                            (FUNCTION MeterNEWREGIONfn)
                                            self))
                    noUpdateFlg))
      (T (_Super self Shape newRegion noUpdateFlg))))

(Method ((Meter ShowLabels) self)                        (* ; "RBGMartin 21-Apr-86 14:57")
   "If there are any labels, show thenm on the dial"
   [COND
      ((@ labels)
       (DSPRIGHTMARGIN (IPLUS (WINDOWPROP (@ window)
                                     'WIDTH)
                              50)
              (@ window))                                    (* so that labels on the right won't 
                                                           go to the next line)
       (for lab in (@ labels) as a in (EvenIntervals 90 -360 (@ ticks))
          do (ShowRayLabel self a lab])

(Method ((Meter ShowTicks) self)                         (* ; "RBGMartin 29-Apr-86 15:44")
   "Draw ticks at even intervals around the circle starting from 90"
   (for a in (EvenIntervals 90 -360 (@ ticks)) bind (incr _ (IQUOTIENT -360 (@ ticks)))
      do (DrawTick self a (@ ticks%:,smallTicks)
                    incr 0.5)))

(\UnbatchMethodDefs)
(PUTPROPS GAUGEMETERS COPYRIGHT ("Venue & Xerox Corporation" 1986 1987 1988 1990))
(DECLARE%: DONTCOPY
  (FILEMAP (NIL)))
STOP
