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

eu.hansolo.steelseries.gauges.AbstractLinear 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, indicators from cars and some instruments from airplanes and sailboats.

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


/**
 *
 * @author hansolo
 */
public abstract class AbstractLinear extends AbstractGauge implements Lcd
{    
    //     
    private final java.awt.Rectangle INNER_BOUNDS;
    private final java.awt.GraphicsConfiguration GFX_CONF; 
    // Bar related
    private boolean startingFromZero;
    private eu.hansolo.steelseries.tools.ColorDef valueColor;
    private eu.hansolo.steelseries.tools.CustomColorDef customValueColor;
    // LCD related variables
    private boolean valueCoupled;
    private String lcdUnitString;
    private boolean lcdUnitStringVisible;
    private boolean lcdScientificFormat;
    private double lcdValue;
    private boolean lcdVisible;
    private boolean digitalFont;
    private java.awt.Font lcdValueFont;
    private java.awt.Font lcdUnitFont;
    private boolean useCustomLcdUnitFont;
    protected static final java.awt.Font LCD_STANDARD_FONT = new java.awt.Font("Verdana", 1, 24);  
    protected static final java.awt.Font LCD_DIGITAL_FONT = eu.hansolo.steelseries.tools.Util.INSTANCE.getDigitalFont().deriveFont(24);
    private java.awt.Font customLcdUnitFont;
    private eu.hansolo.steelseries.tools.LcdColor lcdColor;
    private java.awt.Paint customLcdBackground;
    private java.awt.Color customLcdForeground;
    private int lcdDecimals;
    private final org.pushingpixels.trident.Timeline LCD_TIMELINE;
    // Animation related variables
    private final org.pushingpixels.trident.Timeline TIMELINE;
    private final org.pushingpixels.trident.ease.TimelineEase STANDARD_EASING;
    private final org.pushingpixels.trident.ease.TimelineEase RETURN_TO_ZERO_EASING;
    private final org.pushingpixels.trident.callback.TimelineCallback TIMELINE_CALLBACK;
    // 
    
    // 
    public AbstractLinear()
    {
        super();
        INNER_BOUNDS = new java.awt.Rectangle(getPreferredSize());   
        GFX_CONF = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
        startingFromZero = false;
        valueColor = eu.hansolo.steelseries.tools.ColorDef.RED;
        customValueColor = new eu.hansolo.steelseries.tools.CustomColorDef(java.awt.Color.RED);
        setLedPositionX((getInnerBounds().width - 18.0 - 16.0) / getInnerBounds().width);
        setLedPositionY(0.453271028);        
        setOrientation(eu.hansolo.steelseries.tools.Orientation.HORIZONTAL);
        //addComponentListener(this);
        valueCoupled = true;            
        lcdUnitStringVisible = false;
        lcdScientificFormat = false;
        lcdValue = 0;   
        lcdVisible = false;
        digitalFont = false;                        
        customLcdUnitFont = new java.awt.Font("Verdana", 1, 24);
        lcdColor = eu.hansolo.steelseries.tools.LcdColor.WHITE_LCD;
        customLcdBackground = java.awt.Color.BLACK;
        customLcdForeground = java.awt.Color.WHITE;
        lcdDecimals = 0;
        LCD_TIMELINE = new org.pushingpixels.trident.Timeline(this);
        lcdUnitString = getUnitString();
        TIMELINE = new org.pushingpixels.trident.Timeline(this);
        STANDARD_EASING = new org.pushingpixels.trident.ease.Spline(0.5f);
        RETURN_TO_ZERO_EASING = new org.pushingpixels.trident.ease.Sine();
        TIMELINE_CALLBACK = new org.pushingpixels.trident.callback.TimelineCallback()
        {        
            @Override
            public void onTimelineStateChanged(final org.pushingpixels.trident.Timeline.TimelineState OLD_STATE, final org.pushingpixels.trident.Timeline.TimelineState NEW_STATE, final float OLD_VALUE, final float NEW_VALUE)
            {
                if (NEW_STATE == org.pushingpixels.trident.Timeline.TimelineState.IDLE)
                {
                    repaint(getInnerBounds());
                }
                
                // Check if current value exceeds maxMeasuredValue
                if (getValue() > getMaxMeasuredValue())
                {
                    setMaxMeasuredValue(getValue());
                }
            }

            @Override
            public void onTimelinePulse(final float OLD_VALUE, final float NEW_VALUE)
            {      
                final double CURRENT_VALUE = getValue();
                
                // Check if current value exceeds maxMeasuredValue
                if (CURRENT_VALUE > getMaxMeasuredValue())
                {
                    setMaxMeasuredValue(CURRENT_VALUE);
                }

                // Check if current value exceeds minMeasuredValue
                if (CURRENT_VALUE < getMinMeasuredValue())
                {
                    setMinMeasuredValue(CURRENT_VALUE);
                }
            }
        };
        TIMELINE.addCallback(TIMELINE_CALLBACK);        
    }
    // 
    
    // 
    /**
     * Uses trident animation library to animate
     * the setting of the value.
     * The method plays a defined trident timeline
     * that calls the setValue(double value) method
     * with a given easing behaviour and duration.
     * You should always use this method to set the
     * gauge to a given value.
     * @param VALUE
     */
    public void setValueAnimated(final double VALUE)
    {        
        if (isEnabled())
        {
            if (TIMELINE.getState() != org.pushingpixels.trident.Timeline.TimelineState.IDLE)
            {
                TIMELINE.abort();            
            }

            final double OVERALL_RANGE = getMaxValue() - getMinValue();
            final double RANGE = Math.abs(getValue() - VALUE);
            final double FRACTION = RANGE / OVERALL_RANGE;

            if (isAutoResetToZero())
            {
                final org.pushingpixels.trident.TimelineScenario AUTOZERO_SCENARIO = new org.pushingpixels.trident.TimelineScenario.Sequence();

                final org.pushingpixels.trident.Timeline TIMELINE_TO_VALUE = new org.pushingpixels.trident.Timeline(this);
                TIMELINE_TO_VALUE.addPropertyToInterpolate("value", getValue(), VALUE);
                TIMELINE_TO_VALUE.setEase(RETURN_TO_ZERO_EASING);
                TIMELINE_TO_VALUE.setDuration((long) (getRtzTimeToValue() * FRACTION));
                TIMELINE_TO_VALUE.addCallback(new org.pushingpixels.trident.callback.TimelineCallback()
                {
                    @Override
                    public void onTimelineStateChanged(org.pushingpixels.trident.Timeline.TimelineState oldState, org.pushingpixels.trident.Timeline.TimelineState newState, float oldValue, float newValue)
                    {            
                        if (oldState == org.pushingpixels.trident.Timeline.TimelineState.PLAYING_FORWARD && newState == org.pushingpixels.trident.Timeline.TimelineState.DONE)
                        {
                            // Set the peak value and start the timer
                            setPeakValue(getValue());
                            setPeakValueVisible(true);
                            if (getPeakTimer().isRunning())
                            {
                                stopPeakTimer();
                            }
                            startPeakTimer();

                            // Check if current value exceeds maxMeasuredValue
                            if (getValue() > getMaxMeasuredValue())
                            {
                                setMaxMeasuredValue(getValue());
                            }                    
                        }
                    }

                    @Override
                    public void onTimelinePulse(float oldValue, float newValue)
                    {
                        final double CURRENT_VALUE = getValue();

                        // Check if current value exceeds maxMeasuredValue
                        if (CURRENT_VALUE > getMaxMeasuredValue())
                        {
                            setMaxMeasuredValue(CURRENT_VALUE);
                        }

                        // Check if current value exceeds minMeasuredValue
                        if (CURRENT_VALUE < getMinMeasuredValue())
                        {
                            setMinMeasuredValue(CURRENT_VALUE);
                        }
                    }
                });

                final org.pushingpixels.trident.Timeline TIMELINE_TO_ZERO = new org.pushingpixels.trident.Timeline(this);
                TIMELINE_TO_ZERO.addPropertyToInterpolate("value", VALUE, 0.0);
                TIMELINE_TO_ZERO.setEase(RETURN_TO_ZERO_EASING);
                TIMELINE_TO_ZERO.setDuration((long) (getRtzTimeBackToZero() * FRACTION));

                AUTOZERO_SCENARIO.addScenarioActor(TIMELINE_TO_VALUE);
                AUTOZERO_SCENARIO.addScenarioActor(TIMELINE_TO_ZERO);

                AUTOZERO_SCENARIO.addCallback(new org.pushingpixels.trident.callback.TimelineScenarioCallback()
                {
                    @Override
                    public void onTimelineScenarioDone()
                    {

                    }
                });

                AUTOZERO_SCENARIO.play();
            }      
            else
            {
                TIMELINE.addPropertyToInterpolate("value", getValue(), VALUE);
                TIMELINE.setEase(STANDARD_EASING);
                TIMELINE.setDuration((long) (getStdTimeToValue() * FRACTION));
                TIMELINE.play();
            }    
        }
    }
 
