package org.chartsy.main.chart; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.LinkedHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; import org.chartsy.main.ChartFrame; import org.chartsy.main.ChartFrameAdapter; import org.chartsy.main.data.Dataset; import org.chartsy.main.managers.DatasetUsage; import org.chartsy.main.utils.Range; import org.chartsy.main.utils.SerialVersion; import org.chartsy.main.utils.XMLUtil; import org.chartsy.main.utils.XMLUtil.XMLTemplate; import org.openide.nodes.AbstractNode; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * * @author viorel.gheba */ public abstract class Overlay extends ChartFrameAdapter implements Serializable, XMLTemplate { private static final long serialVersionUID = SerialVersion.APPVERSION; protected String datasetKey; protected ConcurrentHashMap<String, Dataset> datasets; protected boolean active = true; public Overlay() { datasets = new ConcurrentHashMap<String, Dataset>(); } public String getFontHTML(Color color, String text) { String html = "<font color=\"" + Integer.toHexString(color.getRGB() & 0x00ffffff) + "\">" + text + "</font>"; return html; } public Dataset getDataset() { return DatasetUsage.getInstance().getDatasetFromMemory(datasetKey); } public void setDatasetKey(String datasetKey) { this.datasetKey = datasetKey; } public void clearDatasets() { datasets.clear(); } public void addDataset(String key, Dataset value) { datasets.put(key, value); } public Dataset getDataset(String key) { return datasets.get(key); } private boolean datasetExists(String key) { return datasets.containsKey(key); } public Dataset visibleDataset(ChartFrame cf, String key) { if (datasetExists(key)) { Dataset dataset = getDataset(key); if (dataset == null) { return null; } int period = cf.getChartData().getPeriod(); int last = cf.getChartData().getLast(); Dataset visible = dataset.getVisibleDataset(period, last); return visible; } return null; } public abstract String getName(); public abstract String getLabel(); public abstract Overlay newInstance(); public abstract LinkedHashMap getHTML(ChartFrame cf, int i); public Range getRange(ChartFrame cf, String price) { Range range = null; String[] keys = datasets.keySet().toArray(new String[datasets.size()]); for (String key : keys) { Dataset dataset = visibleDataset(cf, key); double min = dataset.getMinNotZero(price); double max = dataset.getMaxNotZero(price); if (range == null) { range = new Range(min - (max - min) * 0.01, max + (max - min) * 0.01); } else { range = Range.combine(range, new Range(min - (max - min) * 0.01, max + (max - min) * 0.01)); } } return range; } public abstract void paint(Graphics2D g, ChartFrame cf, Rectangle bounds); public abstract void calculate(); public abstract Color[] getColors(); public abstract double[] getValues(ChartFrame cf); public abstract double[] getValues(ChartFrame cf, int i); public abstract boolean getMarkerVisibility(); public abstract AbstractNode getNode(); public abstract String getPrice(); /** * If an override in the overlay class sets this to false * that overlay is not included in the range calculation of the chart. * * @return whether to include this overlay in chart range */ public boolean isIncludedInRange() { return true; } public void saveToTemplate(Document document, Element element) { AbstractPropertiesNode node = (AbstractPropertiesNode) getNode(); AbstractPropertyListener listener = node.getAbstractPropertyListener(); Field[] fields = listener.getClass().getDeclaredFields(); for (Field field : fields) { try { field.setAccessible(true); if (field.getModifiers() == Modifier.PRIVATE) XMLUtil.addProperty(document, element, field.getName(), field.get(listener)); } catch (Exception ex) { Logger.getLogger(getName()).log(Level.SEVERE, "", ex); } } } public void loadFromTemplate(Element element) { AbstractPropertiesNode node = (AbstractPropertiesNode) getNode(); AbstractPropertyListener listener = node.getAbstractPropertyListener(); Field[] fields = listener.getClass().getDeclaredFields(); for (Field field : fields) { try { field.setAccessible(true); if (field.getModifiers() == Modifier.PRIVATE) { if (XMLUtil.elementExists(element, field.getName())) { Class type = field.getType(); if (type.equals(String.class)) field.set(listener, XMLUtil.getStringProperty(element, field.getName())); else if (type.equals(int.class)) field.set(listener, XMLUtil.getIntegerProperty(element, field.getName())); else if (type.equals(double.class)) field.set(listener, XMLUtil.getDoubleProperty(element, field.getName())); else if (type.equals(float.class)) field.set(listener, XMLUtil.getFloatProperty(element, field.getName())); else if (type.equals(boolean.class)) field.set(listener, XMLUtil.getBooleanProperty(element, field.getName())); else if (type.equals(Color.class)) field.set(listener, XMLUtil.getColorProperty(element, field.getName())); } } } catch (Exception ex) { Logger.getLogger(getName()).log(Level.SEVERE, "", ex); } } } public void setActive(boolean active) { this.active = active; } public boolean isActive() { return active; } @Override public void datasetKeyChanged(String datasetKey) { setDatasetKey(datasetKey); calculate(); } }