/** * 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.ArrayList; import java.util.List; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.FigureCanvas; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.ImageFigure; import org.eclipse.draw2d.LineBorder; import org.eclipse.draw2d.Locator; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.SWTGraphics; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.PrecisionRectangle; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.gef.DragTracker; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.Handle; import org.eclipse.gef.Request; import org.eclipse.gef.RequestConstants; import org.eclipse.gef.SharedCursors; import org.eclipse.gef.editparts.ScalableRootEditPart; import org.eclipse.gef.editpolicies.NonResizableEditPolicy; import org.eclipse.gef.handles.AbstractHandle; import org.eclipse.gef.handles.HandleBounds; import org.eclipse.gef.handles.MoveHandle; import org.eclipse.gef.handles.ResizeHandle; import org.eclipse.gef.requests.ChangeBoundsRequest; import org.eclipse.gef.tools.SelectEditPartTracker; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.whole.lang.ui.editparts.IGraphicalEntityPart; import org.whole.lang.ui.figures.FigureConstants; /** * @author Riccardo Solmi, Enrico Persiani */ public class WholeNonResizableEditPolicy extends NonResizableEditPolicy { @Override protected List<?> createSelectionHandles() { final GraphicalEditPart host = (GraphicalEditPart) getHost(); final DragTracker tracker = new SelectEditPartTracker(host); final Cursor cursor = SharedCursors.ARROW; final MoveHandle moveHandle = new MoveHandle(host) { @Override protected void initialize() { setOpaque(false); setBorder(new LineBorder(ColorConstants.gray, 1)); setCursor(cursor); setDragTracker(tracker); } }; final List<Handle> handles = new ArrayList<Handle>(5); handles.add(moveHandle); if (isDragAllowed()) { handles.add(createHandle(host, PositionConstants.SOUTH_EAST, tracker, cursor)); handles.add(createHandle(host, PositionConstants.SOUTH_WEST, tracker, cursor)); handles.add(createHandle(host, PositionConstants.NORTH_WEST, tracker, cursor)); handles.add(createHandle(host, PositionConstants.NORTH_EAST, tracker, cursor)); } return handles; } public Handle createHandle(GraphicalEditPart owner, int direction, DragTracker tracker, Cursor cursor) { ResizeHandle handle = new ResizeHandle(owner, direction) { protected Color getBorderColor() { return ColorConstants.black; } protected Color getFillColor() { return (isPrimary()) ? FigureConstants.lightBlueColor : ColorConstants.white; } public void paintFigure(Graphics g) { Rectangle r = getBounds(); r.shrink(1, 1); try { g.setBackgroundColor(getFillColor()); g.fillOval(r.x, r.y, r.width, r.height); g.setForegroundColor(getBorderColor()); g.drawOval(r.x, r.y, r.width, r.height); } finally { r.expand(1, 1); } } }; handle.setCursor(cursor); handle.setDragTracker(tracker); return handle; } protected IFigure targetFeedback; @Override public void showTargetFeedback(Request request) { if (request.getType().equals(RequestConstants.REQ_MOVE) || request.getType().equals(RequestConstants.REQ_CLONE) || request.getType().equals(RequestConstants.REQ_ADD)) if (targetFeedback == null) { targetFeedback = new AbstractHandle( (GraphicalEditPart)getHost(), new Locator() { public void relocate(IFigure target) { IFigure figure = getHostFigure(); Rectangle r; if (figure instanceof HandleBounds) r = ((HandleBounds)figure).getHandleBounds().getCopy(); else r = getHostFigure().getBounds().getResized(-1, -1); getHostFigure().translateToAbsolute(r); target.translateToRelative(r); target.setBounds(r.expand(5, 5).resize(1, 1)); } }) { { setBorder(new LineBorder(ColorConstants.lightGray, 1)); } protected DragTracker createDragTracker() { return null; } }; addFeedback(targetFeedback); } } @Override public void eraseTargetFeedback(Request request) { if (targetFeedback != null) removeFeedback(targetFeedback); targetFeedback = null; } public static class FeedbackImageFigure extends ImageFigure { public static final Dimension DIMENSION = new Dimension(500, 500); public static final int ALPHA = 160; protected int ix, iy; public FeedbackImageFigure(Image image) { super(image); } public void setImageLocation(int x, int y) { ix = x; iy = y; } @Override protected void paintFigure(Graphics graphics) { Rectangle area = getClientArea(); graphics.drawImage(getImage(), area.x + ix, area.y + iy); } } @Override protected IFigure createDragSourceFeedbackFigure() { IFigure figure = new FeedbackImageFigure(createFeedbackImage((IGraphicalEntityPart) getHost(), FeedbackImageFigure.ALPHA, true, FitToScreenStrategy.instance())); figure.setBounds(getInitialFeedbackBounds()); addFeedback(figure); return figure; } @Override protected void removeFeedback(IFigure figure) { super.removeFeedback(figure); if (figure instanceof ImageFigure) ((ImageFigure) figure).getImage().dispose(); }; public static Image createFeedbackImage(IGraphicalEntityPart part, int alpha, boolean withBorder, IConstraintDimensionStrategy strategy) { double scale = ((ScalableRootEditPart) part.getViewer().getRootEditPart()).getZoomManager().getZoom(); return createFeedbackImage(part, alpha, withBorder, strategy, scale); } public static Image createFeedbackImage(IGraphicalEntityPart part, int alpha, boolean withBorder, IConstraintDimensionStrategy strategy, double scale) { IFigure figure = part.getFigure(); Rectangle figureBounds = figure.getBounds(); Control figureCanvas = part.getViewer().getControl(); // calculate feedback maximum dimension Dimension dimension = strategy.constraintDimensions(new Dimension( (int) Math.round(figureBounds.width*scale), (int) Math.round(figureBounds.height*scale))); if (dimension == null) return null; Image img = new Image(null, dimension.width, dimension.height); img.setBackground(ColorConstants.white); GC imageGC = new GC(img); Graphics imgGraphics = new SWTGraphics(imageGC); imgGraphics.scale(scale); imgGraphics.translate(-figureBounds.x, -figureBounds.y); figure.paint(imgGraphics); // draw dashed border if (withBorder) { imgGraphics.translate(figureBounds.x, figureBounds.y); imgGraphics.scale(1.0/scale); imgGraphics.setForegroundColor(ColorConstants.white); imgGraphics.drawRectangle(0, 0, dimension.width-1, dimension.height-1); imgGraphics.setLineStyle(SWT.LINE_DASH); imgGraphics.setLineDash(new int[] {4,3}); imgGraphics.setForegroundColor(ColorConstants.black); imgGraphics.drawRectangle(0, 0, dimension.width-1, dimension.height-1); } ImageData data = img.getImageData(); // alpha only for (int x=0 ; x<data.width; x++) for (int y=0 ; y<data.height; y++) data.setAlpha(x, y, alpha); Image feedbackImage = new Image(figureCanvas.getDisplay(), data); imageGC.dispose(); img.dispose(); return feedbackImage; } @Override protected void showChangeBoundsFeedback(ChangeBoundsRequest request) { final FeedbackImageFigure feedback = (FeedbackImageFigure) getDragSourceFeedbackFigure(); final PrecisionRectangle rect = new PrecisionRectangle(getInitialFeedbackBounds().getCopy()); getHostFigure().translateToAbsolute(rect); rect.translate(request.getMoveDelta()); // rect.resize(request.getSizeDelta()); FigureCanvas figureCanvas = (FigureCanvas) getHost().getViewer().getControl(); Rectangle viewportArea = figureCanvas.getViewport().getBounds(); int dx = Math.min(rect.x - viewportArea.x, 0); int dy = Math.min(rect.y - viewportArea.y, 0); rect.intersect(viewportArea); feedback.setImageLocation(dx, dy); feedback.translateToRelative(rect); Display.getCurrent().asyncExec(new Runnable() { public void run() { feedback.setBounds(rect); } }); } }