/* * #%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.geom.Point2D; import java.awt.image.BufferedImage; import java.util.HashSet; import java.util.Set; /** * An overlay for marking pixels of the image. A circle will be drawn around the selected pixels; the size of the circle * is set independently of the current zoom, but it may be enlarged in order to contain the pixel entirely. * <p/> * The default size is 5 pixels and the default color is red. * <p/> * This object stores the list of pixels; this list can be edited with the {@link #setPoint(java.awt.Point)}, * {@link #setPoints(Iterable)}, {@link #addPoint(java.awt.Point)}, and {@link #clear()} functions. All of these * mutator functions cause the overlay to be repainted. * * @author Kazó Csaba */ public final class PixelMarkerOverlay extends Overlay { private Set<Point> points = new HashSet<>(); private Color color = Color.RED; private int size = 5; /** * Sets the size of the circle. The actual width and height of the circle will be {@code 2*newSize+1}. * * @param newSize the new size of the marker circles * @throws IllegalArgumentException if {@code newSize} is negative */ public void setSize(int newSize) { if (newSize < 0) throw new IllegalArgumentException("Negative size"); size = newSize; repaint(); } /** * Sets the color of the marker circles. * * @param color the new color * @throws NullPointerException if {@code color} is {@code null} */ public void setColor(Color color) { if (color == null) throw new NullPointerException(); this.color = color; repaint(); } /** * Adds a point to the list of pixels marked by this overlay. * * @param p a new point * @throws NullPointerException if {@code p} is {@code null} */ public void addPoint(Point p) { if (p == null) throw new NullPointerException(); points.add(new Point(p)); repaint(); } /** * Sets the argument as the only point marked by this overlay. * * @param p the point to mark; if {@code null}, then no points will be selected */ public void setPoint(Point p) { points.clear(); if (p != null) { points.add(new Point(p)); } repaint(); } /** * Sets the marked pixels. * * @param points an iterable of all the pixels that should be selected * @throws NullPointerException if {@code points} or any individual point is {@code null} */ public void setPoints(Iterable<Point> points) { if (points == null) throw new NullPointerException(); this.points.clear(); for (Point p : points) { this.points.add(new Point(p)); } repaint(); } /** * Removes all pixels from the overlay, clearing the selection. */ public void clear() { if (!points.isEmpty()) { points.clear(); repaint(); } } @Override public void paint(Graphics2D g, BufferedImage image, AffineTransform transform) { g.setColor(color); Point2D p2d = new Point2D.Double(); int currentSize = Math.max(size, (int) Math.ceil(transform.getScaleX() / Math.sqrt(2))); for (Point p : points) { p2d.setLocation(p.x + .5, p.y + .5); transform.transform(p2d, p2d); g.drawOval((int) p2d.getX() - currentSize, (int) p2d.getY() - currentSize, 2 * currentSize + 1, 2 * currentSize + 1); } } }