blob: 30d252fe7bb23a15c458de795ff11b253704dfb1 [file] [log] [blame]
/*******************************************************************************
* 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() {
}
}