| /********************************************************************* |
| * Copyright (c) 2005, 2019 SAP SE |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * Contributors: |
| * SAP SE - initial API, implementation and documentation |
| * mwenz - Bug 334233 - Fixed issue with zooming of diagrams when object in diagram is selected |
| * mgorning - Bug 391523 - Revise getSelectionInfo...() in IToolBehaviorProvider |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| **********************************************************************/ |
| package org.eclipse.graphiti.ui.internal.util.draw2d; |
| |
| import org.eclipse.draw2d.Cursors; |
| import org.eclipse.draw2d.Graphics; |
| import org.eclipse.draw2d.geometry.Dimension; |
| import org.eclipse.draw2d.geometry.Rectangle; |
| import org.eclipse.gef.DragTracker; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.GraphicalEditPart; |
| import org.eclipse.gef.editpolicies.ResizableEditPolicy; |
| import org.eclipse.gef.handles.AbstractHandle; |
| import org.eclipse.gef.tools.DragEditPartsTracker; |
| import org.eclipse.gef.tools.ResizeTracker; |
| import org.eclipse.graphiti.tb.IShapeSelectionInfo; |
| import org.eclipse.graphiti.ui.internal.config.IConfigurationProviderInternal; |
| import org.eclipse.graphiti.ui.internal.figures.GFFigureUtil; |
| import org.eclipse.graphiti.ui.internal.util.DataTypeTransformation; |
| import org.eclipse.graphiti.util.IColorConstant; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.SWTException; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.widgets.Display; |
| |
| /** |
| * A rectangular handle which is placed at a corner or at a side of a shape |
| * edit-part. It can be used to move or resize the shape edit-part. |
| * |
| * @noinstantiate This class is not intended to be instantiated by clients. |
| * @noextend This class is not intended to be subclassed by clients. |
| */ |
| public class GFCornerHandle extends AbstractHandle { |
| |
| /** |
| * The line-width of the handle. |
| */ |
| private static int LINE_WIDTH = 1; |
| |
| /** |
| * The handle-dimension is used to locate the handle as described in |
| * {@link ZoomingRelativeHandleLocator}. |
| */ |
| private static Dimension HANDLE_DIMENSION = new Dimension(5, 5); |
| |
| /** |
| * The handle-insets are used to locate the handle as described in |
| * {@link ZoomingRelativeHandleLocator}. |
| */ |
| private static Dimension HANDLE_INSETS = new Dimension(3, 3); |
| |
| /** |
| * The foreground color for for primary-selected, resizable directions. |
| */ |
| private static Color FG_COLOR_PRIMARY_RESIZABLE; |
| |
| /** |
| * The foreground color for for secondary-selected, resizable directions. |
| */ |
| private static Color FG_COLOR_SECONDARY_RESIZABLE; |
| |
| /** |
| * The foreground color for not-resizable directions. |
| */ |
| private static Color FG_COLOR_NOT_RESIZABLE; |
| |
| /** |
| * The background color for primary-selected, resizable directions. |
| */ |
| private static Color BG_COLOR_PRIMARY_RESIZABLE; |
| |
| /** |
| * The background color for secondary-selected, resizable directions. |
| */ |
| private static Color BG_COLOR_SECONDARY_RESIZABLE; |
| |
| /** |
| * The background color for primary-selected, not-resizable directions. |
| */ |
| private static Color BG_COLOR_PRIMARY_NOT_RESIZABLE; |
| |
| /** |
| * The background color for secondary-selected, not-resizable directions. |
| */ |
| private static Color BG_COLOR_SECONDARY_NOT_RESIZABLE; |
| |
| // ======================================================================== |
| |
| /** |
| * The configuration provider, which can be used to access the environment. |
| */ |
| private IConfigurationProviderInternal configurationProvider; |
| |
| /** |
| * The supported resize direction (see |
| * {@link ResizableEditPolicy#getResizeDirections()}). Is 0 if resizing is |
| * not allowed. |
| */ |
| private int resizeDirection; |
| |
| /** |
| * Indicates, if moving the shape edit-part via this handle is supported. |
| */ |
| private boolean movable; |
| |
| /** |
| * the selection info, e.g. handle colors |
| */ |
| private IShapeSelectionInfo shapeSelectionInfo; |
| |
| /** |
| * Creates a new GFCornerHandle. |
| * |
| * @param owner |
| * The shape edit-part associated with this handle. |
| * @param configurationProvider |
| * The configuration provider, which can be used to access the |
| * environment. |
| * @param location |
| * The location at which to locate the handle. If the location is |
| * part of the supported resize directions, then resizing is |
| * supported for this handle. |
| * @param supportedResizeDirections |
| * The supported resize directions (see |
| * {@link ResizableEditPolicy#getResizeDirections()}) |
| * @param movable |
| * Indicates, if moving the shape edit-part via this handle is |
| * supported. |
| * @param shapeSelectionInfo |
| */ |
| public GFCornerHandle(GraphicalEditPart owner, IConfigurationProviderInternal configurationProvider, int location, |
| int supportedResizeDirections, boolean movable, IShapeSelectionInfo shapeSelectionInfo) { |
| this.configurationProvider = configurationProvider; |
| this.resizeDirection = supportedResizeDirections & location; |
| this.movable = movable; |
| this.shapeSelectionInfo = shapeSelectionInfo; |
| |
| setOwner(owner); |
| setLocator(new ZoomingRelativeHandleLocator(owner.getFigure(), configurationProvider, location, |
| HANDLE_DIMENSION, HANDLE_INSETS)); |
| |
| setOpaque(false); |
| |
| if (isResizable()) { |
| setCursor(Cursors.getDirectionalCursor(resizeDirection, owner.getFigure().isMirrored())); |
| } else if (movable) { |
| setCursor(Cursors.SIZEALL); |
| } else { |
| setCursor(null); |
| } |
| } |
| |
| /** |
| * @return the fG_COLOR_PRIMARY_RESIZABLE |
| */ |
| public Color getFG_COLOR_PRIMARY_RESIZABLE() { |
| if (shapeSelectionInfo != null) { |
| IColorConstant color = shapeSelectionInfo.getPrimarySelectionHandleForegroundColor(); |
| if (color != null) { |
| Color swtColor = DataTypeTransformation.toSwtColor(configurationProvider.getResourceRegistry(), color); |
| return swtColor; |
| } |
| } |
| if (FG_COLOR_PRIMARY_RESIZABLE == null || FG_COLOR_PRIMARY_RESIZABLE.isDisposed()) |
| FG_COLOR_PRIMARY_RESIZABLE = configurationProvider.getResourceRegistry().getSwtColor("f17d00"); //$NON-NLS-1$ |
| return FG_COLOR_PRIMARY_RESIZABLE; |
| } |
| |
| /** |
| * @return the fG_COLOR_SECONDARY_RESIZABLE |
| */ |
| public Color getFG_COLOR_SECONDARY_RESIZABLE() { |
| if (shapeSelectionInfo != null) { |
| IColorConstant color = shapeSelectionInfo.getSecondarySelectionHandleForegroundColor(); |
| if (color != null) { |
| Color swtColor = DataTypeTransformation.toSwtColor(configurationProvider.getResourceRegistry(), color); |
| return swtColor; |
| } |
| } |
| if (FG_COLOR_SECONDARY_RESIZABLE == null || FG_COLOR_SECONDARY_RESIZABLE.isDisposed()) |
| FG_COLOR_SECONDARY_RESIZABLE = configurationProvider.getResourceRegistry().getSwtColor("f17d00"); //$NON-NLS-1$ |
| return FG_COLOR_SECONDARY_RESIZABLE; |
| } |
| |
| /** |
| * @return the fG_COLOR_NOT_RESIZABLE |
| */ |
| public Color getFG_COLOR_NOT_RESIZABLE() { |
| if (FG_COLOR_NOT_RESIZABLE == null || FG_COLOR_NOT_RESIZABLE.isDisposed()) |
| FG_COLOR_NOT_RESIZABLE = configurationProvider.getResourceRegistry().getSwtColor("b3b6bb"); //$NON-NLS-1$ |
| return FG_COLOR_NOT_RESIZABLE; |
| } |
| |
| /** |
| * @return the bG_COLOR_PRIMARY_RESIZABLE |
| */ |
| public Color getBG_COLOR_PRIMARY_RESIZABLE() { |
| if (shapeSelectionInfo != null) { |
| IColorConstant color = shapeSelectionInfo.getPrimarySelectionHandleBackgroundColor(); |
| if (color != null) { |
| Color swtColor = DataTypeTransformation.toSwtColor(configurationProvider.getResourceRegistry(), color); |
| return swtColor; |
| } |
| } |
| if (BG_COLOR_PRIMARY_RESIZABLE == null || BG_COLOR_PRIMARY_RESIZABLE.isDisposed()) |
| BG_COLOR_PRIMARY_RESIZABLE = configurationProvider.getResourceRegistry().getSwtColor("ff8400"); //$NON-NLS-1$ |
| return BG_COLOR_PRIMARY_RESIZABLE; |
| } |
| |
| /** |
| * @return the bG_COLOR_SECONDARY_RESIZABLE |
| */ |
| public Color getBG_COLOR_SECONDARY_RESIZABLE() { |
| if (shapeSelectionInfo != null) { |
| IColorConstant color = shapeSelectionInfo.getSecondarySelectionHandleBackgroundColor(); |
| if (color != null) { |
| Color swtColor = DataTypeTransformation.toSwtColor(configurationProvider.getResourceRegistry(), color); |
| return swtColor; |
| } |
| } |
| if (BG_COLOR_SECONDARY_RESIZABLE == null || BG_COLOR_SECONDARY_RESIZABLE.isDisposed()) |
| BG_COLOR_SECONDARY_RESIZABLE = configurationProvider.getResourceRegistry().getSwtColor("ffffff"); //$NON-NLS-1$ |
| return BG_COLOR_SECONDARY_RESIZABLE; |
| } |
| |
| /** |
| * @return the bG_COLOR_PRIMARY_NOT_RESIZABLE |
| */ |
| public Color getBG_COLOR_PRIMARY_NOT_RESIZABLE() { |
| if (BG_COLOR_PRIMARY_NOT_RESIZABLE == null || BG_COLOR_PRIMARY_NOT_RESIZABLE.isDisposed()) |
| BG_COLOR_PRIMARY_NOT_RESIZABLE = configurationProvider.getResourceRegistry().getSwtColor("b3b6bb"); //$NON-NLS-1$ |
| return BG_COLOR_PRIMARY_NOT_RESIZABLE; |
| } |
| |
| /** |
| * @return the bG_COLOR_SECONDARY_NOT_RESIZABLE |
| */ |
| public Color getBG_COLOR_SECONDARY_NOT_RESIZABLE() { |
| if (BG_COLOR_SECONDARY_NOT_RESIZABLE == null || BG_COLOR_SECONDARY_NOT_RESIZABLE.isDisposed()) |
| BG_COLOR_SECONDARY_NOT_RESIZABLE = configurationProvider.getResourceRegistry().getSwtColor("edf4ff"); //$NON-NLS-1$ |
| return BG_COLOR_SECONDARY_NOT_RESIZABLE; |
| } |
| |
| /** |
| * Overridden to create a {@link ResizeTracker}, if resizing is supported, |
| * or to create a {@link DragEditPartsTracker}, if moving is supported. |
| */ |
| @Override |
| protected DragTracker createDragTracker() { |
| if (isResizable()) { |
| return new ResizeTracker(getOwner(), resizeDirection); |
| } else if (movable) { |
| DragEditPartsTracker tracker = new DragEditPartsTracker(getOwner()); |
| tracker.setDefaultCursor(getCursor()); |
| return tracker; |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Returns <code>true</code> if the handles owner is the primary selection. |
| * If not, it must be the secondary selection. |
| * |
| * @return <code>true</code> if the handles owner is the primary selection. |
| */ |
| private boolean isPrimarySelected() { |
| return getOwner().getSelected() == EditPart.SELECTED_PRIMARY; |
| } |
| |
| /** |
| * Paints a rectangular handle which is placed at a corner or at a side of |
| * the shape edit-part. |
| */ |
| @Override |
| public void paintFigure(Graphics g) { |
| g.setAntialias(SWT.ON); |
| g.setLineWidth(getLineWidth()); |
| |
| boolean primary = isPrimarySelected(); |
| Color fg; |
| Color bg; |
| if (primary && isResizable()) { |
| fg = getFG_COLOR_PRIMARY_RESIZABLE(); |
| bg = getBG_COLOR_PRIMARY_RESIZABLE(); |
| } else if (primary && !isResizable()) { |
| fg = getFG_COLOR_NOT_RESIZABLE(); |
| bg = getBG_COLOR_PRIMARY_NOT_RESIZABLE(); |
| } else if (!primary && isResizable()) { |
| fg = getFG_COLOR_SECONDARY_RESIZABLE(); |
| bg = getBG_COLOR_SECONDARY_RESIZABLE(); |
| } else { // (!primary && !isResizable()) |
| fg = getFG_COLOR_NOT_RESIZABLE(); |
| bg = getBG_COLOR_SECONDARY_NOT_RESIZABLE(); |
| } |
| if (fg != null) { |
| // It is necessary to adapt the color. This ensures the support for |
| // the high contrast mode. |
| g.setForegroundColor(convertColorForHighContrastMode(fg, SWT.COLOR_WIDGET_FOREGROUND)); |
| } |
| if (bg != null) { |
| // It is necessary to adapt the color. This ensures the support for |
| // the high contrast mode. |
| g.setBackgroundColor(convertColorForHighContrastMode(bg, SWT.COLOR_WIDGET_BACKGROUND)); |
| } |
| |
| Rectangle r = GFFigureUtil.getAdjustedRectangle(getBounds(), 1.0, getLineWidth()); |
| g.fillRectangle(r); |
| g.drawRectangle(r); |
| } |
| |
| /** |
| * Converts the given color according to the high contrast mode settings. If |
| * the system is not in high contrast mode the given value is simply |
| * returned. |
| * |
| * @param color |
| * The color to convert |
| * @param colorType |
| * can be SWT.COLOR_WIDGET_BACKGROUND for the background color or |
| * SWT.COLOR_WIDGET_FOREGROUND for the foreground color in high |
| * contrast mode |
| * @return The converted color if in high contrast mode, otherwise the given |
| * color |
| */ |
| private Color convertColorForHighContrastMode(Color color, int colorType) { |
| Color result = null; |
| // Set background color to bg unless in high contrast mode. |
| // In that case, get the color from system |
| Display display = Display.getCurrent(); |
| if (display == null) { |
| display = Display.getDefault(); |
| } |
| Color highContrastClr = null; |
| try { |
| if (display.getHighContrast()) { |
| highContrastClr = display.getSystemColor(colorType); |
| } |
| } catch (SWTException e) { |
| highContrastClr = null; |
| } |
| result = highContrastClr == null ? color : highContrastClr; |
| return result; |
| } |
| |
| /** |
| * Returns the line-width adjusted with the current zoom-level. |
| * |
| * @return The line-width adjusted with the current zoom-level. |
| */ |
| private int getLineWidth() { |
| double zoom = GFHandleHelper.getZoomLevel(configurationProvider); |
| return Math.max(1, (int) (zoom * LINE_WIDTH)); |
| } |
| |
| /** |
| * Returns true, if the handle can be used to resize the shape edit-part. |
| * |
| * @return true, if the handle can be used to resize the shape edit-part. |
| */ |
| private boolean isResizable() { |
| return resizeDirection != 0; |
| } |
| } |