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

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

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;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.LCD);
        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;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.LCD);
        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;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.LCD);
        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;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.LCD);
        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;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.LCD);
        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;
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.LCD);
        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());
    }
    // 

    // 
    /**
     * Fills the EnumSet with all ImageTypes that are needed for initialization     
     */
    protected void createInitialImages()
    {            
        {
            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.TICKMARKS);
            IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.TITLE);
            IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.LCD);
            IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.FOREGROUND);        
        }
    }

    @Override
    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.LOW);
        IMAGES_TO_UPDATE.add(eu.hansolo.steelseries.tools.ImageType.HIGH);
        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);
    }

    /**
     * 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 / (MAX_VALUE - MIN_VALUE));
        final float TRACK_STOP_POSITION = (float) (TRACK_STOP / (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 / (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 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)

        java.awt.font.TextLayout currentLayout;
        java.awt.geom.Rectangle2D currentBounds;
        float textOffset = 0;
                
        java.awt.geom.Line2D tick;
        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)
                {
                    for (double tmpPos = (currentPos - STEP_SIZE) ; tmpPos < (currentPos - TICK_STEP) ; tmpPos -= STEP_SIZE)
                    {
                        if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                        {
                            // Vertical orientation
                            tick = new java.awt.geom.Line2D.Double(WIDTH * 0.35, (int) tmpPos, WIDTH * 0.36, tmpPos);
                        }
                        else
                        {
                            // Horizontal orientation
                            tick = new java.awt.geom.Line2D.Double((int) tmpPos, HEIGHT * 0.66, (int) tmpPos, HEIGHT * 0.63);
                        }
                        G2.draw(tick);
                    }
                }
            }

            // Thin tickmark every 1 unit
            if (counter % 5 != 0 && counter % 10 != 0 && counter % 100 != 0 && RANGE < 500)
            {
                if (DRAW_TICKS)
                {
                    G2.setStroke(THIN_STROKE);
                    if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                    {
                        // Vertical orientation
                        tick = new java.awt.geom.Line2D.Double(WIDTH * 0.34, currentPos, WIDTH * 0.36, currentPos);
                    }
                    else
                    {
                        // Horizontal orientation
                        tick = new java.awt.geom.Line2D.Double(currentPos, HEIGHT * 0.65, currentPos, HEIGHT * 0.63);
                    }
                    G2.draw(tick);
                }
            }

            // Medium tickmark every 5 units
            if (counter % 5 == 0 && counter % 10 != 0 && counter % 100 != 0 && RANGE < 1000)
            {
                if (DRAW_TICKS)
                {
                    G2.setStroke(MEDIUM_STROKE);
                    if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                    {
                        // Vertical orientation
                        tick = new java.awt.geom.Line2D.Double(WIDTH * 0.33, currentPos, WIDTH * 0.36, currentPos);
                    }
                    else
                    {
                        // Horizontal orientation
                        tick = new java.awt.geom.Line2D.Double(currentPos, HEIGHT * 0.66, currentPos, HEIGHT * 0.63);
                    }
                    G2.draw(tick);
                }
            }

            // Standard tickmark every 10 units
            if (counter % 10 == 0 && counter % 100 != 0 || counter == 0 && RANGE < 1000)
            {
                if (DRAW_TICKS)
                {
                    G2.setStroke(STD_STROKE);
                    if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                    {
                        // Vertical orientation
                        tick = new java.awt.geom.Line2D.Double(WIDTH * 0.32, currentPos, WIDTH * 0.36, currentPos);
                    }
                    else
                    {
                        // Horizontal orientation
                        tick = new java.awt.geom.Line2D.Double(currentPos, HEIGHT * 0.67, currentPos, HEIGHT * 0.63);
                    }
                    G2.draw(tick);
                }
            }

            // Longer standard tickmark every 100 units
            if (counter == 100)
            {
                if (DRAW_TICKS)
                {
                    G2.setStroke(STD_STROKE);
                    if (getOrientation() == eu.hansolo.steelseries.tools.Orientation.VERTICAL)
                    {
                        // Vertical orientation
                        tick = new java.awt.geom.Line2D.Double(WIDTH * 0.31, currentPos, WIDTH * 0.36, currentPos);
                    }
                    else
                    {
                        // Horizontal orientation
                        tick = new java.awt.geom.Line2D.Double(currentPos, HEIGHT * 0.68, currentPos, HEIGHT * 0.63);
                    }
                    G2.draw(tick);
                }
                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);
        repaint();
    }
    
    @Override
    public void setSize(final int WIDTH, final int HEIGHT)
    {
        super.setSize(WIDTH, HEIGHT);
        calcInnerBounds();
        init(WIDTH, HEIGHT);
        setInitialized(true);
        repaint();
    }
    
    @Override
    public void setSize(final java.awt.Dimension DIM)
    {
        super.setSize(DIM);
        calcInnerBounds();
        init(DIM.width, DIM.height);
        setInitialized(true);
        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);
        }        

        recreateAllImages();
        init(getInnerBounds().width, getInnerBounds().height);  
        revalidate();
        repaint();
    }
    // 
 
    @Override
    public String toString()
    {
        return "AbstractLinear";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy