/*****************************************************************************
 *  Module for Microchip Graphics Library
 *  GOL Layer 
 *  Slider
 *****************************************************************************
 * FileName:        Slider.c
 * Dependencies:    None 
 * Processor:       PIC24, PIC32
 * Compiler:       	MPLAB C30 V3.00, MPLAB C32
 * Linker:          MPLAB LINK30, MPLAB LINK32
 * Company:         Microchip Technology Incorporated
 *
 * Software License Agreement
 *
 * Copyright © 2008 Microchip Technology Inc.  All rights reserved.
 * Microchip licenses to you the right to use, modify, copy and distribute
 * Software only when embedded on a Microchip microcontroller or digital
 * signal controller, which is integrated into your product or third party
 * product (pursuant to the sublicense terms in the accompanying license
 * agreement).  
 *
 * You should refer to the license agreement accompanying this Software
 * for additional information regarding your rights and obligations.
 *
 * SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY
 * OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR
 * PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR
 * OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION,
 * BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT
 * DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL,
 * INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA,
 * COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY
 * CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
 * OR OTHER SIMILAR COSTS.
 *
 * Author               Date        Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Paolo A. Tamayo		11/12/07	Version 1.0 release
 *****************************************************************************/

#include "Graphics\Graphics.h"

#ifdef USE_SLIDER

/* Internal Functions */
SHORT SldSetThumbSize(SLIDER *pSld, SHORT high, SHORT low);
void SldGetMinMaxPos(SLIDER *pSld, WORD *minPos, WORD *maxPos);
WORD SldGetWidth(SLIDER *pSld);
WORD SldGetHeight(SLIDER *pSld);

/*********************************************************************
* Function: SLIDER *SldCreate(WORD ID, SHORT left, SHORT top, SHORT right, 
*							  SHORT bottom, WORD state, SHORT range, 
*							  SHORT page, SHORT pos, GOL_SCHEME *pScheme)
*
* Notes: Creates a SLIDER object and adds it to the current active list.
*        If the creation is successful, the pointer to the created Object 
*        is returned. If not successful, NULL is returned.
*
********************************************************************/
SLIDER *SldCreate(WORD ID, SHORT left, SHORT top, SHORT right, SHORT bottom, 
			      WORD state, WORD range, WORD page, WORD pos, GOL_SCHEME *pScheme)
{
	SLIDER *pSld = NULL;
	
	pSld = (SLIDER*)malloc(sizeof(SLIDER));
	if (pSld == NULL)
		return pSld;
	
	pSld->hdr.ID      = ID;									// unique id assigned for referencing
	pSld->hdr.pNxtObj = NULL;
	pSld->hdr.type    = OBJ_SLIDER;               			// set object type
	
	pSld->hdr.left    = left; 	    						// left and right should be equal when oriented vertically
	pSld->hdr.top     = top;								// top and bottom should be equal when oriented horizontally
	pSld->hdr.right   = right;   		    		 
	pSld->hdr.bottom  = bottom;
	pSld->hdr.state   = state;
	  
	// Parameters in the user defined range system (pos, page and range)
	pSld->range   = range;              				// range of the slider movement (always measured from 0 to range)
														// 0 refers to pSld->minPos and 
														// range refers to pSld->maxpos where: minPos and maxPos are
														// the coordinate equivalent of 0 and range value
	pSld->page    = page;								// set the resolution
	pSld->pos     = pos;								// set the initial position
	
	// calculate the thumb width and height
	pSld->thWidth = SldGetWidth(pSld);	
	pSld->thHeight = SldGetHeight(pSld);	

	// Set the color scheme to be used
	if (pScheme == NULL)
		pSld->hdr.pGolScheme = _pDefaultGolScheme;          // use default scheme
	else 	
		pSld->hdr.pGolScheme = (GOL_SCHEME *)pScheme;       // user defined scheme
		
	GOLAddObject((OBJ_HEADER*) pSld);	                // add the new object to the current list
	return pSld;
}

