/* * This file is subject to the terms of the GFX License. If a copy of * the license was not distributed with this file, you can obtain one at: * * http://ugfx.io/license.html */ /** * @file src/gwin/gwin_progressbar.c * @brief GWIN sub-system progressbar code */ #include "../../gfx.h" #if (GFX_USE_GWIN && GWIN_NEED_PROGRESSBAR) || defined(__DOXYGEN__) #include "gwin_class.h" // Reset the display position back to the value predicted by the saved progressbar position static void PBResetDisplayPos(GProgressbarObject *gsw) { if (gsw->w.g.width < gsw->w.g.height) gsw->dpos = gsw->w.g.height-1-((gsw->w.g.height-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min); else gsw->dpos = ((gsw->w.g.width-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min); } // We have to deinitialize the timer which auto updates the progressbar if any static void PBDestroy(GHandle gh) { #if GWIN_PROGRESSBAR_AUTO gtimerStop(&((GProgressbarObject *)gh)->gt); gtimerDeinit(&((GProgressbarObject *)gh)->gt); #endif _gwidgetDestroy(gh); } // The progressbar VMT table static const gwidgetVMT progressbarVMT = { { "Progressbar", // The classname sizeof(GProgressbarObject), // The object size PBDestroy, // The destroy routine _gwidgetRedraw, // The redraw routine 0, // The after-clear routine }, gwinProgressbarDraw_Std, // The default drawing routine #if GINPUT_NEED_MOUSE { 0, // Process mouse down events (NOT USED) 0, // Process mouse up events 0, // Process mouse move events }, #endif #if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD { 0 // Process keyboard events }, #endif #if GINPUT_NEED_TOGGLE { 0, // 1 toggle role 0, // Assign Toggles 0, // Get Toggles 0, // Process toggle off events (NOT USED) 0, // Process toggle on events }, #endif #if GINPUT_NEED_DIAL { 0, // 1 dial roles 0, // Assign Dials 0, // Get Dials 0, // Process dial move events }, #endif }; GHandle gwinGProgressbarCreate(GDisplay *g, GProgressbarObject *gs, const GWidgetInit *pInit) { if (!(gs = (GProgressbarObject *)_gwidgetCreate(g, &gs->w, pInit, &progressbarVMT))) return 0; gs->min = 0; gs->max = 100; gs->res = 1; gs->pos = 0; #if GWIN_PROGRESSBAR_AUTO gtimerInit(&gs->gt); #endif PBResetDisplayPos(gs); gwinSetVisible((GHandle)gs, pInit->g.show); return (GHandle)gs; } void gwinProgressbarSetRange(GHandle gh, int min, int max) { #define gsw ((GProgressbarObject *)gh) if (gh->vmt != (gwinVMT *)&progressbarVMT) return; if (min == max) // prevent divide by 0 errors. max++; if (min <= max) { gsw->min = min; gsw->max = max; gsw->pos = min; gsw->res = 1; } else { gsw->min = max; gsw->max = min; gsw->pos = min; gsw->res = -1; } PBResetDisplayPos(gsw); #undef gsw } void gwinProgressbarSetPosition(GHandle gh, int pos) { #define gsw ((GProgressbarObject *)gh) if (gh->vmt != (gwinVMT *)&progressbarVMT) return; if (pos < gsw->min) gsw->pos = gsw->min; else if (pos > gsw->max) gsw->pos = gsw->max; else gsw->pos = pos; PBResetDisplayPos(gsw); _gwinUpdate(gh); #undef gsw } void gwinProgressbarSetResolution(GHandle gh, int resolution) { #define gsw ((GProgressbarObject *)gh) if (gh->vmt != (gwinVMT *)&progressbarVMT) return; gsw->res = resolution; #undef gsw } void gwinProgressbarIncrement(GHandle gh) { #define gsw ((GProgressbarObject *)gh) if (gh->vmt != (gwinVMT *)&progressbarVMT) return; gsw->pos += gsw->res; if (gsw->pos < gsw->min) gsw->pos = gsw->min; else if (gsw->pos > gsw->max) gsw->pos = gsw->max; PBResetDisplayPos(gsw); _gwinUpdate(gh); #undef gsw } void gwinProgressbarDecrement(GHandle gh) { #define gsw ((GProgressbarObject *)gh) if (gh->vmt != (gwinVMT *)&progressbarVMT) return; gsw->pos -= gsw->res; if (gsw->pos < gsw->min) gsw->pos = gsw->min; else if (gsw->pos > gsw->max) gsw->pos = gsw->max; PBResetDisplayPos(gsw); _gwinUpdate(gh); #undef gsw } #if GWIN_PROGRESSBAR_AUTO // used by gwinProgressbarStart(); static void _progressbarCallback(void *param) { #define gsw ((GProgressbarObject *)gh) GHandle gh = (GHandle)param; if (gh->vmt != (gwinVMT *)&progressbarVMT) return; gwinProgressbarIncrement(gh); if (gsw->pos >= gsw->max) gtimerStop(&gsw->gt); #undef gsw } void gwinProgressbarStart(GHandle gh, gDelay delay) { #define gsw ((GProgressbarObject *)gh) if (gh->vmt != (gwinVMT *)&progressbarVMT) return; gtimerStart(&gsw->gt, _progressbarCallback, gh, gTrue, delay); #undef gsw } void gwinProgressbarStop(GHandle gh) { #define gsw ((GProgressbarObject *)gh) if (gh->vmt != (gwinVMT *)&progressbarVMT) return; gtimerStop(&gsw->gt); #undef gsw } #endif /* GWIN_PROGRESSBAR_AUTO */ /*---------------------------------------------------------- * Custom Draw Routines *----------------------------------------------------------*/ void gwinProgressbarDraw_Std(GWidgetObject *gw, void *param) { #define gsw ((GProgressbarObject *)gw) const GColorSet * pcol; (void) param; if (gw->g.vmt != (gwinVMT *)&progressbarVMT) return; // get the colors right if ((gw->g.flags & GWIN_FLG_SYSENABLED)) pcol = &gw->pstyle->enabled; else pcol = &gw->pstyle->disabled; // Vertical progressbar if (gw->g.width < gw->g.height) { if (gsw->dpos != gw->g.height-1) gdispGFillArea(gw->g.display, gw->g.x, gw->g.y+gsw->dpos, gw->g.width, gw->g.height - gsw->dpos, pcol->progress); // Active Area if (gsw->dpos != 0) gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gsw->dpos, pcol->fill); // Inactive area gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos, pcol->edge); // Thumb // Horizontal progressbar } else { if (gsw->dpos != gw->g.width-1) gdispGFillArea(gw->g.display, gw->g.x+gsw->dpos, gw->g.y, gw->g.width-gsw->dpos, gw->g.height, pcol->fill); // Inactive area if (gsw->dpos != 0) gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gsw->dpos, gw->g.height, pcol->progress); // Active Area gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge gdispGDrawLine(gw->g.display, gw->g.x+gsw->dpos, gw->g.y, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-1, pcol->edge); // Thumb } gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, gJustifyCenter); #undef gsw } #if GDISP_NEED_IMAGE void gwinProgressbarDraw_Image(GWidgetObject *gw, void *param) { #define gsw ((GProgressbarObject *)gw) #define gi ((gImage *)param) const GColorSet * pcol; gCoord z, v; if (gw->g.vmt != (gwinVMT *)&progressbarVMT) return; if ((gw->g.flags & GWIN_FLG_SYSENABLED)) pcol = &gw->pstyle->enabled; else pcol = &gw->pstyle->disabled; // Vertical progressbar if (gw->g.width < gw->g.height) { if (gsw->dpos != 0) // The unfilled area gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gsw->dpos-1, gw->pstyle->enabled.progress); // Inactive area if (gsw->dpos != gw->g.height-1) { // The filled area for(z=gw->g.height, v=gi->height; z > gsw->dpos;) { z -= v; if (z < gsw->dpos) { v -= gsw->dpos - z; z = gsw->dpos; } gdispGImageDraw(gw->g.display, gi, gw->g.x+1, gw->g.y+z+1, gw->g.width-1, v-2, 0, gi->height-v); } } gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge gdispGDrawLine(gw->g.display, gw->g.x+1, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-2, gw->g.y+gsw->dpos, pcol->edge); // Thumb // Horizontal progressbar } else { if (gsw->dpos != gw->g.width-1) // The unfilled area gdispGFillArea(gw->g.display, gw->g.x+gsw->dpos+1, gw->g.y+1, gw->g.width-gsw->dpos-2, gw->g.height-2, gw->pstyle->enabled.progress); // Inactive area if (gsw->dpos != 0) { // The filled area for(z=0, v=gi->width; z < gsw->dpos; z += v) { if (z+v > gsw->dpos) v -= z+v - gsw->dpos; gdispGImageDraw(gw->g.display, gi, gw->g.x+z+1, gw->g.y+1, v-1, gw->g.height-2, 0, 0); } } gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); // Edge gdispGDrawLine(gw->g.display, gw->g.x+gsw->dpos, gw->g.y+1, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-2, pcol->edge); // Thumb } gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, gJustifyCenter); #undef gsw } #endif /* GDISP_NEED_IMAGE */ #endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */