/*******************************************************************************
* 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
*
* Note: Parts of this interface have been transferred from org.eclipse.gef.EditPart
*
*******************************************************************************/
package org.eclipse.gef.mvc.fx.parts;
import java.util.List;
import java.util.Map;
import org.eclipse.gef.common.activate.IActivatable;
import org.eclipse.gef.common.adapt.AdapterKey;
import org.eclipse.gef.common.adapt.IAdaptable;
import org.eclipse.gef.common.beans.property.ReadOnlyMultisetProperty;
import org.eclipse.gef.common.beans.property.ReadOnlySetMultimapProperty;
import org.eclipse.gef.common.collections.ObservableMultiset;
import org.eclipse.gef.common.collections.ObservableSetMultimap;
import org.eclipse.gef.common.dispose.IDisposable;
import org.eclipse.gef.mvc.fx.behaviors.IBehavior;
import org.eclipse.gef.mvc.fx.domain.IDomain;
import org.eclipse.gef.mvc.fx.gestures.IGesture;
import org.eclipse.gef.mvc.fx.handlers.IHandler;
import org.eclipse.gef.mvc.fx.policies.IPolicy;
import org.eclipse.gef.mvc.fx.viewer.IViewer;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provider;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ReadOnlyListProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.transform.Affine;
/**
* An {@link IVisualPart} plays the controller role in the model-view-controller
* architecture. While it does not have to be bound to a model (actually only
* {@link IContentPart}s are bound to model elements, {@link IFeedbackPart}s and
* {@link IHandlePart}s do not refer to model elements), an {@link IVisualPart}
* always controls a visual.
* <p>
* Within an {@link IViewer}, {@link IVisualPart} are organized in a hierarchy
* via a <code>[1:n]</code> parent-children relationship ({@link #getParent()},
* {@link #getChildrenUnmodifiable()}), which roots in an {@link IRootPart}.
* Furthermore a <code>[n:m]</code> anchorage-anchored relationship (
* {@link #getAnchoragesUnmodifiable()} , {@link #getAnchoredsUnmodifiable()})
* may be established between {@link IVisualPart}s located at arbitrary places
* within the hierarchy.
* <p>
* An {@link IVisualPart} is adaptable ({@link IAdaptable}). Usually,
* {@link IPolicy}s and {@link IBehavior}s are adapted to it (but arbitrary
* adapters may indeed be registered as needed). {@link IPolicy}s are usually
* required in case the {@link IVisualPart} is directly involved in user
* interaction (e.g. the user clicks on its controlled visual). They may be
* accessed type-safe by {@link IGesture}s or other {@link IPolicy}s (
* {@link IPolicy}s may delegate to other {@link IPolicy}s)). {@link IBehavior}s
* are used to react to changes of the attached model (in case of an
* {@link IContentPart}s), the viewer models, or others sources (e.g. adapters
* of the {@link IViewer} or {@link IDomain}), thereby reacting to changes of
* the interactive state.
* <p>
* {@link IVisualPart}s are {@link IActivatable} activatable, and an
* activation/deactivation of an {@link IVisualPart} will result in the
* activation/deactivation of all registered adapters (i.e. {@link IPolicy}s and
* {@link IBehavior}s).
* <p>
* An {@link IVisualPart} is responsible for registering itself for its
* visualization at the {@link IViewer#getVisualPartMap()} when it obtains a
* link to the {@link IViewer}. Equally, an {@link IVisualPart} is responsible
* for unregistering itself for its visualization from the
* {@link IViewer#getVisualPartMap()} when it loses a link to the
* {@link IViewer}.
*
* @noimplement This interface is not intended to be implemented by clients.
* Instead, {@link AbstractVisualPart} should be subclassed.
*
* @author anyssen
*
* @param <V>
* The visual node used by this {@link IVisualPart}.
*/
public interface IVisualPart<V extends Node> extends IAdaptable,
IAdaptable.Bound<IViewer>, IActivatable, IDisposable {
/**
* Name of the property storing this part's parent.
*/
public static final String PARENT_PROPERTY = "parent";
/**
* Name of the property storing this part's children.
*/
public static final String CHILDREN_PROPERTY = "children";
/**
* Name of the property storing this part's anchorages.
*/
public static final String ANCHORAGES_PROPERTY = "anchorages";
/**
* Name of the property storing this part's anchoreds.
*/
public static final String ANCHOREDS_PROPERTY = "anchoreds";
/**
* Name of the property storing the refresh visual boolean property.
*/
public static final String REFRESH_VISUAL_PROPERTY = "refreshVisual";
/**
* The role for the adapter key of the <code>Provider<Affine></code>
* that will be used to obtain the part's {@link Affine} transformation.
*/
// TODO: replace with a read-only object (Affine) property instead of using
// a provider, inserting the Affine within #getVisual()
String TRANSFORMATION_PROVIDER_ROLE = "transformationProvider";
/**
* The adapter key for the <code>Provider<Affine></code> that will be
* used to obtain the host's {@link Affine} transformation.
*/
@SuppressWarnings("serial")
AdapterKey<Provider<? extends Affine>> TRANSFORM_PROVIDER_KEY = AdapterKey
.get(new TypeToken<Provider<? extends Affine>>() {
}, IVisualPart.TRANSFORMATION_PROVIDER_ROLE);
/**
* Adds the given child to the list of this part's children.
*
* @param child
* The {@link IVisualPart} which is added to the list of this
* part's children.
*/
public void addChild(IVisualPart<? extends Node> child);
/**
* Adds the given child to the list of this part's children at the specified
* index.
*
* @param child
* The {@link IVisualPart} which is added to the list of this
* part's children.
* @param index
* The index at which the given {@link IVisualPart} is inserted
* into this part's children list.
*/
public void addChild(IVisualPart<? extends Node> child, int index);
/**
* Adds the given children to the list of this part's children.
*
* @param children
* The {@link IVisualPart}s which are added to the list of this
* part's children.
*/
public void addChildren(
List<? extends IVisualPart<? extends Node>> children);
/**
* Adds the given children to the list of this part's children at the
* specified index.
*
* @param children
* The {@link IVisualPart}s which are added to the list of this
* part's children.
* @param index
* The index at which the given {@link IVisualPart}s are inserted
* into this part's children list.
*/
public void addChildren(
List<? extends IVisualPart<? extends Node>> children, int index);
/**
* Returns a read-only set-multimap property containing this part's
* anchorages and their corresponding roles.
*
* @return A read-only set-multimap property named
* {@link #ANCHORAGES_PROPERTY}.
*/
public ReadOnlySetMultimapProperty<IVisualPart<? extends Node>, String> anchoragesUnmodifiableProperty();
/**
* Returns an unmodifiable read-only multiset property representing the
* anchoreds of this {@link IVisualPart}.
*
* @return An unmodifiable read-only multiset property named
* {@link #ANCHOREDS_PROPERTY}.
*/
public ReadOnlyMultisetProperty<IVisualPart<? extends Node>> anchoredsUnmodifiableProperty();
/**
* Used by an anchored {@link IVisualPart} to establish an
* anchorage-anchored relationship with this anchorage {@link IVisualPart}.
* <P>
* Clients should never call this operation directly but instead add the
* anchorage to its anchored via the {@link #attachToAnchorage(IVisualPart)}
* and {@link #attachToAnchorage(IVisualPart, String)} operations, which
* will indirectly lead to a call here.
*
* @param anchored
* An {@link IVisualPart} to attach to this anchorage
* {@link IVisualPart} as anchored.
*
* @noreference Clients should call {@link #attachToAnchorage(IVisualPart)},
* {@link #attachToAnchorage(IVisualPart, String)} instead to
* establish an anchored-anchorage relationship.
*/
public void attachAnchored(IVisualPart<? extends Node> anchored);
/**
* Attaches the given {@link IVisualPart} to the given anchorage under the
* "default" role.
*
* @param anchorage
* The anchorage {@link IVisualPart} to attach this part to.
*/
public void attachToAnchorage(IVisualPart<? extends Node> anchorage);
/**
* Attaches the given {@link IVisualPart} to the given anchorage under the
* given role.
*
* @param anchorage
* The anchorage {@link IVisualPart} to attach this part to.
* @param role
* The role under which this {@link IVisualPart} is attached to
* the given anchorage. <code>null</code>.
*/
public void attachToAnchorage(IVisualPart<? extends Node> anchorage,
String role);
/**
* Returns an unmodifiable read-only property containing the children of
* this {@link IVisualPart}.
*
* @see #getChildrenUnmodifiable()
* @see #addChild(IVisualPart)
* @see #addChild(IVisualPart, int)
* @see #addChildren(List)
* @see #addChildren(List, int)
* @see #removeChild(IVisualPart)
* @see #removeChildren(List)
* @see #reorderChild(IVisualPart, int)
*
* @return An unmodifiable read-only property named
* {@link #CHILDREN_PROPERTY}.
*/
public ReadOnlyListProperty<IVisualPart<? extends Node>> childrenUnmodifiableProperty();
/**
* Used by an anchored {@link IVisualPart} to unestablish an
* anchorage-anchored relationship with this anchorage {@link IVisualPart}.
* <P>
* Clients should never call this operation directly but instead remove the
* anchorage from its anchored via the
* {@link #detachFromAnchorage(IVisualPart)} or
* {@link #detachFromAnchorage(IVisualPart, String)} operations, which will
* indirectly lead to a call here.
*
* @param anchored
* An {@link IVisualPart} (currently attached as anchored to this
* anchorage {@link IVisualPart}) to detach from this anchorage
* {@link IVisualPart} as anchored.
*
* @noreference Clients should call
* {@link #detachFromAnchorage(IVisualPart)} or
* {@link #detachFromAnchorage(IVisualPart, String)} instead to
* unestablish an anchored-anchorage relationship.
*/
public void detachAnchored(IVisualPart<? extends Node> anchored);
/**
* Detaches this {@link IVisualPart} from the given anchorage
* {@link IVisualPart} under the 'default' role.
*
* @param anchorage
* The anchorage {@link IVisualPart} to detach this part from.
*/
public void detachFromAnchorage(IVisualPart<? extends Node> anchorage);
/**
* Detaches this {@link IVisualPart} from the given anchorage
* {@link IVisualPart} under the given role.
*
* @param anchorage
* The anchorage {@link IVisualPart} to detach this part from.
* @param role
* The role under which the {@link IVisualPart} can be found in
* this part's anchorages.
*/
public void detachFromAnchorage(IVisualPart<? extends Node> anchorage,
String role);
/**
* Returns an unmodifiable {@link ObservableSetMultimap} of this part's
* anchorages and their corresponding roles.
*
* @return A {@link ObservableSetMultimap} of this part's anchorages and
* their corresponding roles.
*/
public ObservableSetMultimap<IVisualPart<? extends Node>, String> getAnchoragesUnmodifiable();
/**
* Returns an unmodifiable {@link ObservableMultiset} of this part's
* anchoreds.
*
* @return An unmodifiable {@link ObservableMultiset} of this part's
* anchoreds.
*/
public ObservableMultiset<IVisualPart<? extends Node>> getAnchoredsUnmodifiable();
/**
* Returns a {@link Map} of this part's behaviors and their corresponding
* {@link AdapterKey}s.
*
* @return A {@link Map} of this part's behaviors and their corresponding
* {@link AdapterKey}s.
*/
public Map<AdapterKey<? extends IBehavior>, IBehavior> getBehaviors();
/**
* Returns an unmodifiable {@link ObservableList} of this part's children.
*
* @return A {@link ObservableList} of this part's children.
*/
public ObservableList<IVisualPart<? extends Node>> getChildrenUnmodifiable();
/**
* Returns a {@link Map} of this part's handlers and their corresponding
* {@link AdapterKey}s.
*
* @return A {@link Map} of this part's handlers and their corresponding
* {@link AdapterKey}s.
*/
public Map<AdapterKey<? extends IHandler>, IHandler> getHandlers();
/**
* Returns the parent of this part.
*
* @return The parent of this part.
*/
public IVisualPart<? extends Node> getParent();
/**
* Returns a {@link Map} of this part's policies and their corresponding
* {@link AdapterKey}s.
*
* @return A {@link Map} of this part's policies and their corresponding
* {@link AdapterKey}s.
*/
public Map<AdapterKey<? extends IPolicy>, IPolicy> getPolicies();
/**
* Returns the {@link IRootPart}. This method should only be called
* internally or by helpers such as edit policies. The root can be used to
* get the viewer.
*
* @return <code>null</code> or the {@link IRootPart}
*/
public IRootPart<? extends Node> getRoot();
/**
* Returns the {@link IViewer} this {@link IVisualPart} is bound to.
*
* @return The {@link IViewer} this {@link IVisualPart} is attached to.
*/
public default IViewer getViewer() {
return getAdaptable();
}
/**
* Returns this part's visual.
*
* @return This part's visual.
*/
public V getVisual();
/**
* Returns <code>true</code> if this part is allowed to refresh its
* visualization based on its content. Otherwise returns <code>false</code>.
*
* @return <code>true</code> if this part is allowed to refresh its
* visualization based on its content, otherwise <code>false</code>.
*/
public boolean isRefreshVisual();
/**
* Returns a read-only property that refers to the parent of this
* {@link IVisualPart}.
*
* @see #getParent()
* @see #setParent(IVisualPart)
*
* @return A read-only property named {@link #PARENT_PROPERTY}.
*/
public ReadOnlyObjectProperty<IVisualPart<? extends Node>> parentProperty();
/**
* Refreshes this part's visualization based on this part's content.
*/
public void refreshVisual();
/**
* A boolean property indicating whether this {@link IVisualPart} should
* refresh its visuals or not.
*
* @see #isRefreshVisual()
* @see #setRefreshVisual(boolean)
*
* @return A boolean property named {@link #REFRESH_VISUAL_PROPERTY}.
*/
public BooleanProperty refreshVisualProperty();
/**
* Removes the given {@link IVisualPart} from the list of this part's
* children.
*
* @param child
* The {@link IVisualPart} which is removed from the list of this
* part's children.
*/
public void removeChild(IVisualPart<? extends Node> child);
/**
* Removes the given {@link IVisualPart}s from the list of this part's
* children.
*
* @param children
* The {@link IVisualPart}s which are removed from the list of
* this part's children.
*/
public void removeChildren(
List<? extends IVisualPart<? extends Node>> children);
/**
* Swaps the given {@link IVisualPart} with the part at the given index
* position within this part's list of children.
*
* @param child
* The {@link IVisualPart} which is reordered.
* @param index
* The index to which the part is reordered.
*/
public void reorderChild(IVisualPart<? extends Node> child, int index);
/**
* Used by a parent {@link IVisualPart} to establish/unestablish a
* parent-child relationship with this child {@link IVisualPart}.
* <P>
* Clients should never call this operation directly but instead add the
* children to its parent via the {@link #addChild(IVisualPart)},
* {@link #addChild(IVisualPart, int)}, {@link #addChildren(List)}, or
* {@link #addChildren(List, int)} or remove it via the
* {@link #removeChild(IVisualPart)} or {@link #removeChildren(List)}
* operations, which will indirectly lead to a call here.
*
* @param parent
* The new parent {@link IVisualPart} or <code>null</code>.
*
* @noreference Clients should use {@link #addChild(IVisualPart)},
* {@link #addChild(IVisualPart, int)},
* {@link #addChildren(List)}, {@link #addChildren(List, int)},
* {@link #removeChild(IVisualPart)}, or
* {@link #removeChildren(List)} to establish/unestablish a
* parent-child relationship instead.
*/
public void setParent(IVisualPart<? extends Node> parent);
/**
* Allows to temporarily turn {@link #refreshVisual()} into a no-op
* operation. This may for instance be used to disable visual updates that
* are initiated by the model (in case of {@link IContentPart}s) while
* interacting with the {@link IVisualPart}.
*
* @param refreshVisual
* Whether {@link #refreshVisual()} should perform updates of the
* visual (<code>true</code>) or behave like a no-op operation (
* <code>false</code>).
*/
public void setRefreshVisual(boolean refreshVisual);
}