/* * This file is part of Caliph & Emir. * * Caliph & Emir 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. * * Caliph & Emir 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 Caliph & Emir; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Copyright statement: * -------------------- * (c) 2002-2005 by Mathias Lux (mathias@juggle.at) * http://www.juggle.at, http://caliph-emir.sourceforge.net */ package at.lux.fotoretrieval; import at.lux.imageanalysis.ColorLayout; import at.lux.retrieval.calculations.DistanceMatrix; import at.lux.retrieval.fdp.FDP; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; /** * Date: 14.01.2005 * Time: 00:00:38 * * @author Mathias Lux, mathias@juggle.at */ public class PointPanel extends JPanel implements MouseListener { private float points[][]; private float maxX, maxY, minX, minY; DistanceMatrix matrixFastmap; private FDP fdp; /** * Creates a new <code>JPanel</code> with a double buffer * and a flow layout. */ public PointPanel(float[][] points, DistanceMatrix matrixFastmap) { this.points = points; this.matrixFastmap = matrixFastmap; fdp = new FDP(matrixFastmap, points); addMouseListener(this); initMinMax(); } private void initMinMax() { maxX = getMax(0); maxY = getMax(1); minX = getMin(0); minY = getMin(1); /* for (int i = 1; i < points.length; i++) { float[] point = points[i]; if (point[0] > maxX) { maxX = point[0]; } else if (point[0] < minX) { minX = point[0]; } if (point[1] > maxY) { maxY = point[1]; } else if (point[1] < minY) { minX = point[1]; } } */ } /** * Calls the UI delegate's paint method, if the UI delegate * is non-<code>null</code>. We pass the delegate a copy of the * <code>Graphics</code> object to protect the rest of the * paint code from irrevocable changes * (for example, <code>Graphics.translate</code>). * <p/> * If you override this in a subclass you should not make permanent * changes to the passed in <code>Graphics</code>. For example, you * should not alter the clip <code>Rectangle</code> or modify the * transform. If you need to do these operations you may find it * easier to create a new <code>Graphics</code> from the passed in * <code>Graphics</code> and manipulate it. Further, if you do not * invoker super's implementation you must honor the opaque property, * that is * if this component is opaque, you must completely fill in the background * in a non-opaque color. If you do not honor the opaque property you * will likely see visual artifacts. * <p/> * The passed in <code>Graphics</code> object might * have a transform other than the identify transform * installed on it. In this case, you might get * unexpected results if you cumulatively apply * another transform. * * @param g the <code>Graphics</code> object to protect * @see #paint * @see javax.swing.plaf.ComponentUI */ protected void paintComponent(Graphics g) { initMinMax(); super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; float width = this.getWidth(); float height = this.getHeight(); for (int i = 0; i < points.length; i++) { float[] point = points[i]; float x = (point[0] - minX) / (maxX - minX); float y = (point[1] - minY) / (maxY - minY); Object cl = matrixFastmap.getUserObject(i); if (cl instanceof ColorLayout) { g2.drawImage(((ColorLayout) cl).getColorLayoutImage(), (int) (x * width), (int) (y * height), null); } else { g2.drawOval((int) (x * width), (int) (y * height), 3, 3); } } } /** * Invoked when the mouse button has been clicked (pressed * and released) on a component. */ public void mouseClicked(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1) { Thread t = new Thread(new FdpThread(fdp, this)); t.start(); } } /** * Invoked when a mouse button has been pressed on a component. */ public void mousePressed(MouseEvent e) { //To change body of implemented methods use File | Settings | File Templates. } /** * Invoked when a mouse button has been released on a component. */ public void mouseReleased(MouseEvent e) { //To change body of implemented methods use File | Settings | File Templates. } /** * Invoked when the mouse enters a component. */ public void mouseEntered(MouseEvent e) { //To change body of implemented methods use File | Settings | File Templates. } /** * Invoked when the mouse exits a component. */ public void mouseExited(MouseEvent e) { //To change body of implemented methods use File | Settings | File Templates. } private float getMax(int index) { float f = points[0][index]; for (int i = 1; i < points.length; i++) { if (f < points[i][index]) f = points[i][index]; } return f; } private float getMin(int index) { float f = points[0][index]; for (int i = 1; i < points.length; i++) { if (f > points[i][index]) f = points[i][index]; } return f; } } class FdpThread implements Runnable { FDP fdp; PointPanel panel; public FdpThread(FDP fdp, PointPanel panel) { this.fdp = fdp; this.panel = panel; } /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p/> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see Thread#run() */ public void run() { for (int i = 0; i < 100; i++) { try { Thread.sleep(25); } catch (InterruptedException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } fdp.step(); System.out.println(fdp.getCurrentMovement()); panel.repaint(); } } }