diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java index 3fb2fdf113e..404f026161f 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/callhierarchy/CallHierarchyContentProvider.java @@ -20,7 +20,6 @@ import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.ITreeContentProvider; @@ -47,6 +46,9 @@ import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.util.ExceptionHandler; +/** + * Content provider for call hierarchy. + */ public class CallHierarchyContentProvider implements ITreeContentProvider { /** @@ -57,215 +59,218 @@ public class CallHierarchyContentProvider implements ITreeContentProvider { * It has been replaced in 3.6 by API: * {@link PreferenceConstants#PREF_DEFAULT_EXPAND_WITH_CONSTRUCTORS_MEMBERS} *
- * * @since 3.5 */ - public static final String OLD_PREF_DEFAULT_EXPAND_WITH_CONSTRUCTORS= "CallHierarchy.defaultExpandWithConstructors"; //$NON-NLS-1$ + public static final String OLD_PREF_DEFAULT_EXPAND_WITH_CONSTRUCTORS + = "CallHierarchy.defaultExpandWithConstructors"; //$NON-NLS-1$ - private final static Object[] EMPTY_ARRAY= new Object[0]; + /** Empty object array. */ + private static final Object[] EMPTY_ARRAY = new Object[0]; + /** Tree content manager. */ + private DeferredTreeContentManager fManager; + /** View part. */ + private CallHierarchyViewPart fPart; - private DeferredTreeContentManager fManager; - private CallHierarchyViewPart fPart; + /** + * Class representing a method wrapper runnable. + */ + private static class MethodWrapperRunnable implements IRunnableWithProgress { + /** Method wrapper. */ + private MethodWrapper fMethodWrapper; + /** The calls. */ + private MethodWrapper[] fCalls = null; + + /** + * Constructor. + * @param methodWrapper Method wrapper + */ + MethodWrapperRunnable(MethodWrapper methodWrapper) { + fMethodWrapper = methodWrapper; + } - private static class MethodWrapperRunnable implements IRunnableWithProgress { - private MethodWrapper fMethodWrapper; - private MethodWrapper[] fCalls= null; + /** + * {@inheritDoc} + * @see org.eclipse.jface.operation.IRunnableWithProgress#run(IProgressMonitor) + */ + @Override + public void run(IProgressMonitor pm) { + fCalls = fMethodWrapper.getCalls(pm); + } - MethodWrapperRunnable(MethodWrapper methodWrapper) { - fMethodWrapper= methodWrapper; - } + /** + * Answers the calls. + * @return The calls + */ + MethodWrapper[] getCalls() { + return fCalls == null ? new MethodWrapper[0] : fCalls; + } + } - @Override - public void run(IProgressMonitor pm) { - fCalls= fMethodWrapper.getCalls(pm); - } - - MethodWrapper[] getCalls() { - if (fCalls != null) { - return fCalls; - } - return new MethodWrapper[0]; - } - } - - public CallHierarchyContentProvider(CallHierarchyViewPart part) { - super(); - fPart= part; - } - - /** - * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) - */ + /** + * Constructor. + * @param part Call hierarchy view part + */ + public CallHierarchyContentProvider(CallHierarchyViewPart part) { + super(); + fPart = part; + } + + /** + * {@inheritDoc} + * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) + */ @Override public Object[] getChildren(Object parentElement) { - if (parentElement instanceof TreeRoot) { - TreeRoot dummyRoot= (TreeRoot)parentElement; - return dummyRoot.getRoots(); - - } else if (parentElement instanceof RealCallers) { - MethodWrapper parentWrapper= ((RealCallers)parentElement).getParent(); - RealCallers element= ((RealCallers)parentElement); + if (parentElement instanceof TreeRoot tr) { + return tr.getRoots(); + } + if (parentElement instanceof RealCallers rc) { + MethodWrapper parentWrapper = rc.getParent(); if (fManager != null) { - Object[] children= fManager.getChildren(new DeferredMethodWrapper(this, element)); - if (children != null) + Object[] children = fManager.getChildren(new DeferredMethodWrapper(this, rc)); + if (children != null) { return children; + } } return fetchChildren(parentWrapper); - - } else if (parentElement instanceof MethodWrapper) { - MethodWrapper methodWrapper= ((MethodWrapper)parentElement); - - if (shouldStopTraversion(methodWrapper)) { + } + if (parentElement instanceof MethodWrapper mw) { + if (shouldStopTraversion(mw)) { return EMPTY_ARRAY; - } else { - if (parentElement instanceof CallerMethodWrapper) { - CallerMethodWrapper caller= (CallerMethodWrapper)parentElement; - ensureDefaultExpandWithConstructors(caller); - if (caller.getExpandWithConstructors()) { - IType type= caller.getMember().getDeclaringType(); - try { - if (type.isAnonymous()) { - IMember anonymousClass= type; - MethodCall anonymousConstructor= new MethodCall(anonymousClass); - CallerMethodWrapper anonymousWrapper= (CallerMethodWrapper)caller.createMethodWrapper(anonymousConstructor); - return new Object[] { anonymousWrapper, new RealCallers(methodWrapper, caller.getMethodCall()) }; - } if (type.isLambda()) { - IJavaElement definingMethod = type.getParent(); - if (definingMethod instanceof IMember) { - MethodCall methodCall = new MethodCall((IMember) definingMethod); - MethodWrapper wrapper = caller.createMethodWrapper(methodCall); - return new Object [] { wrapper, new RealCallers(methodWrapper, caller.getMethodCall()) }; - } - } else { - IMember[] constructors= JavaElementUtil.getAllConstructors(type); - if (constructors.length == 0) { - constructors= new IType[] { type }; // type stands for the default constructor - } - Object children[]= new Object[constructors.length + 1]; - for (int j= 0; j < constructors.length; j++) { - MethodCall constructor= new MethodCall(constructors[j]); - CallerMethodWrapper constructorWrapper= (CallerMethodWrapper)caller.createMethodWrapper(constructor); - children[j]= constructorWrapper; - } - children[constructors.length]= new RealCallers(methodWrapper, caller.getMethodCall()); - return children; + } + if (parentElement instanceof CallerMethodWrapper caller) { + ensureDefaultExpandWithConstructors(caller); + if (caller.getExpandWithConstructors()) { + IType type = caller.getMember().getDeclaringType(); + try { + if (type.isAnonymous()) { + MethodCall anonConstructor = new MethodCall(type); + CallerMethodWrapper anonWrapper + = (CallerMethodWrapper) caller.createMethodWrapper(anonConstructor); + return new Object[] { anonWrapper, new RealCallers(mw, caller.getMethodCall()) }; + } + if (type.isLambda()) { + IJavaElement definingMethod = type.getParent(); + if (definingMethod instanceof IMember mb) { + MethodWrapper wrapper = caller.createMethodWrapper(new MethodCall(mb)); + return new Object [] { wrapper, new RealCallers(mw, caller.getMethodCall()) }; } - } catch (JavaModelException e) { - JavaPlugin.log(e); - return null; + } else { + IMember[] constructors = JavaElementUtil.getAllConstructors(type); + if (constructors.length == 0) { + constructors = new IType[] { type }; // type stands for the default constructor + } + Object[] children = new Object[constructors.length + 1]; + for (int j = 0; j < constructors.length; j++) { + MethodCall constructor = new MethodCall(constructors[j]); + children[j] = caller.createMethodWrapper(constructor); + } + children[constructors.length] = new RealCallers(mw, caller.getMethodCall()); + return children; } - + } catch (JavaModelException e) { + JavaPlugin.log(e); + return null; } } - if (fManager != null) { - Object[] children= fManager.getChildren(new DeferredMethodWrapper(this, methodWrapper)); - if (children != null) - return children; + } + if (fManager != null) { + Object[] children = fManager.getChildren(new DeferredMethodWrapper(this, mw)); + if (children != null) { + return children; } - return fetchChildren(methodWrapper); } + return fetchChildren(mw); } - return EMPTY_ARRAY; - } + return EMPTY_ARRAY; + } /** * Sets the default "expand with constructors" mode for the method wrapper. Does nothing if the * mode has already been set. - * - * * @param wrapper the caller method wrapper * @since 3.5 */ static void ensureDefaultExpandWithConstructors(CallerMethodWrapper wrapper) { - - if (!wrapper.isExpandWithConstructorsSet()) { - if (CallHierarchyContentProvider.canExpandWithConstructors(wrapper)) { - IMethod method= (IMethod)wrapper.getMember(); - IType type= method.getDeclaringType(); - try { - boolean withConstructors= false; - if (type != null) { - boolean anonymousPref= PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.PREF_ANONYMOUS_EXPAND_WITH_CONSTRUCTORS); - if ((anonymousPref && (type.isAnonymous() || type.isLambda())) - || isInTheDefaultExpandWithConstructorList(method)) { - withConstructors= true; - } + if (!wrapper.isExpandWithConstructorsSet() && canExpandWithConstructors(wrapper)) { + IMethod method = (IMethod) wrapper.getMember(); + IType type = method.getDeclaringType(); + try { + boolean withConstructors = false; + if (type != null) { + final String key = PreferenceConstants.PREF_ANONYMOUS_EXPAND_WITH_CONSTRUCTORS; + boolean anonymousPref = PreferenceConstants.getPreferenceStore().getBoolean(key); + if ((anonymousPref && (type.isAnonymous() || type.isLambda())) + || isInTheDefaultExpandWithConstructorList(method)) { + withConstructors = true; } - wrapper.setExpandWithConstructors(withConstructors); - } catch (JavaModelException e) { - // ignore: expand mode will be off } + wrapper.setExpandWithConstructors(withConstructors); + } catch (JavaModelException e) { + // ignore: expand mode will be off } } - } /** * Checks whether given caller method wrapper can be expanded with constructors. - * * @param wrapper the caller method wrapper * @return true
if the wrapper can be expanded with constructors, false
otherwise
* @since 3.5
*/
static boolean canExpandWithConstructors(CallerMethodWrapper wrapper) {
- IMember member= wrapper.getMember();
- if (!(member instanceof IMethod))
- return false;
- IMethod method= (IMethod)member;
- try {
- if (JdtFlags.isStatic(method) || method.isConstructor())
- return false;
- } catch (JavaModelException e) {
- return false; // don't try to work with inexistent elements
+ if (wrapper.getMember() instanceof IMethod method) {
+ try {
+ return !JdtFlags.isStatic(method) && !method.isConstructor();
+ } catch (JavaModelException e) {
+ return false; // don't try to work with inexistent elements
+ }
}
- return true;
+ return false;
}
/**
* Checks if the method or its declaring type matches the pre-defined array of methods and types
* for default expand with constructors.
- *
* @param method the wrapped method
- * @return true
if method or type matches the pre-defined list, false
- * otherwise
- *
+ * @return true
if method or type matches the pre-defined list, false
otherwise
* @since 3.5
*/
static boolean isInTheDefaultExpandWithConstructorList(IMethod method) {
- String serializedMembers= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.PREF_DEFAULT_EXPAND_WITH_CONSTRUCTORS_MEMBERS);
- if (serializedMembers.length() == 0)
+ final String key = PreferenceConstants.PREF_DEFAULT_EXPAND_WITH_CONSTRUCTORS_MEMBERS;
+ String serializedMembers = PreferenceConstants.getPreferenceStore().getString(key);
+ if (serializedMembers.isEmpty()) {
return false;
+ }
- String[] defaultMemberPatterns= serializedMembers.split(";"); //$NON-NLS-1$
-
- String methodName= method.getElementName();
- IType declaringType= method.getDeclaringType();
- String declaringTypeName= declaringType.getFullyQualifiedName('.');
+ IType declaringType = method.getDeclaringType();
String superClassName;
String[] superInterfaceNames;
try {
- superClassName= declaringType.getSuperclassName();
+ superClassName = declaringType.getSuperclassName();
if (superClassName != null) {
- superClassName= stripTypeArguments(superClassName);
+ superClassName = stripTypeArguments(superClassName);
}
- superInterfaceNames= declaringType.getSuperInterfaceNames();
- for (int i= 0; i < superInterfaceNames.length; i++) {
- superInterfaceNames[i]= stripTypeArguments(superInterfaceNames[i]);
+ superInterfaceNames = declaringType.getSuperInterfaceNames();
+ for (int i = 0; i < superInterfaceNames.length; i++) {
+ superInterfaceNames[i] = stripTypeArguments(superInterfaceNames[i]);
}
} catch (JavaModelException e) {
return false;
}
+ String[] defaultMemberPatterns = serializedMembers.split(";"); //$NON-NLS-1$
+ String declaringTypeName = declaringType.getFullyQualifiedName('.');
for (String defaultMemberPattern : defaultMemberPatterns) {
- int pos= defaultMemberPattern.lastIndexOf('.');
- String defaultTypeName= defaultMemberPattern.substring(0, pos);
- String defaultMethodName= defaultMemberPattern.substring(pos + 1);
+ int pos = defaultMemberPattern.lastIndexOf('.');
+ String defaultTypeName = defaultMemberPattern.substring(0, pos);
+ String defaultMethodName = defaultMemberPattern.substring(pos + 1);
if ("*".equals(defaultMethodName)) { //$NON-NLS-1$
if (declaringTypeName.equals(defaultTypeName)) {
return true;
}
} else {
- if (!methodName.equals(defaultMethodName)) {
+ if (!method.getElementName().equals(defaultMethodName)) {
continue;
}
if (declaringTypeName.equals(defaultTypeName)) {
@@ -286,123 +291,124 @@ static boolean isInTheDefaultExpandWithConstructorList(IMethod method) {
/**
* Strips type arguments from the given type name and returns only erased type name.
- *
* @param typeName the type name
* @return the erased type name
- *
* @since 3.6
*/
private static String stripTypeArguments(String typeName) {
- int pos= typeName.indexOf('<');
- if (pos != -1)
- return typeName.substring(0, pos);
- return typeName;
+ int pos = typeName.indexOf('<');
+ return pos == -1 ? typeName : typeName.substring(0, pos);
}
+ /**
+ * Fetches the children.
+ * @param methodWrapper Method wrapper
+ * @return Fetched children
+ */
protected Object[] fetchChildren(final MethodWrapper methodWrapper) {
- IRunnableContext context= JavaPlugin.getActiveWorkbenchWindow();
- MethodWrapperRunnable runnable= new MethodWrapperRunnable(methodWrapper);
- try {
- context.run(true, true, runnable);
- } catch (InvocationTargetException e) {
- ExceptionHandler.handle(e, CallHierarchyMessages.CallHierarchyContentProvider_searchError_title, CallHierarchyMessages.CallHierarchyContentProvider_searchError_message);
- return EMPTY_ARRAY;
- } catch (InterruptedException e) {
- final CallerMethodWrapper element= (CallerMethodWrapper)methodWrapper;
- if (!isExpandWithConstructors(element)) {
- Display.getDefault().asyncExec(() -> collapseAndRefresh(element));
- }
- }
-
- return runnable.getCalls();
- }
-
-
- /**
- * Returns whether the given element is an "Expand witch Constructors" node.
- *
+ MethodWrapperRunnable runnable = new MethodWrapperRunnable(methodWrapper);
+ try {
+ JavaPlugin.getActiveWorkbenchWindow().run(true, true, runnable);
+ } catch (InvocationTargetException e) {
+ final String title = CallHierarchyMessages.CallHierarchyContentProvider_searchError_title;
+ ExceptionHandler.handle(e, title, CallHierarchyMessages.CallHierarchyContentProvider_searchError_message);
+ return EMPTY_ARRAY;
+ } catch (InterruptedException e) {
+ final CallerMethodWrapper element = (CallerMethodWrapper) methodWrapper;
+ if (!isExpandWithConstructors(element)) {
+ Display.getDefault().asyncExec(() -> collapseAndRefresh(element));
+ }
+ }
+ return runnable.getCalls();
+ }
+
+ /**
+ * Returns whether the given element is an "Expand witch Constructors" node.
* @param element a method wrapped
- * @return true
iff the element is an "Expand witch Constructors" node
+ * @return true
if the element is an "Expand witch Constructors" node
* @since 3.5
*/
static boolean isExpandWithConstructors(MethodWrapper element) {
- return element instanceof CallerMethodWrapper && ((CallerMethodWrapper)element).getExpandWithConstructors();
+ return element instanceof CallerMethodWrapper cmw && cmw.getExpandWithConstructors();
}
/**
- * Collapses and refreshes the given element when search has been canceled.
- *
- * @param element the element on which search has been canceled and which has to be collapsed
- * @since 3.5
- */
- protected void collapseAndRefresh(MethodWrapper element) {
- CallHierarchyViewer viewer= fPart.getViewer();
+ * Collapses and refreshes the given element when search has been canceled.
+ * @param element the element on which search has been canceled and which has to be collapsed
+ * @since 3.5
+ */
+ protected void collapseAndRefresh(MethodWrapper element) {
+ CallHierarchyViewer viewer = fPart.getViewer();
/* Problem case: The user expands the RealCallers node and then unchecks "Expand with Constructors"
* while the search for the real callers is still in progress.
*
* In this scenario, the RealCallers is not even part of the current tree any more, since the
* ExpandWithConstructorsAction already toggled the flag and refreshed the tree.
- *
- * But since setExpandedState(element, false) walks up the getParent() chain of the given element,
- * this causes the parent's children to be created, which would wrongly start a deferred search.
- *
- * The fix is to do nothing when the RealCaller's parent is expandWithConstructors.
+ *
+ * But since setExpandedState(element, false) walks up the getParent() chain of the given element,
+ * this causes the parent's children to be created, which would wrongly start a deferred search.
+ *
+ * The fix is to do nothing when the RealCaller's parent is expandWithConstructors.
*/
- boolean elementStays= true;
- if (element instanceof RealCallers) {
- elementStays= isExpandWithConstructors(element.getParent());
- }
+ boolean elementStays = true;
+ if (element instanceof RealCallers) {
+ elementStays = isExpandWithConstructors(element.getParent());
+ }
if (elementStays) {
- viewer.setExpandedState(element, false);
- }
+ viewer.setExpandedState(element, false);
+ }
- viewer.refresh(element);
- }
+ viewer.refresh(element);
+ }
/**
- * Returns the call hierarchy view part.
- *
+ * Returns the call hierarchy view part.
* @return the call hierarchy view part
* @since 3.5
*/
- public CallHierarchyViewPart getViewPart() {
- return fPart;
- }
-
- private boolean shouldStopTraversion(MethodWrapper methodWrapper) {
- return (methodWrapper.getLevel() > CallHierarchyUI.getDefault().getMaxCallDepth()) || methodWrapper.isRecursive();
- }
-
- /**
- * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
- */
- @Override
+ public CallHierarchyViewPart getViewPart() {
+ return fPart;
+ }
+
+ /**
+ * Checks if traversion should be stopped.
+ * @param mw Method wrapper
+ * @return true
if traversion should be stopped, false
otherwise
+ */
+ private boolean shouldStopTraversion(MethodWrapper mw) {
+ return mw.getLevel() > CallHierarchyUI.getDefault().getMaxCallDepth() || mw.isRecursive();
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+ */
+ @Override
public Object[] getElements(Object inputElement) {
- return getChildren(inputElement);
- }
+ return getChildren(inputElement);
+ }
- /**
- * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
- */
- @Override
+ /**
+ * {@inheritDoc}
+ * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
+ */
+ @Override
public Object getParent(Object element) {
- if (element instanceof MethodWrapper) {
- return ((MethodWrapper) element).getParent();
- }
-
- return null;
- }
+ return element instanceof MethodWrapper mw ? mw.getParent() : null;
+ }
- /**
- * @see org.eclipse.jface.viewers.IContentProvider#dispose()
- */
- @Override
+ /**
+ * {@inheritDoc}
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ @Override
public void dispose() {
- // Nothing to dispose
- }
+ // Nothing to dispose
+ }
- /**
+ /**
+ * {@inheritDoc}
* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
*/
@Override
@@ -413,17 +419,9 @@ public boolean hasChildren(Object element) {
// Only certain members can have subelements, so there's no need to fool the
// user into believing that there is more
- if (element instanceof MethodWrapper) {
- MethodWrapper methodWrapper= (MethodWrapper) element;
- if (! methodWrapper.canHaveChildren()) {
- return false;
- }
- if (shouldStopTraversion(methodWrapper)) {
- return false;
- }
- return true;
- } else if (element instanceof TreeRoot
- || element instanceof DeferredMethodWrapper) {
+ if (element instanceof MethodWrapper mw) {
+ return mw.canHaveChildren() && !shouldStopTraversion(mw);
+ } else if (element instanceof TreeRoot || element instanceof DeferredMethodWrapper) {
// Err on the safe side by returning true even though
// we don't know for sure that there are children.
return true;
@@ -432,45 +430,51 @@ public boolean hasChildren(Object element) {
return false; // the "Update ..." placeholder has no children
}
- /**
+ /**
+ * {@inheritDoc}
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
- * java.lang.Object, java.lang.Object)
+ * java.lang.Object, java.lang.Object)
*/
- @Override
+ @Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- if (oldInput instanceof TreeRoot) {
- MethodWrapper[] roots = ((TreeRoot) oldInput).getRoots();
- cancelJobs(roots);
- }
- if (viewer instanceof AbstractTreeViewer) {
- fManager = new DeferredTreeContentManager((AbstractTreeViewer) viewer, fPart.getSite());
- }
- }
-
- /**
- * Cancel all current jobs.
- * @param wrappers the parents to cancel jobs for
- */
- void cancelJobs(MethodWrapper[] wrappers) {
- if (fManager != null && wrappers != null) {
- for (MethodWrapper wrapper : wrappers) {
- fManager.cancel(wrapper);
- }
- if (fPart != null) {
- fPart.setCancelEnabled(false);
- }
- }
- }
-
- public void doneFetching() {
- if (fPart != null) {
- fPart.setCancelEnabled(false);
- }
- }
-
- public void startFetching() {
- if (fPart != null) {
- fPart.setCancelEnabled(true);
- }
- }
-}
+ if (oldInput instanceof TreeRoot tr) {
+ cancelJobs(tr.getRoots());
+ }
+ if (viewer instanceof AbstractTreeViewer atv) {
+ fManager = new DeferredTreeContentManager(atv, fPart.getSite());
+ }
+ }
+
+ /**
+ * Cancel all current jobs.
+ * @param wrappers the parents to cancel jobs for
+ */
+ void cancelJobs(MethodWrapper[] wrappers) {
+ if (fManager != null && wrappers != null) {
+ for (MethodWrapper wrapper : wrappers) {
+ fManager.cancel(wrapper);
+ }
+ if (fPart != null) {
+ fPart.setCancelEnabled(false);
+ }
+ }
+ }
+
+ /**
+ * Actions after fetching is done.
+ */
+ public void doneFetching() {
+ if (fPart != null) {
+ fPart.setCancelEnabled(false);
+ }
+ }
+
+ /**
+ * Actions when fetching is starting.
+ */
+ public void startFetching() {
+ if (fPart != null) {
+ fPart.setCancelEnabled(true);
+ }
+ }
+}
\ No newline at end of file