    /**
     * Returns the color of the bar
     * @return the selected color of the bar
     */
    public eu.hansolo.steelseries.tools.ColorDef getValueColor()
    {
        return this.valueColor;
    }

    /**
     * Sets the color of the bar
     * @param VALUE_COLOR
     */
    public void setValueColor(final eu.hansolo.steelseries.tools.ColorDef VALUE_COLOR)
    {
        this.valueColor = VALUE_COLOR;
        repaint(getInnerBounds());
    }

    /**
     * Returns the object that represents holds the custom value color
     * @return the object that represents the custom value color
     */
    public eu.hansolo.steelseries.tools.CustomColorDef getCustomValueColorObject()
    {
        return this.customValueColor;
    }
    
    /**
     * Returns the color of the bar from which the custom bar color will calculated
     * @return the color of the bar from which the custom bar color will be calculated
     */
    public java.awt.Color getCustomValueColor()
    {
        return this.customValueColor.COLOR;
    }
    
    /**
     * Sets the color of the bar from which the custom bar color will be calculated
     * @param COLOR 
     */
    public void setCustomValueColor(final java.awt.Color COLOR)
    {
        this.customValueColor = new eu.hansolo.steelseries.tools.CustomColorDef(COLOR);
        repaint(getInnerBounds());
    }
    
    /**
     * Returns true if the bar/bargraph will always start from zero instead from
     * the minValue. This could be useful if you would like to create something
     * like a g-force meter, where 0 is in the center of the range and the bar
     * could move in negative and positive direction. In combination with 
     * AutoReturnToZero this feature might be useful.
     * @return true if the bar/bargraph will always start to in-/decrease from zero
     */
    public boolean isStartingFromZero()
    {
        return this.startingFromZero;
    }

    /**
     * Enables/Disables the feature that the bar/bargraph will always start from zero
     * instead from the minValue. This could be useful if you would like to create
     * something like a g-force meter, where 0 is in the center of the range and
     * the bar could move in negative and positive direction. In combination with
     * AutoReturnToZero this feature might be useful.
     * @param STARTING_FROM_ZERO
     */
    public void setStartingFromZero(final boolean STARTING_FROM_ZERO)
    {
        this.startingFromZero = STARTING_FROM_ZERO;
    }

    protected void createLedImages()
    {
        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
        {
            recreateLedImages(getWidth());
        }
        else
        {
            recreateLedImages(getHeight());
        }
    }
    
    /**
     * Returns the visibility of the lcd display
     * @return true if the lcd display is visible
     */
    public boolean isLcdVisible()
    {
        return this.lcdVisible;
    }
    
    /**
     * Enables or disables the visibility of the lcd display
     * @param LCD_VISIBLE 
     */
    public void setLcdVisible(final boolean LCD_VISIBLE)
    {
        this.lcdVisible = LCD_VISIBLE;
        repaint(getInnerBounds());
    }
    
    @Override
    public boolean isValueCoupled()
    {
        return this.valueCoupled;
    }
    
    @Override
    public void setValueCoupled(final boolean VALUE_COUPLED)
    {
        this.valueCoupled = VALUE_COUPLED;
        repaint(getInnerBounds());
    }
    
    @Override
    public double getLcdValue()
    {
        return this.lcdValue;
    }

    @Override
    public void setLcdValue(final double LCD_VALUE)
    {
        this.lcdValue = LCD_VALUE;
        repaint(getInnerBounds());
    }

    @Override
    public void setLcdValueAnimated(final double LCD_VALUE)
    {
        if (LCD_TIMELINE.getState() == org.pushingpixels.trident.Timeline.TimelineState.PLAYING_FORWARD || LCD_TIMELINE.getState() == org.pushingpixels.trident.Timeline.TimelineState.PLAYING_REVERSE)
        {
            LCD_TIMELINE.abort();
        }
        LCD_TIMELINE.addPropertyToInterpolate("lcdValue", this.lcdValue, LCD_VALUE);
        LCD_TIMELINE.setEase(new org.pushingpixels.trident.ease.Spline(0.5f));
  
        LCD_TIMELINE.play();
    }

    @Override
    public String getLcdUnitString()
    {
        return lcdUnitString;
    }

