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: * @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; } }