/*********************************************************************
* Function: SHORT SldSetThumbSize(SLIDER *pSld, SHORT high, SHORT low)
*
* Notes: An INTERNAL function used to compute for the width or 
*        height of the thumb. This function is created to save
*        code size. This function is called only to dynamically
*        compute for the thumb size. Used only when slider is 
* 		 type Scrollbar. Parameter are defined as:
*		 pSld - pointer to the object
*        high - higher value to be used
*        low  - lower value to be used
*
********************************************************************/
SHORT SldSetThumbSize(SLIDER *pSld, SHORT high, SHORT low)
{
	WORD temp;

	temp = (pSld->range/pSld->page);
	temp = (high - low)/temp;

	// when size is less than half of emboss size, set the
	// size to half the emboss size. This is to make sure 
	// thumb will always have a size.
	if (temp < (GOL_EMBOSS_SIZE<<1))
		temp = (GOL_EMBOSS_SIZE<<1);

	return (SHORT)temp;
}

/*********************************************************************
* Function: WORD SldGetWidth(SLIDER *pSld)
*
* Notes: An INTERNAL function that computes for the width  
*        of the thumb. This function is created to save
*        code size. This function is called only to dynamically
*        compute for the thumb size. 
*
********************************************************************/
WORD SldGetWidth(SLIDER *pSld)
{
	WORD temp;
	
	/*
		Calculating the width is dependent on the mode type.
		If type Scrollbar, width is dependent on the ratio of the
		page/range = width/max-min (see SetThumbSize())
		if type is Slider, width is dependent on height*3/8
		
		When horizontal width is dynamic, height is contant.
	
	*/
	
	if (GetState(pSld, SLD_VERTICAL)) {
		temp = pSld->hdr.right - pSld->hdr.left;
		if (GetState(pSld, SLD_SCROLLBAR)) {
			temp = temp-(GOL_EMBOSS_SIZE<<1); 
		}
		else {
			temp = temp-(GOL_EMBOSS_SIZE<<1)-2; 
		}
	}
	else {
		if (GetState(pSld, SLD_SCROLLBAR)) {
			temp = SldSetThumbSize(pSld, pSld->hdr.right, pSld->hdr.left);
		}
		else {
			temp = (((pSld->hdr.bottom-pSld->hdr.top)-(GOL_EMBOSS_SIZE << 1)-2)*3)>>3;
		}
	}
	// to avoid calculations of dividing by two, we store half the width value
	return temp>>1;
		
	
}	

/*********************************************************************
* Function: WORD SldGetHeight(SLIDER *pSld)
*
* Notes: An INTERNAL function that computes for the height  
*        of the thumb. This function is created to save
*        code size. This function is called only to dynamically
*        compute for the thumb size.
*
********************************************************************/
WORD SldGetHeight(SLIDER *pSld)
{
	WORD temp;

	/*
		Calculating the height is dependent on the mode type.
		If type Scrollbar, width is dependent on the ratio of the
		page/range = width/max-min (see SetThumbSize())
		if type is Slider, width is dependent on width*3/8
	
		When vertical height is dynamic, width is contant.
	*/
	
	if (GetState(pSld, SLD_VERTICAL)) {
		if (GetState(pSld, SLD_SCROLLBAR)) {
			temp = SldSetThumbSize(pSld, pSld->hdr.bottom, pSld->hdr.top); 
		}
		else {
			temp = (((pSld->hdr.right-pSld->hdr.left)-(GOL_EMBOSS_SIZE<<1)-2)*3)>>3; 
		}
	}
	else {
		temp = pSld->hdr.bottom - pSld->hdr.top;
		if (GetState(pSld, SLD_SCROLLBAR)) {
			temp = temp-(GOL_EMBOSS_SIZE<<1);
		}
		else {
			temp = temp-(GOL_EMBOSS_SIZE<<1)-2;
		}
	}
	// to avoid calculations of dividing by two, we store half the height value
	return temp>>1;
}	

