/*
 * #%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<>(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);
}
