Package org.locationtech.udig.style.sld.editor.raster

Source Code of org.locationtech.udig.style.sld.editor.raster.SingleBandEditorPage

/*
*    uDig - User Friendly Desktop Internet GIS client
*    http://udig.refractions.net
*    (C) 2011, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.style.sld.editor.raster;

import java.io.File;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import org.locationtech.udig.catalog.ID;
import org.locationtech.udig.catalog.IGeoResource;
import org.locationtech.udig.project.internal.Layer;
import org.locationtech.udig.project.internal.StyleBlackboard;
import org.locationtech.udig.style.sld.SLDContent;
import org.locationtech.udig.style.sld.SLDPlugin;
import org.locationtech.udig.style.sld.editor.CustomDynamicPalette;
import org.locationtech.udig.style.sld.editor.CustomPalettesLoader;
import org.locationtech.udig.style.sld.editor.StyleEditor;
import org.locationtech.udig.style.sld.editor.StyleEditorPage;
import org.locationtech.udig.style.sld.editor.internal.BrewerPaletteLabelProvider;
import org.locationtech.udig.style.sld.editor.raster.PredefinedColorRules.PredefinedColorRule;
import org.locationtech.udig.style.sld.editor.raster.ValueFormatter.DataType;
import org.locationtech.udig.style.sld.internal.Messages;
import org.locationtech.udig.ui.PlatformGIS;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.geotools.brewer.color.BrewerPalette;
import org.geotools.brewer.color.ColorBrewer;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.styling.ColorMap;
import org.geotools.styling.ColorMapEntry;
import org.geotools.styling.ColorMapEntryImpl;
import org.geotools.styling.ColorMapImpl;
import org.geotools.styling.RasterSymbolizer;
import org.geotools.styling.SLD;
import org.geotools.styling.SLDTransformer;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.coverage.grid.GridCoverageReader;

/**
* Style editor page for single banded rasters
* that allow users to create styles for
* each ColorMap type -
* ColorMap.TYPE_RAMP,
* ColorMap.TYPE_INTERVALS,
* ColorMap.TYPE_VALUES
*
* @author Emily Gouge (Refractions Research Inc.)
*
*/
public class SingleBandEditorPage extends StyleEditorPage {
  /**
   * Maximum number of unique values supported by
   * the geotools styling.
   */
  public static final int MAX_ENTRIES = 256;

 
    private static final String SLD_EXTENSION = ".sld"; //$NON-NLS-1$

    private double[] noDataValues = null;
   
  private StyleFactory sf = CommonFactoryFinder.getStyleFactory(null);
  private LabelProvider brewerLblProvider = new BrewerPaletteLabelProvider();
 
    final private IColorMapTypePanel[] stylePanels = new IColorMapTypePanel[]{
        new UniqueValuesPanel(this),
        new RampValuesPanel(this),
        new IntervalValuesPanel(this)
    };

    private String errorMessage = null;
   
  private ComboViewer cmbThemingStyle;
  private ComboViewer cmbPalette;
  private Composite tableComp;
  private ColorBrewer brewer = null;
  private boolean reverseColors = false;
  private ValueFormatter formatter;
 
  private PredefinedColorRules colorRules;
 
  /**
   * Creates a new style editor page
   */
  public SingleBandEditorPage() {
    super();
    formatter = new ValueFormatter();
   
  }

  /**
   * @see org.locationtech.udig.style.sld.IEditorPage#okToLeave()
   */
  @Override
  public boolean okToLeave() {
    return errorMessage == null;
  }

  @Override
  public boolean performOk() {
    return performApply();
  }

  @Override
  public boolean performApply() {
    try{
      updateStyle();
    }catch (Exception ex){
      SLDPlugin.log("Error applying style.", ex); //$NON-NLS-1$
      MessageDialog.openError(getShell(), Messages.SingleBandEditorPage_Error, Messages.SingleBandEditorPage_ApplyError + ex.getLocalizedMessage());
      return false;
    }
    return true;
  }