/*********************************************************************
* Function: void SldGetMinMaxPos(SLIDER *pSld, WORD *min, WORD *max)
*
* Notes:  An INTERNAL function that computes for the minimum
*         and maximum pixel position in the screen. This function is 
*         created to save code size. Used to define the minimum 
*         & maximum position of the thumb when sliding. Parameters
*		  used are defined as:
*		  pSld - pointer to the object
*         min  - pointer to the minimum variable
*         max  - pointer to the maximum variable
*
********************************************************************/
void SldGetMinMaxPos(SLIDER *pSld, WORD *min, WORD *max)
{ 
	WORD temp;

	// calculate maximum and minimum position	
	if (GetState(pSld, SLD_VERTICAL)) {
		temp = pSld->thHeight+GOL_EMBOSS_SIZE;
		*min = pSld->hdr.top+temp; 
		*max = pSld->hdr.bottom-temp; 
	}
	else {
		temp = pSld->thWidth+GOL_EMBOSS_SIZE;	
		*min = pSld->hdr.left+temp; 
		*max = pSld->hdr.right-temp; 
	}

	// for aestetics.
	if (!GetState(pSld, SLD_SCROLLBAR)) {
		*min = *min+2;
		*max = *max-2;
	}
}

/*********************************************************************
* Function: void SldSetRange(SLIDER *pSld, SHORT newRange)
*
* Notes:  Sets the new range value of the slider or scrollbar.
*         Object must be redrawn after this function is called to 
*         reflect the changes to the object.
*
********************************************************************/
void SldSetRange(SLIDER *pSld, SHORT newRange) 
{
	WORD  newPos;
	DWORD_VAL dTemp;

	// this checks for limits of the range (minimum is 2)
	if (newRange <= 2)
		newRange = 2;
		
	if ((WORD)newRange > (WORD)0x7FFF)
		newRange = 0x7FFF;	

	dTemp.Val = newRange*pSld->pos;
	dTemp.Val = dTemp.Val/pSld->range;
	
	// get new range
	newPos = dTemp.w[0];

	// set the new range
	pSld->range = newRange; 				

	// now check the page, adjust when necessary
	// page maximum limit is range/2, minimum is 1
	if (pSld->page > ((pSld->range)>>1)) {
		if (!((pSld->range)>>1))
			pSld->page = 1;
		else	
			pSld->page = (pSld->range)>>1;
	}
	
	// calculate new thumb width and height
	pSld->thWidth = SldGetWidth(pSld);	
	pSld->thHeight = SldGetHeight(pSld);
    SldSetPos(pSld, newPos);
}

/*********************************************************************
* Function: void SldSetPage(SLIDER *pSld, WORD newPage) 
*
* Notes: Sets the new page value of the slider or scrollbar.
*        The page maximum limit is range/2, minimum is 1
*
********************************************************************/
void SldSetPage(SLIDER *pSld, WORD newPage) 
{
	if (newPage < 1)
		newPage = 1;
	else if (newPage > ((pSld->range)>>1))
		newPage = (pSld->range)>>1;
	pSld->page = newPage;

	// calculate new thumb width and height
	pSld->thWidth = SldGetWidth(pSld);	
	pSld->thHeight = SldGetHeight(pSld);
}

/*********************************************************************
* Function: SldSetPos(SLIDER *pSld, SHORT newPos)
*
* Notes: Sets the thumb to the new position. Checking is first 
*        preformed if the new position is within the range (0 to range)
*        of the slider. Object must be redrawn after this function is called to 
*        reflect the changes to the object.
*
********************************************************************/
void SldSetPos(SLIDER *pSld, SHORT newPos)
{
	WORD minPos, maxPos, relPos;
	DWORD_VAL dTemp;
	
	// get minimum and maximum positions
	SldGetMinMaxPos(pSld, &minPos, &maxPos);
	dTemp.Val = 0;

#ifndef SLD_INVERT_VERTICAL
	
	// check if the new value is still in range
	if (newPos <= 0) {
		pSld->pos = 0;									// set to zero in range domain
		if (GetState(pSld, SLD_VERTICAL)) {				// min and max in vertical is inverted
	    	pSld->currPos = maxPos;						// minimum position is the bottom position in 
	    }												// coordinate domain
	    else
	    	pSld->currPos = minPos;						// minimum is left most position in coordinate domain
	}	
	else if (newPos >= pSld->range) {					
		pSld->pos = pSld->range;						// set to maximum value in range domain
		if (GetState(pSld, SLD_VERTICAL)) {				// min and max in vertical is inverted
	    	pSld->currPos = minPos;						// maximum position is the top position in
	    }												// coordinate domain
	    else
	    	pSld->currPos = maxPos;						// maximum is right most position in coordinate domain
	}
	else {
		pSld->pos = newPos;								// get new position in range domain
		dTemp.w[1] = newPos;
		dTemp.Val = dTemp.Val/pSld->range;
		dTemp.Val = (maxPos-minPos)*dTemp.Val;
		// set current position in coordinate domain
		relPos = dTemp.w[1] + minPos;

		if (GetState(pSld, SLD_VERTICAL)) {				// test if we need to transform min and max position 
			pSld->currPos = maxPos - (relPos - minPos); // min and max position is swapped in coordinate domain
		}	
		else
			pSld->currPos = relPos;						// use position
	}

#else	

	// check if the new value is still in range
	if (newPos <= 0) {
		pSld->pos = 0;									// set to zero in range domain
	    pSld->currPos = minPos;							// set to minimum in coordinate domain
	}	
	else if (newPos >= pSld->range) {
		pSld->pos = pSld->range;						// set to maximum value in range domain
	    pSld->currPos = maxPos;							// set to minimum in coordinate domain
	}
	else {
		pSld->pos = newPos;								// get new position in range domain
		dTemp.w[1] = newPos;
		dTemp.Val = dTemp.Val/pSld->range;
		dTemp.Val = (maxPos-minPos)*dTemp.Val;
		// set current position in coordinate domain
		pSld->currPos = dTemp.w[1] + minPos;
	}	
#endif // ifndef SLD_INVERT_VERTICAL
}

