/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2009-2014 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.styleproperty;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import org.apache.sis.util.logging.Logging;
import org.geotoolkit.display2d.service.DefaultGlyphService;
import org.geotoolkit.factory.FactoryFinder;
import org.geotoolkit.factory.Hints;
import org.geotoolkit.gui.swing.propertyedit.AbstractPropertyPane;
import org.geotoolkit.gui.swing.propertyedit.JPropertyPane;
import org.geotoolkit.font.FontAwesomeIcons;
import org.geotoolkit.font.IconBuilder;
import org.geotoolkit.gui.swing.resource.IconBundle;
import org.geotoolkit.gui.swing.resource.MessageBundle;
import org.geotoolkit.gui.swing.util.JOptionDialog;
import org.geotoolkit.image.palette.PaletteFactory;
import org.geotoolkit.map.FeatureMapLayer;
import org.geotoolkit.style.FeatureTypeStyleListener;
import org.geotoolkit.style.MutableFeatureTypeStyle;
import org.geotoolkit.style.MutableRule;
import org.geotoolkit.style.MutableStyleFactory;
import org.geotoolkit.style.interval.DefaultIntervalPalette;
import org.geotoolkit.style.interval.IntervalPalette;
import org.geotoolkit.style.interval.IntervalStyleBuilder;
import org.geotoolkit.style.interval.IntervalStyleBuilder.METHOD;
import org.geotoolkit.util.collection.CollectionChangeEvent;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.combobox.EnumComboBoxModel;
import org.jdesktop.swingx.combobox.ListComboBoxModel;
import org.jdesktop.swingx.decorator.Highlighter;
import org.jdesktop.swingx.decorator.HighlighterFactory;
import org.opengis.filter.And;
import org.opengis.filter.BinaryComparisonOperator;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.PropertyIsEqualTo;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.PropertyName;
import org.opengis.style.Rule;
import org.opengis.style.SemanticType;
import org.opengis.style.Symbolizer;
import org.opengis.util.GenericName;
/**
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class JClassificationIntervalStylePanel extends AbstractPropertyPane{
private static final Logger LOGGER = Logging.getLogger("org.geotoolkit.gui.swing.propertyedit.styleproperty");
private static final NumberFormat FORMAT = NumberFormat.getNumberInstance();
private static final ImageIcon DELETE = IconBuilder.createIcon(FontAwesomeIcons.ICON_TRASH_O, 16, FontAwesomeIcons.DEFAULT_COLOR);
private final Dimension GLYPH_DIMENSION = new Dimension(30, 20);
private static final PaletteFactory PF = PaletteFactory.getDefault();
private static final List<IntervalPalette> PALETTES;
static{
PALETTES = new ArrayList<IntervalPalette>();
final Set<String> paletteNames = PF.getAvailableNames();
for (String palName : paletteNames) {
try {
PALETTES.add(new DefaultIntervalPalette(PF.getColors(palName)));
} catch (IOException ex) {
LOGGER.log(Level.WARNING, ex.getMessage(), ex);
}
}
}
private static final MutableStyleFactory SF = (MutableStyleFactory) FactoryFinder.getStyleFactory(new Hints(Hints.STYLE_FACTORY, MutableStyleFactory.class));
private static final FilterFactory FF = FactoryFinder.getFilterFactory(null);
private final RuleModel model = new RuleModel();
private final IntervalStyleBuilder analyze = new IntervalStyleBuilder();
private FeatureMapLayer layer = null;
public JClassificationIntervalStylePanel() {
super(MessageBundle.format("property_style_classification_interval"),
IconBundle.getIcon("16_classification_interval"),
IconBundle.getIcon("preview_style_class2").getImage(),
"");
initComponents();
guiTable.setModel(model);
guiProperty.setRenderer(new PropertyRenderer());
guiPalette.setModel(new ListComboBoxModel(PALETTES));
guiPalette.setRenderer(new PaletteCellRenderer());
guiPalette.setSelectedIndex(0);
guiTable.getColumnModel().getColumn(0).setCellRenderer(new RuleStyleRenderer());
guiTable.getColumnModel().getColumn(0).setCellEditor(new RuleStyleEditor());
guiTable.getColumnModel().getColumn(1).setCellRenderer(new RulePropertyRenderer());
guiTable.getColumnModel().getColumn(1).setCellEditor(new RulePropertyEditor());
guiTable.getColumnModel().getColumn(2).setCellRenderer(new RuleNameRenderer());
guiTable.getColumnModel().getColumn(2).setCellEditor(new RuleNameEditor());
guiTable.getColumnModel().getColumn(3).setCellRenderer(new DeleteRenderer());
guiTable.getColumnModel().getColumn(3).setCellEditor(new DeleteEditor());
guiTable.setShowGrid(false, false);
guiTable.setHighlighters(new Highlighter[]{HighlighterFactory.createAlternateStriping(Color.WHITE, HighlighterFactory.QUICKSILVER, 1)});
guiTable.getColumnExt(0).setMaxWidth(30);
guiTable.getColumnExt(3).setMaxWidth(20);
guiMethod.setModel(new EnumComboBoxModel(IntervalStyleBuilder.METHOD.class));
guiMethod.setRenderer(new MethodRenderer());
guiNormalize.setRenderer(new DefaultListCellRenderer(){
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
final JLabel lbl = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if(value == analyze.noValue){
lbl.setText("-");
}
return lbl;
}
});
}
private void parse(){
model.fts.rules().clear();
if(layer != null){
analyze.setLayer(layer);
if(analyze.isIntervalStyle(layer.getStyle())){
model.fts.rules().addAll(layer.getStyle().featureTypeStyles().get(0).rules());
}
}
List<PropertyName> props = analyze.getProperties();
guiProperty.setModel(new ListComboBoxModel(new ArrayList<PropertyName>(props)));
if(!props.isEmpty()){
guiProperty.setSelectedIndex(0);
}
updateNormalizeList();
updateModelGlyph();
guiMethod.setSelectedItem(analyze.getMethod());
guiClasses.setValue(analyze.getNbClasses());
}
private void updateNormalizeList(){
Object oldSelected = guiNormalize.getSelectedItem();
List<PropertyName> lstnormalize = new ArrayList<PropertyName>();
lstnormalize.add(analyze.noValue);
lstnormalize.addAll(analyze.getProperties());
lstnormalize.remove(guiProperty.getSelectedItem());
guiNormalize.setModel(new ListComboBoxModel(lstnormalize));
if(oldSelected != null){
guiNormalize.setSelectedItem(oldSelected);
}
if(guiNormalize.getSelectedItem() == null){
guiNormalize.setSelectedItem(analyze.noValue);
}
}
private void updateModelGlyph(){
Symbolizer template = analyze.getTemplate();
if(template == null){
guiModel.setIcon(null);
guiModel.setText(" ");
}else{
BufferedImage img = new BufferedImage(30, 20, BufferedImage.TYPE_INT_ARGB);
DefaultGlyphService.render(template, new Rectangle(GLYPH_DIMENSION), img.createGraphics(),null);
guiModel.setIcon(new ImageIcon(img));
guiModel.setText("");
}
}
/** 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.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
guiRemoveAll = new JButton();
jPanel1 = new JPanel();
guiLblProperty = new JLabel();
guiProperty = new JComboBox();
guiLblPalette = new JLabel();
guiLblModel = new JLabel();
guiModel = new JButton();
guiGenerate = new JButton();
guiPalette = new JComboBox();
guiLblNormalize = new JLabel();
guiNormalize = new JComboBox();
guiClassify = new JButton();
guiLblMethod = new JLabel();
guiMethod = new JComboBox();
guiLblClasses = new JLabel();
guiClasses = new JSpinner();
jScrollPane1 = new JScrollPane();
guiTable = new JXTable();
guiInvert = new JButton();
guiRemoveAll.setText(MessageBundle.format("remove_all_values")); // NOI18N
guiRemoveAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
guiRemoveAllActionPerformed(evt);
}
});
jPanel1.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 5));
guiLblProperty.setText(MessageBundle.format("property")); // NOI18N
guiProperty.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
guiPropertyActionPerformed(evt);
}
});
guiLblPalette.setText(MessageBundle.format("palette")); // NOI18N
guiLblModel.setText(MessageBundle.format("model")); // NOI18N
guiModel.setText(" ");
guiModel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
guiModelActionPerformed(evt);
}
});
guiGenerate.setText(MessageBundle.format("generate")); // NOI18N
guiGenerate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
guiGenerateActionPerformed(evt);
}
});
guiLblNormalize.setText(MessageBundle.format("normalize")); // NOI18N
guiNormalize.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
guiNormalizeActionPerformed(evt);
}
});
guiClassify.setText(MessageBundle.format("classify")); // NOI18N
guiClassify.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
guiClassifyActionPerformed(evt);
}
});
guiLblMethod.setText(MessageBundle.format("method")); // NOI18N
guiMethod.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
guiMethodActionPerformed(evt);
}
});
guiLblClasses.setText(MessageBundle.format("classes")); // NOI18N
guiClasses.setModel(new SpinnerNumberModel(Integer.valueOf(5), Integer.valueOf(1), null, Integer.valueOf(1)));
guiClasses.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent evt) {
guiClassesStateChanged(evt);
}
});
GroupLayout jPanel1Layout = new GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanel1Layout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(guiLblProperty)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(guiProperty, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(guiLblNormalize)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(guiNormalize, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(guiLblMethod)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(guiMethod, GroupLayout.PREFERRED_SIZE, 130, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(guiLblClasses)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(guiClasses, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(guiClassify)
.addGap(0, 81, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(guiLblPalette)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(guiPalette, 0, 305, Short.MAX_VALUE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(guiLblModel)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(guiModel)))
.addContainerGap()))
.addComponent(guiGenerate, Alignment.TRAILING)))
);
jPanel1Layout.linkSize(SwingConstants.HORIZONTAL, new Component[] {guiLblMethod, guiLblPalette, guiLblProperty});
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(Alignment.BASELINE)
.addComponent(guiLblProperty)
.addComponent(guiProperty, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(guiLblNormalize)
.addComponent(guiNormalize, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(Alignment.BASELINE)
.addComponent(guiLblMethod)
.addComponent(guiMethod, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(guiLblClasses)
.addComponent(guiClasses, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(guiClassify))
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(Alignment.BASELINE)
.addComponent(guiLblPalette, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)
.addComponent(guiPalette, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(guiLblModel, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)
.addComponent(guiModel))
.addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(guiGenerate))
);
jPanel1Layout.linkSize(SwingConstants.VERTICAL, new Component[] {guiLblModel, guiLblPalette, guiModel});
jScrollPane1.setViewportView(guiTable);
guiInvert.setText(MessageBundle.format("invert_palette")); // NOI18N
guiInvert.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
guiInvertActionPerformed(evt);
}
});
GroupLayout layout = new GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(Alignment.LEADING)
.addComponent(jPanel1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 490, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(guiInvert)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(guiRemoveAll)
.addContainerGap(253, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 227, Short.MAX_VALUE)
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(Alignment.BASELINE)
.addComponent(guiInvert)
.addComponent(guiRemoveAll)))
);
}// </editor-fold>//GEN-END:initComponents
private void guiRemoveAllActionPerformed(final ActionEvent evt) {//GEN-FIRST:event_guiRemoveAllActionPerformed
model.fts.rules().clear();
}//GEN-LAST:event_guiRemoveAllActionPerformed
private void guiGenerateActionPerformed(final ActionEvent evt) {//GEN-FIRST:event_guiGenerateActionPerformed
model.fts.rules().clear();
model.fts.rules().addAll(analyze.generateRules((IntervalPalette) guiPalette.getSelectedItem()));
}//GEN-LAST:event_guiGenerateActionPerformed
private void guiModelActionPerformed(final ActionEvent evt) {//GEN-FIRST:event_guiModelActionPerformed
analyze.setTemplate(JPropertyPane.showSymbolizerDialog(this,analyze.getTemplate(), true, layer));
updateModelGlyph();
}//GEN-LAST:event_guiModelActionPerformed
private void guiPropertyActionPerformed(final ActionEvent evt) {//GEN-FIRST:event_guiPropertyActionPerformed
analyze.setClassification((PropertyName) guiProperty.getSelectedItem());
updateNormalizeList();
}//GEN-LAST:event_guiPropertyActionPerformed
private void guiNormalizeActionPerformed(final ActionEvent evt) {//GEN-FIRST:event_guiNormalizeActionPerformed
PropertyName prop = (PropertyName) guiNormalize.getSelectedItem();
analyze.setNormalize(prop);
}//GEN-LAST:event_guiNormalizeActionPerformed
private void guiClassesStateChanged(final ChangeEvent evt) {//GEN-FIRST:event_guiClassesStateChanged
analyze.setNbClasses((Integer)guiClasses.getModel().getValue());
}//GEN-LAST:event_guiClassesStateChanged
private void guiInvertActionPerformed(final ActionEvent evt) {//GEN-FIRST:event_guiInvertActionPerformed
Symbolizer[] symbols = new Symbolizer[model.fts.rules().size()];
for(int i=0;i<model.fts.rules().size();i++){
symbols[model.fts.rules().size()-1-i] = model.fts.rules().get(i).symbolizers().get(0);
}
for(int i=0;i<model.fts.rules().size();i++){
model.fts.rules().get(i).symbolizers().clear();
((MutableRule)model.fts.rules().get(i)).symbolizers().add(symbols[i]);
}
}//GEN-LAST:event_guiInvertActionPerformed
private void guiMethodActionPerformed(final ActionEvent evt) {//GEN-FIRST:event_guiMethodActionPerformed
analyze.setMethod((METHOD) guiMethod.getSelectedItem());
}//GEN-LAST:event_guiMethodActionPerformed
private void guiClassifyActionPerformed(final ActionEvent evt) {//GEN-FIRST:event_guiClassifyActionPerformed
final JAnalizePanel panel = new JAnalizePanel(analyze);
JOptionDialog.show(this, panel, JOptionPane.OK_CANCEL_OPTION);
guiMethod.setSelectedItem(analyze.getMethod());
guiClasses.setValue(analyze.getNbClasses());
}//GEN-LAST:event_guiClassifyActionPerformed
@Override
public boolean canHandle(Object target) {
return target instanceof FeatureMapLayer;
}
@Override
public void setTarget(final Object layer) {
if(layer instanceof FeatureMapLayer){
this.layer = (FeatureMapLayer) layer;
parse();
}else{
this.layer = null;
}
}
@Override
public void apply() {
if(layer == null) return;
layer.getStyle().featureTypeStyles().clear();
MutableFeatureTypeStyle fts = SF.featureTypeStyle(
"", SF.description("analyze", "analyze"), null, null, null, (List)model.fts.rules());
layer.getStyle().featureTypeStyles().add(fts);
}
@Override
public void reset() {
if(layer != null){
parse();
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private JSpinner guiClasses;
private JButton guiClassify;
private JButton guiGenerate;
private JButton guiInvert;
private JLabel guiLblClasses;
private JLabel guiLblMethod;
private JLabel guiLblModel;
private JLabel guiLblNormalize;
private JLabel guiLblPalette;
private JLabel guiLblProperty;
private JComboBox guiMethod;
private JButton guiModel;
private JComboBox guiNormalize;
private JComboBox guiPalette;
private JComboBox guiProperty;
private JButton guiRemoveAll;
private JXTable guiTable;
private JPanel jPanel1;
private JScrollPane jScrollPane1;
// End of variables declaration//GEN-END:variables
private class PropertyRenderer extends DefaultListCellRenderer{
@Override
public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected, final boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if(value instanceof PropertyName){
setText(((PropertyName)value).getPropertyName());
}
return PropertyRenderer.this;
}
}
private class MethodRenderer extends DefaultListCellRenderer{
@Override
public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected, final boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
MethodRenderer.this.setText(" ");
if(value instanceof IntervalStyleBuilder.METHOD){
METHOD mt = (METHOD) value;
final String txt;
switch(mt){
case EL : txt = MessageBundle.format("el"); break;
case MANUAL : txt = MessageBundle.format("manual"); break;
default : txt = MessageBundle.format("qantile"); break;
}
MethodRenderer.this.setText(txt);
}
return MethodRenderer.this;
}
}
private class DeleteRenderer extends DefaultTableCellRenderer{
@Override
public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
DeleteRenderer.this.setIcon(DELETE);
return DeleteRenderer.this;
}
}
private class DeleteEditor extends AbstractCellEditor implements TableCellEditor{
private final JButton button = new JButton();
private Object value;
public DeleteEditor() {
button.setBorderPainted(false);
button.setContentAreaFilled(false);
button.setIcon(DELETE);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(value != null && value instanceof Rule){
model.fts.rules().remove(value);
}
}
});
}
@Override
public Object getCellEditorValue() {
return null;
}
@Override
public Component getTableCellEditorComponent(final JTable table, final Object value, final boolean isSelected, final int row, final int column) {
this.value = value;
return button;
}
}
private class RulePropertyRenderer extends DefaultTableCellRenderer{
@Override
public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
RulePropertyRenderer.this.setText("");
if(value instanceof Rule){
Rule r = (Rule) value;
Filter f = r.getFilter();
if(f != null && f instanceof And){
And prop = (And) f;
BinaryComparisonOperator under = (BinaryComparisonOperator) prop.getChildren().get(0);
BinaryComparisonOperator above = (BinaryComparisonOperator) prop.getChildren().get(1);
Number nUnder = under.getExpression2().evaluate(null, Number.class);
Number nAbove = above.getExpression2().evaluate(null, Number.class);
this.setText( FORMAT.format(nUnder.doubleValue()) + " -> " + FORMAT.format(nAbove.doubleValue()) );
}
}
return RulePropertyRenderer.this;
}
}
private class RulePropertyEditor extends AbstractCellEditor implements TableCellEditor{
private final JTextField field = new JTextField();
private MutableRule value;
public RulePropertyEditor() {
}
@Override
public Object getCellEditorValue() {
return FF.literal(field.getText());
}
@Override
public Component getTableCellEditorComponent(final JTable table, final Object value, final boolean isSelected, final int row, final int column) {
if(value instanceof MutableRule){
this.value = (MutableRule) value;
Filter f = this.value.getFilter();
if(f != null && f instanceof PropertyIsEqualTo){
PropertyIsEqualTo prop = (PropertyIsEqualTo) f;
if(prop.getExpression1() instanceof Literal){
field.setText(prop.getExpression1().toString());
}else if(prop.getExpression2() instanceof Literal){
field.setText(prop.getExpression2().toString());
}
}
}else{
this.value = null;
}
return field;
}
}
private class RuleNameRenderer extends DefaultTableCellRenderer{
@Override
public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
RuleNameRenderer.this.setText("");
if(value instanceof Rule){
Rule r = (Rule) value;
RuleNameRenderer.this.setText(r.getDescription().getTitle().toString());
}
return RuleNameRenderer.this;
}
}
private class RuleNameEditor extends AbstractCellEditor implements TableCellEditor{
private final JTextField field = new JTextField();
private MutableRule value;
public RuleNameEditor() {
}
@Override
public Object getCellEditorValue() {
return field.getText();
}
@Override
public Component getTableCellEditorComponent(final JTable table, final Object value, final boolean isSelected, final int row, final int column) {
if(value instanceof MutableRule){
this.value = (MutableRule) value;
field.setText(this.value.getDescription().getTitle().toString());
}else{
field.setText("");
this.value = null;
}
return field;
}
}
private class RuleStyleRenderer extends DefaultTableCellRenderer{
@Override
public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
RuleStyleRenderer.this.setText("");
if(value instanceof Rule){
BufferedImage img = new BufferedImage(30, 20, BufferedImage.TYPE_INT_ARGB);
DefaultGlyphService.render((Rule)value, new Rectangle(GLYPH_DIMENSION), img.createGraphics(),null);
RuleStyleRenderer.this.setIcon(new ImageIcon(img));
}
return RuleStyleRenderer.this;
}
}
private class RuleStyleEditor extends AbstractCellEditor implements TableCellEditor{
private final JButton button = new JButton();
private MutableRule value;
public RuleStyleEditor() {
button.setBorderPainted(false);
button.setContentAreaFilled(false);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(value != null){
Symbolizer symbol = JPropertyPane.showSymbolizerDialog(JClassificationIntervalStylePanel.this,value.symbolizers().get(0), layer);
value.symbolizers().clear();
value.symbolizers().add(symbol);
}
}
});
}
@Override
public Object getCellEditorValue() {
return null;
}
@Override
public Component getTableCellEditorComponent(final JTable table, final Object value, final boolean isSelected, final int row, final int column) {
if(value instanceof MutableRule){
this.value = (MutableRule) value;
BufferedImage img = new BufferedImage(30, 20, BufferedImage.TYPE_INT_ARGB);
DefaultGlyphService.render(this.value, new Rectangle(GLYPH_DIMENSION), img.createGraphics(),null);
button.setIcon(new ImageIcon(img));
}else{
this.value = null;
}
return button;
}
}
private class RuleModel extends AbstractTableModel{
private final MutableFeatureTypeStyle fts = SF.featureTypeStyle();
public RuleModel() {
fts.addListener(new FeatureTypeStyleListener() {
@Override
public void ruleChange(CollectionChangeEvent<MutableRule> event) {
JClassificationIntervalStylePanel.RuleModel.this.fireTableDataChanged();
}
@Override
public void featureTypeNameChange(CollectionChangeEvent<GenericName> event) {}
@Override
public void semanticTypeChange(CollectionChangeEvent<SemanticType> event) {}
@Override
public void propertyChange(PropertyChangeEvent evt) {}
});
}
@Override
public int getRowCount() {
return fts.rules().size();
}
@Override
public int getColumnCount() {
return 4;
}
@Override
public boolean isCellEditable(final int rowIndex, final int columnIndex) {
return columnIndex != 1;
}
@Override
public Object getValueAt(final int rowIndex, final int columnIndex) {
return fts.rules().get(rowIndex);
}
@Override
public String getColumnName(final int columnIndex) {
switch(columnIndex){
case 0: return "";
case 1: return MessageBundle.format("value");
case 2: return MessageBundle.format("title");
case 3: return "";
}
return "";
}
@Override
public void setValueAt(final Object aValue, final int rowIndex, final int columnIndex) {
MutableRule rule = (MutableRule) fts.rules().get(rowIndex);
if(aValue instanceof Literal){
//the property value field has changed
Filter f = rule.getFilter();
if(f != null){
PropertyIsEqualTo prop = (PropertyIsEqualTo) f;
if(prop.getExpression1() instanceof Literal){
rule.setFilter(FF.equals(prop.getExpression2(),(Expression) aValue));
}else if(prop.getExpression2() instanceof Literal){
rule.setFilter(FF.equals(prop.getExpression1(),(Expression) aValue));
}
}
}else if(aValue instanceof String){
//the rule title changed
rule.setDescription(SF.description((String)aValue, (String)aValue));
}
super.setValueAt(aValue, rowIndex, columnIndex);
}
}
}