    @Override
    public void setLcdUnitString(final String UNIT_STRING)
    {
        this.lcdUnitString = UNIT_STRING;
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    @Override
    public boolean isLcdUnitStringVisible()
    {
        return lcdUnitStringVisible;
    }

    @Override
    public void setLcdUnitStringVisible(final boolean UNIT_STRING_VISIBLE)
    {
        this.lcdUnitStringVisible = UNIT_STRING_VISIBLE;
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    @Override
    public boolean isDigitalFont()
    {
        return this.digitalFont;
    }

    @Override
    public void setDigitalFont(final boolean DIGITAL_FONT)
    {
        this.digitalFont = DIGITAL_FONT;
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    @Override
    public boolean getUseCustomLcdUnitFont()
    {
        return this.useCustomLcdUnitFont;
    }

    @Override
    public void setUseCustomLcdUnitFont(final boolean USE_CUSTOM_LCD_UNIT_FONT)
    {
        useCustomLcdUnitFont = USE_CUSTOM_LCD_UNIT_FONT;
        repaint(getInnerBounds());
    }

    @Override
    public java.awt.Font getCustomLcdUnitFont()
    {
        return this.customLcdUnitFont;
    }

    @Override
    public void setCustomLcdUnitFont(final java.awt.Font CUSTOM_LCD_UNIT_FONT)
    {
        customLcdUnitFont = CUSTOM_LCD_UNIT_FONT;
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    @Override
    public int getLcdDecimals()
    {
        return this.lcdDecimals;
    }

    @Override
    public void setLcdDecimals(final int DECIMALS)
    {
        this.lcdDecimals = DECIMALS;
        repaint(getInnerBounds());
    }

    @Override
    public eu.hansolo.steelseries.tools.LcdColor getLcdColor()
    {
        return this.lcdColor;
    }

    @Override
    public void setLcdColor(final eu.hansolo.steelseries.tools.LcdColor COLOR)
    {
        this.lcdColor = COLOR;
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }

    @Override
    public java.awt.Paint getCustomLcdBackground()
    {
        return this.customLcdBackground;
    }
    
    @Override
    public void setCustomLcdBackground(final java.awt.Paint CUSTOM_LCD_BACKGROUND)
    {
        this.customLcdBackground = CUSTOM_LCD_BACKGROUND;
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }
    
    @Override
    public java.awt.Color getCustomLcdForeground()
    {
        return this.customLcdForeground;
    }
    
    @Override
    public void setCustomLcdForeground(final java.awt.Color CUSTOM_LCD_FOREGROUND)
    {
        this.customLcdForeground = CUSTOM_LCD_FOREGROUND;
        init(getInnerBounds().width, getInnerBounds().height);
        repaint(getInnerBounds());
    }
    
    @Override
    public String formatLcdValue(final double VALUE)
    {
        final StringBuilder DEC_BUFFER = new StringBuilder();
        DEC_BUFFER.append("0");

        if (this.lcdDecimals > 0)
        {
            DEC_BUFFER.append(".");
        }

        for (int i = 0; i < this.lcdDecimals; i++)
        {
            DEC_BUFFER.append("0");
        }

        if(lcdScientificFormat)
        {
            DEC_BUFFER.append("E0");
        }

        final java.text.DecimalFormat DEC_FORMAT = new java.text.DecimalFormat(DEC_BUFFER.toString(), new java.text.DecimalFormatSymbols(java.util.Locale.US));

        return DEC_FORMAT.format(VALUE);
    }

    @Override
    public boolean isLcdScientificFormat()
    {
        return this.lcdScientificFormat;
    }

    @Override
    public void setLcdScientificFormat(boolean LCD_SCIENTIFIC_FORMAT)
    {
        lcdScientificFormat = LCD_SCIENTIFIC_FORMAT;
        repaint(getInnerBounds());
    }
    
    @Override
    public java.awt.Font getLcdValueFont()
    {
        return this.lcdValueFont;
    }
    
    @Override
    public void setLcdValueFont(final java.awt.Font LCD_VALUE_FONT)
    {
        this.lcdValueFont = LCD_VALUE_FONT;
        repaint(getInnerBounds());
    }
    
    @Override
    public java.awt.Font getLcdUnitFont()
    {
        return this.lcdUnitFont;
    }
    
    @Override
    public void setLcdUnitFont(final java.awt.Font LCD_UNIT_FONT)
    {
        this.lcdUnitFont = LCD_UNIT_FONT;
        repaint(getInnerBounds());
    }
    // 

    // 
    /**
     * Returns the frame image with the currently active framedesign
     * with the given with and height.
     * @param WIDTH
     * @param HEIGHT
     * @return buffered image containing the frame in the active frame design
     */
    protected java.awt.image.BufferedImage create_FRAME_Image(final int WIDTH, final int HEIGHT)
    {
        return FRAME_FACTORY.createLinearFrame(WIDTH, HEIGHT, getFrameDesign(), getCustomFrameDesign(), isFrame3dEffectVisible());
    }

    /**
     * Returns the background image with the currently active backgroundcolor
     * with the given width and height.
     * @param WIDTH
     * @param HEIGHT
     * @return buffered image containing the background with the selected background design
     */
    protected java.awt.image.BufferedImage create_BACKGROUND_Image(final int WIDTH, final int HEIGHT)
    {
        if (WIDTH <= 0 || HEIGHT <= 0)
        {
            return GFX_CONF.createCompatibleImage(140, 140, java.awt.Transparency.TRANSLUCENT);
        }

        final java.awt.image.BufferedImage IMAGE = GFX_CONF.createCompatibleImage(WIDTH, HEIGHT, java.awt.Transparency.TRANSLUCENT);
        final java.awt.Graphics2D G2 = IMAGE.createGraphics();
        G2.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
        G2.setRenderingHint(java.awt.RenderingHints.KEY_STROKE_CONTROL, java.awt.RenderingHints.VALUE_STROKE_PURE);

        final int IMAGE_WIDTH = IMAGE.getWidth();
        final int IMAGE_HEIGHT = IMAGE.getHeight();
       
        // Draw the background image
        G2.drawImage(BACKGROUND_FACTORY.createLinearBackground(WIDTH, HEIGHT, getBackgroundColor(), getCustomBackground()), 0, 0, null);

        // Draw the custom layer if selected
        if (isCustomLayerVisible())
        {
            G2.drawImage(UTIL.getScaledInstance(getCustomLayer(), IMAGE_WIDTH, IMAGE_HEIGHT, java.awt.RenderingHints.VALUE_INTERPOLATION_BICUBIC, true), 0, 0, null);
        }

        G2.dispose();

        return IMAGE;
    }

    /**
     * Returns the track image with the given values.
     * @param WIDTH
     * @param HEIGHT
     * @param MIN_VALUE
     * @param MAX_VALUE
     * @param TRACK_START
     * @param TRACK_SECTION
     * @param TRACK_STOP
     * @param TRACK_START_COLOR
     * @param TRACK_SECTION_COLOR
     * @param TRACK_STOP_COLOR
     * @return a buffered image of the track colored with the given values
     */
    protected java.awt.image.BufferedImage create_TRACK_Image(final int WIDTH, final int HEIGHT, final double MIN_VALUE, final double MAX_VALUE, final double TRACK_START, final double TRACK_SECTION, final double TRACK_STOP, final java.awt.Color TRACK_START_COLOR, final java.awt.Color TRACK_SECTION_COLOR, final java.awt.Color TRACK_STOP_COLOR)
    {
        if (WIDTH <= 0 || HEIGHT <= 0)
        {
            return GFX_CONF.createCompatibleImage(140, 140, java.awt.Transparency.TRANSLUCENT);
        }

        if (TRACK_STOP > MAX_VALUE)
        {
            throw new IllegalArgumentException("Please adjust track start and/or track stop values");
        }
                
        final java.awt.image.BufferedImage IMAGE = GFX_CONF.createCompatibleImage(WIDTH, HEIGHT, 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();
        
        final java.awt.geom.Rectangle2D TRACK;
        final java.awt.geom.Point2D TRACK_START_POINT;
        final java.awt.geom.Point2D TRACK_STOP_POINT;

        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
        {            
                // Vertical orientation
                TRACK = new java.awt.geom.Rectangle2D.Double(IMAGE_WIDTH * 0.315, IMAGE_HEIGHT * 0.1276, IMAGE_WIDTH * 0.05, IMAGE_HEIGHT * 0.7280);
                TRACK_START_POINT = new java.awt.geom.Point2D.Double(0, TRACK.getMaxY());
                TRACK_STOP_POINT = new java.awt.geom.Point2D.Double(0, TRACK.getMinY());
        }
        else
        {
                // Horizontal orientation
                TRACK = new java.awt.geom.Rectangle2D.Double(IMAGE_WIDTH * 0.139, IMAGE_HEIGHT * 0.6285714285714286, IMAGE_WIDTH * 0.735, IMAGE_HEIGHT * 0.05);
                TRACK_START_POINT = new java.awt.geom.Point2D.Double(TRACK.getMinX(), 0);
                TRACK_STOP_POINT = new java.awt.geom.Point2D.Double(TRACK.getMaxX(), 0);        
        }
        
        // Calculate the track start and stop position for the gradient
        final float TRACK_START_POSITION = (float) ((TRACK_START - MIN_VALUE) / (MAX_VALUE - MIN_VALUE));
        final float TRACK_STOP_POSITION = (float) ((TRACK_STOP - MIN_VALUE) / (MAX_VALUE - MIN_VALUE));

        final java.awt.Color FULLY_TRANSPARENT = new java.awt.Color(0.0f, 0.0f, 0.0f, 0.0f);

        final float[] TRACK_FRACTIONS;
        final java.awt.Color[] TRACK_COLORS;
        
        // Three color gradient from trackStart over trackSection to trackStop
        final float TRACK_SECTION_POSITION = (float) ((TRACK_SECTION - MIN_VALUE) / (MAX_VALUE - MIN_VALUE));
        
        TRACK_FRACTIONS = new float[]
        {
            0.0f,
            TRACK_START_POSITION + 0.001f,
            TRACK_START_POSITION + 0.002f,
            TRACK_SECTION_POSITION,
            TRACK_STOP_POSITION - 0.002f,
            TRACK_STOP_POSITION - 0.001f,
            1.0f
        };

        TRACK_COLORS = new java.awt.Color[]
        {
            FULLY_TRANSPARENT,
            FULLY_TRANSPARENT,
            TRACK_START_COLOR,
            TRACK_SECTION_COLOR,
            TRACK_STOP_COLOR,
            FULLY_TRANSPARENT,
            FULLY_TRANSPARENT
        };
       
        final java.awt.LinearGradientPaint TRACK_GRADIENT = new java.awt.LinearGradientPaint(TRACK_START_POINT, TRACK_STOP_POINT, TRACK_FRACTIONS, TRACK_COLORS);
        G2.setPaint(TRACK_GRADIENT);
        G2.fill(TRACK);

        G2.dispose();

        return IMAGE;
    }

    /**
     * Returns the image of the title.
     * @param WIDTH
     * @param HEIGHT
     * @param UNIT_STRING_VISIBLE
     * @return a buffered image of the title and unit string
     */
    protected java.awt.image.BufferedImage create_TITLE_Image(final int WIDTH, final int HEIGHT, final boolean UNIT_STRING_VISIBLE)
    {
        if (WIDTH <= 0 || HEIGHT <= 0)
        {
            return GFX_CONF.createCompatibleImage(140, 140, java.awt.Transparency.TRANSLUCENT);
        }
        
        final java.awt.image.BufferedImage IMAGE = GFX_CONF.createCompatibleImage(WIDTH, HEIGHT, java.awt.Transparency.TRANSLUCENT);
        final java.awt.Graphics2D G2 = IMAGE.createGraphics();
        G2.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
        G2.setRenderingHint(java.awt.RenderingHints.KEY_FRACTIONALMETRICS, java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        G2.setRenderingHint(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

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

        final java.awt.font.FontRenderContext RENDER_CONTEXT = new java.awt.font.FontRenderContext(null, true, true);

        if (isLabelColorFromThemeEnabled())
        {
            G2.setColor(getBackgroundColor().LABEL_COLOR);
        }
        else
        {
            G2.setColor(getLabelColor());
        }

        final java.awt.font.TextLayout LAYOUT_TITLE;

        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
        {            
                // Vertical orientation
            // Draw title
            // Use custom font if selected
            if (isTitleAndUnitFontEnabled())
            {
                G2.setFont(new java.awt.Font(getTitleAndUnitFont().getFamily(), getTitleAndUnitFont().getStyle(), getTitleAndUnitFont().getSize()));
            }
            else
            {
                G2.setFont(new java.awt.Font("Verdana", 0, (int) (0.1 * IMAGE_WIDTH)));
            }
            LAYOUT_TITLE = new java.awt.font.TextLayout(getTitle(), G2.getFont(), RENDER_CONTEXT);
            final java.awt.geom.AffineTransform OLD_TRANSFORM = G2.getTransform();
            G2.translate(0.0, -0.05 * IMAGE_HEIGHT);
            G2.rotate(1.5707963267948966, 0.6714285714285714f * IMAGE_WIDTH, 0.1375f * IMAGE_HEIGHT + LAYOUT_TITLE.getAscent() - LAYOUT_TITLE.getDescent());
            G2.drawString(getTitle(), 0.6714285714285714f * IMAGE_WIDTH, 0.1375f * IMAGE_HEIGHT + LAYOUT_TITLE.getAscent() - LAYOUT_TITLE.getDescent());
            G2.setTransform(OLD_TRANSFORM);

            // Draw unit string
            if (UNIT_STRING_VISIBLE)
            {
                if (isTitleAndUnitFontEnabled())
                {
                    G2.setFont(new java.awt.Font(getTitleAndUnitFont().getFamily(), 0, (int) (0.07142857142857142 * IMAGE_WIDTH)));
                }
                else
                {
                    G2.setFont(new java.awt.Font("Verdana", 0, (int) (0.07142857142857142 * IMAGE_WIDTH)));
                }
                final java.awt.font.TextLayout LAYOUT_UNIT = new java.awt.font.TextLayout(getUnitString(), G2.getFont(), RENDER_CONTEXT);
                final java.awt.geom.Rectangle2D UNIT_BOUNDARY = LAYOUT_UNIT.getBounds();
                G2.drawString(getUnitString(), (float) (IMAGE_WIDTH - UNIT_BOUNDARY.getWidth()) / 2f, 0.8875f * IMAGE_HEIGHT + LAYOUT_UNIT.getAscent() - LAYOUT_UNIT.getDescent());
            }
        }
        else
        {
            // Horizontal orientation
            // Draw title
            if (isTitleAndUnitFontEnabled())
            {
                G2.setFont(new java.awt.Font(getTitleAndUnitFont().getFamily(), 0, (int) (0.1 * IMAGE_HEIGHT)));
            }
            else
            {
                G2.setFont(new java.awt.Font("Verdana", 0, (int) (0.1 * IMAGE_HEIGHT)));
            }
            LAYOUT_TITLE = new java.awt.font.TextLayout(getTitle(), G2.getFont(), RENDER_CONTEXT);
            G2.drawString(getTitle(), 0.15f * IMAGE_WIDTH, 0.25f * IMAGE_HEIGHT + LAYOUT_TITLE.getAscent() - LAYOUT_TITLE.getDescent());

            // Draw unit string
            if (UNIT_STRING_VISIBLE)
            {
                if (isTitleAndUnitFontEnabled())
                {
                    G2.setFont(new java.awt.Font(getTitleAndUnitFont().getFamily(), 0, (int) (0.025 * IMAGE_WIDTH)));
                }
                else
                {
                    G2.setFont(new java.awt.Font("Verdana", 0, (int) (0.025 * IMAGE_WIDTH)));
                }
                final java.awt.font.TextLayout LAYOUT_UNIT = new java.awt.font.TextLayout(getUnitString(), G2.getFont(), RENDER_CONTEXT);
                G2.drawString(getUnitString(), 0.0625f * IMAGE_WIDTH, 0.7f * IMAGE_HEIGHT + LAYOUT_UNIT.getAscent() - LAYOUT_UNIT.getDescent());
            }
        }

        G2.dispose();

        return IMAGE;
    }

    /**
     * Returns the image with the given lcd color.
     * @param WIDTH
     * @param HEIGHT
     * @param LCD_COLOR
     * @param CUSTOM_LCD_BACKGROUND 
     * @return buffered image containing the lcd with the selected lcd color
     */
    protected java.awt.image.BufferedImage create_LCD_Image(final int WIDTH, final int HEIGHT, final eu.hansolo.steelseries.tools.LcdColor LCD_COLOR, final java.awt.Paint CUSTOM_LCD_BACKGROUND)
    {
        if (WIDTH <= 0)
        {
            return GFX_CONF.createCompatibleImage(10, 10, java.awt.Transparency.TRANSLUCENT);
        }

        final java.awt.image.BufferedImage IMAGE = GFX_CONF.createCompatibleImage(WIDTH, HEIGHT, java.awt.Transparency.TRANSLUCENT);
        final java.awt.Graphics2D G2 = IMAGE.createGraphics();
        G2.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
        //G2.setRenderingHint(java.awt.RenderingHints.KEY_RENDERING, java.awt.RenderingHints.VALUE_RENDER_QUALITY);
        //G2.setRenderingHint(java.awt.RenderingHints.KEY_DITHERING, java.awt.RenderingHints.VALUE_DITHER_ENABLE);
        //G2.setRenderingHint(java.awt.RenderingHints.KEY_ALPHA_INTERPOLATION, java.awt.RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        //G2.setRenderingHint(java.awt.RenderingHints.KEY_COLOR_RENDERING, java.awt.RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        G2.setRenderingHint(java.awt.RenderingHints.KEY_STROKE_CONTROL, java.awt.RenderingHints.VALUE_STROKE_PURE);
        //G2.setRenderingHint(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        final int IMAGE_WIDTH = IMAGE.getWidth();
        final int IMAGE_HEIGHT = IMAGE.getHeight();

        // Background rectangle
        final java.awt.geom.Point2D BACKGROUND_START = new java.awt.geom.Point2D.Double(0.0, 0.0);
        final java.awt.geom.Point2D BACKGROUND_STOP = new java.awt.geom.Point2D.Double(0.0, IMAGE_HEIGHT);

        final float[] BACKGROUND_FRACTIONS =
        {
            0.0f,
            0.08f,
            0.92f,
            1.0f
        };

        final java.awt.Color[] BACKGROUND_COLORS =
        {
            new java.awt.Color(0.3f, 0.3f, 0.3f, 1.0f),
            new java.awt.Color(0.4f, 0.4f, 0.4f, 1.0f),
            new java.awt.Color(0.4f, 0.4f, 0.4f, 1.0f),
            new java.awt.Color(0.9f, 0.9f, 0.9f, 1.0f)
        };

        final java.awt.LinearGradientPaint BACKGROUND_GRADIENT = new java.awt.LinearGradientPaint(BACKGROUND_START, BACKGROUND_STOP, BACKGROUND_FRACTIONS, BACKGROUND_COLORS);
        final double BACKGROUND_CORNER_RADIUS = IMAGE_WIDTH * 0.078125f;
        //final double BACKGROUND_CORNER_RADIUS = IMAGE_WIDTH * 0.09375f;
        final java.awt.geom.RoundRectangle2D BACKGROUND = new java.awt.geom.RoundRectangle2D.Double(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, BACKGROUND_CORNER_RADIUS, BACKGROUND_CORNER_RADIUS);
        G2.setPaint(BACKGROUND_GRADIENT);
        G2.fill(BACKGROUND);

        // Foreground rectangle
        final java.awt.geom.Point2D FOREGROUND_START = new java.awt.geom.Point2D.Double(0.0, 1.0);
        final java.awt.geom.Point2D FOREGROUND_STOP = new java.awt.geom.Point2D.Double(0.0, IMAGE_HEIGHT - 1);

        final float[] FOREGROUND_FRACTIONS =
        {
            0.0f,
            0.03f,
            0.49f,
            0.5f,
            1.0f
        };

        final java.awt.Color[] FOREGROUND_COLORS =
        {
            LCD_COLOR.GRADIENT_START_COLOR,
            LCD_COLOR.GRADIENT_FRACTION1_COLOR,
            LCD_COLOR.GRADIENT_FRACTION2_COLOR,
            LCD_COLOR.GRADIENT_FRACTION3_COLOR,
            LCD_COLOR.GRADIENT_STOP_COLOR
        };
                
        if (LCD_COLOR == eu.hansolo.steelseries.tools.LcdColor.CUSTOM)
        {
            G2.setPaint(CUSTOM_LCD_BACKGROUND);
        }
        else
        {
            final java.awt.LinearGradientPaint FOREGROUND_GRADIENT = new java.awt.LinearGradientPaint(FOREGROUND_START, FOREGROUND_STOP, FOREGROUND_FRACTIONS, FOREGROUND_COLORS);        
            G2.setPaint(FOREGROUND_GRADIENT);
        }
        final double FOREGROUND_CORNER_RADIUS = BACKGROUND.getArcWidth() - 1;
        final java.awt.geom.RoundRectangle2D FOREGROUND = new java.awt.geom.RoundRectangle2D.Double(1, 1, IMAGE_WIDTH - 2, IMAGE_HEIGHT - 2, FOREGROUND_CORNER_RADIUS, FOREGROUND_CORNER_RADIUS);
        G2.fill(FOREGROUND);

        G2.dispose();

        return IMAGE;
    }
    
    /**
     * Returns the image of the tickmarks
     * @param WIDTH
     * @param HEIGHT
     * @param MIN_VALUE
     * @param MAX_VALUE
     * @param TICK_LABEL_PERIOD
     * @return a buffered image of the tickmarks with the current settings
     */
    protected java.awt.image.BufferedImage create_TICKMARKS_Image(final int WIDTH, final int HEIGHT, final double MIN_VALUE, final double MAX_VALUE, final int TICK_LABEL_PERIOD)
    {
        return create_TICKMARKS_Image(WIDTH, HEIGHT, MIN_VALUE, MAX_VALUE, TICK_LABEL_PERIOD, 0, true, true, null);
    }

    /**
     * Returns the image of the tickmarks
     * @param WIDTH
     * @param HEIGHT
     * @param MIN_VALUE
     * @param MAX_VALUE
     * @param TICK_LABEL_PERIOD
     * @param SCALE_DIVIDER_POWER
     * @param DRAW_TICKS
     * @param DRAW_TICK_LABELS
     * @param TICKMARK_SECTIONS
     * @return a buffered image of the tickmarks with the current settings
     */
    protected java.awt.image.BufferedImage create_TICKMARKS_Image(final int WIDTH, final int HEIGHT, final double MIN_VALUE, final double MAX_VALUE, final int TICK_LABEL_PERIOD, final int SCALE_DIVIDER_POWER, final boolean DRAW_TICKS, final boolean DRAW_TICK_LABELS, final java.util.ArrayList TICKMARK_SECTIONS)
    {
        if (WIDTH <= 0 || HEIGHT <= 0)
        {
            return GFX_CONF.createCompatibleImage(140, 140, java.awt.Transparency.TRANSLUCENT);
        }

        if (!DRAW_TICKS && !DRAW_TICK_LABELS)
        {
            return null;
        }
        
        final java.awt.image.BufferedImage IMAGE = GFX_CONF.createCompatibleImage(WIDTH, HEIGHT, java.awt.Transparency.TRANSLUCENT);
        final java.awt.Graphics2D G2 = IMAGE.createGraphics();
        G2.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON);
        G2.setRenderingHint(java.awt.RenderingHints.KEY_STROKE_CONTROL, java.awt.RenderingHints.VALUE_STROKE_PURE);
        G2.setRenderingHint(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        // Definitions
        final java.awt.Font STD_FONT;
        final java.awt.BasicStroke STD_STROKE = new java.awt.BasicStroke(1.0f, java.awt.BasicStroke.CAP_ROUND, java.awt.BasicStroke.JOIN_BEVEL);
        final java.awt.BasicStroke MEDIUM_STROKE = new java.awt.BasicStroke(0.5f, java.awt.BasicStroke.CAP_ROUND, java.awt.BasicStroke.JOIN_BEVEL);
        final java.awt.BasicStroke THIN_STROKE = new java.awt.BasicStroke(0.3f, java.awt.BasicStroke.CAP_ROUND, java.awt.BasicStroke.JOIN_BEVEL);
        final java.awt.BasicStroke VERY_THIN_STROKE = new java.awt.BasicStroke(0.1f, java.awt.BasicStroke.CAP_ROUND, java.awt.BasicStroke.JOIN_BEVEL);
        final int MINI_DIAMETER;
        final int MINOR_DIAMETER;
        final int MAJOR_DIAMETER;
        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
        {
            MINI_DIAMETER = (int) (0.0093457944 * WIDTH);
            MINOR_DIAMETER = (int) (0.0186915888 * WIDTH);
            MAJOR_DIAMETER = (int) (0.0280373832 * WIDTH);  
        }
        else
        {
            MINI_DIAMETER = (int) (0.0093457944 * HEIGHT);
            MINOR_DIAMETER = (int) (0.0186915888 * HEIGHT);
            MAJOR_DIAMETER = (int) (0.0280373832 * HEIGHT);  
        }
        
        final double TICK_MAX;
        final double TICK_MIN;

        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
        {            
            // Vertical orientation
            STD_FONT = new java.awt.Font("Verdana", 0, (int) (0.062 * WIDTH));
            TICK_MIN = HEIGHT * 0.8567961165048543; // position of min value
            TICK_MAX =  HEIGHT * 0.12864077669902912; // position of max value
        }
        else
        {
            // Horizontal orientation
            STD_FONT = new java.awt.Font("Verdana", 0, (int) (0.062 * HEIGHT));
            TICK_MIN = WIDTH * 0.14285714285714285;
            TICK_MAX =  WIDTH * 0.8710124827; // position of max value
        }
        final double RANGE = getMaxValue() - getMinValue();
        final double TICK_STEP = (TICK_MAX - TICK_MIN) / RANGE; // pixel per tick

        G2.setFont(STD_FONT);
        
        final java.awt.font.FontRenderContext RENDER_CONTEXT = new java.awt.font.FontRenderContext(null, true, true);
        final java.awt.font.TextLayout TEXT_LAYOUT = new java.awt.font.TextLayout(String.valueOf(getMaxValue()), G2.getFont(), RENDER_CONTEXT);
        final java.awt.geom.Rectangle2D MAX_BOUNDS = TEXT_LAYOUT.getBounds(); // needed to align the numbers on the right (in vertical layout)
        final java.awt.geom.Line2D TICK_LINE = new java.awt.geom.Line2D.Double(0, 0, 1, 1);
        final java.awt.geom.Ellipse2D TICK_CIRCLE = new java.awt.geom.Ellipse2D.Double(0, 0, 1, 1);        
        
        java.awt.font.TextLayout currentLayout;
        java.awt.geom.Rectangle2D currentBounds;
        float textOffset = 0;
                        
        int counter = 0;
        int tickCounter = 0;
 
//        if (isTickmarkColorFromThemeEnabled())
//        {
//            G2.setColor(backgroundColor.LABEL_COLOR);
//        }
//        else
//        {
//            G2.setColor(tickmarkColor);
//        }

        for (double pos = getMinValue() ; pos < getMaxValue() + 1 ; pos++)
        {
            if (TICKMARK_SECTIONS != null && !TICKMARK_SECTIONS.isEmpty())
            {
                if (isTickmarkSectionsVisible())
                {
                    for (eu.hansolo.steelseries.tools.Section section : TICKMARK_SECTIONS)
                    {
                        if (pos >= section.getStart() && pos <= section.getStop())
                        {
                            G2.setColor(section.getColor());
                            break;
                        }
                        else if(isTickmarkColorFromThemeEnabled())
                        {
                            G2.setColor(getBackgroundColor().LABEL_COLOR);
                        }
                        else
                        {
                            G2.setColor(getTickmarkColor());
                        }
                    }
                }
                else
                {
                    if(isTickmarkColorFromThemeEnabled())
                    {
                        G2.setColor(getBackgroundColor().LABEL_COLOR);
                    }
                    else
                    {
                        G2.setColor(getTickmarkColor());
                    }
                }
            }
            else
            {
                if(isTickmarkColorFromThemeEnabled())
                {
                    G2.setColor(getBackgroundColor().LABEL_COLOR);
                }
                else
                {
                    G2.setColor(getTickmarkColor());
                }
            }

            double currentPos;
            if (getMinValue() <= 0)
            {
                currentPos = TICK_MIN + (pos * TICK_STEP) + Math.abs(getMinValue()) * TICK_STEP;
            }
            else
            {
                currentPos = TICK_MIN + (pos * TICK_STEP) - Math.abs(getMinValue()) * TICK_STEP;
            }


            // Very thin tickmark every 0.1 unit
            if (RANGE <= 10 && counter != 0)
            {                
                final double STEP_SIZE = TICK_STEP / 10.0;
                G2.setStroke(VERY_THIN_STROKE);
                if (DRAW_TICKS && getMiniTickmarkType() == eu.hansolo.steelseries.tools.TickmarkType.LINE)
                {
                    for (double tmpPos = (currentPos - STEP_SIZE) ; tmpPos < (currentPos - TICK_STEP) ; tmpPos -= STEP_SIZE)
                    {
                        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                        {
                            // Vertical orientation
                            TICK_LINE.setLine(WIDTH * 0.35, (int) tmpPos, WIDTH * 0.36, tmpPos);
                        }
                        else
                        {
                            // Horizontal orientation
                            TICK_LINE.setLine((int) tmpPos, HEIGHT * 0.66, (int) tmpPos, HEIGHT * 0.63);
                        }
                        G2.draw(TICK_LINE);
                    }
                }
            }

            // Thin tickmark every 1 unit
            if (counter % 5 != 0 && counter % 10 != 0 && counter % 100 != 0 && RANGE < 500)
            {
                if (DRAW_TICKS && isMiniTickmarkVisible())
                {
                    G2.setStroke(THIN_STROKE);
                    switch(getMiniTickmarkType())
                    {
                        case LINE:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                // Vertical orientation
                                TICK_LINE.setLine(WIDTH * 0.34, currentPos, WIDTH * 0.36, currentPos);
                            }
                            else
                            {
                                // Horizontal orientation
                                TICK_LINE.setLine(currentPos, HEIGHT * 0.65, currentPos, HEIGHT * 0.63);
                            }
                            G2.draw(TICK_LINE);
                            break;
                        case CIRCLE:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                TICK_CIRCLE.setFrame(WIDTH * 0.34, currentPos - MINI_DIAMETER / 2.0, MINI_DIAMETER, MINI_DIAMETER);
                            }
                            else
                            {
                                TICK_CIRCLE.setFrame(currentPos - MINI_DIAMETER / 2.0, HEIGHT * 0.63, MINI_DIAMETER, MINI_DIAMETER);
                            }
                            G2.fill(TICK_CIRCLE);
                            break;                                                
                        default:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                // Vertical orientation
                                TICK_LINE.setLine(WIDTH * 0.34, currentPos, WIDTH * 0.36, currentPos);
                            }
                            else
                            {
                                // Horizontal orientation
                                TICK_LINE.setLine(currentPos, HEIGHT * 0.65, currentPos, HEIGHT * 0.63);
                            }
                            G2.draw(TICK_LINE);
                    }
                }
            }

            // Medium tickmark every 5 units
            if (counter % 5 == 0 && counter % 10 != 0 && counter % 100 != 0 && RANGE < 1000)
            {
                if (DRAW_TICKS && isMinorTickmarkVisible())
                {
                    G2.setStroke(MEDIUM_STROKE);
                    switch(getMinorTickmarkType())
                    {
                        case LINE:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                // Vertical orientation
                                TICK_LINE.setLine(WIDTH * 0.33, currentPos, WIDTH * 0.36, currentPos);
                            }
                            else
                            {
                                // Horizontal orientation
                                TICK_LINE.setLine(currentPos, HEIGHT * 0.66, currentPos, HEIGHT * 0.63);
                            }
                            G2.draw(TICK_LINE);
                            break;
                        case CIRCLE:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                TICK_CIRCLE.setFrame(WIDTH * 0.33, currentPos - MINOR_DIAMETER / 2.0, MINOR_DIAMETER, MINOR_DIAMETER);
                            }
                            else
                            {
                                TICK_CIRCLE.setFrame(currentPos - MINOR_DIAMETER / 2.0, HEIGHT * 0.63, MINOR_DIAMETER, MINOR_DIAMETER);
                            }
                            G2.fill(TICK_CIRCLE);
                            break;                                                
                        default:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                // Vertical orientation
                                TICK_LINE.setLine(WIDTH * 0.33, currentPos, WIDTH * 0.36, currentPos);
                            }
                            else
                            {
                                // Horizontal orientation
                                TICK_LINE.setLine(currentPos, HEIGHT * 0.66, currentPos, HEIGHT * 0.63);
                            }
                            G2.draw(TICK_LINE);
                    }
                }
            }

            // Standard tickmark every 10 units
            if (counter % 10 == 0 && counter % 100 != 0 || counter == 0 && RANGE < 1000)
            {
                if (DRAW_TICKS && isMajorTickmarkVisible())
                {
                    G2.setStroke(STD_STROKE);
                    switch(getMajorTickmarkType())
                    {
                        case LINE:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                // Vertical orientation
                                TICK_LINE.setLine(WIDTH * 0.32, currentPos, WIDTH * 0.36, currentPos);
                            }
                            else
                            {
                                // Horizontal orientation
                                TICK_LINE.setLine(currentPos, HEIGHT * 0.67, currentPos, HEIGHT * 0.63);
                            }
                            G2.draw(TICK_LINE);
                            break;
                        case CIRCLE:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                TICK_CIRCLE.setFrame(WIDTH * 0.32, currentPos - MAJOR_DIAMETER / 2.0, MAJOR_DIAMETER, MAJOR_DIAMETER);
                            }
                            else
                            {
                                TICK_CIRCLE.setFrame(currentPos - MAJOR_DIAMETER / 2.0, HEIGHT * 0.63, MAJOR_DIAMETER, MAJOR_DIAMETER);
                            }
                            G2.fill(TICK_CIRCLE);
                            break;                                                
                        default:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                // Vertical orientation
                                TICK_LINE.setLine(WIDTH * 0.32, currentPos, WIDTH * 0.36, currentPos);
                            }
                            else
                            {
                                // Horizontal orientation
                                TICK_LINE.setLine(currentPos, HEIGHT * 0.67, currentPos, HEIGHT * 0.63);
                            }
                            G2.draw(TICK_LINE);
                    }  
                }
            }

