/******************************************************************************* * Copyright (c) 2014, 2016 itemis AG and others. * 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: * Alexander Nyßen (itemis AG) - initial API and implementation * *******************************************************************************/ package org.eclipse.gef.mvc.fx.gestures; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import org.eclipse.gef.common.activate.ActivatableSupport; import org.eclipse.gef.mvc.fx.domain.IDomain; import org.eclipse.gef.mvc.fx.handlers.IHandler; import org.eclipse.gef.mvc.fx.viewer.IViewer; import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectWrapper; /** * The {@link AbstractGesture} can be used as a base class for {@link IGesture} * implementations. * * @author anyssen * @author mwienand * */ public abstract class AbstractGesture implements IGesture { private ActivatableSupport acs = new ActivatableSupport(this); private ReadOnlyObjectWrapper<IDomain> domainProperty = new ReadOnlyObjectWrapper<>(); private Map<IViewer, List<IHandler>> activeHandlers = new IdentityHashMap<>(); @Override public final void activate() { acs.activate(null, this::doActivate); } @Override public final ReadOnlyBooleanProperty activeProperty() { return acs.activeProperty(); } @Override public ReadOnlyObjectProperty<IDomain> adaptableProperty() { return domainProperty.getReadOnlyProperty(); } /** * Clears the list of active handlers of this gesture for the given viewer. * * @param viewer * The {@link IViewer} for which to clear the active handlers of * this gesture. * @see #getActiveHandlers(IViewer) * @see #setActiveHandlers(IViewer, Collection) */ protected void clearActiveHandlers(IViewer viewer) { if (viewer == null) { throw new IllegalArgumentException( "The given viewer may not be null."); } activeHandlers.remove(viewer); } @Override public final void deactivate() { acs.deactivate(this::doDeactivate, null); } /** * This method is called when a valid {@link IDomain} is attached to this * gesture so that you can register event listeners for various inputs * (keyboard, mouse) or model changes (selection, scroll offset / viewport). */ protected void doActivate() { } /** * This method is called when the attached {@link IDomain} is reset to * <code>null</code> so that you can unregister previously registered event * listeners. */ protected void doDeactivate() { } @Override public List<? extends IHandler> getActiveHandlers(IViewer viewer) { if (activeHandlers.containsKey(viewer)) { return Collections.unmodifiableList(activeHandlers.get(viewer)); } else { return Collections.emptyList(); } } @Override public IDomain getAdaptable() { return domainProperty.get(); } @Override public IDomain getDomain() { return getAdaptable(); } /** * Returns the {@link IHandlerResolver} of the {@link IDomain}. * * @return the {@link IHandlerResolver} of the {@link IDomain}. */ protected IHandlerResolver getHandlerResolver() { return getDomain().getAdapter(IHandlerResolver.class); } @Override public final boolean isActive() { return acs.isActive(); } /** * Set the active handlers of this gesture to the given handlers. * * @param viewer * The {@link IViewer} for which to store the active handlers of * this gesture. * @param activeHandlers * The active handlers of this gesture. * @see #clearActiveHandlers(IViewer) * @see #getActiveHandlers(IViewer) */ protected void setActiveHandlers(IViewer viewer, Collection<? extends IHandler> activeHandlers) { if (viewer == null) { throw new IllegalArgumentException( "The given viewer may not be null."); } if (activeHandlers == null) { throw new IllegalArgumentException( "The given activePolicies may not be null."); } for (IHandler ap : activeHandlers) { if (ap.getHost().getViewer() != viewer) { throw new IllegalArgumentException( "Resolved handler is not hosted within viewer."); } } clearActiveHandlers(viewer); this.activeHandlers.put(viewer, new ArrayList<>(activeHandlers)); } @Override public void setAdaptable(IDomain adaptable) { if (isActive()) { throw new IllegalStateException( "The reference to the IDomain may not be changed while the gesture is active. Please deactivate the gesture before setting the IEditDomain and re-activate it afterwards."); } domainProperty.set(adaptable); } }