Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

ProgressBar.cpp

Committer:
jmitc91516
Date:
2017-07-31
Revision:
8:26e49e6955bd
Parent:
1:a5258871b33d

File content as of revision 8:26e49e6955bd:

#include "ProgressBar.h"

#include <math.h>

/*
    Default constructor
*/
ProgressBar::ProgressBar()
{
    barX = 0;
    barY = 0;
    
    barW = 1;
    barH = 1;
    
    orientation = horizontal;
    
    barPosition = 0;
    calibratedRange = 1.0;
    
    barColor = 0x8888;
    backColor = 0xFFFF;
    borderColor = 0;

    calibrationFactor = calibratedRange / (double)barW;
    
    previousBarPositionDisplayed = -1;
    
    fillBackground = false; 
}

/*
    Constructor with coordinates, etc, specified explicitly
*/
ProgressBar::ProgressBar(int x, int y, int w, int h, progressBarOrientation o, double newCalibratedRange, GuiConst_INTCOLOR brColor, GuiConst_INTCOLOR bkColor, GuiConst_INTCOLOR brdColor)
{
    barX = x;
    barY = y;
    
    barW = w;
    barH = h;
    
    orientation = o;
    
    barPosition = 0;
    calibratedRange = newCalibratedRange;
    
    barColor = brColor;
    backColor = bkColor;
    borderColor = brdColor;
    
    calibrationFactor = calibratedRange / (double)barW;
    
    previousBarPositionDisplayed = -1;
    
    fillBackground = false;
}

/*
    Change the calibrated end position of the bar to the new value,
    having applied the relevant checks to make sure it is valid.
    
    Then display the bar in its new position.
    
    If specified by the caller, (re)display the whole progress bar, regardless of whether or not 
    its end position has changed.
    
    Args: the new calibrated position
          boolean true to force the entire bar to be redisplayed, false if this is not necessary
*/
void ProgressBar::UpdateCalibratedPosition(double newCalibratedPosition, bool forceFullDisplay)
{
    if(newCalibratedPosition < 0.0) newCalibratedPosition = 0.0;
    
    if(newCalibratedPosition > calibratedRange) newCalibratedPosition = calibratedRange;
    
    barPosition = (int) floor((newCalibratedPosition / calibrationFactor) + 0.5);
    
    if(forceFullDisplay) {
        previousBarPositionDisplayed = -1;
    }
    
    DisplayNewPosition();
}

/*
    Display the bar with its position at the right hand end, 
    showing that the process is complete
    
    If specified by the caller, (re)display the whole progress bar, 
    regardless of how far it has moved since it was previously displayed.
    
    Args: a boolean - true to redisplay the whole bar, 
                      false to display only the area that has changed
*/
void ProgressBar::DisplayBarComplete(bool forceFullDisplay)
{
    barPosition = barW + 1; // '+ 1' to make sure the bar fills the bounding box
        
    if(forceFullDisplay) {
        previousBarPositionDisplayed = -1;
    }
    
    DisplayNewPosition();
}


/*
    Change the calibrated range of the bar to the new value,
    having applied the relevant checks to make sure it is valid.
    
    Then re-display the bar.
    
    Args: the new calibrated range
*/
void ProgressBar::SetCalibratedRange(double newCalibratedRange)
{
    if(newCalibratedRange < 0.0) {
        newCalibratedRange = 0.0;
    }

    calibratedRange = newCalibratedRange;

    calibrationFactor = calibratedRange / (double)barW;
    
    // Force the full bar to be re-displayed
    previousBarPositionDisplayed = -1;
    
    DisplayNewPosition();
}

/*
    After updating the position of the (end of) the bar, display it.
    
    If possible, display only the part that has moved, otherwise display the whole bar.
*/
void ProgressBar::DisplayNewPosition(void)
{
    if(previousBarPositionDisplayed == -1) {
        DisplayFullBar();
    } else {
        DisplayBarChangeOnly();
    }
    
    previousBarPositionDisplayed = barPosition;
}