            // Longer standard tickmark every 100 units
            if (counter == 100)
            {
                if (DRAW_TICKS && isMajorTickmarkVisible())
                {
                    G2.setStroke(STD_STROKE);
                    switch(getMajorTickmarkType())
                    {
                        case LINE:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                // Vertical orientation
                                TICK_LINE.setLine(WIDTH * 0.31, currentPos, WIDTH * 0.36, currentPos);
                            }
                            else
                            {
                                // Horizontal orientation
                                TICK_LINE.setLine(currentPos, HEIGHT * 0.68, currentPos, HEIGHT * 0.63);
                            }
                            G2.draw(TICK_LINE);
                            break;
                        case CIRCLE:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                TICK_CIRCLE.setFrame(WIDTH * 0.31, currentPos - MAJOR_DIAMETER / 2.0, MAJOR_DIAMETER, MAJOR_DIAMETER);
                            }
                            else
                            {
                                TICK_CIRCLE.setFrame(currentPos - MAJOR_DIAMETER / 2.0, HEIGHT * 0.63, MAJOR_DIAMETER, MAJOR_DIAMETER);
                            }
                            G2.fill(TICK_CIRCLE);
                            break;                                                
                        default:
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                // Vertical orientation
                                TICK_LINE.setLine(WIDTH * 0.31, currentPos, WIDTH * 0.36, currentPos);
                            }
                            else
                            {
                                // Horizontal orientation
                                TICK_LINE.setLine(currentPos, HEIGHT * 0.68, currentPos, HEIGHT * 0.63);
                            }
                            G2.draw(TICK_LINE);
                    }  
                }
                counter = 0;
                tickCounter++;
            }

            // Draw text
            // Draw the tickmark labels
            if (DRAW_TICK_LABELS)
            {
                if (isCustomTickmarkLabelsEnabled())
                {
                    // Draw custom tickmark labels if selected
                    for (double tickLabel : getCustomTickmarkLabels())
                    {
                        if (Double.compare(pos, tickLabel) == 0)
                        {
                            currentLayout = new java.awt.font.TextLayout(String.valueOf(pos), G2.getFont(), RENDER_CONTEXT);
                            currentBounds = currentLayout.getBounds();                
                            if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                            {
                                // Vertical orientation
                                textOffset = (float) (MAX_BOUNDS.getWidth() - currentBounds.getWidth());
                                G2.drawString(String.valueOf((int)pos), 0.18f * WIDTH + textOffset, (float) (currentPos - currentBounds.getHeight() / 2.0 + currentBounds.getHeight()));
                            }
                            else
                            {
                                // Horizontal orientation
                                G2.drawString(String.valueOf((int)pos), (float) (currentPos - currentBounds.getWidth() / 3.0), (float) (HEIGHT * 0.68 + 1.5 * currentBounds.getHeight()));
                            }
                        }
                    }
                }
                else
                {
                    // Draw the standard tickmark labels
                    if (pos % TICK_LABEL_PERIOD == 0)
                    {
                        currentLayout = new java.awt.font.TextLayout(String.valueOf(pos), G2.getFont(), RENDER_CONTEXT);
                        currentBounds = currentLayout.getBounds();                
                        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                        {
                            // Vertical orientation
                            textOffset = (float) (MAX_BOUNDS.getWidth() - currentBounds.getWidth());
                            G2.drawString(String.valueOf((int)pos), 0.18f * WIDTH + textOffset, (float) (currentPos - currentBounds.getHeight() / 2.0 + currentBounds.getHeight()));
                        }
                        else
                        {
                            // Horizontal orientation
                            G2.drawString(String.valueOf((int)pos), (float) (currentPos - currentBounds.getWidth() / 3.0), (float) (HEIGHT * 0.68 + 1.5 * currentBounds.getHeight()));
                        }
                    }
                }
            }

            counter++;
        }

        G2.dispose();

        return IMAGE;
    }

    /**
     * Returns the image of the threshold indicator
     * @param WIDTH
     * @param HEIGHT
     * @return a buffered image of the threshold indicator
     */
    protected java.awt.image.BufferedImage create_THRESHOLD_Image(final int WIDTH, final int HEIGHT)
    {
        if (WIDTH <= 14 || HEIGHT <= 14) // 14 is needed otherwise the image size could be smaller than 1
        {
            return GFX_CONF.createCompatibleImage(10, 10, java.awt.Transparency.TRANSLUCENT);
        }
                
        final int IMAGE_WIDTH;
        final int IMAGE_HEIGHT;
        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
        {            
                // Vertical orientation
                IMAGE_WIDTH = (int) (WIDTH * 0.0714285714);
                IMAGE_HEIGHT = (int) (IMAGE_WIDTH * 0.8);
        }
        else
        {
                // Horizontal orientation
                IMAGE_HEIGHT = (int) (HEIGHT * 0.0714285714);
                IMAGE_WIDTH = (int) (IMAGE_HEIGHT * 0.8);        
        }
        final java.awt.image.BufferedImage IMAGE = GFX_CONF.createCompatibleImage(IMAGE_WIDTH, IMAGE_HEIGHT, java.awt.Transparency.TRANSLUCENT);
        final java.awt.Graphics2D G2 = IMAGE.createGraphics();
        G2.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON);

        G2.translate(0, IMAGE_WIDTH * 0.005);
        final java.awt.geom.GeneralPath THRESHOLD = new java.awt.geom.GeneralPath();
        THRESHOLD.setWindingRule(java.awt.geom.GeneralPath.WIND_EVEN_ODD);
        final java.awt.geom.Point2D THRESHOLD_START;
        final java.awt.geom.Point2D THRESHOLD_STOP;

        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
        {
            // Vertical orientation
            THRESHOLD.moveTo(IMAGE_WIDTH * 0.1, IMAGE_HEIGHT * 0.5);
            THRESHOLD.lineTo(IMAGE_WIDTH * 0.9, IMAGE_HEIGHT * 0.1);
            THRESHOLD.lineTo(IMAGE_WIDTH * 0.9, IMAGE_HEIGHT * 0.9);
            THRESHOLD.lineTo(IMAGE_WIDTH * 0.1, IMAGE_HEIGHT * 0.5);
            THRESHOLD.closePath();
            THRESHOLD_START = new java.awt.geom.Point2D.Double(THRESHOLD.getBounds2D().getMinX(), 0);
            THRESHOLD_STOP = new java.awt.geom.Point2D.Double(THRESHOLD.getBounds2D().getMaxX(), 0);
        }
        else
        {
            // Horizontal orientation
            THRESHOLD.moveTo(IMAGE_WIDTH * 0.5, IMAGE_HEIGHT * 0.9);
            THRESHOLD.lineTo(IMAGE_WIDTH * 1.0, IMAGE_HEIGHT * 0.1);
            THRESHOLD.lineTo(IMAGE_WIDTH * 0.1, IMAGE_HEIGHT * 0.1);
            THRESHOLD.lineTo(IMAGE_WIDTH * 0.5, IMAGE_HEIGHT * 0.9);
            THRESHOLD.closePath();
            THRESHOLD_START = new java.awt.geom.Point2D.Double(0, THRESHOLD.getBounds2D().getMaxY() );
            THRESHOLD_STOP = new java.awt.geom.Point2D.Double(0, THRESHOLD.getBounds2D().getMinY() );
        }
        final float[] THRESHOLD_FRACTIONS =
        {
            0.0f,
            0.3f,
            0.59f,
            1.0f
        };
        final java.awt.Color[] THRESHOLD_COLORS =
        {
            new java.awt.Color(82, 0, 0, 255),
            new java.awt.Color(252, 29, 0, 255),
            new java.awt.Color(252, 29, 0, 255),
            new java.awt.Color(82, 0, 0, 255)
        };
        final java.awt.LinearGradientPaint THRESHOLD_GRADIENT = new java.awt.LinearGradientPaint(THRESHOLD_START, THRESHOLD_STOP, THRESHOLD_FRACTIONS, THRESHOLD_COLORS);
        G2.setPaint(THRESHOLD_GRADIENT);
        G2.fill(THRESHOLD);
                
        G2.setColor(java.awt.Color.WHITE);
        G2.setStroke(new java.awt.BasicStroke(1.0f, java.awt.BasicStroke.CAP_BUTT, java.awt.BasicStroke.JOIN_MITER));
        G2.draw(THRESHOLD);

        G2.dispose();

        return IMAGE;
    }

    /**
     * Returns the image of the MinMeasuredValue and MaxMeasuredValue dependend
     * on the given color
     * @param WIDTH
     * @param HEIGHT
     * @param COLOR
     * @return a buffered image of either the min measured value or the max measured value indicator
     */
    protected java.awt.image.BufferedImage create_MEASURED_VALUE_Image(final int WIDTH, final int HEIGHT, final java.awt.Color COLOR)
    {
        if (WIDTH <= 20 || HEIGHT <= 20) // 20 is needed otherwise the image size could be smaller than 1
        {
            return GFX_CONF.createCompatibleImage(10, 10, java.awt.Transparency.TRANSLUCENT);
        }
                
        final int IMAGE_WIDTH;
        final int IMAGE_HEIGHT;
        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
        {
            // Vertical orientation
            IMAGE_WIDTH = (int) (WIDTH * 0.05);
            IMAGE_HEIGHT = IMAGE_WIDTH;
        }
        else
        {
            // Horizontal orientation
            IMAGE_HEIGHT = (int) (HEIGHT * 0.05);
            IMAGE_WIDTH = IMAGE_HEIGHT;
        }
       
        final java.awt.image.BufferedImage IMAGE = GFX_CONF.createCompatibleImage(IMAGE_WIDTH, IMAGE_HEIGHT, 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 java.awt.geom.GeneralPath INDICATOR = new java.awt.geom.GeneralPath();
        INDICATOR.setWindingRule(java.awt.geom.GeneralPath.WIND_EVEN_ODD);
        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
        {
            INDICATOR.moveTo(IMAGE_WIDTH, IMAGE_HEIGHT * 0.5);
            INDICATOR.lineTo(0.0, 0.0);
            INDICATOR.lineTo(0.0, IMAGE_HEIGHT);
            INDICATOR.lineTo(IMAGE_WIDTH, IMAGE_HEIGHT * 0.5);
            INDICATOR.closePath();
        }
        else
        {
            INDICATOR.moveTo(IMAGE_WIDTH * 0.5, 0.0);
            INDICATOR.lineTo(IMAGE_WIDTH, IMAGE_HEIGHT);
            INDICATOR.lineTo(0.0, IMAGE_HEIGHT);
            INDICATOR.lineTo(IMAGE_WIDTH * 0.5, 0.0);
            INDICATOR.closePath();
        }
        G2.setColor(COLOR);
        G2.fill(INDICATOR);

        G2.dispose();

        return IMAGE;
    }

    /**
     * Returns the image of the glasseffect image
     * @param WIDTH
     * @param HEIGHT
     * @return a buffered image of the foreground glass effect
     */
    protected java.awt.image.BufferedImage create_FOREGROUND_Image(final int WIDTH, final int HEIGHT)
    {
        return FOREGROUND_FACTORY.createLinearForeground(WIDTH, HEIGHT);
    }
    
    /**
     * Returns the image that will be displayed if the gauge is disabled
     * @param WIDTH
     * @param HEIGHT 
     * @return the disabled image that will be displayed if the gauge is disabled
     */
    protected java.awt.image.BufferedImage create_DISABLED_Image(final int WIDTH, final int HEIGHT)
    {
        return DISABLED_FACTORY.createLinearDisabled(WIDTH, HEIGHT);
    }
    // 

    //     
    @Override
    public void calcInnerBounds()
    {
        final java.awt.Insets INSETS = getInsets();
        INNER_BOUNDS.setBounds(INSETS.left, INSETS.top, getWidth() - INSETS.left - INSETS.right, getHeight() - INSETS.top - INSETS.bottom);        
    }

    /**
     * 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
     */
    @Override
    public final java.awt.Rectangle getInnerBounds()
    {
        return INNER_BOUNDS;
    }

    @Override
    public java.awt.Dimension getMinimumSize()
    {        
        return new java.awt.Dimension(140, 140);
    }
            
    @Override
    public void setPreferredSize(final java.awt.Dimension DIM)
    {        
        super.setPreferredSize(DIM);
        calcInnerBounds();
        init(DIM.width, DIM.height);
        setInitialized(true);
        revalidate();
        repaint();
    }
    
    @Override
    public void setSize(final int WIDTH, final int HEIGHT)
    {
        super.setSize(WIDTH, HEIGHT);
        calcInnerBounds();
        init(WIDTH, HEIGHT);
        setInitialized(true);
        revalidate();
        repaint();
    }
    
    @Override
    public void setSize(final java.awt.Dimension DIM)
    {
        super.setSize(DIM);
        calcInnerBounds();
        init(DIM.width, DIM.height);
        setInitialized(true);
        revalidate();
        repaint();
    }
    
    @Override
    public void setBounds(final java.awt.Rectangle BOUNDS)
    {
        super.setBounds(BOUNDS);
        calcInnerBounds();
        init(BOUNDS.width, BOUNDS.height);        
        setInitialized(true);
        revalidate();
        repaint();
    }
    
    @Override
    public void setBounds(final int X, final int Y, final int WIDTH, final int HEIGHT)
    {
        super.setBounds(X, Y, WIDTH, HEIGHT);
        calcInnerBounds();
        init(WIDTH, HEIGHT);        
        setInitialized(true);
        revalidate();
        repaint();
    }
    // 

    // 
    // ComponentListener methods
    @Override
    public void componentResized(final java.awt.event.ComponentEvent EVENT)
    {        
        if (getParent().getLayout() == null)
        {
            setSize(this.getWidth(), this.getHeight());
        }
        else
        {
            setPreferredSize(new java.awt.Dimension(this.getWidth(), this.getHeight()));
        }
        
        calcInnerBounds();
                       
        if (this.getWidth() >= this.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);
        }        
        
        init(getInnerBounds().width, getInnerBounds().height);  
        revalidate();
        repaint();
    }
    // 
 
    @Override
    public String toString()
    {
        return "AbstractLinear";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy