/* * Copyright 2016 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.lienzo.primitive; import com.ait.lienzo.client.core.shape.Layer; import com.google.gwt.event.dom.client.MouseDownEvent; import com.google.gwt.event.dom.client.MouseDownHandler; import com.google.gwt.event.dom.client.MouseMoveEvent; import com.google.gwt.event.dom.client.MouseMoveHandler; import com.google.gwt.event.dom.client.MouseUpEvent; import com.google.gwt.event.dom.client.MouseUpHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.RootPanel; public abstract class AbstractDragProxy<T> { public interface Callback { void onStart(final int x, final int y); void onMove(final int x, final int y); void onComplete(final int x, final int y); } private boolean attached = false; private Timer timer; private Runnable timeoutRunnable; private Integer xDiff = null; private Integer yDiff = null; private Layer layer = null; private T shapeProxy = null; private final HandlerRegistration[] handlerRegs = new HandlerRegistration[3]; protected abstract void addToLayer(final Layer layer, final T shape); protected abstract void removeFromLayer(final Layer layer, final T shape); protected abstract void setX(final T shape, final int x); protected abstract void setY(final T shape, final int y); public AbstractDragProxy(final Layer layer, final T shape, final int x, final int y, final int timeout, final Callback callback) { this.timer = new Timer() { @Override public void run() { if (null != timeoutRunnable) { timeoutRunnable.run(); ; } } }; this.timer.schedule(timeout); this.xDiff = null; this.yDiff = null; this.layer = layer; this.shapeProxy = shape; create(x, y, timeout, callback); } private void create(final int initialX, final int initialY, final int timeout, final Callback callback) { if (!attached) { addToLayer(layer, shapeProxy); setX(shapeProxy, initialX); setY(shapeProxy, initialY); attached = true; callback.onStart(initialX, initialY); } handlerRegs[0] = RootPanel.get().addDomHandler(new MouseMoveHandler() { @Override public void onMouseMove(final MouseMoveEvent mouseMoveEvent) { if (attached) { if (xDiff == null) { xDiff = initialX - mouseMoveEvent.getX(); } if (yDiff == null) { yDiff = initialY - mouseMoveEvent.getY(); } final int x = getXDiff() + mouseMoveEvent.getX(); final int y = getYDiff() + mouseMoveEvent.getY(); setX(shapeProxy, x); setY(shapeProxy, y); layer.batch(); if (!timer.isRunning()) { timer.schedule(timeout); } timeoutRunnable = () -> callback.onMove(x, y); timer.schedule(timeout); } } }, MouseMoveEvent.getType()); handlerRegs[1] = RootPanel.get().addDomHandler(new MouseDownHandler() { @Override public void onMouseDown(final MouseDownEvent mouseDownEvent) { mouseDownEvent.stopPropagation(); mouseDownEvent.preventDefault(); } }, MouseDownEvent.getType()); handlerRegs[2] = RootPanel.get().addDomHandler(new MouseUpHandler() { @Override public void onMouseUp(final MouseUpEvent mouseUpEvent) { if (attached) { timer.cancel(); final int x = getXDiff() + mouseUpEvent.getX(); final int y = getYDiff() + mouseUpEvent.getY(); AbstractDragProxy.this.clear(); callback.onComplete(x, y); } } }, MouseUpEvent.getType()); } private void removeHandlers() { handlerRegs[0].removeHandler(); handlerRegs[1].removeHandler(); handlerRegs[2].removeHandler(); } public void clear() { removeHandlers(); removeFromLayer(layer, shapeProxy); if (null != this.timer && this.timer.isRunning()) { this.timer.cancel(); } this.attached = false; this.xDiff = null; this.yDiff = null; } public void destroy() { clear(); this.timer = null; this.layer = null; this.shapeProxy = null; } private int getXDiff() { return null != xDiff ? xDiff : 0; } private int getYDiff() { return null != yDiff ? yDiff : 0; } }