  @Override
  public void refresh() {
    init();
  }
 
 
  @Override
  public void createPageContent(Composite parent) {
   
    Composite main = new Composite(parent, SWT.NONE);
    main.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    main.setLayout(new GridLayout(3, false));

    Label lbl = new Label(main, SWT.NONE);
    lbl.setText(Messages.SingleBandEditorPage_ThemingStyleLabel);
    cmbThemingStyle = new ComboViewer(main, SWT.DROP_DOWN | SWT.READ_ONLY);
    cmbThemingStyle.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, false,
        false, 2, 1));
    ((GridData)cmbThemingStyle.getControl().getLayoutData()).widthHint = 150;
    cmbThemingStyle.setContentProvider(ArrayContentProvider.getInstance());
    cmbThemingStyle.setInput(stylePanels);
    cmbThemingStyle.setLabelProvider(new LabelProvider(){
      @Override
      public String getText(Object element){
        if (element instanceof IColorMapTypePanel){
          return ((IColorMapTypePanel) element).getName();
        }
        return super.getText(element);
      }
    });
   

    lbl = new Label(main, SWT.NONE);
    lbl.setText(Messages.SingleBandEditorPage_ColorPaletteLabel);
    cmbPalette = createPaletteViewer(main);

    final Button btnTest = new Button(main, SWT.PUSH);
    btnTest.setText(Messages.SingleBandEditorPage_ComputeBreaksButtonText);
    btnTest.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
    btnTest.addSelectionListener(new SelectionAdapter(){
      @Override
      public void widgetSelected(SelectionEvent e){
        getCurrentSelection().computeValues();
      }
    });
   
    tableComp = new Composite(main, SWT.NONE);
    tableComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
    tableComp.setLayout(new StackLayout());
   
    final HashMap<IColorMapTypePanel, Composite> stacks = new HashMap<IColorMapTypePanel, Composite>();
    for (IColorMapTypePanel pnl : stylePanels){
      Composite stack = pnl.createControl(tableComp);
      stacks.put(pnl, stack);
    }
   
    Composite linkPnl = new Composite(main, SWT.NONE);
    linkPnl.setLayout(new GridLayout(4, false));
    linkPnl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1));
   
   
    Link lnk = new Link(linkPnl, SWT.NONE);
    lnk.setText("<a>" + Messages.SingleBandEditorPage_ReverseColorLabel + "</a>"); //$NON-NLS-1$ //$NON-NLS-2$
    lnk.addSelectionListener(new SelectionAdapter() {
     
      @Override
      public void widgetSelected(SelectionEvent e) {
        reverseColors = !reverseColors;
        if (getCurrentSelection() != null){
          Object x = ((IStructuredSelection)cmbPalette.getSelection()).getFirstElement();
          if (x instanceof BrewerPalette){
            BrewerPalette palette = (BrewerPalette) ((IStructuredSelection)cmbPalette.getSelection()).getFirstElement();
            getCurrentSelection().setColorPalette(palette, reverseColors);
          }else if (x instanceof PredefinedColorRule){
            ColorMap cm = ((PredefinedColorRule)x).getColorMap();
            if (cm != null && getCurrentSelection() != null){
              //flip colors
              if (reverseColors){
                ColorMap reverse = new ColorMapImpl();
                for (int i = 0; i < cm.getColorMapEntries().length; i ++){
                  ColorMapEntry entry = cm.getColorMapEntries()[i];
                  ColorMapEntry clone = new ColorMapEntryImpl();
                  clone.setColor(cm.getColorMapEntry(cm.getColorMapEntries().length - 1 - i).getColor());
                  clone.setLabel(entry.getLabel());
                  clone.setQuantity(entry.getQuantity());
                  clone.setOpacity(entry.getOpacity());
                  reverse.addColorMapEntry(clone);
                 
                }
                cm = reverse;
              }
             
              getCurrentSelection().init(cm);
            }
          }
        }
      }
    });
   
    Label lblSep = new Label(linkPnl, SWT.SEPARATOR | SWT.VERTICAL);
    GridData gd = new GridData(SWT.FILL, SWT.FILL, false, false);
    gd.heightHint = 10;
    lblSep.setLayoutData(gd);
   
    lnk = new Link(linkPnl, SWT.NONE);
    lnk.setText("<a>" + Messages.SingleBandEditorPage_FormatExportLink + "</a>")//$NON-NLS-1$ //$NON-NLS-2$
    lnk.addSelectionListener(new SelectionAdapter() {
     
      @Override
      public void widgetSelected(SelectionEvent e) {
        getFormat();
      }
    });
   
    Link lnk2 = new Link(linkPnl, SWT.NONE);
    lnk2.setText("<a>" + Messages.SingleBandEditorPage_OneClickExportLink + "</a>"); //$NON-NLS-1$ //$NON-NLS-2$
    lnk2.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
    lnk2.setToolTipText(Messages.SingleBandEditorPage_OneClickTooltip);
    lnk2.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        oneClickExport();
      }
    });
   
   
    cmbThemingStyle.getCombo().addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        IColorMapTypePanel panel = getCurrentSelection();
        if (panel != null){
          ((StackLayout)tableComp.getLayout()).topControl = stacks.get(panel);
          tableComp.layout();
          btnTest.setText(panel.getComputeValuesLabel());
          btnTest.getParent().layout();
         

          Object x = ((IStructuredSelection)cmbPalette.getSelection()).getFirstElement();;
          if (x instanceof BrewerPalette){
            BrewerPalette palette = (BrewerPalette) x;
            getCurrentSelection().setInitialColorPalette(palette);
          }else if (x instanceof PredefinedColorRule){
            ColorMap cm = ((PredefinedColorRule)x).getColorMap();
            if (cm != null && getCurrentSelection() != null){
              getCurrentSelection().init(cm);
            }
           
          }
        }
      }
    });
   
   
    cmbPalette.addSelectionChangedListener(new ISelectionChangedListener() {     
      @Override
      public void selectionChanged(SelectionChangedEvent event) {
        Object x = ((IStructuredSelection)cmbPalette.getSelection()).getFirstElement();;
        if (x instanceof BrewerPalette){
          BrewerPalette palette = (BrewerPalette) x;
          if (getCurrentSelection() != null){
            getCurrentSelection().setColorPalette(palette, reverseColors);
          }
        }else if (x instanceof PredefinedColorRule){
          ColorMap cm = ((PredefinedColorRule)x).getColorMap();
          if (cm != null && getCurrentSelection() != null){
            getCurrentSelection().init(cm);
          }
        }
       
      }
    });

    cmbThemingStyle.getControl().addDisposeListener(new DisposeListener() {
      @Override
      public void widgetDisposed(DisposeEvent e) {
        if (colorRules != null){
          colorRules.dispose();
        }
      }
    });
   
    init();
  }

  private void getFormat(){
    FormatDialog fd = new FormatDialog(getShell(), this.formatter);
    if (fd.open() == FormatDialog.OK){
      if (fd.getSelectedDataType() != null){
        formatter.setDataType(fd.getSelectedDataType());
        formatter.setNumberFormatter(null);
      }else if (fd.getSelectedDataType() == null && fd.getCustom() == null){
        formatter.setDataType(null);
        formatter.setNumberFormatter(null);
      }else{
        formatter.setNumberFormatter(fd.getCustom());
      }
      for (IColorMapTypePanel pnl : stylePanels){
        pnl.refresh();
      }
    }
  }
 
  /*
   * Performs a single click export which exports
   * the style to a .sld file beside the associated layer file.
   * Does nothing for non-file based layers.
   */
  private void oneClickExport(){
    IGeoResource geoResource = getSelectedLayer().getGeoResource();
        ID id = geoResource.getID();
    if (id.isFile()) {
      try {
        File file = id.toFile();
        SLDTransformer aTransformer = new SLDTransformer();
        aTransformer.setIndentation(StyleEditor.INDENT);
        String xml = aTransformer.transform(getSLD());
        File newFile = new File(file.getParent(), FilenameUtils
            .getBaseName(file.getAbsolutePath())
            + SLD_EXTENSION);
        FileUtils.writeStringToFile(newFile, xml);
        MessageDialog.openInformation(getShell(), Messages.SingleBandEditorPage_ExportOkDialogTitle, Messages.SingleBandEditorPage_ExportOkDialogMessage);
      } catch (Exception e1) {
        MessageDialog.openError(getShell(), Messages.SingleBandEditorPage_ErrorDialogTitle,
            Messages.SingleBandEditorPage_ErrorMessage);
        e1.printStackTrace();
      }
    } else {
      MessageDialog.openWarning(getShell(), Messages.SingleBandEditorPage_WarningDialogTitle,
          Messages.SingleBandEditorPage_WarningMessage);
    }
  }
  /**
   *
   * @return the current selected color map panel
   */
  private IColorMapTypePanel getCurrentSelection(){
    return (IColorMapTypePanel) ((IStructuredSelection)cmbThemingStyle.getSelection()).getFirstElement();
  }
 
 
  /**
   * If you call then function you MUST dispose of the reader
   * when you are finished with it!
   *
   * @return the grid coverage associated with the current
   * layer being styled
   */
  public GridCoverageReader getGridCoverageReader(){ 
    try {
      GridCoverageReader reader = getSelectedLayer().getGeoResource().resolve(GridCoverageReader.class, null);
      return reader;
     
    }catch (Exception ex){
      SLDPlugin.log("Error getting grid coverage.", ex); //$NON-NLS-1$
    }
    return null;
  }
 
  public static final void sortEntries(ColorMapEntry[] entries){
    Arrays.sort(entries, new Comparator<ColorMapEntry>(){

      @Override
      public int compare(ColorMapEntry c0, ColorMapEntry c1) {
        Number v1 = (Number) c0.getQuantity().evaluate(null, Double.class);
        Number v2 = (Number) c1.getQuantity().evaluate(null, Double.class);
        return ((Double)v1.doubleValue()).compareTo(v2.doubleValue());
      }});
  }
 
  /**
   * Updates the style of the current layer
   * with the style specified the current style
   * panel.
   *
   * @throws Exception
   */
  private void updateStyle() throws Exception{
        RasterSymbolizer rasterSym = sf.createRasterSymbolizer();
              
        ColorMap colorMap = getCurrentSelection().getColorMap();
        rasterSym.setColorMap(colorMap);

        Style newStyle = SLD.wrapSymbolizers(rasterSym);
        newStyle.setName(((Layer)getSelectedLayer()).getName() );
        StyleBlackboard styleBlackboard = getSelectedLayer().getStyleBlackboard();

        // put style back on blackboard
        styleBlackboard.put(SLDContent.ID, newStyle);
        styleBlackboard.setSelected(new String[]{SLDContent.ID});
       
        Object x = ((IStructuredSelection)cmbPalette.getSelection()).getFirstElement();
        if (x instanceof BrewerPalette){
          BrewerPalette palette = (BrewerPalette) x;
          if (palette != null){
            styleBlackboard.put("org.locationtech.udig.style.raster.palette", palette.getName()); //$NON-NLS-1$
          }
        }else if (x instanceof PredefinedColorRule){
          styleBlackboard.put("org.locationtech.udig.style.raster.palette", ((PredefinedColorRule) x).getName()); //$NON-NLS-1$
        }
 
  }
 
 
  private ComboViewer createPaletteViewer(Composite parent) {
    ComboViewer thiscv = new ComboViewer(parent, SWT.DROP_DOWN
        | SWT.READ_ONLY);
    thiscv.getControl().setLayoutData(
        new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
    ((GridData)thiscv.getControl().getLayoutData()).widthHint = 150;
    // list of matching palettes
    
   
    thiscv.setLabelProvider(new LabelProvider(){
     
      public String getText(Object element){
        if (element instanceof BrewerPalette){
          return brewerLblProvider.getText(element);
        }else if (element instanceof String){
          return (String)element;
        }else if (element instanceof PredefinedColorRule){
          return ((PredefinedColorRule) element).getName();
        }
        return super.getText(element);
      }
    });
    thiscv.setContentProvider(ArrayContentProvider.getInstance());
   
   
    return thiscv;

  }

  private ColorBrewer getBrewer() {
    if (brewer == null) {
      brewer = PlatformGIS.getColorBrewer();

      // add custom palettes
      List<BrewerPalette> palettesList = CustomPalettesLoader.PALETTESLIST;
      for (BrewerPalette brewerPalette : palettesList) {
        brewer.registerPalette(brewerPalette);
      }
      // add a dynamic one that support everything
      CustomDynamicPalette customDynamicPalette = new CustomDynamicPalette(
          CustomDynamicPalette.TABLE.RAINBOW);
      brewer.registerPalette(customDynamicPalette);
      customDynamicPalette = new CustomDynamicPalette(
          CustomDynamicPalette.TABLE.GREY);
      brewer.registerPalette(customDynamicPalette);

    }
    return brewer;
  }

  @Override
  public String getLabel() {
    return null;
  }

  @Override
  public boolean performCancel() {
    return false;
  }

  @Override
  public void gotFocus() {
    cmbPalette.getControl().setFocus();
  }

  @Override
  public void styleChanged(Object source) {

  }

  /**
   *
   * @return the nodata values associated with the grid coverate
   * <code>null</code> if no, no data values found
   */
  public double[] getNoDataValues(){
    return this.noDataValues;
  }
 
 
  private void init(){
    Layer l = getSelectedLayer();
   
    for (IColorMapTypePanel pnl : stylePanels){
      pnl.setFormatter(this.formatter);
    }
    try{
      GridCoverage coverage = l.getGeoResource().resolve(GridCoverage.class, null);
     
      if (coverage.getNumSampleDimensions() > 0){
        formatter.setRawDataType(coverage.getSampleDimension(0).getSampleDimensionType());
        this.noDataValues = coverage.getSampleDimension(0).getNoDataValues();     
      }
    }catch (Exception ex){
      //eat me
    }
    if (colorRules != null){
      colorRules.dispose();
      colorRules = null;
    }
    colorRules = new PredefinedColorRules(getGridCoverageReader(), this.noDataValues);
   
    Style style = (Style) l.getStyleBlackboard().get(SLDContent.ID);
   
    RasterSymbolizer symbolizer = SLD.rasterSymbolizer(style);
    if (symbolizer == null || symbolizer.getColorMap() == null){
      //no symbolizer
     
    }else{
      ColorMap cm = symbolizer.getColorMap();
      for (IColorMapTypePanel pnl : stylePanels){
        if (pnl.canSupport(cm.getType())){
          pnl.init(cm);
          cmbThemingStyle.setSelection(new StructuredSelection(pnl));
          cmbThemingStyle.getControl().notifyListeners(SWT.Selection, new Event());
        }
      }
      if (formatter.getRawDataType() == DataType.INTEGER){
        //if some of the entries are doubles we want to format in double
        //regardless of the fact that the raster is an integer raster.
        try{
          for (ColorMapEntry e : cm.getColorMapEntries()){
            Double dvalue = (Double) e.getQuantity().evaluate(null, Double.class);
            Integer ivalue = (Integer) e.getQuantity().evaluate(null, Integer.class);
            if (ivalue.doubleValue() != dvalue){
              formatter.setDataType(DataType.DOUBLE);
            }
          }
        }catch (Exception ex){
          //eatme
        }
      }
     
    }
   
    //set inputs based on brewer and colorRules
    List<Object> inputs = new ArrayList<Object>();
    BrewerPalette[] palettes = getBrewer().getPalettes(ColorBrewer.ALL);
    Arrays.sort(palettes, 0, palettes.length, new Comparator<BrewerPalette>(){
      @Override
      public int compare(BrewerPalette arg0,
          BrewerPalette arg1) {
        return Collator.getInstance().compare(brewerLblProvider.getText(arg0), brewerLblProvider.getText(arg1));
      }});
    for (BrewerPalette p : palettes){
      inputs.add(p);
    }
    inputs.add(Messages.SingleBandEditorPage_predefinedStyleSeperator);
    for (PredefinedColorRule key: colorRules.getPredefinedSets()){
      inputs.add(key);
    }
    cmbPalette.setInput(inputs);
   
    /* reselect based on blackboard setting */
    String paletteName = (String) l.getStyleBlackboard().get("org.locationtech.udig.style.raster.palette"); //$NON-NLS-1$
    if (paletteName != null){
      ColorBrewer cb = getBrewer();
      BrewerPalette palette = cb.getPalette(paletteName);
      if (palette != null){
        cmbPalette.setSelection(new StructuredSelection(cb.getPalette(paletteName)));
      }else{
        PredefinedColorRule cm = colorRules.getPredefinedRule(paletteName);
        if (cm != null){
          cmbPalette.setSelection(new StructuredSelection(cm));
        }
      }
    }
   
  }

  @Override
  public String getErrorMessage() {
    return errorMessage;
  }
 
  public void setErrorMessage(String message){
    this.errorMessage = message;
    super.getContainer().updateMessage();
  }
}
TOP

Related Classes of org.locationtech.udig.style.sld.editor.raster.SingleBandEditorPage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.