/** * Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ package org.python.pydev.navigator; import static org.python.pydev.navigator.PythonModelProvider.DEBUG; import java.util.ArrayList; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ITreeSelection; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.ui.IMemento; import org.eclipse.ui.IWorkingSet; import org.python.pydev.core.log.Log; import org.python.pydev.navigator.elements.IWrappedResource; import org.python.pydev.navigator.ui.PydevPackageExplorer.PydevCommonViewer; /** * This class saves and restores the expanded and selected items in the tree. */ public class PyPackageStateSaver { private PythonModelProvider provider; private Viewer viewer; private IMemento memento; public PyPackageStateSaver(PythonModelProvider provider, Viewer viewer, IMemento memento) { this.provider = provider; this.viewer = viewer; this.memento = memento; } public void restoreState() { try { if (!(viewer instanceof PydevCommonViewer) || memento == null) { //we have to check that because we can be asked to restore things in the ProjectExplorer too, and not //only in the pydev package explorer -- and in this case, the method: getTreePathFromItem(Item item) is //not be overridden and can cause the method to fail. if (DEBUG) { System.out.println("Memento == null:" + memento == null); } return; } PydevCommonViewer treeViewer = (PydevCommonViewer) viewer; //we have to restore it only at the 'right' time... see https://bugs.eclipse.org/bugs/show_bug.cgi?id=195184 for more details if (!treeViewer.availableToRestoreMemento) { if (DEBUG) { System.out.println("Not available for restore"); } return; } if (DEBUG) { System.out.println("Restoring"); } IMemento[] expanded = memento.getChildren("expanded"); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); for (IMemento m : expanded) { Object resource = getResourceFromPath(root, m); if (resource != null) { if (DEBUG) { System.out.println("Expanding:" + resource); } //it has to be done level by level because the children may be created //for each expand (so, we 1st must expand the source folder in order to //get the correct folders beneath it). treeViewer.expandToLevel(resource, 1); } } ArrayList<TreePath> paths = new ArrayList<TreePath>(); IMemento[] selected = memento.getChildren("selected"); for (IMemento m : selected) { Object resource = getResourceFromPath(root, m); if (resource != null) { treeViewer.expandToLevel(resource, 1); if (DEBUG) { System.out.println("Selecting:" + resource); } paths.add(new TreePath(getCompletPath(resource).toArray())); } } treeViewer.setSelection(new TreeSelection(paths.toArray(new TreePath[0])), true); } catch (Exception e) { Log.log(e); } } /** * This method will get the complete path in the tree for a resource (or wrapped resource) */ private ArrayList<Object> getCompletPath(Object resource) { int max = 100; // cannot have more than 100 levels... ok? (this is just a 'safeguard') int i = 0; ArrayList<Object> ret = new ArrayList<Object>(); ret.add(0, resource); while (true) { i++; if (i > max) { Log.log("Could not get the structure for: " + resource); return new ArrayList<Object>();//something strange happened... } else if (resource instanceof IProject || resource instanceof IWorkspaceRoot || resource instanceof IWorkingSet) { break; } else if (resource instanceof IWrappedResource) { IWrappedResource w = (IWrappedResource) resource; resource = w.getParentElement(); if (resource == null) { break; } ret.add(0, resource); } else if (resource instanceof IResource) { IResource r = (IResource) resource; resource = r.getParent(); if (resource == null) { break; } ret.add(0, resource); } } return ret; } private Object getResourceFromPath(IWorkspaceRoot root, IMemento m) { IPath path = Path.fromPortableString(m.getID()); IResource resource = root.getFileForLocation(path); if (resource == null || !resource.exists()) { resource = root.getContainerForLocation(path); } if (resource != null && resource.exists()) { return provider.getResourceInPythonModel(resource); } return null; } /** * This is the function that is responsible for saving the paths in the tree. */ public void saveState() { try { if (!(viewer instanceof PydevCommonViewer)) { //we have to check that because we can be asked to restore things in the ProjectExplorer too, and not //only in the pydev package explorer -- and in this case, the method: getTreePathFromItem(Item item) is //not be overridden and can cause the method to fail. return; } if (DEBUG) { System.out.println("saveState"); } PydevCommonViewer treeViewer = (PydevCommonViewer) viewer; TreePath[] expandedTreePaths = treeViewer.getExpandedTreePaths(); for (TreePath path : expandedTreePaths) { if (DEBUG) { System.out.println("saveState expanded:" + path); } save(path, "expanded"); } ISelection selection = viewer.getSelection(); if (selection instanceof ITreeSelection) { ITreeSelection treeSelection = (ITreeSelection) selection; TreePath[] paths = treeSelection.getPaths(); for (TreePath path : paths) { if (DEBUG) { System.out.println("saveState selected:" + path); } save(path, "selected"); } } } catch (Exception e) { Log.log(e); } } /** * Saves some selection in the memento object. */ private void save(TreePath treePath, String type) { if (treePath != null) { Object object = treePath.getLastSegment(); if (object instanceof IAdaptable) { IAdaptable adaptable = (IAdaptable) object; IResource resource = (IResource) adaptable.getAdapter(IResource.class); if (resource != null) { IPath path = resource.getLocation(); if (path != null) { memento.createChild(type, path.toPortableString()); } } } } } }