/*-
 * #%L
 * Fiji distribution of ImageJ for the life sciences.
 * %%
 * Copyright (C) 2007 - 2017 Fiji developers.
 * %%
 * 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.
 * 
 * You should have received a copy of the GNU General Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/gpl-2.0.html>.
 * #L%
 */
package spim.fiji.plugin.util;

import ij.gui.GenericDialog;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Panel;
import java.awt.RenderingHints;

public class MyMultiLineLabel extends Canvas
{
	private static final long serialVersionUID = 1L;

	protected String[] lines;
	protected int num_lines;
	protected int margin_width = 6;
	protected int margin_height = 6;
	protected int line_height;
	protected int line_ascent;
	protected int[] line_widths;
	protected int min_width, max_width;
    
	final GenericDialog gd;
	final Panel panel;
	
    // Breaks the specified label up into an array of lines.
    public MyMultiLineLabel( final GenericDialog gd, final Panel panel, final String[] label )
    {
        this( gd, panel, label, 0 );
    }

    public MyMultiLineLabel( final GenericDialog gd, final Panel panel, final String[] label, final int minimumWidth )
    {
        num_lines = label.length;
        lines = label;
        line_widths = new int[ num_lines ];
        min_width = minimumWidth;
        this.gd = gd;
        this.panel = panel;
    }
    
    public String[] getLines() { return lines; }
    public void setText( final String[] lines )
    {
    	for ( int i = 0; i < this.lines.length; ++i )
    	{
    		if ( i >= lines.length )
    			this.lines[ i ] = " ";
    		else
    			this.lines[ i ] = lines[ i ];
    	}
    	
    	updateLabel();
    }
    
    public void updateLabel()
    {
    	this.update( this.getGraphics() );
    }

    /** Adds a message consisting of one or more lines of text,
    which will be displayed using the specified font and color. */
    public static MyMultiLineLabel addMessage( final GenericDialog gd, final String[] text, final Font font, final Color color )
    {
    	final Panel panel = new Panel();
    	final MyMultiLineLabel l = new MyMultiLineLabel( gd, panel, text );
    	
    	l.setFont( font );
    	l.setForeground( color );

    	panel.add( l );
    	gd.addPanel( panel );
    	
    	return l;
    }

    // Figures out how wide each line of the label
    // is, and how wide the widest line is.
    protected void measure()
    {
        final FontMetrics fm = this.getFontMetrics( this.getFont() );
        // If we don't have font metrics yet, just return.
        if (fm == null) return;
        
        line_height = fm.getHeight();
        line_ascent = fm.getAscent();
        max_width = 0;
        
        for( int i = 0; i < num_lines; i++ )
        {
            line_widths[ i ] = fm.stringWidth( lines[ i ] );
            if ( line_widths[ i ] > max_width )
            	max_width = line_widths[i];
        }
    }
    

    public void setFont( final Font f )
    {
        super.setFont( f );
        measure();
        repaint();
    }


    // This method is invoked after our Canvas is first created
    // but before it can actually be displayed.  After we've
    // invoked our superclass's addNotify() method, we have font
    // metrics and can successfully call measure() to figure out
    // how big the label is.
    public void addNotify()
    {
        super.addNotify();
        measure();
    }
    

    // Called by a layout manager when it wants to
    // know how big we'd like to be.  
    public Dimension getPreferredSize()
    {
        return new Dimension( Math.max( min_width, max_width + 2*margin_width ), 
                     num_lines * line_height + 2*margin_height );
    }
    

    // Called when the layout manager wants to know
    // the bare minimum amount of space we need to get by.
    public Dimension getMinimumSize()
    {
        return new Dimension(Math.max(min_width, max_width), num_lines * line_height);
    }
    
    // Draws the label
    public void paint( final Graphics g )
    {
        int x, y;
        final Dimension d = this.getSize();
        if ( !ij.IJ.isLinux() ) setAntialiasedText( g );
        y = line_ascent + (d.height - num_lines * line_height)/2;
        for( int i = 0; i < num_lines; i++, y += line_height )
        {
            x = margin_width;
            g.drawString( lines[ i ], x, y );
        }
    }

    void setAntialiasedText( final Graphics g )
    {
    	final Graphics2D g2d = (Graphics2D)g;
    	g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    }

}