/*********************************************************************
* Function: void SldMsgDefault(WORD translatedMsg, SLIDER* pSld, 
*							   GOL_MSG* pMsg)
*
* Notes: This the default operation to change the state of the button.
*		 Called inside GOLMsg() when GOLMsgCallback() returns a 1.
*
********************************************************************/
void SldMsgDefault(WORD translatedMsg, SLIDER* pSld, GOL_MSG* pMsg)
{
#ifdef  USE_TOUCHSCREEN

WORD  newPos, minPos, maxPos;
DWORD_VAL dTemp;

#ifdef  USE_FOCUS

    if(pMsg->type == TYPE_TOUCHSCREEN){
    	if(!GetState(pSld,SLD_FOCUSED)){
        	GOLSetFocus((OBJ_HEADER*)pSld);
        }
    }
    
#endif // USE_FOCUS

	// get the min and max positions
	SldGetMinMaxPos(pSld, &minPos, &maxPos);

    if(pMsg->type == TYPE_TOUCHSCREEN){
	    
	    if((translatedMsg == SLD_MSG_DEC) || (translatedMsg == SLD_MSG_INC)) {

			// newPos in this context is used in the coordinate domain
	        if (!GetState(pSld, SLD_VERTICAL)){				// check if Horizontal or Vertical orientation
	       	    if (pMsg->param1 <= minPos) {				// Horizontal orientation: test x position	
	                newPos = minPos;						// beyond minimum, use min position
	            } else if ( pMsg->param1 >= maxPos) {
		            newPos = maxPos;						// beyond maximum, use max position
		        }    
		        else{
	                newPos =  pMsg->param1;					// within range: use x position given
	            }  
	        }
		    else {
	       	    if (pMsg->param2 <= minPos) {				// Vertical orientation: test y position
	                newPos = minPos;						// beyond minimum, use min position
	            } else if ( pMsg->param2 >= maxPos) {
		            newPos = maxPos;						// beyond maximum, use max position
	            } else{
	                newPos =  pMsg->param2;					// within range: use y position given
	            }
	        }
	        
	        if (newPos != pSld->currPos) {					// check if we need to redraw thumb

	        	// yes redraw is needed, translate newPos into range domain
				// first get new position in range domain
				dTemp.Val = (DWORD)(newPos-minPos)*(DWORD)pSld->range;	
				dTemp.Val = dTemp.Val/(maxPos-minPos);
	        	newPos = dTemp.w[0];
	        	
	#ifndef SLD_INVERT_VERTICAL								
				
				if (GetState(pSld, SLD_VERTICAL)) {			// check if we need to swap min and max in vertical
					newPos = pSld->range - newPos;			// min and max is swapped in vertical orientation
				}											 
	#endif			
	        	SldSetPos(pSld, newPos);					// set to new position	
			    SetState(pSld, SLD_DRAW_THUMB); 			// redraw the thumb only
	        }	
	        else
	        	return;	
        } else
        	return;	
    }

#endif // USE_TOUCHSCREEN
    
#ifdef  USE_KEYBOARD

    if(pMsg->type == TYPE_KEYBOARD){					// for keyboard
        if(translatedMsg == SLD_MSG_INC){
	        SldIncPos(pSld);							// increment is requested
        }else{
	        SldDecPos(pSld);							// decrement is requested
        }
	    SetState(pSld, SLD_DRAW_THUMB); 			    // redraw the thumb only
    }
#endif // USE_KEYBOARD

}

/*********************************************************************
* Function: WORD SldTranslateMsg(SLIDER *pSld, GOL_MSG *pMsg)
*
* Notes: Evaluates the message if the object will be affected by the 
*		 message or not.
*
********************************************************************/
WORD SldTranslateMsg(SLIDER *pSld, GOL_MSG *pMsg)
{
	// Evaluate if the message is for the slider
    // Check if disabled first
	if (GetState(pSld,SLD_DISABLED))
		return OBJ_MSG_INVALID;

#ifdef USE_TOUCHSCREEN

    if(pMsg->type == TYPE_TOUCHSCREEN) {
		// Check if it falls to the left or right of the center of the thumb's face
		if((pMsg->uiEvent == EVENT_PRESS) || (pMsg->uiEvent == EVENT_MOVE)) {

			if ((pSld->hdr.left     < pMsg->param1) &&
                (pSld->hdr.right    > pMsg->param1) &&
	            (pSld->hdr.top      < pMsg->param2) &&
    	        (pSld->hdr.bottom   > pMsg->param2) ) {
	    		
	    		if (GetState(pSld, SLD_VERTICAL)) 
	    			if (pSld->currPos < pMsg->param2)
	    	    		return SLD_MSG_INC;
	    	    	else	
	    	    		return SLD_MSG_DEC;
	    	    else		
	    			if (pSld->currPos < pMsg->param1)
	    	    		return SLD_MSG_INC;
	    	    	else	
	    	    		return SLD_MSG_DEC;
		    }
	    } // end of if((pMsg->uiEvent == EVENT_PRESS) || (pMsg->uiEvent == EVENT_MOVE))

   	    return OBJ_MSG_INVALID;	

    } // end of if(pMsg->type == TYPE_TOUCHSCREEN
#endif

#ifdef USE_KEYBOARD

    if(pMsg->type == TYPE_KEYBOARD){
	    if(pMsg->param1 == pSld->hdr.ID){

            if(pMsg->uiEvent == EVENT_KEYSCAN){

                if( (pMsg->param2 == SCAN_LEFT_PRESSED) ||
                    (pMsg->param2 == SCAN_UP_PRESSED) ){
                    return SLD_MSG_INC;
                }

                if( (pMsg->param2 == SCAN_RIGHT_PRESSED) ||
                    (pMsg->param2 == SCAN_DOWN_PRESSED) )
                    return SLD_MSG_DEC;

            }

        }
    }

#endif

   	return OBJ_MSG_INVALID;	
}

