/*
 * #%L
 * gitools-ui-platform
 * %%
 * Copyright (C) 2013 Universitat Pompeu Fabra - Biomedical Genomics group
 * %%
 * 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 3 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-3.0.html>.
 * #L%
 */
package org.gitools.ui.platform.imageviewer;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

/**
 * An overlay is a layer on top of an image. It can be used to add annotations, arbitrary
 * shapes to an image. Drawing is implemented in the <code>paint</code> method.
 * <p>
 * The following is an implementation of a simple example overlay that draws a cross over
 * the image:
 * <pre>
 * 
 * class XPainter extends Overlay {
 *   public void paint(Graphics2D g, BufferedImage image, AffineTransform transform) {
 *     g.setColor(Color.RED);
 *     double[] bounds={
 *       0, 0, 
 *       image.getWidth(), 0,
 *       image.getWidth(), image.getHeight(),
 *       0, image.getHeight()};
 *     transform.transform(bounds, 0, bounds, 0, 4);
 *     g.drawLine((int)bounds[0], (int)bounds[1], (int)bounds[4], (int)bounds[5]);
 *     g.drawLine((int)bounds[2], (int)bounds[3], (int)bounds[6], (int)bounds[7]);
 *   }
 * }
 * </pre>
 * It can be added to a viewer by calling <code>viewer.addOverlay(new XPainter(), 10)</code>.
 * @author Kazó Csaba
 */
public abstract class Overlay {
	List<OverlayComponent> overlayComponents=new ArrayList<OverlayComponent>(1);
	final void addOverlayComponent(OverlayComponent c) {
		overlayComponents.add(c);
	}
	final void removeOverlayComponent(OverlayComponent c) {
		overlayComponents.remove(c);
	}
	/**
	 * Causes the overlay to be repainted.
	 */
	public void repaint() {
		for (OverlayComponent overlayComponent: overlayComponents)
			overlayComponent.repaint();
	}
	/**
	 * Called to paint the contents of this overlay. The graphics context to paint on is a copy
	 * for this overlay and can be freely modified.
	 * <p>
	 * The method receives the currently displayed image. The image is never <code>null</code> -
	 * if there is currently no image being displayed in the image viewer, then the
	 * <code>paint</code> method is not called.
	 * <p>
	 * This method also receives the transformation that is applied to the image before it
	 * is displayed. This transformation is most commonly the concatenation of a uniform scale
	 * and a translation. The original image bounds (0, 0)
	 * - (image.getWidth(), image.getHeight()) are mapped using this transformation to get the
	 * final display bounds. The overlay should not rely on whether painting outside these
	 * final bounds will be visible or not.
	 * @param g the graphics context to draw onto
	 * @param image the current image
	 * @param transform the transformation applied to the image before displaying
	 */
	public abstract void paint(Graphics2D g, BufferedImage image, AffineTransform transform);
}
