BigEasy/BigEasyStandardControls.c

/*
    File:       BigEasyStandardControls.c
 
    Contains:   xxx put contents here xxx
 
    Written by: xxx put writers here xxx
 
    Copyright:  © 1990-1991 by Apple Computer, Inc., all rights reserved.
 
    This file is used in these builds: Warhol
 
    Change History (most recent first):
 
         <9>      4/3/92    dvb     Allow nil for default style.
         <8>     1/20/92    dvb     Latest BigEasy revs.
         <7>    11/12/91    dvb     General fixation
         <6>      9/6/91    MD      don't HLock a Ptr
         <5>     5/28/91    JB      Added prototypes for BigEasy Proc Ptrs
         <4>     5/23/91    PH      THINK C 5
         <3>     4/25/91    JB      Changing to new THINK_C interface files
         <2>    11/17/90    dvb     Return unprocessed key-actions
         <4>      8/4/90    dvb     Fix unused picture thing
         <3>      8/2/90    dvb     Fix prototypes
         <2>     7/31/90    dvb     Fix include paths
 
    To Do:
*/
 
/*
  * file: BigEasyControls.c
  *
  * started 25 May 1990 12:07:24 Friday at 310 Nobel
  * 
  * david van brink
  *
  */
 
 
 
 
/************************************
* Inclusions
************************************/
 
#include <QuickDraw.h>
#include <Memory.h>
#include <Resources.h>
#include <OSUtils.h>
#include <OSUtils.h>
#include <OSUtils.h>
#include <Events.h>
#include <desk.h>
 
#define privateEasyControls
#include "BigEasy2.h"
#include "BigEasyGrafish.h"
#include "BigEasyTextish.h"
#include "BigEasyControls.h"
#include "BigEasyStandardControls.h"
 
 
/************************************
* Constants
************************************/
 
#define kSlop 10
#define kBarVMargin 4
#define kSliderCursor 200
 
/************************************
    Default Styles
************************************/
 
static tSliderStyle dDefaultSliderStyle =
    {
    longNum,
    120,15,
    80,13,
    nil
    };
 
 
/************************************
* Prototypes
************************************/
static void MaybeRaisedRect(short c,Rect *r,Boolean b);
 
static void NewSlider(easyControlPtr ec);
static void DisposeSlider(easyControlPtr ec);
static void DrawSlider(easyControlPtr );
static void TrackSlider(easyControlPtr,Point p);
static void KeySlider(easyControlPtr,short k,short m,Boolean *tookKey);
static void DrawSliderValue(easyControlPtr );
static void HitTestSlider(void);
static void SetSliderValue(struct easyControlRecord *ec,long value);
 
static void NewToggle(easyControlPtr ec);
static void DisposeToggle(easyControlPtr ec);
static void DrawToggle(easyControlPtr );
static void DrawToggleValue(easyControlPtr );
static void HitTestToggle(easyControlPtr,Point p);
static void TrackToggle(easyControlPtr,Point p,short *trackResult,short mods);
static void KeyToggle(easyControlPtr,short k,short mods,Boolean *tookKey);
static void SetToggleValue(easyControlPtr,long);
static void Idle(easyControlPtr,long *);
 
easyControlType toggleType =
    {
    NewToggle,
    DisposeToggle,
    DrawToggle,
    HitTestToggle,
    TrackToggle,
    KeyToggle,
    SetToggleValue,
    Idle,
    DrawToggleValue
    };
 
easyControlType sliderType =
    {
    NewSlider,
    DisposeSlider,
    DrawSlider,
    (becHitTestProcPtr)HitTestSlider,
    (becTrackProcPtr)TrackSlider,
    KeySlider,
    SetSliderValue,
    Idle,
    DrawSliderValue
    };
 
 
 
/************************************
* Routines
************************************/
 
void MaybeRaisedRect(short c,Rect *r,Boolean b)
/*
  * if background, draw a flat rect,
  * else a raised rect.
  */
    {
    if(b)
        {
        Fore555(c);
        PaintRect(r);
        }
    else
        RaisedRect(r,c);
    }
 
 
 
/*
  * Sliders
  *
  * Sliders copy their style into a handle, stored
  * in the slide field of the easyControl.
  */
 
void TrackSlider(ec,p)
 /*
   * Track the mouse within the slider as long
   * as the button is held down, all the while
   * updating the value and drawing the bar.
   */
    register easyControlPtr ec;
    Point p;
    {
    tSliderStyle *st;
    Point lastP;
    long oldValue;
    long value;
    long vRange, rRange,rounding;
    double fVRange, fRRange, fRounding;     /* for floating point sliders   */
    Rect slopRect;
    long q;
    Boolean zingCursor;
    Handle tempH;
 
    GoCursor(kSliderCursor);
    zingCursor = true;
 
    st = *(tSliderStyle **)ec->style;
    HLock(tempH = RecoverHandle((Ptr)st));
    oldValue = ec->value;
 
    slopRect = ec->rect;
    InsetRect(&slopRect,-kSlop,-kSlop);
 
    if(st->numberType == floatNum)
        {
        fVRange = AsFloat(ec->high) - AsFloat(ec->low);
        fRRange = st->sWidth - 2;
        fRounding = (fRRange / fVRange) / 2;
        }
    else
        {
        vRange = ec->high - ec->low;
        rRange = st->sWidth - 2;
        rounding = (rRange / vRange) / 2;
        }
 
    if(ec->initActionProc)                  /* Call initAction proc once        */
        (*ec->initActionProc)(ec->value,ec->refcon);
    while(Button())
        {
        q = TickCount()+2;
        while(TickCount() < q)
            SystemTask();
 
 
        if(ec->actionProc)                  /* Call action proc every time      */
            (*ec->actionProc)(ec->value,ec->refcon);
 
        lastP.h = p.h+1;                        /* Guarantee do first time through  */
        GetMouse(&p);
        if( (p.h != lastP.h) || (p.v != lastP.v) )
            {
            if(PtInRect(p,&slopRect))
                {
                if(!zingCursor)
                    {
                    GoCursor(kSliderCursor);
                    zingCursor = true;
                    }
                if(st->numberType == floatNum)
                    ;
                else
                    value = ec->low + (long)(p.h - ec->rect.left + rounding + 1) * vRange/rRange;
                }
            else
                {
                value = oldValue;
                if(zingCursor)
                    {
                    InitCursor();
                    zingCursor = false;
                    }
                }
 
            if(value < ec->low)
                value = ec->low;
            else if(value > ec->high)
                value = ec->high;
 
            if(value != ec->value)
                {
                ec->value = value;
                DrawSliderValue(ec);
 
                if(ec->valueProc)               /* Call value proc for new value    */
/*                  (*ec->valueProc)(ec); */
                    (*ec->valueProc)((easyControl)RecoverHandle((Ptr)ec));
                }
            lastP = p;
            }
        }
    if(ec->doneActionProc)                  /* Call doneAction proc once        */
        (*ec->doneActionProc)(ec->value,ec->refcon);
 
    HUnlock(tempH);
    InitCursor();
    }
 
void DrawSlider(ec)
/*
  * Draw the slider passed.
  */
    register easyControlPtr ec;
    {
    register tSliderStyle *st;
    Rect r;
    Handle tempH;
 
    st = *(tSliderStyle **)ec->style;
    HLock(tempH = RecoverHandle((Ptr)st));
    r = ec->rect;
/*  r.right = r.left + st->sWidth;
    r.bottom = r.top + st->sHeight;*/
 
    if(ec->flags & easyControlActive)
        PenPat((Pattern *)dBlackPat);
    else
        PenPat((Pattern *)&dGrayPat);
 
    Fore555(ec->color[controlFrame]);
    PenSize(1,1);
    FrameRect(&r);
    InsetRect(&r,1,1);
    Fore555(ec->color[controlBackground]);
    PaintRect(&r);
 
    DrawSliderValue(ec);
    HUnlock(tempH);
    }
 
 
