/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform 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, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.ui.editpolicies;
import java.util.List;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Polyline;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.geometry.Transposer;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
/**
* @author Riccardo Solmi
*/
public class FeedbackEditPolicyStrategy {
protected static final int FEEDBACK_LINE_WIDTH = 2;
public static FeedbackEditPolicyStrategy instance = new FeedbackEditPolicyStrategy();
protected FeedbackEditPolicyStrategy() {
}
public IFigure createFeedbackFigure() {
Polyline figure = new Polyline();
figure.setLineWidth(FEEDBACK_LINE_WIDTH);
figure.setForegroundColor(ColorConstants.gray);
figure.addPoint(new Point(0, 0));
figure.addPoint(new Point(10, 10));
return figure;
}
public void updateTargetFeedback(GraphicalEditPart host, Point location, boolean isHorizontal, IFigure feedbackFigure) {
Transposer transposer = new Transposer();
transposer.setEnabled(!isHorizontal);
Rectangle hostBounds = transposer.t(getAbsoluteBounds(host));
Rectangle feedbackArea = new Rectangle();
getFeedbackIndexFor(host, location, isHorizontal, feedbackArea);
int x;
boolean empty = host.getChildren().isEmpty();
if (!empty && feedbackArea.x == hostBounds.x)
x = feedbackArea.right() - FEEDBACK_LINE_WIDTH; //before first child
else if (!empty && feedbackArea.right() == hostBounds.right())
x = feedbackArea.x + FEEDBACK_LINE_WIDTH; //after last child
else
x = feedbackArea.x + feedbackArea.width/2;
Point p1 = new Point(x, feedbackArea.y);
p1 = transposer.t(p1);
feedbackFigure.translateToRelative(p1);
Point p2 = new Point(x, feedbackArea.bottom());
p2 = transposer.t(p2);
feedbackFigure.translateToRelative(p2);
Polyline feedbackLine = (Polyline) feedbackFigure;
feedbackLine.setPoint(p1, 0);
feedbackLine.setPoint(p2, 1);
}
protected int getFeedbackIndexFor(EditPart host, Point location, boolean isHorizontal) {
return getFeedbackIndexFor(host, location, isHorizontal, new Rectangle());
}
protected int getFeedbackIndexFor(EditPart host, Point location, boolean isHorizontal, Rectangle feedbackArea) {
Transposer transposer = new Transposer();
transposer.setEnabled (!isHorizontal);
location = transposer.t(location);
Rectangle hostBounds = transposer.t(getAbsoluteBounds((GraphicalEditPart) host));
Rectangle prevBounds = Rectangle.SINGLETON;
List<?> children = host.getChildren();
if (children.isEmpty() || location == null) {
if (host instanceof AbstractGraphicalEditPart) {
IFigure compositePane = ((AbstractGraphicalEditPart) host).getContentPane();
Rectangle compositeBounds = transposer.t(getAbsoluteBounds(compositePane));
feedbackArea.setBounds(compositeBounds);
} else
feedbackArea.setBounds(hostBounds);
return -1;
}
int candidate = -1;
int i=0;
int size=children.size();
for (; i<size; i++) {
IFigure figure = ((GraphicalEditPart) children.get(i)).getFigure();
if (!figure.isVisible())
continue;
Rectangle childBounds = transposer.t(getAbsoluteBounds(figure));
if (i == 0 || childBounds.x <= prevBounds.x) {
if (i > 0 && location.y < feedbackArea.bottom())
break;
candidate = -1;
prevBounds.setLocation(hostBounds.x, Integer.MIN_VALUE);
prevBounds.setSize(0, 0);
feedbackArea.setLocation(Integer.MIN_VALUE, Integer.MAX_VALUE);
feedbackArea.setSize(0, 0);
}
feedbackArea.y = Math.min(feedbackArea.y, childBounds.y);
feedbackArea.height += Math.max(0, childBounds.bottom() - feedbackArea.bottom());
if (candidate == -1 && location.x <= childBounds.x + (childBounds.width / 2)) {
candidate = i;
feedbackArea.x = prevBounds.right();
feedbackArea.width = Math.max(0, childBounds.x - feedbackArea.x);
}
prevBounds = childBounds;
}
if (candidate == -1) {
if (i < size)
candidate = i;
feedbackArea.x = prevBounds.right();
feedbackArea.width = Math.max(0, hostBounds.right() - feedbackArea.x);;
}
return candidate;
}
public static Rectangle getAbsoluteBounds(GraphicalEditPart ep) {
return getAbsoluteBounds(ep.getFigure());
}
public static Rectangle getAbsoluteBounds(IFigure figure) {
Rectangle bounds = figure.getBounds().getCopy();
figure.translateToAbsolute(bounds);
return bounds;
}
}