/* * 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; import java.util.LinkedList; import java.util.List; 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.listener.CanvasElementListener; import org.kie.workbench.common.stunner.core.client.canvas.listener.CanvasShapeListener; import org.kie.workbench.common.stunner.core.client.command.RequiresCommandManager; import org.kie.workbench.common.stunner.core.client.shape.Shape; import org.kie.workbench.common.stunner.core.graph.Element; /** * Handles Canvas Control instances lifecycle. * @param <C> The canvas type. * @param <H> The canvas handler type. */ public class CanvasControlRegistrationHandler<C extends AbstractCanvas, H extends AbstractCanvasHandler> implements RequiresCommandManager<H> { private final List<CanvasControl<C>> canvasControls = new LinkedList<>(); private final List<CanvasControl<H>> canvasHandlerControls = new LinkedList<>(); private final C canvas; private final H handler; private CanvasShapeListener shapeListener; private CanvasElementListener elementListener; private CommandManagerProvider<H> commandManagerProvider; public CanvasControlRegistrationHandler(final C canvas, final H handler) { this.canvas = canvas; this.handler = handler; } /** * Registers a canvas control. * @param control The control instance. */ public void registerCanvasControl(final CanvasControl<C> control) { this.canvasControls.add(control); } /** * Registers a canvas handler control. * @param control The control instance. */ public void registerCanvasHandlerControl(final CanvasControl<H> control) { this.canvasHandlerControls.add(control); } /** * Enables current registered controls. */ public void enable() { initializeListeners(); enableControls(); } /** * Disables current registered controls. */ public void disable() { removeListeners(); disableControls(); } /** * Enables the canvas control. */ public void enableCanvasControl(final CanvasControl<C> control) { if (null != control) { control.enable(getCanvas()); } } /** * Enables the canvas handler control. */ @SuppressWarnings("unchecked") public void enableCanvasHandlerControl(final CanvasControl<H> control) { if (null != control) { control.enable(getCanvasHandler()); if (null != commandManagerProvider && control instanceof RequiresCommandManager) { ((RequiresCommandManager<H>) control).setCommandManagerProvider(commandManagerProvider); } } } /** * Clears the registered controls. * Controls can be added again and listeners will make it fire. */ public void clear() { disable(); canvasControls.clear(); canvasHandlerControls.clear(); } /** * Destroys the registered controls and this instance. */ public void destroy() { clear(); canvas.clearRegistrationListeners(); handler.clearRegistrationListeners(); shapeListener = null; elementListener = null; commandManagerProvider = null; } @Override public void setCommandManagerProvider(final CommandManagerProvider<H> provider) { this.commandManagerProvider = provider; } private void enableControls() { canvasControls.forEach(this::enableCanvasControl); canvasHandlerControls.forEach(this::enableCanvasHandlerControl); } private void disableControls() { canvasControls.forEach(CanvasControl::disable); canvasHandlerControls.forEach(CanvasControl::disable); } private void fireRegistrationListeners(final CanvasControl<H> control, final Element element, final boolean add) { if (null != control && null != element && control instanceof CanvasRegistationControl) { final CanvasRegistationControl<H, Element> registationControl = (CanvasRegistationControl<H, Element>) control; if (add) { registationControl.register(element); } else { registationControl.deregister(element); } } } private void fireRegistrationListeners(final CanvasControl<C> control, final Shape shape, final boolean add) { if (null != control && null != shape && control instanceof CanvasRegistationControl) { final CanvasRegistationControl<C, Shape> registationControl = (CanvasRegistationControl<C, Shape>) control; if (add) { registationControl.register(shape); } else { registationControl.deregister(shape); } } } private void fireRegistrationUpdateListeners(final CanvasControl<H> control, final Element element) { if (null != control && null != element && control instanceof AbstractCanvasHandlerRegistrationControl) { final AbstractCanvasHandlerRegistrationControl registationControl = (AbstractCanvasHandlerRegistrationControl) control; registationControl.update(element); } } private void fireRegistrationClearListeners(final CanvasControl<H> control) { if (null != control && control instanceof AbstractCanvasHandlerRegistrationControl) { final AbstractCanvasHandlerRegistrationControl registationControl = (AbstractCanvasHandlerRegistrationControl) control; registationControl.deregisterAll(); } } private C getCanvas() { return canvas; } private H getCanvasHandler() { return handler; } private void initializeListeners() { // Canvas listeners. final C canvas = getCanvas(); this.shapeListener = new CanvasShapeListener() { @Override public void register(final Shape item) { onRegisterShape(item); } @Override public void deregister(final Shape item) { onDeregisterShape(item); } @Override public void clear() { onClear(); } }; canvas.addRegistrationListener(shapeListener); // Canvas handler listeners. this.elementListener = new CanvasElementListener() { @Override public void update(final Element item) { onElementRegistration(item, false, true); } @Override public void register(final Element item) { onRegisterElement(item); } @Override public void deregister(final Element item) { onDeregisterElement(item); } @Override public void clear() { onClear(); } }; getCanvasHandler().addRegistrationListener(elementListener); } private void removeListeners() { if (null != shapeListener) { getCanvas().removeRegistrationListener(shapeListener); } if (null != elementListener) { getCanvasHandler().removeRegistrationListener(elementListener); } } private void onRegisterShape(final Shape shape) { onShapeRegistration(shape, true); } private void onDeregisterShape(final Shape shape) { onShapeRegistration(shape, false); } private void onRegisterElement(final Element element) { onElementRegistration(element, true, false); } private void onDeregisterElement(final Element element) { onElementRegistration(element, false, false); } private void onElementRegistration(final Element element, final boolean add, final boolean update) { if (update) { canvasHandlerControls.forEach(c -> fireRegistrationUpdateListeners(c, element)); } else { canvasHandlerControls.forEach(c -> fireRegistrationListeners(c, element, add)); } } private void onShapeRegistration(final Shape shape, final boolean add) { canvasControls.forEach(c -> fireRegistrationListeners(c, shape, add)); } private void onClear() { canvasHandlerControls.forEach(this::fireRegistrationClearListeners); } }