// Copyright (c) 2006-2008 by Leif Frenzel - see http://leiffrenzel.de
// This code is made available under the terms of the Eclipse Public License,
// version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
package net.sf.eclipsefp.haskell.ui.internal.views.projectexplorer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.sf.eclipsefp.haskell.buildwrapper.BWFacade;
import net.sf.eclipsefp.haskell.buildwrapper.BuildWrapperPlugin;
import net.sf.eclipsefp.haskell.buildwrapper.types.OutlineDef;
import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescription;
import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionLoader;
import net.sf.eclipsefp.haskell.core.cabalmodel.PackageDescriptionStanza;
import net.sf.eclipsefp.haskell.core.preferences.ICorePreferenceNames;
import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin;
import net.sf.eclipsefp.haskell.ui.internal.views.common.ITreeElement;
import net.sf.eclipsefp.haskell.ui.internal.views.projectexplorer.model.GHCSystemLibrary;
import net.sf.eclipsefp.haskell.util.FileUtil;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.navigator.ICommonContentExtensionSite;
import org.eclipse.ui.navigator.ICommonContentProvider;
/**
* <p>
* content provider which is declared in <code>plugin.xml</code> for the project
* explorer view.
* </p>
*
* @author Leif Frenzel
*/
public class HaskellResourceExtensionCP implements ICommonContentProvider {
// interface methods of ITreeContentProvider
// //////////////////////////////////////////
@Override
public Object[] getChildren( final Object parentElement ) {
final List<Object> result = new ArrayList<>();
try {
if( parentElement instanceof IProject
&& ResourceUtil.hasHaskellNature( ( IProject )parentElement ) ){
IProject p = ( IProject )parentElement;
result.add( new GHCSystemLibrary( p ));
IFile f = BuildWrapperPlugin.getCabalFile( p );
if (f != null && f.exists()) {
result.add( f );
}
Set<IContainer> srcs=new HashSet<>(ResourceUtil.getSourceFolders( p ));
srcs.remove( parentElement ); // may happen if . is a source folder
result.addAll(srcs);
// add all remaining members so that they appear after the haskell content in view
for (IResource r:p.members()){
if (!r.equals( f ) && !srcs.contains( r )){
result.add(r);
}
}
// addProjectExecutable( ( IProject )parentElement, result );
} else if( parentElement instanceof IFile ) {
final IFile f = ( IFile )parentElement;
// if we have a Haskell source file, we show the same content as outline
// underneath
if( FileUtil.hasHaskellExtension( f ) && ResourceUtil.isInHaskellProject( f )) {
BWFacade si = BuildWrapperPlugin.getFacade( f.getProject() );//ScionPlugin.getScionInstance( f );
if (si != null) {
List<OutlineDef> outlineDefs = si.outline( f,null ).getOutlineDefs();
//OutlineCP cp = new OutlineCP();
//cp.inputChanged( null, null, outlineDefs );
for( OutlineDef def : outlineDefs ) {
//if( def.getParentID() == null ) {
result.add( new ProjectExplorerOutlineDef( f, def ) );
//}
}
}
}
// if we have a Haskell source file, we show the same content as outline
// underneath
else if( FileUtil.hasCabalExtension( f ) && ResourceUtil.isInHaskellProject( f )) {
PackageDescription descr = PackageDescriptionLoader.load( f );
PackageDescriptionStanza lib = descr.getLibraryStanza();
if (lib != null) {
result.add( new ProjectExplorerStanza( f,descr.getLibraryStanza() ));
}
if (descr.getExecutableStanzas().size() > 0) {
result.add( new CabalFolder(f, CabalFolderType.EXECUTABLE ));
}
if (descr.getTestSuiteStanzas().size() > 0) {
result.add( new CabalFolder(f, CabalFolderType.TEST_SUITE ));
}
if (descr.getBenchmarkStanzas().size() > 0) {
result.add( new CabalFolder(f, CabalFolderType.BENCHMARK ));
}
}
} else if (parentElement instanceof CabalFolder) {
CabalFolder folder = ( CabalFolder )parentElement;
result.addAll( folder.getStanzas() );
}else if( parentElement instanceof ITreeElement ) {
ITreeElement treeElement = ( ITreeElement )parentElement;
result.addAll( treeElement.getChildren() );
// outline results are wrapped in a structure keeping the tree and the file
} else if( parentElement instanceof ProjectExplorerOutlineDef ) {
ProjectExplorerOutlineDef outline = ( ProjectExplorerOutlineDef )parentElement;
result.addAll( outline.getChildren() );
}
} catch( final CoreException cex ) {
HaskellUIPlugin.log( cex );
}
return result.toArray();
}
@Override
public Object getParent( final Object element ) {
Object result = null;
if( element instanceof ITreeElement ) {
result = ( ( ITreeElement )element ).getParent();
}
return result;
}
@Override
public boolean hasChildren( final Object element ) {
if( element instanceof IFile ) {
IFile f = ( IFile )element;
if( FileUtil.hasHaskellExtension( f ) || FileUtil.hasCabalExtension( f ) ) {
return true;
}
return false;
} else if ( element instanceof CabalFolder ) {
return true;
} else if (element instanceof GHCSystemLibrary){ // for performance, we know we always have children
return true;
}
Object[] children = getChildren( element );
return children == null ? false : children.length > 0;
}
@Override
public Object[] getElements( final Object inputElement ) {
return new Object[ 0 ];
}
@Override
public void dispose() {
// unused
}
@Override
public void inputChanged( final Viewer viewer, final Object oldInput,
final Object newInput ) {
// unused
}
// interface methods of ICommonContentProvider
// ////////////////////////////////////////////
// TODO lf note to self: config -> navigator service -> can be used to
// get state information from the View
@Override
public void init( final ICommonContentExtensionSite config ) {
IEclipsePreferences node = InstanceScope.INSTANCE.getNode( HaskellCorePlugin
.getPluginId() );
node.addPreferenceChangeListener( new IPreferenceChangeListener() {
@Override
public void preferenceChange( final PreferenceChangeEvent event ) {
String prop = event.getKey();
if( ICorePreferenceNames.HS_IMPLEMENTATIONS.equals( prop )
|| ICorePreferenceNames.SELECTED_HS_IMPLEMENTATION.equals( prop ) ) {
config.getService().update();
}
}
} );
}
@Override
public void restoreState( final IMemento memento ) {
// unused
}
@Override
public void saveState( final IMemento memento ) {
// unused
}
// helping functions
// //////////////////
/* private void addProjectExecutable( final IProject project,
final List<Object> list ) {
try {
IFile[] executables = ResourceUtil.getProjectExecutables( project );
list.addAll( Arrays.asList( executables ) );
} catch( CoreException ex ) {
String msg = "Problem determining project executable for "
+ project.getName();
HaskellUIPlugin.log( msg, ex );
}
}*/
}