package com.revolsys.swing.map.layer; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.swing.Icon; import com.revolsys.collection.map.LinkedHashMapEx; import com.revolsys.collection.map.MapEx; import com.revolsys.properties.BaseObjectWithPropertiesAndChange; import com.revolsys.swing.Icons; import com.revolsys.swing.component.Form; import com.revolsys.swing.map.Viewport2D; import com.revolsys.swing.map.layer.record.style.panel.BaseStylePanel; import com.revolsys.util.Cancellable; import com.revolsys.util.CaseConverter; import com.revolsys.util.Property; public abstract class AbstractLayerRenderer<T extends Layer> extends BaseObjectWithPropertiesAndChange implements LayerRenderer<T>, PropertyChangeListener, Cloneable { private static final Icon ICON = Icons.getIcon("palette"); private boolean editing = true; private Icon icon = ICON; private T layer; private long maximumScale = 0; private long minimumScale = Long.MAX_VALUE; private String name; private LayerRenderer<?> parent; private final String type; private boolean visible = true; private boolean open = false; public AbstractLayerRenderer(final String type) { this(type, (String)null); } public AbstractLayerRenderer(final String type, final String name) { this.type = type; setName(name); } public AbstractLayerRenderer(final String type, final String name, final T layer, final LayerRenderer<?> parent) { this(type, name); setLayer(layer); setParent(parent); } public AbstractLayerRenderer(final String type, final T layer) { this(type); this.layer = layer; } @SuppressWarnings("unchecked") @Override public AbstractLayerRenderer<T> clone() { final AbstractLayerRenderer<T> clone = (AbstractLayerRenderer<T>)super.clone(); clone.parent = null; clone.editing = false; return clone; } @Override public Icon getIcon() { return this.icon; } @SuppressWarnings("unchecked") @Override public T getLayer() { final LayerRenderer<?> parent = getParent(); if (parent == null) { return this.layer; } else { return (T)parent.getLayer(); } } public long getMaximumScale() { return this.maximumScale; } public long getMinimumScale() { return this.minimumScale; } @Override public String getName() { return this.name; } @Override public LayerRenderer<?> getParent() { return this.parent; } @Override public List<String> getPathNames() { final LinkedList<String> names = new LinkedList<>(); final String name = getName(); names.add(name); for (LayerRenderer<?> parent = getParent(); parent != null; parent = parent.getParent()) { final String parentName = parent.getName(); names.addFirst(parentName); } return names; } @Override public List<LayerRenderer<?>> getPathRenderers() { final LinkedList<LayerRenderer<?>> renderers = new LinkedList<>(); renderers.add(this); for (LayerRenderer<?> parent = getParent(); parent != null; parent = parent.getParent()) { renderers.addFirst(parent); } return renderers; } @Override @SuppressWarnings("unchecked") public <V extends LayerRenderer<?>> V getRenderer(final List<String> path) { if (path.isEmpty()) { return null; } else if (path.get(0).equals(getName())) { return (V)this; } return null; } public String getType() { return this.type; } @SuppressWarnings("unchecked") protected <V> V getValue(final Map<String, Object> map, final String name) { final Object value = map.get(name); return (V)value; } @Override public boolean isEditing() { if (this.parent == null) { return this.editing; } else { return this.parent.isEditing(); } } @Override public boolean isOpen() { return this.open; } @Override public boolean isVisible() { return this.visible; } public boolean isVisible(final double scale) { if (isVisible()) { final long longScale = Math.round(scale); final long min = getMinimumScale(); final long max = getMaximumScale(); if (min >= longScale && longScale >= max) { return true; } } return false; } @Override public Form newStylePanel() { return new BaseStylePanel(this, true); } @Override public void propertyChange(final PropertyChangeEvent event) { firePropertyChange(event); } @Override public final void render(final Viewport2D viewport, final Cancellable cancellable) { final T layer = getLayer(); if (layer != null) { final double scaleForVisible = viewport.getScaleForVisible(); if (isVisible(scaleForVisible)) { render(viewport, cancellable, layer); } } } public abstract void render(Viewport2D viewport, Cancellable cancellable, T layer); @Override public void setEditing(final boolean editing) { final boolean oldValue = this.editing; this.editing = editing; firePropertyChange("editing", oldValue, this.layer); } public void setIcon(final Icon icon) { final Object oldValue = this.icon; this.icon = icon; firePropertyChange("icon", oldValue, icon); } @Override public void setLayer(final T layer) { final Object oldValue = this.layer; this.layer = layer; firePropertyChange("layer", oldValue, layer); } public void setMaximumScale(long maximumScale) { if (maximumScale < 0) { maximumScale = 0; } final long oldValue = this.maximumScale; this.maximumScale = maximumScale; firePropertyChange("maximumScale", oldValue, maximumScale); } public void setMinimumScale(long minimumScale) { if (minimumScale <= 0) { minimumScale = Long.MAX_VALUE; } final long oldValue = this.minimumScale; this.minimumScale = minimumScale; firePropertyChange("minimumScale", oldValue, minimumScale); } public void setName(final String name) { final String oldName = getName(); if (Property.hasValue(name)) { this.name = name; } else { this.name = CaseConverter.toCapitalizedWords(this.type); } firePropertyChange("name", oldName, this.name); } @Override public void setOpen(final boolean open) { final boolean oldValue = this.open; this.open = open; firePropertyChange("open", oldValue, this.open); } @SuppressWarnings("unchecked") @Override public void setParent(final LayerRenderer<?> parent) { final LayerRenderer<?> oldValue = this.parent; Property.removeListener(this, oldValue); this.parent = parent; if (parent != null) { setLayer((T)parent.getLayer()); } Property.addListener(this, parent); firePropertyChange("parent", oldValue, parent); } @Override public void setVisible(final boolean visible) { final boolean oldVisible = this.visible; this.visible = visible; firePropertyChange("visible", oldVisible, visible); } public void showProperties() { final T layer = getLayer(); if (layer != null) { layer.showRendererProperties(this); } } @Override public MapEx toMap() { final MapEx map = new LinkedHashMapEx(); addTypeToMap(map, this.type); addToMap(map, "name", this.name); addToMap(map, "visible", this.visible, true); addToMap(map, "maximumScale", this.maximumScale, 0); addToMap(map, "minimumScale", this.minimumScale, Long.MAX_VALUE); addToMap(map, "open", this.open, false); return map; } @Override public String toString() { if (Property.hasValue(this.name)) { return this.name; } else { return this.type; } } }