/*
    Display the complete bar, including the border rectangle
*/
void ProgressBar::DisplayFullBar(void)
{
    // First display the border rectangle
    const int borderMargin = 1;
    GuiLib_Box(barX - borderMargin, barY - borderMargin, (barX + barW + borderMargin), (barY + barH + borderMargin), borderColor);
            
    if( barPosition > 0) {
        int barX1, barY1, barX2, barY2;
        int backX1, backY1, backX2, backY2;
        
        if( orientation == vertical) {
            barX1 = barX;
            barX2 = barX + barW;
            
            backX1 = barX1;
            backX2 = barX2;
            
            
            // We fill from the bottom, not the top
            barY1 = barY + barH - barPosition;
            barY2 = barY + barH;
            if(barY1 > barY2) { barY1 = barY2; }
            
            backY1 = barY;
            backY2 = barY1;
        } else {
            barX1 = barX;
            barX2 = barX + barPosition;
            if( barX2 < barX1) { barX2 = barX1; }
            
            backX1 = barX2;
            backX2 = barX + barW;
            
            barY1 = barY;
            barY2 = barY + barH;
            
            backY1 = barY1;
            backY2 = barY2;
        }
        
        GuiLib_FillBox(barX1, barY1, barX2, barY2, barColor);
        if(fillBackground) {
            GuiLib_FillBox(backX1, backY1, backX2, backY2, backColor);
        }
    } else {
        // Bar position is zero - display background only
        if(fillBackground) {
            GuiLib_FillBox(barX, barY, (barX + barW), (barY + barH), backColor);
        }
    }
}

/*
    Display only the part of the bar that has changed
    (minimises flickering on the display).
*/
void ProgressBar::DisplayBarChangeOnly(void)
{
    // We are displaying only the changed portion of the bar and background rectangle.
    // Assume we do not therefore need to (re)display the border box.
    // Note also that 'barPosition' is in display units (pixels) 
    // relative to the left hand end (horizontal bar) or bottom (vertical)
    
    if(barPosition != previousBarPositionDisplayed) {
            
        if(barPosition > previousBarPositionDisplayed) {
            // Need to extend bar
            int barX1, barY1, barX2, barY2;
            
            if( orientation == vertical) {
                barX1 = barX;
                barX2 = barX + barW;

                
                // We fill from the bottom, not the top
                barY1 = barY + barH - barPosition;
                barY2 = barY + barH - previousBarPositionDisplayed;
                
                if(barY1 < barY) barY1 = barY;
                if(barY2 > (barY + barH)) barY2 = barY + barH;
                
                if(barY1 > barY2) { barY1 = barY2; }
                
            } else {
                barX1 = barX + previousBarPositionDisplayed;
                barX2 = barX + barPosition;
                
                if(barX1 < barX) barX1 = barX;
                if(barX2 > (barX + barW)) barX2 = barX + barW;
                
                if( barX2 < barX1) { barX2 = barX1; }

                
                barY1 = barY;
                barY2 = barY + barH;
            }
            
            GuiLib_FillBox(barX1, barY1, barX2, barY2, barColor);
        } else {
            if(fillBackground) {
                // Bar has reduced in length - need to extend background bitmap/fill
                int backX1, backY1, backX2, backY2;
                
                if( orientation == vertical) {
                    backX1 = barX;
                    backX2 = barX + barW;
    
                    
                    // We fill from the bottom, not the top
                    backY1 = barY + barH - previousBarPositionDisplayed;
                    backY2 = barY + barH - barPosition;
                    
                    if(backY1 < barY) backY1 = barY;
                    if(backY2 > (barY + barH)) backY2 = barY + barH;
                    
                    if(backY1 > backY2) { backY1 = backY2; }
                    
                } else {
                    backX1 = barX + barPosition;
                    backX2 = barX + previousBarPositionDisplayed;
                    
                    if(backX1 < barX) backX1 = barX;
                    if(backX2 > (barX + barW)) backX2 = barX + barW;
                    
                    if( backX2 < backX1) { backX2 = backX1; }
                    
    
                    backY1 = barY;
                    backY2 = barY + barH;
                }
                
                GuiLib_FillBox(backX1, backY1, backX2, backY2, backColor);
            }
        }
    }
    // else no change - nothing to do
}