### Eclipse Workspace Patch 1.0 #P org.eclipse.ui.navigator Index: schema/navigatorContent.exsd =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/schema/navigatorContent.exsd,v retrieving revision 1.22 diff -u -r1.22 navigatorContent.exsd --- schema/navigatorContent.exsd 9 Feb 2006 21:32:11 -0000 1.22 +++ schema/navigatorContent.exsd 15 Mar 2006 18:58:09 -0000 @@ -144,6 +144,18 @@ + + + + Supplies the name of a class which implements <code>org.eclipse.ui.navigator.ISaveableModelProvider</code>. +<br><br> +The model provider will be used to determine the saveable models that are shown in the tree. + + + + + + Index: src/org/eclipse/ui/navigator/CommonNavigator.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/navigator/CommonNavigator.java,v retrieving revision 1.12 diff -u -r1.12 CommonNavigator.java --- src/org/eclipse/ui/navigator/CommonNavigator.java 6 Feb 2006 22:24:46 -0000 1.12 +++ src/org/eclipse/ui/navigator/CommonNavigator.java 15 Mar 2006 18:58:09 -0000 @@ -10,12 +10,20 @@ *******************************************************************************/ package org.eclipse.ui.navigator; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.swt.SWT; @@ -23,7 +31,12 @@ import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IMemento; +import org.eclipse.ui.IModelLifecycleListener; +import org.eclipse.ui.ISaveableModel; +import org.eclipse.ui.ISaveableModelManager; +import org.eclipse.ui.ISaveableModelSource; import org.eclipse.ui.IViewSite; +import org.eclipse.ui.ModelLifecycleEvent; import org.eclipse.ui.PartInitException; import org.eclipse.ui.actions.ActionGroup; import org.eclipse.ui.internal.navigator.CommonNavigatorActionGroup; @@ -111,7 +124,7 @@ * * @since 3.2 */ -public class CommonNavigator extends ViewPart implements ISetSelectionTarget { +public class CommonNavigator extends ViewPart implements ISetSelectionTarget, ISaveableModelSource { /** *

