Turning back to our example, the PosTrackerViewer maintains an ImageDisplayMap object which must updated everytime a new Slice is displayed. Here is that first section of code from the displaySlice(Slice sl) that we showed above but with a few more lines:
if (newViewable) {
// this is a new data set, so we need to update our coordinate
// system
coordSys = data.getCoordSys();
// we also need to reset our ImageDisplayMap object that defines
// the mapping between display and data pixels.
setPixelMap(slice, null);
newViewable = false;
}
else {
// this is just a new slice from an already attached Viewable;
// thus, we need only update the pixel mapper.
updatePixelMap();
}
The setPixelMap() and updatePixelMap() methods keep the
ImageDisplayMap object in sync with what is being viewed, so let's
have a look at them. Here's the code for the method that sets up the
ImageDisplayMap when a new Viewable is attached to the
Viewer:
protected synchronized void setPixelMap(Slice dataSlice,
Rectangle displayRegion) {
Boolean xaxisReversed, yaxisReversed;
if (data != null) {
pixelMap = new ImageDisplayMap();
// the attached viewable may give some hints on how the
// data is ordered in the form of "xaxisReversed" and
// "yaxisReversed" metadata
//
Metadata md = data.getMetadata();
if (md != null) {
try {
xaxisReversed = (Boolean) md.getMetadatum("xaxisReversed");
} catch (ClassCastException ex) { xaxisReversed = null; }
try {
yaxisReversed = (Boolean) md.getMetadatum("yaxisReversed");
} catch (ClassCastException ex) { yaxisReversed = null; }
}
if (xaxisReversed != null)
pixelMap.xaxisReversed = xaxisReversed.booleanValue();
if (yaxisReversed != null)
pixelMap.yaxisReversed = yaxisReversed.booleanValue();
}
// now set the mapping appropriate for a slice of requested size
updatePixelMap(dataSlice, displayRegion);
}
Note that we have consulted the Viewable's metadata for the
values xaxisReversed and yaxisReversed. If values are
found there, they are passed to the ImageDisplayMap object;
otherwise, the default value of false is kept.
Now let's look at updatePixelMap which is called whenever a new slice is displayed:
protected synchronized void updatePixelMap(Slice dataSlice,
Rectangle displayRegion) {
int dwd=-1, dht=-1;
if (pixelMap == null) {
setPixelMap(dataSlice, displayRegion);
return; // this calls updatePixelMap(),
// so we should return
}
if (dataSlice == null && displayRegion == null) return;
if (displayRegion == null) {
dwd = dataSlice.getTrueLength(slice.getXaxis());
dht = dataSlice.getTrueLength(slice.getYaxis());
// this is how much space an image with an unscaled size of
// wd x ht will take up on the screen
//
Dimension dispdim = display.viewSize(dwd, dht);
displayRegion = new Rectangle(0, 0, dispdim.width, dispdim.height);
}
if (dataSlice != null) pixelMap.setSlice(dataSlice);
if (displayRegion != null) pixelMap.setDisplay(displayRegion);
}
As it turns out in our implementation, the value of
displayRegion is always null, so the default--as much as
the display area as possible--is used instead.