/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
package de.cismet.cismap.commons.gui.layerwidget;
import org.openide.util.NbBundle;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JSlider;
import javax.swing.JTable;
import javax.swing.Timer;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import de.cismet.cismap.commons.Debug;
import de.cismet.cismap.commons.LayerInfoProvider;
import de.cismet.cismap.commons.ModeLayer;
import de.cismet.cismap.commons.RetrievalServiceLayer;
import de.cismet.cismap.commons.featureservice.AbstractFeatureService;
import de.cismet.cismap.commons.featureservice.WebFeatureService;
import de.cismet.cismap.commons.featureservice.factory.AbstractFeatureFactory;
import de.cismet.cismap.commons.featureservice.factory.FeatureFactory;
import de.cismet.cismap.commons.featureservice.style.BasicStyle;
import de.cismet.cismap.commons.gui.simplelayerwidget.NewSimpleInternalLayerWidget;
import de.cismet.cismap.commons.interaction.CismapBroker;
import de.cismet.cismap.commons.interaction.events.ActiveLayerEvent;
import de.cismet.cismap.commons.raster.wms.WMSLayer;
import de.cismet.cismap.commons.raster.wms.WMSServiceLayer;
import de.cismet.cismap.commons.util.SLDStyleUtil;
import de.cismet.cismap.commons.wms.capabilities.Style;
import de.cismet.tools.CurrentStackTrace;
import de.cismet.tools.gui.StaticSwingTools;
import de.cismet.tools.gui.treetable.TreeTableModelAdapter;
/**
* DOCUMENT ME!
*
* @author thorsten.hell@cismet.de
* @version $Revision$, $Date$
*/
public class ActiveLayerTableCellRenderer extends DefaultTableCellRenderer {
//~ Static fields/initializers ---------------------------------------------
protected static final boolean DEBUG = Debug.DEBUG;
private static final Dimension ZERO_DIMENSION = new Dimension(0, 0);
//~ Instance fields --------------------------------------------------------
private javax.swing.ImageIcon styleIcon;
private javax.swing.ImageIcon unselectedStyleIcon;
private LayerWidget layerWidgetParent = null;
private NewSimpleInternalLayerWidget internalWidgetParent = null;
private JButton moreButton = new JButton("..."); // NOI18N
private JSlider slider = new JSlider(0, 100);
private JSlider slider2 = new JSlider(0, 100);
private final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(this.getClass());
private ImageIcon layersIcon;
private ImageIcon layerIcon;
private ImageIcon layersInfoIcon;
private ImageIcon layerInfoIcon;
private ImageIcon okIcon;
private ImageIcon errorIcon;
private ImageIcon refreshIcon;
private ImageIcon refreshNeededIcon;
private ImageIcon inProgressIcon;
// private Timer indeterminateProgressTimer = null;
private Map<Integer, Timer> indeterminateProgressTimers = new HashMap<Integer, Timer>();
private StyleLabel styleLabel = new StyleLabel();
private boolean isWidgetTable = false;
private JProgressBar progressBar = new JProgressBar(0, 100) {
@Override
public boolean isDisplayable() {
// This does the trick. It makes sure animation is always performed
return true;
}
};
private JProgressBar progressIndeterminate = new JProgressBar(0, 100) {
@Override
public boolean isDisplayable() {
// This does the trick. It makes sure animation is always performed
return true;
}
};
//~ Constructors -----------------------------------------------------------
/**
* Creates a new instance of ActiveLayerTableCellRenderer.
*/
public ActiveLayerTableCellRenderer() {
// progress.setUI(new MetalProgressBarUI());
// progress.setString("");progress.setStringPainted(true);
// progressIndeterminate.setUI(new MetalProgressBarUI());
// progressIndeterminate.setString("");progressIndeterminate.setStringPainted(true);
styleIcon = new javax.swing.ImageIcon(getClass().getResource(
"/de/cismet/cismap/commons/raster/wms/res/style.png")); // NOI18N
unselectedStyleIcon = new javax.swing.ImageIcon(getClass().getResource(
"/de/cismet/cismap/commons/raster/wms/res/disabledStyle.png")); // NOI18N
moreButton.setEnabled(false);
styleLabel.setOpaque(false);
styleLabel.setBackground(Color.WHITE);
// progressBar.setLayout(new BorderLayout(2, 2));
progressBar.setLayout(new GridLayout(1, 1));
slider.setOpaque(false);
progressBar.add(slider); // , BorderLayout.CENTER);
progressIndeterminate.setLayout(new BorderLayout(2, 2));
slider2.setOpaque(false);
progressIndeterminate.add(slider2, BorderLayout.CENTER);
progressIndeterminate.setIndeterminate(true);
layersIcon = new javax.swing.ImageIcon(getClass().getResource(
"/de/cismet/cismap/commons/raster/wms/res/layers.png")); // NOI18N
layerIcon = new javax.swing.ImageIcon(getClass().getResource(
"/de/cismet/cismap/commons/raster/wms/res/layer.png")); // NOI18N
layersInfoIcon = new javax.swing.ImageIcon(getClass().getResource(
"/de/cismet/cismap/commons/raster/wms/res/layers_i.png")); // NOI18N
layerInfoIcon = new javax.swing.ImageIcon(getClass().getResource(
"/de/cismet/cismap/commons/raster/wms/res/layer_i.png")); // NOI18N
okIcon = new javax.swing.ImageIcon(getClass().getResource(
"/de/cismet/cismap/commons/gui/layerwidget/res/enable30.png")); // NOI18N
errorIcon = new javax.swing.ImageIcon(getClass().getResource(
"/de/cismet/cismap/commons/gui/layerwidget/res/error.png")); // NOI18N
refreshIcon = new javax.swing.ImageIcon(getClass().getResource(
"/de/cismet/cismap/commons/gui/layerwidget/res/refresh.png")); // NOI18N
refreshNeededIcon = new javax.swing.ImageIcon(getClass().getResource(
"/de/cismet/cismap/commons/gui/layerwidget/res/refresh30.png")); // NOI18N
inProgressIcon = new javax.swing.ImageIcon(getClass().getResource(
"/de/cismet/cismap/commons/gui/layerwidget/res/inProgress.png")); // NOI18N
}
/**
* Creates a new ActiveLayerTableCellRenderer object.
*
* @param widgetTable DOCUMENT ME!
*/
public ActiveLayerTableCellRenderer(final boolean widgetTable) {
this();
this.isWidgetTable = widgetTable;
}
//~ Methods ----------------------------------------------------------------
/**
* Returns the default table cell renderer.
*
* @param table the <code>JTable</code>
* @param value the value to assign to the cell at <code>[row, column]</code>
* @param isSelected true if cell is selected
* @param hasFocus true if cell has focus
* @param row the row of the cell to render
* @param column the column of the cell to render
*
* @return the default table cell renderer
*/
@Override
public Component getTableCellRendererComponent(final JTable table,
final Object value,
final boolean isSelected,
final boolean hasFocus,
final int row,
final int column) {
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(value + ": column=" + column);
}
}
if (value instanceof ModeLayer) {
return getTableCellRendererComponent(
table,
((ModeLayer)value).getCurrentLayer(),
isSelected,
hasFocus,
row,
column);
}
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(value + ": column=" + column + ", crw=" + row, new CurrentStackTrace());
}
}
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
final int realColumn = table.convertColumnIndexToModel(column);
final int realRow = table.convertRowIndexToModel(row);
final TableCellRenderer booleanRenderer = table.getDefaultRenderer(Boolean.class);
final TableCellRenderer stringRenderer = table.getDefaultRenderer(String.class);
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(value + ": realColumn=" + realColumn + ", realRow=" + realRow, new CurrentStackTrace());
}
}
setToolTipText(null);
if (!isWidgetTable) {
if (layerWidgetParent == null) {
layerWidgetParent = StaticSwingTools.findSpecificParentComponent(table, LayerWidget.class);
layerWidgetParent.setErrorImage(null);
} else {
layerWidgetParent.setErrorImage(null);
}
} else {
if (internalWidgetParent == null) {
internalWidgetParent = StaticSwingTools.findSpecificParentComponent(
table,
NewSimpleInternalLayerWidget.class);
internalWidgetParent.setErrorImage(null);
} else {
internalWidgetParent.setErrorImage(null);
}
}
if (realColumn == 0) {
setText(""); // NOI18N
// label.setIconTextGap(4);
setHorizontalAlignment(JLabel.CENTER);
if (value instanceof RetrievalServiceLayer) {
final int progress = ((RetrievalServiceLayer)value).getProgress();
if (((RetrievalServiceLayer)value).isRefreshNeeded()) {
if (DEBUG) {
log.warn(value + " isRefreshNeeded"); // NOI18N
}
setIcon(refreshNeededIcon);
} else if ((progress > 0) && (progress < 100)) {
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(value + " isInProgress"); // NOI18N
}
}
setIcon(inProgressIcon);
} else if (((RetrievalServiceLayer)value).hasErrors()) {
if (DEBUG) {
log.warn(value + " has errors"); // NOI18N
}
setIcon(errorIcon);
if (((RetrievalServiceLayer)value).getErrorObject() instanceof Image) {
if (!isWidgetTable) {
if (layerWidgetParent == null) {
layerWidgetParent = StaticSwingTools.findSpecificParentComponent(
table,
LayerWidget.class);
layerWidgetParent.setErrorImage((Image)((RetrievalServiceLayer)value).getErrorObject());
} else {
layerWidgetParent.setErrorImage((Image)((RetrievalServiceLayer)value).getErrorObject());
}
} else {
if (internalWidgetParent == null) {
internalWidgetParent = StaticSwingTools.findSpecificParentComponent(
table,
NewSimpleInternalLayerWidget.class);
internalWidgetParent.setErrorImage((Image)((RetrievalServiceLayer)value)
.getErrorObject());
} else {
internalWidgetParent.setErrorImage((Image)((RetrievalServiceLayer)value)
.getErrorObject());
}
}
setToolTipText(org.openide.util.NbBundle.getMessage(
ActiveLayerTableCellRenderer.class,
"ActiveLayerTableCellRenderer.toolTipText")); // NOI18N
} else if (((RetrievalServiceLayer)value).getErrorObject() instanceof String) {
setToolTipText(((RetrievalServiceLayer)value).getErrorObject().toString());
}
} else {
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(value + " isFinished"); // NOI18N
}
}
setIcon(okIcon);
}
}
} else if (realColumn == 2) {
setText(""); // NOI18N
setIcon(null);
if (value instanceof WMSServiceLayer) {
if (((WMSServiceLayer)value).getWMSLayers().size() > 1) {
setText(""); // NOI18N
} else {
setHorizontalAlignment(JLabel.LEFT);
setText(""); // NOI18N
// label.setIconTextGap(4);
Style selectedStyle = null;
String styleName = null;
int styleCount = 0;
// Kann nur ein WMSLayer haben (wegen Bedingung weiter oben)
final List<WMSLayer> wmsLayers = ((WMSServiceLayer)value).getWMSLayers();
if (!((WMSServiceLayer)value).isDummy() && !wmsLayers.isEmpty()) {
selectedStyle = wmsLayers.get(0).getSelectedStyle();
styleCount = wmsLayers.get(0).getOgcCapabilitiesLayer().getStyles().length;
} else if (!wmsLayers.isEmpty()) {
styleName = wmsLayers.get(0).getStyleName();
}
if (selectedStyle != null) {
styleName = selectedStyle.getTitle();
}
if (styleName != null) {
setText(styleName);
}
if (styleCount <= 1) {
setIcon(unselectedStyleIcon);
} else {
setIcon(styleIcon);
}
}
} else if (value instanceof AbstractFeatureService) {
// final Color bg = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row,
// column).getBackground(); return temp;
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(value + " getStyleLabel (" + realRow + ", " + realColumn + ")"); // NOI18N
}
}
if (log.isDebugEnabled()) {
log.debug("is it null? " + ((AbstractFeatureService)value).getLayerProperties());
}
final AbstractFeatureService service = (AbstractFeatureService)value;
final FeatureFactory ff = service.getFeatureFactory();
BasicStyle basicStyle = null;
if (ff instanceof AbstractFeatureFactory) {
final AbstractFeatureFactory aff = (AbstractFeatureFactory)ff;
final List<org.deegree.style.se.unevaluated.Style> styleList = aff.getStyle(aff.layerName);
basicStyle = SLDStyleUtil.getBasicStyleFromSLDStyle(styleList);
}
if ((service.getLayerProperties() != null)
&& (service.getLayerProperties().getAttributeTableRuleSet() != null)
&& (service.getLayerProperties().getAttributeTableRuleSet().getFeatureClass() != null)) {
setHorizontalAlignment(JLabel.LEFT);
setText(NbBundle.getMessage(
ActiveLayerTableCellRenderer.class,
"ActiveLayerTableCellRenderer.getTableCellRendererComponent().customStyle"));
setIcon(unselectedStyleIcon);
} else {
if (basicStyle != null) {
styleLabel.style = basicStyle;
} else {
if (((AbstractFeatureService)value).getLayerProperties() != null) {
styleLabel.style = ((AbstractFeatureService)value).getLayerProperties().getStyle();
}
}
styleLabel.repaint();
return styleLabel;
}
}
} else if (realColumn == 3) {
final WMSLayer wmsLayer = null;
setText(""); // NOI18N
setIcon(null);
setHorizontalAlignment(JLabel.LEFT);
// if (value instanceof WMSServiceLayer && ((WMSServiceLayer) value).getWMSLayers().size() > 1) {
// } else {
// if (value instanceof WMSServiceLayer && ((WMSServiceLayer) value).getWMSLayers().size() == 1) {
// wmsLayer = ((WMSLayer) ((WMSServiceLayer) value).getWMSLayers().get(0));
// } else if (value instanceof WMSLayer) {
// wmsLayer = (WMSLayer) value;
// }
// if (wmsLayer != null && wmsLayer.getOgcCapabilitiesLayer().isQueryable()) {
// return booleanRenderer.getTableCellRendererComponent(table, new Boolean(wmsLayer.isQuerySelected()), isSelected, hasFocus, row, column);
// } else {
// setIcon(null);
// setText("");//NOI18N
// }
// }
if ((value instanceof LayerInfoProvider) && ((LayerInfoProvider)value).isQueryable()) {
return booleanRenderer.getTableCellRendererComponent(
table,
((LayerInfoProvider)value).isLayerQuerySelected(),
isSelected,
hasFocus,
row,
column);
} else {
setIcon(null);
setText(""); // NOI18N
}
} else if (realColumn == 4) {
// Component returnComp = null;
if (value instanceof RetrievalServiceLayer) {
slider.setValue((int)(((RetrievalServiceLayer)value).getTranslucency() * 100));
slider2.setValue((int)(((RetrievalServiceLayer)value).getTranslucency() * 100));
this.slider.updateUI();
this.slider2.updateUI();
final int currentProgress = ((RetrievalServiceLayer)value).getProgress();
// -1: progress is indeterminate
if ((currentProgress == -1) && ((RetrievalServiceLayer)value).isEnabled()
&& !((RetrievalServiceLayer)value).isRefreshNeeded()) {
if (indeterminateProgressTimers.get(realRow) == null) {
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug("new indeterminateProgressTimers[" + realRow + "] created"); // NOI18N
}
}
indeterminateProgressTimers.put(realRow, new Timer(30, new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final int currentProgress = ((RetrievalServiceLayer)value).getProgress();
// redraw only progress bar column (indeterminate)
((TreeTableModelAdapter)(table.getModel())).fireTableCellUpdated(
realRow,
realColumn);
if ((currentProgress == 0) || (currentProgress == 100)) {
final Timer timer = indeterminateProgressTimers.get(realRow);
timer.stop();
timer.setRepeats(false);
indeterminateProgressTimers.remove(realRow);
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(
value
+ ": indeterminateProgressTimer["
+ realRow
+ "] stopped from Timer"); // NOI18N
}
}
// redraw all columns (including status icon)
final TableModelEvent evt = new TableModelEvent(
table.getModel(),
realRow,
realRow,
TableModelEvent.UPDATE);
((TreeTableModelAdapter)(table.getModel())).fireTableChanged(evt);
}
}
}));
}
if (!indeterminateProgressTimers.get(realRow).isRunning()) {
// this.progressBar.invalidate();
final Timer timer = indeterminateProgressTimers.get(realRow);
timer.start();
timer.setRepeats(true);
}
// In this scenario of displaying a JSlider in a JProgressBar as renderer for a table cell, the
// JSlider component resizes sloppy. But only the JSlider in the firt row shows this effect. If you
// don't set the size of the JSlider you easily can reconstruct this effect by forcing the layer
// widget to resize with the help of the docking framework. See
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7092176 for more details.
this.slider2.setSize(ZERO_DIMENSION);
this.slider2.updateUI();
return progressIndeterminate;
} else {
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(value + ": getProgress(): " + currentProgress + " (realColumn=" + realColumn
+ ", realRow=" + realRow + ") (column=" + column + ", row=" + row + ")"); // NOI18N
}
}
this.progressBar.setValue(currentProgress);
if ((indeterminateProgressTimers.get(realRow) != null)
&& ((currentProgress == 100) || (currentProgress == 0))) {
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(value + ": indeterminateProgressTimer[" + realRow
+ "] stopped from Renderer"); // NOI18N
}
}
final Timer timer = indeterminateProgressTimers.get(realRow);
timer.setRepeats(false);
timer.stop();
indeterminateProgressTimers.remove(realRow);
if (DEBUG) {
if (log.isDebugEnabled()) {
log.debug(value + " indeterminateProgressTimer [" + realRow + "] stopped"); // NOI18N
}
}
// redraw all columns (including status icon)
final TableModelEvent evt = new TableModelEvent(table.getModel(),
realRow,
realRow,
TableModelEvent.UPDATE);
((TreeTableModelAdapter)(table.getModel())).fireTableChanged(evt);
}
}
// TableModelEvent evt = new TableModelEvent(table.getModel(), realRow, realRow,
// TableModelEvent.UPDATE); ((TreeTableModelAdapter) (table.getModel())).fireTableChanged(evt);
// In this scenario of displaying a JSlider in a JProgressBar as renderer for a table cell, the JSlider
// component resizes sloppy. But only the JSlider in the firt row shows this effect. If you don't set
// the size of the JSlider you easily can reconstruct this effect by forcing the layer widget to resize
// with the help of the docking framework.
// See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7092176 for more details.
this.slider.setSize(ZERO_DIMENSION);
this.slider.updateUI();
return this.progressBar;
} else {
setIcon(null);
setText(""); // NOI18N
}
// return new JLabel("turned off");
} else if (realColumn == 5) {
if (value instanceof WMSServiceLayer) {
moreButton.setEnabled(false);
} else if (value instanceof WebFeatureService) {
moreButton.setEnabled(true);
}
return moreButton;
} else {
setIcon(null);
setText(""); // NOI18N
}
return this;
}
//~ Inner Classes ----------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private class StyleLabel extends JLabel {
//~ Instance fields ----------------------------------------------------
protected de.cismet.cismap.commons.featureservice.style.Style style;
//~ Methods ------------------------------------------------------------
// paint style-rectangle inside the button that creates the StyleDialog
@Override
protected void paintComponent(final Graphics g) {
try {
if (style != null) {
final Graphics2D g2d = (Graphics2D)g;
g.setColor(ActiveLayerTableCellRenderer.this.getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
if (style.isDrawFill() && (style.getFillColor() != null)) {
g2d.setColor((Color)style.getFillColor());
g2d.fillRect(10, 4, getWidth() - 20, getHeight() - 8);
}
if (style.isDrawLine() && (style.getLineColor() != null)) {
g2d.setColor((Color)style.getLineColor());
final float width = new Float(Math.min(3.0f, style.getLineWidth())).intValue();
g2d.setStroke(new BasicStroke(width));
g2d.drawRect(10, 4, getWidth() - 20, getHeight() - 8);
}
}
} catch (Exception ex) {
}
}
}
}