/*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2012 by: Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de 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; either version 2.1 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: lat/lon GmbH Aennchenstr. 19 53177 Bonn Germany E-Mail: info@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.igeo.views.swing.style.component.classification; import static org.deegree.igeo.style.model.classification.Column.COLUMNTYPE.VALUE; import java.awt.Color; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.TableModelEvent; import javax.swing.table.AbstractTableModel; import org.deegree.graphics.sld.Rule; import org.deegree.igeo.style.classification.SldFromClassification; import org.deegree.igeo.style.model.DashArray; import org.deegree.igeo.style.model.Fill; import org.deegree.igeo.style.model.FillColor; import org.deegree.igeo.style.model.LinearGradient; import org.deegree.igeo.style.model.SldProperty; import org.deegree.igeo.style.model.SldValues; import org.deegree.igeo.style.model.Symbol; import org.deegree.igeo.style.model.classification.ClassificationTableRow; import org.deegree.igeo.style.model.classification.ClassificationTableRowComparator; import org.deegree.igeo.style.model.classification.Column; import org.deegree.igeo.style.model.classification.Column.COLUMNTYPE; import org.deegree.igeo.style.model.classification.DoubleRange; import org.deegree.igeo.style.model.classification.IntegerRamp; import org.deegree.igeo.style.model.classification.IntegerRange; import org.deegree.igeo.style.model.classification.Intervallable; import org.deegree.igeo.style.model.classification.SingleDouble; import org.deegree.igeo.style.model.classification.SingleInteger; import org.deegree.igeo.style.model.classification.ThematicGrouping; import org.deegree.igeo.style.model.classification.ThematicGroupingInformation.GROUPINGTYPE; import org.deegree.igeo.style.model.classification.ValueRange; import org.deegree.igeo.views.swing.style.StyleDialog; import org.deegree.igeo.views.swing.style.component.classification.AbstractClassificationPanel.SYMBOLIZERTYPE; import org.deegree.igeo.views.swing.style.editor.ClassificationValuesEditor; import org.deegree.model.filterencoding.PropertyName; /** * <code>ClassificationTableModel</code> * * @author <a href="mailto:wanhoff@lat-lon.de">Jeronimo Wanhoff</a> * @author <a href="mailto:buesching@lat-lon.de">Lyn Buesching</a> * @author last edited by: $Author$ * * @version $Revision$, $Date$ * */ public class ClassificationTableModel<U extends Comparable<U>> extends AbstractTableModel implements CellEditorListener { private static final long serialVersionUID = 7835812908636984046L; private SldFromClassification<U> sldClassificationCalculator; private ThematicGrouping<U> thematicGrouping; private List<ClassificationTableRow<U>> rows = new ArrayList<ClassificationTableRow<U>>(); private List<ClassificationTableRow<U>> oldRows = new ArrayList<ClassificationTableRow<U>>(); private List<Column> columns = new ArrayList<Column>(); private StyleDialog styleDialog; private GROUPINGTYPE baseType = GROUPINGTYPE.MANUAL; /** * @param thematicGrouping * the classification */ public ClassificationTableModel( List<Column> columns, StyleDialog styleDialog ) { this.styleDialog = styleDialog; this.columns = columns; sldClassificationCalculator = new SldFromClassification<U>(); } /** * updates the column with the given index * * @param columnIndex * the index of the column to update * @param updateTable * true, if the table should be redrawn */ public void update( COLUMNTYPE type, boolean updateTable ) { if ( thematicGrouping != null ) { switch ( type ) { case VALUE: oldRows.addAll( rows ); List<ValueRange<U>> values = thematicGrouping.getValues(); rows.clear(); for ( ValueRange<U> value : values ) { rows.add( new ClassificationTableRow<U>( value ) ); } sort( COLUMNTYPE.VALUE, false ); // update all other components too! update( COLUMNTYPE.FILLCOLOR, false ); update( COLUMNTYPE.FILLTRANSPARENCY, false ); update( COLUMNTYPE.LINECOLOR, false ); update( COLUMNTYPE.LINETRANSPARENCY, false ); update( COLUMNTYPE.LINEWIDTH, false ); update( COLUMNTYPE.SIZE, false ); update( COLUMNTYPE.SYMBOL, false ); update( COLUMNTYPE.LINECAP, false ); update( COLUMNTYPE.LINESTYLE, false ); update( COLUMNTYPE.FONTCOLOR, false ); update( COLUMNTYPE.FONTFAMILY, false ); update( COLUMNTYPE.FONTWEIGHT, false ); update( COLUMNTYPE.FONTSTYLE, false ); update( COLUMNTYPE.FONTSIZE, false ); update( COLUMNTYPE.ANCHORPOINT, false ); update( COLUMNTYPE.DISPLACEMENT, false ); update( COLUMNTYPE.ROTATION, false ); update( COLUMNTYPE.HALOCOLOR, false ); update( COLUMNTYPE.HALORADIUS, false ); update( COLUMNTYPE.FONTTRANSPARENCY, false ); oldRows.clear(); break; case FILLCOLOR: Fill fillColor = thematicGrouping.getFillColor(); if ( fillColor != null ) { if ( fillColor instanceof FillColor && SldValues.getDefaultColor().equals( ( (FillColor) fillColor ).getColor() ) ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setFillColor( oldRows.get( i ).getFillColor() ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setFillColor( oldRows.get( oldRows.size() - 1 ).getFillColor() ); } } } else { List<Object> colors = thematicGrouping.getFillColor().getFills( getRowCount() ); for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setFillColor( colors.get( i ) ); } } } break; case FILLTRANSPARENCY: IntegerRange fillTransparency = thematicGrouping.getFillTransparency(); if ( fillTransparency != null ) { if ( fillTransparency instanceof SingleInteger && SldValues.getOpacityInPercent( SldValues.getDefaultOpacity() ) == fillTransparency.getMax() ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setFillTransparency( oldRows.get( i ).getFillTransparency() ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setFillTransparency( oldRows.get( oldRows.size() - 1 ).getFillTransparency() ); } } } else { List<Integer> integers = fillTransparency.getIntegers( getRowCount() ); for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setFillTransparency( integers.get( i ) ); } } } break; case LINECOLOR: Fill lineColor = thematicGrouping.getLineColor(); if ( lineColor != null ) { if ( lineColor instanceof FillColor && SldValues.getDefaultLineColor().equals( ( (FillColor) lineColor ).getColor() ) ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setLineColor( oldRows.get( i ).getLineColor() ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setLineColor( oldRows.get( oldRows.size() - 1 ).getLineColor() ); } } } else { List<Object> colors = lineColor.getFills( getRowCount() ); for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setLineColor( (Color) colors.get( i ) ); } } } break; case LINETRANSPARENCY: IntegerRange lineTransparency = thematicGrouping.getLineTransparency(); if ( lineTransparency != null ) { if ( lineTransparency instanceof SingleInteger && SldValues.getOpacityInPercent( SldValues.getDefaultOpacity() ) == lineTransparency.getMax() ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setLineTransparency( oldRows.get( i ).getLineTransparency() ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setLineTransparency( oldRows.get( oldRows.size() - 1 ).getLineTransparency() ); } } } else { List<Integer> integers = lineTransparency.getIntegers( getRowCount() ); for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setLineTransparency( integers.get( i ) ); } } } break; case LINEWIDTH: DoubleRange lineWidth = thematicGrouping.getLineWidth(); if ( lineWidth != null ) { if ( lineWidth instanceof SingleDouble && SldValues.getDefaultLineWidth() == lineWidth.getMax() ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setLineWidth( oldRows.get( i ).getLineWidth() ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setLineWidth( oldRows.get( oldRows.size() - 1 ).getLineWidth() ); } } } else { List<Double> doubles = lineWidth.getDoubles( getRowCount(), 2 ); for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setLineWidth( doubles.get( i ) ); } } } break; case LINESTYLE: DashArray lineStyle = thematicGrouping.getLineStyle(); if ( lineStyle != null ) { if ( SldValues.getDefaultLineStyle().equals( lineStyle ) ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setLineStyle( oldRows.get( i ).getLineStyle() ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setLineStyle( oldRows.get( oldRows.size() - 1 ).getLineStyle() ); } } } else { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setLineStyle( lineStyle ); } } } break; case SIZE: DoubleRange size = thematicGrouping.getSize(); if ( size != null ) { if ( size instanceof SingleDouble && SldValues.getDefaultSize() == size.getMax() ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setSize( oldRows.get( i ).getSize() ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setSize( oldRows.get( oldRows.size() - 1 ).getSize() ); } } } else { List<Double> doubles = size.getDoubles( getRowCount(), 2 ); for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setSize( doubles.get( i ) ); } } } break; case SYMBOL: Symbol symbol = thematicGrouping.getSymbol(); if ( symbol != null ) { if ( SldValues.getDefaultWKM().equals( symbol ) ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setSymbol( oldRows.get( i ).getSymbol() ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setSymbol( oldRows.get( oldRows.size() - 1 ).getSymbol() ); } } } else { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setSymbol( symbol ); } } } break; case LINECAP: SldProperty lineCap = thematicGrouping.getLineCap(); if ( lineCap != null ) { if ( SldValues.getDefaultLineCapAsProperty().equals( lineCap ) ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setLineCap( oldRows.get( i ).getLineCap() ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setLineCap( oldRows.get( oldRows.size() - 1 ).getLineCap() ); } } } else { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setLineCap( lineCap ); } } } break; case FONTCOLOR: Object fontColor = thematicGrouping.getFontColor(); if ( fontColor != null ) { if ( fontColor instanceof FillColor && SldValues.getDefaultFontColor().equals( ( (FillColor) fontColor ).getColor() ) ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setValue( COLUMNTYPE.FONTCOLOR, oldRows.get( i ).getValue( COLUMNTYPE.FONTCOLOR ) ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setValue( COLUMNTYPE.FONTCOLOR, oldRows.get( oldRows.size() - 1 ).getValue( COLUMNTYPE.FONTCOLOR ) ); } } } else if ( fontColor instanceof Fill ) { List<Object> colors = ( (Fill) fontColor ).getFills( getRowCount() ); for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.FONTCOLOR, (Color) colors.get( i ) ); } } else if ( fontColor instanceof PropertyName ) { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.FONTCOLOR, fontColor ); } } } break; case FONTFAMILY: Object fontFamily = thematicGrouping.getFontFamily(); if ( fontFamily != null ) { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.FONTFAMILY, fontFamily ); } } break; case FONTWEIGHT: Object fontWeight = thematicGrouping.getFontWeight(); if ( fontWeight != null ) { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.FONTWEIGHT, fontWeight ); } } break; case FONTSTYLE: Object fontStyle = thematicGrouping.getFontStyle(); if ( fontStyle != null ) { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.FONTSTYLE, fontStyle ); } } break; case FONTSIZE: Object fontSize = thematicGrouping.getFontSize(); if ( fontSize != null ) { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.FONTSIZE, fontSize ); } } break; case FONTTRANSPARENCY: Object fontTransparency = thematicGrouping.getFontTransparency(); if ( fontTransparency != null ) { if ( fontTransparency instanceof SingleInteger ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setValue( COLUMNTYPE.FONTTRANSPARENCY, oldRows.get( i ).getValue( COLUMNTYPE.FONTTRANSPARENCY ) ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setValue( COLUMNTYPE.FONTTRANSPARENCY, oldRows.get( oldRows.size() - 1 ).getValue( COLUMNTYPE.FONTTRANSPARENCY ) ); } } } else if ( fontTransparency instanceof IntegerRamp ) { List<Integer> integers = ( (IntegerRamp) fontTransparency ).getIntegers( getRowCount() ); for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.FONTTRANSPARENCY, integers.get( i ) ); } } else if ( fontTransparency instanceof PropertyName ) { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.FONTTRANSPARENCY, (PropertyName) fontTransparency ); } } } break; case ROTATION: Object rotation = thematicGrouping.getRotation(); if ( rotation != null ) { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.ROTATION, rotation ); } } break; case DISPLACEMENT: Object displacement = thematicGrouping.getDisplacement(); if ( displacement != null ) { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.DISPLACEMENT, displacement ); } } break; case ANCHORPOINT: Object anchorPoint = thematicGrouping.getAnchorPoint(); if ( anchorPoint != null ) { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.ANCHORPOINT, anchorPoint ); } } break; case HALOCOLOR: Object haloColor = thematicGrouping.getHaloColor(); if ( haloColor != null ) { if ( haloColor instanceof FillColor && SldValues.getDefaultFontColor().equals( ( (FillColor) haloColor ).getColor() ) ) { for ( int i = 0; i < getRowCount(); i++ ) { if ( oldRows.size() > 0 && i < oldRows.size() ) { rows.get( i ).setValue( COLUMNTYPE.HALOCOLOR, oldRows.get( i ).getValue( COLUMNTYPE.HALOCOLOR ) ); } else if ( oldRows.size() > 0 ) { rows.get( i ).setValue( COLUMNTYPE.HALOCOLOR, oldRows.get( oldRows.size() - 1 ).getValue( COLUMNTYPE.HALOCOLOR ) ); } } } else if ( haloColor instanceof Fill ) { List<Object> colors = ( (Fill) haloColor ).getFills( getRowCount() ); for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.HALOCOLOR, (Color) colors.get( i ) ); } } else if ( haloColor instanceof PropertyName ) { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.HALOCOLOR, haloColor ); } } } break; case HALORADIUS: Object haloRadius = thematicGrouping.getHaloRadius(); if ( haloRadius != null ) { for ( int i = 0; i < getRowCount(); i++ ) { rows.get( i ).setValue( COLUMNTYPE.HALORADIUS, haloRadius ); } } break; } if ( updateTable ) { fireTableDataChanged(); } } } /** * sorts the column specified with the given column index in ascending order * * @param column * the index of the column to sort * @param updateTable * true, if the table should be redrawn * */ public void sort( COLUMNTYPE type, boolean updateTable ) { Collections.sort( rows, new ClassificationTableRowComparator<U>( type ) ); if ( updateTable ) { fireTableDataChanged(); } } /** * @param thematicGrouping * the classification to set * @param baseType */ public void setThematicGrouping( ThematicGrouping<U> thematicGrouping, GROUPINGTYPE baseType ) { this.thematicGrouping = thematicGrouping; this.baseType = baseType; } /** * @return the classification represented in the table */ public ThematicGrouping<U> getThematicGrouping() { return thematicGrouping; } /** * @return the classification; each entry in the list means one row in the table */ public List<ClassificationTableRow<U>> getClassification() { return rows; } /** * @param set * the rows of the classification */ public void setClassification( List<ClassificationTableRow<U>> rows, GROUPINGTYPE baseType ) { this.rows = rows; this.baseType = baseType; fireTableDataChanged(); } /** * inserts a new row in the table before the selected row * * @param selectedRow * the index of the selected row */ public void addRowBefore( int selectedRow ) { ClassificationTableRow<U> newRow = new ClassificationTableRow<U>( baseType ); // fillColor Fill fillColor = thematicGrouping.getFillColor(); if ( fillColor instanceof FillColor ) { newRow.setFillColor( ( (FillColor) fillColor ).getColor() ); } else if ( fillColor instanceof LinearGradient ) { Color prevColor = null; if ( rows.size() > 0 && selectedRow > 0 && rows.get( selectedRow - 1 ).getFillColor() instanceof Color ) { prevColor = (Color) rows.get( selectedRow - 1 ).getFillColor(); } Color nextColor = null; if ( rows.size() > 0 && selectedRow < rows.size() && rows.get( selectedRow ).getFillColor() instanceof Color ) { nextColor = (Color) rows.get( selectedRow ).getFillColor(); } Color c = calculateMiddleColor( prevColor, nextColor ); if ( c != null ) { newRow.setFillColor( c ); } } // fillTransparency if ( thematicGrouping.getFillTransparency() instanceof SingleInteger ) { newRow.setFillTransparency( thematicGrouping.getFillTransparency().getMin() ); } else { int prevTrans = -1; if ( rows.size() > 0 && selectedRow > 0 ) { prevTrans = rows.get( selectedRow - 1 ).getFillTransparency(); } int nextTrans = -1; if ( rows.size() > 0 && selectedRow < rows.size() ) { nextTrans = rows.get( selectedRow ).getFillTransparency(); } int trans = calculateIntMiddle( prevTrans, nextTrans ); if ( trans != -1 ) { newRow.setFillTransparency( trans ); } } // lineColor Fill lineColor = thematicGrouping.getLineColor(); if ( lineColor instanceof FillColor ) { newRow.setLineColor( ( (FillColor) thematicGrouping.getLineColor() ).getColor() ); } else if ( lineColor instanceof LinearGradient ) { Color prevColor = null; if ( rows.size() > 0 && selectedRow > 0 ) { prevColor = (Color) rows.get( selectedRow - 1 ).getLineColor(); } Color nextColor = null; if ( rows.size() > 0 && selectedRow < rows.size() ) { nextColor = (Color) rows.get( selectedRow ).getLineColor(); } Color c = calculateMiddleColor( prevColor, nextColor ); if ( c != null ) { newRow.setLineColor( c ); } } // lineTransparency if ( thematicGrouping.getLineTransparency() instanceof SingleInteger ) { newRow.setLineTransparency( thematicGrouping.getLineTransparency().getMin() ); } else { int prevTrans = -1; if ( rows.size() > 0 && selectedRow > 0 ) { prevTrans = rows.get( selectedRow - 1 ).getLineTransparency(); } int nextTrans = -1; if ( rows.size() > 0 && selectedRow < rows.size() ) { nextTrans = rows.get( selectedRow ).getLineTransparency(); } int trans = calculateIntMiddle( prevTrans, nextTrans ); if ( trans != -1 ) { newRow.setLineTransparency( trans ); } } // lineWidth if ( thematicGrouping.getLineWidth() instanceof SingleDouble ) { newRow.setLineWidth( thematicGrouping.getLineWidth().getMin() ); } else { double prevWidth = Double.NaN; if ( rows.size() > 0 && selectedRow > 0 ) { prevWidth = rows.get( selectedRow - 1 ).getLineWidth(); } double nextWidth = Double.NaN; if ( rows.size() > 0 && selectedRow < rows.size() ) { nextWidth = rows.get( selectedRow ).getLineWidth(); } double width = calculateDoubleMiddle( prevWidth, nextWidth ); if ( !Double.isNaN( width ) ) { BigDecimal bc = new BigDecimal( width ); newRow.setLineWidth( bc.setScale( 2, BigDecimal.ROUND_HALF_UP ).doubleValue() ); } } // lineStyle newRow.setLineStyle( thematicGrouping.getLineStyle() ); // size if ( thematicGrouping.getSize() instanceof SingleDouble ) { newRow.setSize( thematicGrouping.getSize().getMin() ); } else { double prevSize = Double.NaN; if ( rows.size() > 0 && selectedRow > 0 ) { prevSize = rows.get( selectedRow - 1 ).getSize(); } double nextSize = Double.NaN; if ( rows.size() > 0 && selectedRow < rows.size() ) { nextSize = rows.get( selectedRow ).getSize(); } double size = calculateDoubleMiddle( prevSize, nextSize ); if ( !Double.isNaN( size ) ) { BigDecimal bc = new BigDecimal( size ); newRow.setSize( bc.setScale( 2, BigDecimal.ROUND_HALF_UP ).doubleValue() ); } } // symbol newRow.setSymbol( thematicGrouping.getSymbol() ); // lineCap newRow.setLineCap( thematicGrouping.getLineCap() ); rows.add( selectedRow, newRow ); fireTableRowsInserted( selectedRow, selectedRow ); } /** * removes the selected rows * * @param selectedRows * the rows to remove */ public void removeRows( int[] selectedRows ) { Arrays.sort( selectedRows ); for ( int i = selectedRows.length - 1; i > -1; i-- ) { rows.remove( selectedRows[i] ); fireTableRowsDeleted( i, i ); } } private Color calculateMiddleColor( Color c1, Color c2 ) { if ( c1 == null && c2 != null ) { return c2; } else if ( c2 == null && c1 != null ) { return c1; } else if ( c2 != null && c1 != null ) { float r, g, b; float[] rgbs1 = c1.getRGBColorComponents( null ); float[] rgbs2 = c2.getRGBColorComponents( null ); float r1 = Math.min( rgbs1[0], rgbs2[0] ); float r2 = Math.max( rgbs1[0], rgbs2[0] ); r = r1 + ( ( r2 - r1 ) / 2 ); float g1 = Math.min( rgbs1[1], rgbs2[1] ); float g2 = Math.max( rgbs1[1], rgbs2[1] ); g = g1 + ( ( g2 - g1 ) / 2 ); float b1 = Math.min( rgbs1[2], rgbs2[2] ); float b2 = Math.max( rgbs1[2], rgbs2[2] ); b = b1 + ( ( b2 - b1 ) / 2 ); return new Color( r, g, b ); } return null; } private int calculateIntMiddle( int i1, int i2 ) { if ( i1 == -1 && i2 != -1 ) { return i2; } else if ( i2 == -1 && i1 != -1 ) { return i1; } else if ( i2 != -1 && i1 != -1 ) { return Math.min( i1, i2 ) + ( ( Math.max( i1, i2 ) - Math.min( i1, i2 ) ) / 2 ); } return -1; } private double calculateDoubleMiddle( double d1, double d2 ) { if ( Double.isNaN( d1 ) && !Double.isNaN( d2 ) ) { return d2; } else if ( Double.isNaN( d2 ) && !Double.isNaN( d1 ) ) { return d1; } else if ( !Double.isNaN( d2 ) && !Double.isNaN( d1 ) ) { return Math.min( d1, d2 ) + ( ( Math.max( d1, d2 ) - Math.min( d1, d2 ) ) / 2 ); } return Double.NaN; } /** * @param symbolizertype * @param map * @return a list of rules, representing the classification as SLD */ public List<Rule> getClassifiedData( SYMBOLIZERTYPE symbolizertype, PropertyName propertyName ) { switch ( symbolizertype ) { case POINT: return sldClassificationCalculator.createPointClassificationRules( rows, propertyName, styleDialog.isDefaultUnitPixel() ); case POLYGON: return sldClassificationCalculator.createPolygonClassificationRules( rows, propertyName, styleDialog.isDefaultUnitPixel() ); case LINE: return sldClassificationCalculator.createLineClassificationRules( rows, propertyName, styleDialog.isDefaultUnitPixel() ); case LABEL: return sldClassificationCalculator.createLabelClassificationRules( rows, propertyName, styleDialog.isDefaultUnitPixel() ); } return new ArrayList<Rule>(); } public int getColumnCount() { return columns.size(); } public int getRowCount() { return rows.size(); } public Object getValueAt( int rowIndex, int columnIndex ) { ClassificationTableRow<U> row = rows.get( rowIndex ); return row.getValue( columns.get( columnIndex ).getType() ); } @Override public String getColumnName( int column ) { return columns.get( column ).getHeader(); } public String getColumnTooltip( int column ) { return columns.get( column ).getTooltip(); } @Override public void setValueAt( Object value, int rowIndex, int columnIndex ) { ClassificationTableRow<U> row = rows.get( rowIndex ); TableModelEvent event = new TableModelEvent( this, rowIndex, rowIndex, columnIndex, TableModelEvent.UPDATE ); fireTableChanged( event ); row.setValue( getColumnType( columnIndex ), value ); } @Override public boolean isCellEditable( int rowIndex, int columnIndex ) { COLUMNTYPE type = getColumnType( columnIndex ); switch ( type ) { case VALUE: if ( rows.get( rowIndex ).getValue().getMin() == null && rows.get( rowIndex ).getValue().getMax() != null ) { return false; } return true; case COUNT: return false; case FILLCOLOR: case LINECOLOR: case LINETRANSPARENCY: case FILLTRANSPARENCY: case FONTTRANSPARENCY: case LINEWIDTH: case LINESTYLE: case SIZE: case SYMBOL: case LINECAP: return true; case FONTCOLOR: if ( thematicGrouping.getFontColor() instanceof PropertyName ) { return false; } return true; case FONTFAMILY: if ( thematicGrouping.getFontFamily() instanceof PropertyName ) { return false; } return true; case FONTWEIGHT: if ( thematicGrouping.getFontWeight() instanceof PropertyName ) { return false; } return true; case FONTSTYLE: if ( thematicGrouping.getFontStyle() instanceof PropertyName ) { return false; } return true; case FONTSIZE: if ( thematicGrouping.getFontSize() instanceof PropertyName ) { return false; } return true; case ANCHORPOINT: if ( thematicGrouping.getAnchorPoint() instanceof PropertyName ) { return false; } return true; case DISPLACEMENT: if ( thematicGrouping.getDisplacement() instanceof PropertyName ) { return false; } return true; case ROTATION: if ( thematicGrouping.getRotation() instanceof PropertyName ) { return false; } return true; case HALOCOLOR: if ( thematicGrouping.getHaloRadius() instanceof PropertyName ) { return false; } return true; case HALORADIUS: if ( thematicGrouping.getHaloColor() instanceof PropertyName ) { return false; } return true; default: return false; } } public void editingCanceled( ChangeEvent e ) { } @SuppressWarnings("unchecked") public void editingStopped( ChangeEvent e ) { if ( e.getSource() instanceof ClassificationValuesEditor<?> && baseType.changesAffectsOtherRows() ) { // update all classes! ClassificationValuesEditor<U> editor = (ClassificationValuesEditor<U>) e.getSource(); ValueRange<U> vr = editor.getValueRange(); Collections.sort( rows, new ClassificationTableRowComparator<U>( VALUE ) ); Intervallable<U> lastMin = null; boolean deleteEditingRow = false; int indexOfEditedRow = -1; for ( int i = rows.size() - 1; i > -1; i-- ) { ValueRange<U> currentRowValue = rows.get( i ).getValue(); if ( currentRowValue == vr ) { indexOfEditedRow = i; } // update other class borders, only, when classification does not support same class // borders if ( !thematicGrouping.hasSameClassBorders() ) { currentRowValue.setMax( lastMin ); lastMin = currentRowValue.getMin(); } else { // take a look, if class with the same border exist if ( vr.getMin().equals( currentRowValue.getMin() ) && i != indexOfEditedRow ) { deleteEditingRow = true; } } } // delete row, when min and max value are the same and classification does not support // same class borders if ( !thematicGrouping.hasSameClassBorders() && ( ( vr.getMin() != null && vr.getMax() != null && vr.getMin().getValue().equals( vr.getMax().getValue() ) ) ) || ( vr.getMin() == null && vr.getMax() == null ) && indexOfEditedRow > -1 ) { rows.remove( indexOfEditedRow ); } else if ( thematicGrouping.hasSameClassBorders() ) { // if same class borders are supported, set max value to min value, otherwise update // class borders if ( deleteEditingRow ) { rows.remove( indexOfEditedRow ); } else { vr.setMax( vr.getMin() ); } } editor.setValueRange( vr ); } sort( COLUMNTYPE.VALUE, true ); updatedCount(); } /** * @param column * the type of the column to return the index * @return the index of the column with the given type or -1 if no column with this type exist */ public int getColumnIndex( COLUMNTYPE column ) { for ( Column col : columns ) { if ( col.getType().equals( column ) ) { return columns.indexOf( col ); } } return -1; } /** * @param columnIndex * the index of the column to return the type * @return the type of the column in the specified index or null, if a column with the index does not exist */ public COLUMNTYPE getColumnType( int columnIndex ) { if ( columns.get( columnIndex ) != null ) { return columns.get( columnIndex ).getType(); } return null; } /** * @return the rows */ public List<ClassificationTableRow<U>> getRows() { return rows; } /** * @param index * the index of the row to return * @return the row on the given index, or null, if no row exists */ public ClassificationTableRow<U> getRowAt( int index ) { if ( index > -1 && index < rows.size() ) { return rows.get( index ); } return null; } private void updatedCount() { List<ValueRange<U>> values = new ArrayList<ValueRange<U>>(); for ( ClassificationTableRow<U> row : rows ) { values.add( row.getValue() ); } thematicGrouping.updateValueCounts( values ); } }