@@ -132,6 +145,8 @@ private String LINKING_ENABLED = "CommonNavigator.LINKING_ENABLED"; //$NON-NLS-1$ + private ISaveableModel[] currentModels; + /** * */ @@ -185,6 +200,8 @@ commonActionGroup = createCommonActionGroup(); commonActionGroup.fillActionBars(getViewSite().getActionBars()); + + currentModels = computeModels(); } @@ -515,5 +532,149 @@ .getText(anElement); return ""; //$NON-NLS-1$ } + + public ISaveableModel[] getModels() { + return currentModels; + } + + private ISaveableModel[] computeModels() { + List result = new ArrayList(); + ITreeContentProvider contentProvider = (ITreeContentProvider) getCommonViewer().getContentProvider(); + Set roots = new HashSet(Arrays.asList(contentProvider.getElements(getInitialInput()))); + ISaveableModelProvider[] modelProviders = getModelProviders(); + for (int i = 0; i < modelProviders.length; i++) { + ISaveableModelProvider modelProvider = modelProviders[i]; + ISaveableModel[] models = modelProvider.getModels(); + for (int j = 0; j < models.length; j++) { + ISaveableModel model = models[j]; + Object[] elements = modelProvider.getElements(model); + findParentChainLoop: for (int k = 0; k < elements.length; k++) { + Object element = elements[k]; + while (element != null) { + if (roots.contains(element)) { + // found a parent chain leading to a root. The model is part of the tree. + result.add(model); + break findParentChainLoop; + } + element = contentProvider.getParent(element); + } + } + } + } + return (ISaveableModel[]) result.toArray(new ISaveableModel[result.size()]); + } + + /** + * @return all model objects + */ + private ISaveableModelProvider[] getModelProviders() { + // TODO implement this + return new ISaveableModelProvider[0]; + } + + public ISaveableModel[] getActiveModels() { + ITreeContentProvider contentProvider = (ITreeContentProvider) getCommonViewer().getContentProvider(); + List result = new ArrayList(); + IStructuredSelection selection = (IStructuredSelection) getCommonViewer().getSelection(); + for(Iterator it=selection.iterator();it.hasNext();){ + Object element = it.next(); + // try to find a model that contains the selected element + while (element!=null) { + ISaveableModel model = getModel(element); + if(model!=null){ + result.add(model); + break; + } + element = contentProvider.getParent(element); + } + } + return (ISaveableModel[]) result.toArray(new ISaveableModel[result.size()]); + } + + /** + * @param element + * @return the saveable model associated with the given element + */ + private ISaveableModel getModel(Object element) { + ISaveableModelProvider[] modelProviders = getModelProviders(); + for (int i = 0; i < modelProviders.length; i++) { + ISaveableModelProvider modelProvider = modelProviders[i]; + ISaveableModel model = modelProvider.getModel(element); + if(model!=null){ + return model; + } + } + return null; + } + + // TODO make this private, and register it on the model providers. + public IModelLifecycleListener listener = new IModelLifecycleListener() { + + public void handleModelLifecycleEvent(ModelLifecycleEvent event) { + ISaveableModelManager modelManager = (ISaveableModelManager) getSite() + .getService(ISaveableModelManager.class); + ISaveableModel[] models = event.getModels(); + switch (event.getEventType()) { + case ModelLifecycleEvent.POST_OPEN: { + Set oldModels = new HashSet(Arrays.asList(currentModels)); + currentModels = computeModels(); + Set newModels = new HashSet(Arrays.asList(currentModels)); + newModels.removeAll(oldModels); + if (newModels.size() > 0) { + modelManager + .handleModelLifecycleEvent(new ModelLifecycleEvent( + CommonNavigator.this, + ModelLifecycleEvent.POST_OPEN, + (ISaveableModel[]) newModels + .toArray(new ISaveableModel[newModels + .size()]), false)); + } + } + break; + case ModelLifecycleEvent.POST_CLOSE: { + Set oldModels = new HashSet(Arrays.asList(currentModels)); + currentModels = computeModels(); + Set newModels = new HashSet(Arrays.asList(currentModels)); + oldModels.removeAll(newModels); + // TODO this will make the closing of models non-cancelable. + // Ideally, we should react to PRE_CLOSE events and fire + // an appropriate PRE_CLOSE to the model manager + if (newModels.size() > 0) { + modelManager + .handleModelLifecycleEvent(new ModelLifecycleEvent( + CommonNavigator.this, + ModelLifecycleEvent.PRE_CLOSE, + (ISaveableModel[]) oldModels + .toArray(new ISaveableModel[oldModels + .size()]), true)); + modelManager + .handleModelLifecycleEvent(new ModelLifecycleEvent( + CommonNavigator.this, + ModelLifecycleEvent.POST_CLOSE, + (ISaveableModel[]) oldModels + .toArray(new ISaveableModel[oldModels + .size()]), false)); + } + } + break; + case ModelLifecycleEvent.DIRTY_CHANGED: + ISaveableModel[] shownModels = getShownModels(models); + if (shownModels.length > 0) { + modelManager + .handleModelLifecycleEvent(new ModelLifecycleEvent( + CommonNavigator.this, + ModelLifecycleEvent.DIRTY_CHANGED, + shownModels, false)); + } + break; + } + } + }; + + private ISaveableModel[] getShownModels(ISaveableModel[] models) { + Set result = new HashSet(Arrays.asList(currentModels)); + result.retainAll(Arrays.asList(models)); + return (ISaveableModel[]) result.toArray(new ISaveableModel[result.size()]); + } } Index: src/org/eclipse/ui/navigator/ISaveableModelProvider.java =================================================================== RCS file: src/org/eclipse/ui/navigator/ISaveableModelProvider.java diff -N src/org/eclipse/ui/navigator/ISaveableModelProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/navigator/ISaveableModelProvider.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2006 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.ui.navigator; + +import org.eclipse.ui.IModelLifecycleListener; +import org.eclipse.ui.ISaveableModel; + +/** + * @since 3.2 + * + */ +public interface ISaveableModelProvider { + + /** + * @return the models returned by this model provider. + */ + public ISaveableModel[] getModels(); + + /** + * @return the elements representing the given model + */ + public Object[] getElements(ISaveableModel model); + + /** + * @return the model for the given element, or null + */ + public ISaveableModel getModel(Object element); + + /** + * Initializes this model provider with the given listener. The listener + * must be notified about changes to this provider's models. + * + */ + public void init(IModelLifecycleListener listener); + +}