/* Spatial Operations & Editing Tools for uDig
*
* Axios Engineering under a funding contract with:
* Diputación Foral de Gipuzkoa, Ordenación Territorial
*
* http://b5m.gipuzkoa.net
* http://www.axios.es
*
* (C) 2006, Diputación Foral de Gipuzkoa, Ordenación Territorial (DFG-OT).
* DFG-OT agrees to licence under Lesser General Public License (LGPL).
*
* 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 es.axios.udig.ui.editingtools.parallel;
import java.util.ArrayList;
import java.util.List;
import net.refractions.udig.core.IProvider;
import net.refractions.udig.project.BlackboardEvent;
import net.refractions.udig.project.IBlackboard;
import net.refractions.udig.project.IBlackboardListener;
import net.refractions.udig.project.IMap;
import net.refractions.udig.project.render.IViewportModel;
import net.refractions.udig.project.render.IViewportModelListener;
import net.refractions.udig.project.render.ViewportModelEvent;
import net.refractions.udig.project.ui.tool.IToolContext;
import net.refractions.udig.tools.edit.Activator;
import net.refractions.udig.tools.edit.EditToolConfigurationHelper;
import net.refractions.udig.tools.edit.EditToolHandler;
import net.refractions.udig.tools.edit.EventBehaviour;
import net.refractions.udig.tools.edit.activator.DrawCurrentGeomVerticesActivator;
import net.refractions.udig.tools.edit.behaviour.DrawCreateVertexSnapAreaBehaviour;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.LineSegment;
import es.axios.udig.ui.commons.util.GeoToolsUtils;
import es.axios.udig.ui.editingtools.internal.behaviour.DrawEditGeomWithCustomEndlineActivator;
import es.axios.udig.ui.editingtools.internal.behaviour.DrawOrthoAxesActivator;
import es.axios.udig.ui.editingtools.internal.behaviour.IEditPointProvider;
import es.axios.udig.ui.editingtools.internal.behaviour.ParallelEditPointProvider;
import es.axios.udig.ui.editingtools.internal.behaviour.SelectLineSegmentBehaviour;
import es.axios.udig.ui.editingtools.internal.behaviour.SelectLineSegmentBehaviour.BlackboardSegmentProvider;
/**
* @author Gabriel Roldan (www.axios.es)
* @author Mauricio Pazos (www.axios.es)
* @since 0.2.0
*/
public class ParallelAction extends AbstractEditModifierActionDelegate {
@Override
protected void activate() {
super.removeRunningActivators();
EditToolHandler handler = getHandler();
IBlackboard blackboard = handler.getContext().getMap().getBlackboard();
IProvider<LineSegment> lineProvider = new BlackboardSegmentProvider(blackboard);
IEditPointProvider editPointProvider = new ParallelEditPointProvider(lineProvider);
addActivator(new DrawParallelOrhoAxesActivator());
addActivator(new DrawEditGeomWithCustomEndlineActivator(editPointProvider));
addActivator(new DrawCurrentGeomVerticesActivator());
addActivator(new ClearSelectedSegmentActivator());
List<EventBehaviour> eventBehaviours = handler.getBehaviours();
List<EventBehaviour> backup = new ArrayList<EventBehaviour>(eventBehaviours);
eventBehaviours.clear();
EditToolConfigurationHelper helper = new EditToolConfigurationHelper(eventBehaviours);
helper.add(new DrawCreateVertexSnapAreaBehaviour());
helper.startMutualExclusiveList();
// either select a parallel reference segment
helper.add(new SelectLineSegmentBehaviour());
// or run the default behaviours to add the shape points
helper.startOrderedList(true);
for( EventBehaviour b : backup ) {
helper.add(b);
}
helper.stopOrderedList();
helper.stopMutualExclusiveList();
helper.done();
}
// @Override
// protected void deactivate() {
// super.deactivate();
// restoreOriginalActivators();
// }
/**
* Activator that draws the orthogonal axes centered at the mouse location only if there is a
* selected line segment for the parallel mode.
* <p>
* The axes rotation changes when:
* <ul>
* <li> The map's CRS changes
* <li> The selected segment in the map's blackboard changes
* </ul>
* </p>
*/
private static class DrawParallelOrhoAxesActivator extends DrawOrthoAxesActivator
implements
IViewportModelListener,
IBlackboardListener {
/**
* Registers itself as a listener of CRS changes in the map and line segment selection
* changes in the blackboard to update the ortho axes rotation angle accordingly
*/
@Override
public void activate( EditToolHandler handler ) {
super.activate(handler);
IViewportModel viewportModel = getViewportModel(handler);
viewportModel.addViewportModelListener(this);
IBlackboard blackboard = getBlackboard(handler);
blackboard.addListener(this);
}
/**
* Deregisters itself as a listener of CRS changes in the map and line segment selection
* changes in the blackboard
*/
@Override
public void deactivate( EditToolHandler handler ) {
super.deactivate(handler);
super.setValid(false);
IViewportModel viewportModel = getViewportModel(handler);
viewportModel.removeViewportModelListener(this);
IBlackboard blackboard = getBlackboard(handler);
blackboard.removeListener(this);
}
private IViewportModel getViewportModel( EditToolHandler handler ) {
final IToolContext context = handler.getContext();
final IMap map = context.getMap();
IViewportModel viewportModel = map.getViewportModel();
return viewportModel;
}
private IBlackboard getBlackboard( EditToolHandler handler ) {
IToolContext context = handler.getContext();
IMap map = context.getMap();
IBlackboard blackboard = map.getBlackboard();
return blackboard;
}
/**
* Returns the angle in radians of the <code>segmentInLayerCrs</code> inclination
* calculated in the CRS of the map, so the visualized feedback is consistent with the
* user's view regardless of the internal CRS of the data.
*
* @param segmentInLayerCrs
* @return
*/
private double getAngleInMapCoordinates( LineSegment segmentInLayerCrs ) {
CoordinateReferenceSystem mapCrs = handler.getContext().getCRS();
CoordinateReferenceSystem layerCrs = handler.getEditLayer().getCRS();
LineSegment segmentInMapCrs = GeoToolsUtils.reproject(segmentInLayerCrs, layerCrs,
mapCrs);
double angle = segmentInMapCrs.angle();
return angle;
}
/**
* Gets notified of changes in the map's CRS so to update the rotation angle of the axes
*
* @see IViewportModelListener#changed(ViewportModelEvent)
*/
public void changed( ViewportModelEvent event ) {
if (ViewportModelEvent.EventType.CRS == event.getType()) {
perfomAxesRotation(getBlackboard(handler));
}
}
/**
* Gets notified of changes in the selected segment and updates the axes rotation angle
* accordingly
*
* @see IBlackboardListener#blackBoardChanged(BlackboardEvent)
*/
public void blackBoardChanged( BlackboardEvent event ) {
if (SelectLineSegmentBehaviour.SELECTED_SEGMENT_BBOARD_KEY == event.getKey()) {
perfomAxesRotation(event.getSource());
}
}
/**
* Gets notified when the map's blackboard is cleared (and this if there were a selected
* segment it does no longer exists) and updates the axes rotation angle accordingly
*
* @see IBlackboardListener#blackBoardCleared(IBlackboard)
*/
public void blackBoardCleared( IBlackboard source ) {
perfomAxesRotation(source);
}
private void perfomAxesRotation( IBlackboard bboard ) {
LineSegment segmentInLayerCrs;
segmentInLayerCrs = (LineSegment) bboard
.get(SelectLineSegmentBehaviour.SELECTED_SEGMENT_BBOARD_KEY);
double angle = 0;
if (segmentInLayerCrs != null) {
angle = getAngleInMapCoordinates(segmentInLayerCrs);
}
super.setRotationAngle(angle);
handler.repaint();
}
}
/**
* Activator meant to remove any selected line segment from the map's blackboard when this tool
* mode is deactivated.
*/
private static class ClearSelectedSegmentActivator implements Activator {
/**
* Empty method
*/
public void activate( EditToolHandler handler ) {
}
/**
* Removes the selected line segment from the map's blackboard by setting the value of the
* {@link SelectLineSegmentBehaviour#SELECTED_SEGMENT_BBOARD_KEY} key to <code>null</code>
*/
public void deactivate( EditToolHandler handler ) {
final IToolContext context = handler.getContext();
final IMap map = context.getMap();
IBlackboard blackboard = map.getBlackboard();
blackboard.put(SelectLineSegmentBehaviour.SELECTED_SEGMENT_BBOARD_KEY, null);
}
/**
* Empty method
*/
public void handleActivateError( EditToolHandler handler, Throwable error ) {
}
/**
* Empty method
*/
public void handleDeactivateError( EditToolHandler handler, Throwable error ) {
}
}
}