/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2007 - 2009, Johann Sorel
* (C) 2010 - 2013, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.gui.swing.propertyedit;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import org.geotoolkit.factory.FactoryFinder;
import org.geotoolkit.gui.swing.util.ActionCell;
import org.geotoolkit.gui.swing.resource.IconBundle;
import org.geotoolkit.gui.swing.resource.MessageBundle;
import org.geotoolkit.gui.swing.style.JTextExpressionPane;
import org.geotoolkit.map.FeatureMapLayer;
import org.geotoolkit.map.FeatureMapLayer.DimensionDef;
import org.geotoolkit.map.MapLayer;
import org.apache.sis.referencing.crs.DefaultEngineeringCRS;
import org.apache.sis.referencing.cs.AbstractCS;
import org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
import org.apache.sis.referencing.datum.DefaultEngineeringDatum;
import org.apache.sis.util.iso.SimpleInternationalString;
import org.geotoolkit.font.FontAwesomeIcons;
import org.geotoolkit.font.IconBuilder;
import org.netbeans.swing.outline.DefaultOutlineModel;
import org.netbeans.swing.outline.Outline;
import org.netbeans.swing.outline.OutlineModel;
import org.netbeans.swing.outline.RenderDataProvider;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.datum.EngineeringDatum;
import org.apache.sis.measure.Units;
/**
* layer general information panel
*
* @author Johann Sorel
* @author Cédric Briançon (Geomatys)
* @module
*/
public class LayerGeneralPanel extends AbstractPropertyPane {
private MapLayer layer = null;
private static final ImageIcon ICON_DELETE = IconBuilder.createIcon(FontAwesomeIcons.ICON_TRASH_O, 16, FontAwesomeIcons.DEFAULT_COLOR);
/** Creates new form LayerGeneralPanel */
public LayerGeneralPanel() {
super(MessageBundle.format("property_general_title"),null,null,MessageBundle.format("property_general_title"));
initComponents();
guiTable.setDefaultRenderer(LayerGeneralTableRowModel.CrsCookie.class, new CrsRenderer());
guiTable.setDefaultRenderer(LayerGeneralTableRowModel.LowerCookie.class, new ExpressionLowerRenderer());
guiTable.setDefaultRenderer(LayerGeneralTableRowModel.UpperCookie.class, new ExpressionUpperRenderer());
guiTable.setDefaultRenderer(LayerGeneralTableRowModel.DeleteCookie.class, new ActionCell.Renderer(ICON_DELETE));
guiTable.setDefaultEditor(LayerGeneralTableRowModel.DeleteCookie.class, new ActionCell.Editor(ICON_DELETE) {
@Override
public void actionPerformed(final ActionEvent e, Object value) {
if (value instanceof DefaultMutableTreeNode){
value = ((DefaultMutableTreeNode)value).getUserObject();
}
if (value instanceof DimensionDef) {
final DimensionDef dimDef = (DimensionDef)value;
removeDimensionFromLayer(dimDef);
updateTableModel();
}
}
});
guiTable.setRenderDataProvider(new DimensionRenderer());
guiTable.setFillsViewportHeight(true);
guiTable.setShowVerticalLines(false);
updateTableModel();
}
private void removeDimensionFromLayer(final DimensionDef dimension) {
if (!(layer instanceof FeatureMapLayer)) {
return;
}
final FeatureMapLayer fml = (FeatureMapLayer)layer;
fml.getExtraDimensions().remove(dimension);
}
/** 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() {
jLabel15 = new JLabel();
gui_jtf_name = new JTextField();
jPanelDimensions = new JPanel();
jPanelAddDimension = new JPanel();
guiTextExpressionUpper = new JTextExpressionPane();
guiTextExpressionLower = new JTextExpressionPane();
jLabel1 = new JLabel();
jLabel2 = new JLabel();
jLabel3 = new JLabel();
guiBtnAddDimension = new JButton();
guiCrsName = new JTextField();
jScrollPane1 = new JScrollPane();
guiTable = new Outline();
jLabel15.setFont(jLabel15.getFont().deriveFont(jLabel15.getFont().getStyle() | Font.BOLD));
jLabel15.setText(MessageBundle.format("property_title")); // NOI18N
jPanelDimensions.setName("New attribute"); // NOI18N
jLabel1.setText("Crs");
jLabel2.setText("lower");
jLabel3.setText("upper");
guiBtnAddDimension.setText(MessageBundle.format("add_dimension")); // NOI18N
guiBtnAddDimension.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
guiBtnAddDimensionActionPerformed(evt);
}
});
GroupLayout jPanelAddDimensionLayout = new GroupLayout(jPanelAddDimension);
jPanelAddDimension.setLayout(jPanelAddDimensionLayout);
jPanelAddDimensionLayout.setHorizontalGroup(
jPanelAddDimensionLayout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanelAddDimensionLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelAddDimensionLayout.createParallelGroup(Alignment.TRAILING, false)
.addComponent(guiBtnAddDimension, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanelAddDimensionLayout.createSequentialGroup()
.addGroup(jPanelAddDimensionLayout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanelAddDimensionLayout.createSequentialGroup()
.addGroup(jPanelAddDimensionLayout.createParallelGroup(Alignment.LEADING)
.addComponent(jLabel1)
.addComponent(jLabel2))
.addGap(20, 20, 20))
.addGroup(Alignment.TRAILING, jPanelAddDimensionLayout.createSequentialGroup()
.addComponent(jLabel3)
.addGap(18, 18, 18)))
.addGroup(jPanelAddDimensionLayout.createParallelGroup(Alignment.LEADING, false)
.addComponent(guiTextExpressionUpper, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(guiTextExpressionLower, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(guiCrsName))))
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanelAddDimensionLayout.setVerticalGroup(
jPanelAddDimensionLayout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanelAddDimensionLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelAddDimensionLayout.createParallelGroup(Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(guiCrsName, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(jPanelAddDimensionLayout.createParallelGroup(Alignment.LEADING)
.addComponent(jLabel2)
.addComponent(guiTextExpressionLower, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(jPanelAddDimensionLayout.createParallelGroup(Alignment.LEADING)
.addComponent(guiTextExpressionUpper, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel3))
.addGap(18, 18, 18)
.addComponent(guiBtnAddDimension)
.addContainerGap(16, Short.MAX_VALUE))
);
jScrollPane1.setViewportView(guiTable);
GroupLayout jPanelDimensionsLayout = new GroupLayout(jPanelDimensions);
jPanelDimensions.setLayout(jPanelDimensionsLayout);
jPanelDimensionsLayout.setHorizontalGroup(
jPanelDimensionsLayout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanelDimensionsLayout.createSequentialGroup()
.addComponent(jPanelAddDimension, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 618, Short.MAX_VALUE)
.addContainerGap())
);
jPanelDimensionsLayout.setVerticalGroup(
jPanelDimensionsLayout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanelDimensionsLayout.createSequentialGroup()
.addGroup(jPanelDimensionsLayout.createParallelGroup(Alignment.LEADING)
.addComponent(jScrollPane1, GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(jPanelDimensionsLayout.createSequentialGroup()
.addComponent(jPanelAddDimension, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
GroupLayout layout = new GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(Alignment.LEADING)
.addGroup(Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel15)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(gui_jtf_name)
.addContainerGap())
.addComponent(jPanelDimensions, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(jLabel15)
.addComponent(gui_jtf_name, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addComponent(jPanelDimensions, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanelDimensions.getAccessibleContext().setAccessibleName("New attribute");
}// </editor-fold>//GEN-END:initComponents
private void guiBtnAddDimensionActionPerformed(ActionEvent evt) {//GEN-FIRST:event_guiBtnAddDimensionActionPerformed
if (!(layer instanceof FeatureMapLayer)) {
return;
}
final FeatureMapLayer fml = (FeatureMapLayer)layer;
final CoordinateReferenceSystem crs = buildCrs1DFromName(guiCrsName.getText());
final DimensionDef dimToAdd = new DimensionDef(crs, guiTextExpressionLower.create(), guiTextExpressionUpper.create());
if (!fml.getExtraDimensions().contains(dimToAdd)) {
fml.getExtraDimensions().add(dimToAdd);
}
updateTableModel();
}//GEN-LAST:event_guiBtnAddDimensionActionPerformed
private CoordinateReferenceSystem buildCrs1DFromName(final String crsName) {
final EngineeringDatum customDatum = new DefaultEngineeringDatum(Collections.singletonMap("name", crsName));
final CoordinateSystemAxis csAxis = new DefaultCoordinateSystemAxis(Collections.singletonMap("name", crsName), "u", AxisDirection.valueOf(crsName), Units.UNITY);
final AbstractCS customCs = new AbstractCS(Collections.singletonMap("name", crsName), csAxis);
return new DefaultEngineeringCRS(Collections.singletonMap("name", crsName), customDatum, customCs);
}
private void parse() {
if (layer != null) {
gui_jtf_name.setText(layer.getDescription().getTitle().toString());
} else {
gui_jtf_name.setText("");
}
// Do not display the whole panel if not a feature map layer
final boolean isFeature = (layer instanceof FeatureMapLayer);
jPanelDimensions.setVisible(isFeature);
if (isFeature) {
guiTextExpressionLower.setLayer(layer);
guiTextExpressionUpper.setLayer(layer);
updateTableModel();
}
}
@Override
public void setTarget(final Object target) {
if (target instanceof MapLayer) {
layer = (MapLayer) target;
} else {
layer = null;
}
parse();
}
@Override
public void apply() {
if (layer != null) {
layer.setDescription(FactoryFinder.getStyleFactory(null).description(
new SimpleInternationalString(gui_jtf_name.getText()),
new SimpleInternationalString("")));
if (layer instanceof FeatureMapLayer) {
final FeatureMapLayer fml = (FeatureMapLayer)layer;
final OutlineModel model = (OutlineModel) guiTable.getModel();
final List<DimensionDef> dimensions = new ArrayList<DimensionDef>();
final DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) model.getRoot();
for (int i=0; i < rootNode.getChildCount(); i++) {
final DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) rootNode.getChildAt(i);
if (childNode.getUserObject() instanceof DimensionDef) {
final DimensionDef dim = (DimensionDef) childNode.getUserObject();
dimensions.add(dim);
}
}
if (!dimensions.isEmpty()) {
fml.getExtraDimensions().clear();
fml.getExtraDimensions().addAll(dimensions);
}
}
}
}
@Override
public void reset() {
parse();
}
@Override
public boolean canHandle(Object target) {
return true;
}
private void updateTableModel() {
if (!(layer instanceof FeatureMapLayer)) {
return;
}
final DefaultMutableTreeNode root = new DefaultMutableTreeNode();
final DefaultTreeModel treeModel = new org.geotoolkit.gui.swing.tree.DefaultTreeModel(root);
final FeatureMapLayer fml = (FeatureMapLayer)layer;
for (DimensionDef dim : fml.getExtraDimensions()) {
root.add(new DefaultMutableTreeNode(dim, false));
}
final LayerGeneralTableRowModel model = new LayerGeneralTableRowModel();
guiTable.setRootVisible(false);
guiTable.setModel(DefaultOutlineModel.createOutlineModel(treeModel, model));
guiTable.repaint();
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private JButton guiBtnAddDimension;
private JTextField guiCrsName;
private Outline guiTable;
private JTextExpressionPane guiTextExpressionLower;
private JTextExpressionPane guiTextExpressionUpper;
private JTextField gui_jtf_name;
private JLabel jLabel1;
private JLabel jLabel15;
private JLabel jLabel2;
private JLabel jLabel3;
private JPanel jPanelAddDimension;
private JPanel jPanelDimensions;
private JScrollPane jScrollPane1;
// End of variables declaration//GEN-END:variables
private static class DimensionRenderer implements RenderDataProvider{
@Override
public String getDisplayName(Object o) {
return "";
}
@Override
public boolean isHtmlDisplayName(Object o) {
return true;
}
@Override
public Color getBackground(Object o) {
return null;
}
@Override
public Color getForeground(Object o) {
return null;
}
@Override
public String getTooltipText(Object o) {
return null;
}
@Override
public Icon getIcon(Object o) {
return IconBundle.EMPTY_ICON_16;
}
}
private static class ExpressionLowerRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
final JLabel lbl = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
lbl.setText("");
if (value instanceof DefaultMutableTreeNode) {
value = ((DefaultMutableTreeNode)value).getUserObject();
}
if (value instanceof DimensionDef) {
final DimensionDef def = (DimensionDef)value;
if (def.getLower() != null) {
lbl.setText(def.getLower().toString());
}
}
return lbl;
}
}
private static class ExpressionUpperRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
final JLabel lbl = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
lbl.setText("");
if (value instanceof DefaultMutableTreeNode) {
value = ((DefaultMutableTreeNode)value).getUserObject();
}
if (value instanceof DimensionDef) {
final DimensionDef def = (DimensionDef)value;
if (def.getUpper() != null) {
lbl.setText(def.getUpper().toString());
}
}
return lbl;
}
}
private static class CrsRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
final JLabel lbl = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
lbl.setText("");
if (value instanceof DefaultMutableTreeNode) {
value = ((DefaultMutableTreeNode)value).getUserObject();
}
if (value instanceof DimensionDef) {
final DimensionDef def = (DimensionDef)value;
if (def.getCrs() != null) {
lbl.setText(def.getCrs().getName().toString());
}
}
return lbl;
}
}
}