Package org.gephi.ui.components.gradientslider

Source Code of org.gephi.ui.components.gradientslider.GradientSliderUI

/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org

This file is part of Gephi.

Gephi is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Gephi is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Gephi.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.gephi.ui.components.gradientslider;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.TexturePaint;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;

/** The UI for the GradientSlider class.
*
* There are 3 properties you can use to customize the UI
* of a GradientSlider.  You can set these for each slider
* by calling:
* <BR><code>slider.putClientProperty(key,value);</code>
* <P>Or you can set these globally by calling:
* <BR><code>UIManager.put(key,value);</code>
* <P>The three properties are:
* <P><TABLE BORDER="1" CELLPADDING=5>
* <TR>
* <TD>Property Name</TD><TD>Default Value</TD><TD>Description</DT>
* </TR>
* <TR>
* <TD>GradientSlider.useBevel</TD><TD>"false"</TD><TD>If this is <code>true</code>, then this slider will be painted in a rectangle with a bevel effect around the borders.  If this is <code>false</code>, then this slider will be painted in a rounded rectangle.</DT>
* </TR>
* <TR>
* <TD>GradientSlider.showTranslucency</TD><TD>"true"</TD><TD>If this is <code>true</code>, then the slider will reflect the opacity of the colors in the gradient, and paint a checkered background underneath the colors to indicate opacity.  If this is <code>false</code>, then this slider will always paint with completely opaque colors, although the actual colors may be translucent.</DT>
* </TR>
* <TR>
* <TD>GradientSlider.includeOpacity</TD><TD>"true"</TD><TD>This is used when the user double-clicks a color and a ColorPicker dialog is invoked.  (So this value may not have any meaning if you override <code>GradientSlider.doDoubleClick()</code>.)  This controls whether the opacity/alpha controls are available in that dialog.  This does <i>not</i> control whether translucent colors can be used in this slider: translucent colors are always allowed, if the user can enter them.</TD>
* </TR>
* <TR>
* <TD>MultiThumbSlider.indicateComponent</TD><TD>"true"</TD><TD>If this is <code>true</code>, then the thumbs will only paint on this component when the mouse is inside this slider <i>or</i> when this slider as the keyboard focus.</DT>
* </TR>
* <TR>
* <TD>MultiThumbSlider.indicateThumb</TD><TD>"true"</TD><TD>If this is <code>true</code>, then the thumb the mouse is over will gently fade into a slightly different color.</DT>
* </TR>
* </TABLE>
*
*/
public class GradientSliderUI extends MultiThumbSliderUI {

    int TRIANGLE_SIZE = 8;
    /** The width of this image is the absolute widest the track will
     * ever become.
     */
    BufferedImage img = new BufferedImage(1000, 1, BufferedImage.TYPE_INT_ARGB);
    /** A temporary array used for the buffered image */
    int[] array = new int[img.getWidth()];

    public GradientSliderUI(GradientSlider slider) {
        super(slider);
    }

    public int getClickLocationTolerance() {
        return TRIANGLE_SIZE;
    }

    protected void calculateImage() {
        float[] f = slider.getThumbPositions();
        Color[] c = ((GradientSlider) slider).getColors();

        /** make sure we DO have a value at 0 and 1:
         */
        if (f[0] != 0) {
            float[] f2 = new float[f.length + 1];
            System.arraycopy(f, 0, f2, 1, f.length);
            Color[] c2 = new Color[c.length + 1];
            System.arraycopy(c, 0, c2, 1, f.length);
            f = f2;
            c = c2;
            f[0] = 0;
            c[0] = c[1];
        }
        if (f[f.length - 1] != 1) {
            float[] f2 = new float[f.length + 1];
            System.arraycopy(f, 0, f2, 0, f.length);
            Color[] c2 = new Color[c.length + 1];
            System.arraycopy(c, 0, c2, 0, f.length);
            f = f2;
            c = c2;
            f[f.length - 1] = 1;
            c[c.length - 1] = c[c.length - 2];
        }

        /** Now, finally paint */
        int[] argb = new int[c.length];
        for (int a = 0; a < argb.length; a++) {
            argb[a] = ((c[a].getAlpha() & 0xff) << 24) +
                    ((c[a].getRed() & 0xff) << 16) +
                    ((c[a].getGreen() & 0xff) << 8) +
                    ((c[a].getBlue() & 0xff) << 0);
        }
        int max;
        if (slider.getOrientation() == GradientSlider.HORIZONTAL) {
            max = trackRect.width;
        } else {
            max = trackRect.height;
        }
        if (max <= 0) {
            return;
        }

        boolean alwaysOpaque = getProperty(slider, "GradientSlider.showTranslucency", "true").equals("false");

        float fraction;
        int i1 = 0;
        int i2 = 1;
        int a1 = (argb[0] >> 24) & 0xff;
        int r1 = (argb[0] & 0x00ff0000) >> 16;
        int g1 = (argb[0] & 0x0000ff00) >> 8;
        int b1 = (argb[0] & 0x000000ff) >> 0;
        int a2 = (argb[1] >> 24) & 0xff;
        int r2 = (argb[1] & 0x00ff0000) >> 16;
        int g2 = (argb[1] & 0x0000ff00) >> 8;
        int b2 = (argb[1] & 0x000000ff) >> 0;
        for (int z = 0; z < max; z++) {
            fraction = ((float) z) / ((float) (max - 1));
            if (fraction < 1 && fraction >= f[i2]) {
                while (fraction < 1 && fraction >= f[i2]) {
                    i1++;
                    i2++;
                }

                a1 = (argb[i1] >> 24) & 0xff;
                r1 = (argb[i1] & 0x00ff0000) >> 16;
                g1 = (argb[i1] & 0x0000ff00) >> 8;
                b1 = (argb[i1] & 0x000000ff) >> 0;
                a2 = (argb[i2] >> 24) & 0xff;
                r2 = (argb[i2] & 0x00ff0000) >> 16;
                g2 = (argb[i2] & 0x0000ff00) >> 8;
                b2 = (argb[i2] & 0x000000ff) >> 0;
            }
            float colorFraction = (fraction - f[i1]) / (f[i2] - f[i1]);
            if (colorFraction > 1) {
                colorFraction = 1;
            }
            if (colorFraction < 0) {
                colorFraction = 0;
            }
            if (alwaysOpaque) {
                a1 = 255;
                a2 = 255;
            }
            array[z] = (((int) (a1 * (1 - colorFraction) + a2 * colorFraction)) << 24) +
                    (((int) (r1 * (1 - colorFraction) + r2 * colorFraction)) << 16) +
                    (((int) (g1 * (1 - colorFraction) + g2 * colorFraction)) << 8) +
                    (((int) (b1 * (1 - colorFraction) + b2 * colorFraction)));
        }
        img.getRaster().setDataElements(0, 0, max, 1, array);
    }

    public Dimension getMinimumSize(JComponent s) {
        Dimension d = super.getMinimumSize(s);
        if (slider.getOrientation() == GradientSlider.HORIZONTAL) {
            d.height += 2;
        } else {
            d.width += 2;
        }
        return d;
    }

    public Dimension getPreferredSize(JComponent s) {
        Dimension d = super.getPreferredSize(s);
        if (slider.getOrientation() == GradientSlider.HORIZONTAL) {
            d.height += 2;
        } else {
            d.width += 2;
        }
        return d;
    }

    protected Rectangle calculateTrackRect() {
        int w = slider.getWidth();
        int h = slider.getHeight();

        Rectangle r = new Rectangle();

        if (slider.getOrientation() == GradientSlider.HORIZONTAL) {
            r.x = TRIANGLE_SIZE;
            r.y = 3;
            r.height = h - TRIANGLE_SIZE - r.y;
            r.width = w - 2 * TRIANGLE_SIZE;
            if (r.width > img.getWidth()) {
                r.width = img.getWidth();
                r.x = (w - 2 * TRIANGLE_SIZE) / 2 - r.width / 2;
            }
            if (r.height > 2 * DEPTH) {
                r.height = 2 * DEPTH;
                r.y = (h - TRIANGLE_SIZE) / 2 - r.height / 2;
            }
        } else {
            r.x = 3;
            r.y = TRIANGLE_SIZE;
            r.width = w - TRIANGLE_SIZE - r.x;
            r.height = h - 2 * TRIANGLE_SIZE;
            if (r.height > img.getWidth()) {
                r.height = img.getWidth();
                r.y = (h - 2 * TRIANGLE_SIZE) / 2 - r.height / 2;
            }
            if (r.width > 2 * DEPTH) {
                r.width = 2 * DEPTH;
                r.x = (w - TRIANGLE_SIZE) / 2 - r.width / 2;
            }
        }
        return r;
    }

    protected void calculateGeometry() {
        super.calculateGeometry();
        calculateImage();
    }
    static TexturePaint checkerPaint;

    private static void createCheckerPaint() {
        int k = 4;
        BufferedImage bi = new BufferedImage(2 * k, 2 * k, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bi.createGraphics();
        g.setColor(Color.white);
        g.fillRect(0, 0, 2 * k, 2 * k);
        g.setColor(Color.lightGray);
        g.fillRect(0, 0, k, k);
        g.fillRect(k, k, k, k);
        checkerPaint = new TexturePaint(bi, new Rectangle(0, 0, bi.getWidth(), bi.getHeight()));
    }

    /** The "frame" includes the trackRect and possible some extra padding.
     * For example, the frame might be the rounded rectangle enclosing the
     * track (if rounded rectangles are turned on)
     * @return
     */
    private Shape getFrame() {

        if (getProperty(slider, "GradientSlider.useBevel", "false").equals("true")) {
            return trackRect;
        }

        if (slider.getOrientation() == GradientSlider.HORIZONTAL) {
            int curve = Math.min(TRIANGLE_SIZE - 2, trackRect.height / 2);
            return new RoundRectangle2D.Float(
                    trackRect.x - curve, trackRect.y,
                    trackRect.width + 2 * curve, trackRect.height,
                    curve * 2, curve * 2);
        } else {
            int curve = Math.min(TRIANGLE_SIZE - 2, trackRect.width / 2);
            return new RoundRectangle2D.Float(
                    trackRect.x, trackRect.y - curve,
                    trackRect.width, trackRect.height + 2 * curve,
                    curve * 2, curve * 2);
        }
    }

    protected void paintTrack(Graphics2D g) {
        Composite oldComposite = g.getComposite();
        float alpha = slider.isEnabled() ? 1 : .5f;
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));

        Shape frame = getFrame();

        boolean alwaysOpaque = getProperty(slider, "GradientSlider.showTranslucency", "true").equals("false");

        if (alwaysOpaque == false) {
            if (checkerPaint == null) {
                createCheckerPaint();
            }
            g.setPaint(checkerPaint);
            g.fill(frame);
        }

        TexturePaint tp = new TexturePaint(img, new Rectangle(trackRect.x, 0, img.getWidth(), 1));
        g.setPaint(tp);
        AffineTransform oldTransform = null;

        oldTransform = g.getTransform();
        AffineTransform transform = new AffineTransform();
        if (slider.getOrientation() == GradientSlider.VERTICAL) {
            if (slider.isInverted()) {
                transform.rotate(Math.PI / 2, trackRect.x, trackRect.y);
            } else {
                transform.rotate(-Math.PI / 2, trackRect.x, trackRect.y + trackRect.height);
            }
        } else {
            if (slider.isInverted()) {
                //flip horizontal:
                double x1 = trackRect.x;
                double x2 = trackRect.x + trackRect.width;
                //m00*x1+m02 = x2
                //m00*x2+m02 = x1
                double m00 = (x2 - x1) / (x1 - x2);
                double m02 = x1 - m00 * x2;
                transform.setTransform(m00, 0, 0, 1, m02, 0);
            } else {
                //no transform necessary
            }
        }

        g.transform(transform);

        try {
            g.fill(transform.createInverse().createTransformedShape(trackRect));
        } catch (NoninvertibleTransformException e) {
            //this won't happen; unless a width/height
            //is zero somewhere, in which case we have nothing to paint anyway.
        }
        if (oldTransform != null) {
            g.setTransform(oldTransform);
        }
        if (getProperty(slider, "GradientSlider.useBevel", "false").equals("true")) {
            PaintUtils.drawBevel(g, trackRect);
        } else {
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            Shape oldClip = g.getClip();
            int first, last;
            Color[] colors = ((GradientSlider) slider).getColors();
            float[] f = slider.getThumbPositions();
            if ((slider.isInverted() == false && slider.getOrientation() == GradientSlider.HORIZONTAL) ||
                    (slider.isInverted() == true && slider.getOrientation() == GradientSlider.VERTICAL)) {
                first = 0;
                last = colors.length - 1;
                while (f[first] < 0) {
                    first++;
                }
                while (f[last] > 1) {
                    last--;
                }
            } else {
                last = 0;
                first = colors.length - 1;
                while (f[last] < 0) {
                    last++;
                }
                while (f[first] > 1) {
                    first--;
                }
            }
            if (slider.getOrientation() == GradientSlider.HORIZONTAL) {
                g.clip(frame);
                g.setColor(colors[first]);
                g.fillRect(0, 0, trackRect.x, slider.getHeight());
                g.setColor(colors[last]);
                g.fillRect(trackRect.x + trackRect.width, 0,
                        slider.getWidth() - (trackRect.x + trackRect.width), slider.getHeight());
            } else {
                g.clip(frame);
                g.setColor(colors[first]);
                g.fillRect(0, 0, slider.getWidth(), trackRect.y);
                g.setColor(colors[last]);
                g.fillRect(0, trackRect.y + trackRect.height,
                        slider.getWidth(), slider.getHeight() - (trackRect.y + trackRect.height));
            }
            g.setStroke(new BasicStroke(1));
            g.setClip(oldClip);
            g.setColor(new Color(0, 0, 0, 130));
            g.draw(frame);

            g.setColor(new Color(0, 0, 0, 130));
        }

