/**
* OrbisGIS is a java GIS application dedicated to research in GIScience.
* OrbisGIS is developed by the GIS group of the DECIDE team of the
* Lab-STICC CNRS laboratory, see <http://www.lab-sticc.fr/>.
*
* The GIS group of the DECIDE team is located at :
*
* Laboratoire Lab-STICC – CNRS UMR 6285
* Equipe DECIDE
* UNIVERSITÉ DE BRETAGNE-SUD
* Institut Universitaire de Technologie de Vannes
* 8, Rue Montaigne - BP 561 56017 Vannes Cedex
*
* OrbisGIS is distributed under GPL 3 license.
*
* Copyright (C) 2007-2014 CNRS (IRSTV FR CNRS 2488)
* Copyright (C) 2015-2017 CNRS (Lab-STICC UMR CNRS 6285)
*
* This file is part of OrbisGIS.
*
* OrbisGIS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* OrbisGIS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* OrbisGIS. If not, see <http://www.gnu.org/licenses/>.
*
* For more information, please consult: <http://www.orbisgis.org/>
* or contact directly:
* info_at_ orbisgis.org
*/
package org.orbisgis.legend.thematic.recode;
import org.orbisgis.coremap.renderer.se.AreaSymbolizer;
import org.orbisgis.coremap.renderer.se.Symbolizer;
import org.orbisgis.coremap.renderer.se.common.Uom;
import org.orbisgis.coremap.renderer.se.fill.Fill;
import org.orbisgis.coremap.renderer.se.fill.SolidFill;
import org.orbisgis.coremap.renderer.se.stroke.PenStroke;
import org.orbisgis.coremap.renderer.se.stroke.Stroke;
import org.orbisgis.legend.structure.fill.RecodedSolidFillLegend;
import org.orbisgis.legend.structure.recode.*;
import org.orbisgis.legend.structure.stroke.RecodedPenStroke;
import org.orbisgis.legend.thematic.AreaParameters;
import org.orbisgis.legend.thematic.EnablesStroke;
import org.orbisgis.legend.thematic.uom.StrokeUom;
import org.xnap.commons.i18n.I18n;
import org.xnap.commons.i18n.I18nFactory;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Wrapper for unique value classification that are made on AreaSymbolizer instances.
* @author Alexis Guéganno
*/
public class RecodedArea extends AbstractRecodedLegend<AreaParameters>
implements EnablesStroke {
private AreaSymbolizer areaSymbolizer;
private final RecodedSolidFillLegend fill;
private RecodedPenStroke ps;
private static final I18n I18N = I18nFactory.getI18n(RecodedArea.class);
public static final String NAME = I18N.tr("Value Classification - Area");
/**
* Default constructor : builds an empty classification based on the default {@link AreaSymbolizer}.
*/
public RecodedArea(){
this(new AreaSymbolizer());
}
/**
* Builds a new {@code RecodedArea} considering that {@code sym} matches the configuration constraints expected
* by this class. That means it must be made of a {@link PenStroke} and of a {@link SolidFill} and that both of
* them are built with literals or recode instances containing only literals, and that the recode instances are
* all built with the same analysis field. Use the analyzer dedicated to area to check that automatically.
* @param sym The base Symbolizer
*/
public RecodedArea(AreaSymbolizer sym){
areaSymbolizer=sym;
Stroke p = areaSymbolizer.getStroke();
if(p instanceof PenStroke){
ps=new RecodedPenStroke((PenStroke)p);
} else if( p == null){
ps = null;
} else {
throw new UnsupportedOperationException("Can't build a RecodedLine with such a Stroke: "+p.getClass().getName());
}
Fill originalFill = areaSymbolizer.getFill();
if(originalFill instanceof SolidFill){
this.fill = new RecodedSolidFillLegend((SolidFill)originalFill);
} else {
throw new UnsupportedOperationException("Can't build a RecodedLine with such a Fill: "+originalFill.getClass().getName());
}
FieldAggregatorVisitor fav = new FieldAggregatorVisitor();
applyGlobalVisitor(fav);
String f = getLookupFieldName();
if(!f.isEmpty()){
SetFieldVisitor sfv = new SetFieldVisitor(f);
applyGlobalVisitor(sfv);
}
}
@Override
public Symbolizer getSymbolizer() {
return areaSymbolizer;
}
@Override
public String getLegendTypeName() {
return NAME;
}
/**
* Gets the wrapper that manages the width of the line.
* @return the recoded width
*/
public RecodedReal getLineWidth(){
return ps == null ? null :ps.getWidthLegend();
}
/**
* Gets the wrapper that manages the opacity of the line.
* @return the recoded opacity
*/
public RecodedReal getLineOpacity(){
return ps == null ? null :(RecodedReal) ps.getFillLegend().getFillOpacityLegend();
}
/**
* Gets the wrapper that manages the color of the line.
* @return the recoded color
*/
public RecodedColor getLineColor(){
return ps == null ? null :(RecodedColor) ps.getFillLegend().getFillColorLegend();
}
/**
* Gets the wrapper that manages the dash pattern of the line.
* @return the recoded dash
*/
public RecodedString getLineDash() {
return ps == null ? null :ps.getDashLegend();
}
/**
* Gets the wrapper that manages the opacity of the line.
* @return the recoded opacity
*/
public RecodedReal getFillOpacity(){
return (RecodedReal) fill.getFillOpacityLegend();
}
/**
* Gets the wrapper that manages the color of the line.
* @return the recoded color
*/
public RecodedColor getFillColor(){
return (RecodedColor) fill.getFillColorLegend();
}
@Override
public Uom getStrokeUom() {
return ps == null ? Uom.PX : areaSymbolizer.getStroke().getUom();
}
@Override
public void setStrokeUom(Uom u) {
if(ps != null){
areaSymbolizer.getStroke().setUom(u);
}
}
@Override
public AreaParameters get(Object objKey) {
String key = (String) objKey;
if(!keySet().contains(key)){
return null;
}
Color sc;
Double sop;
Double w;
String d;
if(ps !=null){
sc = getLineColor().getItemValue(key);
sc = sc==null ? getLineColor().getFallbackValue() : sc;
sop = getLineOpacity().getItemValue(key);
sop = sop==null || sop.isNaN() ? getLineOpacity().getFallbackValue() : sop;
w = getLineWidth().getItemValue(key);
w = w==null || w.isNaN()? getLineWidth().getFallbackValue() : w;
d = getLineDash().getItemValue(key);
d = d==null ? getLineDash().getFallbackValue() : d;
} else {
sc= Color.WHITE;
sop = 0.0;
w = 0.0;
d = "";
}
Color fc = getFillColor().getItemValue(key);
fc = fc==null ? getFillColor().getFallbackValue() : fc;
Double fop = getFillOpacity().getItemValue(key);
fop = sop==null || fop.isNaN() ? getFillOpacity().getFallbackValue() : fop;
return new AreaParameters(sc,sop,w,d,fc,fop);
}
@Override
public AreaParameters put(String key, AreaParameters value) {
if(key == null || value == null){
throw new NullPointerException("We don't manage null as key");
}
AreaParameters ret = keySet().contains(key) ? get(key) : null;
if(this.ps != null){
getLineColor().addItem(key, value.getLineColor());
getLineOpacity().addItem(key, value.getLineOpacity());
getLineWidth().addItem(key, value.getLineWidth());
getLineDash().addItem(key, value.getLineDash());
}
getFillColor().addItem(key, value.getFillColor());
getFillOpacity().addItem(key, value.getFillOpacity());
return ret;
}
@Override
public AreaParameters remove(Object objKey) {
String key = (String) objKey;
if(key == null){
throw new NullPointerException("We don't manage null as key");
}
AreaParameters ret = keySet().contains(key) ? get(key) : null;
if(this.ps != null){
getLineColor().removeItem(key);
getLineDash().removeItem(key);
getLineOpacity().removeItem(key);
getLineWidth().removeItem(key);
}
getFillColor().removeItem(key);
getFillOpacity().removeItem(key);
return ret;
}
@Override
public List<RecodedLegend> getRecodedLegends() {
List<RecodedLegend> psl = ps == null ? new ArrayList<RecodedLegend>() : ps.getRecodedLegends();
List<RecodedLegend> fsl = fill.getRecodedLegends();
List<RecodedLegend> ret = new ArrayList<RecodedLegend>(psl.size()+fsl.size());
ret.addAll(psl);
ret.addAll(fsl);
return ret;
}
@Override
public AreaParameters getFallbackParameters(){
if(ps == null){
return new AreaParameters(Color.WHITE,
0.0,
0.0,
"",
getFillColor().getFallbackValue(),
getFillOpacity().getFallbackValue());
} else {
return new AreaParameters(getLineColor().getFallbackValue(),
getLineOpacity().getFallbackValue(),
getLineWidth().getFallbackValue(),
getLineDash().getFallbackValue(),
getFillColor().getFallbackValue(),
getFillOpacity().getFallbackValue());
}
}
@Override
public void setFallbackParameters(AreaParameters ap){
if(ps != null){
getLineColor().setFallbackValue(ap.getLineColor());
getLineOpacity().setFallbackValue(ap.getLineOpacity());
getLineWidth().setFallbackValue(ap.getLineWidth());
getLineDash().setFallbackValue(ap.getLineDash());
}
getFillColor().setFallbackValue(ap.getFillColor());
getFillOpacity().setFallbackValue(ap.getFillOpacity());
}
@Override
public int hashCode(){
int ret = 0;
Set<Entry<String, AreaParameters>> entries = entrySet();
for(Map.Entry m : entries){
ret += m.hashCode();
}
return ret;
}
@Override
public String getLegendTypeId() {
return "org.orbisgis.legend.thematic.recode.RecodedArea";
}
@Override
public boolean isStrokeEnabled(){
return ps != null;
}
@Override
public void setStrokeEnabled(boolean enable){
if(enable && ps ==null){
PenStroke stroke = new PenStroke();
areaSymbolizer.setStroke(stroke);
ps = new RecodedPenStroke(stroke);
String lfn = fill.getRecodedLegends().get(0).getField();
for( RecodedLegend rl : ps.getRecodedLegends()){
rl.setField(lfn);
}
} else if(!enable && ps != null){
areaSymbolizer.setStroke(null);
ps = null;
}
}
}