/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C)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.render2d.control;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JMenu;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import org.apache.sis.feature.FeatureExt;
import org.geotoolkit.storage.coverage.CoverageReference;
import org.geotoolkit.coverage.io.GridCoverageReader;
import org.geotoolkit.display2d.container.ContextContainer2D;
import org.geotoolkit.gui.swing.render2d.JMap2D;
import org.geotoolkit.gui.swing.navigator.JNavigator;
import org.geotoolkit.gui.swing.navigator.JNavigatorBand;
import org.geotoolkit.gui.swing.resource.MessageBundle;
import org.geotoolkit.map.ContextListener;
import org.geotoolkit.map.CoverageMapLayer;
import org.geotoolkit.map.FeatureMapLayer;
import org.geotoolkit.map.MapContext;
import org.geotoolkit.map.MapItem;
import org.geotoolkit.map.MapLayer;
import org.apache.sis.referencing.CRS;
import org.geotoolkit.style.RandomStyleBuilder;
import org.geotoolkit.util.collection.CollectionChangeEvent;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.TemporalCRS;
import org.opengis.style.Description;
import org.opengis.util.InternationalString;
/**
*
* @author Johann Sorel
* @module
*/
public class JLayerBandMenu extends JMenu implements ContextListener{
private final JNavigator navigator;
private WeakReference<JMap2D> map = null;
public JLayerBandMenu(final JNavigator navigator){
super(MessageBundle.format("layers"));
this.navigator = navigator;
}
@Override
public boolean isEnabled() {
return getMap() != null;
}
public JMap2D getMap() {
if(map != null){
return map.get();
}
return null;
}
public void setMap(final JMap2D map) {
this.map = new WeakReference<JMap2D>(map);
checkBands();
if(map != null){
map.getContainer().addPropertyChangeListener(this);
final MapContext context = map.getContainer().getContext();
if(context != null){
context.addContextListener(new ContextListener.Weak(this));
layerChange(new CollectionChangeEvent<MapLayer>(this, context.layers(), CollectionChangeEvent.ITEM_ADDED, null,null));
}
}
}
private void checkBands(){
for(JNavigatorBand b : new ArrayList<JNavigatorBand>(navigator.getBands())){
navigator.getBands().remove(b);
}
}
@Override
public void layerChange(CollectionChangeEvent<MapLayer> event) {
final JMap2D map2d = getMap();
if(map2d == null){
return;
}
final MapContext context = map2d.getContainer().getContext();
if(context == null){
return;
}
removeAll();
final List<MapLayer> layers = new ArrayList<MapLayer>();
parseItem(context, layers);
for(final MapLayer layer : layers){
add(new LayerPane(layer));
}
if(event == null){
return;
}
final int type = event.getType();
if(type == CollectionChangeEvent.ITEM_ADDED && navigator.getModel().getCRS() instanceof TemporalCRS){
//automaticaly add temporal layer bands.
for(MapLayer ml : event.getItems()){
CoordinateReferenceSystem crs = null;
if(ml instanceof CoverageMapLayer){
final CoverageMapLayer cml = (CoverageMapLayer) ml;
final CoverageReference ref = cml.getCoverageReference();
try {
final GridCoverageReader reader = ref.acquireReader();
crs = reader.getGridGeometry(ref.getImageIndex()).getCoordinateReferenceSystem();
ref.recycle(reader);
} catch (Exception ex) {
//we tryed ...
}
}else if(ml instanceof FeatureMapLayer){
final FeatureMapLayer fml = (FeatureMapLayer) ml;
crs = FeatureExt.getCRS(fml.getCollection().getFeatureType());
}
if(crs != null){
final TemporalCRS tc = CRS.getTemporalComponent(ml.getBounds().getCoordinateReferenceSystem());
if(tc != null){
//add it in the bands
final JLayerBand band = new JLayerBand(ml);
navigator.getBands().add(band);
for(Component c : getMenuComponents()){
if(!(c instanceof LayerPane)){
continue;
}
final LayerPane lp = (LayerPane) c;
if(lp.layer == ml){
lp.update();
break;
}
}
}
}
}
}else if(type == CollectionChangeEvent.ITEM_REMOVED){
//update the navigator bands
for(JNavigatorBand b : new ArrayList<JNavigatorBand>(navigator.getBands())){
if(b instanceof JLayerBand){
final JLayerBand lb = (JLayerBand) b;
if(!layers.contains(lb.getLayer())){
navigator.getBands().remove(b);
}
}
}
}
}
@Override
public void itemChange(CollectionChangeEvent<MapItem> event) {
final Collection<MapItem> items = event.getItems();
final List<MapLayer> layers = new ArrayList<MapLayer>();
for (MapItem item : items) {
parseItem(item, layers);
}
final CollectionChangeEvent newEvent = new CollectionChangeEvent(
event.getSource(), layers, event.getType(), event.getRange(), event);
layerChange(newEvent);
}
protected void parseItem (final MapItem source, final List<MapLayer> destination) {
if (source instanceof MapLayer) {
destination.add((MapLayer) source);
} else {
for (MapItem child : source.items()) {
parseItem(child, destination);
}
}
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
final String propName = evt.getPropertyName();
if(propName.equals(ContextContainer2D.CONTEXT_PROPERTY)){
if(map == null){
return;
}
final JMap2D map2d = map.get();
if(map2d == null){
return;
}
final MapContext context = map2d.getContainer().getContext();
if(context != null){
context.addContextListener(new ContextListener.Weak(this));
}
checkBands();
}
}
private final class LayerPane extends JPanel implements ActionListener,org.geotoolkit.map.ItemListener{
private final JCheckBox box = new JCheckBox();
private final JButton colorButton = new JButton();
private final MapLayer layer;
private LayerPane(final MapLayer layer){
super(new FlowLayout(FlowLayout.LEFT,4,1));
this.layer = layer;
box.addActionListener(this);
colorButton.setHorizontalTextPosition(SwingConstants.LEFT);
colorButton.addActionListener(this);
colorButton.setBorderPainted(true);
colorButton.setContentAreaFilled(false);
colorButton.setOpaque(true);
colorButton.setPreferredSize(new Dimension(20, 20));
colorButton.setBackground(RandomStyleBuilder.randomColor());
add(colorButton);
add(box);
layer.addItemListener(new Weak(this));
update();
}
private void update(){
box.setText(getLayerName());
for(final JNavigatorBand band : navigator.getBands()){
if(band instanceof JLayerBand){
final JLayerBand lb = (JLayerBand) band;
if(lb.getLayer().equals(this.layer)){
final Color c = lb.getColor();
colorButton.setBackground(c);
box.setSelected(true);
return;
}
}
}
box.setSelected(false);
}
private String getLayerName(){
final Description desc = layer.getDescription();
if(desc != null){
final InternationalString title = desc.getTitle();
if(title != null){
return title.toString();
}
}
final String name = layer.getName();
return (name == null)? "" : name;
}
@Override
public void actionPerformed(final ActionEvent e) {
if(e.getSource().equals(box)){
if(box.isSelected()){
for(final Object band : navigator.getBands().toArray()){
if(band instanceof JLayerBand){
final JLayerBand lb = (JLayerBand) band;
if(lb.getLayer().equals(this.layer)){
//already exist
return;
}
}
}
final JLayerBand band = new JLayerBand(layer);
band.setColor(colorButton.getBackground());
navigator.getBands().add(band);
}else{
for(final Object band : navigator.getBands().toArray()){
if(band instanceof JLayerBand){
final JLayerBand lb = (JLayerBand) band;
if(lb.getLayer().equals(this.layer)){
navigator.getBands().remove(lb);
}
}
}
}
}else{
Color c = colorButton.getBackground();
c = JColorChooser.showDialog(this, "", c);
if(c != null){
colorButton.setBackground(c);
for(final JNavigatorBand band : navigator.getBands()){
if(band instanceof JLayerBand){
final JLayerBand lb = (JLayerBand) band;
if(lb.getLayer().equals(this.layer)){
lb.setColor(c);
return;
}
}
}
}
}
}
@Override
public void itemChange(CollectionChangeEvent<MapItem> event) {
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(MapItem.NAME_PROPERTY.equalsIgnoreCase(evt.getPropertyName())){
update();
}
}
}
}