/* This file is part of the source code for 3D-XplorMath-J, Version 1.0 (January 2008). * Copyright (c) 2008 The 3D-XplorMath Consortium (http://3d-xplormath.org). * This source code is released under a BSD License, which allows redistribution * in source and binary form, with or without modification, provided copyright * and license information are included, and with no warranty or guarantee of * any kind. For details, see http://3d-xplormath.org/j/source/BSDLicense.txt */ package vmm.core; import java.awt.Graphics2D; import java.io.IOException; import java.util.ArrayList; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * Decorations are extra visual components that can be added to an Exhibit, such as * a set of axes or a solution curve of an ODE. Decorations can be added either to * Views or directly to Exhibits -- a decoration that is added to a View is visible * only in that View. A decoration that is added to an Exhibit is visible in all * Views of that Exhibit. *
When a Decoration is added to an Exhibit or View, that object will listen for * ChangeEvents from the Decoration. These events will produce the necessary redrawing. * The listening is set up automatically when the Decoration is added. *
This is an abstract class, even though it has no abstract methods. Subclasses
* will probably override the doDraw method and possibly the computeDrawData method.
* However, subclasses might also provide some other method for drawing the decoration.
*
Note that to work correctly with the XML save/restore facility defined in {@link vmm.core.SaveAndRestore},
* a subclass of Decoration must have a parameterless constructor, and it must be an independent class or
* a public nested class.
* However, decorations are not saved by default, so this is not a consideration for all subclasses.
*/
abstract public class Decoration {
private ArrayList The default value for the layer is 1, which puts it
* on top of the Exhibit.
*/
public int getLayer() {
return layer;
}
/**
* Set the layer in which this decoration is drawn. The default layer is 1.
* @see #getLayer()
*/
public void setLayer(int layer) {
if (this.layer != layer) {
this.layer = layer;
fireDecorationChangeEvent();
}
}
/**
* Causes this decoration to be recomputed and redrawn.
*/
public void forceRedraw() {
decorationNeedsRedraw = true;
fireDecorationChangeEvent();
}
/**
* This method is called by the In general, a Decoration should check its The method in this top-level Decoration class does nothing.
* When a subclass overrides this method, it should ordinarily start by calling
* super.addExtraXML(containingDocument,decorationElement) to make sure that information from the superclass
* is saved.
* @param containingDocument The overall XML document that contains the decoration Element that is being created.
* This parameter is necessary because it is needed to create any nested sub-elements that are to be added
* to the decoration element.
* @param decorationElement The XML element that is being constructed. This element already exists; the
* purpose of this method to add any extra information that would be needed to reconstruct this decoration
* object from the XML represenation.
* @see #readExtraXML(Element)
*/
public void addExtraXML(Document containingDocument, Element decorationElement) {
}
/**
* This method is called when this decoration is being reconstructed from an XML representation by the
* {@link SaveAndRestore} class. This method is responsible
* for retrieving any data that was written by {@link #addExtraXML(Document, Element)},
* except that properties written with {@link SaveAndRestore#addProperty(Object, String, Document, Element)}
* are retrieved automatically.
* The method in this top-level Decoration class does nothing.
* In general, when a subclass overrides this method, it should be sure to call
* super.readExtraXML(decorationInfo).
* @param decoratinInfo The <decoration> element from the XML file that contains the information about this
* decoration. Some methods from the {@link SaveAndRestore} class might be useful for getting the data.
* @throws IOException If an error is found, an exception of type IOException should be thrown.
* This will abort the whole processing of the XML file.
* @see #addExtraXML(Document, Element)
*/
public void readExtraXML(Element decoratinInfo) throws IOException {
}
}
fireDecorationChangeEvent
* method is called. It can be used in the computeDrawData method by Decoration
* subclasses that cache data, to decide whether or not to recompute that data.
*/
protected boolean decorationNeedsRedraw = true;
/**
* Return the layer number for this decoration. The layer number can be a
* positive or negative integer or zero. Decorations with smaller (or more negative)
* layer numbers are drawn first. The Exhibit itself is in layer zero, so decorations
* with negaitve layer numbers are drawn behind the exhibit and decorations with
* positive layer numbers will overlay the exhibit. For decorations in the same
* layer, the default behavior for 2D exhibits, as defined in the Exhibit class, is to draw
* the decorations in the same layer in the order in which they were added,
* except that decorations added directly to the Exhibit are drawn before those that
* were added to the View. For 3D exhibits, objects in the same layer should be treated
* as one object for the purpose of hidden surface removal. (Note: Currently, this is not done.
* Decorations are simply drawn in order by layer, even for 3D exhibits.)
* render method in the Exhibit class before it calls
* this Decoration's doDraw method, in order to give the Decoration
* a chance to recalculate any cached data that it needs in order to draw itself.
* (Note that subclasses of the View and Exhibit class are not necessarily required to
* follow this pattern.) Not all Decorations will need to "cache"
* computed data in this way. Decorations that do not cache data do not have to override this method.
* The method in this top-level exhibit class does nothing.
* decorationNeedsRedraw variable and
* also check the exhibitNeedsRedraw parameter. It should recompute cached
* data if either of these is true. A decoration might also need to compute data if
* the Transform has changed, if it has cached any data that depends on the Transform.
* @see Exhibit#render(Graphics2D, View, Transform, ArrayList)
* @see #doDraw(Graphics2D, View, Transform)
* @param view The View that is drawing the Exhibit; this object contains other
* information that might be of use, such as the Display where the Exhibit is drawn
* and the the Exhibit that is being drawn.
* @param exhibitNeedsRedraw This parameter is set to "true" when the Exhibit changes.
* If it is true, then presumably the appearance of the Exhibit has
* changed, so any cached data for this decoration should probably be recomputed.
* @param previousTransform The Transform object that was used the last time the Exhibit was
* drawn. This can be null if the Exhibit is being drawn for the first time.
* @param newTransform The Transform object that is being used for this drawing of the Exhibit.
* Transform objects contain data about the window in the xy-plane where the Exhibit is
* being drawn and about the pixel coordinates on the drawing area.
* The two Transform objects are provided just in case any cached data depends on the xy-window
* or on the pixel coordinates.
*/
public void computeDrawData(View view, boolean exhibitNeedsRedraw, Transform previousTransform, Transform newTransform) {
}
/**
* This method is called by the render method of the Exhbit class to draw the Decoration.
* The computeDrawData method is called by render before it calls this method, so any cached
* data should be valid by the time this method is called. (Note that subclasses of View and
* Exhibit are not necessarily required to follow this pattern.)
* The method in this class does nothing. Subclasses will ordinarily override this method to draw the Decoration.
* @see Exhibit#render(Graphics2D, View, Transform, ArrayList)
* @see #computeDrawData(View, boolean, Transform, Transform)
* @param g The graphics context where the Exhibit and its decorations are being drawn.
* @param view The View that is drawing the Exhibit; this object contains other
* information that might be of use, such as the Display, if any, associated with
* the View, and the the actual Exhibit that is being drawn.
* @param transform Contains information about the rectangular area in the
* xy-plane that is being drawn and about the rectangle of pixels in the graphics
* context where it is drawn. Note that at least for the top-level View class,
* transform.getX() and transform.getY() can be assumed to be zero.
*/
public void doDraw(Graphics2D g, View view, Transform transform) {
}
//----------------- support for ChangeEvents --------------------------------------
/**
* Change events are sent when the decoration needs to be redrawn. This is set up
* automatically in the VMM core. It should not
* be necessary for ordinary programmers to call this method.
*/
synchronized public void addChangeListener(ChangeListener listener) {
if (listener == null)
return;
if (changeListeners == null)
changeListeners = new ArrayList