/*
 * $Id: JPane.java,v 1.31 2003/09/16 19:05:41 dwd Exp $
 *
 * This software is provided by NOAA for full, free and open release.  It is
 * understood by the recipient/user that NOAA assumes no liability for any
 * errors contained in the code.  Although this software is released without
 * conditions or restrictions in its use, it is expected that appropriate
 * credit be given to its author and to the National Oceanic and Atmospheric
 * Administration should the software be included by the recipient as an
 * element in other product development.
 */

package  sgtplot;


import java.awt.Rectangle;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.AWTEvent;

import java.awt.event.MouseEvent;
import java.beans.PropertyChangeListener;

import javax.swing.SwingConstants;
//import javax.swing.RepaintManager;
import javax.swing.border.Border;

import org.freehep.graphics2d.VectorGraphics;

import sgtplot.beans.Panel;
import sgtplot.util.Debug;

import java.awt.print.*;
import java.awt.Color;
import java.awt.geom.AffineTransform;

/**
 * The JPane class is extended from
 * javax.swing.JLayeredPane
 * and is the basis for using the gov.noaa.pmel.sgt
 * package with swing components.
 * 

* The Java scientific graphics toolkit is designed to allow a * graphics client developer a great deal of flexibility and freedom. * sgtplot is a package that greatly aids a developer in * creating graphics applets. sgtplot is not a general * purpose graphics package, but provides the tools to enable * scientific graphics to be easily incorporated into JApplet. *

* sgtplot has three main components, the "pane", on which * all graphics are drawn. The JPane is a fairly simple * class and all drawing is done in "device" coordinates (pixels). * By default, the JPane will draw on the screen, but it is * designed to allow drawing in an offscreen buffer that can be * printed (for applications). *

* The next component is the Layer. Several * Layers can be associated with a single * JPane. The Layer class insulates * the developer from the details of device coordinates by * using "physical" coordinates. Physical coordinates are * a right-hand coordinate systems with an origin of (0.0, 0.0) in the * lower-left-hand corner and have the same scale in both the vertical * and horizontal directions. Thus, a Layer that is * 5.0 units wide and 3.0 units high can be made larger and smaller * on the screen by resizing the JPane, but will not be * distorted. The Layer class is responsible for * displaying labels, keys (color, vector, and line), and rulers. * A Layer can contain a single Graph. *

* Finally, the Graph component transforms from * user coordinates (e.g. cm/sec, time, degC, or meters) to * physical coordinates. The Graph * classes handle the display of axes and data. Children of * the Graph class are capable of creating Cartesian, * polar, and map graphics. For Cartesian graphs, several different * axes (log, plain and time), transforms (linear, log, and * tablelookup), and CartesianGraph (pixel, * line, vector, and contour) classes are available. These classes can be * combined in almost any combination. *

* While only one dataset may be plotted per Layer, * co-plotting is supported by allowing layers to use the same * transform objects. The order that the layers are plotted can * be changed, allowing the developer (or user) to control what * may be obscured. *

* Member functions, in package gov.noaa.pmel.sgt, * follow the following naming convention. Member functions that * have a P, U, or nothing at the end of the * function name are of type double in Physical * units, type double in User units, and type int in Device * units, respectively. * Variables that start with p, u, t, or d are coordinates of type physical, * user, time, or device, respectively. *

* All graphics are rendered when the draw() method is invoked. *

* Mouse Events *

* Mouse events are processed by the JPane object to support * object selection and zooming. Object selection is accomplished by * left clicking the mouse on the desired object. JPane * then fires a PropertyChangeEvent of type * "objectSelected" that can be listened for by the users application. * The user application then invokes the * getSelectedObject() method. Zooming is accomplished in * several steps. *

* *

 * 1) Begin a zoom operation by pressing the left button.
 * 2) Describe a zoom rectangle by dragging the mouse with the left
 *    button down.
 * 3) Finish the zoom operation by releasing the left mouse button.
 * 
* *

* When the mouse button has been release JPane fires a * PropertyChangeEvent of type "zoomRectangle" that can * be listened for by the users application. The user application can * then obtain the zoom rectangle by invoking the * getZoomBounds() method. * * *

 * ...
 * //
 * // register the PropertyChangeListener listener with pane
 * // (assuming that application implements PropertyChangeListener)
 * //
 * mainPane_.addPropertyChangeListener(this);
 * //
 * ...
 * //
 * // Implement the propertyChange() method and listen for events
 * //
 *  public void propertyChange(PropertyChangeEvent event) {
 *    //
 *    // Listen for property change events from JPane
 *    //
 *    String name = event.getPropertyName();
 *    if(name.equals("zoomRectangle")) {
 *      //
 *      // compute zoom rectangle in user units
 *      //
 *      Range2D xr = new Range2D();
 *      Range2D yr = new Range2D();
 *      Rectangle zm = (Rectangle)event.getNewValue();
 *      //
 *      // if rectangle size is one pixel or less return
 *      //
 *      if(zm.width <= 1 || zm.height <= 1) return;
 *      xr.start = graph_.getXPtoU(layer_.getXDtoP(zm.x));
 *      xr.end = graph_.getXPtoU(layer_.getXDtoP(zm.x + zm.width));
 *      if(xr.start > xr.end) {
 *        double temp = xr.start;
 *        xr.start = xr.end;
 *        xr.end = temp;
 *      }
 *      yr.start = graph_.getYPtoU(layer_.getYDtoP(zm.y));
 *      yr.end = graph_.getYPtoU(layer_.getYDtoP(zm.y + zm.height));
 *      if(yr.start > yr.end) {
 *        double temp = yr.start;
 *        yr.start = yr.end;
 *        yr.end = temp;
 *      }
 *      //
 *      // turn batching on so all changes will appear at the
 *      // same time
 *      //
 *      mainPane_.setBatch(true);
 *      //
 *      // set range for transforms
 *      //
 *      xt_.setRangeU(xr);
 *      yt_.setRangeU(yr);
 *      //
 *      // set range and origin for axes
 *      //
 *      Point2D.Double orig = new Point2D.Double(xr.start, yr.start);
 *      xbot_.setRangeU(xr);
 *      xbot_.setLocationU(orig);
 *
 *      yleft_.setRangeU(yr);
 *      yleft_.setLocationU(orig);
 *      //
 *      // set clipping on all graphs
 *      //
 *      Component[] comps = mainPane_.getComponents();
 *      Layer ly;
 *      for(int i=0; i < comps.length; i++) {
 *        if(comps[i] instanceof Layer) {
 *          ly = (Layer)comps[i];
 *          ((CartesianGraph)ly.getGraph()).setClip(xr.start, xr.end,
 *                                                  yr.start, yr.end);
 *        }
 *      }
 *      //
 *      // done with sgtplot modifications, turn batching off
 *      //
 *      mainPane_.setBatch(false);
 *    } else if(name.equals("objectSelected")) {
 *      //
 *      // An sgtplot object has been selected.
 *      // If it is a PointCartesianRenderer that means the key has been
 *      // selected and so open a dialog to modified the PointAttribute.
 *      //
 *      if(event.getNewValue() instanceof PointCartesianRenderer) {
 *	  PointAttribute pattr =
 *	    ((PointCartesianRenderer)event.getNewValue()).getPointAttribute();
 *	  if(pAttrDialog_ == null) {
 *	    pAttrDialog_ = new PointAttributeDialog();
 *	  }
 *	  pAttrDialog_.setPointAttribute(pattr, mainPane_);
 *	  pAttrDialog_.setVisible(true);
 *      } else {
 *	  //
 *	  // Print the name of the object selected.
 *	  //
 *	  System.out.println("objectSelected = " + event.getNewValue());
 *      }
 *    }
 *  }
 * 
* * @author Donald Denbo * @version $Revision: 1.31 $, $Date: 2003/09/16 19:05:41 $ * @since 2.0 * @see Layer * @see Graph * @see java.awt.Graphics **/ public class JPane extends javax.swing.JLayeredPane //public class JPane extends javax.swing.JComponent implements AbstractPane, javax.swing.Scrollable, Printable { /** * */ private static final long serialVersionUID = 1L; // private PaneProxy proxy_; private int horizBlockIncrement = -1; private int vertBlockIncrement = -1; private int horizUnitIncrement = 1; private int vertUnitIncrement = 1; // /**@shapeType AggregationLink * @supplierCardinality 1..* * @label components*/ /*# Layer lnkUnnamed*/ /** * Constructs a Pane. * * @param id the Pane identifier * @param size the size of the Pane in pixels **/ public JPane(String id, Dimension size) { super(); proxy_ = new PaneProxy(this, id, size); setSize(size); // // setup for Low-Level Events // this.enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); setDoubleBuffered(false); // // RepaintManager currentManager = RepaintManager.currentManager(this); // currentManager.setDoubleBufferingEnabled(false); // } /** * Default constructor. The identifier is set to an empty string and * the size is set to a width and height of 50 pixels. A default constructor * is required to work as a component with Visual Cafe. * *
   * import gov.noaa.pmel.sgt.JPane;
   * ...
   * JPane pane;
   * ...
   * pane = new JPane("main graph", new Dimension(400, 500));
   * pane.setLayout(new StackedLayout());
   * ...
   * 
* * @see StackedLayout * **/ public JPane() { this(new String(""), new Dimension(50,50)); } /** * Return the version of SGT. * @since 3.0 */ public static String getVersion() { return PaneProxy.getVersion(); } public void draw(VectorGraphics g, String s) { proxy_.setOpaque(isOpaque()); proxy_.draw(g,s); } public void draw() { } /** * No initialization required. */ public void init() { } public void draw(VectorGraphics g) { proxy_.setOpaque(isOpaque()); proxy_.draw(g); } public void draw(VectorGraphics g, int width, int height) { proxy_.setOpaque(isOpaque()); proxy_.draw(g, width, height); } public boolean isPrinter() { return proxy_.isPrinter(); } /** * Internal method to access jdk1.1 or Java2D line drawing. */ public static StrokeDrawer getStrokeDrawer() { return PaneProxy.strokeDrawer; } public Dimension getPageSize() { return proxy_.getPageSize(); } /** * Override default painting by swing. */ public void paintComponent(Graphics g) { super.paintComponent(g); proxy_.paint(g); } /** * Adds the specified component to the end of the Pane. * * @param comp the component to be added * @return component argument */ public Component add(Component comp) { if(comp instanceof LayerControl) { ((LayerControl)comp).setPane(this); } return super.add(comp); } /** * Adds the specified component to the Pane at the * given position. * * @param comp the component to be added * @param index the position at which to insert the component, or -1 to insert the component at the end. * @return component argument */ public Component add(Component comp, int index) { if(comp instanceof LayerControl) { ((LayerControl)comp).setPane(this); } return super.add(comp, index); } /** * Adds the specified component to the end of this Pane. * Also notifies the layout manager to add the component to this * Pane's layout using the specified constraints object. * * @param comp the component to be added * @param constraints an object expressing layout constraints for this component */ public void add(Component comp, Object constraints) { super.add(comp, constraints); if(comp instanceof LayerControl) { ((LayerControl)comp).setPane(this); } } /** * Adds the specified component to the end of this Pane * at the specified index. * Also notifies the layout manager to add the component to this * Pane's layout using the specified constraints object. * * @param comp the component to be added * @param constraints an object expressing layout constraints for this component * @param index the position in the Pane's list at which to insert the component -1 means insert at the end. */ public void add(Component comp, Object constraints, int index) { super.add(comp, constraints, index); if(comp instanceof LayerControl) { ((LayerControl)comp).setPane(this); } } /** * Adds the specified component to this Pane. It * is strongly advised to use add(Component, Object), in place * of this method. */ public Component add(String name, Component comp) { if(comp instanceof LayerControl) { ((LayerControl)comp).setPane(this); } return super.add(name, comp); } public String getId() { return proxy_.getId(); } public void setId(String id) { proxy_.setId(id); } public void setPageAlign(int vert,int horz) { proxy_.setPageAlign(vert, horz); } public void setPageVAlign(int vert) { proxy_.setPageVAlign(vert); } public void setPageHAlign(int horz) { proxy_.setPageHAlign(horz); } public int getPageVAlign() { return proxy_.getPageVAlign(); } public int getPageHAlign() { return proxy_.getPageHAlign(); } public void setPageOrigin(Point p) { proxy_.setPageOrigin(p); } public Point getPageOrigin() { return proxy_.getPageOrigin(); } /** * Set the size. */ public void setSize(Dimension d) { super.setSize(d); if(Debug.DEBUG) System.out.println("JPane: setSize()"); proxy_.setSize(d); } public Layer getFirstLayer() { return proxy_.getFirstLayer(); } public Layer getLayer(String id) throws LayerNotFoundException { return proxy_.getLayer(id); } public Layer getLayerFromDataId(String id) throws LayerNotFoundException { return proxy_.getLayerFromDataId(id); } /** * Move the Layer up in the stack. * The order of the layers determine when they * are drawn. Moving the Layer up causes the * Layer to be drawn later and over earlier * layers. * * @param lyr Layer object. * @exception LayerNotFoundException The specified Layer was not found in the list. * @see Layer **/ public void moveLayerUp(Layer lyr) throws LayerNotFoundException { throw new MethodNotImplementedError(); } /** * Move the Layer up in the stack. * The order of the layers determine when they * are drawn. Moving the Layer up causes the * Layer to be drawn later and over earlier * layers. * * @param id identifier. * @exception LayerNotFoundException The specified Layer was not found in the list. * @see Layer **/ public void moveLayerUp(String id) throws LayerNotFoundException { throw new MethodNotImplementedError(); } /** * Move the Layer down in the stack. * The order of the layers determine when they * are drawn. Moving the Layer down causes the * Layer to be drawn earlier. * * @param lyr Layer object. * @exception LayerNotFoundException The specified Layer was not found in the list. * @see Layer **/ public void moveLayerDown(Layer lyr) throws LayerNotFoundException { throw new MethodNotImplementedError(); } /** * Move the Layer down in the stack. * The order of the layers determine when they * are drawn. Moving the Layer down causes the * Layer to be drawn earlier. * * @param id identifier * @exception LayerNotFoundException The specified Layer was not found in the list. * @see Layer **/ public void moveLayerDown(String id) throws LayerNotFoundException { throw new MethodNotImplementedError(); } public Object getSelectedObject() { return proxy_.getSelectedObject(); } public void setSelectedObject(Object obj) { proxy_.setSelectedObject(obj); } /** * Overrides the default event methods. **/ public void processMouseEvent(MouseEvent event) { if(!proxy_.processMouseEvent(event)) super.processMouseEvent(event); } /** * Used internally by sgtplot. */ public void processMouseMotionEvent(MouseEvent event) { if(!proxy_.processMouseMotionEvent(event)) super.processMouseMotionEvent(event); } /** * Get the current zoom bounding box. */ public Rectangle getZoomBounds() { return proxy_.getZoomBounds(); } /** * @since 3.0 */ public Point getZoomStart() { return proxy_.getZoomStart(); } public Object getObjectAt(int x, int y) { return proxy_.getObjectAt(x,y); } /** * @since 3.0 */ public Object[] getObjectsAt(int x, int y) { return proxy_.getObjectsAt(x,y); } /** * @since 3.0 */ public Object[] getObjectsAt(Point pt) { return proxy_.getObjectsAt(pt.x, pt.y); } public Component getComponent() { return (Component)this; } public Dimension getMaximumSize() { return proxy_.getMaximumSize(); } public Dimension getMinimumSize() { return proxy_.getMinimumSize(); } public Dimension getPreferredSize() { return proxy_.getPreferredSize(); } /** * Get a String representatinof the * Pane. * * @return String representation */ public String toString() { return proxy_.toString(); } public void setBatch(boolean batch, String msg) { proxy_.setBatch(batch, msg); } public void setBatch(boolean batch) { proxy_.setBatch(batch, ""); } public boolean isBatch() { return proxy_.isBatch(); } public void setModified(boolean mod, String mess) { proxy_.setModified(mod, mess); } public boolean isModified() { return proxy_.isModified(); } /** * @since 3.0 */ public void setMouseEventsEnabled(boolean enable) { proxy_.setMouseEventsEnabled(enable); } /** * @since 3.0 */ public boolean isMouseEventsEnabled() { return proxy_.isMouseEventsEnabled(); } /** * Set the horizontal and vertical block increments. */ public void setScrollableBlockIncrement(int horiz, int vert) { horizBlockIncrement = horiz; vertBlockIncrement = vert; } public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { if(orientation == SwingConstants.HORIZONTAL) { if(horizBlockIncrement <= 0) { return getVisibleRect().width; } else { return horizBlockIncrement; } } else { if(vertBlockIncrement <= 0) { return getVisibleRect().height; } else { return vertBlockIncrement; } } } /** * Set the horizontal and vertical unit increments. */ public void setScrollableUnitIncrement(int horiz, int vert) { horizUnitIncrement = horiz; vertUnitIncrement = vert; } public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { if(orientation == SwingConstants.HORIZONTAL) { if(horizUnitIncrement <= 0) { return 1; } else { return horizUnitIncrement; } } else { if(vertUnitIncrement <= 0) { return 1; } else { return vertUnitIncrement; } } } public Dimension getPreferredScrollableViewportSize() { return getSize(); } public boolean getScrollableTracksViewportHeight() { return false; } public boolean getScrollableTracksViewportWidth() { return false; } public int print(Graphics g, PageFormat pf, int pageIndex) { VectorGraphics vg = VectorGraphics.create(g); if(pageIndex > 0) { return NO_SUCH_PAGE; } else { drawPage(vg, pf); return PAGE_EXISTS; } } public void setPageScaleMode(int mode) { proxy_.setPageScaleMode(mode); } public int getPageScaleMode() { return proxy_.getPageScaleMode(); } public void drawPage(VectorGraphics g, PageFormat pf, boolean scale) { if(scale) { drawPage(g, pf); } else { proxy_.drawPage(g, pf.getImageableWidth(), pf.getImageableHeight()); } } /** * Used by internally by sgtplot. */ protected void drawPage(VectorGraphics g, PageFormat pf) { Dimension d = getSize(); Point pageOrigin = null; pageOrigin = proxy_.getPageOrigin(); if(pageOrigin == null) pageOrigin = new Point(0,0); VectorGraphics g2 = VectorGraphics.create(g); double scale = 1.0; double dx = pf.getImageableX(); double dy = pf.getImageableY(); int scaleMode = proxy_.getPageScaleMode(); if(scaleMode == AbstractPane.TO_FIT || scaleMode == AbstractPane.SHRINK_TO_FIT) { double yf = pf.getImageableHeight()/d.getHeight(); double xf = pf.getImageableWidth()/d.getWidth(); if(xf < yf) { scale = xf; } else if(xf > yf) { scale = yf; } if(scaleMode == AbstractPane.SHRINK_TO_FIT && scale > 1.0) scale = 1.0; } switch(proxy_.getPageHAlign()) { default: case AbstractPane.CENTER: dx += (pf.getImageableWidth() - scale*d.getWidth())/2.0; break; case AbstractPane.RIGHT: dx += pf.getImageableWidth() - scale*d.getWidth(); break; case AbstractPane.LEFT: // do nothing break; case AbstractPane.SPECIFIED_LOCATION: dx += pageOrigin.x; break; } switch(proxy_.getPageVAlign()) { default: case AbstractPane.TOP: // do nothing break; case AbstractPane.BOTTOM: dy += pf.getImageableHeight() - scale*d.getHeight(); break; case AbstractPane.MIDDLE: dy += (pf.getImageableHeight() - scale*d.getHeight())/2.0; break; case AbstractPane.SPECIFIED_LOCATION: dy += pageOrigin.y; break; } g.clipRect(-1000, -1000, 2000, 2000); // g.clipRect(Integer.MIN_VALUE, Integer.MIN_VALUE, // Integer.MAX_VALUE, Integer.MAX_VALUE); g2.translate(dx, dy); g2.scale(scale, scale); proxy_.drawPage(g, pf.getImageableWidth(), pf.getImageableHeight()); } /* * Pane PropertyChange methods */ public void addPropertyChangeListener(PropertyChangeListener l) { proxy_.addPropertyChangeListener(l); } public void removePropertyChangeListener(PropertyChangeListener l) { proxy_.removePropertyChangeListener(l); } @Override public void draw(Graphics g) { // TODO Auto-generated method stub } @Override public void draw(Graphics g, int width, int height) { // TODO Auto-generated method stub } }

Ads help maintain this website.