/* DefaultRenderer.java
 * =========================================================================
 * This file is part of the GrInvIn project - http://www.grinvin.org
 * 
 * Copyright (C) 2005-2008 Universiteit Gent
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 * 
 * This program 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
 * General Public License for more details.
 * 
 * A copy of the GNU General Public License can be found in the file
 * LICENSE.txt provided with the source distribution of this program (see
 * the META-INF directory in the source jar). This license can also be
 * found on the GNU website at http://www.gnu.org/licenses/gpl.html.
 * 
 * If you did not receive a copy of the GNU General Public License along
 * with this program, contact the lead developer, or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

package org.grinvin.graphs.render;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;

import org.grinvin.graphs.Edge;
import org.grinvin.graphs.Vertex;

/**
 * Default implementation of a renderer. Renders vertices as small circles
 * and edges as solid lines. Is a singleton class whose sole instance should
 * be retrieved by means of the method {@link #getInstance}.
 */
public class DefaultRenderer implements Renderer {
    
    // Radius of a circle that represents a vertex
    private double radius = 4.0;
    
    // Radius of the circle that represents the current 'roll over'-vertex
    private double rollOverRadius = 5.0;
    
    // Paint to use when filling the vertex circle
    private Paint fillPaint = Color.WHITE;
    
    // Stroke used to draw the vertex circle border
    private Stroke borderStroke = new BasicStroke(2.0f);
    
    // Stroke used to draw a normal edge
    private Stroke stroke = new BasicStroke(2.0f);
    
    // Stroke to use to draw a 'roll over'-edge
    private Stroke rollOverStroke = new BasicStroke(3.0f);
    
    //  Paint used for normal vertex circle borders and edges
    private Paint paint = Color.BLACK;
    
    //  Paint used for selected vertex circle borders and edges
    private Paint selectedPaint  = new Color(0, 127, 255);
    
    //
    protected DefaultRenderer () { }
    
    //
    private static final Renderer SINGLETON = new DefaultRenderer();
    
    /**
     * Get the singleton instance of this renderer.
     */
    public static Renderer getInstance () {
        return SINGLETON;
    }
    
    // implements Renderer
    /**
     * Render a Vertex
     * @param vertex Vertex to render
     * @param coordinates Coordinates of the Vertex
     * @param rollover Is this the current rollover?
     * @param selected Is this Vertex selected?
     * @param g2 Panel to paint on
     */
    public void paint(Vertex vertex, double[] coordinates, boolean rollover, boolean selected, Object annotation, Graphics2D g2) {
        double r = rollover ? rollOverRadius : radius;
        Ellipse2D ell = new Ellipse2D.Double(coordinates[0]-r,coordinates[1]-r,2*r,2*r);
        g2.setPaint(fillPaint);
        g2.fill(ell);
        g2.setPaint(selected ? selectedPaint : paint);
        g2.setStroke(borderStroke);
        g2.draw(ell);
    }
    
    // implements Renderer
    /**
     * Render an Edge
     * @param edge Edge to render
     * @param coordinates_first Coordinates of the first Vertex
     * @param coordinates_second Coordinates of the second Vertex
     * @param rollover Is this the current rollover?
     * @param selected Is this Edge selected?
     * @param g2 Panel to paint on
     */
    public void paint(Edge edge, double[] coordinates_first, double[] coordinates_second, boolean rollover, boolean selected, Object annotation, Graphics2D g2) {
        Shape shape;
        if (!edge.getFirstEndpoint().equals(edge.getSecondEndpoint())) {
            shape = new Line2D.Double(
                    coordinates_first[0],
                    coordinates_first[1],
                    coordinates_second[0],
                    coordinates_second[1]);
        } else {
            shape = new Ellipse2D.Double(
                    coordinates_first[0],
                    coordinates_first[1],
                    10,
                    10);
        }
        g2.setPaint(selected ? selectedPaint : paint);
        g2.setStroke(rollover ? rollOverStroke : stroke);
        g2.draw(shape);
    }
    
}
