/*************************************************** * * cismet GmbH, Saarbruecken, Germany * * ... and it just works. * ****************************************************/ package de.cismet.cismap.commons.gui.infowidgets; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.EventQueue; import java.awt.Image; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.border.EmptyBorder; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; import de.cismet.cismap.commons.interaction.ActiveLayerListener; import de.cismet.cismap.commons.interaction.StatusListener; import de.cismet.cismap.commons.interaction.events.ActiveLayerEvent; import de.cismet.cismap.commons.interaction.events.StatusEvent; import de.cismet.cismap.commons.raster.wms.SlidableWMSServiceLayerGroup; import de.cismet.cismap.commons.raster.wms.WMSLayer; import de.cismet.cismap.commons.raster.wms.WMSServiceLayer; import de.cismet.cismap.commons.raster.wms.simple.SimpleLegendProvider; import de.cismet.cismap.commons.rasterservice.ImageRetrieval; import de.cismet.cismap.commons.retrieval.RetrievalEvent; import de.cismet.cismap.commons.retrieval.RetrievalListener; import de.cismet.cismap.commons.wms.capabilities.WMSCapabilities; import de.cismet.tools.gui.StaticSwingTools; /** * DOCUMENT ME! * * @author thorsten.hell@cismet.de * @version $Revision$, $Date$ */ public class Legend extends javax.swing.JPanel implements ActiveLayerListener, StatusListener { //~ Instance fields -------------------------------------------------------- private int maxWidth = 0; private final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(this.getClass()); private HashMap<String, WMSCapabilities> wmsCapabilities = new HashMap<String, WMSCapabilities>(); private LegendModel tableModel = new LegendModel(); // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JScrollPane scpLegends; private javax.swing.JTable tblLegends; // End of variables declaration//GEN-END:variables //~ Constructors ----------------------------------------------------------- /** * Creates new form Legend. */ public Legend() { initComponents(); this.setLayout(new BorderLayout()); tblLegends.setModel(tableModel); tblLegends.setTableHeader(null); tblLegends.setDefaultRenderer(LegendPanel.class, new CustomCellRenderer()); tblLegends.setShowHorizontalLines(false); tblLegends.setBorder(new EmptyBorder(0, 0, 0, 0)); tblLegends.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tblLegends.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); scpLegends = new JScrollPane(tblLegends); StaticSwingTools.setNiftyScrollBars(scpLegends); add(scpLegends, BorderLayout.CENTER); } //~ Methods ---------------------------------------------------------------- /** * DOCUMENT ME! * * @param url DOCUMENT ME! * @param layername DOCUMENT ME! */ public void addLegend(final String url, final String layername) { tableModel.addLegend(url, layername); } /*public void addLegend(final BufferedImage img, final String layername) { * tableModel.addLegend(img, layername);}*/ /*public void addLegend(final BufferedImage img, final String layername) { * tableModel.addLegend(img, layername);}*/ /*public void addLegend(final BufferedImage img, final String layername) { * tableModel.addLegend(img, layername);}*/ /*public void addLegend(final BufferedImage img, final String layername) { * tableModel.addLegend(img, layername);}*/ /*public void addLegend(final BufferedImage img, final String layername) { * tableModel.addLegend(img, layername);}*/ /*public void addLegend(final BufferedImage img, final String layername) { * tableModel.addLegend(img, layername);}*/ /*public void addLegend(final BufferedImage img, final String layername) { * tableModel.addLegend(img, layername);}*/ /*public void addLegend(final BufferedImage img, final String layername) { * tableModel.addLegend(img, layername);}*/ /** * DOCUMENT ME! * * @param layerurl DOCUMENT ME! */ public void removeLegendByUrl(final String layerurl) { tableModel.removeLegendByUrl(layerurl); } /** * DOCUMENT ME! * * @param url DOCUMENT ME! */ public void scrollToLegend(final String url) { final int pos = tableModel.getPosition(url); if (pos != -1) { StaticSwingTools.jTableScrollToVisible(tblLegends, pos, 0); if (log.isDebugEnabled()) { log.debug(tblLegends.getSelectionModel().getValueIsAdjusting()); } if (!tblLegends.getSelectionModel().isSelectedIndex(pos)) { tblLegends.getSelectionModel().setSelectionInterval(pos, pos); } } else { tblLegends.getSelectionModel().clearSelection(); } } @Override public void layerVisibilityChanged(final ActiveLayerEvent e) { } @Override public void layerAvailabilityChanged(final ActiveLayerEvent e) { } @Override public void layerRemoved(final ActiveLayerEvent e) { if (log.isDebugEnabled()) { log.debug("layerRemoved() fired"); // NOI18N } if (e.getLayer() instanceof WMSServiceLayer) { removeWmsServiceLayer((WMSServiceLayer)e.getLayer()); } else if (e.getLayer() instanceof WMSLayer) { removeWMSLayer((WMSLayer)e.getLayer()); } else if (e.getLayer() instanceof SimpleLegendProvider) { final SimpleLegendProvider slp = (SimpleLegendProvider)e.getLayer(); removeLegendByUrl(slp.getLegendUrl()); } else if (e.getLayer() instanceof SlidableWMSServiceLayerGroup) { final SlidableWMSServiceLayerGroup wmsLayer = (SlidableWMSServiceLayerGroup)e.getLayer(); final List v = wmsLayer.getLayers(); final Iterator it = v.iterator(); if (it.hasNext()) { final Object elem = it.next(); if (elem instanceof WMSServiceLayer) { removeWmsServiceLayer((WMSServiceLayer)elem); } } } /*else if(e.getLayer() instanceof * ServiceLayer) { * removeLegendByName(((ServiceLayer)e.getLayer()).getName());}*/ else { log.warn("For this type no legend can be created. " + e.getLayer()); // NOI18N } } /** * DOCUMENT ME! * * @param wmsLayer DOCUMENT ME! */ private void removeWmsServiceLayer(final WMSServiceLayer wmsLayer) { final List v = wmsLayer.getWMSLayers(); final Iterator it = v.iterator(); while (it.hasNext()) { final Object elem = it.next(); if (elem instanceof WMSLayer) { final WMSLayer wl = (WMSLayer)elem; removeWMSLayer(wl); } } } /** * DOCUMENT ME! * * @param wl DOCUMENT ME! */ private void removeWMSLayer(final WMSLayer wl) { assert (wl != null); if (wl.getOgcCapabilitiesLayer() == null) { if (log.isDebugEnabled()) { log.debug( "in removeWMSLayer waren die capabilities null. kann die Legende nicht entferenen. Wahrscheinlich war deshalb auch gar keine drin. "); } } else { final String title = wl.getOgcCapabilitiesLayer().getTitle(); String url = null; try { final URL[] lua = wl.getSelectedStyle().getLegendURL(); url = lua[0].toString(); } catch (final Exception t) { if (log.isDebugEnabled()) { log.debug("Could not find a legend for " + title, t); // NOI18N } } if (url != null) { this.removeLegendByUrl(url); } } } @Override public void layerSelectionChanged(final ActiveLayerEvent e) { if (log.isDebugEnabled()) { log.debug("layerSelectionChanged() fired"); // NOI18N } if ((e.getLayer() instanceof WMSLayer) || (e.getLayer() instanceof WMSServiceLayer) || (e.getLayer() instanceof SlidableWMSServiceLayerGroup)) { WMSLayer layer = null; if (e.getLayer() instanceof WMSLayer) { layer = (WMSLayer)e.getLayer(); } else if ((e.getLayer() instanceof WMSServiceLayer) && (((WMSServiceLayer)e.getLayer()).getWMSLayers().size() == 1)) { layer = (WMSLayer)((WMSServiceLayer)e.getLayer()).getWMSLayers().get(0); } else if ((e.getLayer() instanceof SlidableWMSServiceLayerGroup) && (((SlidableWMSServiceLayerGroup)e.getLayer()).getLayers().size() > 0)) { final WMSServiceLayer sLayer = ((SlidableWMSServiceLayerGroup)e.getLayer()).getLayers().get(0); if (sLayer.getWMSLayers().size() == 1) { layer = (WMSLayer)sLayer.getWMSLayers().get(0); } } try { if (!layer.isDummy()) { scrollToLegend(layer.getSelectedStyle().getLegendURL()[0].toString()); } } catch (Exception ex) { if (log.isDebugEnabled()) { log.debug("Cannot scroll to legend of " + e.getLayer(), ex); // NOI18N } } } else if (e.getLayer() instanceof SimpleLegendProvider) { final SimpleLegendProvider slp = (SimpleLegendProvider)e.getLayer(); scrollToLegend(slp.getLegendUrl()); } } @Override public void layerPositionChanged(final ActiveLayerEvent e) { if (log.isDebugEnabled()) { log.debug("layerPositionChanged() fired"); // NOI18N } } @Override public void layerAdded(final ActiveLayerEvent e) { if (log.isDebugEnabled()) { log.debug("layerAdded() fired"); // NOI18N } if (e.getLayer() instanceof WMSServiceLayer) { addWmsServiceLayer((WMSServiceLayer)e.getLayer()); } else if (e.getLayer() instanceof SimpleLegendProvider) { final SimpleLegendProvider slp = (SimpleLegendProvider)e.getLayer(); this.addLegend(slp.getLegendUrl(), slp.getLegendIdentifier()); } else if (e.getLayer() instanceof SlidableWMSServiceLayerGroup) { final SlidableWMSServiceLayerGroup wmsLayer = (SlidableWMSServiceLayerGroup)e.getLayer(); final List v = wmsLayer.getLayers(); final Iterator it = v.iterator(); if (it.hasNext()) { final Object elem = it.next(); if (elem instanceof WMSServiceLayer) { addWmsServiceLayer((WMSServiceLayer)elem); } } } /*else if (e.getLayer() instanceof * SLDStyledLayer) { final * SLDStyledLayer sldLayer = * (SLDStyledLayer) e.getLayer(); * Pair<Integer, Integer> size = * sldLayer.getLegendSize(); * BufferedImage legendImage = new * BufferedImage(size.first, * size.second, * BufferedImage.TYPE_4BYTE_ABGR); * sldLayer.getLegend(legendImage.getWidth(), * legendImage.getHeight(), * legendImage.createGraphics()); * addLegend(legendImage, * ((ServiceLayer)e.getLayer()).getName());} */ else { log.warn("For this type no legend can be created. " + e.getLayer()); // NOI18N } } /** * DOCUMENT ME! * * @param wmsLayer DOCUMENT ME! */ private void addWmsServiceLayer(final WMSServiceLayer wmsLayer) { if (!wmsLayer.isDummy()) { final List v = wmsLayer.getWMSLayers(); final Iterator it = v.iterator(); while (it.hasNext()) { final Object elem = it.next(); if (elem instanceof WMSLayer) { final WMSLayer wl = (WMSLayer)elem; final String title = wl.getOgcCapabilitiesLayer().getTitle(); final String name = wl.getOgcCapabilitiesLayer().getName(); String url = null; try { final URL[] lua = wl.getSelectedStyle().getLegendURL(); url = lua[0].toString(); } catch (final Exception t) { if (log.isDebugEnabled()) { log.debug("Could not find legend for " + title, t); // NOI18N } } if (url != null) { wmsCapabilities.put(url, wmsLayer.getWmsCapabilities()); this.addLegend(url, name); if (log.isDebugEnabled()) { log.debug("added legend:" + name + "=" + url); // NOI18N } } } } } } @Override public void layerInformationStatusChanged(final ActiveLayerEvent e) { } /** * 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() { scpLegends = new javax.swing.JScrollPane(); tblLegends = new javax.swing.JTable(); scpLegends.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); scpLegends.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); scpLegends.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); scpLegends.setDoubleBuffered(true); tblLegends.setBackground(new java.awt.Color(236, 233, 216)); tblLegends.setModel(new javax.swing.table.DefaultTableModel( new Object[][] { { null } }, new String[] { "Title 1" })); setLayout(new java.awt.BorderLayout()); setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 1, 5, 1)); } // </editor-fold>//GEN-END:initComponents @Override public void statusValueChanged(final StatusEvent e) { if (e.getName().equals(StatusEvent.AWAKED_FROM_DUMMY)) { if (e.getValue() instanceof WMSServiceLayer) { addWmsServiceLayer((WMSServiceLayer)e.getValue()); } } } //~ Inner Classes ---------------------------------------------------------- /** * DOCUMENT ME! * * @version $Revision$, $Date$ */ private class LegendPanel extends JPanel implements RetrievalListener { //~ Instance fields ---------------------------------------------------- JLabel lblImage = new JLabel(); private String url = ""; // NOI18N //~ Constructors ------------------------------------------------------- /** * Creates a new LegendPanel object. */ public LegendPanel() { super(); setBorder(new EmptyBorder(2, 2, 2, 2)); setLayout(new BorderLayout()); add(lblImage, BorderLayout.CENTER); lblImage.setHorizontalAlignment(JLabel.LEADING); lblImage.setVerticalAlignment(JLabel.CENTER); } /** * Creates a new LegendPanel object. * * @param url DOCUMENT ME! */ public LegendPanel(final String url) { this(); this.url = url; refresh(); } /*public LegendPanel(final BufferedImage img) { * this(); lblImage.setText(""); // NOI18N lblImage.setIcon(new ImageIcon(img)); * tableModel.fireTableDataChanged(); int newWidth = img.getWidth(null); if (newWidth < * tblLegends.getPreferredSize().width) { newWidth = tblLegends.getPreferredSize().width; } else { * maxWidth = newWidth; } tblLegends.getColumnModel().getColumn(0).setPreferredWidth(newWidth);}*/ //~ Methods ------------------------------------------------------------ /** * DOCUMENT ME! * * @param r DOCUMENT ME! */ private void dispatch(final Runnable r) { if (EventQueue.isDispatchThread()) { r.run(); } else { EventQueue.invokeLater(r); } } /** * DOCUMENT ME! */ public final void refresh() { final ImageRetrieval ir = new ImageRetrieval(this); ir.setUrl(url); ir.setWMSCapabilities(wmsCapabilities.get(url)); ir.setPriority(Thread.NORM_PRIORITY); ir.start(); } @Override public void retrievalStarted(final RetrievalEvent e) { final Runnable r = new Runnable() { @Override public void run() { lblImage.setIcon(null); lblImage.setText("..."); // NOI18N if (maxWidth > 0) { tblLegends.getColumnModel().getColumn(0).setPreferredWidth(maxWidth); } tableModel.fireTableDataChanged(); } }; dispatch(r); } @Override public void retrievalProgress(final RetrievalEvent e) { } @Override public void retrievalError(final RetrievalEvent e) { final Runnable r = new Runnable() { @Override public void run() { lblImage.setText(""); // NOI18N log.error("Error while loading legend."); // NOI18N tableModel.fireTableDataChanged(); } }; dispatch(r); } @Override public void retrievalComplete(final RetrievalEvent e) { if (e.getRetrievedObject() instanceof Image) { final Image image = (Image)e.getRetrievedObject(); final ImageIcon ii = new ImageIcon(image); final Runnable r = new Runnable() { @Override public void run() { lblImage.setText(""); // NOI18N lblImage.setIcon(ii); tableModel.fireTableDataChanged(); int newWidth = image.getWidth(null) + 10; // because of the border and stuff of the JTable if (newWidth < tblLegends.getPreferredSize().width) { newWidth = tblLegends.getPreferredSize().width; } else { maxWidth = newWidth; } tblLegends.getColumnModel().getColumn(0).setPreferredWidth(newWidth); } }; dispatch(r); } } @Override public void retrievalAborted(final RetrievalEvent e) { final Runnable r = new Runnable() { @Override public void run() { lblImage.setText(""); // NOI18N } }; dispatch(r); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public String getUrl() { return url; } /** * DOCUMENT ME! * * @param url DOCUMENT ME! */ public void setUrl(final String url) { this.url = url; } @Override public boolean equals(final Object tester) { if (tester instanceof LegendPanel) { final LegendPanel t = (LegendPanel)tester; return t.url.equals(url); } else { return false; } } } /** * DOCUMENT ME! * * @version $Revision$, $Date$ */ private class CustomCellRenderer implements TableCellRenderer { //~ Methods ------------------------------------------------------------ /** * Returns the component used for drawing the cell. This method is used to configure the renderer appropriately * before drawing. * * @param table the <code>JTable</code> that is asking the renderer to draw; can be <code>null</code> * @param value the value of the cell to be rendered. It is up to the specific renderer to interpret and * draw the value. For example, if <code>value</code> is the string "true", it could be * rendered as a string or it could be rendered as a check box that is checked. <code> * null</code> is a valid value * @param isSelected true if the cell is to be rendered with the selection highlighted; otherwise false * @param hasFocus if true, render cell appropriately. For example, put a special border on the cell, if * the cell can be edited, render in the color used to indicate editing * @param row the row index of the cell being drawn. When drawing the header, the value of <code> * row</code> is -1 * @param column the column index of the cell being drawn * * @return DOCUMENT ME! */ @Override public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) { final Component component = (Component)value; if (isSelected) { component.setBackground(Color.white); // javax.swing.UIManager.getDefaults().getColor("Table.highlight")); component.setForeground(Legend.this.getForeground()); } else { component.setBackground(Legend.this.getBackground()); component.setForeground(Legend.this.getForeground()); } if (table.getRowHeight(row) != (int)component.getPreferredSize().getHeight()) { table.setRowHeight(row, (int)component.getPreferredSize().getHeight()); } return component; } } /** * DOCUMENT ME! * * @version $Revision$, $Date$ */ private class LegendModel extends AbstractTableModel { //~ Instance fields ---------------------------------------------------- private List<LegendPanel> panels = new ArrayList<LegendPanel>(); private HashMap<String, LegendPanel> panelsByUrl = new HashMap<String, LegendPanel>(); //~ Methods ------------------------------------------------------------ @Override public Class<?> getColumnClass(final int columnIndex) { return LegendPanel.class; } @Override public int getRowCount() { return panels.size(); } @Override public Object getValueAt(final int row, final int column) { return panels.get(panels.size() - 1 - row); } @Override public int getColumnCount() { return 1; } /** * DOCUMENT ME! * * @param url DOCUMENT ME! * @param name DOCUMENT ME! */ public void addLegend(final String url, final String name) { final LegendPanel lp = new LegendPanel(url); if (!panels.contains(lp)) { panels.add(lp); panelsByUrl.put(url, lp); } EventQueue.invokeLater(new Runnable() { @Override public void run() { LegendModel.super.fireTableStructureChanged(); } }); } /** * DOCUMENT ME! * * @param url layerurl DOCUMENT ME! */ public void removeLegendByUrl(final String url) { if (panelsByUrl.containsKey(url)) { final LegendPanel lp = new LegendPanel(url); if (panels.contains(lp)) { panels.remove(new LegendPanel(url)); panelsByUrl.remove(url); final int index = panels.indexOf(lp); super.fireTableRowsDeleted(index, index); } } } @Override public boolean isCellEditable(final int row, final int column) { return false; } /** * DOCUMENT ME! * * @param url DOCUMENT ME! * * @return DOCUMENT ME! */ public int getPosition(final String url) { final LegendPanel lp = panelsByUrl.get(url); return panels.size() - 1 - panels.indexOf(lp); } } }