/* * Copyright 2017 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kie.workbench.common.stunner.core.client.canvas.controls.drag; import java.util.logging.Level; import java.util.logging.Logger; import javax.enterprise.context.Dependent; import javax.inject.Inject; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvas; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.canvas.Point2D; import org.kie.workbench.common.stunner.core.client.canvas.controls.AbstractCanvasHandlerRegistrationControl; import org.kie.workbench.common.stunner.core.client.command.CanvasCommand; import org.kie.workbench.common.stunner.core.client.command.CanvasCommandFactory; import org.kie.workbench.common.stunner.core.client.command.CanvasCommandManager; import org.kie.workbench.common.stunner.core.client.command.CanvasCommandResultBuilder; import org.kie.workbench.common.stunner.core.client.command.CanvasViolation; import org.kie.workbench.common.stunner.core.client.shape.Shape; import org.kie.workbench.common.stunner.core.client.shape.view.HasDragBounds; import org.kie.workbench.common.stunner.core.client.shape.view.HasEventHandlers; import org.kie.workbench.common.stunner.core.client.shape.view.event.DragEvent; import org.kie.workbench.common.stunner.core.client.shape.view.event.DragHandler; import org.kie.workbench.common.stunner.core.client.shape.view.event.MouseEnterEvent; import org.kie.workbench.common.stunner.core.client.shape.view.event.MouseEnterHandler; import org.kie.workbench.common.stunner.core.client.shape.view.event.MouseExitEvent; import org.kie.workbench.common.stunner.core.client.shape.view.event.MouseExitHandler; import org.kie.workbench.common.stunner.core.client.shape.view.event.ViewEventType; import org.kie.workbench.common.stunner.core.command.CommandResult; import org.kie.workbench.common.stunner.core.command.util.CommandUtils; import org.kie.workbench.common.stunner.core.graph.Edge; import org.kie.workbench.common.stunner.core.graph.Element; import org.kie.workbench.common.stunner.core.graph.Graph; import org.kie.workbench.common.stunner.core.graph.Node; import org.kie.workbench.common.stunner.core.graph.content.Bounds; import org.kie.workbench.common.stunner.core.graph.content.definition.DefinitionSet; import org.kie.workbench.common.stunner.core.graph.content.view.View; import org.kie.workbench.common.stunner.core.graph.util.GraphUtils; @Dependent public class DragControlImpl extends AbstractCanvasHandlerRegistrationControl<AbstractCanvasHandler> implements DragControl<AbstractCanvasHandler, Element> { private static Logger LOGGER = Logger.getLogger(DragControlImpl.class.getName()); private static final int delta = 10; private final CanvasCommandFactory<AbstractCanvasHandler> canvasCommandFactory; private CommandManagerProvider<AbstractCanvasHandler> commandManagerProvider; protected final double[] dragShapeSize = new double[]{0, 0}; protected DragControlImpl() { this(null); } @Inject public DragControlImpl(final CanvasCommandFactory<AbstractCanvasHandler> canvasCommandFactory) { this.canvasCommandFactory = canvasCommandFactory; } @Override public void setCommandManagerProvider(final CommandManagerProvider<AbstractCanvasHandler> provider) { this.commandManagerProvider = provider; } @Override @SuppressWarnings("unchecked") public void register(final Element element) { if (checkNotRegistered(element)) { final AbstractCanvas<?> canvas = canvasHandler.getAbstractCanvas(); final Shape<?> shape = canvas.getShape(element.getUUID()); if (shape.getShapeView() instanceof HasEventHandlers) { final HasEventHandlers hasEventHandlers = (HasEventHandlers) shape.getShapeView(); // Register the drag handler. if (supportsDrag(hasEventHandlers)) { final DragHandler handler = new DragHandler() { @Override public void start(final DragEvent event) { doDragStart(element); } @Override public void handle(final DragEvent event) { } @Override public void end(final DragEvent event) { final CommandResult<CanvasViolation> result = doDragEnd(element); if (CommandUtils.isError(result)) { LOGGER.log(Level.SEVERE, "Update element's position command failed [result=" + result + "]"); event.getDragContext().reset(); } } }; hasEventHandlers.addHandler(ViewEventType.DRAG, handler); registerHandler(element.getUUID(), handler); } // Set the drag bounds. if (shape.getShapeView() instanceof HasDragBounds) { ensureDragConstraints((HasDragBounds<?>) shape.getShapeView()); } // Change mouse cursor, if shape supports it. if (supportsMouseEnter(hasEventHandlers) && supportsMouseExit(hasEventHandlers)) { final MouseEnterHandler overHandler = new MouseEnterHandler() { @Override public void handle(MouseEnterEvent event) { canvasHandler.getAbstractCanvas().getView().setCursor(AbstractCanvas.Cursors.MOVE); } }; hasEventHandlers.addHandler(ViewEventType.MOUSE_ENTER, overHandler); registerHandler(shape.getUUID(), overHandler); final MouseExitHandler outHandler = new MouseExitHandler() { @Override public void handle(MouseExitEvent event) { canvasHandler.getAbstractCanvas().getView().setCursor(AbstractCanvas.Cursors.AUTO); } }; hasEventHandlers.addHandler(ViewEventType.MOUSE_EXIT, outHandler); registerHandler(shape.getUUID(), outHandler); } } } } @Override @SuppressWarnings("unchecked") public CommandResult<CanvasViolation> move(final Element element, final double tx, final double ty) { final CanvasCommand<AbstractCanvasHandler> c = canvasCommandFactory.updatePosition((Node<View<?>, Edge>) element, tx, ty); CommandResult<CanvasViolation> result = getCommandManager().allow(canvasHandler, c); if (!CommandUtils.isError(result)) { result = getCommandManager().execute(canvasHandler, c); } return result; } public CommandResult<CanvasViolation> moveUp(final Element element) { return translate(element, 0, -delta); } public CommandResult<CanvasViolation> moveDown(final Element element) { return translate(element, 0, delta); } public CommandResult<CanvasViolation> moveLeft(final Element element) { return translate(element, -delta, 0); } public CommandResult<CanvasViolation> moveRight(final Element element) { return translate(element, delta, 0); } public CommandResult<CanvasViolation> translate(final Element element, final double dx, final double dy) { final Point2D p; try { p = GraphUtils.getPosition((View) element.getContent()); } catch (ClassCastException e) { LOGGER.log(Level.WARNING, "Update element's position command only cannot be applied to View elements."); return CanvasCommandResultBuilder.FAILED; } final double tx = p.getX() + dx; final double ty = p.getY() + dy; return move(element, tx, ty); } @Override protected void doDisable() { super.doDisable(); commandManagerProvider = null; } @SuppressWarnings("unchecked") protected void ensureDragConstraints(final HasDragBounds<?> shapeView) { final Graph<DefinitionSet, ? extends Node> graph = canvasHandler.getGraphIndex().getGraph(); final Bounds bounds = graph.getContent().getBounds(); shapeView.setDragBounds(bounds.getUpperLeft().getX(), bounds.getUpperLeft().getY(), bounds.getLowerRight().getX(), bounds.getLowerRight().getY()); } private void doDragStart(final Element element) { final double[] size = GraphUtils.getNodeSize((View) element.getContent()); dragShapeSize[0] = size[0]; dragShapeSize[1] = size[1]; } private CommandResult<CanvasViolation> doDragEnd(final Element element) { final AbstractCanvas<?> canvas = canvasHandler.getAbstractCanvas(); final Shape<?> shape = canvas.getShape(element.getUUID()); final double x = shape.getShapeView().getShapeX(); final double y = shape.getShapeView().getShapeY(); return move(element, x, y); } private boolean supportsDrag(final HasEventHandlers shapeView) { return shapeView.supports(ViewEventType.DRAG); } private boolean supportsMouseEnter(final HasEventHandlers shapeView) { return shapeView.supports(ViewEventType.MOUSE_ENTER); } private boolean supportsMouseExit(final HasEventHandlers shapeView) { return shapeView.supports(ViewEventType.MOUSE_EXIT); } private CanvasCommandManager<AbstractCanvasHandler> getCommandManager() { return commandManagerProvider.getCommandManager(); } }