        if (slider.isPaintTicks()) {
            paintTick(g, .25f, 2);
            paintTick(g, .5f, 2);
            paintTick(g, .75f, 2);
            paintTick(g, 0f, 2);
            paintTick(g, 1f, 2);
        }
        g.setComposite(oldComposite);
    }

    protected void paintTick(Graphics2D g, float f, int d) {
        if (slider.getOrientation() == GradientSlider.HORIZONTAL) {
            int x = (int) (trackRect.x + trackRect.width * f + .5f);
            int y = trackRect.y + trackRect.height;
            g.drawLine(x, y, x, y + d);
            y = trackRect.y;
            g.drawLine(x, y, x, y - d);
        } else {
            int y = (int) (trackRect.y + trackRect.height * f + .5f);
            int x = trackRect.x + trackRect.width;
            g.drawLine(x, y, x + d, y);
            x = trackRect.x;
            g.drawLine(x, y, x - d, y);
        }
    }

    protected void paintFocus(Graphics2D g) {
    }
    static GeneralPath hTriangle = null;
    static GeneralPath vTriangle = null;

    protected void paintThumbs(Graphics2D g) {
        if (slider.isEnabled() == false) {
            return;
        }

        if (hTriangle == null) {
            hTriangle = new GeneralPath();
            hTriangle.moveTo(0, 0);
            hTriangle.lineTo(TRIANGLE_SIZE, TRIANGLE_SIZE);
            hTriangle.lineTo(-TRIANGLE_SIZE, TRIANGLE_SIZE);
            hTriangle.lineTo(0, 0);
            hTriangle.closePath();
            vTriangle = new GeneralPath();
            vTriangle.moveTo(0, 0);
            vTriangle.lineTo(TRIANGLE_SIZE, TRIANGLE_SIZE);
            vTriangle.lineTo(TRIANGLE_SIZE, -TRIANGLE_SIZE);
            vTriangle.lineTo(0, 0);
            vTriangle.closePath();
        }


        AffineTransform t = new AffineTransform();
        int dx = trackRect.x + trackRect.width;
        int dy = trackRect.y + trackRect.height;
        dy -= trackRect.height / 6;
        dx -= trackRect.width / 6;
        int selected = slider.getSelectedThumb(false);
        float[] f = slider.getThumbPositions();
        int orientation = slider.getOrientation();
        Shape shape;

        Composite oldComposite = g.getComposite();

        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                indication));

        for (int a = 0; a < thumbPositions.length; a++) {
            if (f[a] >= 0 && f[a] <= 1 && a != selected) {
                if (orientation == GradientSlider.HORIZONTAL) {
                    dx = thumbPositions[a];
                    shape = hTriangle;
                } else {
                    dy = thumbPositions[a];
                    shape = vTriangle;
                }
                t.setToTranslation(dx, dy);
                g.transform(t);

                float brightness = Math.max(0, thumbIndications[a] * .6f);

                g.setColor(new Color((int) (255 * brightness),
                        (int) (255 * brightness),
                        (int) (255 * brightness)));
                g.fill(shape);
                g.translate(-.5f, -.5f);

                g.setColor(new Color(255, 255, 255));

                g.draw(shape);
                g.translate(.5f, .5f);

                t.setToTranslation(-dx, -dy);
                g.transform(t);
            }
        }

        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                indication));

        if (selected != -1 && f[selected] >= 0 && f[selected] <= 1) {
            if (orientation == GradientSlider.HORIZONTAL) {
                dx = thumbPositions[selected];
                shape = hTriangle;
            } else {
                dy = thumbPositions[selected];
                shape = vTriangle;
            }
            t.setToTranslation(dx, dy);
            g.transform(t);

            g.setColor(new Color(255, 255, 255));
            g.fill(shape);
            g.translate(-.5f, -.5f);

            g.setColor(new Color(0, 0, 0));

            g.draw(shape);
            g.translate(.5f, .5f);

            t.setToTranslation(-dx, -dy);
            g.transform(t);
        }

        g.setComposite(oldComposite);
    }
}
TOP

Related Classes of org.gephi.ui.components.gradientslider.GradientSliderUI

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.