package org.autoplot.dom;
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import org.das2.datum.DatumRange;
import org.das2.graph.DasColorBar;
import org.das2.graph.LegendPosition;
/**
* Represents a 2-D plot with an X and Y axis, and "Z" axis that is often hidden or
* implemented with a color bar.
*
* @author jbf
*/
public class Plot extends DomNode {
public Plot() {
}
protected Axis xaxis = new Axis();
public static final String PROP_XAXIS = "xaxis";
public Axis getXaxis() {
return xaxis;
}
public void setXaxis(Axis xaxis) {
Axis oldXaxis = this.xaxis;
this.xaxis = xaxis;
propertyChangeSupport.firePropertyChange(PROP_XAXIS, oldXaxis, xaxis);
}
protected Axis yaxis = new Axis();
public static final String PROP_YAXIS = "yaxis";
public Axis getYaxis() {
return yaxis;
}
public void setYaxis(Axis yaxis) {
Axis oldYaxis = this.yaxis;
this.yaxis = yaxis;
propertyChangeSupport.firePropertyChange(PROP_YAXIS, oldYaxis, yaxis);
}
protected Axis zaxis = new Axis();
public static final String PROP_ZAXIS = "zaxis";
public Axis getZaxis() {
return zaxis;
}
public void setZaxis(Axis zaxis) {
Axis oldZaxis = this.zaxis;
this.zaxis = zaxis;
propertyChangeSupport.firePropertyChange(PROP_ZAXIS, oldZaxis, zaxis);
}
private String title = "";
/**
* title for the plot.
*/
public static final String PROP_TITLE = "title";
public String getTitle() {
return title;
}
public void setTitle(String title) {
String oldTitle = this.title;
this.title = title;
propertyChangeSupport.firePropertyChange(PROP_TITLE, oldTitle, title);
}
private String fontSize = "1em";
public static final String PROP_FONTSIZE = "fontSize";
public String getFontSize() {
return fontSize;
}
/**
* set the font size relative to the canvas font size. For example
* "2em" will be twice the size. "" is an alias for 1em.
*
* @param fontSize
*/
public void setFontSize(String fontSize) {
String oldFontSize = this.fontSize;
this.fontSize = fontSize;
propertyChangeSupport.firePropertyChange(PROP_FONTSIZE, oldFontSize, fontSize);
}
/**
* font size for the legend. This can be "" or "1em" meaning that the
* plot's font size should be used.
*/
private String legendFontSize = "1em";
public static final String PROP_LEGENDFONTSIZE = "legendFontSize";
public String getLegendFontSize() {
return legendFontSize;
}
/**
* set the font size for the legend, using the conventions where 1em is
* the plot's font size:
* - 1em same as plot font.
*
- 2em twice plot font.
*
- 1em+2pt two points bigger than plot font.
*
* @see #setFontSize(java.lang.String)
* @param legendFontSize
*/
public void setLegendFontSize(String legendFontSize) {
String oldLegendFontSize = this.legendFontSize;
this.legendFontSize = legendFontSize;
propertyChangeSupport.firePropertyChange(PROP_LEGENDFONTSIZE, oldLegendFontSize, legendFontSize);
}
private Color background = new Color( 0, 0, 0, 0 );
public static final String PROP_BACKGROUND = "background";
public Color getBackground() {
return background;
}
/**
* set the background color for the plot. This is normally transparent, so
* the canvas color is used, and can be reset with Color(0,0,0,0).
* @param background
*/
public void setBackground(Color background) {
Color oldBackground = this.background;
this.background = background;
propertyChangeSupport.firePropertyChange(PROP_BACKGROUND, oldBackground, background);
}
/**
* do display the title. Turning this off has the same effect as setting the title to ""
*/
private boolean displayTitle = true;
public static final String PROP_DISPLAYTITLE = "displayTitle";
public boolean isDisplayTitle() {
return displayTitle;
}
public void setDisplayTitle(boolean displayTitle) {
boolean oldDisplayTitle = this.displayTitle;
this.displayTitle = displayTitle;
propertyChangeSupport.firePropertyChange(PROP_DISPLAYTITLE, oldDisplayTitle, displayTitle);
}
private LegendPosition legendPosition = LegendPosition.NE;
public static final String PROP_LEGENDPOSITION = "legendPosition";
public LegendPosition getLegendPosition() {
return legendPosition;
}
public void setLegendPosition(LegendPosition legendPosition) {
LegendPosition oldLegendPosition = this.legendPosition;
this.legendPosition = legendPosition;
propertyChangeSupport.firePropertyChange(PROP_LEGENDPOSITION, oldLegendPosition, legendPosition);
}
protected boolean displayLegend = true;
public static final String PROP_DISPLAYLEGEND = "displayLegend";
public boolean isDisplayLegend() {
return displayLegend;
}
public void setDisplayLegend(boolean displayLegend) {
boolean oldDisplayLegend = this.displayLegend;
this.displayLegend = displayLegend;
propertyChangeSupport.firePropertyChange(PROP_DISPLAYLEGEND, oldDisplayLegend, displayLegend);
}
/**
* indicates that the label was set by a machine, not a human, and can be
* updated automatically.
*/
private boolean autoLabel = false;
public static final String PROP_AUTOLABEL = "autoLabel";
public boolean isAutoLabel() {
return autoLabel;
}
public void setAutoLabel(boolean autolabel) {
boolean oldAutolabel = this.autoLabel;
this.autoLabel = autolabel;
propertyChangeSupport.firePropertyChange(PROP_AUTOLABEL, oldAutolabel, autolabel);
}
/**
* false indicates that the plot and its data will not
* be drawn.
*/
public static final String PROP_VISIBLE = "visible";
private boolean visible = true;
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
boolean oldVisible = this.visible;
this.visible = visible;
propertyChangeSupport.firePropertyChange(PROP_VISIBLE, oldVisible, visible);
}
/**
* indicates the application is allowed to automatically create bindings to
* the plot, typically when it is first created.
*/
public static final String PROP_AUTOBINDING = "autoBinding";
protected boolean autoBinding = false;
public boolean isAutoBinding() {
return autoBinding;
}
public void setAutoBinding(boolean autoBinding) {
boolean oldAutoBinding = this.autoBinding;
this.autoBinding = autoBinding;
propertyChangeSupport.firePropertyChange(PROP_AUTOBINDING, oldAutoBinding, autoBinding);
}
private boolean isotropic = false;
public static final String PROP_ISOTROPIC = "isotropic";
public boolean isIsotropic() {
return isotropic;
}
public void setIsotropic(boolean isotropic) {
boolean oldIsotropic = this.isotropic;
this.isotropic = isotropic;
propertyChangeSupport.firePropertyChange(PROP_ISOTROPIC, oldIsotropic, isotropic);
}
public final static String PROP_COLORTABLE= "colortable";
private DasColorBar.Type colortable= DasColorBar.Type.COLOR_WEDGE;
public DasColorBar.Type getColortable() {
return this.colortable;
}
public void setColortable(DasColorBar.Type colortable) {
Object oldVal= this.colortable;
this.colortable = colortable;
propertyChangeSupport.firePropertyChange( PROP_COLORTABLE, oldVal, this.colortable );
}
private String colorbarColumnPosition = "100%+1em,100%+2em";
public static final String PROP_COLORBARCOLUMNPOSITION = "colorbarColumnPosition";
public String getColorbarColumnPosition() {
return colorbarColumnPosition;
}
public void setColorbarColumnPosition(String colorbarColumnPosition) {
String oldColorbarColumnPosition = this.colorbarColumnPosition;
this.colorbarColumnPosition = colorbarColumnPosition;
propertyChangeSupport.firePropertyChange(PROP_COLORBARCOLUMNPOSITION, oldColorbarColumnPosition, colorbarColumnPosition);
}
private String rowId="";
public static final String PROP_ROWID = "rowId";
public String getRowId() {
return rowId;
}
public void setRowId(String rowId) {
String oldRowId = this.rowId;
this.rowId = rowId;
propertyChangeSupport.firePropertyChange(PROP_ROWID, oldRowId, rowId);
}
private String columnId="";
public static final String PROP_COLUMNID = "columnId";
public String getColumnId() {
return columnId;
}
public void setColumnId(String columnId) {
String oldColumnId = this.columnId;
this.columnId = columnId;
propertyChangeSupport.firePropertyChange(PROP_COLUMNID, oldColumnId, columnId);
}
/**
* The context is the "fourth axis" of a plot: allowing one last place to control the dimensions of data to be loaded..
* For example, if a histogram is shown of
* http://sarahandjeremy.net/~jbf/autoplot/data/jyds/demoTsb.jyds?y3&timerange=2012-04-17 , then the
* context property of the plot can be used to control the range. Note this is presently a "open-loop" where
* control can be set.
*/
private DatumRange context= Axis.DEFAULT_RANGE;
public static final String PROP_CONTEXT= "context";
public DatumRange getContext() {
return context;
}
public void setContext(DatumRange context) {
DatumRange old= this.context;
this.context = context;
propertyChangeSupport.firePropertyChange(PROP_CONTEXT, old, context );
}
/**
* The address of a dataset where additional labels for the x axis ticks can be
* found. This should be the address of a bundle dataset.
*/
private String ticksURI= "";
public static final String PROP_TICKS_URI= "ticksURI";
public String getTicksURI() {
return ticksURI;
}
public void setTicksURI( String ticksURI ) {
String old= this.ticksURI;
this.ticksURI = ticksURI;
propertyChangeSupport.firePropertyChange(PROP_TICKS_URI, old, ticksURI );
}
/**
* -1 or the number of lines to allocate space for ephemeris.
*/
private int ephemerisLineCount = -1;
public static final String PROP_EPHEMERISLINECOUNT = "ephemerisLineCount";
/**
* 0 or the number of lines to allocate space for ephemeris. Note this is set automatically when the ephemeris is
* loaded. This was introduced so that fixLayout could be performed without knowing what the TCA dataset contains.
* @return the line count or -1 if no lines are allocated.
*/
public int getEphemerisLineCount() {
return ephemerisLineCount;
}
/**
* 0 or the number of lines to allocate space for ephemeris. Note this is set automatically when the ephemeris is
* loaded.
* @param ephemerisLineCount
*/
public void setEphemerisLineCount(int ephemerisLineCount) {
int oldEphemerisLineCount = this.ephemerisLineCount;
this.ephemerisLineCount = ephemerisLineCount;
propertyChangeSupport.firePropertyChange(PROP_EPHEMERISLINECOUNT, oldEphemerisLineCount, ephemerisLineCount);
}
private String ephemerisLabels="";
public static final String PROP_EPHEMERIS_LABELS = "ephemerisLabels";
public String getEphemerisLabels() {
return ephemerisLabels;
}
/**
* explicitly set the label for each line of ephemeris, using a semi-colon delimited list of labels.
* @param ephemerisLabels
*/
public void setEphemerisLabels(String ephemerisLabels) {
String oldEphemerisLabels = this.ephemerisLabels;
this.ephemerisLabels = ephemerisLabels;
propertyChangeSupport.firePropertyChange(PROP_EPHEMERIS_LABELS, oldEphemerisLabels, ephemerisLabels);
}
protected PlotController controller;
public PlotController getController() {
return controller;
}
@Override
public DomNode copy() {
Plot result = (Plot) super.copy();
result.controller = null;
result.xaxis = (Axis) result.xaxis.copy();
result.yaxis = (Axis) result.yaxis.copy();
result.zaxis = (Axis) result.zaxis.copy();
return result;
}
@Override
public void syncTo(DomNode n) {
syncTo( n, new ArrayList<>() );
}
@Override
public void syncTo(DomNode n, List exclude) {
super.syncTo(n,exclude);
if ( !( n instanceof Plot ) ) throw new IllegalArgumentException("node should be a Plot");
Plot that = (Plot) n;
if (!exclude.contains(PROP_TITLE)) this.setTitle(that.getTitle());
if (!exclude.contains(PROP_ISOTROPIC)) this.setIsotropic(that.isIsotropic());
if (!exclude.contains(PROP_COLORTABLE ) ) this.setColortable( that.colortable );
if (!exclude.contains(PROP_ROWID)) this.setRowId(that.getRowId());
if (!exclude.contains(PROP_COLUMNID)) this.setColumnId(that.getColumnId());
if (!exclude.contains(PROP_AUTOLABEL)) this.setAutoLabel(that.isAutoLabel());
if (!exclude.contains(PROP_XAXIS)) this.xaxis.syncTo(that.getXaxis(),exclude); // possibly exclude id's.
if (!exclude.contains(PROP_YAXIS)) this.yaxis.syncTo(that.getYaxis(),exclude);
if (!exclude.contains(PROP_ZAXIS)) this.zaxis.syncTo(that.getZaxis(),exclude);
if (!exclude.contains(PROP_VISIBLE)) this.setVisible(that.isVisible());
if (!exclude.contains(PROP_CONTEXT)) this.setContext(that.getContext());
if (!exclude.contains(PROP_TICKS_URI)) this.setTicksURI(that.getTicksURI());
if (!exclude.contains(PROP_EPHEMERIS_LABELS)) this.setEphemerisLabels(that.getEphemerisLabels());
if (!exclude.contains(PROP_EPHEMERISLINECOUNT)) this.setEphemerisLineCount(that.getEphemerisLineCount());
if (!exclude.contains(PROP_LEGENDPOSITION)) this.setLegendPosition(that.getLegendPosition());
if (!exclude.contains(PROP_COLORBARCOLUMNPOSITION)) this.setColorbarColumnPosition( that.getColorbarColumnPosition() );
if (!exclude.contains(PROP_FONTSIZE) ) this.setFontSize(that.getFontSize());
if (!exclude.contains(PROP_LEGENDFONTSIZE) ) this.setLegendFontSize(that.getLegendFontSize());
if (!exclude.contains(PROP_DISPLAYLEGEND)) this.setDisplayLegend(that.isDisplayLegend());
if (!exclude.contains(PROP_DISPLAYTITLE)) this.setDisplayTitle(that.isDisplayTitle());
if (!exclude.contains(PROP_BACKGROUND)) this.setBackground(that.getBackground());
}
@Override
public List childNodes() {
ArrayList result = new ArrayList<>();
result.add(xaxis);
result.add(yaxis);
result.add(zaxis);
return result;
}
@Override
public List diffs(DomNode node) {
if ( !( node instanceof Plot ) ) throw new IllegalArgumentException("node should be a Plot");
Plot that = (Plot) node;
List result = super.diffs(node);
boolean b;
b = that.title.equals(this.title);
if (!b) result.add(new PropertyChangeDiff(PROP_TITLE, that.title, this.title));
b = that.isotropic == this.isotropic;
if (!b) result.add(new PropertyChangeDiff(PROP_ISOTROPIC, that.isotropic, this.isotropic));
b= that.colortable.equals(this.colortable) ;
if ( !b ) result.add( new PropertyChangeDiff( PROP_COLORTABLE, that.colortable , this.colortable ) );
b = that.autoLabel == this.autoLabel;
if (!b) result.add(new PropertyChangeDiff(PROP_AUTOLABEL, that.autoLabel, this.autoLabel));
b = that.autoBinding == this.autoBinding;
if (!b) result.add(new PropertyChangeDiff(PROP_AUTOBINDING, that.autoBinding, this.autoBinding));
b = that.rowId.equals(this.rowId);
if (!b) result.add(new PropertyChangeDiff(PROP_ROWID, that.rowId, this.rowId));
b = that.columnId.equals(this.columnId);
if (!b) result.add(new PropertyChangeDiff(PROP_COLUMNID, that.columnId, this.columnId));
b = that.visible == this.visible;
if (!b) result.add(new PropertyChangeDiff(PROP_VISIBLE, that.visible, this.visible));
if ( that.context==this.context ) {
b= true;
} else {
b = that.context!=null && that.context.equals(this.context);
}
if (!b) result.add(new PropertyChangeDiff(PROP_CONTEXT, that.context, this.context));
b= that.ticksURI.equals(this.ticksURI);
if (!b) result.add(new PropertyChangeDiff(PROP_TICKS_URI, that.ticksURI, this.ticksURI));
b= that.ephemerisLabels.equals(this.ephemerisLabels);
if (!b) result.add(new PropertyChangeDiff(PROP_EPHEMERIS_LABELS, that.ephemerisLabels, this.ephemerisLabels));
b= that.ephemerisLineCount==this.ephemerisLineCount;
if (!b) result.add(new PropertyChangeDiff(PROP_EPHEMERISLINECOUNT, that.ephemerisLineCount, this.ephemerisLineCount));
b= that.legendPosition.equals(this.legendPosition);
if (!b) result.add(new PropertyChangeDiff(PROP_LEGENDPOSITION, that.legendPosition, this.legendPosition ));
b= that.colorbarColumnPosition.equals(this.colorbarColumnPosition);
if (!b) result.add(new PropertyChangeDiff(PROP_COLORBARCOLUMNPOSITION, that.colorbarColumnPosition, this.colorbarColumnPosition ));
b= that.displayLegend==this.displayLegend;
if (!b) result.add(new PropertyChangeDiff(PROP_DISPLAYLEGEND, that.displayLegend, this.displayLegend ));
b= that.fontSize.equals(this.fontSize) ;
if ( !b ) result.add(new PropertyChangeDiff( PROP_FONTSIZE, that.fontSize , this.fontSize ) );
b= that.legendFontSize.equals(this.legendFontSize) ;
if ( !b ) result.add(new PropertyChangeDiff( PROP_LEGENDFONTSIZE, that.legendFontSize , this.legendFontSize ) );
b= that.displayTitle==this.displayTitle;
if (!b) result.add(new PropertyChangeDiff(PROP_DISPLAYTITLE, that.displayTitle, this.displayTitle ));
b= that.background.equals(this.background);
if (!b) result.add(new PropertyChangeDiff(PROP_BACKGROUND, that.background, this.background ));
result.addAll(DomUtil.childDiffs( PROP_XAXIS, this.getXaxis().diffs(that.getXaxis())));
result.addAll(DomUtil.childDiffs( PROP_YAXIS, this.getYaxis().diffs(that.getYaxis())));
result.addAll(DomUtil.childDiffs( PROP_ZAXIS, this.getZaxis().diffs(that.getZaxis())));
return result;
}
}