/******************************************************************************* * Copyright (c) 2007 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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 * * Contributor: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.seam.ui.views; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IMemento; import org.eclipse.ui.navigator.ICommonContentExtensionSite; import org.eclipse.ui.navigator.ICommonContentProvider; import org.eclipse.ui.navigator.IExtensionStateModel; import org.jboss.tools.seam.core.IRole; import org.jboss.tools.seam.core.ISeamComponent; import org.jboss.tools.seam.core.ISeamComponentDeclaration; import org.jboss.tools.seam.core.ISeamElement; import org.jboss.tools.seam.core.ISeamJavaComponentDeclaration; import org.jboss.tools.seam.core.ISeamPackage; import org.jboss.tools.seam.core.ISeamProject; import org.jboss.tools.seam.core.ISeamScope; import org.jboss.tools.seam.core.SeamCorePlugin; import org.jboss.tools.seam.core.SeamCoreMessages; import org.jboss.tools.seam.core.event.ISeamProjectChangeListener; import org.jboss.tools.seam.core.event.SeamProjectChangeEvent; import org.jboss.tools.seam.ui.SeamGuiPlugin; /** * Basic type for content providers that add seam components * tree structure to views based on * org.eclipse.ui.navigator.CommonNavigator * Sub-classes need to override methods getChildren(Object) * and getParent(Object) to specify starting points of the * seam components sub-trees. * Content provider for stand-alone view may start from * the workspace root, while content provider contributing * to the standard Project Explorer is better to append * project-specific seam components to that project's node. * * @author Viacheslav Kabanovich */ public abstract class AbstractSeamContentProvider implements ITreeContentProvider, ISeamProjectChangeListener, ICommonContentProvider { protected TreeViewer viewer; IResourceChangeListener listener = null; Set<ISeamProject> processed = new HashSet<ISeamProject>(); private IExtensionStateModel fStateModel; IPropertyChangeListener scopePropertyListener; IPropertyChangeListener layoutPropertyListener; boolean isFlatLayout = true; boolean isScopeLable = false; public AbstractSeamContentProvider() {} public void init(ICommonContentExtensionSite commonContentExtensionSite) { fStateModel = commonContentExtensionSite.getExtensionStateModel(); IMemento memento = commonContentExtensionSite.getMemento(); restoreState(memento); scopePropertyListener = new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { if (ViewConstants.SCOPE_PRESENTATION.equals(event.getProperty())) { if (event.getNewValue() != null) { boolean newValue = ((Boolean) event.getNewValue()).booleanValue(); setIsScopeLable(newValue); } } } }; fStateModel.addPropertyChangeListener(scopePropertyListener); layoutPropertyListener = new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { if (ViewConstants.PACKAGE_STRUCTURE.equals(event.getProperty())) { if (event.getNewValue() != null) { boolean newValue = ((Boolean)event.getNewValue()).booleanValue(); setIsFlatLayout(newValue); } } } }; fStateModel.addPropertyChangeListener(layoutPropertyListener); } void setIsFlatLayout(boolean b) { isFlatLayout = b; } void setIsScopeLable(boolean b) { isScopeLable = b; } public Object[] getElements(Object inputElement) { if(inputElement instanceof IProject) { ISeamProject p = SeamCorePlugin.getSeamProject((IProject)inputElement, false); if (p == null) return new Object[0]; if(!processed.contains(p)) { processed.add(p); p.addSeamProjectListener(this); } return new Object[]{p}; } return getChildren(inputElement); } boolean isNotShowingScopeNodes() { return isScopeLable; // ScopePresentationActionProvider.isScopePresentedAsLabel(); // if(viewer == null) return false; // Boolean b = (Boolean)viewer.getData("scopeAsNode"); // return b != null && b.booleanValue(); } boolean isPackageStructureFlat() { return isFlatLayout; //ScopePresentationActionProvider.isPackageStructureFlat(); } public boolean hasChildren(Object element) { if(element instanceof ISeamComponentDeclaration) return false; if(element instanceof IRole) return false; return true; } public Object[] getChildren(Object parentElement) { if(parentElement instanceof ISeamProject) { ISeamProject project = (ISeamProject)parentElement; if(isNotShowingScopeNodes()) { project.resolve(); if(isPackageStructureFlat()) { return project.getAllPackages().toArray(new Object[0]); } else { return project.getPackages().toArray(new Object[0]); } } return project.getScopes(); } else if(parentElement instanceof ISeamScope) { ((ISeamScope)parentElement).getSeamProject().resolve(); if(isPackageStructureFlat()) { return ((ISeamScope)parentElement).getAllPackages().toArray(new Object[0]); } else { return ((ISeamScope)parentElement).getPackages().toArray(new Object[0]); } // return ((ISeamScope)parentElement).getComponents().toArray(new Object[0]); } else if(parentElement instanceof ISeamPackage) { ISeamPackage p = (ISeamPackage)parentElement; List<Object> children = new ArrayList<Object>(); for (ISeamComponent c : p.getComponents()) { children.add(c); } if(!isPackageStructureFlat()) { for (ISeamPackage pc : p.getPackages().values()) { children.add(pc); } } return children.toArray(new Object[0]); } else if(parentElement instanceof ISeamComponent) { List<Object> children = new ArrayList<Object>(); Set<ISeamComponentDeclaration> ds = ((ISeamComponent)parentElement).getAllDeclarations(); children.addAll(ds); for (ISeamComponentDeclaration d : ds) { if(d instanceof ISeamJavaComponentDeclaration) { Set<IRole> rs = ((ISeamJavaComponentDeclaration)d).getRoles(); children.addAll(rs); } } return children.toArray(new Object[0]); } return new Object[0]; } public Object getParent(Object element) { if(element instanceof IRole) { ISeamElement p = ((IRole)element).getParent(); return p == null ? p : p.getParent(); } else if(element instanceof ISeamElement) { if(element instanceof ISeamComponent) { ISeamComponent c = (ISeamComponent)element; if(isNotShowingScopeNodes()) { return c.getSeamProject().getPackage(c); } else { ISeamScope s = (ISeamScope)c.getParent(); ISeamPackage p = s.getPackage(c); return p == null ? s : p; } } return ((ISeamElement)element).getParent(); } return null; } public void projectChanged(SeamProjectChangeEvent event) { if(viewer != null) { refresh(event.getSource()); } } void refresh(final Object o) { Display.getDefault().asyncExec(new Runnable() { public void run() { if(viewer != null) { viewer.refresh(getTreeObject(o)); } } }); } void refresh() { Display.getDefault().asyncExec(new Runnable() { public void run() { if(viewer != null) { viewer.refresh(); } } }); } protected Object getTreeObject(Object source) { return source; } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { this.viewer = (TreeViewer)viewer; if(listener == null) { listener = new ResourceChangeListener(); ResourcesPlugin.getWorkspace().addResourceChangeListener(listener); } } class ResourceChangeListener implements IResourceChangeListener { ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(); public void resourceChanged(IResourceChangeEvent event) { try { if (event.getDelta() == null) { if(event.getType() == IResourceChangeEvent.PRE_DELETE || event.getType() == IResourceChangeEvent.PRE_CLOSE) { handlePreDelete(event.getResource()); } } else { event.getDelta().accept(visitor); } } catch (CoreException e) { SeamCorePlugin.getPluginLog().logError(e); } } } protected void handlePreDelete(IResource resource) { } protected void handleProjectAdded(IProject project) { } protected void handleProjectInfoChanged(IProject project) { refresh(project); } class ResourceDeltaVisitor implements IResourceDeltaVisitor { public boolean visit(IResourceDelta delta) throws CoreException { int kind = delta.getKind(); IResource r = delta.getResource(); if(kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) { if(r instanceof IProject) { if(kind == IResourceDelta.ADDED) { handleProjectAdded((IProject)r); } //Do nothing for IResourceDelta.REMOVED, PRE_DELETE event already was sent. } } else if(kind == IResourceDelta.CHANGED) { IResourceDelta[] cs = delta.getAffectedChildren(); if(cs != null) for (int i = 0; i < cs.length; i++) { IResource c = cs[i].getResource(); if(c instanceof IFile && c.getName().endsWith(".project")) { //$NON-NLS-1$ handleProjectInfoChanged(c.getProject()); } } } if(r instanceof IProject) return false; return true; } } public void restoreState(IMemento memento) { } public void saveState(IMemento memento) { } public void dispose() { fStateModel.removePropertyChangeListener(layoutPropertyListener); fStateModel.removePropertyChangeListener(scopePropertyListener); if(listener != null) { ResourcesPlugin.getWorkspace().removeResourceChangeListener(listener); listener = null; } viewer = null; if(processed != null) { for (ISeamProject p : processed) { p.removeSeamProjectListener(this); } processed.clear(); } fStateModel.removePropertyChangeListener(layoutPropertyListener); fStateModel.removePropertyChangeListener(scopePropertyListener); } }