/*******************************************************************************
* Copyright 2012 Geoscience Australia
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package au.gov.ga.earthsci.layer.ui;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Named;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Scale;
import au.gov.ga.earthsci.layer.tree.ILayerTreeNode;
import au.gov.ga.earthsci.layer.tree.LayerNode;
/**
* Tool control used to change layer opacity.
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
public class LayerOpacityToolControl
{
/**
*
*/
private static final String OPACITY = "opacity";
private boolean settingScale = false;
private Scale scale;
private ILayerTreeNode[] selection = null;
private SelectionListener selectionListener;
@PostConstruct
public void createControls(Composite parent, IEclipseContext context)
{
int width = 80;
int height = 21;
Composite child = new Composite(parent, SWT.NONE);
child.setSize(child.computeSize(width, SWT.DEFAULT));
scale = new Scale(child, SWT.HORIZONTAL);
Point size = scale.computeSize(width, SWT.DEFAULT);
scale.setSize(size);
scale.setMinimum(0);
scale.setMaximum(100);
scale.setSelection(100);
scale.setLocation(0, (height - size.y) / 2);
scale.setToolTipText("Set opacity of the selected layer(s)");
scale.setEnabled(false);
selectionListener = new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
if (settingScale)
{
return;
}
double opacity = scale.getSelection() / 100d;
setOpacity(Arrays.asList(selection), opacity);
}
};
scale.addSelectionListener(selectionListener);
if (selection != null)
{
setSelection(selection);
}
}
@PreDestroy
public void tearDown()
{
setSelection(null); // wipes out the selection listers.
scale.removeSelectionListener(selectionListener);
}
@Inject
public void selectionChanged(@Optional @Named(IServiceConstants.ACTIVE_SELECTION) ILayerTreeNode layer)
{
if (layer != null)
{
setSelection(new ILayerTreeNode[] { layer });
}
}
@Inject
public void selectionChanged(@Optional @Named(IServiceConstants.ACTIVE_SELECTION) ILayerTreeNode[] layers)
{
if (layers != null)
{
setSelection(layers);
}
}
private void setSelection(ILayerTreeNode[] selection)
{
if (this.selection != null)
{
for (ILayerTreeNode node : this.selection)
{
node.removePropertyChangeListener(OPACITY, opacityPropertyChangeListener);
}
}
this.selection = selection;
if (this.selection != null)
{
for (ILayerTreeNode node : this.selection)
{
node.addPropertyChangeListener(OPACITY, opacityPropertyChangeListener);
}
updateScale();
}
}
private void updateScale()
{
if (scale == null)
{
return;
}
scale.getDisplay().syncExec(new Runnable()
{
@Override
public void run()
{
settingScale = true;
double opacity = scale.getSelection() / 100d;
Double o = getMinOpacity(Arrays.asList(selection), null);
opacity = o == null ? opacity : o;
scale.setSelection((int) (opacity * 100d));
scale.setEnabled(selection.length > 0);
settingScale = false;
}
});
}
private Double getMinOpacity(List<ILayerTreeNode> nodes, Double opacity)
{
for (ILayerTreeNode node : nodes)
{
if (node instanceof LayerNode)
{
LayerNode layer = (LayerNode) node;
opacity = opacity == null ? layer.getOpacity() : Math.min(opacity, layer.getOpacity());
}
opacity = getMinOpacity(node.getChildren(), opacity);
}
return opacity;
}
private void setOpacity(List<ILayerTreeNode> nodes, double opacity)
{
if (nodes != null)
{
for (ILayerTreeNode node : nodes)
{
if (node instanceof LayerNode)
{
LayerNode layer = (LayerNode) node;
layer.setOpacity(opacity);
}
setOpacity(node.getChildren(), opacity);
}
}
}
private PropertyChangeListener opacityPropertyChangeListener = new PropertyChangeListener()
{
@Override
public void propertyChange(PropertyChangeEvent evt)
{
updateScale();
}
};
}