/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
/*
* FeatureInfoWidget.java
*
* Created on 5. April 2006, 10:41
*/
package de.cismet.cismap.commons.gui.featureinfowidget;
import com.jgoodies.looks.Options;
import org.apache.log4j.Logger;
import java.awt.Color;
import java.awt.Component;
import java.util.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import de.cismet.cismap.commons.ChildrenProvider;
import de.cismet.cismap.commons.LayerInfoProvider;
import de.cismet.cismap.commons.gui.MappingComponent;
import de.cismet.cismap.commons.gui.piccolo.eventlistener.GetFeatureInfoClickDetectionListener;
import de.cismet.cismap.commons.interaction.ActiveLayerListener;
import de.cismet.cismap.commons.interaction.CismapBroker;
import de.cismet.cismap.commons.interaction.MapClickListener;
import de.cismet.cismap.commons.interaction.events.ActiveLayerEvent;
import de.cismet.cismap.commons.interaction.events.MapClickedEvent;
import de.cismet.cismap.commons.raster.wms.SlidableWMSServiceLayerGroup;
import de.cismet.cismap.commons.raster.wms.WMSLayer;
import de.cismet.cismap.commons.raster.wms.WMSServiceLayer;
/**
* DOCUMENT ME!
*
* @author thorsten.hell@cismet.de
* @version $Revision$, $Date$
*/
public class FeatureInfoWidget extends JPanel implements ActiveLayerListener, MapClickListener {
//~ Static fields/initializers ---------------------------------------------
private static final transient Logger LOG = Logger.getLogger(FeatureInfoWidget.class);
//~ Instance fields --------------------------------------------------------
private final transient Map<Object, FeatureInfoDisplay> displays;
private final transient FeatureInfoDisplayRepository displayRepo;
private final transient Map<String, List<AggregateableFeatureInfoDisplay>> aggregatableDisplayMap;
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButton1;
private javax.swing.JTabbedPane tbpFeatureInfos;
// End of variables declaration//GEN-END:variables
//~ Constructors -----------------------------------------------------------
/**
* Creates new form FeatureInfoWidget.
*/
public FeatureInfoWidget() {
displays = new HashMap<Object, FeatureInfoDisplay>();
displayRepo = new FeatureInfoDisplayRepository();
aggregatableDisplayMap = new HashMap<String, List<AggregateableFeatureInfoDisplay>>();
initComponents();
tbpFeatureInfos.putClientProperty(Options.NO_CONTENT_BORDER_KEY, Boolean.FALSE);
tbpFeatureInfos.setRequestFocusEnabled(true);
tbpFeatureInfos.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
}
//~ Methods ----------------------------------------------------------------
@Override
public void layerVisibilityChanged(final ActiveLayerEvent e) {
// noop
}
@Override
public void layerAvailabilityChanged(final ActiveLayerEvent e) {
// noop
}
@Override
public void layerSelectionChanged(final ActiveLayerEvent e) {
final Object o = e.getLayer();
if ((o instanceof WMSLayer) && (displays.get(o) != null)) {
tbpFeatureInfos.setSelectedComponent(displays.get(o).getDisplayComponent());
} else if ((o instanceof WMSServiceLayer) && (((WMSServiceLayer)o).getWMSLayers().size() == 1)) {
final FeatureInfoDisplay displ = displays.get(((WMSServiceLayer)o).getWMSLayers().get(0));
if (displ != null) {
tbpFeatureInfos.setSelectedComponent(displ.getDisplayComponent());
}
} else if ((o instanceof SlidableWMSServiceLayerGroup) && (displays.get(o) != null)) {
tbpFeatureInfos.setSelectedComponent(displays.get(o).getDisplayComponent());
}
}
@Override
public void layerRemoved(final ActiveLayerEvent e) {
handleInformationStatusChanged(e, true);
}
@Override
public void layerPositionChanged(final ActiveLayerEvent e) {
// noop
}
@Override
public void layerInformationStatusChanged(final ActiveLayerEvent e) {
handleInformationStatusChanged(e, false);
}
@Override
public void layerAdded(final ActiveLayerEvent e) {
handleInformationStatusChanged(e, false);
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
* @param remove DOCUMENT ME!
*/
private void handleInformationStatusChanged(final ActiveLayerEvent e, final boolean remove) {
final Object o = e.getLayer();
if (o instanceof ChildrenProvider) {
final Collection c = ((ChildrenProvider)o).getChildren();
for (final Object childlayer : c) {
final ActiveLayerEvent ale = new ActiveLayerEvent();
ale.setLayer(childlayer);
handleInformationStatusChanged(ale, remove);
}
} else if ((o instanceof LayerInfoProvider) && ((LayerInfoProvider)o).isQueryable()) {
final LayerInfoProvider layer = (LayerInfoProvider)o;
FeatureInfoDisplay display = displays.get(layer);
if ((display != null) && ((layer.isLayerQuerySelected() == false) || remove)) {
final FeatureInfoDisplay d = displays.get(layer);
if (d instanceof AggregateableFeatureInfoDisplay) {
final AggregateableFeatureInfoDisplay aggrDisplay = ((AggregateableFeatureInfoDisplay)d);
final String aggregateType = aggrDisplay.getAggregateTypeID();
aggregatableDisplayMap.get(aggregateType).remove(aggrDisplay);
for (final AggregateableFeatureInfoDisplay displ : aggregatableDisplayMap.get(aggregateType)) {
displ.setAggregatableDisplayList(aggregatableDisplayMap.get(aggregateType));
}
}
try {
tbpFeatureInfos.remove(display.getDisplayComponent());
displays.remove(layer);
} catch (Exception ex) {
LOG.warn("Workaround for style changes(there is no refresh, but only remove/add)", ex); // NOI18N I dont understand this
}
} else if (((display == null) && layer.isLayerQuerySelected()) && !remove) {
try {
display = displayRepo.getDisplay(layer.getClass(), layer);
if (display == null) {
// TODO: use default display? or should even a default be delivered by the repo?
throw new IllegalStateException("dispay info for layer is null: " + layer); // NOI18N
}
display.init(layer, tbpFeatureInfos);
if (display instanceof AggregateableFeatureInfoDisplay) {
final String aggregateType = ((AggregateableFeatureInfoDisplay)display).getAggregateTypeID();
if (!aggregatableDisplayMap.containsKey(aggregateType)) {
final ArrayList<AggregateableFeatureInfoDisplay> displayList =
new ArrayList<AggregateableFeatureInfoDisplay>();
aggregatableDisplayMap.put(aggregateType, displayList);
}
aggregatableDisplayMap.get(aggregateType).add((AggregateableFeatureInfoDisplay)display);
for (final AggregateableFeatureInfoDisplay d : aggregatableDisplayMap.get(aggregateType)) {
d.setAggregatableDisplayList(aggregatableDisplayMap.get(aggregateType));
}
}
final MappingComponent mc = CismapBroker.getInstance().getMappingComponent();
final GetFeatureInfoClickDetectionListener listener = (GetFeatureInfoClickDetectionListener)
mc.getInputListener(MappingComponent.FEATURE_INFO);
if ((listener != null) && (display instanceof MultipleFeatureInfoRequestsDisplay)) {
((MultipleFeatureInfoRequestsDisplay)display).addHoldListener(listener);
}
tbpFeatureInfos.add(layer.toString(), display.getDisplayComponent());
displays.put(layer, display);
} catch (final Exception exception) {
LOG.error("Exception in creating featureInfoDisplay component", exception); // NOI18N
layer.setLayerQuerySelected(false);
}
}
}
}
/**
* This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The
* content of this method is always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
private void initComponents() {
jButton1 = new javax.swing.JButton();
tbpFeatureInfos = new javax.swing.JTabbedPane();
jButton1.setText(null);
tbpFeatureInfos.addChangeListener(new javax.swing.event.ChangeListener() {
@Override
public void stateChanged(final javax.swing.event.ChangeEvent evt) {
tbpFeatureInfosStateChanged(evt);
}
});
final org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add(
tbpFeatureInfos,
org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
400,
Short.MAX_VALUE));
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add(
org.jdesktop.layout.GroupLayout.TRAILING,
tbpFeatureInfos,
org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
300,
Short.MAX_VALUE));
} // </editor-fold>//GEN-END:initComponents
/**
* DOCUMENT ME!
*
* @param evt DOCUMENT ME!
*/
private void tbpFeatureInfosStateChanged(final javax.swing.event.ChangeEvent evt) { //GEN-FIRST:event_tbpFeatureInfosStateChanged
for (final FeatureInfoDisplay d : displays.values()) {
if ((d != null) && (d instanceof MultipleFeatureInfoRequestsDisplay)) {
final MultipleFeatureInfoRequestsDisplay multiRequestDisplay = (MultipleFeatureInfoRequestsDisplay)d;
multiRequestDisplay.setDisplayVisble(false);
}
}
final Component c = tbpFeatureInfos.getSelectedComponent();
if ((c != null) && (c instanceof MultipleFeatureInfoRequestsDisplay)) {
final MultipleFeatureInfoRequestsDisplay multiRequestDisplay = (MultipleFeatureInfoRequestsDisplay)c;
final MappingComponent mc = CismapBroker.getInstance().getMappingComponent();
final GetFeatureInfoClickDetectionListener listener = (GetFeatureInfoClickDetectionListener)
mc.getInputListener(MappingComponent.FEATURE_INFO);
if (listener != null) {
multiRequestDisplay.removeHoldListener(listener);
multiRequestDisplay.addHoldListener(listener);
}
multiRequestDisplay.setDisplayVisble(true);
} else {
final MappingComponent mc = CismapBroker.getInstance().getMappingComponent();
final GetFeatureInfoClickDetectionListener listener = (GetFeatureInfoClickDetectionListener)
mc.getInputListener(MappingComponent.FEATURE_INFO);
listener.addFeatureInfoIconForLastClick();
}
for (int i = 0; i < tbpFeatureInfos.getTabCount(); ++i) {
tbpFeatureInfos.setForegroundAt(i, null);
}
final int selectedindex = tbpFeatureInfos.getSelectedIndex();
if ((selectedindex >= 0) && (tbpFeatureInfos.getTabCount() != 0)) {
try {
tbpFeatureInfos.setForegroundAt(selectedindex, Color.blue);
} catch (Exception ex) {
if (LOG.isDebugEnabled()) {
LOG.debug("Error. Feeling not blue.", ex); // NOI18N
}
}
}
} //GEN-LAST:event_tbpFeatureInfosStateChanged
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public Map<Object, FeatureInfoDisplay> getDisplays() {
return displays;
}
@Override
public void clickedOnMap(final MapClickedEvent mce) {
if (mce.getMode().equals(GetFeatureInfoClickDetectionListener.FEATURE_INFO_MODE)) {
final Set layers = displays.keySet();
for (final Object layer : layers) {
displays.get(layer).showFeatureInfo(mce);
}
}
}
}