/*******************************************************************************
* Copyright (c) 2000, 2007 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.IAdaptable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Assert;
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;
/**
* 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() {
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() {
return getRoot().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);
}
/**
* Reserved for future use
* @return boolean
*/
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 exising 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;
Map modelToEditPart = new HashMap();
List children = getChildren();
for (i = 0; i < children.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);
}
}
List trash = new ArrayList();
for (; i < children.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;
}
/**
* @see EditPart#setFocus(boolean)
*/
public void setFocus(boolean value) {
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) {
if (getModel() == model)
return;
this.model = model;
}
/**
* Sets the parent EditPart. There is no reason to
* override this method.
* @see EditPart#setParent(EditPart)
*/
public void setParent(EditPart parent) {
if (this.parent == parent)
return;
this.parent = parent;
}
/**
* sets the selected state for this EditPart. This
* method should rarely be overridden. Instead, EditPolicies that are selection-aware will
* listen for notification of this property changing.
* @see org.eclipse.gef.editpolicies.SelectionEditPolicy
* @see EditPartListener#selectedStateChanged(EditPart)
* @see EditPart#setSelected(int)
* @param value the selected value
*/
public void setSelected(int value) {
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() { }
}