All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.hansolo.steelseries.gauges.AbstractGauge Maven / Gradle / Ivy

Go to download

The SteelSeries is a javabeans component library that contains gauges. You will find linear and radial gauges. In addition you will also find digital displays.

There is a newer version: 3.9.6
Show newest version
package eu.hansolo.steelseries.gauges;

/**
 * The "mother" of most of the gauges in the steelseries library.
 * It contains common methods that are used in most of the gauges, no
 * matter if they are radial or linear.
 * @author hansolo
 */
public abstract class AbstractGauge extends javax.swing.JComponent implements java.awt.event.ComponentListener, java.awt.event.ActionListener
{
    // 
    protected static final eu.hansolo.steelseries.tools.Util UTIL = eu.hansolo.steelseries.tools.Util.INSTANCE;
    protected static final eu.hansolo.steelseries.tools.FrameImageFactory FRAME_FACTORY = eu.hansolo.steelseries.tools.FrameImageFactory.INSTANCE;
    protected static final eu.hansolo.steelseries.tools.BackgroundImageFactory BACKGROUND_FACTORY = eu.hansolo.steelseries.tools.BackgroundImageFactory.INSTANCE;
    protected static final eu.hansolo.steelseries.tools.PointerImageFactory POINTER_FACTORY = eu.hansolo.steelseries.tools.PointerImageFactory.INSTANCE;
    protected static final eu.hansolo.steelseries.tools.ForegroundImageFactory FOREGROUND_FACTORY = eu.hansolo.steelseries.tools.ForegroundImageFactory.INSTANCE;
    protected static final eu.hansolo.steelseries.tools.DisabledImageFactory DISABLED_FACTORY = eu.hansolo.steelseries.tools.DisabledImageFactory.INSTANCE;
    protected static final java.util.Set IMAGES_TO_UPDATE = java.util.EnumSet.of(
        eu.hansolo.steelseries.tools.ImageType.FRAME,
        eu.hansolo.steelseries.tools.ImageType.BACKGROUND,
        eu.hansolo.steelseries.tools.ImageType.POSTS,
        eu.hansolo.steelseries.tools.ImageType.BARGRAPHTRACK,
        eu.hansolo.steelseries.tools.ImageType.TRACK,
        eu.hansolo.steelseries.tools.ImageType.TICKMARKS,
        eu.hansolo.steelseries.tools.ImageType.TITLE,
        eu.hansolo.steelseries.tools.ImageType.THRESHOLD,
        eu.hansolo.steelseries.tools.ImageType.MIN_MEASURED,
        eu.hansolo.steelseries.tools.ImageType.MAX_MEASURED,
        eu.hansolo.steelseries.tools.ImageType.LCD,
        eu.hansolo.steelseries.tools.ImageType.POINTER,
        eu.hansolo.steelseries.tools.ImageType.POINTER_SHADOW,
        eu.hansolo.steelseries.tools.ImageType.FOREGROUND);
    // Initialization
    private boolean initialized;
    // Value related
    private javax.swing.event.ChangeEvent changeEvent;
    private final javax.swing.event.EventListenerList LISTENER_LIST = new javax.swing.event.EventListenerList();
    private double value;
    private double oldValue;
    private double minValue;
    private double maxValue;
    private double peakValue;
    private boolean autoResetToZero;
    //protected static final String VALUE_PROPERTY = "value";
    protected static final String THRESHOLD_PROPERTY = "threshold";
    // Threshold value related
    private double threshold;
    private boolean thresholdVisible;
    // Threshold LED related variables
    private double ledPositionX;
    private double ledPositionY;
    private eu.hansolo.steelseries.tools.LedColor ledColor;
    private final java.awt.GraphicsConfiguration GFX_CONF = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
    private java.awt.image.BufferedImage ledImageOff = GFX_CONF.createCompatibleImage(19, 19, java.awt.Transparency.TRANSLUCENT);
    private java.awt.image.BufferedImage ledImageOn = GFX_CONF.createCompatibleImage(19, 19, java.awt.Transparency.TRANSLUCENT);
    private java.awt.image.BufferedImage currentLedImage = GFX_CONF.createCompatibleImage(19, 19, java.awt.Transparency.TRANSLUCENT);
    private final javax.swing.Timer LED_BLINKING_TIMER;
    private boolean ledBlinking;
    private boolean ledOn;
    // Peak value related
    private boolean peakValueVisible;
    private final javax.swing.Timer PEAK_TIMER;
    // Measured value related variables
    private double minMeasuredValue;
    private boolean minMeasuredValueVisible;
    private double maxMeasuredValue;
    private boolean maxMeasuredValueVisible;    
    // Tickmark related
    private boolean drawTicks;
    private boolean drawTickLabels;
    private int scaleDividerPower;
    private boolean usingTickmarkColorFromTheme;
    private java.awt.Color tickmarkColor;
    private boolean tickmarkSectionsVisible;
    private final java.util.ArrayList TICKMARK_SECTIONS;
    private boolean usingCustomTickmarkLabels;
    private final java.util.ArrayList CUSTOM_TICKMARK_LABELS;
    // Track related
    private boolean trackVisible;
    private double trackStart;
    private double trackSection;
    private double trackStop;
    private java.awt.Color trackStartColor;
    private java.awt.Color trackSectionColor;
    private java.awt.Color trackStopColor;
    // Section related
    private boolean sectionsVisible;
    protected final java.util.ArrayList SECTIONS;
    // Area related
    private boolean areasVisible;
    protected final java.util.ArrayList AREAS;
    // Title and unit related
    private String title;
    private String unitString;
    private boolean usingLabelColorFromTheme;
    private java.awt.Color labelColor;
    private boolean usingTitleAndUnitFont;
    private java.awt.Font titleAndUnitFont;
    // Threshold LED related variables
    private boolean ledVisible;
    // Frame
    private eu.hansolo.steelseries.tools.FrameDesign frameDesign;
    private boolean frameVisible;
    // Background    
    private eu.hansolo.steelseries.tools.BackgroundColor backgroundColor;
    private boolean backgroundVisible;
    // Custom background
    private boolean customBackgroundVisible;
    private java.awt.Paint customBackground;
    // Custom layer
    private boolean customLayerVisible;
    private java.awt.image.BufferedImage customLayer;
    // Foreground
    private boolean foregroundVisible;
    // Timeline
    private long stdTimeToValue;
    private long rtzTimeToValue;
    private long rtzTimeBackToZero;
    // Orientation
    private eu.hansolo.steelseries.tools.Orientation orientation;    
    // 

    // 
    public AbstractGauge()
    {
        super();
        initialized = false;
        value = 0;
        minValue = 0;
        maxValue = 100;
        autoResetToZero = false;
        threshold = 100;
        thresholdVisible = false;
        ledPositionX = 0.6;
        ledPositionY = 0.4;
        ledColor = eu.hansolo.steelseries.tools.LedColor.RED_LED;
        ledImageOff.flush();
        ledImageOff = create_LED_Image(200, 0, ledColor);
        ledImageOn.flush();
        ledImageOn = create_LED_Image(200, 1, ledColor);
        LED_BLINKING_TIMER = new javax.swing.Timer(500, this);
        ledOn = false;
        ledBlinking = false;
        peakValueVisible = false;
        PEAK_TIMER = new javax.swing.Timer(1000, this);
        minMeasuredValue = maxValue;
        minMeasuredValueVisible = false;
        maxMeasuredValue = minValue;
        maxMeasuredValueVisible = false;
        drawTicks = true;
        drawTickLabels = true;
        scaleDividerPower = 0;
        usingTickmarkColorFromTheme = true;
        tickmarkColor = java.awt.Color.WHITE;
        tickmarkSectionsVisible = false;
        TICKMARK_SECTIONS = new java.util.ArrayList();
        usingCustomTickmarkLabels = false;
        CUSTOM_TICKMARK_LABELS = new java.util.ArrayList();
        trackVisible = false;
        trackStart = 0;
        trackSection = 50;
        trackStop = 100;
        trackStartColor = new java.awt.Color(0.0f, 1.0f, 0.0f, 0.5f);
        trackSectionColor = new java.awt.Color(1.0f, 1.0f, 0.0f, 0.5f);
        trackStopColor = new java.awt.Color(1.0f, 0.0f, 0.0f, 0.5f);
        sectionsVisible = false;
        SECTIONS = new java.util.ArrayList();
        areasVisible = false;
        AREAS = new java.util.ArrayList();
        title = "Title";
        unitString = "unit";
        usingLabelColorFromTheme = true;
        labelColor = java.awt.Color.WHITE;
        usingTitleAndUnitFont = false;
        titleAndUnitFont = new java.awt.Font("Verdana", 0, 10);
        ledVisible = true;
        frameDesign = eu.hansolo.steelseries.tools.FrameDesign.METAL;
        frameVisible = true;
        backgroundColor = eu.hansolo.steelseries.tools.BackgroundColor.DARK_GRAY;
        backgroundVisible = true;
        customBackgroundVisible = false;
        customBackground = java.awt.Color.BLACK;        
        customLayerVisible = false;
        customLayer = null;
        foregroundVisible = true;
        stdTimeToValue = 2000;
        rtzTimeToValue = 800;
        rtzTimeBackToZero = 2000;
        orientation = eu.hansolo.steelseries.tools.Orientation.NORTH;         
    }
    // 
    
    // 
    /**
     * In the init method all the images will be created. To avoid the creation
     * of each image everytime the method is called you have to add the appropriate
     * imagetype that should be recreated to IMAGES_TO_UPDATE enumset.
     * There is a additional method called recreateAllImages(),
     * that add's all available images to the enumset.
     * @param WIDTH
     * @param HEIGHT
     * @return a instance of the current gauge
     */
    abstract public AbstractGauge init(final int WIDTH, final int HEIGHT);
    // 
    
    // 
    /**
     * Returns true if the component is initialized and ready to display
     * @return a boolean that represents the initialzation state
     */
    public boolean isInitialized()
    {
        return this.initialized;
    }
    
    /**
     * Sets the state of initialization of the component
     * @param INITIALIZED 
     */
    public void setInitialized(final boolean INITIALIZED)
    {
        this.initialized = INITIALIZED;
    }
    
    /**
     * Returns the value of the gauge as a double
     * @return the value of the gauge
     */
    public double getValue()
    {        
        return value;
    }

    /**
     * Sets the value of the gauge. This method is primarly used for
     * static gauges or if you really have measurement results that
     * are occuring within the range of a second. If you have slow
     * changing values you should better use the method setValueAnimated.
     * @param VALUE
     */
    public void setValue(final double VALUE)
    {
        if (isEnabled())
        {
            oldValue = value;

            value = VALUE > getMaxValue() ? getMaxValue() : VALUE;
            value = VALUE < getMinValue() ? getMinValue() : VALUE;

            // LED blinking makes only sense when autoResetToZero == OFF
            if (!isAutoResetToZero())
            {
                // Check if current value exceeds threshold and activate led as indicator
                if (value >= getThreshold())
                {
                    if (!LED_BLINKING_TIMER.isRunning())
                    {
                        LED_BLINKING_TIMER.start();
                        firePropertyChange(THRESHOLD_PROPERTY, false, true);                        
                    }
                }
                else
                {
                    LED_BLINKING_TIMER.stop();
                    setCurrentLedImage(getLedImageOff());                
                }
            }
            
            repaint(getInnerBounds());        

            if (value != oldValue)
            {            
                //firePropertyChange("value", oldValue, value);                
                fireStateChanged();
            }
        }
    }

    /**
     * Returns the minimum value of the measurement
     * range of this gauge.
     * @return a dobule representing the min value the gauge could visualize
     */
    public double getMinValue()
    {
        return this.minValue;
    }

    /**
     * Sets the minimum value of the measurement
     * range of this gauge. This value defines the
     * minimum value the gauge could display.
     * @param MIN_VALUE
     */
    public void setMinValue(final double MIN_VALUE)
    {
        this.minValue = MIN_VALUE;
        if (MIN_VALUE > 0)
        {
            setValue(minValue);
        }

        // Validate connected variables
        // AutoResetToZero
        if (getMinValue() > 0 || getMaxValue() < 0)
        {
            setAutoResetToZero(false);            
        }
        // Threshold
        if (getThreshold() < getMinValue() || getThreshold() > getMaxValue())
        {            
            setThreshold(getMaxValue());
        }
        // TrackStart
        if (getTrackStart() <= getMinValue() || getTrackStart() >= getMaxValue() || getTrackStart() >= getTrackStop())
        {            
            setTrackStart(getMinValue());
        }
        // TrackSection
        if (getTrackSection() <= getMinValue() || getTrackSection() >= getMaxValue() || getTrackSection() <= getTrackStart() || getTrackSection() >= getTrackStop())
        {
            setTrackSection((getTrackStart() + (getTrackStop() - getTrackStart()) / 2.0));            
        }
        // TrackStop
        if ((getTrackStop() <= getMinValue()) || getTrackStop() >= getMaxValue() || getTrackStop() <= getTrackStart())
        {
            setTrackStop(getMaxValue());
        }
        // Sections
        for (eu.hansolo.steelseries.tools.Section section : getSections())
        {
            if (section.getStart() != -1 && section.getStop() != -1)
            {
                if ((section.getStart() < getMinValue()) || section.getStart() >= getMaxValue() || section.getStart() >= section.getStop())
                {
                    section.setStart(getMinValue());
                }

                if (section.getStop() < getMinValue() || section.getStop() > getMaxValue() || section.getStop() <= section.getStart())
                {
                    section.setStop(getMaxValue());
                }
            }
        }

        calcAngleStep();
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the maximum value of the measurement
     * range of this gauge. This means the gauge could
     * not display values larger than this value.
     * @return Double that represents the maximum value the gauge could display
     */
    public double getMaxValue()
    {
        return this.maxValue;
    }

    /**
     * Sets the maximum value of the measurement
     * range of this gauge. This value defines the
     * maximum value the gauge could display.
     * It has nothing to do with MaxMeasuredValue,
     * which represents the max. value that was
     * measured since the last reset of MaxMeasuredValue
     * @param MAX_VALUE
     */
    public void setMaxValue(final double MAX_VALUE)
    {
        this.maxValue = MAX_VALUE;
        
        // Validate connected variables
        // AutoResetToZero
        if (getMinValue() > 0 || getMaxValue() < 0)
        {
            setAutoResetToZero(false);
        }
        // Threshold
        if (getThreshold() < getMinValue() || getThreshold() > getMaxValue())
        {
            setThreshold(getMaxValue());
        }
        // TrackStart
        if (getTrackStart() <= getMinValue() || getTrackStart() >= getMaxValue() || getTrackStart() >= getTrackStop())
        {
            setTrackStart(getMinValue());
        }
        // TrackSection
        if (getTrackSection() <= getMinValue() || getTrackSection() >= getMaxValue() || getTrackSection() <= getTrackStart() || getTrackSection() >= getTrackStop())
        {
            setTrackSection(getTrackStart() + (getTrackStop() - getTrackStart()) / 2.0);
        }
        // TrackStop
        if ((getTrackStop() <= getMinValue()) || getTrackStop() >= getMaxValue() || getTrackStop() <= getTrackStart())
        {
            setTrackStop(getMaxValue());
        }
        // Sections
        for (eu.hansolo.steelseries.tools.Section section : SECTIONS)
        {
            if (section.getStart() != -1 && section.getStop() != -1)
            {
                if ((section.getStart() < getMinValue()) || section.getStart() >= getMaxValue() || section.getStart() >= section.getStop())
                {
                    section.setStart(getMinValue());
                }

                if (section.getStop() < getMinValue() || section.getStop() > getMaxValue() || section.getStop() <= section.getStart())
                {
                    section.setStop(getMaxValue());
                }
            }
        }
        setSections((eu.hansolo.steelseries.tools.Section[]) SECTIONS.toArray()); 
        
        // Areas
        for (eu.hansolo.steelseries.tools.Section area : AREAS)
        {
            if (area.getStart() != -1 && area.getStop() != -1)
            {
                if ((area.getStart() < getMinValue()) || area.getStart() >= getMaxValue() || area.getStart() >= area.getStop())
                {
                    area.setStart(getMinValue());
                }

                if (area.getStop() < getMinValue() || area.getStop() > getMaxValue() || area.getStop() <= area.getStart())
                {
                    area.setStop(getMaxValue());
                }
            }
        }
        setAreas((eu.hansolo.steelseries.tools.Section[]) AREAS.toArray());
        
        calcAngleStep();
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the peak value which is the last
     * value that was set before the current one
     * This feature is used in the bargraphs
     * @return a double that represents the peak value
     */
    public double getPeakValue()
    {
        return this.peakValue;
    }

    /**
     * Sets the peak value of the gauge. This method will
     * be used in the bargraph gauges to visualize the last
     * displayed value
     * @param PEAK_VALUE
     */
    public void setPeakValue(final double PEAK_VALUE)
    {
        this.peakValue = PEAK_VALUE;
    }

    /**
     * Returns true if the last measured value (peak value)
     * is visible and will be painted.
     * @return the visibility of the peak value
     */
    public boolean isPeakValueVisible()
    {
        return this.peakValueVisible;
    }

    /**
     * Sets the visbility of the peak value which
     * is the last measured value.
     * @param PEAK_VALUE_VISIBLE
     */
    public void setPeakValueVisible(final boolean PEAK_VALUE_VISIBLE)
    {
        this.peakValueVisible = PEAK_VALUE_VISIBLE;
    }

    /**
     * Returns true if the gauge will be reseted to
     * zero after each value.
     * Means if you set a value the pointer will
     * move to this value and after it reached the
     * given value it will return back to zero.
     * @return true if the value will be set to
     * zero automaticaly
     */
    public boolean isAutoResetToZero()
    {
        return this.autoResetToZero;
    }

    /**
     * Enables/disables the mode where the gauge
     * will return to zero after a value was set.
     * Means if you set a value the pointer will
     * move to this value and after it reached the
     * given value it will return back to zero.
     * @param AUTO_RESET_TO_ZERO
     */
    public void setAutoResetToZero(final boolean AUTO_RESET_TO_ZERO)
    {
        if (getMinValue() > 0 || getMaxValue() < 0)
        {
            this.autoResetToZero = false;
        }
        else
        {
            this.autoResetToZero = AUTO_RESET_TO_ZERO;
            if (AUTO_RESET_TO_ZERO)
            {
                setThresholdVisible(false);
                setLedVisible(false);
            }
        }
    }

    /**
     * Returns the value that is defined as a threshold.
     * If the current value of the gauge exceeds this
     * threshold, a event will be fired and the led will
     * start blinking (if the led is visible).
     * @return the threshold value where the led starts blinking
     */
    public double getThreshold()
    {
        return this.threshold;
    }

    /**
     * Sets the given value as the threshold.
     * If the current value of the gauge exceeds this
     * threshold, a event will be fired and the led will
     * start blinking (if the led is visible).
     * @param THRESHOLD
     */
    public void setThreshold(final double THRESHOLD)
    {
        if (THRESHOLD < getMinValue() || THRESHOLD > getMaxValue())
        {
            this.threshold = getMaxValue();
        }
        else
        {
            this.threshold = THRESHOLD;
        }
        //setValue(getValue());
    }

    /**
     * Returns the visibility of the threshold indicator.
     * The value of the threshold will be visualized by
     * a small red triangle that points on the threshold
     * value.
     * @return true if the threshold indicator is visible
     */
    public boolean isThresholdVisible()
    {
        return this.thresholdVisible;
    }

    /**
     * Sets the visibility of the threshold indicator.
     * The value of the threshold will be visualized by
     * a small red triangle that points on the threshold
     * value.
     * @param THRESHOLD_VISIBLE
     */
    public void setThresholdVisible(final boolean THRESHOLD_VISIBLE)
    {
        this.thresholdVisible = THRESHOLD_VISIBLE;
        repaint(getInnerBounds());
    }

    /**
     * Returns the visiblity of the threshold led.
     * @return a boolean that indicates if the led is visible
     */
    public boolean isLedVisible()
    {
        return this.ledVisible;
    }

    /**
     * Sets the visibility of the threshold led.
     * @param LED_VISIBLE
     */
    public void setLedVisible(final boolean LED_VISIBLE)
    {
        this.ledVisible = LED_VISIBLE;
        repaint(getInnerBounds());
    }

    /**
     * Returns the x position of the threshold led.
     * This is needed because in some gauges the led
     * might be placed on a different position than the
     * default position.
     * @return the x position of the led as a factor
     */
    protected double getLedPositionX()
    {
        return this.ledPositionX;
    }

    /**
     * Sets the x position of the threshold led.
     * This is needed because in some gauges the led
     * might be placed on a different position than the
     * default position.
     * @param LED_POSITION_X
     */
    protected void setLedPositionX(final double LED_POSITION_X)
    {
        this.ledPositionX = LED_POSITION_X;
    }

    /**
     * Returns the y position of the threshold led.
     * This is needed because in some gauges the led
     * might be placed on a different position than the
     * default position.
     * @return the y position of the led as a factor
     */
    protected double getLedPositionY()
    {
        return this.ledPositionY;
    }

    /**
     * Sets the y position of the threshold led.
     * This is needed because in some gauges the led
     * might be placed on a different position than the
     * default position.
     * @param LED_POSITION_Y
     */
    protected void setLedPositionY(final double LED_POSITION_Y)
    {
        this.ledPositionY = LED_POSITION_Y;
    }

    /**
     * Returns the color of the threshold led.
     * The LedColor is not a standard color but defines a
     * color scheme for the led. The default ledcolor is RED
     * @return the selected the color for the led
     */
    public eu.hansolo.steelseries.tools.LedColor getLedColor()
    {
        return this.ledColor;
    }
   
    /**
     * Sets the color of the threshold led dependend on the orientation of
     * a component. This is only important for the linear gauges where the width
     * and the height are different.
     * The LedColor is not a standard color but defines a
     * color scheme for the led. The default ledcolor is RED
     * @param LED_COLOR
     */
    public void setLedColor(final eu.hansolo.steelseries.tools.LedColor LED_COLOR)
    {
        this.ledColor = LED_COLOR;
        final boolean LED_WAS_ON = currentLedImage.equals(ledImageOn) ? true : false;

        switch (getOrientation())
        {
            case HORIZONTAL:
                recreateLedImages(getHeight());
                break;
            case VERTICAL:
                recreateLedImages(getWidth());
                break;
            default:
                recreateLedImages();
                break;
        }
        
        currentLedImage.flush();
        currentLedImage = LED_WAS_ON == true ? ledImageOn : ledImageOff;

        repaint(getInnerBounds());
    }

    /**
     * Returns the state of the threshold led.
     * The led could blink which will be triggered by a javax.swing.Timer
     * that triggers every 500 ms. The blinking will be done by switching
     * between two images.
     * @return true if the led is blinking
     */
    public boolean isLedBlinking()
    {
        return this.ledBlinking;
    }

    /**
     * Sets the state of the threshold led.
     * The led could blink which will be triggered by a javax.swing.Timer
     * that triggers every 500 ms. The blinking will be done by switching
     * between two images.
     * @param LED_BLINKING
     */
    public void setLedBlinking(final boolean LED_BLINKING)
    {
        this.ledBlinking = LED_BLINKING;
        if (LED_BLINKING)
        {
            LED_BLINKING_TIMER.start();
        }
        else
        {
            setCurrentLedImage(getLedImageOff());
            LED_BLINKING_TIMER.stop();
        }
    }

    /**
     * Returns the image of the switched on threshold led
     * with the currently active ledcolor.
     * @return the image of the led with the state active
     * and the selected led color
     */
    protected java.awt.image.BufferedImage getLedImageOn()
    {
        return this.ledImageOn;
    }

    /**
     * Returns the image of the switched off threshold led
     * with the currently active ledcolor.
     * @return the image of the led with the state inactive
     * and the selected led color
     */
    protected java.awt.image.BufferedImage getLedImageOff()
    {
        return this.ledImageOff;
    }

    /**
     * Recreates the current threshold led images due to the size of the component
     */
    protected void recreateLedImages()
    {
        recreateLedImages(getInnerBounds().width);        
    }
    
    /**
     * Recreates the current threshold led images due to the given width
     * @param SIZE 
     */
    protected void recreateLedImages(final int SIZE)
    {
        ledImageOff.flush();
        ledImageOff = create_LED_Image(SIZE, 0, getLedColor());
        ledImageOn.flush();
        ledImageOn = create_LED_Image(SIZE, 1, getLedColor());
    }
    
    /**
     * Returns the image of the currently used led image.
     * @return the led image at the moment (depends on blinking)
     */
    protected java.awt.image.BufferedImage getCurrentLedImage()
    {
        return this.currentLedImage;
    }

    /**
     * Sets the image of the currently used led image.
     * @param CURRENT_LED_IMAGE
     */
    protected void setCurrentLedImage(final java.awt.image.BufferedImage CURRENT_LED_IMAGE)
    {
        currentLedImage.flush();
        currentLedImage = CURRENT_LED_IMAGE;
        repaint(getInnerBounds());
    }
    
    /**
     * Returns the current state of the threshold led
     * @return a boolean that represents the state of the threshold led
     */
    protected boolean isLedOn()
    {
        return this.ledOn;
    }
    
    /**
     * Returns the lowest measured value.
     * On every move of the bar/pointer the lowest value
     * will be stored in the minMeasuredValue variable.
     * @return a double representing the min measure value
     */
    public double getMinMeasuredValue()
    {
        return this.minMeasuredValue;
    }

    /**
     * Sets the lowest value that was measured
     * On every move of the bar/pointer the lowest value
     * will be stored in the minMeasuredValue variable.
     * @param MIN_MEASURED_VALUE
     */
    protected void setMinMeasuredValue(final double MIN_MEASURED_VALUE)
    {
        this.minMeasuredValue = MIN_MEASURED_VALUE;
        repaint(getInnerBounds());
    }

    /**
     * Returns the visibility of the minMeasuredValue indicator.
     * The lowest value that was measured by the gauge will
     * be visualized by a little blue triangle.
     * @return a boolean that indicates if the min measured value image is visible
     */
    public boolean isMinMeasuredValueVisible()
    {
        return this.minMeasuredValueVisible;
    }

    /**
     * Sets the visibility of the minMeasuredValue indicator.
     * The lowest value that was measured by the gauge will
     * be visualized by a little blue triangle.
     * @param MIN_MEASURED_VALUE_VISIBLE
     */
    public void setMinMeasuredValueVisible(final boolean MIN_MEASURED_VALUE_VISIBLE)
    {
        this.minMeasuredValueVisible = MIN_MEASURED_VALUE_VISIBLE;
        repaint(getInnerBounds());
    }

    /**
     * Resets the minMeasureValue variable to the maximum value
     * that the gauge could display. So on the next move of the
     * pointer/bar the indicator will be set to the pointer/bar
     * position again.
     */
    public void resetMinMeasuredValue()
    {
        this.minMeasuredValue = getValue();
        repaint(getInnerBounds());
    }

    /**
     * Resets the minMeasuredValue variable to the given value.
     * So on the next move of the pointer/bar the indicator will
     * be set to the pointer/bar position again.
     * @param VALUE
     */
    public void resetMinMeasuredValue(final double VALUE)
    {
        this.maxMeasuredValue = VALUE; 
        repaint(getInnerBounds());
    }

    /**
     * Returns the biggest measured value.
     * On every move of the bar/pointer the biggest value
     * will be stored in the maxMeasuredValue variable.
     * @return a double representing the max measured value
     */
    public double getMaxMeasuredValue()
    {
        return this.maxMeasuredValue;
    }

    /**
     * Sets the highest value that was measured
     * On every move of the bar/pointer the highest value
     * will be stored in the maxMeasuredValue variable.
     * @param MAX_MEASURED_VALUE
     */
    protected void setMaxMeasuredValue(final double MAX_MEASURED_VALUE)
    {
        this.maxMeasuredValue = MAX_MEASURED_VALUE;
        repaint(getInnerBounds());
    }

    /**
     * Returns the visibility of the maxMeasuredValue indicator.
     * The biggest value that was measured by the gauge will
     * be visualized by a little red triangle.
     * @return a boolean that indicates if the max measured value image is visible
     */
    public boolean isMaxMeasuredValueVisible()
    {
        return this.maxMeasuredValueVisible;
    }

    /**
     * Sets the visibility of the maxMeasuredValue indicator.
     * The biggest value that was measured by the gauge will
     * be visualized by a little red triangle.
     * @param MAX_MEASURED_VALUE_VISIBLE
     */
    public void setMaxMeasuredValueVisible(final boolean MAX_MEASURED_VALUE_VISIBLE)
    {
        this.maxMeasuredValueVisible = MAX_MEASURED_VALUE_VISIBLE;
        repaint(getInnerBounds());
    }

    /**
     * Resets the maxMeasureValue variable to the minimum value
     * that the gauge could display. So on the next move of the
     * pointer/bar the indicator will be set to the pointer/bar
     * position again.
     */
    public void resetMaxMeasuredValue()
    {
        this.maxMeasuredValue = getValue();    
        repaint(getInnerBounds());
    }

    /**
     * Resets the maxMeasuredValue variable to the given value.
     * So on the next move of the pointer/bar the indicator will
     * be set to the pointer/bar position again.
     * @param VALUE
     */
    public void resetMaxMeasuredValue(final double VALUE)
    {
        this.maxMeasuredValue = VALUE;        
        repaint(getInnerBounds());
    }

    /**
     * Returns the time in milliseconds that the pointer/bar/led needs to move from
     * the minimum value of the gauge to the maximum of the gauge in standard mode.
     * The minimum time is 250 ms and the maximum time is 5000 ms.
     * @return time in ms that the pointer/bar/led needs to move from minValue to maxValue in standard mode
     */
    public long getStdTimeToValue()
    {
        return this.stdTimeToValue;
    }

    /**
     * Sets the time in milliseconds that the pointer/bar/led needs to move from
     * the minimum value of the gauge to the maximum of the gauge in standard mode.
     * The minimum time is 250 ms and the maximum time is 5000 ms.
     * @param STD_TIME_TO_VALUE
     */
    public void setStdTimeToValue(final long STD_TIME_TO_VALUE)
    {
        stdTimeToValue = STD_TIME_TO_VALUE < 250 ? 250 : STD_TIME_TO_VALUE;
        stdTimeToValue = STD_TIME_TO_VALUE > 5000 ? 5000 : STD_TIME_TO_VALUE;
    }

    /**
     * Returns the time in milliseconds that the pointer/bar/led needs to move from
     * the minimum value of the gauge to the maximum of the gauge in autoreturn to zero mode.
     * The minimum time is 250 ms and the maximum time is 5000 ms.
     * @return time in ms that the pointer/bar/led needs to move from minValue to maxValue in autoreturn to zero mode
     */
    public long getRtzTimeToValue()
    {
        return this.rtzTimeToValue;
    }

    /**
     * Sets the time in milliseconds that the pointer/bar/led needs to move from
     * the minimum value of the gauge to the maximum of the gauge in autoreturn to zero mode.
     * The minimum time is 250 ms and the maximum time is 5000 ms.
     * @param RTZ_TIME_TO_VALUE
     */
    public void setRtzTimeToValue(final long RTZ_TIME_TO_VALUE)
    {
        rtzTimeToValue = RTZ_TIME_TO_VALUE < 250 ? 250 : RTZ_TIME_TO_VALUE;
        rtzTimeToValue = RTZ_TIME_TO_VALUE > 5000 ? 5000 : RTZ_TIME_TO_VALUE;
    }

    /**
     * Returns the time in milliseconds that the pointer/bar/led needs back from the value to zero
     * in autoreturn to zero mode. The minimum time is 250 ms and the maximum time is 5000 ms.
     * @return the time in ms that the pointer/bar/led needs to move back from the value to zero
     */
    public long getRtzTimeBackToZero()
    {
        return this.rtzTimeBackToZero;
    }

    /**
     * Sets the time in milliseconds that the pointer/bar/led needs to move back from the value
     * to zero in autoreturn to zero mode. The minimum time is 250 ms and the maximum time is 5000 ms.
     * @param RTZ_TIME_BACK_TO_ZERO
     */
    public void setRtzTimeBackToZero(final long RTZ_TIME_BACK_TO_ZERO)
    {
        rtzTimeBackToZero = RTZ_TIME_BACK_TO_ZERO < 250 ? 250 : RTZ_TIME_BACK_TO_ZERO;
        rtzTimeBackToZero = RTZ_TIME_BACK_TO_ZERO > 5000 ? 5000 : RTZ_TIME_BACK_TO_ZERO;
    }
    
    /**
     * Returns the timer that is used to timeout the peak value in
     * the bargraph gauges.
     * @return a javax.swing.Timer object
     */
    public javax.swing.Timer getPeakTimer()
    {
        return this.PEAK_TIMER;
    }
    
    /**
     * Start the peak timer
     */
    public void startPeakTimer()
    {
        if (!PEAK_TIMER.isRunning())
        {
            PEAK_TIMER.start();
        }
    }
    
    /**
     * Stop the peak timer
     */
    public void stopPeakTimer()
    {
        if (PEAK_TIMER.isRunning())
        {
            PEAK_TIMER.stop();
        }
    }
    
    /**
     * Returns an int that represents the orientation of the gauge.
     * The values are taken from eu.hansolo.steelseries.tools.Orientation     
     * NORTH         => Used in Radial1Vertical
     * NORTH_EAST    => Used in Radial1Square
     * EAST          => Used in Radial1Vertical
     * SOUTH_EAST    => Used in Radial1Square
     * SOUTH         => Used in Radial1Vertical
     * SOUTH_WEST    => Used in Radial1Square
     * WEST          => Used in Radial1Vertical
     * NORTH_WEST    => Used in Radial1Square
     * HORIZONTAL    => Used in Linear
     * VERTICAL      => Used in Linear
     * @return a enum that represents the orientation
     */
    public eu.hansolo.steelseries.tools.Orientation getOrientation()
    {
        return this.orientation;
    }
    
    /**
     * Sets the orientation of the gauge.
     * The values are taken from eu.hansolo.steelseries.tools.Orientation     
     * NORTH         => Used in Radial1Vertical
     * NORTH_EAST    => Used in Radial1Square
     * EAST          => Used in Radial1Vertical
     * SOUTH_EAST    => Used in Radial1Square
     * SOUTH         => Used in Radial1Vertical
     * SOUTH_WEST    => Used in Radial1Square
     * WEST          => Used in Radial1Vertical
     * NORTH_WEST    => Used in Radial1Square
     * HORIZONTAL    => Used in Linear
     * VERTICAL      => Used in Linear
     * @param ORIENTATION 
     */
    public void setOrientation(final eu.hansolo.steelseries.tools.Orientation ORIENTATION)
    {        
        this.orientation = ORIENTATION;
        repaint(getInnerBounds());
    }            
    //
    
    // 
    /**
     * In normal case the scale is divided into a stepsize of one (10e0). This
     * works for a value range up to 1000. If the gauge should show higher
     * values, you may want to divide the scale through a higher potency.
     * This method returns the power of 10, the scale gets divided through
     * (e.g. 10e2 for power of 2).
     * Common settings for SCALE_DIVIDER_POWER
     * RANGE: 100     -> SCALE_DIVIDER_POWER: 0
     * RANGE: 1000    -> SCALE_DIVIDER_POWER: 0
     * RANGE: 10000   -> SCALE_DIVIDER_POWER: 1
     * RANGE: 100000  -> SCALE_DIVIDER_POWER: 2
     * @return power to 10 the scale gets divided through
     */
    public int getScaleDividerPower()
    {
        return this.scaleDividerPower;
    }

    /**
     * In normal case the scale is divided into a stepsize of one (10e0). This
     * works for a value range up to 1000. If the gauge should show higher
     * values, you may want to divide the scale through a higher potency.
     * This method sets the power of 10, the scale gets divided through
     * (e.g. 10e2 for power of 2).
     * Common settings for SCALE_DIVIDER_POWER
     * RANGE: 100     -> SCALE_DIVIDER_POWER: 0
     * RANGE: 1000    -> SCALE_DIVIDER_POWER: 0
     * RANGE: 10000   -> SCALE_DIVIDER_POWER: 1
     * RANGE: 100000  -> SCALE_DIVIDER_POWER: 2
     * @param SCALE_DIVIDER_POWER to 10 the scale gets divided through
     */
    public void setScaleDividerPower(final int SCALE_DIVIDER_POWER)
    {
        this.scaleDividerPower = SCALE_DIVIDER_POWER;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        repaint(getInnerBounds());
    }

    /**
     * Returns true if the color of the tickmarks will be
     * used from the defined background color.
     * @return true if tickmarks will use the color defined in the current
     * background color
     */
    public boolean isUsingTickmarkColorFromTheme()
    {
        return this.usingTickmarkColorFromTheme;
    }

    /**
     * Enables/disables the usage of a separate color for the
     * tickmarks.
     * @param USING_TICKMARK_COLOR_FROM_THEME
     */
    public void setUsingTickmarkColorFromTheme(final boolean USING_TICKMARK_COLOR_FROM_THEME)
    {
        this.usingTickmarkColorFromTheme = USING_TICKMARK_COLOR_FROM_THEME;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the color of the tickmarks and their labels
     * @return the custom defined color for the tickmarks and labels
     */
    public java.awt.Color getTickmarkColor()
    {
        return this.tickmarkColor;
    }

    /**
     * Sets the color of the tickmarks and their labels
     * @param TICKMARK_COLOR
     */
    public void setTickmarkColor(final java.awt.Color TICKMARK_COLOR)
    {
        this.tickmarkColor = TICKMARK_COLOR;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns true if the tickmarks are visible
     * @return true if the tickmarks are visible
     */
    public boolean isDrawTicks()
    {
        return this.drawTicks;
    }

    /**
     * Enables or disables the visibility of the tickmarks
     * @param DRAW_TICKS
     */
    public void setDrawTicks(final boolean DRAW_TICKS)
    {
        this.drawTicks = DRAW_TICKS;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns true if the tickmark labels are visible
     * @return true if the tickmark labels are visible
     */
    public boolean isDrawTickLabels()
    {
        return this.drawTickLabels;
    }

    /**
     * Enables or disables the visibility of the tickmark labels
     * @param DRAW_TICK_LABELS
     */
    public void setDrawTickLabels(final boolean DRAW_TICK_LABELS)
    {
        this.drawTickLabels = DRAW_TICK_LABELS;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns true if customer defined tickmark labels will be
     * used for the scaling.
     * e.g. you only want to show "0, 10, 50, 100" in your
     * gauge scale so you could set the custom tickmarklabels
     * to these values.
     * @return a boolean that indicates if custom tickmark labels will be used
     */
    public boolean isUsingCustomTickmarkLabels()
    {
        return this.usingCustomTickmarkLabels;
    }

    /**
     * Enables/Disables the usage of custom tickmark labels.
     * e.g. you only want to show "0, 10, 50, 100" in your
     * gauge scale so you could set the custom tickmarklabels
     * to these values.
     * @param USING_CUSTOM_TICKMARK_LABELS
     */
    public void setUsingCustomTickmarkLabels(final boolean USING_CUSTOM_TICKMARK_LABELS)
    {
        this.usingCustomTickmarkLabels = USING_CUSTOM_TICKMARK_LABELS;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns a list of the defined custom tickmark labels
     * e.g. you only want to show "0, 10, 50, 100" in your
     * gauge scale so you could set the custom tickmarklabels
     * to these values.
     * @return the arraylist containing custom tickmark labels
     */
    public java.util.ArrayList getCustomTickmarkLabels()
    {
        return (java.util.ArrayList) this.CUSTOM_TICKMARK_LABELS.clone();
    }

    /**
     * Takes a array of doubles that will be used as custom tickmark labels
     * e.g. you only want to show "0, 10, 50, 100" in your
     * gauge scale so you could set the custom tickmarklabels
     * to these values.
     * @param CUSTOM_TICKMARK_LABELS_ARRAY
     */
    public void setCustomTickmarkLabels(final double... CUSTOM_TICKMARK_LABELS_ARRAY)
    {
        CUSTOM_TICKMARK_LABELS.clear();
        for (Double label : CUSTOM_TICKMARK_LABELS_ARRAY)
        {
            CUSTOM_TICKMARK_LABELS.add(label);
        }
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Adds the given double to the list of custom tickmark labels
     * e.g. you only want to show "0, 10, 50, 100" in your
     * gauge scale so you could set the custom tickmarklabels
     * to these values.
     * @param CUSTOM_TICKMARK_LABEL
     */
    public void addCustomTickmarkLabel(final double CUSTOM_TICKMARK_LABEL)
    {
        CUSTOM_TICKMARK_LABELS.add(CUSTOM_TICKMARK_LABEL);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Reset the list of custom tickmark labels, which means clear the list
     */
    public void resetCustomTickmarkLabels()
    {
        CUSTOM_TICKMARK_LABELS.clear();
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns a copy of the ArrayList that stores the sections.
     * The sections could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The sections are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you would like to visualize by
     * colored tickmarks.
     * @return a arraylist representing the sections for the tickmarks
     */
    public java.util.ArrayList getTickmarkSections()
    {
        return (java.util.ArrayList) this.TICKMARK_SECTIONS.clone();
    }

    /**
     * Sets the sections given in a array of sections (Section[])
     * The sections could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The sections are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you would like to visualize by
     * by colored tickmarks.
     * @param TICKMARK_SECTIONS_ARRAY
     */
    public void setTickmarkSections(final eu.hansolo.steelseries.tools.Section... TICKMARK_SECTIONS_ARRAY)
    {
        TICKMARK_SECTIONS.clear();
        TICKMARK_SECTIONS.addAll(java.util.Arrays.asList(TICKMARK_SECTIONS_ARRAY));        
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Adds a given section to the list of sections
     * The sections could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The sections are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you would like to visualize by
     * by colored tickmarks.
     * @param TICKMARK_SECTION
     */
    public void addTickmarkSection(final eu.hansolo.steelseries.tools.Section TICKMARK_SECTION)
    {
        TICKMARK_SECTIONS.add(TICKMARK_SECTION);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Clear the TICKMARK_SECTIONS arraylist
     */
    public void resetTickmarkSections()
    {
        TICKMARK_SECTIONS.clear();
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the visibility of the tickmark sections.
     * The sections could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The sections are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * the tickmark labels colored for specific areas.
     * @return true if the tickmark sections are visible
     */
    public boolean isTickmarkSectionsVisible()
    {
        return this.tickmarkSectionsVisible;
    }

    /**
     * Sets the visibility of the tickmark sections.
     * The sections could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The sections are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * the tickmark labels colored for specific areas.
     * @param TICKMARK_SECTIONS_VISIBLE
     */
    public void setTickmarkSectionsVisible(final boolean TICKMARK_SECTIONS_VISIBLE)
    {
        this.tickmarkSectionsVisible = TICKMARK_SECTIONS_VISIBLE;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }
    //
    
    // 
    /**
     * Returns the visibility of the track.
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @return true if the track is visible
     */
    public boolean isTrackVisible()
    {
        return this.trackVisible;
    }

    /**
     * Sets the visibility of the track.
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @param TRACK_VISIBLE
     */
    public void setTrackVisible(final boolean TRACK_VISIBLE)
    {
        this.trackVisible = TRACK_VISIBLE;
        repaint(getInnerBounds());
    }

    /**
     * Returns the value where the track will start.
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @return represents the value where the track starts
     */
    public double getTrackStart()
    {
        return this.trackStart;
    }

    /**
     * Sets the value where the track will start.
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @param TRACK_START
     */
    public void setTrackStart(final double TRACK_START)
    {
        if (TRACK_START <= getMinValue() || TRACK_START >= getMaxValue() || TRACK_START >= getTrackStop())
        {
            this.trackStart = getMinValue();
        }
        else
        {
            this.trackStart = TRACK_START;
        }
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TRACK);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the value of the point between trackStart and trackStop.
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @return represents the value where the intermediate position
     * of the track is defined.
     */
    public double getTrackSection()
    {
        return this.trackSection;
    }

    /**
     * Sets the value of the point between trackStart and trackStop.
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @param TRACK_SECTION
     */
    public void setTrackSection(final double TRACK_SECTION)
    {
        if (TRACK_SECTION <= getMinValue() || TRACK_SECTION >= getMaxValue() || TRACK_SECTION <= getTrackStart() || TRACK_SECTION >= getTrackStop())
        {
            this.trackSection = (getTrackStart() + (getTrackStop() - getTrackStart()) / 2.0);
        }
        else
        {
            this.trackSection = TRACK_SECTION;
        }
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TRACK);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the value of the point where the track will stop
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @return represents the position where the track stops
     */
    public double getTrackStop()
    {
        return this.trackStop;
    }

    /**
     * Sets the value of the end of the track.
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @param TRACK_STOP
     */
    public void setTrackStop(final double TRACK_STOP)
    {
        if ((TRACK_STOP <= getMinValue()) || TRACK_STOP >= getMaxValue() || TRACK_STOP <= getTrackStart())
        {
            this.trackStop = getMaxValue();
        }
        else
        {
            this.trackStop = TRACK_STOP;
        }
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TRACK);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the color of the point where the track will start.
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @return represents the color at the point where the track starts
     */
    public java.awt.Color getTrackStartColor()
    {
        return this.trackStartColor;
    }

    /**
     * Sets the color of the point where the track will start.
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @param TRACK_START_COLOR
     */
    public void setTrackStartColor(final java.awt.Color TRACK_START_COLOR)
    {
        this.trackStartColor = TRACK_START_COLOR;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TRACK);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the color of the value between trackStart and trackStop
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @return represents the color of the intermediate position on the track
     */
    public java.awt.Color getTrackSectionColor()
    {
        return this.trackSectionColor;
    }

    /**
     * Sets the color of the value between trackStart and trackStop
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @param TRACK_SECTION_COLOR
     */
    public void setTrackSectionColor(final java.awt.Color TRACK_SECTION_COLOR)
    {
        this.trackSectionColor = TRACK_SECTION_COLOR;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TRACK);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the color of the point where the track will stop.
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @return represents the color of the point where the track stops
     */
    public java.awt.Color getTrackStopColor()
    {
        return this.trackStopColor;
    }

    /**
     * Sets the color of the point where the track will stop.
     * The track is a area that could be defined by a start value,
     * a section stop value. This area will be painted with a
     * gradient that uses two or three given colors.
     * E.g. a critical area of a thermometer could be defined between
     * 30 and 100 degrees celsius and could have a gradient from
     * green over yellow to red. In this case the start
     * value would be 30, the stop value would be 100 and the section could
     * be somewhere between 30 and 100 degrees.
     * @param TRACK_STOP_COLOR
     */
    public void setTrackStopColor(final java.awt.Color TRACK_STOP_COLOR)
    {
        this.trackStopColor = TRACK_STOP_COLOR;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TRACK);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }
    //
    
    // 
    /**
     * Returns the visibility of the sections.
     * The sections could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The sections are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you could not visualize with the
     * track feature.
     * @return true if the sections are visible
     */
    public boolean isSectionsVisible()
    {
        return this.sectionsVisible;
    }

    /**
     * Sets the visibility of the sections.
     * The sections could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The sections are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you could not visualize with the
     * track feature.
     * @param SECTIONS_VISIBLE
     */
    public void setSectionsVisible(final boolean SECTIONS_VISIBLE)
    {
        this.sectionsVisible = SECTIONS_VISIBLE;
        repaint(getInnerBounds());
    }

    /**
     * Returns a copy of the ArrayList that stores the sections.
     * The sections could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The sections are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you could not visualize with the
     * track feature.
     * @return a list of sections
     */
    protected java.util.ArrayList getSections()
    {        
        return (java.util.ArrayList) this.SECTIONS.clone();
    }

    /**
     * Sets the sections given in a array of sections (Section[])
     * The sections could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The sections are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you could not visualize with the
     * track feature.
     * @param SECTIONS_ARRAY
     */
    public void setSections(final eu.hansolo.steelseries.tools.Section... SECTIONS_ARRAY)
    {                
        SECTIONS.clear();        
        for (eu.hansolo.steelseries.tools.Section section : SECTIONS_ARRAY)
        {
            if (section.getStart() != -1 && section.getStop() != -1)
            {
                if ((section.getStart() < getMinValue()) || section.getStart() >= getMaxValue() || section.getStart() >= section.getStop())
                {
                    section.setStart(getMinValue());
                }

                if (section.getStop() < getMinValue() || section.getStop() > getMaxValue() || section.getStop() <= section.getStart())
                {
                    section.setStop(getMaxValue());
                }
            }
            SECTIONS.add(new eu.hansolo.steelseries.tools.Section(section.getStart(), section.getStop(), section.getColor()));
        }
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Adds a given section to the list of sections
     * The sections could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The sections are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you could not visualize with the
     * track feature.
     * @param SECTION
     */
    public void addSection(final eu.hansolo.steelseries.tools.Section SECTION)
    {
        SECTIONS.add(new eu.hansolo.steelseries.tools.Section(SECTION.getStart(), SECTION.getStop(), SECTION.getColor()));
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Clear the SECTIONS arraylist
     */
    public void resetSections()
    {
        SECTIONS.clear();
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }
    //
    
    // 
    /**
     * Returns the visibility of the areas.
     * The areas could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The areas are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you could not visualize with the
     * track feature.
     * @return true if the areas are visible
     */
    public boolean isAreasVisible()
    {
        return this.areasVisible;
    }

    /**
     * Sets the visibility of the areas.
     * The areas could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The areas are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you could not visualize with the
     * track feature.
     * @param AREAS_VISIBLE
     */
    public void setAreasVisible(final boolean AREAS_VISIBLE)
    {
        this.areasVisible = AREAS_VISIBLE;
        repaint(getInnerBounds());
    }

    /**
     * Returns a copy of the ArrayList that stores the areas.
     * The areas could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The areas are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you could not visualize with the
     * track feature.
     * @return a clone of the list of areas
     */
    protected java.util.ArrayList getAreas()
    {        
        return (java.util.ArrayList) this.AREAS.clone();
    }

    /**
     * Sets the areas given in a array of areas (Section[])
     * A local copy of the Section object will created and will
     * be stored in the component.
     * The areas could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The areas are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you could not visualize with the
     * track feature.
     * @param AREAS_ARRAY
     */
    public void setAreas(final eu.hansolo.steelseries.tools.Section... AREAS_ARRAY)
    {
        AREAS.clear();        
        for (eu.hansolo.steelseries.tools.Section area : AREAS_ARRAY)
        {
            if (area.getStart() != -1 && area.getStop() != -1)
            {
                if ((area.getStart() < getMinValue()) || area.getStart() >= getMaxValue() || area.getStart() >= area.getStop())
                {
                    area.setStart(getMinValue());
                }

                if (area.getStop() < getMinValue() || area.getStop() > getMaxValue() || area.getStop() <= area.getStart())
                {
                    area.setStop(getMaxValue());
                }
            }
            AREAS.add(new eu.hansolo.steelseries.tools.Section(area.getStart(), area.getStop(), area.getColor()));
        }
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Adds a given area to the list of areas
     * The areas could be defined by a start value, a stop value
     * and a color. One has to create a Section object from the
     * class eu.hansolo.steelseries.tools.Section.
     * The areas are stored in a ArrayList so there could be
     * multiple. This might be a useful feature if you need to have
     * exactly defined areas that you could not visualize with the
     * track feature.
     * @param AREA
     */
    public void addArea(final eu.hansolo.steelseries.tools.Section AREA)
    {
        AREAS.add(new eu.hansolo.steelseries.tools.Section(AREA.getStart(), AREA.getStop(), AREA.getColor()));
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Clear the AREAS arraylist
     */
    public void resetAreas()
    {
        AREAS.clear();
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }
    //
    
    // 
    /**
     * Returns the title of the gauge.
     * A title could be for example "Temperature".
     * @return the title of the gauge
     */
    public String getTitle()
    {
        return this.title;
    }

    /**
     * Sets the title of the gauge.
     * A title could be for example "Temperature".
     * @param TITLE
     */
    public void setTitle(final String TITLE)
    {
        this.title = TITLE;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TITLE);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the unit string of the gauge.
     * A unit string could be for example "[cm]".
     * @return the unit string of the gauge
     */
    public String getUnitString()
    {
        return this.unitString;
    }

    /**
     * Sets the unit string of the gauge.
     * A unit string could be for example "[cm]"
     * @param UNIT_STRING
     */
    public void setUnitString(final String UNIT_STRING)
    {
        this.unitString = UNIT_STRING;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TITLE);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.LCD);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns true if the color of the tickmarks will be
     * used from the defined background color.
     * @return true if the color for the tickmarks and labels
     * will be used from the selected backgroundcolor
     */
    public boolean isUsingLabelColorFromTheme()
    {
        return this.usingLabelColorFromTheme;
    }

    /**
     * Enables/disables the usage of a separate color for the
     * title and unit string.
     * @param USING_LABEL_COLOR_FROM_THEME
     */
    public void setUsingLabelColorFromTheme(final boolean USING_LABEL_COLOR_FROM_THEME)
    {
        this.usingLabelColorFromTheme = USING_LABEL_COLOR_FROM_THEME;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TITLE);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the color of the Title and the Unit string.
     * @return the color of the title and unit string
     */
    public java.awt.Color getLabelColor()
    {
        return this.labelColor;
    }

    /**
     * Sets the color of the Title and the Unit string.
     * @param LABEL_COLOR
     */
    public void setLabelColor(final java.awt.Color LABEL_COLOR)
    {
        this.labelColor = LABEL_COLOR;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TITLE);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns true if a custom font will be used for the title and unit string
     * @return true if a custom font will be used for the title and unit string
     */
    public boolean isUsingTitleAndUnitFont()
    {
        return this.usingTitleAndUnitFont;
    }

    /**
     * Enables and disables the usage of a custom title and unit string font
     * @param USING_TITLE_AND_UNIT_FONT
     */
    public void setUsingTitleAndUnitFont(final boolean USING_TITLE_AND_UNIT_FONT)
    {
        this.usingTitleAndUnitFont = USING_TITLE_AND_UNIT_FONT;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TITLE);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Sets the given font for the title and unit string.
     * @return the custom defined font for the title and unit string
     */
    public java.awt.Font getTitleAndUnitFont()
    {
        return this.titleAndUnitFont;
    }

    /**
     * Returns the font that will be used for the title and unit string
     * @param TITLE_UNIT_FONT
     */
    public void setTitleAndUnitFont(final java.awt.Font TITLE_UNIT_FONT)
    {
        this.titleAndUnitFont = TITLE_UNIT_FONT;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TITLE);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }
    //
    
    // 
    /**
     * Returns the framedesign of the component.
     * The framedesign is some kind of a color scheme for the
     * frame of the component.
     * The typical framedesign is METAL
     * @return the selected framedesign
     */
    public eu.hansolo.steelseries.tools.FrameDesign getFrameDesign()
    {
        return this.frameDesign;
    }

    /**
     * Sets the framedesign of the component.
     * The framedesign is some kind of a color scheme for the
     * frame of the component.
     * The typical framedesign is METAL
     * @param FRAME_DESIGN
     */
    public void setFrameDesign(final eu.hansolo.steelseries.tools.FrameDesign FRAME_DESIGN)
    {
        this.frameDesign = FRAME_DESIGN;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.FRAME);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns true if the frameImage is visible and will be painted
     * @return a boolean that represents the visibility of the frameImage
     */
    public boolean isFrameVisible()
    {
        return this.frameVisible;
    }

    /**
     * Enables/Disables the visibility of the frame.
     * If enabled the frame will be painted in the paintComponent() method.
     * Setting the frameDesign to NO_FRAME will only make the frame transparent.
     * @param FRAME_VISIBLE
     */
    public void setFrameVisible(final boolean FRAME_VISIBLE)
    {
        this.frameVisible = FRAME_VISIBLE;
        repaint(getInnerBounds());
    }
    //

    // 
    /**
     * Returns the backgroundcolor of the gauge.
     * The backgroundcolor is not a standard color but more a
     * color scheme with colors and a gradient.
     * The typical backgroundcolor is DARK_GRAY.
     * @return the selected backgroundcolor
     */
    public eu.hansolo.steelseries.tools.BackgroundColor getBackgroundColor()
    {
        return this.backgroundColor;
    }

    /**
     * Sets the backgroundcolor of the gauge.
     * The backgroundcolor is not a standard color but more a
     * color scheme with colors and a gradient.
     * The typical backgroundcolor is DARK_GRAY.
     * @param BACKGROUND_COLOR
     */
    public void setBackgroundColor(final eu.hansolo.steelseries.tools.BackgroundColor BACKGROUND_COLOR)
    {
        this.backgroundColor = BACKGROUND_COLOR;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TITLE);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns true if the backgroundImage is visible and will be painted
     * @return a boolean that represents the visibility of the backgroundImage
     */
    public boolean isBackgroundVisible()
    {
        return this.backgroundVisible;
    }

    /**
     * Enables/Disables the visibility of the backgroundImage.
     * If enabled the backgroundImage will be painted in the
     * paintComponent() method. The backgroundColor TRANSPARENT
     * only makes the background transparent but the custom
     * background will still be visible.
     * @param BACKGROUND_VISIBLE
     */
    public void setBackgroundVisible(final boolean BACKGROUND_VISIBLE)
    {
        this.backgroundVisible = BACKGROUND_VISIBLE;
        repaint(getInnerBounds());
    }
    // 

    // 
    /**
     * Returns true if the custom background paint will be taken
     * instead of the background from the "theme" (e.g. "DARK_GRAY").
     * @return true if custom background paint is used
     */
    public boolean isCustomBackgroundVisible()
    {
        return this.customBackgroundVisible;
    }

    /**
     * Enables/disables the usage of a custom paint as
     * replacement for the predefined background colors like "DARK_GRAY" etc.
     * @param CUSTOM_BACKGROUND_VISIBLE
     */
    public void setCustomBackgroundVisible(final boolean CUSTOM_BACKGROUND_VISIBLE)
    {
        this.customBackgroundVisible = CUSTOM_BACKGROUND_VISIBLE;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the custom background paint that will be used instead of
     * the predefined backgroundcolors like DARK_GRAY, BEIGE etc.
     * @return the custom paint that will be used for the background of the gauge
     */
    public java.awt.Paint getCustomBackground()
    {
        return this.customBackground;
    }

    /**
     * Sets the custom background paint that will be used instead of
     * the predefined backgroundcolors like DARK_GRAY, BEIGE etc.
     * @param CUSTOM_BACKGROUND
     */
    public void setCustomBackground(final java.awt.Paint CUSTOM_BACKGROUND)
    {
        this.customBackground = CUSTOM_BACKGROUND;
        if (this.customBackgroundVisible)
        {
            IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
            init(getInnerBounds().width, getInnerBounds().height);
            repaint(getInnerBounds());
        }
    }        
    //
    
    // 
    /**
     * Returns true if the custom layer is visible.
     * The custom layer (which is a buffered image) will be
     * drawn on the background of the gauge and could be used
     * to display logos or icons.
     * @return true if custom layer is visible
     */
    public boolean isCustomLayerVisible()
    {
        return this.customLayerVisible;
    }

    /**
     * Enables/disables the usage of the custom layer.
     * The custom layer (which is a buffered image) will be
     * drawn on the background of the gauge and could be used
     * to display logos or icons.
     * @param CUSTOM_LAYER_VISIBLE
     */
    public void setCustomLayerVisible(final boolean CUSTOM_LAYER_VISIBLE)
    {
        if (this.customLayer != null)
        {
            this.customLayerVisible = CUSTOM_LAYER_VISIBLE;
        }
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    /**
     * Returns the buffered image that represents the custom layer.
     * The custom layer (which is a buffered image) will be
     * drawn on the background of the gauge and could be used
     * to display logos or icons.
     * @return the buffered image that represents the custom layer
     */
    public java.awt.image.BufferedImage getCustomLayer()
    {
        return this.customLayer;
    }

    /**
     * Sets the buffered image that represents the custom layer.
     * It will automaticaly scale the given image to the bounds.
     * The custom layer (which is a buffered image) will be
     * drawn on the background of the gauge and could be used
     * to display logos or icons.
     * @param CUSTOM_LAYER
     */
    public void setCustomLayer(final java.awt.image.BufferedImage CUSTOM_LAYER)
    {
        if (this.customLayer != null)
        {
            this.customLayer.flush();
        }

        if (CUSTOM_LAYER == null)
        {
            this.customLayerVisible = false;
            return;
        }

        this.customLayer = CUSTOM_LAYER;

        if (customLayerVisible)
        {
            IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
            init(getInnerBounds().width, getInnerBounds().height);
            repaint(getInnerBounds());
        }
    }
    //
    
    // 
    /**
     * Returns true if the foreground image is visible
     * The foreground image will only be painted if
     * it is set to true.
     * @return visibility of the foreground image
     */
    public boolean isForegroundVisible()
    {
        return this.foregroundVisible;
    }

    /**
     * Enables/Disables the visibility of the glass effect foreground image.
     * If enabled the foregroundImage will be painted.
     * @param FOREGROUND_VISIBLE
     */
    public void setForegroundVisible(final boolean FOREGROUND_VISIBLE)
    {
        this.foregroundVisible = FOREGROUND_VISIBLE;
        repaint(getInnerBounds());
    }
    //

    /**
     * Returns a image of a led with the given size, state and color.
     * @param SIZE
     * @param STATE
     * @param LED_COLOR
     * @return the led image 
     */
    protected final java.awt.image.BufferedImage create_LED_Image(final int SIZE, final int STATE, final eu.hansolo.steelseries.tools.LedColor LED_COLOR)
    {
        if (SIZE <= 0)
        {
            return null;
        }

        final java.awt.image.BufferedImage IMAGE = GFX_CONF.createCompatibleImage((int) (SIZE * 0.0934579439), (int) (SIZE * 0.0934579439), java.awt.Transparency.TRANSLUCENT);
        final java.awt.Graphics2D G2 = IMAGE.createGraphics();

        G2.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON);

        final int IMAGE_WIDTH = IMAGE.getWidth();
        final int IMAGE_HEIGHT = IMAGE.getHeight();

        // Define led data
        final java.awt.geom.Ellipse2D LED = new java.awt.geom.Ellipse2D.Double(0.25 * IMAGE_WIDTH, 0.25 * IMAGE_HEIGHT, 0.5 * IMAGE_WIDTH, 0.5 * IMAGE_HEIGHT);
        final java.awt.geom.Ellipse2D LED_CORONA = new java.awt.geom.Ellipse2D.Double(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);

        final java.awt.geom.Point2D LED_CENTER = new java.awt.geom.Point2D.Double(LED.getCenterX(), LED.getCenterY());

        final float[] LED_FRACTIONS =
        {
            0.0f,
            0.2f,
            1.0f
        };

        final java.awt.Color[] LED_OFF_COLORS =
        {
            LED_COLOR.INNER_COLOR1_OFF,
            LED_COLOR.INNER_COLOR2_OFF,
            LED_COLOR.OUTER_COLOR_OFF
        };

        final java.awt.Color[] LED_ON_COLORS =
        {
            LED_COLOR.INNER_COLOR1_ON,
            LED_COLOR.INNER_COLOR2_ON,
            LED_COLOR.OUTER_COLOR_ON
        };

        final float[] LED_INNER_SHADOW_FRACTIONS =
        {
            0.0f,
            0.8f,
            1.0f
        };

        final java.awt.Color[] LED_INNER_SHADOW_COLORS =
        {
            new java.awt.Color(0.0f, 0.0f, 0.0f, 0.0f),
            new java.awt.Color(0.0f, 0.0f, 0.0f, 0.0f),
            new java.awt.Color(0.0f, 0.0f, 0.0f, 0.4f),
        };

        final float[] LED_ON_CORONA_FRACTIONS =
        {
            0.0f,
            0.6f,
            0.7f,
            0.8f,
            0.85f,
            1.0f
        };

        final java.awt.Color[] LED_ON_CORONA_COLORS =
        {
            UTIL.setAlpha(LED_COLOR.CORONA_COLOR, 0.0f),
            UTIL.setAlpha(LED_COLOR.CORONA_COLOR, 0.4f),
            UTIL.setAlpha(LED_COLOR.CORONA_COLOR, 0.25f),
            UTIL.setAlpha(LED_COLOR.CORONA_COLOR, 0.15f),
            UTIL.setAlpha(LED_COLOR.CORONA_COLOR, 0.05f),
            UTIL.setAlpha(LED_COLOR.CORONA_COLOR, 0.0f)
        };

        // Define gradients for the lower led
        final java.awt.RadialGradientPaint LED_OFF_GRADIENT = new java.awt.RadialGradientPaint(LED_CENTER, 0.25f * IMAGE_WIDTH, LED_FRACTIONS, LED_OFF_COLORS);
        final java.awt.RadialGradientPaint LED_ON_GRADIENT = new java.awt.RadialGradientPaint(LED_CENTER, 0.25f * IMAGE_WIDTH, LED_FRACTIONS, LED_ON_COLORS);
        final java.awt.RadialGradientPaint LED_INNER_SHADOW_GRADIENT = new java.awt.RadialGradientPaint(LED_CENTER, 0.25f * IMAGE_WIDTH, LED_INNER_SHADOW_FRACTIONS, LED_INNER_SHADOW_COLORS);
        final java.awt.RadialGradientPaint LED_ON_CORONA_GRADIENT = new java.awt.RadialGradientPaint(LED_CENTER, 0.5f * IMAGE_WIDTH, LED_ON_CORONA_FRACTIONS, LED_ON_CORONA_COLORS);


        // Define light reflex data
        final java.awt.geom.Ellipse2D LED_LIGHTREFLEX = new java.awt.geom.Ellipse2D.Double(0.4 * IMAGE_WIDTH, 0.35 * IMAGE_WIDTH, 0.2 * IMAGE_WIDTH, 0.15 * IMAGE_WIDTH);
        final java.awt.geom.Point2D LED_LIGHTREFLEX_START = new java.awt.geom.Point2D.Double(0, LED_LIGHTREFLEX.getMinY());
        final java.awt.geom.Point2D LED_LIGHTREFLEX_STOP = new java.awt.geom.Point2D.Double(0, LED_LIGHTREFLEX.getMaxY());

        final float[] LIGHT_REFLEX_FRACTIONS =
        {
            0.0f,
            1.0f
        };

        final java.awt.Color[] LIGHTREFLEX_COLORS =
        {
            new java.awt.Color(1.0f, 1.0f, 1.0f, 0.4f),
            new java.awt.Color(1.0f, 1.0f, 1.0f, 0.0f)
        };

        // Define light reflex gradients
        final java.awt.LinearGradientPaint LED_LIGHTREFLEX_GRADIENT = new java.awt.LinearGradientPaint(LED_LIGHTREFLEX_START, LED_LIGHTREFLEX_STOP, LIGHT_REFLEX_FRACTIONS, LIGHTREFLEX_COLORS);


        switch (STATE)
        {
            case 0:
                // LED OFF
                G2.setPaint(LED_OFF_GRADIENT);
                G2.fill(LED);
                G2.setPaint(LED_INNER_SHADOW_GRADIENT);
                G2.fill(LED);
                G2.setPaint(LED_LIGHTREFLEX_GRADIENT);
                G2.fill(LED_LIGHTREFLEX);
                break;
            case 1:
                // LED ON
                G2.setPaint(LED_ON_CORONA_GRADIENT);
                G2.fill(LED_CORONA);
                G2.setPaint(LED_ON_GRADIENT);
                G2.fill(LED);
                G2.setPaint(LED_INNER_SHADOW_GRADIENT);
                G2.fill(LED);
                G2.setPaint(LED_LIGHTREFLEX_GRADIENT);
                G2.fill(LED_LIGHTREFLEX);
                break;
            default:
                // LED OFF
                G2.setPaint(LED_OFF_GRADIENT);
                G2.fill(LED);
                G2.setPaint(LED_INNER_SHADOW_GRADIENT);
                G2.fill(LED);
                G2.setPaint(LED_LIGHTREFLEX_GRADIENT);
                G2.fill(LED_LIGHTREFLEX);
                break;
        }

        G2.dispose();

        return IMAGE;
    }
    
    /**
     * Calculates the rectangle that is defined by the dimension of the component
     * and it's insets given by e.g. a border.
     */
    abstract public void calcInnerBounds();

    /**
     * Returns the rectangle that is defined by the dimension of the component and
     * it's insets given by e.g. a border.
     * @return rectangle that defines the inner area available for painting
     */
    abstract public java.awt.Rectangle getInnerBounds();
        
    /**
     * Returns a point2d object that defines the center of the gauge.
     * This method will take the insets and the real position of the
     * gauge into account.
     * @return a point2d object that represents the center of the gauge
     */
    abstract protected java.awt.geom.Point2D getCenter();

    /**
     * Returns the boundary of the gauge itself as a rectangle2d.
     * @return a rectangle2d that represents the boundary of the gauge itself
     */
    abstract protected java.awt.geom.Rectangle2D getBounds2D();

    /**
     * Calculates the stepsize of the radial gauge dependend
     * on the type of radial gauge.
     */
    protected void calcAngleStep()
    {        
    }

    /**
     * Fills the EnumSet with all ImageTypes so that the next time the init method
     * will be called all images will be recreated
     */
    protected void recreateAllImages()
    {
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.FRAME);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BACKGROUND);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.POSTS);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.BARGRAPHTRACK);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TRACK);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TICKMARKS);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TITLE);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.THRESHOLD);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.MIN_MEASURED);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.MAX_MEASURED);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.LCD);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.POINTER);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.POINTER_SHADOW);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.FOREGROUND);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.DISABLED);
    }