void DrawSliderValue(ec)
    register easyControlPtr ec;
    {
    Rect bar,r;
    register tSliderStyle *st;
 
    st = *(tSliderStyle **)ec->style;       /* already locked by caller */
 
    if(ec->value < ec->low)
        ec->value = ec->low;
    else if(ec->value > ec->high)
        ec->value = ec->high;
 
    bar.top = ec->rect.top + kBarVMargin;
    bar.bottom = ec->rect.top + st->sHeight - kBarVMargin;
    bar.left = ec->rect.left + 1;
    bar.right = ec->rect.left + 1 + (long)(ec->value - ec->low) * (long)(st->sWidth - 2) /
            (long)(ec->high - ec->low);
 
    if(ec->flags & easyControlActive)
        PenPat((Pattern *)&dBlackPat);
    else
        PenPat((Pattern *)&dGrayPat);
 
    RaisedRect(&bar,ec->color[controlPart1]);
 
    bar.left = bar.right;
    bar.right = ec->rect.left + st->sWidth - 1;
    if(ec->variation & drawRightSlider)
        RaisedRect(&bar,ec->color[controlPart2]);
    else
        {
        Fore555(ec->color[controlBackground]);
        PaintRect(&bar);
        }
 
    if(st->tHeight)                     /* tHeight = 0 means no text    */
        {
        r.left = ec->rect.left;
        r.top = ec->rect.top + st->sHeight - 1;
        r.right = r.left + st->tWidth;
        r.bottom = r.top + st->tHeight;
        Fore555(ec->color[controlFrame]);
        FrameRect(&r);
        InsetRect(&r,1,1);
        Fore555(ec->color[controlBackground]);
        PaintRect(&r);
        MoveTo(r.left + 2,r.bottom - (st->tHeight - 9)/2);
        Fore555(ec->color[controlFrame]);
        if(st->drawValue)
            (*st->drawValue)((easyControl)RecoverHandle((Ptr)ec));
        else
            {
            if(st->numberType == longNum)
                DrawNum(ec->value);
            else if(st->numberType == fixedNum)
                DrawFixed(ec->value,4);
            else if(st->numberType == fracNum)
                DrawFrac(ec->value,8);
            else
                DrawString((StringPtr)"\pxyz");
            }
        }
    }
 
void NewSlider(ec)
/*
  * Do allocations for a new easyControl slider type
  */
    easyControlPtr ec;
    {
    Handle h;
    register tSliderStyle *st;
 
/*
  * Copy the style information to our very own handle
  */
    if(ec->style == 0)
        ec->style = &dDefaultSliderStyle;
    h = NewHandle(sizeof(tSliderStyle));
    BlockMove(ec->style,*h,sizeof(tSliderStyle));
    ec->style = h;
    st = (tSliderStyle *)*h;
    st->sWidth = ec->rect.right - ec->rect.left;
    st->sHeight = ec->rect.bottom - ec->rect.top;
 
    ec->low = 0;
    ec->high = 100;
    }
 
void DisposeSlider(ec)
/*
  * Deallocate the slider
  */
    register easyControlPtr ec;
    {
    DisposHandle((Handle)ec->style);
    }
 
void SetSliderValue(struct easyControlRecord *ec,long value)
    {
    ec->value = value;  
    }
 
void HitTestSlider()
    {
    }
 
void NewToggle(ec)
    easyControlPtr ec;
    {
    ec->low = 0;
    ec->high = 1;
    }
 
void DisposeToggle(ec)
    easyControlPtr ec;
    {
    #pragma unused(ec)
    }
 
void DrawToggle(ec)
    easyControlPtr ec;
    {
    Rect r;
 
    r = ec->rect;
    Fore555(ec->color[0]);
    PenSize(1,1);
    FrameRect(&r);
    DrawToggleValue(ec);
    }
 
void DrawToggleValue(ec)
    easyControlPtr ec;
    {
    register tToggleStyle *st;
    Rect r;
    short c;
    PicHandle p;
 
    r = ec->rect;
    InsetRect(&r,1,1);
 
    if((ec->variation & checkboxToggle) && !(ec->flags & easyControlTracking))  /* checkbox version ? */
        {
        MaybeRaisedRect(ec->color[controlBackground],&r,ec->flags & easyControlBack);
        if(ec->value)
            {
            Fore555(ec->color[controlFrame]);
            PenSize(2,2);
            MoveTo(r.left,r.top);
            LineTo(r.right-2,r.bottom-2);
            MoveTo(r.left,r.bottom-2);
            LineTo(r.right-2,r.top);
            }
        }
    else
        {
        if((!ec->value) ^ (ec->variation & checkboxToggle != 0))
            c = ec->color[controlBackground];
        else
            c = ec->color[controlPart1];
        
        if(ec->flags & easyControlBack)
            {
            Fore555(c);
            PaintRect(&r);
            }
        else
            {
            RaisedRect(&r,c);
        
            st = ec->style;
            if(st && st->p)                 /* res ID zero doesn't draw */
                {
                p = (PicHandle)GetResource('PICT',st->p);
                if(p)
                    {
                    r = (**p).picFrame;
                    OffsetRect(&r,((ec->rect.left  + ec->rect.right) - (r.left + r.right))/2,
                            ((ec->rect.top + ec->rect.bottom) - (r.top + r.bottom))/2);
                    DrawPicture(p,&r);
                    }
                else                        /* missing picture */
                    {
                    GoBlack();
                    PenSize(1,1);
                    MoveTo(ec->rect.left,ec->rect.top);
                    LineTo(ec->rect.right-1,ec->rect.bottom-1);
                    }
                }
            }
        }
    }
 
void TrackToggle(register easyControlPtr ec,Point p,
            short *trackResult,short mods)
    {
    long oldValue,newValue;
    register Boolean inRect;
    long dummylong;
    
    #pragma unused(mods)
 
    oldValue = ec->value;
    newValue = !ec->value;
 
    if(ec->variation & dontTrackToggle)
        {
        ec->value = newValue;
        DrawToggleValue(ec);
        if(!(ec->variation & toggleToggle))
            Delay(5,&dummylong);
        inRect = true;
        }
    else
        do
            {
            SystemTask();
            GetMouse(&p);
            inRect = PtInRect(p,&ec->rect);
            if(inRect)
                newValue = !oldValue;
            else
                newValue = oldValue;
            if(newValue != ec->value)
                {
                ec->value = newValue;
                DrawToggleValue(ec);
                }
            } while(Button());
 
    if(!(ec->variation & toggleToggle) && (ec->value))      /* if it's not toggle-ish, reset it */
        {
        ec->value = 0;
        DrawToggleValue(ec);
        }
 
    *trackResult = inRect;
    }
 
void SetToggleValue(easyControlPtr ec,long v)
    {
    ec->value = v;
    DrawToggleValue(ec);
    }
 
void HitTestToggle(easyControlPtr ec,Point p)
    {
    #pragma unused(ec)
    #pragma unused(p)
    }
 
void Idle(ec,r)
    easyControlPtr ec;
    long *r;
    {
    if(*r & 1)
        Fore555(ec->color[1]);
    else
        Fore555(ec->color[0]);
 
    PenSize(1,1);
    FrameRect(&ec->rect);
    }
 
void KeySlider(register easyControlPtr ec,short k,short m,register Boolean *tookKey)
    {
    register short step;
 
    *tookKey = true;
 
    if(m&shiftKey)
        step = 10;
    else
        step = 1;
    switch(k)
        {
        case 28:
            ec->value-=step;
            break;
        case 29:
            ec->value+=step;
            break;
        default:
            *tookKey = false;
        }
    DrawSliderValue(ec);
    }
 
void KeyToggle(easyControlPtr ec,short k,short m,Boolean *tookKey)
    {
#pragma unused (m)
 
    long dummylong;
    
    if(k == ' ')        /* spacebar only */
        {
        *tookKey = true;
 
        if(ec->variation & toggleToggle)
            {
            ec->value = !ec->value;
            DrawToggleValue(ec);
            }
        else
            {
            ec->value = 1;
            DrawToggleValue(ec);
            Delay(5,&dummylong);
            ec->value = 0;
            DrawToggleValue(ec);
            }
    
        if(ec->valueProc)
            (*ec->valueProc)((easyControl)RecoverHandle((Ptr)ec));
        }
    else
        *tookKey = false;
    }