package net.sf.openrocket.gui.scalefigure; import java.awt.Color; import java.awt.Dimension; import java.util.EventListener; import java.util.EventObject; import java.util.LinkedList; import java.util.List; import javax.swing.JPanel; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.util.StateChangeListener; public abstract class AbstractScaleFigure extends JPanel implements ScaleFigure { // Number of pixels to leave at edges when fitting figure private static final int DEFAULT_BORDER_PIXELS_WIDTH = 30; private static final int DEFAULT_BORDER_PIXELS_HEIGHT = 20; protected final double dpi; protected double scale = 1.0; protected double scaling = 1.0; protected int borderPixelsWidth = DEFAULT_BORDER_PIXELS_WIDTH; protected int borderPixelsHeight = DEFAULT_BORDER_PIXELS_HEIGHT; protected final List<EventListener> listeners = new LinkedList<EventListener>(); public AbstractScaleFigure() { this.dpi = GUIUtil.getDPI(); this.scaling = 1.0; this.scale = dpi / 0.0254 * scaling; setBackground(Color.WHITE); setOpaque(true); } public abstract void updateFigure(); public abstract double getFigureWidth(); public abstract double getFigureHeight(); @Override public double getScaling() { return scaling; } @Override public double getAbsoluteScale() { return scale; } @Override public void setScaling(double scaling) { if (Double.isInfinite(scaling) || Double.isNaN(scaling)) scaling = 1.0; if (scaling < 0.001) scaling = 0.001; if (scaling > 1000) scaling = 1000; if (Math.abs(this.scaling - scaling) < 0.01) return; this.scaling = scaling; this.scale = dpi / 0.0254 * scaling; updateFigure(); } @Override public void setScaling(Dimension bounds) { double zh = 1, zv = 1; int w = bounds.width - 2 * borderPixelsWidth - 20; int h = bounds.height - 2 * borderPixelsHeight - 20; if (w < 10) w = 10; if (h < 10) h = 10; zh = (w) / getFigureWidth(); zv = (h) / getFigureHeight(); double s = Math.min(zh, zv) / dpi * 0.0254 - 0.001; // Restrict to 100% if (s > 1.0) { s = 1.0; } setScaling(s); } @Override public Dimension getBorderPixels() { return new Dimension(borderPixelsWidth, borderPixelsHeight); } @Override public void setBorderPixels(int width, int height) { this.borderPixelsWidth = width; this.borderPixelsHeight = height; } @Override public void addChangeListener(StateChangeListener listener) { listeners.add(0, listener); } @Override public void removeChangeListener(StateChangeListener listener) { listeners.remove(listener); } private EventObject changeEvent = null; protected void fireChangeEvent() { if (changeEvent == null) changeEvent = new EventObject(this); // Copy the list before iterating to prevent concurrent modification exceptions. EventListener[] list = listeners.toArray(new EventListener[0]); for (EventListener l : list) { if (l instanceof StateChangeListener) { ((StateChangeListener) l).stateChanged(changeEvent); } } } }