    @Override
    public void setBorder(final javax.swing.border.Border BORDER)
    {
        super.setBorder(BORDER);
        calcInnerBounds();
        recreateAllImages();
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    // 
    @Override
    public void componentResized(java.awt.event.ComponentEvent event)
    {
        // Radial gauge
        if (event.getComponent() instanceof AbstractRadial)
        {
            final int SIZE = getWidth() < getHeight() ? getWidth() : getHeight();        
            setSize(SIZE, SIZE);
            setPreferredSize(getSize());            

            if (SIZE < getMinimumSize().width || SIZE < getMinimumSize().height)
            {
                setSize(getMinimumSize());
            }

            calcInnerBounds();

            recreateLedImages();
            if (isLedOn())
            {
                setCurrentLedImage(getLedImageOn());
            }
            else
            {
                setCurrentLedImage(getLedImageOff());
            }

            recreateAllImages();

            init(getInnerBounds().width, getInnerBounds().height);
            revalidate();
            repaint();
        }
        
        // Linear gauge
        if (event.getComponent() instanceof AbstractLinear)
        {
            setSize(getWidth(), getHeight());            
            setPreferredSize(getSize());
            calcInnerBounds();

            if (getWidth() >= getHeight())
            {
                // Horizontal
                setOrientation(eu.hansolo.steelseries.tools.Orientation.HORIZONTAL);
                recreateLedImages(getInnerBounds().height);

                if (isLedOn())
                {
                    setCurrentLedImage(getLedImageOn());
                }
                else
                {
                    setCurrentLedImage(getLedImageOff());
                }
                setLedPositionX((getInnerBounds().width - 18.0 - 16.0) / getInnerBounds().width);
                setLedPositionY(0.453271028);
            }
            else
            {
                // Vertical
                setOrientation(eu.hansolo.steelseries.tools.Orientation.VERTICAL);
                recreateLedImages(getInnerBounds().width);

                if (isLedOn())
                {
                    setCurrentLedImage(getLedImageOn());
                }
                else
                {
                    setCurrentLedImage(getLedImageOff());
                }
                setLedPositionX(0.453271028);
                setLedPositionY(18.0 / getInnerBounds().height);
            }        

            recreateAllImages();
            init(getInnerBounds().width, getInnerBounds().height); 
            revalidate();
            repaint();
        }
    }

    @Override
    public void componentMoved(java.awt.event.ComponentEvent event)
    {
    }

    @Override
    public void componentShown(java.awt.event.ComponentEvent event)
    {
    }

    @Override
    public void componentHidden(java.awt.event.ComponentEvent event)
    {
    }
    //
    
    // 
    
    /**
     * Add a given ChangeListener to the list of listeners
     * @param LISTENER 
     */
    public void addChangeListener(final javax.swing.event.ChangeListener LISTENER) 
    {
        LISTENER_LIST.add(javax.swing.event.ChangeListener.class, LISTENER);
    }

    /**
    * Remove the given ChangeListener from the list of listeners
    * @param LISTENER 
    */
    public void removeChangeListener(javax.swing.event.ChangeListener LISTENER) 
    {
        LISTENER_LIST.remove(javax.swing.event.ChangeListener.class, LISTENER);
    }

    /**
     * Notify all registered listeners about a state change
     */
    protected void fireStateChanged() 
    {
        Object[] listeners = LISTENER_LIST.getListenerList();
        
        // Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = listeners.length - 2; i >= 0; i -= 2) 
        {
            if (listeners[i] == javax.swing.event.ChangeListener.class) 
            {
                if (changeEvent == null)
                {
                    changeEvent = new javax.swing.event.ChangeEvent(this);
                }
                ((javax.swing.event.ChangeListener) listeners[i + 1]).stateChanged(changeEvent);
            }
        }
    }
    // 
  
    // 
    @Override
    public void actionPerformed(final java.awt.event.ActionEvent EVENT)
    {
        if (EVENT.getSource().equals(LED_BLINKING_TIMER))
        {
            currentLedImage.flush();
            currentLedImage = ledOn == true ? getLedImageOn() : getLedImageOff();
            ledOn ^= true;

            repaint((int) (getInnerBounds().width * ledPositionX + getInnerBounds().x), (int) (getInnerBounds().height * ledPositionY + getInnerBounds().y), currentLedImage.getWidth(), currentLedImage.getHeight());
        }

        if (EVENT.getSource().equals(PEAK_TIMER))
        {
            setPeakValueVisible(false);
            PEAK_TIMER.stop();
        }
    }
    // 
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy