/* AnnotatedRenderer.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.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Stroke;
import java.awt.geom.Rectangle2D;

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

/**
 * An extension of DefaultRenderer that adds rendering of annotations.
 */
public class AnnotatedRenderer extends DefaultRenderer {

    //
    private static final Renderer SINGLETON = new AnnotatedRenderer();

    /**
     * Get the singleton instance of this renderer.
     */
    public static Renderer getInstance() {
        return SINGLETON;
    }

    /**
     * Paints the given vertex onto the given graphics context, with annotations
     * (when available).
     */
    public void paint(Vertex vertex, double[] coordinates, boolean rollover, boolean selected, Object annotation, Graphics2D g2) {
        super.paint(vertex, coordinates, rollover, selected, annotation, g2);
        if (annotation != null) {
            paintAnnotation(g2, coordinates[0], coordinates[1],
                    annotation.toString(), selected);
        }
    }

    /**
     * Paints the given edge onto the given graphics context, with annotations
     * (when available).
     */
    public void paint(Edge edge, double[] coordinates_first, double[] coordinates_second, boolean rollover, boolean selected, Object annotation, Graphics2D g2) {
        super.paint(edge, coordinates_first, coordinates_second, rollover, selected, annotation, g2);
        if (annotation != null) {
            double x = coordinates_first[0] + ((coordinates_second[0] - coordinates_first[0]) / 2);
            double y = coordinates_first[1] + ((coordinates_second[1] - coordinates_first[1]) / 2);
            paintAnnotation(g2, x, y,
                    annotation.toString(), selected);
        }
    }

    // Font used for rendering annotations
    private Font font = Font.decode("serif-10");
    
    // Vertical offset for annotations
    private int voffset = -10;
    
    // Horizontal margin for annotation border
    private int hmargin = 2;
    
    // Vertical margin for annotation border
    private int vmargin = 0;
    
    // Stroke to be used for annotation border
    private Stroke annotationStroke = new BasicStroke(1.0f);
    
    // Color of annotation background
    //private Color annotationBackground = new Color (183,204,225,192);
    private Color annotationBackground = new Color(183, 204, 225);
    
    // Color of annotation border
    private Color annotationBorder = new Color(128, 149, 170);
    
    // Color of select annotation background
    //private Color annotationSelected = new Color (174,255,0,192);
    //private Color annotationSelected = new Color (131,193, 255);
    private Color annotationSelected = new Color(174, 255, 0);
    
    //  Paint used for annotation text
    private Paint paint = Color.BLACK;

    /**
     * Paints the annotation of a given element near the given coordinate.
     */
    private void paintAnnotation(Graphics2D g2, double x, double y,
            String label, boolean selected) {
        g2.setFont(font);
        FontMetrics metrics = g2.getFontMetrics();
        int width = metrics.stringWidth(label);
        int top = metrics.getAscent() + vmargin;
        int height = top + metrics.getDescent() + vmargin;
        Rectangle2D rect = new Rectangle2D.Double(x - width / 2 - hmargin, y + voffset - top, width + 2 * hmargin - 1, height - 1);
        g2.setPaint(selected ? annotationSelected : annotationBackground);
        g2.fill(rect);
        g2.setPaint(paint);
        g2.drawString(label, (float) x - width / 2, (float) y + voffset);
        g2.setPaint(annotationBorder);
        g2.setStroke(annotationStroke);
        g2.draw(rect);
    }
    
}
