/*
* Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.sds.components.ui.internal.feedback;
import org.csstudio.sds.components.model.AbstractPolyModel;
import org.eclipse.draw2d.Cursors;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Polyline;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.PrecisionPoint;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.SnapToHelper;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.handles.HandleBounds;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.tools.ResizeTracker;
import org.eclipse.gef.tools.SimpleDragTracker;
/**
* A drag tracker, that moves points of polygons or polylines.
*
* @author Sven Wende
*
*/
public final class PolyPointDragTracker extends SimpleDragTracker {
/**
* Extended data key "pointIndex".
*/
private static final String EXT_DATA_POINT_INDEX = "pointIndex"; //$NON-NLS-1$
/**
* Extended data key "points".
*/
private static final String EXT_DATA_POINTS = "points"; //$NON-NLS-1$
/**
* The source edit part.
*/
private GraphicalEditPart _owner;
/**
* The index of the poly point, which should be dragged.
*/
private int _pointIndex;
/**
* A snap helper.
*/
private SnapToHelper _snapToHelper;
/**
* The initial point list, when a drag operation starts. Used to calculate
* deviations for feedback.
*/
private PointList _oldPoints;
/**
* The request, which is currently used to communicate with the edit part.
*/
private Request _sourceRequest;
/**
* Constructs a new DragEditPartsTracker with the given source edit part and
* point index.
*
* @param owner
* the source edit part
* @param pointIndex
* the index of the poly point, which should be dragged
*/
public PolyPointDragTracker(final GraphicalEditPart owner,
final int pointIndex) {
super();
setDisabledCursor(Cursors.NO);
assert owner != null;
assert owner.getFigure() instanceof Polyline : "owner.getFigure() instanceof Polyline"; //$NON-NLS-1$
assert ((Polyline) owner.getFigure()).getPoints().size() > pointIndex : "((Polyline) owner.getFigure()).getPoints().size()>pointIndex"; //$NON-NLS-1$
assert pointIndex >= 0 : "pointIndex>=0"; //$NON-NLS-1$
_owner = owner;
_pointIndex = pointIndex;
_oldPoints = ((Polyline) _owner.getFigure()).getPoints().getCopy();
if (getTargetEditPart() != null) {
_snapToHelper = (SnapToHelper) getTargetEditPart().getAdapter(
SnapToHelper.class);
}
}
/**
* The TargetEditPart is the parent of the EditPart being resized.
*
* @return The target EditPart; may be <code>null</code> in 2.1
* applications that use the now deprecated
* {@link ResizeTracker#ResizeTracker(int) constructor}.
*/
protected GraphicalEditPart getTargetEditPart() {
if (_owner != null) {
return (GraphicalEditPart) _owner.getParent();
}
return null;
}
/**
* Gets the source bounds of the owners figure.
*
* @return the source bounds
*/
protected PrecisionRectangle getSourceBounds() {
PrecisionRectangle sourceRect;
IFigure figure = _owner.getFigure();
if (figure instanceof HandleBounds) {
sourceRect = new PrecisionRectangle(((HandleBounds) figure)
.getHandleBounds());
} else {
sourceRect = new PrecisionRectangle(figure.getBounds());
}
figure.translateToAbsolute(sourceRect);
return sourceRect;
}
/**
* {@inheritDoc}
*/
@Override
protected String getCommandName() {
return RequestConstants.REQ_RESIZE;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
protected Request createSourceRequest() {
ChangeBoundsRequest request = new ChangeBoundsRequest();
request.setEditParts(getTargetEditPart());
PointList points = ((AbstractPolyModel) _owner.getModel())
.getPoints();
request.getExtendedData().put(AbstractPolyFeedbackFactory.PROP_POINTS,
points.getCopy());
request.setType(RequestConstants.REQ_RESIZE);
_oldPoints = points.getCopy();
return request;
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings("unchecked")
protected void updateSourceRequest() {
super.updateSourceRequest();
ChangeBoundsRequest request = (ChangeBoundsRequest) getSourceRequest();
PrecisionPoint location = new PrecisionPoint(getLocation().x,
getLocation().y);
if (_snapToHelper != null) {
_snapToHelper.snapPoint(request, PositionConstants.NORTH_WEST,
new PrecisionPoint(getLocation().x, getLocation().y),
location);
}
_owner.getFigure().translateToRelative(location);
PointList oldPoints = ((PointList) request.getExtendedData().get(
EXT_DATA_POINTS)).getCopy();
PointList newPoints = oldPoints.getCopy();
newPoints.setPoint(location.getCopy(), _pointIndex);
// calculate difference
Rectangle oldBounds = _oldPoints.getBounds();
Rectangle newBounds = newPoints.getBounds();
request.setLocation(getLocation());
Dimension locationDiff = newBounds.getLocation().getDifference(
oldBounds.getLocation());
_owner.getFigure().translateToAbsolute(locationDiff);
Dimension sizeDiff = newBounds.getSize().getDifference(
oldBounds.getSize());
_owner.getFigure().translateToAbsolute(sizeDiff);
request
.setMoveDelta(new Point(locationDiff.width, locationDiff.height));
request.setSizeDelta(sizeDiff);
request.getExtendedData().put(EXT_DATA_POINTS, newPoints);
request.getExtendedData().put(EXT_DATA_POINT_INDEX, _pointIndex);
}
/**
* {@inheritDoc}
*/
@Override
protected Command getCommand() {
if (_owner == null) {
return null;
}
return _owner.getCommand(getSourceRequest());
}
/**
* Returns the request for the source of the drag, creating it if necessary.
*
* @return the source request
*/
@Override
protected Request getSourceRequest() {
if (_sourceRequest == null) {
_sourceRequest = createSourceRequest();
}
return _sourceRequest;
}
/**
* {@inheritDoc}
*/
@Override
protected void performDrag() {
super.performDrag();
resetRequestState();
}
/**
* Clears and resets the state of the tracker.
*/
private void resetRequestState() {
_oldPoints = ((AbstractPolyModel) _owner.getModel()).getPoints().getCopy();
_sourceRequest = null;
}
}