| /******************************************************************************* |
| * Copyright (c) 2000, 2010 IBM Corporation 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.gef.editparts; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.Platform; |
| |
| import org.eclipse.draw2d.EventListenerList; |
| |
| import org.eclipse.gef.AccessibleEditPart; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.EditPartFactory; |
| import org.eclipse.gef.EditPartListener; |
| import org.eclipse.gef.EditPartViewer; |
| import org.eclipse.gef.EditPolicy; |
| import org.eclipse.gef.Request; |
| import org.eclipse.gef.RequestConstants; |
| import org.eclipse.gef.RootEditPart; |
| import org.eclipse.gef.commands.Command; |
| import org.eclipse.gef.editpolicies.SelectionEditPolicy; |
| |
| /** |
| * The baseline implementation for the {@link EditPart} interface. |
| * <P> |
| * Since this is the default implementation of an interface, this document deals |
| * with proper sub-classing of this implementation. This class is not the API. |
| * For documentation on proper usage of the public API, see the documentation |
| * for the interface itself: {@link EditPart}. |
| * <P> |
| * This class assumes no visual representation. Subclasses |
| * {@link AbstractGraphicalEditPart} and {@link AbstractTreeEditPart} add |
| * support for {@link org.eclipse.draw2d.IFigure Figures} and |
| * {@link org.eclipse.swt.widgets.TreeItem TreeItems} respectively. |
| * <P> |
| * AbstractEditPart provides support for children. All AbstractEditPart's can |
| * potentially be containers for other EditParts. |
| */ |
| public abstract class AbstractEditPart implements EditPart, RequestConstants, |
| IAdaptable { |
| |
| /** |
| * This flag is set during {@link #activate()}, and reset on |
| * {@link #deactivate()} |
| */ |
| protected static final int FLAG_ACTIVE = 1; |
| /** |
| * This flag indicates that the EditPart has focus. |
| */ |
| protected static final int FLAG_FOCUS = 2; |
| |
| /** |
| * The left-most bit that is reserved by this class for setting flags. |
| * Subclasses may define additional flags starting at |
| * <code>(MAX_FLAG << 1)</code>. |
| */ |
| protected static final int MAX_FLAG = FLAG_FOCUS; |
| |
| private Object model; |
| private int flags; |
| private EditPart parent; |
| private int selected; |
| |
| private Object policies[]; |
| |
| /** |
| * The List of children EditParts |
| */ |
| protected List children; |
| |
| /** |
| * call getEventListeners(Class) instead. |
| */ |
| EventListenerList eventListeners = new EventListenerList(); |
| |
| /** |
| * Iterates over a <code>List</code> of EditPolcies, skipping any |
| * <code>null</code> values encountered. |
| */ |
| protected static class EditPolicyIterator { |
| private Object list[]; |
| private int offset = 0; |
| private final int length; |
| |
| EditPolicyIterator(Object list[]) { |
| this.list = list; |
| length = (list == null) ? 0 : list.length; |
| } |
| |
| /** |
| * Constructs an Iterator for the given <code>List</code>. |
| * |
| * @deprecated this constructor should not be used |
| * @param list |
| * the list of policies. |
| */ |
| public EditPolicyIterator(List list) { |
| this(list.toArray()); |
| } |
| |
| /** |
| * Returns the next non-<code>null</code> EditPolicy. |
| * |
| * @return the next non-<code>null</code> EditPolicy. |
| */ |
| public EditPolicy next() { |
| if (offset < length) |
| return (EditPolicy) list[offset++]; |
| return null; |
| } |
| |
| /** |
| * Returns <code>true</code> if there is a next edit policy. |
| * |
| * @return <code>true</code> if there is a next policy |
| */ |
| public boolean hasNext() { |
| if (list == null) |
| return false; |
| |
| while (offset < list.length |
| && !(list[offset] instanceof EditPolicy)) |
| offset++; |
| return offset < list.length; |
| } |
| } |
| |
| /** |
| * Activates this EditPart, which in turn activates its children and |
| * EditPolicies. Subclasses should <em>extend</em> this method to add |
| * listeners to the model. Activation indicates that the EditPart is |
| * realized in an EditPartViewer. <code>deactivate()</code> is the inverse, |
| * and is eventually called on all EditParts. |
| * |
| * @see EditPart#activate() |
| * @see #deactivate() |
| */ |
| public void activate() { |
| setFlag(FLAG_ACTIVE, true); |
| |
| activateEditPolicies(); |
| |
| List c = getChildren(); |
| for (int i = 0; i < c.size(); i++) |
| ((EditPart) c.get(i)).activate(); |
| |
| fireActivated(); |
| } |
| |
| /** |
| * Activates all EditPolicies installed on this part. There is no reason to |
| * override this method. |
| * |
| * @see #activate() |
| */ |
| protected void activateEditPolicies() { |
| EditPolicyIterator i = getEditPolicyIterator(); |
| while (i.hasNext()) |
| i.next().activate(); |
| } |
| |
| /** |
| * Adds a child <code>EditPart</code> to this EditPart. This method is |
| * called from {@link #refreshChildren()}. The following events occur in the |
| * order listed: |
| * <OL> |
| * <LI>The child is added to the {@link #children} List, and its parent is |
| * set to <code>this</code> |
| * <LI>{@link #addChildVisual(EditPart, int)} is called to add the child's |
| * visual |
| * <LI>{@link EditPart#addNotify()} is called on the child. |
| * <LI><code>activate()</code> is called if this part is active |
| * <LI><code>EditPartListeners</code> are notified that the child has been |
| * added. |
| * </OL> |
| * <P> |
| * Subclasses should implement {@link #addChildVisual(EditPart, int)}. |
| * |
| * @param child |
| * The <code>EditPart</code> to add |
| * @param index |
| * The index |
| * @see #addChildVisual(EditPart, int) |
| * @see #removeChild(EditPart) |
| * @see #reorderChild(EditPart,int) |
| */ |
| protected void addChild(EditPart child, int index) { |
| Assert.isNotNull(child); |
| if (index == -1) |
| index = getChildren().size(); |
| if (children == null) |
| children = new ArrayList(2); |
| |
| children.add(index, child); |
| child.setParent(this); |
| addChildVisual(child, index); |
| child.addNotify(); |
| |
| if (isActive()) |
| child.activate(); |
| fireChildAdded(child, index); |
| } |
| |
| /** |
| * Performs the addition of the child's <i>visual</i> to this EditPart's |
| * Visual. The provided subclasses {@link AbstractGraphicalEditPart} and |
| * {@link AbstractTreeEditPart} already implement this method correctly, so |
| * it is unlikely that this method should be overridden. |
| * |
| * @param child |
| * The EditPart being added |
| * @param index |
| * The child's position |
| * @see #addChild(EditPart, int) |
| * @see AbstractGraphicalEditPart#removeChildVisual(EditPart) |
| */ |
| protected abstract void addChildVisual(EditPart child, int index); |
| |
| /** |
| * Adds an EditPartListener. |
| * |
| * @param listener |
| * the listener |
| */ |
| public void addEditPartListener(EditPartListener listener) { |
| eventListeners.addListener(EditPartListener.class, listener); |
| } |
| |
| /** |
| * @see EditPart#addNotify() |
| */ |
| public void addNotify() { |
| register(); |
| createEditPolicies(); |
| List children = getChildren(); |
| for (int i = 0; i < children.size(); i++) |
| ((EditPart) children.get(i)).addNotify(); |
| refresh(); |
| } |
| |
| /** |
| * Create the child <code>EditPart</code> for the given model object. This |
| * method is called from {@link #refreshChildren()}. |
| * <P> |
| * By default, the implementation will delegate to the |
| * <code>EditPartViewer</code>'s {@link EditPartFactory}. Subclasses may |
| * override this method instead of using a Factory. |
| * |
| * @param model |
| * the Child model object |
| * @return The child EditPart |
| */ |
| protected EditPart createChild(Object model) { |
| return getViewer().getEditPartFactory().createEditPart(this, model); |
| } |
| |
| /** |
| * Creates the initial EditPolicies and/or reserves slots for dynamic ones. |
| * Should be implemented to install the inital EditPolicies based on the |
| * model's initial state. <code>null</code> can be used to reserve a "slot", |
| * should there be some desire to guarantee the ordering of EditPolcies. |
| * |
| * @see EditPart#installEditPolicy(Object, EditPolicy) |
| */ |
| protected abstract void createEditPolicies(); |
| |
| /** |
| * Deactivates this EditPart, and in turn deactivates its children and |
| * EditPolicies. Subclasses should <em>extend</em> this method to remove any |
| * listeners established in {@link #activate()} |
| * |
| * @see EditPart#deactivate() |
| * @see #activate() |
| */ |
| public void deactivate() { |
| List c = getChildren(); |
| for (int i = 0; i < c.size(); i++) |
| ((EditPart) c.get(i)).deactivate(); |
| |
| deactivateEditPolicies(); |
| |
| setFlag(FLAG_ACTIVE, false); |
| fireDeactivated(); |
| } |
| |
| /** |
| * Deactivates all installed EditPolicies. |
| */ |
| protected void deactivateEditPolicies() { |
| EditPolicyIterator i = getEditPolicyIterator(); |
| while (i.hasNext()) |
| i.next().deactivate(); |
| } |
| |
| /** |
| * This method will log a message to GEF's trace/debug system if the |
| * corresponding flag for EditParts is set to true. |
| * |
| * @param message |
| * a debug message |
| * @deprecated in 3.1 |
| */ |
| protected final void debug(String message) { |
| } |
| |
| /** |
| * This method will log the message to GEF's trace/debug system if the |
| * corrseponding flag for FEEDBACK is set to true. |
| * |
| * @param message |
| * Message to be passed |
| * @deprecated in 3.1 |
| */ |
| protected final void debugFeedback(String message) { |
| } |
| |
| /** |
| * Erases source feedback for the given <code>Request</code>. By default, |
| * this responsibility is delegated to this part's <code>EditPolicies</code> |
| * . Subclasses should rarely extend this method. |
| * <P> |
| * <table> |
| * <tr> |
| * <td><img src="../doc-files/important.gif"/> |
| * <td>It is recommended that feedback be handled by EditPolicies, and not |
| * directly by the EditPart. |
| * </tr> |
| * </table> |
| * |
| * @param request |
| * identifies the type of feedback to erase. |
| * @see #showSourceFeedback(Request) |
| */ |
| public void eraseSourceFeedback(Request request) { |
| if (isActive()) { |
| EditPolicyIterator iter = getEditPolicyIterator(); |
| while (iter.hasNext()) |
| iter.next().eraseSourceFeedback(request); |
| } |
| } |
| |
| /** |
| * Erases target feedback for the given <code>Request</code>. By default, |
| * this responsibility is delegated to this part's EditPolicies. Subclasses |
| * should rarely extend this method. |
| * <P> |
| * <table> |
| * <tr> |
| * <td><img src="../doc-files/important.gif"/> |
| * <td>It is recommended that feedback be handled by EditPolicies, and not |
| * directly by the EditPart. |
| * </tr> |
| * </table> |
| * |
| * @param request |
| * Command requesting the erase. |
| * @see #showTargetFeedback(Request) |
| */ |
| public void eraseTargetFeedback(Request request) { |
| if (isActive()) { |
| EditPolicyIterator iter = getEditPolicyIterator(); |
| while (iter.hasNext()) |
| iter.next().eraseTargetFeedback(request); |
| } |
| } |
| |
| /** |
| * Notifies <code>EditPartListeners</code> that this EditPart has been |
| * activated. |
| */ |
| protected void fireActivated() { |
| Iterator listeners = getEventListeners(EditPartListener.class); |
| while (listeners.hasNext()) |
| ((EditPartListener) listeners.next()).partActivated(this); |
| } |
| |
| /** |
| * Notifies <code>EditPartListeners</code> that a child has been added. |
| * |
| * @param child |
| * <code>EditPart</code> being added as child. |
| * @param index |
| * Position child is being added into. |
| */ |
| protected void fireChildAdded(EditPart child, int index) { |
| Iterator listeners = getEventListeners(EditPartListener.class); |
| while (listeners.hasNext()) |
| ((EditPartListener) listeners.next()).childAdded(child, index); |
| } |
| |
| /** |
| * Notifies <code>EditPartListeners </code> that this EditPart has been |
| * deactivated. |
| */ |
| protected void fireDeactivated() { |
| Iterator listeners = getEventListeners(EditPartListener.class); |
| while (listeners.hasNext()) |
| ((EditPartListener) listeners.next()).partDeactivated(this); |
| } |
| |
| /** |
| * Notifies <code>EditPartListeners</code> that a child is being removed. |
| * |
| * @param child |
| * <code>EditPart</code> being removed. |
| * @param index |
| * Position of the child in children list. |
| */ |
| protected void fireRemovingChild(EditPart child, int index) { |
| Iterator listeners = getEventListeners(EditPartListener.class); |
| while (listeners.hasNext()) |
| ((EditPartListener) listeners.next()).removingChild(child, index); |
| } |
| |
| /** |
| * Notifies <code>EditPartListeners</code> that the selection has changed. |
| */ |
| protected void fireSelectionChanged() { |
| Iterator listeners = getEventListeners(EditPartListener.class); |
| while (listeners.hasNext()) |
| ((EditPartListener) listeners.next()).selectedStateChanged(this); |
| } |
| |
| /** |
| * Returns the <code>AccessibleEditPart</code> adapter for this EditPart. |
| * The <B>same</B> adapter instance must be used throughout the editpart's |
| * existance. Each adapter has a unique ID which is registered during |
| * {@link #register()}. Accessibility clients can only refer to this |
| * editpart via that ID. |
| * |
| * @return <code>null</code> or an AccessibleEditPart adapter |
| */ |
| protected AccessibleEditPart getAccessibleEditPart() { |
| return null; |
| } |
| |
| /** |
| * Returns the specified adapter if recognized. Delegates to the workbench |
| * adapter mechanism. |
| * <P> |
| * Additional adapter types may be added in the future. Subclasses should |
| * extend this method as needed. |
| * |
| * @see IAdaptable#getAdapter(java.lang.Class) |
| */ |
| public Object getAdapter(Class key) { |
| if (AccessibleEditPart.class == key) |
| return getAccessibleEditPart(); |
| return Platform.getAdapterManager().getAdapter(this, key); |
| } |
| |
| /** |
| * @see org.eclipse.gef.EditPart#getChildren() |
| */ |
| public List getChildren() { |
| if (children == null) |
| return Collections.EMPTY_LIST; |
| return children; |
| } |
| |
| /** |
| * Subclasses should rarely extend this method. The default implementation |
| * combines the contributions from each installed <code>EditPolicy</code>. |
| * This method is implemented indirectly using EditPolicies. |
| * <P> |
| * <table> |
| * <tr> |
| * <td><img src="../doc-files/important.gif"/> |
| * <td>It is recommended that Command creation be handled by EditPolicies, |
| * and not directly by the EditPart. |
| * </tr> |
| * </table> |
| * |
| * @see EditPart#getCommand(Request) |
| * @see EditPolicy#getCommand(Request) |
| * @param request |
| * the Request |
| * @return a Command |
| */ |
| public Command getCommand(Request request) { |
| Command command = null; |
| EditPolicyIterator i = getEditPolicyIterator(); |
| while (i.hasNext()) { |
| if (command != null) |
| command = command.chain(i.next().getCommand(request)); |
| else |
| command = i.next().getCommand(request); |
| } |
| return command; |
| } |
| |
| /** |
| * Returns an iterator for the specified type of listener |
| * |
| * @param clazz |
| * the Listener type over which to iterate |
| * @return Iterator |
| */ |
| protected final Iterator getEventListeners(Class clazz) { |
| return eventListeners.getListeners(clazz); |
| } |
| |
| /** |
| * @see org.eclipse.gef.EditPart#getEditPolicy(Object) |
| */ |
| public EditPolicy getEditPolicy(Object key) { |
| if (policies != null) |
| for (int i = 0; i < policies.length; i += 2) { |
| if (key.equals(policies[i])) |
| return (EditPolicy) policies[i + 1]; |
| } |
| return null; |
| } |
| |
| /** |
| * Used internally to iterate over the installed EditPolicies. While |
| * EditPolicy slots may be reserved with <code>null</code>, the iterator |
| * only returns the non-null ones. |
| * |
| * @return an EditPolicyIterator |
| */ |
| protected final EditPolicyIterator getEditPolicyIterator() { |
| return new EditPolicyIterator(policies); |
| } |
| |
| /** |
| * Returns the boolean value of the given flag. Specifically, returns |
| * <code>true</code> if the bitwise AND of the specified flag and the |
| * internal flags field is non-zero. |
| * |
| * @param flag |
| * Bitmask indicating which flag to return |
| * @return the requested flag's value |
| * @see #setFlag(int,boolean) |
| */ |
| protected final boolean getFlag(int flag) { |
| return (flags & flag) != 0; |
| } |
| |
| /** |
| * @see org.eclipse.gef.EditPart#getModel() |
| */ |
| public Object getModel() { |
| return model; |
| } |
| |
| /** |
| * Returns a <code>List</code> containing the children model objects. If |
| * this EditPart's model is a container, this method should be overridden to |
| * returns its children. This is what causes children EditParts to be |
| * created. |
| * <P> |
| * Callers must not modify the returned List. Must not return |
| * <code>null</code>. |
| * |
| * @return the List of children |
| */ |
| protected List getModelChildren() { |
| return Collections.EMPTY_LIST; |
| } |
| |
| /** |
| * @see org.eclipse.gef.EditPart#getParent() |
| */ |
| public EditPart getParent() { |
| return parent; |
| } |
| |
| /** |
| * @see org.eclipse.gef.EditPart#getRoot() |
| */ |
| public RootEditPart getRoot() { |
| if (getParent() == null) { |
| return null; |
| } |
| return getParent().getRoot(); |
| } |
| |
| /** |
| * @see org.eclipse.gef.EditPart#getSelected() |
| */ |
| public int getSelected() { |
| return selected; |
| } |
| |
| /** |
| * Returns the <code>EditPart</code> which is the target of the |
| * <code>Request</code>. The default implementation delegates this method to |
| * the installed EditPolicies. The first non-<code>null</code> result |
| * returned by an EditPolicy is returned. Subclasses should rarely extend |
| * this method. |
| * <P> |
| * <table> |
| * <tr> |
| * <td><img src="../doc-files/important.gif"/> |
| * <td>It is recommended that targeting be handled by EditPolicies, and not |
| * directly by the EditPart. |
| * </tr> |
| * </table> |
| * |
| * @param request |
| * Describes the type of target desired. |
| * @return <code>null</code> or the <i>target</i> <code>EditPart</code> |
| * @see EditPart#getTargetEditPart(Request) |
| * @see EditPolicy#getTargetEditPart(Request) |
| */ |
| public EditPart getTargetEditPart(Request request) { |
| EditPolicyIterator i = getEditPolicyIterator(); |
| EditPart editPart; |
| while (i.hasNext()) { |
| editPart = i.next().getTargetEditPart(request); |
| if (editPart != null) |
| return editPart; |
| } |
| |
| if (RequestConstants.REQ_SELECTION == request.getType()) { |
| if (isSelectable()) |
| return this; |
| } |
| |
| return null; |
| } |
| |
| /** |
| * @see org.eclipse.gef.EditPart#getViewer() |
| */ |
| public EditPartViewer getViewer() { |
| RootEditPart root = getRoot(); |
| if (root == null) { |
| return null; |
| } |
| return root.getViewer(); |
| } |
| |
| /** |
| * @see org.eclipse.gef.EditPart#hasFocus() |
| */ |
| public boolean hasFocus() { |
| return getFlag(FLAG_FOCUS); |
| } |
| |
| /** |
| * @see EditPart#installEditPolicy(Object, EditPolicy) |
| */ |
| public void installEditPolicy(Object key, EditPolicy editPolicy) { |
| Assert.isNotNull(key, "Edit Policies must be installed with keys");//$NON-NLS-1$ |
| if (policies == null) { |
| policies = new Object[2]; |
| policies[0] = key; |
| policies[1] = editPolicy; |
| } else { |
| int index = 0; |
| while (index < policies.length && !key.equals(policies[index])) |
| index += 2; |
| if (index < policies.length) { |
| index++; |
| EditPolicy old = (EditPolicy) policies[index]; |
| if (old != null && isActive()) |
| old.deactivate(); |
| policies[index] = editPolicy; |
| } else { |
| Object newPolicies[] = new Object[policies.length + 2]; |
| System.arraycopy(policies, 0, newPolicies, 0, policies.length); |
| policies = newPolicies; |
| policies[index] = key; |
| policies[index + 1] = editPolicy; |
| } |
| } |
| |
| if (editPolicy != null) { |
| editPolicy.setHost(this); |
| if (isActive()) |
| editPolicy.activate(); |
| } |
| } |
| |
| /** |
| * @return <code>true</code> if this EditPart is active. |
| */ |
| public boolean isActive() { |
| return getFlag(FLAG_ACTIVE); |
| } |
| |
| /** |
| * By default, an EditPart is regarded to be selectable. |
| * |
| * @see org.eclipse.gef.EditPart#isSelectable() |
| */ |
| public boolean isSelectable() { |
| return true; |
| } |
| |
| /** |
| * Subclasses should extend this method to handle Requests. For now, the |
| * default implementation does not handle any requests. |
| * |
| * @see EditPart#performRequest(Request) |
| */ |
| public void performRequest(Request req) { |
| } |
| |
| /** |
| * Refreshes all properties visually displayed by this EditPart. The default |
| * implementation will call {@link #refreshChildren()} to update its |
| * structural features. It also calls {@link #refreshVisuals()} to update |
| * its own displayed properties. Subclasses should extend this method to |
| * handle additional types of structural refreshing. |
| */ |
| public void refresh() { |
| refreshVisuals(); |
| refreshChildren(); |
| } |
| |
| /** |
| * Updates the set of children EditParts so that it is in sync with the |
| * model children. This method is called from {@link #refresh()}, and may |
| * also be called in response to notification from the model. This method |
| * requires linear time to complete. Clients should call this method as few |
| * times as possible. Consider also calling {@link #removeChild(EditPart)} |
| * and {@link #addChild(EditPart, int)} which run in constant time. |
| * <P> |
| * The update is performed by comparing the existing EditParts with the set |
| * of model children returned from {@link #getModelChildren()}. EditParts |
| * whose models no longer exist are {@link #removeChild(EditPart) removed}. |
| * New models have their EditParts {@link #createChild(Object) created}. |
| * <P> |
| * This method should <em>not</em> be overridden. |
| * |
| * @see #getModelChildren() |
| */ |
| protected void refreshChildren() { |
| int i; |
| EditPart editPart; |
| Object model; |
| |
| List children = getChildren(); |
| int size = children.size(); |
| Map modelToEditPart = Collections.EMPTY_MAP; |
| if (size > 0) { |
| modelToEditPart = new HashMap(size); |
| for (i = 0; i < size; i++) { |
| editPart = (EditPart) children.get(i); |
| modelToEditPart.put(editPart.getModel(), editPart); |
| } |
| } |
| |
| List modelObjects = getModelChildren(); |
| for (i = 0; i < modelObjects.size(); i++) { |
| model = modelObjects.get(i); |
| |
| // Do a quick check to see if editPart[i] == model[i] |
| if (i < children.size() |
| && ((EditPart) children.get(i)).getModel() == model) |
| continue; |
| |
| // Look to see if the EditPart is already around but in the |
| // wrong location |
| editPart = (EditPart) modelToEditPart.get(model); |
| |
| if (editPart != null) |
| reorderChild(editPart, i); |
| else { |
| // An EditPart for this model doesn't exist yet. Create and |
| // insert one. |
| editPart = createChild(model); |
| addChild(editPart, i); |
| } |
| } |
| |
| // remove the remaining EditParts |
| size = children.size(); |
| if (i < size) { |
| List trash = new ArrayList(size - i); |
| for (; i < size; i++) |
| trash.add(children.get(i)); |
| for (i = 0; i < trash.size(); i++) { |
| EditPart ep = (EditPart) trash.get(i); |
| removeChild(ep); |
| } |
| } |
| } |
| |
| /** |
| * Refreshes this EditPart's <i>visuals</i>. This method is called by |
| * {@link #refresh()}, and may also be called in response to notifications |
| * from the model. This method does nothing by default. Subclasses may |
| * override. |
| */ |
| protected void refreshVisuals() { |
| } |
| |
| /** |
| * Registers itself in the viewer's various registries. If your EditPart has |
| * a 1-to-1 relationship with a visual object and a 1-to-1 relationship with |
| * a model object, the default implementation should be sufficent. |
| * |
| * @see #unregister() |
| * @see EditPartViewer#getVisualPartMap() |
| * @see EditPartViewer#getEditPartRegistry() |
| */ |
| protected void register() { |
| registerModel(); |
| registerVisuals(); |
| registerAccessibility(); |
| } |
| |
| /** |
| * Registers the <code>AccessibleEditPart</code> adapter. |
| * |
| * @see #getAccessibleEditPart() |
| */ |
| protected final void registerAccessibility() { |
| if (getAccessibleEditPart() != null) |
| getViewer().registerAccessibleEditPart(getAccessibleEditPart()); |
| } |
| |
| /** |
| * Registers the <i>model</i> in the |
| * {@link EditPartViewer#getEditPartRegistry()}. Subclasses should only |
| * extend this method if they need to register this EditPart in additional |
| * ways. |
| */ |
| protected void registerModel() { |
| getViewer().getEditPartRegistry().put(getModel(), this); |
| } |
| |
| /** |
| * Registers the <i>visuals</i> in the |
| * {@link EditPartViewer#getVisualPartMap()}. Subclasses should override |
| * this method for the visual part they support. |
| * {@link AbstractGraphicalEditPart} and {@link AbstractTreeEditPart} |
| * already do this. |
| */ |
| protected void registerVisuals() { |
| } |
| |
| /** |
| * Removes a child <code>EditPart</code>. This method is called from |
| * {@link #refreshChildren()}. The following events occur in the order |
| * listed: |
| * <OL> |
| * <LI><code>EditPartListeners</code> are notified that the child is being |
| * removed |
| * <LI><code>deactivate()</code> is called if the child is active |
| * <LI>{@link EditPart#removeNotify()} is called on the child. |
| * <LI>{@link #removeChildVisual(EditPart)} is called to remove the child's |
| * visual object. |
| * <LI>The child's parent is set to <code>null</code> |
| * </OL> |
| * <P> |
| * Subclasses should implement {@link #removeChildVisual(EditPart)}. |
| * |
| * @param child |
| * EditPart being removed |
| * @see #addChild(EditPart,int) |
| */ |
| protected void removeChild(EditPart child) { |
| Assert.isNotNull(child); |
| int index = getChildren().indexOf(child); |
| if (index < 0) |
| return; |
| fireRemovingChild(child, index); |
| if (isActive()) |
| child.deactivate(); |
| child.removeNotify(); |
| removeChildVisual(child); |
| child.setParent(null); |
| getChildren().remove(child); |
| } |
| |
| /** |
| * Removes the childs visual from this EditPart's visual. Subclasses should |
| * implement this method to support the visual type they introduce, such as |
| * Figures or TreeItems. |
| * |
| * @param child |
| * the child EditPart |
| */ |
| protected abstract void removeChildVisual(EditPart child); |
| |
| /** |
| * No reason to override |
| * |
| * @see EditPart#removeEditPartListener(EditPartListener) |
| */ |
| public void removeEditPartListener(EditPartListener listener) { |
| eventListeners.removeListener(EditPartListener.class, listener); |
| } |
| |
| /** |
| * No reason to override |
| * |
| * @see EditPart#removeEditPolicy(Object) |
| */ |
| public void removeEditPolicy(Object key) { |
| if (policies == null) |
| return; |
| for (int i = 0; i < policies.length; i += 2) { |
| if (key.equals(policies[i])) { |
| i++; |
| EditPolicy policy = (EditPolicy) policies[i]; |
| policies[i] = null; |
| if (isActive() && policy != null) |
| policy.deactivate(); |
| } |
| } |
| } |
| |
| /** |
| * Removes all references from the <code>EditPartViewer</code> to this |
| * EditPart. This includes: |
| * <UL> |
| * <LI>deselecting this EditPart if selected |
| * <LI>setting the Viewer's focus to <code>null</code> if this EditPart has |
| * <i>focus</i> |
| * <LI>{@link #unregister()} this EditPart |
| * </UL> |
| * <P> |
| * In addition, <code>removeNotify()</code> is called recursively on all |
| * children EditParts. Subclasses should <em>extend</em> this method to |
| * perform any additional cleanup. |
| * |
| * @see EditPart#removeNotify() |
| */ |
| public void removeNotify() { |
| if (getSelected() != SELECTED_NONE) |
| getViewer().deselect(this); |
| if (hasFocus()) |
| getViewer().setFocus(null); |
| |
| List children = getChildren(); |
| for (int i = 0; i < children.size(); i++) |
| ((EditPart) children.get(i)).removeNotify(); |
| unregister(); |
| } |
| |
| /** |
| * Moves a child <code>EditPart</code> into a lower index than it currently |
| * occupies. This method is called from {@link #refreshChildren()}. |
| * |
| * @param editpart |
| * the child being reordered |
| * @param index |
| * new index for the child |
| */ |
| protected void reorderChild(EditPart editpart, int index) { |
| removeChildVisual(editpart); |
| List children = getChildren(); |
| children.remove(editpart); |
| children.add(index, editpart); |
| addChildVisual(editpart, index); |
| } |
| |
| /** |
| * Sets the value of the specified flag. Flag values are decalared as static |
| * constants. Subclasses may define additional constants above |
| * {@link #MAX_FLAG}. |
| * |
| * @param flag |
| * Flag being set |
| * @param value |
| * Value of the flag to be set |
| * @see #getFlag(int) |
| */ |
| protected final void setFlag(int flag, boolean value) { |
| if (value) |
| flags |= flag; |
| else |
| flags &= ~flag; |
| } |
| |
| /** |
| * Called by {@link EditPartViewer} to indicate that the {@link EditPart} |
| * has gained or lost keyboard focus. Focus is considered to be part of the |
| * selected state. Therefore, only selectable {@link EditPart}s are able to |
| * obtain focus, and the method may thus only be called with a value of |
| * <code>true</code> in case the receiver is selectable, i.e. |
| * {@link #isSelectable()} returns <code>true</code>. |
| * |
| * The method should rarely be overridden. Instead, EditPolicies that are |
| * selection-aware listen for notifications about the change of focus via |
| * {@link EditPartListener#selectedStateChanged(EditPart)}. |
| * |
| * @see EditPart#setFocus(boolean) |
| * @see EditPartListener#selectedStateChanged(EditPart) |
| * @see SelectionEditPolicy |
| */ |
| public void setFocus(boolean value) { |
| // only selectable edit parts may obtain focus |
| Assert.isLegal( |
| isSelectable() || !value, |
| "An EditPart has to be selectable (isSelectable() == true) in order to obtain focus."); //$NON-NLS-1$ |
| |
| if (hasFocus() == value) |
| return; |
| setFlag(FLAG_FOCUS, value); |
| fireSelectionChanged(); |
| } |
| |
| /** |
| * Set the primary model object that this EditPart represents. This method |
| * is used by an <code>EditPartFactory</code> when creating an EditPart. |
| * |
| * @see EditPart#setModel(Object) |
| */ |
| public void setModel(Object model) { |
| this.model = model; |
| } |
| |
| /** |
| * Sets the parent EditPart. There is no reason to override this method. |
| * |
| * @see EditPart#setParent(EditPart) |
| */ |
| public void setParent(EditPart parent) { |
| this.parent = parent; |
| } |
| |
| /** |
| * Sets the selected state for this EditPart, which may be one of: |
| * <ul> |
| * <li>{@link EditPart#SELECTED_PRIMARY}</li> |
| * <li>{@link EditPart#SELECTED}</li> |
| * <li>{@link EditPart#SELECTED_NONE}</li>. |
| * </ul> |
| * |
| * As only selectable {@link EditPart}s may get selected, the method may |
| * only be called with a selected value of {@link EditPart#SELECTED} or |
| * {@link EditPart#SELECTED_PRIMARY} in case the receiver is selectable, |
| * i.e. {@link #isSelectable()} returns <code>true</code>. |
| * |
| * The method should rarely be overridden. Instead, EditPolicies that are |
| * selection-aware listen for notifications about the change of selection |
| * state via {@link EditPartListener#selectedStateChanged(EditPart)}. |
| * |
| * @see EditPart#setSelected(int) |
| * @see EditPartListener#selectedStateChanged(EditPart) |
| * @see SelectionEditPolicy |
| * |
| * @param value |
| * the selected value |
| */ |
| public void setSelected(int value) { |
| // only selectable edit parts may get selected. |
| Assert.isLegal( |
| isSelectable() || value == SELECTED_NONE, |
| "An EditPart has to be selectable (isSelectable() == true) in order to get selected."); //$NON-NLS-1$ |
| |
| if (selected == value) |
| return; |
| selected = value; |
| fireSelectionChanged(); |
| } |
| |
| /** |
| * Shows or updates source feedback for the given <code>Request</code>. By |
| * default, this responsibility is delegated to this part's EditPolicies. |
| * Subclasses should rarely extend this method. |
| * <P> |
| * <table> |
| * <tr> |
| * <td><img src="../doc-files/important.gif"/> |
| * <td>It is recommended that feedback be handled by EditPolicies, and not |
| * directly by the EditPart. |
| * </tr> |
| * </table> |
| * |
| * @see EditPolicy#showSourceFeedback(Request) |
| * @see EditPart#showSourceFeedback(Request) |
| * @param request |
| * the Request |
| */ |
| public void showSourceFeedback(Request request) { |
| if (!isActive()) |
| return; |
| EditPolicyIterator i = getEditPolicyIterator(); |
| while (i.hasNext()) |
| i.next().showSourceFeedback(request); |
| } |
| |
| /** |
| * Shows or updates target feedback for the given <code>Request</code>. By |
| * default, this responsibility is delegated to this part's EditPolicies. |
| * Subclasses should rarely extend this method. |
| * <P> |
| * <table> |
| * <tr> |
| * <td><img src="../doc-files/important.gif"/> |
| * <td>It is recommended that feedback be handled by EditPolicies, and not |
| * directly by the EditPart. |
| * </tr> |
| * </table> |
| * |
| * @see EditPolicy#showTargetFeedback(Request) |
| * @see EditPart#showTargetFeedback(Request) |
| * @param request |
| * the Request |
| */ |
| public void showTargetFeedback(Request request) { |
| if (!isActive()) |
| return; |
| EditPolicyIterator i = getEditPolicyIterator(); |
| while (i.hasNext()) |
| i.next().showTargetFeedback(request); |
| } |
| |
| /** |
| * Describes this EditPart for developmental debugging purposes. |
| * |
| * @return a description |
| */ |
| public String toString() { |
| String c = getClass().getName(); |
| c = c.substring(c.lastIndexOf('.') + 1); |
| return c + "( " + getModel() + " )";//$NON-NLS-2$//$NON-NLS-1$ |
| } |
| |
| /** |
| * Returns <code>true</code> if this <code>EditPart</code> understand the |
| * given <code>Request</code>. By default, this responsibility is delegated |
| * to this part's installed EditPolicies. |
| * <P> |
| * <table> |
| * <tr> |
| * <td><img src="../doc-files/important.gif"/> |
| * <td>It is recommended that EditPolicies implement |
| * <code>understandsRequest()</code> |
| * </tr> |
| * </table> |
| * |
| * @see EditPart#understandsRequest(Request) |
| */ |
| public boolean understandsRequest(Request req) { |
| EditPolicyIterator iter = getEditPolicyIterator(); |
| while (iter.hasNext()) { |
| if (iter.next().understandsRequest(req)) |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Undoes any registration performed by {@link #register()}. The provided |
| * base classes will correctly unregister their visuals. |
| */ |
| protected void unregister() { |
| unregisterAccessibility(); |
| unregisterVisuals(); |
| unregisterModel(); |
| } |
| |
| /** |
| * Unregisters the {@link #getAccessibleEditPart() AccessibleEditPart} |
| * adapter. |
| */ |
| protected final void unregisterAccessibility() { |
| if (getAccessibleEditPart() != null) |
| getViewer().unregisterAccessibleEditPart(getAccessibleEditPart()); |
| } |
| |
| /** |
| * Unregisters the <i>model</i> in the |
| * {@link EditPartViewer#getEditPartRegistry()}. Subclasses should only |
| * extend this method if they need to unregister this EditPart in additional |
| * ways. |
| */ |
| protected void unregisterModel() { |
| Map registry = getViewer().getEditPartRegistry(); |
| if (registry.get(getModel()) == this) |
| registry.remove(getModel()); |
| } |
| |
| /** |
| * Unregisters the <i>visuals</i> in the |
| * {@link EditPartViewer#getVisualPartMap()}. Subclasses should override |
| * this method for the visual part they support. |
| * {@link AbstractGraphicalEditPart} and {@link AbstractTreeEditPart} |
| * already do this. |
| */ |
| protected void unregisterVisuals() { |
| } |
| |
| } |