/*
* $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.