jpl.mipl.jade
Class JadeDisplay

java.lang.Object
  extended by java.awt.Component
      extended by java.awt.Container
          extended by javax.swing.JComponent
              extended by javax.swing.JPanel
                  extended by jpl.mipl.jade.JadeDisplay
All Implemented Interfaces:
HierarchyListener, ImageObserver, MenuContainer, PropertyChangeListener, Serializable, EventListener, Accessible, TileComputationListener, BackgroundPainter

public class JadeDisplay
extends JPanel
implements TileComputationListener, BackgroundPainter, PropertyChangeListener, HierarchyListener

The primary image display component for JADE. This class supports asynchronous computation of tiles for display, allowing the user to scroll and otherwise manipulate the image while it is being computed and painted.

JAI 1.1 or later is required to support the asynchronous features. If fed an image that is not a JAI image, it will be wrapped (via PlanarImage.wrapRenderedImage()) to make it one.

This is a Swing lightweight component. It is intended to display the entire image; for scrolling, put it in a JScrollPane.

Repaint Policy

The caller can control when the tiles are painted via the repaintPolicy property. The choices are:

Image Origin

The imageOrigin property defines the image coordinate that is shown in the upper left corner of the component. Any part of the image above and to the left of that coordinate will not be displayed. Note that the logical location of the image is taken into account, so if the image starts at (-100,-100) (see RenderedImage.getMinX/Y()), then the imageOrigin would also need to be set to (-100,-100) in order to display the whole image. This imageOrigin is a hard cropping and should not be confused with a Pan value, which is managed entirely by the JScrollPane (or other higher-level component). If imageOrigin is set to null, then the origin will automatically be set to the image's minX and minY values, and will be reset whenever those change.

Double Buffering

By default, Swing double-buffers its components. This reduces flicker for most components. However, the entire point of this image display is to display things deferred! This creates flicker, intentionally (you see the background before the image gets painted). This completely defeats the purpose of double-buffering. Since double-buffering actually creates extra (unnecessary, here) work, by default JadeDisplay turns it off.

With one exception, the component will work fine either way, with double buffering on or off. However, if you use paintNoErase() with tiles painted using REPAINT_DEFERRED (or REPAINT_CACHE when the tiles aren't in the cache), double buffering will create problems with garbage flashing on the screen. The final image will look fine after all repaints are done, but the purpose of paintNoErase is to not erase the area being drawn, which interacts with double buffering in a bad way.

Although Swing has a setDoubleBuffered call, it is less useful than you might think. In order to disable double buffering, you have to turn it off on every component in the hierarchy up to the root. This can have the side-effect of turning off double buffering for other components in the same window (which may benefit from it being on). It turns out that JPanel turns double-buffering on by default, so most subtrees beyond the display component will be double-buffered. However, it may be necessary to manually enable double buffering for certain components. Only the top-level component of a subtree needs to have double-buffering enabled, although it doesn't hurt to enable children.

The disableDoubleBuffering property controls whether or not this disabling happens. Note: this property does not directly enable or disable double buffering. It simply enables or disables the process by which JadeDisplay turns off double buffering on all of its ancestor components. If true (the default), then all ancestors have double buffering turned off whenever a HierarchyEvent is received indicating a change in parents. If false, nothing is done on receiving the event (JadeDisplay never explicitly turns on double buffering, anywhere). Practically speaking, this means that you should set this flag only in the constructor, or at least before you add the component into any container. Setting the flag to false means that any manual settings of double buffering you might make are honored; JadeDisplay will not change any of them.

Parallelism

Because of the use of background processing, the Parallelism setting in the TileScheduler attached to the image can make quite a difference. This component does not manage the parallelism however; this is up to the application (e.g. via JAI.getDefaultInstance().getTileScheduler().setParallelism()).

RenderingChangeEvent response

JadeDisplay monitors RenderingChangeEvents (RCEs) generated by the image, and automatically repaints portions of the screen affected by that change. So no manual painting is necessary when e.g. JAI operator parameters are modified.

Exactly how that repaint happens, though, is controllable via the RCE mode. The values are:

Note that anything that causes the geometry of the image to change (size, tiling, data type, etc.) will cause repaint() to be used, regardless of the mode setting. This is often the case for JAI operators like Rotate, which change the output size with rotation changes. Also, despite the mode setting, other forms of repainting (scrolls, exposes, etc.) will still happen as usual. This mode affects repaints only in response to a RenderingChangeEvent.

Because RenderingChangeEvent delivery is synchronous, it is possible for an application to set the RCE mode before making an update, make the update which generates the RCE (via RenderedOp.setParameterBlock() or similar), then re-set the RCE mode afterwards. Thus the given mode applies only to one operation. This could be very useful for cases where it is known a priori that the display flashing will be undesirable when certain types of image updates are performed.

Miscellaneous

This component owes a lot of heritage to the XvicImage X-windows/Motif-based image display widget used in xvd. If not actual code, at least the concepts.

This may or may not still be true (copied from the JAI ImageCanvas source): Due to the limitations of BufferedImage, only TYPE_BYTE of band 1, 2, 3, 4, and TYPE_USHORT of band 1, 2, 3 images can be displayed using this component.

The component does not work terribly well if the tile sizes are too small, due to the overhead of tile processing. This is especially apparent with certain TIFF files, where tiles are a single line. The user should reformat the image into larger tiles in that case.

TBD: It is unknown if this component will work for printing. It should, in immediate mode, but this has not been tested.

TBD: Should property events be generated when properties are changed? None have been needed to date.

Author:
Bob Deen, JPL
See Also:
Serialized Form

Nested Class Summary
 
Nested classes/interfaces inherited from class javax.swing.JPanel
JPanel.AccessibleJPanel
 
Nested classes/interfaces inherited from class javax.swing.JComponent
JComponent.AccessibleJComponent
 
Nested classes/interfaces inherited from class java.awt.Container
Container.AccessibleAWTContainer
 
Nested classes/interfaces inherited from class java.awt.Component
Component.AccessibleAWTComponent, Component.BltBufferStrategy, Component.FlipBufferStrategy
 
Field Summary
protected  BackgroundPainter _backgroundPainter
          Background painter
protected  ArrayList _batchOverlayPainters
           
protected  ColorModel _colorModel
          The image's ColorModel or one we supply.
protected  RectRegion _damageList
          The damage list
protected  boolean _disableDoubleBuffering
          Whether or not to ensure double buffering is off.
protected  boolean _eraseBeforeRepaint
          Whether or not to erase before repainting.
protected  PlanarImage _im
          The source PlanarImage.
protected  int _imageHeight
          The image size
protected  Point _imageOrigin
          The pixel to display in the UL corner of the component, or null.
protected  int _imageScreenHeight
          The w/h of the image in screen coordinates.
protected  int _imageScreenWidth
          The w/h of the image in screen coordinates.
protected  int _imageWidth
          The image size
protected  ArrayList _immediateOverlayPainters
          Overlay painters
protected  Insets _insets
          Caches insets
protected  Rectangle _insets_clip
          Insets as a clipping rectangle
protected  int _maxTileX
          The image's min/max X and Y tile indices.
protected  int _maxTileY
          The image's min/max X and Y tile indices.
protected  int _minTileX
          The image's min/max X and Y tile indices.
protected  int _minTileY
          The image's min/max X and Y tile indices.
protected  int _minX
          The minimum X/Y coordinate of the image
protected  int _minY
          The minimum X/Y coordinate of the image
protected  int _numTileX
          The number of tiles in the X/Y directions
protected  int _numTileY
          The number of tiles in the X/Y directions
protected  int _RCE_mode
          RenderingChangeEvent mode.
protected  int _repaintPolicy
          Repaint policy.
protected  int _scr2imgX
          Conversion between screen and image coordinates (img = scr + scr2img)
protected  int _scr2imgY
          Conversion between screen and image coordinates (img = scr + scr2img)
protected  int _tileGridXOffset
          The image's tile grid X/Y offset.
protected  int _tileGridYOffset
          The image's tile grid X/Y offset.
protected  int _tileHeight
          The image's tile width/height.
protected  TilePainter[][] _tilePainters
          The list of TilePainter objects.
protected  int _tileWidth
          The image's tile width/height.
static int RCE_FULL_NOERASE
          When a RenderingChangeEvent is received, use paintNoErase().
static int RCE_PARTIAL_NOERASE
          When a RenderingChangeEvent is received and it is a partial-image update, use paintNoErase().
static int RCE_REPAINT
          When a RenderingChangeEvent is received, use repaint().
static int REPAINT_CACHE
          If the tile is in the cache, same as REPAINT_IMMEDIATE.
static int REPAINT_DEFERRED
          Defer tile computation to asynchronous threads in all possible cases.
static int REPAINT_IMMEDIATE
          Repaint immediately in all cases.
 
Fields inherited from class javax.swing.JComponent
accessibleContext, listenerList, TOOL_TIP_TEXT_KEY, ui, UNDEFINED_CONDITION, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, WHEN_FOCUSED, WHEN_IN_FOCUSED_WINDOW
 
Fields inherited from class java.awt.Component
BOTTOM_ALIGNMENT, CENTER_ALIGNMENT, LEFT_ALIGNMENT, RIGHT_ALIGNMENT, TOP_ALIGNMENT
 
Fields inherited from interface java.awt.image.ImageObserver
ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, WIDTH
 
Constructor Summary
JadeDisplay(RenderedImage im)
          Constructs a JadeDisplay to display a RenderedImage with default origin (null), repaint policy (REPAINT_CACHE), and double buffer disable flag (false).
JadeDisplay(RenderedImage im, Point imageOrigin, int repaintPolicy)
          Constructs a JadeDisplay to display a RenderedImage with the given image origin and repaint policy.
JadeDisplay(RenderedImage im, Point imageOrigin, int repaintPolicy, boolean disableDoubleBuffering)
          Constructs a JadeDisplay to display a RenderedImage with the given image origin, repaint policy, and double buffer disable flag.
 
Method Summary
protected  void abortQueuedTiles()
          Abort all queued computations.
protected  Rectangle addDamage(Rectangle rect)
          Adds a Rectangle to the damage list.
 void addOverlayPainter(int index, OverlayPainter painter, boolean isImmediate)
          Adds an OverlayPainter to this component at the given position in the list.
 void addOverlayPainter(OverlayPainter painter)
          Adds an immediate-mode OverlayPainter to the end of the list (i.e.
 void addOverlayPainterNRP(int index, OverlayPainter painter, boolean isImmediate)
          Adds an OverlayPainter to this component.
static JScrollPane createDisplay(RenderedImage image, int w, int h, boolean mouseScroller)
          Factory function that creates and returns a JScrollPane which contains a JadeDisplay.
 Point getCurrentImageOrigin()
          Returns a copy of the current image origin value.
 boolean getDisableDoubleBuffering()
          Gets the current state of the double-buffer disable flag.
 Graphics2D getGraphics(Rectangle bounds, Graphics g)
          Returns a Graphics2D object that can be used to paint a tile in the given rectangular bounds.
 RenderedImage getImage()
          Returns the image currently being displayed.
 Point getImageOrigin()
          Returns a copy of the image origin value.
 int getRCEmode()
          Gets the RenderingChangeEvent repaint mode.
 int getRepaintPolicy()
          Gets the repaint policy.
protected  void handleResize()
          Handles the component being resized by resetting all size-dependent member variables.
 void hierarchyChanged(HierarchyEvent e)
          We have to monitor hierarchy events for two reasons: If any parent changed, and we're disabling double buffering, then we must disable it all the way to the root component.
 void paintBackground(Graphics g, int x, int y, int width, int height, boolean isNoErase, boolean isInsideImage, boolean isDeferredTile)
          Default background painter method.
 void paintComponent(Graphics g)
          Called by Swing to repaint the component.
 void paintNoErase(int x, int y, int w, int h)
          Paints a portion of the display without erasing it first.
 void paintNoErase(Rectangle r)
          Exactly like paintNoErase(x,y,w,h) except that the area to be repainted is a Rectangle.
 void paintOneOverlay(OverlayPainter painter, Rectangle r)
          Special-purpose routine that repaints one overlay object only, without repainting the background image or other overlays.
 void propertyChange(PropertyChangeEvent evt)
          Responds to a PropertyChangeEvent from the image.
 void removeOverlayPainter(OverlayPainter painter)
          Removes the specified OverlayPainter from this component.
 void removeOverlayPainterNRP(OverlayPainter painter)
          Removes the specified OverlayPainter from this component.
 void repaintOverlay(Graphics g)
          Called by TilePainter to refresh an area of the overlay.
 BackgroundPainter setBackgroundPainter(BackgroundPainter bgpaint)
          Sets the given object to be the BackgroundPainter for this component.
 void setDisableDoubleBuffering(boolean flag)
          Sets the current state of the double-buffer disable flag.
 void setImage(RenderedImage im)
          Changes the source image to a new RenderedImage.
 void setImage(RenderedImage im, Point origin)
          Changes the source image to a new RenderedImage while simultaneously changing the image origin.
protected  void setImageInternal(RenderedImage im)
          Sets up a new image, registering and unregistering Listener's and updating any derived values.
 void setImageOrigin(Point origin)
          Changes the imageOrigin property.
 void setRCEmode(int mode)
          Sets the RenderingChangeEvent repaint mode.
 void setRepaintPolicy(int policy)
          Sets the repaint policy.
protected  void sizeComponent()
          Sizes the component based on the image size.
 void subtractDamage(Rectangle rect)
          Subtracts a Rectangle from the damage list.
protected  Rectangle subtractDamage2(Rectangle rect)
          Subtracts a Rectangle from the damage list.
 void tileCancelled(Object eventSource, TileRequest[] requests, PlanarImage image, int tileX, int tileY)
          TileComputationListener functions.
 void tileComputationFailure(Object eventSource, TileRequest[] requests, PlanarImage image, int tileX, int tileY, Throwable situation)
          TileComputationListener functions.
 void tileComputed(Object eventSource, TileRequest[] requests, PlanarImage image, int tileX, int tileY, Raster tile)
          TileComputationListener functions.
 
Methods inherited from class javax.swing.JPanel
getAccessibleContext, getUI, getUIClassID, paramString, setUI, updateUI
 
Methods inherited from class javax.swing.JComponent
addAncestorListener, addNotify, addVetoableChangeListener, computeVisibleRect, contains, createToolTip, disable, enable, firePropertyChange, firePropertyChange, firePropertyChange, fireVetoableChange, getActionForKeyStroke, getActionMap, getAlignmentX, getAlignmentY, getAncestorListeners, getAutoscrolls, getBorder, getBounds, getClientProperty, getComponentGraphics, getComponentPopupMenu, getConditionForKeyStroke, getDebugGraphicsOptions, getDefaultLocale, getFontMetrics, getGraphics, getHeight, getInheritsPopupMenu, getInputMap, getInputMap, getInputVerifier, getInsets, getInsets, getListeners, getLocation, getMaximumSize, getMinimumSize, getNextFocusableComponent, getPopupLocation, getPreferredSize, getRegisteredKeyStrokes, getRootPane, getSize, getToolTipLocation, getToolTipText, getToolTipText, getTopLevelAncestor, getTransferHandler, getVerifyInputWhenFocusTarget, getVetoableChangeListeners, getVisibleRect, getWidth, getX, getY, grabFocus, isDoubleBuffered, isLightweightComponent, isManagingFocus, isOpaque, isOptimizedDrawingEnabled, isPaintingTile, isRequestFocusEnabled, isValidateRoot, paint, paintBorder, paintChildren, paintImmediately, paintImmediately, print, printAll, printBorder, printChildren, printComponent, processComponentKeyEvent, processKeyBinding, processKeyEvent, processMouseEvent, processMouseMotionEvent, putClientProperty, registerKeyboardAction, registerKeyboardAction, removeAncestorListener, removeNotify, removeVetoableChangeListener, repaint, repaint, requestDefaultFocus, requestFocus, requestFocus, requestFocusInWindow, requestFocusInWindow, resetKeyboardActions, reshape, revalidate, scrollRectToVisible, setActionMap, setAlignmentX, setAlignmentY, setAutoscrolls, setBackground, setBorder, setComponentPopupMenu, setDebugGraphicsOptions, setDefaultLocale, setDoubleBuffered, setEnabled, setFocusTraversalKeys, setFont, setForeground, setInheritsPopupMenu, setInputMap, setInputVerifier, setMaximumSize, setMinimumSize, setNextFocusableComponent, setOpaque, setPreferredSize, setRequestFocusEnabled, setToolTipText, setTransferHandler, setUI, setVerifyInputWhenFocusTarget, setVisible, unregisterKeyboardAction, update
 
Methods inherited from class java.awt.Container
add, add, add, add, add, addContainerListener, addImpl, addPropertyChangeListener, addPropertyChangeListener, applyComponentOrientation, areFocusTraversalKeysSet, countComponents, deliverEvent, doLayout, findComponentAt, findComponentAt, getComponent, getComponentAt, getComponentAt, getComponentCount, getComponents, getComponentZOrder, getContainerListeners, getFocusTraversalKeys, getFocusTraversalPolicy, getLayout, getMousePosition, insets, invalidate, isAncestorOf, isFocusCycleRoot, isFocusCycleRoot, isFocusTraversalPolicyProvider, isFocusTraversalPolicySet, layout, list, list, locate, minimumSize, paintComponents, preferredSize, printComponents, processContainerEvent, processEvent, remove, remove, removeAll, removeContainerListener, setComponentZOrder, setFocusCycleRoot, setFocusTraversalPolicy, setFocusTraversalPolicyProvider, setLayout, transferFocusBackward, transferFocusDownCycle, validate, validateTree
 
Methods inherited from class java.awt.Component
action, add, addComponentListener, addFocusListener, addHierarchyBoundsListener, addHierarchyListener, addInputMethodListener, addKeyListener, addMouseListener, addMouseMotionListener, addMouseWheelListener, bounds, checkImage, checkImage, coalesceEvents, contains, createImage, createImage, createVolatileImage, createVolatileImage, disableEvents, dispatchEvent, enable, enableEvents, enableInputMethods, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, getBackground, getBounds, getColorModel, getComponentListeners, getComponentOrientation, getCursor, getDropTarget, getFocusCycleRootAncestor, getFocusListeners, getFocusTraversalKeysEnabled, getFont, getForeground, getGraphicsConfiguration, getHierarchyBoundsListeners, getHierarchyListeners, getIgnoreRepaint, getInputContext, getInputMethodListeners, getInputMethodRequests, getKeyListeners, getLocale, getLocation, getLocationOnScreen, getMouseListeners, getMouseMotionListeners, getMousePosition, getMouseWheelListeners, getName, getParent, getPeer, getPropertyChangeListeners, getPropertyChangeListeners, getSize, getToolkit, getTreeLock, gotFocus, handleEvent, hasFocus, hide, imageUpdate, inside, isBackgroundSet, isCursorSet, isDisplayable, isEnabled, isFocusable, isFocusOwner, isFocusTraversable, isFontSet, isForegroundSet, isLightweight, isMaximumSizeSet, isMinimumSizeSet, isPreferredSizeSet, isShowing, isValid, isVisible, keyDown, keyUp, list, list, list, location, lostFocus, mouseDown, mouseDrag, mouseEnter, mouseExit, mouseMove, mouseUp, move, nextFocus, paintAll, postEvent, prepareImage, prepareImage, processComponentEvent, processFocusEvent, processHierarchyBoundsEvent, processHierarchyEvent, processInputMethodEvent, processMouseWheelEvent, remove, removeComponentListener, removeFocusListener, removeHierarchyBoundsListener, removeHierarchyListener, removeInputMethodListener, removeKeyListener, removeMouseListener, removeMouseMotionListener, removeMouseWheelListener, removePropertyChangeListener, removePropertyChangeListener, repaint, repaint, repaint, resize, resize, setBounds, setBounds, setComponentOrientation, setCursor, setDropTarget, setFocusable, setFocusTraversalKeysEnabled, setIgnoreRepaint, setLocale, setLocation, setLocation, setName, setSize, setSize, show, show, size, toString, transferFocus, transferFocusUpCycle
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

_im

protected PlanarImage _im
The source PlanarImage.


_tilePainters

protected TilePainter[][] _tilePainters
The list of TilePainter objects. Dimensions are [x][y].


_colorModel

protected ColorModel _colorModel
The image's ColorModel or one we supply.


_minTileX

protected int _minTileX
The image's min/max X and Y tile indices.


_maxTileX

protected int _maxTileX
The image's min/max X and Y tile indices.


_minTileY

protected int _minTileY
The image's min/max X and Y tile indices.


_maxTileY

protected int _maxTileY
The image's min/max X and Y tile indices.


_tileWidth

protected int _tileWidth
The image's tile width/height.


_tileHeight

protected int _tileHeight
The image's tile width/height.


_tileGridXOffset

protected int _tileGridXOffset
The image's tile grid X/Y offset.


_tileGridYOffset

protected int _tileGridYOffset
The image's tile grid X/Y offset.


_numTileX

protected int _numTileX
The number of tiles in the X/Y directions


_numTileY

protected int _numTileY
The number of tiles in the X/Y directions


_minX

protected int _minX
The minimum X/Y coordinate of the image


_minY

protected int _minY
The minimum X/Y coordinate of the image


_imageWidth

protected int _imageWidth
The image size


_imageHeight

protected int _imageHeight
The image size


_imageScreenWidth

protected int _imageScreenWidth
The w/h of the image in screen coordinates. Used to clip to image bounds if the view is bigger than the actual image.


_imageScreenHeight

protected int _imageScreenHeight
The w/h of the image in screen coordinates. Used to clip to image bounds if the view is bigger than the actual image.


_imageOrigin

protected Point _imageOrigin
The pixel to display in the UL corner of the component, or null.


_repaintPolicy

protected int _repaintPolicy
Repaint policy. Determines whether tiles are computed and displayed immediately, or deferred.


_RCE_mode

protected int _RCE_mode
RenderingChangeEvent mode. Determines how tiles are repainted when the image changes. See the class comments.


_disableDoubleBuffering

protected boolean _disableDoubleBuffering
Whether or not to ensure double buffering is off.


_eraseBeforeRepaint

protected boolean _eraseBeforeRepaint
Whether or not to erase before repainting.

See Also:
paintNoErase(int, int, int, int)

_insets

protected Insets _insets
Caches insets


_insets_clip

protected Rectangle _insets_clip
Insets as a clipping rectangle


_scr2imgX

protected int _scr2imgX
Conversion between screen and image coordinates (img = scr + scr2img)


_scr2imgY

protected int _scr2imgY
Conversion between screen and image coordinates (img = scr + scr2img)


_damageList

protected RectRegion _damageList
The damage list


_immediateOverlayPainters

protected ArrayList _immediateOverlayPainters
Overlay painters


_batchOverlayPainters

protected ArrayList _batchOverlayPainters

_backgroundPainter

protected BackgroundPainter _backgroundPainter
Background painter


REPAINT_IMMEDIATE

public static final int REPAINT_IMMEDIATE
Repaint immediately in all cases. No queueing or background processing.

See Also:
Constant Field Values

REPAINT_DEFERRED

public static final int REPAINT_DEFERRED
Defer tile computation to asynchronous threads in all possible cases. Repaints happen when the tile is computed.

See Also:
Constant Field Values

REPAINT_CACHE

public static final int REPAINT_CACHE
If the tile is in the cache, same as REPAINT_IMMEDIATE. If not, same as REPAINT_DEFERRED.

See Also:
Constant Field Values

RCE_REPAINT

public static final int RCE_REPAINT
When a RenderingChangeEvent is received, use repaint(). This is the default.

See Also:
Constant Field Values

RCE_FULL_NOERASE

public static final int RCE_FULL_NOERASE
When a RenderingChangeEvent is received, use paintNoErase().

See Also:
Constant Field Values

RCE_PARTIAL_NOERASE

public static final int RCE_PARTIAL_NOERASE
When a RenderingChangeEvent is received and it is a partial-image update, use paintNoErase().

See Also:
Constant Field Values
Constructor Detail

JadeDisplay

public JadeDisplay(RenderedImage im,
                   Point imageOrigin,
                   int repaintPolicy,
                   boolean disableDoubleBuffering)
Constructs a JadeDisplay to display a RenderedImage with the given image origin, repaint policy, and double buffer disable flag. A JAI PlanarImage is actually required but if the supplied image is not one, it will be automatically wrapped.

Parameters:
im - the RenderedImage to be displayed.
imageOrigin - a Point specifying the image origin.
repaintPolicy - the repaint policy.
disableDoubleBuffering - whether or not to disable double buffering. See the class comments for a discussion.

JadeDisplay

public JadeDisplay(RenderedImage im,
                   Point imageOrigin,
                   int repaintPolicy)
Constructs a JadeDisplay to display a RenderedImage with the given image origin and repaint policy. A JAI PlanarImage is actually required but if the supplied image is not one, it will be automatically wrapped. Double-buffering will be disabled by default.

Parameters:
im - the RenderedImage to be displayed.
imageOrigin - a Point specifying the image origin.
repaintPolicy - the repaint policy.
See Also:
JadeDisplay(RenderedImage, Point, int, boolean)

JadeDisplay

public JadeDisplay(RenderedImage im)
Constructs a JadeDisplay to display a RenderedImage with default origin (null), repaint policy (REPAINT_CACHE), and double buffer disable flag (false).

See Also:
JadeDisplay(RenderedImage, Point, int, boolean)
Method Detail

createDisplay

public static JScrollPane createDisplay(RenderedImage image,
                                        int w,
                                        int h,
                                        boolean mouseScroller)
Factory function that creates and returns a JScrollPane which contains a JadeDisplay. The returned JScrollPane can be added to a JPanel or whatever else is desired.

Any event handlers, such as mouse trackers, should be added to the JViewport returned by sp.getViewport()) (where sp is the component returned by this method). The JadeDisplay itself can be retrieved via sp.getViewport().getView().

The size of the viewport is set to the h and v parameters. If either is 0, the actual image's dimension is used instead. Be careful doing this with large images! Also, the process of determining the image's dimension may cause it to be rendered (depending on what the image is). Be cautious if you default the display size.

A MouseScroller is attached to the image if the mouseScroller parameter is true. This enables simple mouse panning of the image. If false, no panner is added (although the application is free to to so). If you need to control the panner, create it yourself; there is no way to get a handle to the one created by this method.

This factory is a convenience function. The display can be created on your own if you want more control. The guts look like this:

     if (w == 0) w = image.getWidth();
     if (h == 0) h = image.getHeight();
     JPanel img_panel = new JadeDisplay(image);
     JScrollPane sp = new JScrollPane(img_panel);
     sp.setViewport(new JViewportImage());
     sp.setViewportView(img_panel);
     if (mouseScroller)
         new MouseScroller(sp.getViewport());
     sp.setPreferredSize(new Dimension(w, h));
     return sp;
 

Note that a JViewportImage should be used instead of Swing's JViewport. It will give you smoother diagonal scrolling. It should work with JViewport but mouse-based scrolling will be very distracting to the user.


getImage

public RenderedImage getImage()
Returns the image currently being displayed.


setImage

public void setImage(RenderedImage im)
Changes the source image to a new RenderedImage.

If the supplied image is null, the display will simply be cleared to the background color (and remain that way until an image is set). No background or overlay painters are activated.


setImage

public void setImage(RenderedImage im,
                     Point origin)
Changes the source image to a new RenderedImage while simultaneously changing the image origin. Useful if the new image has a different minX/Y value to prevent multiple updates.

If the supplied image is null, the display will simply be cleared to the background color (and remain that way until an image is set). No background or overlay painters are activated.

See Also:
setImageOrigin(Point)

setImageInternal

protected void setImageInternal(RenderedImage im)
Sets up a new image, registering and unregistering Listener's and updating any derived values. For internal use only.


addOverlayPainter

public void addOverlayPainter(int index,
                              OverlayPainter painter,
                              boolean isImmediate)
Adds an OverlayPainter to this component at the given position in the list. If the supplied index is bigger than the size of the list, the painter is simply added to the end of the list. (the end of the list is painted last, and is thus on top).

If isImmediate is true, the painter is added in immediate mode, meaning it is called for each and every screen update. If it is false, it is added in batch mode, meaning it is called when the damage list is empty for a much larger area (often the whole window).

This method is safe to call from any thread.

Note: Batch mode is not yet implemented. Attempting to use it will cause an UnsupportedOperationException.

Parameters:
index - index at which the specified element is to be inserted.
painter - the OverlayPainter being registered.
isImmediate - flag indicating immediate or batch mode.
Throws:
IndexOutOfBoundsException - if the index is < 0.
See Also:
List.add(int, Object)

addOverlayPainter

public void addOverlayPainter(OverlayPainter painter)
Adds an immediate-mode OverlayPainter to the end of the list (i.e. on top of everything else.

This method is safe to call from any thread.

See Also:
addOverlayPainter(int, OverlayPainter, boolean)

addOverlayPainterNRP

public void addOverlayPainterNRP(int index,
                                 OverlayPainter painter,
                                 boolean isImmediate)
Adds an OverlayPainter to this component. This is exactly like addOverlayPainter() except that repaint() is not called to refresh the display. It is imperative that the caller immediately call a variant of repaint() to repaint the affected area.

The intent of this variant is to support OverlayPainters with limited bounding boxes. Instead of requiring the entire image be redrawn, only the area affected by the painter needs to be redrawn.

This method is safe to call from any thread.

See Also:
addOverlayPainter(int, OverlayPainter, boolean)

removeOverlayPainter

public void removeOverlayPainter(OverlayPainter painter)
Removes the specified OverlayPainter from this component. If the painter is not found, nothing happens and no error is generated. If the painter happens to be in the list twice, only the first one found will be removed (batch painters are removed first).

This method is safe to call from any thread.

Parameters:
painter - the OverlayPainter to remove.
See Also:
addOverlayPainter(int, jpl.mipl.jade.OverlayPainter, boolean)

removeOverlayPainterNRP

public void removeOverlayPainterNRP(OverlayPainter painter)
Removes the specified OverlayPainter from this component. This is exactly like removeOverlayPainter() except that repaint() is not called to refresh the display. It is imperative that the caller immediately call a variant of repaint() to repaint the affected area.

The intent of this variant is to support OverlayPainters with limited bounding boxes. Instead of requiring the entire image be redrawn, only the area affected by the painter needs to be redrawn.

This method is safe to call from any thread.

See Also:
removeOverlayPainter(OverlayPainter)

setBackgroundPainter

public BackgroundPainter setBackgroundPainter(BackgroundPainter bgpaint)
Sets the given object to be the BackgroundPainter for this component. This replaces any old BackgroundPainters (there is only one). The previous BackgroundPainter is returned (which could be null if it's the default).

If null is passed in, the default background painting behavior will be restored (which simply erases the background). See BackgroundPainter for the actual code.

This method is safe to call from any thread.

Parameters:
bgpaint - the BackgroundPainter being registered.
Returns:
the previous BackgroundPainter or null if it's the default method.
See Also:
BackgroundPainter

paintBackground

public void paintBackground(Graphics g,
                            int x,
                            int y,
                            int width,
                            int height,
                            boolean isNoErase,
                            boolean isInsideImage,
                            boolean isDeferredTile)
Default background painter method. Implemented as follows:
  private void paintBackground(Graphics g,
                              int x, int y, int width, int height,
                              boolean isNoErase, boolean isInsideImage,
                              boolean isDeferredTile)
  {
      if (isDeferredTile || isNoErase)
          return;
      g.fillRect(x, y, width, height);
  }
 

This method is public only because it implements the BackgroundPainter< interface. It should not be referenced from outside. In order to use this default, call setBackgroundPainter(null).

Specified by:
paintBackground in interface BackgroundPainter
Parameters:
g - The Graphics into which to paint. This is most likely a Graphics2D instance, but that is not guaranteed by JadeDisplay. It is usually whatever was passed in to paint(g), translated and clipped appropriately.
x - The X coordinate of the rectangle to be painted
y - The Y coordinate of the rectangle to be painted
width - The width of the rectangle to be painted
height - The height of the rectangle to be painted
isNoErase - True if called from paintNoErase()
isInsideImage - True if rectangle is inside the image bounds
isDeferredTile - True if tile is deferred (this is the second call)
See Also:
BackgroundPainter, setBackgroundPainter(jpl.mipl.jade.BackgroundPainter)

handleResize

protected void handleResize()
Handles the component being resized by resetting all size-dependent member variables.


sizeComponent

protected void sizeComponent()
Sizes the component based on the image size.


setImageOrigin

public void setImageOrigin(Point origin)
Changes the imageOrigin property. This property defines the image coordinate that is shown in the upper left corner of the component. Any part of the image above and to the left of that coordinate will not be displayed. Note that the logical location of the image is taken into account, so if the image starts at (-100,-100) (see RenderedImage.getMinX/Y()), then the imageOrigin would also need to be set to (-100,-100) in order to display the whole image. This imageOrigin is a hard cropping and should not be confused with a Pan value, which is managed entirely by the JScrollPane (or other higher-level component).

If the origin is set to null, the origin will automatically be set to the image's minX and minY values, and will be reset whenever those change. This means that the origin is pinned to the actual corner of the image.


getImageOrigin

public Point getImageOrigin()
Returns a copy of the image origin value. Will return null if that's the way the user set it (in which case the image's getMinX() and getMinY() will need to be called by the user to get the values).

See Also:
setImageOrigin(java.awt.Point), getCurrentImageOrigin()

getCurrentImageOrigin

public Point getCurrentImageOrigin()
Returns a copy of the current image origin value. This differs from getImageOrigin() because it will never return null. If the origin has not been set, the image's getMinX/Y() will be called as a convenience, and returned. Note that this value can change if the image min does, so it should be used immediately and not stored.

See Also:
setImageOrigin(java.awt.Point), getImageOrigin()

setRepaintPolicy

public void setRepaintPolicy(int policy)
Sets the repaint policy. See the field definitions and class comments for details.


getRepaintPolicy

public int getRepaintPolicy()
Gets the repaint policy. See the field definitions and class comments for details.


setRCEmode

public void setRCEmode(int mode)
Sets the RenderingChangeEvent repaint mode. See the field definitions and class comments for details.


getRCEmode

public int getRCEmode()
Gets the RenderingChangeEvent repaint mode. See the field definitions and class comments for details.


setDisableDoubleBuffering

public void setDisableDoubleBuffering(boolean flag)
Sets the current state of the double-buffer disable flag. Note that this does not change the double-buffer status of any actual components; that happens when a HierarchyChanged event is received. For that matter, it is recommended that this function be called before adding the component to a container... or better yet, set the flag in the constructor. See the class comments for a discussion.


getDisableDoubleBuffering

public boolean getDisableDoubleBuffering()
Gets the current state of the double-buffer disable flag. See the class comments for a discussion.


addDamage

protected Rectangle addDamage(Rectangle rect)
Adds a Rectangle to the damage list. Normally called by paintComponent() with the current clip area. Also returns the bounding rectangle of the damage list after the new piece is added (this is done here solely to avoid another synchronize).


subtractDamage

public void subtractDamage(Rectangle rect)
Subtracts a Rectangle from the damage list. Normally called when a tile has been successfully painted.

Warning! This routine is only intended to be called by TilePainter. Do not call it from application code.


subtractDamage2

protected Rectangle subtractDamage2(Rectangle rect)
Subtracts a Rectangle from the damage list. Normally called when graphics outside the image have been successfully painted. Also returns the bounding rectangle of the damage list after the new piece is subtracted (this is done here solely to avoid another synchronize).


paintNoErase

public void paintNoErase(int x,
                         int y,
                         int w,
                         int h)
Paints a portion of the display without erasing it first. This also causes the painting to happen immediately, without waiting for repaint to batch up requests. This is intended for use with and by graphics overlays. If the background image didn't change, and only the overlay did, then erasing the background first causes undesirable flashing. Calling this routine instead of repaint should eliminate most of that flashing.

We don't paint everything this way because it is very distracting while scrolling. The image to paint changes when you scroll, but that could take some time. In the meantime, you see leftover garbage, which is objectionable. Erasing first gives the user some clue as to how much is left to repaint.

Note: This routine does not work very well if Swing double buffering is enabled. You can get undesirable flashing, which is what the routine is supposed to eliminate in the first place. Double buffering is disabled by default, though. See the discussion on double buffering in the class comments.

Important! As with all other paint-related calls, the coordinates here are Viewport coordinates, which are not necessarily the same as Image coordinates!! There is an offset if the image origin does not start at zero. getCurrentImageOrigin() can be used to get this offset. This may cause confusion because OverlayPainters are called using Image coordinates.

Note: Unlike repaint(), this method must be called from the Swing/AWT Event thread. No check is made, and the behavior is undefined if the wrong thread is used. SwingUtilities.invokeLater() can be used if you're on the wrong thread.

We used to override paintImmediately() for this function, but paintImmediately is called other places in the viewport framework, and suppressing erases caused really objectionable flashing. This routine calls paintImmediately (after setting a flag) so any restrictions with that routine apply here as well.

See Also:
JComponent.repaint(long, int, int, int, int), addOverlayPainter(int, jpl.mipl.jade.OverlayPainter, boolean), JComponent.paintImmediately(int,int,int,int), SwingUtilities.invokeLater(java.lang.Runnable)

paintNoErase

public void paintNoErase(Rectangle r)
Exactly like paintNoErase(x,y,w,h) except that the area to be repainted is a Rectangle. See that routine for details.

See Also:
paintNoErase(int,int,int,int)

paintOneOverlay

public void paintOneOverlay(OverlayPainter painter,
                            Rectangle r)
Special-purpose routine that repaints one overlay object only, without repainting the background image or other overlays.

WARNING! This routine is dangerous. It should ONLY be called to exactly overpaint an existing graphic, such as for color cycling. The exact shape of the existing overlay must be repainted, or expanded. The graphic cannot shrink, since the underlying image is not refreshed and thus the old graphic cannot be erased. Also, the overlays "on top" of this one are NOT repainted, so they may be overwritten (stacking order is not preserved with this routine). In addition, any kind of translucency or blending effect that other overlays may try to do will not work with this routine.

So, users of this routine must be aware of the global overlay environment, and must only repaint (e.g. changing colors) or expand the graphics painted by the overlay.

Note that if the region being requested is not completely drawn, the call will be converted into a call to repaint(r), which will cause ALL overlays in the area to be redrawn, not just this one (thus it may no longer be on top).

It is legal to call this routine with an OverlayPainter that is not registered as a painter (via addOverlayPainter et al. This can be used to advantage to paint special overlays (color cycling, etc). However, in this case the specified painter WILL NOT be called on expose events, or if the call to this routine is converted into a call to repaint, as described above. Thus this feature must be used with extreme caution.

Important! As with all other paint-related calls, the coordinates of r are Viewport coordinates, which are not necessarily the same as Image coordinates!! There is an offset if the image origin does not start at zero. getCurrentImageOrigin() can be used to get this offset. This may cause confusion because OverlayPainters are called using Image coordinates.

This routine must be called from the Swing/AWT event thread.

Parameters:
painter - Specifies which OverlayPainter object should do the painting. May not be called if the area is not completely drawn (see class comments). Only immediate-mode OverlayPainters are supported.
r - The area to redraw.
Throws:
IllegalArgumentException - if index is out of range.
See Also:
addOverlayPainter(int, OverlayPainter, boolean), JComponent.repaint(Rectangle)

paintComponent

public void paintComponent(Graphics g)
Called by Swing to repaint the component. Goes through each tile and tells any TilePainters that intersect the new damaged area to do their thing.

Overrides:
paintComponent in class JComponent

abortQueuedTiles

protected void abortQueuedTiles()
Abort all queued computations. This is called by the hierarchy listener when it determines the component is no longer showing, or when we get a RenderingChangeEvent.

Warning: Calling this routine when the component is showing may result in unpainted holes.


tileComputationFailure

public void tileComputationFailure(Object eventSource,
                                   TileRequest[] requests,
                                   PlanarImage image,
                                   int tileX,
                                   int tileY,
                                   Throwable situation)
TileComputationListener functions. This function is a "broker", or central switching yard, which passes the failure on to the appropriate TilePainter to handle.

Specified by:
tileComputationFailure in interface TileComputationListener

tileComputed

public void tileComputed(Object eventSource,
                         TileRequest[] requests,
                         PlanarImage image,
                         int tileX,
                         int tileY,
                         Raster tile)
TileComputationListener functions. This function is a "broker", or central switching yard, which gets notifications for each tile that is completed, and routes that notification to the appropriate TilePainter. This must be done here rather than in TilePainter directly for efficiency reasons. If JAI adds a per-tile notification mechanism, this can be dispensed with (and this class would no longer need to implement TileComputationListener).

Specified by:
tileComputed in interface TileComputationListener

tileCancelled

public void tileCancelled(Object eventSource,
                          TileRequest[] requests,
                          PlanarImage image,
                          int tileX,
                          int tileY)
TileComputationListener functions. This function is a "broker", or central switching yard, which gets notifications for each tile that is cancelled, and routes that notification to the appropriate TilePainter.

Specified by:
tileCancelled in interface TileComputationListener

getGraphics

public Graphics2D getGraphics(Rectangle bounds,
                              Graphics g)
Returns a Graphics2D object that can be used to paint a tile in the given rectangular bounds. The clip region of the returned Graphics2D will be set to the intersection of the damage list, the visible area, and the supplied bounds. In addition, the Graphics2D object will be translated appropriately to be able to draw the tile directly in image coords, so that coordinate (0,0) is at the upper left corner of the image.

The supplied Graphics object is used as a basis if it exists (the clip area and translation is set), or if it doesn't exist, a Graphics object is obtained from JComponent.getGraphics().

It is recommended (not not required) to call Graphics.dispose() when you are done with the returned Graphics object. A new one is created even if g is passed in.

Parameters:
bounds - The bounding rectangle of the tile
g - The graphics object to use, or null to get a fresh one

repaintOverlay

public void repaintOverlay(Graphics g)
Called by TilePainter to refresh an area of the overlay. If there are any immediate-mode overlay painters, they are called immediately. If there are any batch mode painters, the area is added to the overlay damage list for later painting. The area to paint is the clipRect of the supplied Graphics object.

User code should not call this routine!


propertyChange

public void propertyChange(PropertyChangeEvent evt)
Responds to a PropertyChangeEvent from the image. We look for RenderingChangeEvents and use them to update the display. Other properties are ignored.

Specified by:
propertyChange in interface PropertyChangeListener

hierarchyChanged

public void hierarchyChanged(HierarchyEvent e)
We have to monitor hierarchy events for two reasons:

Specified by:
hierarchyChanged in interface HierarchyListener