/*
* Copyright (c) 2007 Hypertriton, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include
#include
#include "progress_bar.h"
#include "window.h"
#include "primitive.h"
#include "text.h"
#include "text_cache.h"
AG_ProgressBar *
AG_ProgressBarNew(void *parent, enum ag_progress_bar_type type, Uint flags)
{
AG_ProgressBar *pb;
pb = Malloc(sizeof(AG_ProgressBar));
AG_ObjectInit(pb, &agProgressBarClass);
pb->type = type;
pb->flags |= flags;
switch (type) {
case AG_PROGRESS_BAR_HORIZ:
AG_ExpandHoriz(pb);
break;
case AG_PROGRESS_BAR_VERT:
AG_ExpandVert(pb);
break;
default:
break;
}
AG_ObjectAttach(parent, pb);
return (pb);
}
AG_ProgressBar *
AG_ProgressBarNewInt(void *parent, enum ag_progress_bar_type type, Uint flags,
int *val, int *min, int *max)
{
AG_ProgressBar *pb = AG_ProgressBarNew(parent, type, flags);
if (val != NULL) { AG_BindInt(pb, "value", val); }
if (min != NULL) { AG_BindInt(pb, "min", min); }
if (max != NULL) { AG_BindInt(pb, "max", max); }
return (pb);
}
static void
Init(void *obj)
{
AG_ProgressBar *pb = obj;
WIDGET(pb)->flags |= AG_WIDGET_UNFOCUSED_BUTTONUP|
AG_WIDGET_UNFOCUSED_MOTION;
AG_BindInt(pb, "value", &pb->value);
AG_BindInt(pb, "min", &pb->min);
AG_BindInt(pb, "max", &pb->max);
pb->type = AG_PROGRESS_BAR_HORIZ;
pb->flags = 0;
pb->value = 0;
pb->min = 0;
pb->max = 100;
pb->width = 25;
pb->pad = 2;
pb->tCache = AG_TextCacheNew(pb, 50, 10);
}
static void
Destroy(void *obj)
{
AG_ProgressBar *pb = obj;
if (pb->tCache != NULL)
AG_TextCacheDestroy(pb->tCache);
}
void
AG_ProgressBarSetWidth(AG_ProgressBar *pb, int width)
{
AG_ObjectLock(pb);
pb->width = width;
AG_ObjectUnlock(pb);
}
static void
SizeRequest(void *obj, AG_SizeReq *r)
{
AG_ProgressBar *pb = obj;
switch (pb->type) {
case AG_PROGRESS_BAR_HORIZ:
r->w = 32;
r->h = pb->width;
break;
case AG_PROGRESS_BAR_VERT:
r->w = pb->width;
r->h = 32;
break;
}
}
static int
SizeAllocate(void *obj, const AG_SizeAlloc *a)
{
AG_ProgressBar *pb = obj;
if (a->w < pb->width || a->h < pb->width) {
return (-1);
}
return (0);
}
int
AG_ProgressBarPercent(AG_ProgressBar *pb)
{
int min, max, val;
AG_ObjectLock(pb);
min = AG_GetInt(pb, "min");
max = AG_GetInt(pb, "max");
val = AG_GetInt(pb, "value");
AG_ObjectUnlock(pb);
if (val < min) { val = min; }
if (val > max) { val = max; }
return (val - min)*100/(max - min);
}
static void
Draw(void *obj)
{
AG_ProgressBar *pb = obj;
char pctText[32];
AG_Rect rd;
int min, max, val, su, wAvail;
min = AG_GetInt(pb, "min");
max = AG_GetInt(pb, "max");
val = AG_GetInt(pb, "value");
if (val < min) { val = min; }
if (val > max) { val = max; }
STYLE(pb)->ProgressBarBackground(pb);
switch (pb->type) {
case AG_PROGRESS_BAR_VERT:
wAvail = WIDGET(pb)->h - pb->pad*2;
rd.x = pb->pad;
rd.y = pb->pad + (val - min)*wAvail/(max - min);
rd.w = WIDGET(pb)->w - pb->pad*2;
rd.h = WIDGET(pb)->h;
break;
case AG_PROGRESS_BAR_HORIZ:
default:
wAvail = WIDGET(pb)->w - pb->pad*2;
rd.x = pb->pad;
rd.y = pb->pad;
rd.w = (val - min)*wAvail/(max - min);
rd.h = WIDGET(pb)->h - pb->pad*2;
break;
}
AG_DrawRectFilled(pb, rd, AG_COLOR(PROGRESS_BAR_COLOR));
if (pb->flags & AG_PROGRESS_BAR_SHOW_PCT) {
Snprintf(pctText, sizeof(pctText), "%d%%",
AG_ProgressBarPercent(pb));
AG_PushTextState();
AG_TextColor(TEXT_COLOR);
su = AG_TextCacheGet(pb->tCache, pctText);
AG_WidgetBlitSurface(pb, su,
WIDTH(pb)/2 - WSURFACE(pb,su)->w/2,
HEIGHT(pb)/2 - WSURFACE(pb,su)->h/2);
AG_PopTextState();
}
}
AG_WidgetClass agProgressBarClass = {
{
"Agar(Widget:ProgressBar)",
sizeof(AG_ProgressBar),
{ 0,0 },
Init,
NULL, /* free */
Destroy,
NULL, /* load */
NULL, /* save */
NULL /* edit */
},
Draw,
SizeRequest,
SizeAllocate
};