/*********************************************************************
* Function: WORD SldDraw(SLIDER *pSld)
*
* Notes: This is the state machine to draw the slider or scrollbar.
*
********************************************************************/
WORD SldDraw(SLIDER *pSld)
{
typedef enum {
	SLD_STATE_IDLE,
	SLD_STATE_PANEL,
    SLD_STATE_THUMBPATH1,
	SLD_STATE_THUMBPATH2, 
	SLD_STATE_CLEARTHUMB,
	SLD_STATE_REDRAWPATH1,
    SLD_STATE_REDRAWPATH2,
	SLD_STATE_THUMB,
	SLD_STATE_THUMBPANEL,
	SLD_STATE_FOCUS
} SLD_DRAW_STATES;	
	
WORD colorTemp = 0;

static SLD_DRAW_STATES state = SLD_STATE_IDLE;	
static WORD left, top, right, bottom;
static WORD midPoint, thWidth, thHeight;
static WORD minPos, maxPos;

	
    if(IsDeviceBusy())
        return 0;

    switch(state){
	    
        case SLD_STATE_IDLE:
        
        	if (GetState(pSld, SLD_HIDE)) {
	            SetColor(pSld->hdr.pGolScheme->CommonBkColor);		// set to common BK Color
        		Bar(pSld->hdr.left, pSld->hdr.top, pSld->hdr.right, pSld->hdr.bottom);
        		return 1;
        	}	

            if(!GetState(pSld,SLD_DISABLED)){
	            colorTemp = pSld->hdr.pGolScheme->Color0;			// select enabled color
	        }else{    
	            colorTemp = pSld->hdr.pGolScheme->ColorDisabled;	// select disabled color
	        }

			SldGetMinMaxPos(pSld, &minPos, &maxPos);
			
			midPoint = GetState(pSld, SLD_VERTICAL) ? (pSld->hdr.left + pSld->hdr.right)>>1  :     \
													  (pSld->hdr.top + pSld->hdr.bottom)>>1;	

			// calculate the thumb width and height Actually gets the half value
			// (see calculation of width and height) SldGetWidth() and SldGetHeight()
			thWidth = pSld->thWidth;							// gets half the width
			thHeight = pSld->thHeight;							// gets half the height

			SetLineThickness(NORMAL_LINE);
			SetLineType(SOLID_LINE);			
		    if (GetState(pSld,SLD_DRAW)) {						// draw the panel for the slider	
			    
			    // modify the color setting if scroll bar mode or slider mode
	            GOLPanelDraw(pSld->hdr.left,					
	            			 pSld->hdr.top,
	            			 pSld->hdr.right,
	            			 pSld->hdr.bottom, 0,
   	                         colorTemp,
       	                     (GetState(pSld, SLD_SCROLLBAR)) ?  pSld->hdr.pGolScheme->EmbossDkColor :  \
       	                     									pSld->hdr.pGolScheme->EmbossLtColor,
       	                     (GetState(pSld, SLD_SCROLLBAR)) ?  pSld->hdr.pGolScheme->EmbossLtColor :  \
       	                     									pSld->hdr.pGolScheme->EmbossDkColor,
               	             NULL, 
							 GOL_EMBOSS_SIZE);
							 
				// initialize current and previous position   
				SldSetPos(pSld, pSld->pos);
				pSld->prevPos = pSld->currPos;				
               	             
	            state = SLD_STATE_PANEL;
            }else{  	             							// we do not need to draw the whole object
	           	state = SLD_STATE_CLEARTHUMB;					// go to thumb drawing 
               	goto sld_state_clearthumb;
            }

	    case SLD_STATE_PANEL:

            if(!GOLPanelDrawTsk())							    // draw the panel of the slider
                return 0;
            if (GetState(pSld, SLD_SCROLLBAR)) {				// check if slider or scroll bar    
	        	state = SLD_STATE_THUMB;					    // scrollbar: go directly to thumb drawing 
	        	goto sld_state_thumb;							// thumb path is not drawn in scrollbar
	        } else {
	        	state = SLD_STATE_THUMBPATH1;					// slider: draw thumb path next
	        }
        
	    case SLD_STATE_THUMBPATH1:

			SetColor(BLACK);    								// draw the black line
    		if (!GetState(pSld, SLD_VERTICAL)) {
    			Line(minPos, midPoint, maxPos, midPoint);		
    		}	
    		else {
    			Line(midPoint, minPos, midPoint, maxPos);
			}
			
	        state = SLD_STATE_THUMBPATH2;

	    case SLD_STATE_THUMBPATH2:

            if(IsDeviceBusy())
   	            return 0;    

			SetColor(WHITE);    								// draw the white line
    		if (!GetState(pSld, SLD_VERTICAL)) { 
    			Line(minPos, midPoint+1, maxPos, midPoint+1);
			}
    		else {
    			Line(midPoint+1, minPos, midPoint+1, maxPos);
			}

 			if (GetState(pSld,SLD_DRAW)) {						// if drawing the whole slider
	            state = SLD_STATE_THUMB;						// go straight to drawing the thumb
            	goto sld_state_thumb;
            }	
	        else 												// if just drawing the thumb
	        	state = SLD_STATE_CLEARTHUMB;					// go to state to remove current position

	        
	    case SLD_STATE_CLEARTHUMB:								// this removes the current thumb 

sld_state_clearthumb:
            if(IsDeviceBusy())
   	            return 0;    
   	            
			if (!GetState(pSld, SLD_DRAW_THUMB)) {				// SLD_DRAW_THUMB is only set when
				state = SLD_STATE_FOCUS;						// object type is SLIDER
				goto sld_state_focus;
			}	
			
            SetColor(colorTemp);

   	        // Remove the current thumb by drawing a bar with background color    
	    	if (!GetState(pSld, SLD_VERTICAL)) { 
				Bar(pSld->prevPos-thWidth, midPoint-thHeight, 
					pSld->prevPos+thWidth, midPoint+thHeight);	            
			}
			else {
				Bar(midPoint-thWidth, pSld->prevPos-thHeight, 
					midPoint+thWidth, pSld->prevPos+thHeight);	            
			}	
			if (!GetState(pSld, SLD_SCROLLBAR)) {				// check if slider or scroll bar    
				state = SLD_STATE_REDRAWPATH1;
	        } else {
		        state = SLD_STATE_THUMB;					    // go directly to thumb drawing 
	        	goto sld_state_thumb;							// thumb path is not drawn in scrollbar
		    }

		case SLD_STATE_REDRAWPATH1:								// redraws the lines that it covered

            if(IsDeviceBusy())
                return 0;  

			SetColor(BLACK);									// redraw the black line first
			// Check if the redraw area exceeds the actual dimension. This will 
	    	// adjust the redrawing area to just within the parameters
            if (!GetState(pSld, SLD_VERTICAL)) {	    		
    			if (minPos+thWidth > pSld->prevPos)
    				left = minPos;
    			else	
    				left = pSld->prevPos-thWidth;
    			if (maxPos-thWidth < pSld->prevPos)
    				right = maxPos;
    			else	
    				right = pSld->prevPos+thWidth;
    			Line(left, midPoint, right, midPoint);
    		}	
    		else {
    			if (minPos+thHeight > pSld->prevPos)
    				top = minPos;
    			else	
    				top = pSld->prevPos-thHeight;
    			if (maxPos-thHeight < pSld->prevPos)
    				bottom = maxPos;
    			else	
    				bottom = pSld->prevPos+thHeight;
	    		Line(midPoint, top, midPoint, bottom);
	    	}
            state = SLD_STATE_REDRAWPATH2;

        case SLD_STATE_REDRAWPATH2:
        
            if(IsDeviceBusy())
                return 0;    
			SetColor(WHITE);									// redraw the white line next
    		if (!GetState(pSld, SLD_VERTICAL))
    			Line(left, midPoint+1, right, midPoint+1);
    		else	
    			Line(midPoint+1, top, midPoint+1, bottom);
            state = SLD_STATE_THUMB;
				
        case SLD_STATE_THUMB:
sld_state_thumb:        
            if(IsDeviceBusy())
                return 0;    
    		if (!GetState(pSld, SLD_VERTICAL)) {				// Draw the slider thumb based on the 
	    														// current position
	    		left   = pSld->currPos-thWidth;
	    		top    = midPoint-thHeight;
	    		right  = pSld->currPos+thWidth;
	    		bottom = midPoint+thHeight;
	    	}
	    	else {
	    		left   = midPoint-thWidth;
	    		top    = pSld->currPos-thHeight;
	            right  = midPoint+thWidth;
	            bottom = pSld->currPos+thHeight;
	    	}	
    	
	        GOLPanelDraw(left, top, right, bottom, 0,			// set the parameters of the thumb	
   	                     colorTemp,
       	                 pSld->hdr.pGolScheme->EmbossLtColor,
           	             pSld->hdr.pGolScheme->EmbossDkColor,
               	         NULL, 
   						 (GOL_EMBOSS_SIZE-1) ? GOL_EMBOSS_SIZE-1:1);

	        state = SLD_STATE_THUMBPANEL;
	    
	    case SLD_STATE_THUMBPANEL:
	    
            if(!GOLPanelDrawTsk())								// draw the panel of the thumb
                return 0;
	
			pSld->prevPos = pSld->currPos; 						// record the current position as previous

            if (GetState(pSld, SLD_SCROLLBAR)) {				// check if scroll bar focus is not used
	       		state = SLD_STATE_IDLE;							// go back to idle state
    	   		return 1;
    	   	}
    	   	
	        if(!GetState(pSld, SLD_DRAW_FOCUS)) { 	
	       		state = SLD_STATE_IDLE;
    	   		return 1;
    	   	}	
          	state = SLD_STATE_FOCUS;

	    case SLD_STATE_FOCUS:

sld_state_focus:
			if (!GetState(pSld, SLD_SCROLLBAR)) {				// do not draw focus when in scroll bar mode
	            SetLineType(FOCUS_LINE);
	            if(GetState(pSld, SLD_FOCUSED)) {	
	                SetColor(pSld->hdr.pGolScheme->TextColor0);		// draw the focus box
	            }    
	            else {    
	                SetColor(colorTemp); 						// remove the focus box, colorTemp
	            }
	   		    Rectangle(pSld->hdr.left+GOL_EMBOSS_SIZE, 
	   		    		  pSld->hdr.top+GOL_EMBOSS_SIZE, 
	   		    		  pSld->hdr.right-GOL_EMBOSS_SIZE, 
	   		    		  pSld->hdr.bottom-GOL_EMBOSS_SIZE);
	
	      	    SetLineType(SOLID_LINE);						// reset line type
	      	}
            state = SLD_STATE_IDLE;								// set state to idle
            return 1;											// return as done
	}    	
	return 1;
	
}

#endif // USE_SLIDER
