/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program 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.
* This program 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 this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.snap.rcp.actions.interactors;
import com.bc.ceres.glayer.Layer;
import com.bc.ceres.glayer.LayerFilter;
import com.bc.ceres.glayer.support.LayerUtils;
import com.bc.ceres.grender.Viewport;
import com.bc.ceres.swing.figure.AbstractInteractorInterceptor;
import com.bc.ceres.swing.figure.Figure;
import com.bc.ceres.swing.figure.FigureEditor;
import com.bc.ceres.swing.figure.Interactor;
import com.bc.ceres.swing.figure.interactions.SelectionInteractor;
import org.esa.snap.ui.product.ProductSceneView;
import org.esa.snap.ui.product.VectorDataFigureEditor;
import org.esa.snap.ui.product.VectorDataLayer;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
class SelectionInteractorInterceptor extends AbstractInteractorInterceptor {
@Override
public void interactionStopped(Interactor interactor, InputEvent inputEvent) {
if (interactor instanceof SelectionInteractor) {
final SelectionInteractor selectionInteractor = (SelectionInteractor) interactor;
FigureEditor editor = selectionInteractor.getFigureEditor(inputEvent);
if (editor instanceof VectorDataFigureEditor && inputEvent instanceof MouseEvent) {
final VectorDataFigureEditor figureEditor = (VectorDataFigureEditor) editor;
final MouseEvent mouseEvent = (MouseEvent) inputEvent;
// preferring rectangle selection on current selected layer
if (!isSelectionOnCurrentLayer(figureEditor, mouseEvent)) {
findLayerForSelection(figureEditor, mouseEvent);
}
}
}
}
private boolean isSelectionOnCurrentLayer(VectorDataFigureEditor figureEditor, MouseEvent mouseEvent) {
Layer selectedLayer = figureEditor.getProductSceneView().getSelectedLayer();
if (selectedLayer instanceof VectorDataLayer) {
VectorDataLayer vectorDataLayer = (VectorDataLayer) selectedLayer;
return getFigures(vectorDataLayer, figureEditor, mouseEvent).length > 0;
}
return false;
}
private static Figure[] getFigures(VectorDataLayer vectorDataLayer, VectorDataFigureEditor figureEditor, MouseEvent mouseEvent) {
Viewport viewport = figureEditor.getViewport();
AffineTransform v2mTransform = viewport.getViewToModelTransform();
Rectangle rectangle = figureEditor.getSelectionRectangle();
Figure[] figures = new Figure[0];
if (rectangle != null) {
Shape shape = v2mTransform.createTransformedShape(rectangle);
figures = vectorDataLayer.getFigureCollection().getFigures(shape);
} else {
v2mTransform.transform(mouseEvent.getPoint(), null);
Point2D modelPoint = v2mTransform.transform(mouseEvent.getPoint(), null);
AffineTransform m2vTransform = viewport.getModelToViewTransform();
Figure figure = vectorDataLayer.getFigureCollection().getFigure(modelPoint, m2vTransform);
if (figure != null) {
figures = new Figure[]{figure};
}
}
return figures;
}
private void findLayerForSelection(VectorDataFigureEditor figureEditor, MouseEvent mouseEvent) {
LayerWithNearFigureFilter figureFilter = new LayerWithNearFigureFilter(figureEditor, mouseEvent);
final ProductSceneView sceneView = figureEditor.getProductSceneView();
final Layer rootLayer = sceneView.getRootLayer();
selectLayer(rootLayer, figureFilter);
}
private void selectLayer(Layer rootLayer, LayerWithNearFigureFilter figureFilter) {
LayerUtils.getChildLayer(rootLayer, LayerUtils.SearchMode.DEEP, figureFilter);
}
private static class LayerWithNearFigureFilter implements LayerFilter {
private VectorDataFigureEditor figureEditor;
private final MouseEvent mouseEvent;
public LayerWithNearFigureFilter(VectorDataFigureEditor figureEditor, MouseEvent mouseEvent) {
this.figureEditor = figureEditor;
this.mouseEvent = mouseEvent;
}
@Override
public boolean accept(Layer layer) {
if (layer instanceof VectorDataLayer) {
VectorDataLayer vectorDataLayer = (VectorDataLayer) layer;
final Figure[] figures = getFigures(vectorDataLayer, figureEditor, mouseEvent);
if (figures.length > 0) {
ProductSceneView sceneView = figureEditor.getProductSceneView();
// selectVectorDataLayer changes selectionRectangle
// to preserve selection get rectangle first and set it afterwards
Rectangle selectionRectangle = figureEditor.getSelectionRectangle();
sceneView.selectVectorDataLayer(vectorDataLayer.getVectorDataNode());
if (selectionRectangle != null) {
figureEditor.setSelectionRectangle(selectionRectangle);
}
return true;
}
}
return false;
}
}
}