/****************************************************************************** * Copyright (c) 2016 SAP and Oracle * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * SAP - initial implementation * Shenxue Zhou - adaptation for Sapphire and ongoing maintenance ******************************************************************************/ package org.eclipse.sapphire.ui.swt.gef.utils; import org.eclipse.draw2d.Cursors; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Insets; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.gef.DragTracker; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.handles.AbstractHandle; import org.eclipse.gef.tools.DragEditPartsTracker; import org.eclipse.sapphire.ui.swt.gef.DiagramConfigurationManager; import org.eclipse.sapphire.ui.swt.gef.figures.FigureUtil; import org.eclipse.sapphire.ui.swt.gef.model.DiagramResourceCache; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; /** * A rectangular handle, which completely surrounds the owner edit-part. It * serves as selection highlighting and can also be used to move the owner * edit-part. * * @noinstantiate This class is not intended to be instantiated by clients. * @noextend This class is not intended to be subclassed by clients. * * @author SAP * @author <a href="mailto:shenxue.zhou@oracle.com">Shenxue Zhou</a> * */ public class SapphireSurroundingHandle extends AbstractHandle { private int lineWidth = 1; private int lineOffset = 0; private int lineStyle = SWT.LINE_DASH; private Color lineColor; /** * The resource cache, which can be used to access the environment. */ private DiagramResourceCache resourceCache; private DiagramConfigurationManager configManager; /** * Indicates, if moving the owner edit-part via this handle is supported. */ private boolean movable; /** * Creates a new GFSurroundingHandle. * * @param owner * The owner editpart associated with this handle. * @param configurationProvider * The configuration provider, which can be used to access the * environment. * @param supportedResizeDirections * The supported resize directions (see * {@link org.eclipse.gef.editpolicies.ResizableEditPolicy#getResizeDirections()}) * @param movable * Indicates, if moving the owner edit-part via this handle is * supported. */ public SapphireSurroundingHandle(GraphicalEditPart owner, DiagramConfigurationManager configManager, DiagramResourceCache resourceCache, boolean movable) { this.resourceCache = resourceCache; this.configManager = configManager; this.movable = movable; setOwner(owner); int lineWidth = getLineWidth(); setLocator(new ZoomingInsetsHandleLocator(owner.getFigure(), new Insets(lineWidth, lineWidth, lineWidth, lineWidth))); setOpaque(false); this.lineColor = this.resourceCache.getOutlineColor(); if (movable) { setCursor(Cursors.SIZEALL); } else { setCursor(null); } } /** * Overridden to create a {@link DragEditPartsTracker}, if moving is * supported. */ @Override protected DragTracker createDragTracker() { if (movable) { DragEditPartsTracker tracker = new DragEditPartsTracker(getOwner()); tracker.setDefaultCursor(getCursor()); return tracker; } else { return null; } } /** * Returns <code>true</code> if the point (x,y) is contained within this * handle. This means, that the point is on the outline of the handle, not * inside the handle. * * @return <code>true</code> if the point (x,y) is contained within this * handle. */ @Override public boolean containsPoint(int x, int y) { // true, if inside bounds but not inside inner rectangle if (!getBounds().contains(x, y)) return false; Rectangle inner = FigureUtil.getAdjustedRectangle(getBounds(), 1.0, 2 * getLineWidth()); return !inner.contains(x, y); } /** * Returns a point along the right edge of the handle. * * @see org.eclipse.gef.Handle#getAccessibleLocation() */ @Override public Point getAccessibleLocation() { Point p = getBounds().getTopRight().translate(-1, getBounds().height / 4); translateToAbsolute(p); return p; } /** * Paints a rectangular handle surrounding the owner edit-part. */ @Override public void paintFigure(Graphics g) { g.setAntialias(SWT.ON); g.setLineWidth(getLineWidth()); Rectangle r = new Rectangle(getBounds()); int zoom = this.configManager.getDiagramEditor().getPart().getZoomLevel(); int scaledInset = -getLineOffset() * zoom / 100; r.shrink(scaledInset, scaledInset); r = FigureUtil.getAdjustedRectangle(r, 1.0, getLineWidth()); prepareForDrawing(g, PositionConstants.NORTH); g.drawLine(r.getTopLeft(), r.getTopRight()); prepareForDrawing(g, PositionConstants.SOUTH); g.drawLine(r.getBottomLeft(), r.getBottomRight()); prepareForDrawing(g, PositionConstants.EAST); g.drawLine(r.getTopRight(), r.getBottomRight()); prepareForDrawing(g, PositionConstants.WEST); g.drawLine(r.getTopLeft(), r.getBottomLeft()); } public int getLineWidth() { return this.lineWidth; } public void setLineWidth(int lineWidth) { this.lineWidth = lineWidth; } public int getLineOffset() { return this.lineOffset; } public void setLineOffset(int lineOffset) { this.lineOffset = lineOffset; } public void setLineStyle(int style) { this.lineStyle = style; } public void setLineColor(org.eclipse.sapphire.Color color) { this.lineColor = this.resourceCache.getColor(color); } /** * Prepares the graphics to paint the rectangle-side for the given * direction. This will set the line-style and foreground color. * * @param g * The graphics which to prepare. * @param direction * The direction, for which to prepare the graphics. */ private void prepareForDrawing(Graphics g, int direction) { g.setLineStyle(this.lineStyle); // It is necessary to set the color. This ensures the support for the high contrast mode. setForegroundColor(this.lineColor); g.setForegroundColor(getForegroundColor()); } }