?? slider.c
字號:
//*****************************************************************************
//
// slider.c - A simple slider widget class.
//
// Copyright (c) 2008-2010 Texas Instruments Incorporated. All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 5821 of the Stellaris Graphics Library.
//
//*****************************************************************************
#include "driverlib/debug.h"
#include "grlib/grlib.h"
#include "grlib/widget.h"
#include "grlib/slider.h"
//*****************************************************************************
//
//! \addtogroup slider_api
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
// Make sure min and max are defined.
//
//*****************************************************************************
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a, b) (((a) < (b)) ? (b) : (a))
#endif
//*****************************************************************************
//
// Converts a slider value to a position on the display.
//
// \param pSlider is a pointer to the slider widget for which the conversion is
// being requested.
// \param lValue is the slider value that is to be converted to a position.
//
// Converts a value within the range represented by a slider into a position
// along the slider control. The function converts taking into account the
// slider position and style as well as its range.
//
// \return Returns the screen position (x coordinate for horizontal sliders or
// y coordinate for vertical ones) that represents the value passed.
//
//*****************************************************************************
static short
SliderValueToPosition(tSliderWidget *pSlider, long lValue)
{
unsigned short usSize;
long lRange;
long lPos;
//
// First look for the trivial cases. To ensure correct display and remove
// artifacts caused by rounding errors, we specifically catch the cases
// where the value provided is at either end of the slider range. In these
// cases we return values that are outside the actual widget rectangle.
// This is detected while drawing so that the relevant bars fill the full
// area and don't leave single pixel lines at either end even when the
// slider is at full scale. These cases also catch out-of-range values
// and peg them at one end of the range or the other.
//
// First check for values at the top of the range.
//
if(lValue >= pSlider->lMax)
{
//
// Is this a vertical slider?
//
if(pSlider->ulStyle & SL_STYLE_VERTICAL)
{
//
// Vertical slider case. Return the top position.
//
lPos = pSlider->sBase.sPosition.sYMin - 1;
//
// Adjust by 1 to move past the border if this widget has one.
//
if(pSlider->ulStyle & SL_STYLE_OUTLINE)
{
lPos++;
}
}
else
{
//
// Horizontal slider case. Return the rightmost position.
//
lPos = pSlider->sBase.sPosition.sXMax + 1;
//
// Adjust by 1 to move past the border if this widget has one.
//
if(pSlider->ulStyle & SL_STYLE_OUTLINE)
{
lPos--;
}
}
return((short)lPos);
}
//
// Now look at the bottom end of the range.
//
if(lValue <= pSlider->lMin)
{
//
// Is this a vertical slider?
//
if(pSlider->ulStyle & SL_STYLE_VERTICAL)
{
//
// Vertical slider case. Return the bottom position.
//
lPos = pSlider->sBase.sPosition.sYMax + 1;
//
// Adjust by 1 to move past the border if this widget has one.
//
if(pSlider->ulStyle & SL_STYLE_OUTLINE)
{
lPos--;
}
}
else
{
//
// Horizontal slider case. Return the leftmost position.
//
lPos = pSlider->sBase.sPosition.sXMin - 1;
//
// Adjust by 1 to move past the border if this widget has one.
//
if(pSlider->ulStyle & SL_STYLE_OUTLINE)
{
lPos++;
}
}
return((short)lPos);
}
//
// What is the length of the whole slider?
//
if(pSlider->ulStyle & SL_STYLE_VERTICAL)
{
//
// Vertical slider case.
//
usSize = (pSlider->sBase.sPosition.sYMax -
pSlider->sBase.sPosition.sYMin) + 1;
}
else
{
//
// Horizontal slider case.
//
usSize = (pSlider->sBase.sPosition.sXMax -
pSlider->sBase.sPosition.sXMin) + 1;
}
//
// Adjust the range if the slider has an outline (which removes 2 pixels).
//
if(pSlider->ulStyle & SL_STYLE_OUTLINE)
{
usSize -= 2;
}
//
// Determine the range of the slider (the number of individual integers
// represented by the widget).
//
lRange = (pSlider->lMax - pSlider->lMin) + 1;
//
// Now we can determine the relevant position relative to the start of the
// slider.
//
lPos = ((lValue * (long)usSize) / lRange);
//
// Clip the calculated position to the valid range based on the slider
// size.
//
lPos = max(lPos, 0);
lPos = min(lPos, (long)usSize - 1);
//
// Adjust for the position of the widget relative to the screen origin.
//
if(pSlider->ulStyle & SL_STYLE_VERTICAL)
{
//
// Vertical case - adjust the Y coordinate.
//
lPos = pSlider->sBase.sPosition.sYMax - lPos;
}
else
{
//
// Horizontal case - adjust the X coordinate.
//
lPos += pSlider->sBase.sPosition.sXMin;
}
//
// If the widget has an outline, make sure to adjust for this too.
//
lPos += ((pSlider->ulStyle & SL_STYLE_OUTLINE) ? 1 : 0);
//
// Convert to the expected return type and hand the caller the final
// value.
//
return((short)lPos);
}
//*****************************************************************************
//
// Converts a slider position to a value within its range.
//
// \param pSlider is a pointer to the slider widget for which the conversion is
// being requested.
// \param usPos is a position within the slider. This is an x coordinate for
// a horizontal slider or a y coordinate for a vertical one. In both cases,
// the position is relative to the display origin.
//
// Converts a screen position into a value within the current range of the
// slider. The function converts taking into account the slider position and
// style as well as its range.
//
// \return Returns the slider value represented by the position passed.
//
//*****************************************************************************
static long
SliderPositionToValue(tSliderWidget *pSlider, short sPos)
{
short sMax;
short sMin;
long lValue;
//
// Determine the bounds of the control on the display.
//
if(pSlider->ulStyle & SL_STYLE_VERTICAL)
{
sMax = pSlider->sBase.sPosition.sYMax;
sMin = pSlider->sBase.sPosition.sYMin;
}
else
{
sMax = pSlider->sBase.sPosition.sXMax;
sMin = pSlider->sBase.sPosition.sXMin;
}
//
// Adjust for the outline if present.
//
if(pSlider->ulStyle & SL_STYLE_OUTLINE)
{
sMax--;
sMin--;
}
//
// If the control is too narrow, this is a bug but handle it gracefully
// rather than throwing a divide by zero later.
//
ASSERT(sMax > sMin);
if(sMax <= sMin)
{
return(pSlider->lMin);
}
//
// Clip the supplied position to the extent of the widget.
//
sPos = min(sMax, sPos);
sPos = max(sMin, sPos);
//
// Adjust the position to make it relative to the start of the slider.
//
if(pSlider->ulStyle & SL_STYLE_VERTICAL)
{
sPos = sMax - sPos;
}
else
{
sPos -= sMin;
}
//
// Calculate the value represented by this position.
//
lValue = ((long)sPos * ((pSlider->lMax - pSlider->lMin) + 1)) /
(long)((sMax - sMin) + 1);
//
// Adjust for the bottom of the value range.
//
lValue += pSlider->lMin;
//
// Hand the conversion result back to the caller.
//
return(lValue);
}
//*****************************************************************************
//
//! Draws a slider.
//!
//! \param pWidget is a pointer to the slider widget to be drawn.
//! \param pDirty is the subrectangle of the widget which is to be redrawn.
//! This is expressed in screen coordinates.
//!
//! This function draws a slider on the display. This is called in response to
//! a \b #WIDGET_MSG_PAINT message or when the slider position changes.
//!
//! \return None.
//
//*****************************************************************************
static void
SliderPaint(tWidget *pWidget, tRectangle *pDirty)
{
tRectangle sClipRect, sValueRect, sEmptyRect, sActiveClip;
tSliderWidget *pSlider;
tContext sCtx;
long lX, lY, bIntersect;
short sPos;
//
// Check the arguments.
//
ASSERT(pWidget);
//
// Convert the generic widget pointer into a slider widget pointer.
//
pSlider = (tSliderWidget *)pWidget;
//
// Initialize a drawing context.
//
GrContextInit(&sCtx, pWidget->pDisplay);
//
// Initialize the clipping region based on the update rectangle passed.
//
bIntersect = GrRectIntersectGet(pDirty, &(pSlider->sBase.sPosition),
&sClipRect);
GrContextClipRegionSet(&sCtx, &sClipRect);
//
// Draw the control outline if necessary.
//
if(pSlider->ulStyle & SL_STYLE_OUTLINE)
{
//
// Outline the slider with the outline color.
//
GrContextForegroundSet(&sCtx, pSlider->ulOutlineColor);
GrRectDraw(&sCtx, &(pWidget->sPosition));
//
// Adjust the clipping rectangle to prevent the outline from being
// corrupted later.
//
if(sClipRect.sXMin == pWidget->sPosition.sXMin)
{
sClipRect.sXMin++;
}
if(sClipRect.sYMin == pWidget->sPosition.sYMin)
{
sClipRect.sYMin++;
}
if(sClipRect.sXMax == pWidget->sPosition.sXMax)
{
sClipRect.sXMax--;
}
if(sClipRect.sYMax == pWidget->sPosition.sYMax)
{
sClipRect.sYMax--;
}
}
//
// Determine the position associated with the current slider value.
//
sPos = SliderValueToPosition(pSlider, pSlider->lValue);
//
// Remember this so that the dirty rectangle code in the click handler
// draws the correct thing the first time it is called.
//
pSlider->sPos = sPos;
//
// Determine the rectangles for the active and empty portions of the
// widget.
//
if(pSlider->ulStyle & SL_STYLE_VERTICAL)
{
//
// Determine the rectangle corresponding to the bottom (value) portion
// of the slider.
//
sValueRect.sXMin = pWidget->sPosition.sXMin;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -