448 lines
11 KiB
C
448 lines
11 KiB
C
/*
|
|
* Slider.c
|
|
*
|
|
* Slide bar widget definitions.
|
|
*/
|
|
|
|
|
|
#include "widget.h"
|
|
#include "widgint.h"
|
|
#include "slider.h"
|
|
// FIXME Direct iVis implementation include!
|
|
#include "lib/ivis_opengl/vid.h"
|
|
|
|
/* The widget heaps */
|
|
OBJ_HEAP *psSldHeap;
|
|
BOOL DragEnabled = TRUE;
|
|
|
|
void sliderEnableDrag(BOOL Enable)
|
|
{
|
|
DragEnabled = Enable;
|
|
}
|
|
|
|
/* Create a slider widget data structure */
|
|
BOOL sliderCreate(W_SLIDER **ppsWidget, W_SLDINIT *psInit)
|
|
{
|
|
if (psInit->style & ~(WBAR_PLAIN | WIDG_HIDDEN))
|
|
{
|
|
ASSERT((FALSE, "sliderCreate: Unknown style"));
|
|
return FALSE;
|
|
}
|
|
|
|
if (psInit->orientation < WSLD_LEFT || psInit->orientation > WSLD_BOTTOM)
|
|
{
|
|
ASSERT((FALSE, "sliderCreate: Unknown orientation"));
|
|
return FALSE;
|
|
}
|
|
|
|
if (((psInit->orientation == WSLD_LEFT || psInit->orientation == WSLD_RIGHT) &&
|
|
psInit->numStops > (psInit->width - psInit->barSize)) ||
|
|
((psInit->orientation == WSLD_TOP || psInit->orientation == WSLD_BOTTOM) &&
|
|
psInit->numStops > (psInit->height - psInit->barSize)))
|
|
{
|
|
ASSERT((FALSE, "sliderCreate: Too many stops for slider length"));
|
|
return FALSE;
|
|
}
|
|
|
|
if (psInit->pos > psInit->numStops)
|
|
{
|
|
ASSERT((FALSE, "sliderCreate: slider position greater than stops"));
|
|
return FALSE;
|
|
}
|
|
|
|
if (((psInit->orientation == WSLD_LEFT || psInit->orientation == WSLD_RIGHT) &&
|
|
psInit->barSize > psInit->width) ||
|
|
((psInit->orientation == WSLD_TOP || psInit->orientation == WSLD_BOTTOM) &&
|
|
psInit->barSize > psInit->height))
|
|
{
|
|
ASSERT((FALSE, "sliderCreate: slider bar is larger than slider width"));
|
|
return FALSE;
|
|
}
|
|
|
|
/* Allocate the required memory */
|
|
#if W_USE_MALLOC
|
|
*ppsWidget = (W_SLIDER *)MALLOC(sizeof(W_SLIDER));
|
|
if (*ppsWidget == NULL)
|
|
#else
|
|
if (!HEAP_ALLOC(psSldHeap, (void*) ppsWidget))
|
|
#endif
|
|
{
|
|
ASSERT((FALSE, "sliderCreate: Out of memory"));
|
|
return FALSE;
|
|
}
|
|
/* Allocate the memory for the tip and copy it if necessary */
|
|
if (psInit->pTip)
|
|
{
|
|
#if W_USE_STRHEAP
|
|
if (!widgAllocCopyString(&(*ppsWidget)->pTip, psInit->pTip))
|
|
{
|
|
/* Out of memory - just carry on without the tip */
|
|
ASSERT((FALSE, "sliderCreate: Out of memory"));
|
|
(*ppsWidget)->pTip = NULL;
|
|
}
|
|
#else
|
|
(*ppsWidget)->pTip = psInit->pTip;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
(*ppsWidget)->pTip = NULL;
|
|
}
|
|
|
|
/* Initialise the structure */
|
|
(*ppsWidget)->type = WIDG_SLIDER;
|
|
(*ppsWidget)->id = psInit->id;
|
|
(*ppsWidget)->formID = psInit->formID;
|
|
(*ppsWidget)->style = psInit->style;
|
|
(*ppsWidget)->x = psInit->x;
|
|
(*ppsWidget)->y = psInit->y;
|
|
(*ppsWidget)->width = psInit->width;
|
|
(*ppsWidget)->height = psInit->height;
|
|
|
|
if (psInit->pDisplay)
|
|
{
|
|
(*ppsWidget)->display = psInit->pDisplay;
|
|
}
|
|
else
|
|
{
|
|
(*ppsWidget)->display = sliderDisplay;
|
|
}
|
|
(*ppsWidget)->callback = psInit->pCallback;
|
|
(*ppsWidget)->pUserData = psInit->pUserData;
|
|
(*ppsWidget)->UserData = psInit->UserData;
|
|
(*ppsWidget)->orientation = psInit->orientation;
|
|
(*ppsWidget)->numStops = psInit->numStops;
|
|
(*ppsWidget)->barSize = psInit->barSize;
|
|
|
|
sliderInitialise(*ppsWidget);
|
|
|
|
(*ppsWidget)->pos = psInit->pos;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Free the memory used by a slider */
|
|
void sliderFree(W_SLIDER *psWidget)
|
|
{
|
|
ASSERT((PTRVALID(psWidget, sizeof(W_SLIDER)),
|
|
"sliderFree: Invalid widget pointer"));
|
|
|
|
#if W_USE_STRHEAP
|
|
if (psWidget->pTip)
|
|
{
|
|
widgFreeString(psWidget->pTip);
|
|
}
|
|
#endif
|
|
|
|
|
|
#if W_USE_MALLOC
|
|
FREE(psWidget);
|
|
#else
|
|
HEAP_FREE(psSldHeap, psWidget);
|
|
#endif
|
|
}
|
|
|
|
|
|
/* Initialise a slider widget before running it */
|
|
void sliderInitialise(W_SLIDER *psWidget)
|
|
{
|
|
ASSERT((PTRVALID(psWidget, sizeof(W_SLIDER)),
|
|
"sliderInitialise: Invalid slider pointer"));
|
|
|
|
psWidget->state = 0;
|
|
psWidget->pos = 0;
|
|
}
|
|
|
|
|
|
/* Get the current position of a slider bar */
|
|
UDWORD widgGetSliderPos(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
ASSERT((PTRVALID(psWidget, sizeof(W_SLIDER)),
|
|
"widgGetSliderPos: couldn't find widget from id"));
|
|
if (psWidget)
|
|
{
|
|
return ((W_SLIDER *)psWidget)->pos;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Set the current position of a slider bar */
|
|
void widgSetSliderPos(W_SCREEN *psScreen, UDWORD id, UWORD pos)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
ASSERT((PTRVALID(psWidget, sizeof(W_SLIDER)),
|
|
"widgGetSliderPos: couldn't find widget from id"));
|
|
if (psWidget)
|
|
{
|
|
if (pos > ((W_SLIDER *)psWidget)->numStops)
|
|
{
|
|
((W_SLIDER *)psWidget)->pos = ((W_SLIDER *)psWidget)->numStops;
|
|
}
|
|
else
|
|
{
|
|
((W_SLIDER *)psWidget)->pos = pos;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Return the current position of the slider bar on the widget */
|
|
static void sliderGetBarBox(W_SLIDER *psSlider, SWORD *pX, SWORD *pY,
|
|
UWORD *pWidth, UWORD *pHeight)
|
|
{
|
|
switch (psSlider->orientation)
|
|
{
|
|
case WSLD_LEFT:
|
|
*pX = (SWORD)((psSlider->width - psSlider->barSize)
|
|
* psSlider->pos / psSlider->numStops);
|
|
*pY = 0;
|
|
*pWidth = psSlider->barSize;
|
|
*pHeight = psSlider->height;
|
|
break;
|
|
case WSLD_RIGHT:
|
|
*pX = (SWORD)(psSlider->width - psSlider->barSize
|
|
- (psSlider->width - psSlider->barSize)
|
|
* psSlider->pos / psSlider->numStops);
|
|
*pY = 0;
|
|
*pWidth = psSlider->barSize;
|
|
*pHeight = psSlider->height;
|
|
break;
|
|
case WSLD_TOP:
|
|
*pX = 0;
|
|
*pY = (SWORD)((psSlider->height - psSlider->barSize)
|
|
* psSlider->pos / psSlider->numStops);
|
|
*pWidth = psSlider->width;
|
|
*pHeight = psSlider->barSize;
|
|
break;
|
|
case WSLD_BOTTOM:
|
|
*pX = 0;
|
|
*pY = (SWORD)(psSlider->height - psSlider->barSize
|
|
- (psSlider->height - psSlider->barSize)
|
|
* psSlider->pos / psSlider->numStops);
|
|
*pWidth = psSlider->width;
|
|
*pHeight = psSlider->barSize;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Run a slider widget */
|
|
void sliderRun(W_SLIDER *psWidget, W_CONTEXT *psContext)
|
|
{
|
|
SDWORD mx,my;
|
|
UDWORD stopSize;
|
|
|
|
if ((psWidget->state & SLD_DRAG) && !mouseDown(MOUSE_LMB))
|
|
{
|
|
psWidget->state &= ~SLD_DRAG;
|
|
widgSetReturn((WIDGET *)psWidget);
|
|
}
|
|
else if (psWidget->state & SLD_DRAG)
|
|
{
|
|
/* Figure out where the drag box should be */
|
|
mx = psContext->mx - psWidget->x;
|
|
my = psContext->my - psWidget->y;
|
|
switch (psWidget->orientation)
|
|
{
|
|
case WSLD_LEFT:
|
|
if (mx <= psWidget->barSize/2)
|
|
{
|
|
psWidget->pos = 0;
|
|
}
|
|
else if (mx >= psWidget->width - psWidget->barSize/2)
|
|
{
|
|
psWidget->pos = psWidget->numStops;
|
|
}
|
|
else
|
|
{
|
|
/* Mouse is in the middle of the slider, calculate which stop */
|
|
stopSize = (psWidget->width - psWidget->barSize) / psWidget->numStops;
|
|
psWidget->pos = (UWORD)((mx + stopSize/2 - psWidget->barSize/2)
|
|
* psWidget->numStops
|
|
/ (psWidget->width - psWidget->barSize));
|
|
}
|
|
break;
|
|
case WSLD_RIGHT:
|
|
if (mx <= psWidget->barSize/2)
|
|
{
|
|
psWidget->pos = psWidget->numStops;
|
|
}
|
|
else if (mx >= psWidget->width - psWidget->barSize/2)
|
|
{
|
|
psWidget->pos = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Mouse is in the middle of the slider, calculate which stop */
|
|
stopSize = (psWidget->width - psWidget->barSize) / psWidget->numStops;
|
|
psWidget->pos = (UWORD)(psWidget->numStops
|
|
- (mx + stopSize/2 - psWidget->barSize/2)
|
|
* psWidget->numStops
|
|
/ (psWidget->width - psWidget->barSize));
|
|
}
|
|
break;
|
|
case WSLD_TOP:
|
|
if (my <= psWidget->barSize/2)
|
|
{
|
|
psWidget->pos = 0;
|
|
}
|
|
else if (my >= psWidget->height - psWidget->barSize/2)
|
|
{
|
|
psWidget->pos = psWidget->numStops;
|
|
}
|
|
else
|
|
{
|
|
/* Mouse is in the middle of the slider, calculate which stop */
|
|
stopSize = (psWidget->height - psWidget->barSize) / psWidget->numStops;
|
|
psWidget->pos = (UWORD)((my + stopSize/2 - psWidget->barSize/2)
|
|
* psWidget->numStops
|
|
/ (psWidget->height - psWidget->barSize));
|
|
}
|
|
break;
|
|
case WSLD_BOTTOM:
|
|
if (my <= psWidget->barSize/2)
|
|
{
|
|
psWidget->pos = psWidget->numStops;
|
|
}
|
|
else if (my >= psWidget->height - psWidget->barSize/2)
|
|
{
|
|
psWidget->pos = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Mouse is in the middle of the slider, calculate which stop */
|
|
stopSize = (psWidget->height - psWidget->barSize) / psWidget->numStops;
|
|
psWidget->pos = (UWORD)(psWidget->numStops
|
|
- (my + stopSize/2 - psWidget->barSize/2)
|
|
* psWidget->numStops
|
|
/ (psWidget->height - psWidget->barSize));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Respond to a mouse click */
|
|
void sliderClicked(W_SLIDER *psWidget, W_CONTEXT *psContext)
|
|
{
|
|
#if 0
|
|
SWORD x,y;
|
|
UWORD width,height;
|
|
SDWORD mx,my;
|
|
|
|
/* Get the slider position */
|
|
sliderGetBarBox(psWidget, &x,&y, &width,&height);
|
|
|
|
/* Did the mouse click on the slider ? */
|
|
mx = psContext->mx - psWidget->x;
|
|
my = psContext->my - psWidget->y;
|
|
#endif
|
|
if(DragEnabled) {
|
|
if (psContext->mx >= psWidget->x &&
|
|
psContext->mx <= psWidget->x + psWidget->width &&
|
|
psContext->my >= psWidget->y &&
|
|
psContext->my <= psWidget->y + psWidget->height)
|
|
{
|
|
psWidget->state |= SLD_DRAG;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Respond to a mouse up */
|
|
void sliderReleased(W_SLIDER *psWidget)
|
|
{
|
|
(void)psWidget;
|
|
}
|
|
|
|
|
|
/* Respond to a mouse moving over a slider */
|
|
void sliderHiLite(W_SLIDER *psWidget)
|
|
{
|
|
psWidget->state |= SLD_HILITE;
|
|
}
|
|
|
|
|
|
/* Respond to the mouse moving off a slider */
|
|
void sliderHiLiteLost(W_SLIDER *psWidget)
|
|
{
|
|
psWidget->state &= ~SLD_HILITE;
|
|
}
|
|
|
|
/* The slider display function */
|
|
void sliderDisplay(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset,
|
|
UDWORD *pColours)
|
|
{
|
|
W_SLIDER *psSlider;
|
|
SWORD x0,y0, x1,y1;
|
|
UWORD width,height;
|
|
|
|
psSlider = (W_SLIDER *)psWidget;
|
|
|
|
switch (psSlider->orientation)
|
|
{
|
|
case WSLD_LEFT:
|
|
case WSLD_RIGHT:
|
|
/* Draw the line */
|
|
x0 = (SWORD)(psSlider->x + xOffset + psSlider->barSize/(SWORD)2);
|
|
y0 = (SWORD)(psSlider->y + yOffset + psSlider->height/(SWORD)2);
|
|
x1 = (SWORD)(x0 + psSlider->width - psSlider->barSize);
|
|
iV_Line(x0,y0, x1,y0,*(pColours + WCOL_DARK));
|
|
iV_Line(x0,y0+1, x1,y0+1,*(pColours + WCOL_LIGHT));
|
|
|
|
/* Now Draw the bar */
|
|
sliderGetBarBox(psSlider, &x0,&y0, &width,&height);
|
|
x0 = (SWORD)(x0 + psSlider->x + xOffset);
|
|
y0 = (SWORD)(y0 + psSlider->y + yOffset);
|
|
x1 = (SWORD)(x0 + width);
|
|
y1 = (SWORD)(y0 + height);
|
|
pie_BoxFillIndex(x0,y0, x1,y1,WCOL_BKGRND);
|
|
iV_Line(x0,y0, x1,y0,*(pColours + WCOL_LIGHT));
|
|
iV_Line(x0,y0, x0,y1,*(pColours + WCOL_LIGHT));
|
|
iV_Line(x1,y0, x1,y1,*(pColours + WCOL_DARK));
|
|
iV_Line(x0,y1, x1,y1,*(pColours + WCOL_DARK));
|
|
break;
|
|
case WSLD_TOP:
|
|
case WSLD_BOTTOM:
|
|
/* Draw the line */
|
|
x0 = (SWORD)(psSlider->x + xOffset + psSlider->width/(SWORD)2);
|
|
y0 = (SWORD)(psSlider->y + yOffset + psSlider->barSize/(SWORD)2);
|
|
y1 = (SWORD)(y0 + psSlider->height - psSlider->barSize);
|
|
iV_Line(x0,y0, x0,y1,*(pColours + WCOL_DARK));
|
|
iV_Line(x0+1,y0, x0+1,y1,*(pColours + WCOL_LIGHT));
|
|
|
|
/* Now Draw the bar */
|
|
sliderGetBarBox(psSlider, &x0,&y0, &width,&height);
|
|
x0 = (SWORD)(x0 + psSlider->x + xOffset);
|
|
y0 = (SWORD)(y0 + psSlider->y + yOffset);
|
|
x1 = (SWORD)(x0 + width);
|
|
y1 = (SWORD)(y0 + height);
|
|
pie_BoxFillIndex(x0,y0, x1,y1,WCOL_BKGRND);
|
|
iV_Line(x0,y0, x1,y0,*(pColours + WCOL_LIGHT));
|
|
iV_Line(x0,y0, x0,y1,*(pColours + WCOL_LIGHT));
|
|
iV_Line(x1,y0, x1,y1,*(pColours + WCOL_DARK));
|
|
iV_Line(x0,y1, x1,y1,*(pColours + WCOL_DARK));
|
|
break;
|
|
}
|
|
|
|
if (psSlider->state & SLD_HILITE)
|
|
{
|
|
x0 = (SWORD)(psWidget->x + xOffset - 2);
|
|
y0 = (SWORD)(psWidget->y + yOffset - 2);
|
|
x1 = (SWORD)(x0 + psWidget->width + 4);
|
|
y1 = (SWORD)(y0 + psWidget->height + 4);
|
|
iV_Line(x0,y0, x1,y0,*(pColours + WCOL_HILITE));
|
|
iV_Line(x1,y0, x1,y1,*(pColours + WCOL_HILITE));
|
|
iV_Line(x0,y1, x1,y1,*(pColours + WCOL_HILITE));
|
|
iV_Line(x0,y0, x0,y1,*(pColours + WCOL_HILITE));
|
|
}
|
|
}
|
|
|