You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2009/07/13 15:26:06 UTC

svn commit: r793581 [21/23] - in /felix/trunk/sigil: ./ bld-ivy/ bld-ivy/example/ bld-ivy/example/dependence/ bld-ivy/example/dependence/dependee/ bld-ivy/example/dependence/dependee/src/ bld-ivy/example/dependence/dependee/src/standalone/ bld-ivy/exam...

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IAccumulator.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IAccumulator.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IAccumulator.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IAccumulator.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.util;
+
+import java.util.Collection;
+
+public interface IAccumulator<E> {
+	public void addElement(E element);
+	public void addElements(Collection<? extends E> elements);
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IExportToImportConverter.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IExportToImportConverter.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IExportToImportConverter.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IExportToImportConverter.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.util;
+
+public interface IExportToImportConverter<E,I> {
+	I convert(E exportElement);
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IFilter.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IFilter.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IFilter.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IFilter.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.util;
+
+public interface IFilter<T> {
+	boolean select(T element);
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IValidationListener.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IValidationListener.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IValidationListener.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/IValidationListener.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.util;
+
+public interface IValidationListener {
+
+	void validationMessage(String message, int level);
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ModelLabelProvider.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ModelLabelProvider.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ModelLabelProvider.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ModelLabelProvider.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.util;
+
+import java.util.Set;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.osgi.IBundleModelElement;
+import org.cauldron.sigil.model.osgi.IPackageExport;
+import org.cauldron.sigil.model.osgi.IPackageImport;
+import org.cauldron.sigil.model.osgi.IRequiredBundle;
+import org.cauldron.sigil.model.repository.IRepositoryModel;
+import org.cauldron.sigil.repository.IBundleRepository;
+import org.cauldron.sigil.ui.SigilUI;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.osgi.framework.Version;
+
+public class ModelLabelProvider extends LabelProvider {
+	
+	private volatile Set<? extends IModelElement> unresolvedElements = null;
+	
+	public Image getImage(Object element) {
+		boolean unresolved = (unresolvedElements == null) ? false : unresolvedElements.contains(element);
+		
+		if ( element instanceof ISigilBundle || element instanceof IBundleModelElement) {
+			return findBundle();
+		} else if(element instanceof IRequiredBundle) {
+			boolean optional = ((IRequiredBundle) element).isOptional();
+			return findRequiredBundle(optional, unresolved);
+		}
+		else if ( element instanceof IPackageImport ) {
+			boolean optional = ((IPackageImport) element).isOptional();
+			return findPackageImport(optional, unresolved);
+		}
+		else if ( element instanceof IPackageExport ) {
+			return findPackageExport();
+		}
+		else if ( element instanceof IPackageFragmentRoot ) {
+			IPackageFragmentRoot root = (IPackageFragmentRoot) element;
+			try {
+				if ( root.getKind() == IPackageFragmentRoot.K_SOURCE ) {
+					return findPackage();
+				}
+				else {
+					return findBundle();
+				}
+			} catch (JavaModelException e) {
+				SigilCore.error( "Failed to inspect package fragment root", e );
+			}
+		}
+		else if ( element instanceof IClasspathEntry ) {
+			return findPackage();
+		}
+		if ( element instanceof IBundleRepository ) {
+			IBundleRepository rep = (IBundleRepository) element;
+			IRepositoryModel config = SigilCore.getRepositoryConfiguration().findRepository(rep.getId());
+			return config.getType().getIcon();
+		}
+	
+		return null;
+	}
+
+	public String getText(Object element) {
+		if ( element instanceof ISigilBundle ) {
+			ISigilBundle bundle = (ISigilBundle) element;
+			return bundle.getBundleInfo().getSymbolicName() + " " + bundle.getBundleInfo().getVersion(); 
+		}
+		if ( element instanceof IBundleModelElement ) {
+			IBundleModelElement bundle = (IBundleModelElement) element;
+			return bundle.getSymbolicName();
+		}
+		if ( element instanceof IRequiredBundle ) {
+			IRequiredBundle req = (IRequiredBundle) element;
+			return req.getSymbolicName() + " " + req.getVersions();
+		}
+		
+		if ( element instanceof IPackageImport ) {
+			IPackageImport req = (IPackageImport) element;
+			return req.getPackageName() + " " + req.getVersions();
+		}
+		
+		if ( element instanceof IPackageExport ) {
+			IPackageExport pe = (IPackageExport) element;
+			Version rawVersion = pe.getRawVersion();
+			return rawVersion != null ? pe.getPackageName() + " " + rawVersion : pe.getPackageName();
+		}
+		
+		if ( element instanceof IResource ) {
+			IResource resource = (IResource) element;
+			return resource.getName();
+		}
+		
+		if ( element instanceof IPackageFragment )  {
+			IPackageFragment f = (IPackageFragment) element;
+			return f.getElementName();
+		}
+		
+		if ( element instanceof IPackageFragmentRoot ) {
+			IPackageFragmentRoot f = (IPackageFragmentRoot) element;
+			try {
+				return f.getUnderlyingResource().getName();
+			} catch (JavaModelException e) {
+				return "unknown";
+			}
+		}
+		
+		if ( element instanceof IClasspathEntry ) {
+			IClasspathEntry cp = (IClasspathEntry) element;
+			return cp.getPath().toString();
+		}
+		
+		if ( element instanceof IBundleRepository ) {
+			IBundleRepository rep = (IBundleRepository) element;
+			IRepositoryModel config = SigilCore.getRepositoryConfiguration().findRepository(rep.getId());
+			return config.getName();
+		}
+		
+		return element.toString();
+	}
+
+	private Image findPackage() {
+		return cacheImage( "icons/package_obj.png" ); 
+	}
+
+	private Image findPackageImport(boolean optional, boolean unresolved) {
+		String path;
+		if(optional) {
+			path = unresolved ? "icons/package_obj_import_opt_error.png" : "icons/package_obj_import_opt.png";
+		} else {
+			path = unresolved ? "icons/package_obj_import_error.png" : "icons/package_obj_import.png";
+		}
+		return cacheImage(path);
+	}
+	
+	private Image findPackageExport() {
+		return cacheImage("icons/package_obj_export.png");
+	}
+	
+	private Image findBundle() {
+		return cacheImage("icons/jar_obj.png");
+	}
+	
+	private Image findRequiredBundle(boolean optional, boolean unresolved) {
+		String path;
+		if(optional) {
+			path = unresolved ? "icons/required_bundle_opt_error.png" : "icons/required_bundle_opt.png";
+		} else {
+			path = unresolved ? "icons/required_bundle_error.png" : "icons/jar_obj.png";
+		}
+		return cacheImage(path);
+	}
+	
+	private static Image cacheImage(String path) {
+		return SigilUI.cacheImage(path, ModelLabelProvider.class.getClassLoader());
+	}
+
+	public void setUnresolvedElements(Set<? extends IModelElement> elements) {
+		this.unresolvedElements = elements;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/PackageFilter.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/PackageFilter.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/PackageFilter.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/PackageFilter.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.util;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.cauldron.sigil.model.osgi.IPackageExport;
+import org.cauldron.sigil.model.osgi.IPackageImport;
+
+public class PackageFilter implements IFilter<IPackageImport> {
+	
+	private Set<String> names = new HashSet<String>();
+	
+	public PackageFilter(String[] packageNames) {
+		for (String name : packageNames) {
+			names.add(name);
+		}
+	}
+	
+	public PackageFilter(IPackageExport[] packages) {
+		for (IPackageExport packageExport : packages) {
+			names.add(packageExport.getPackageName());
+		}
+	}
+
+	public boolean select(IPackageImport element) {
+		return !names.contains(element.getPackageName());
+	}
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ProjectUtils.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ProjectUtils.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ProjectUtils.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ProjectUtils.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.util;
+
+import java.util.concurrent.Callable;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.ui.SigilUI;
+import org.cauldron.sigil.ui.preferences.OptionalPrompt;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+
+public class ProjectUtils {
+	public static boolean runTaskWithRebuildCheck(final Runnable task, Shell shell) {
+		return runTaskWithRebuildCheck( new Callable<Boolean>() {
+			public Boolean call() throws Exception {
+				task.run();
+				return true;
+			}
+		}, shell);
+	}
+	
+	public static boolean runTaskWithRebuildCheck(Callable<Boolean> callable,
+			Shell shell) {
+		int result = checkRebuild(shell);
+		if ( result == IDialogConstants.CANCEL_ID ) {
+			return false;
+		}
+		else {
+			try {
+				if ( Boolean.TRUE == callable.call() ) {
+					if ( result == IDialogConstants.YES_ID ) {
+						SigilUI.runWorkspaceOperation( new WorkspaceModifyOperation() {
+							@Override
+							protected void execute(IProgressMonitor monitor) {
+								SigilCore.rebuildAllBundleDependencies(monitor);
+							}
+						}, shell );
+					}
+					return true;
+				}
+				else {
+					return false;
+				}
+			} catch (Exception e) {
+				SigilCore.error( "Failed to run caller", e);
+				return false;
+			}
+		}
+	}
+	
+	private static int checkRebuild(Shell shell) {
+		if ( SigilCore.getRoot().getProjects().isEmpty() ) {
+			return IDialogConstants.NO_ID;
+		}
+		else {
+			return OptionalPrompt.optionallyPromptWithCancel(SigilCore.getDefault().getPreferenceStore(), SigilCore.PREFERENCES_REBUILD_PROJECTS, "Rebuild", "Do you wish to rebuild all Sigil projects", shell );
+		}
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ResourceReviewDialog.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ResourceReviewDialog.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ResourceReviewDialog.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ResourceReviewDialog.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.util;
+
+import java.util.Collection;
+
+import org.cauldron.sigil.model.IModelElement;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+
+public class ResourceReviewDialog<T extends IModelElement> extends TitleAreaDialog {
+
+	private String title;	
+	private Collection<T> resources;
+	
+	private TableViewer viewer;
+
+	public ResourceReviewDialog(Shell parentShell, String title, Collection<T> resources) {
+		super(parentShell);
+		this.title = title;
+		this.resources = resources;
+	}
+
+	public Collection<T> getResources() {
+		return resources;
+	}
+
+	@Override
+	protected Control createDialogArea(Composite parent) {
+		setTitle(title);
+
+		// Create controls
+		Composite container = (Composite) super.createDialogArea(parent);
+		Composite composite = new Composite(container, SWT.NONE);		
+		Table table = new Table(composite, SWT.BORDER | SWT.VIRTUAL);
+		
+		final Button remove = new Button(composite, SWT.PUSH);
+		remove.setText("Remove");
+		remove.setEnabled(false);
+		
+		remove.addSelectionListener( new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				handleRemove();
+			}
+		} );
+		
+		viewer = new TableViewer(table);
+		viewer.setContentProvider( new DefaultTableProvider() {
+			public Object[] getElements(Object inputElement) {
+				return toArray(inputElement);
+			}
+		});
+		
+		viewer.setInput( resources );
+		viewer.addSelectionChangedListener( new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				remove.setEnabled(!event.getSelection().isEmpty());
+			}
+		});
+		
+		// layout
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		composite.setLayout(new GridLayout(2, false));
+		GridData tableLayoutData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 4);
+		tableLayoutData.heightHint = 150;
+		table.setLayoutData(tableLayoutData);
+		
+		return container;
+	}
+
+	private void handleRemove() {
+		ISelection s = viewer.getSelection();
+		if ( !s.isEmpty() ) {
+			IStructuredSelection sel = (IStructuredSelection) s;
+			resources.remove( sel.getFirstElement() );
+			viewer.refresh();
+		}
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ResourcesDialogHelper.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ResourcesDialogHelper.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ResourcesDialogHelper.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/ResourcesDialogHelper.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.IModelWalker;
+import org.cauldron.sigil.model.osgi.IBundleModelElement;
+import org.cauldron.sigil.model.osgi.IPackageExport;
+import org.cauldron.sigil.model.osgi.IPackageImport;
+import org.cauldron.sigil.model.osgi.IPackageModelElement;
+import org.cauldron.sigil.model.osgi.IRequiredBundle;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.model.util.JavaHelper;
+import org.cauldron.sigil.ui.editors.project.IElementDescriptor;
+import org.cauldron.sigil.ui.editors.project.NewPackageExportDialog;
+import org.cauldron.sigil.ui.editors.project.NewResourceSelectionDialog;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.progress.IJobRunnable;
+
+public class ResourcesDialogHelper {
+	
+	static final int UPDATE_BATCH_SIZE = 100;
+
+	public static BackgroundLoadingSelectionDialog<String> createClassSelectDialog(Shell shell, String title, final ISigilProjectModel project, String selected, final String ifaceOrParentClass) {
+		final BackgroundLoadingSelectionDialog<String> dialog = new BackgroundLoadingSelectionDialog<String>(shell, "Class Name", true);
+		
+		IJobRunnable job = new IJobRunnable() {
+			public IStatus run(IProgressMonitor monitor) {
+				try {
+					for ( IJavaElement e : JavaHelper.findTypes(project.getJavaModel(), IJavaElement.PACKAGE_FRAGMENT_ROOT ) ) {
+						IPackageFragmentRoot root = (IPackageFragmentRoot) e;
+						if ( project.isInBundleClasspath(root)) {
+							for ( IJavaElement e1 : JavaHelper.findTypes(root, IJavaElement.COMPILATION_UNIT, IJavaElement.CLASS_FILE ) ) {
+								ITypeRoot typeRoot = (ITypeRoot) e1;
+								IType type = (IType) JavaHelper.findType(typeRoot, IJavaElement.TYPE);
+								if ( JavaHelper.isAssignableTo( ifaceOrParentClass, type ) ) {
+									dialog.addElement(type.getFullyQualifiedName());					
+								}							
+							}
+						}
+					}
+					
+					return Status.OK_STATUS;
+				} catch (JavaModelException e) {
+					return e.getStatus();
+				}				
+			}
+
+		};
+		
+		dialog.addBackgroundJob("Scanning for activators in project", job);
+
+		return dialog;
+	}
+	
+	public static NewResourceSelectionDialog<IPackageExport> createImportDialog(
+			Shell shell, 
+			String title, 
+			ISigilProjectModel sigil, 
+			final IPackageImport selected, 
+			final Collection<IPackageImport> existing) {
+		final Set<String> existingNames = new HashSet<String>();
+		
+		for (IPackageImport existingImport : existing) {
+			existingNames.add(existingImport.getPackageName());
+		}
+		
+		final NewResourceSelectionDialog<IPackageExport> dialog = new NewResourceSelectionDialog<IPackageExport>(shell, "Package Name:", false);
+		
+		dialog.setFilter( new IFilter<IPackageModelElement>() {
+			public boolean select(IPackageModelElement element) {
+				return !existingNames.contains(element.getPackageName());
+			}
+		} );
+		
+		dialog.setComparator(new Comparator<IPackageExport>() {
+			public int compare(IPackageExport o1, IPackageExport o2) {
+				return o1.compareTo(o2);
+			}
+		});
+		
+		dialog.setDescriptor(new IElementDescriptor<IPackageExport>() {
+			public String getLabel(IPackageExport element) {
+				return getName(element) + " (" + element.getVersion().toString() + ")";
+			}
+
+			public String getName(IPackageExport element) {
+				return element.getPackageName();
+			}
+		});
+		
+		dialog.setLabelProvider(new WrappedContentProposalLabelProvider<IPackageExport>(dialog.getDescriptor()));
+		
+		if(selected != null) {
+			dialog.setSelectedName(selected.getPackageName());
+			dialog.setVersions(selected.getVersions());
+			dialog.setOptional(selected.isOptional());
+		}
+
+		IJobRunnable job = new ExportedPackageFinder(sigil, dialog);
+		dialog.addBackgroundJob("Scanning for exports in workspace", job);
+		
+		return dialog;
+	}
+	
+	public static NewPackageExportDialog createNewExportDialog(Shell shell, String title, final IPackageExport selected, final ISigilProjectModel project, boolean multiSelect) {
+		IFilter<IJavaElement> selectFilter = new IFilter<IJavaElement>() {
+			public boolean select(IJavaElement e) {
+				if ( selected != null && e.getElementName().equals( selected.getPackageName() ) ) {
+					return true;
+				}
+				
+				if ( e.getElementName().trim().length() > 0 && isLocal( e ) ) {
+					for ( IPackageExport p : project.getBundle().getBundleInfo().getExports() ) {
+						if ( p.getPackageName().equals( e.getElementName() ) ) {
+							return false;
+						}
+					}
+					
+					return true;
+				}
+				else {
+					return false;
+				}
+			}
+			
+			private boolean isLocal(IJavaElement java) {
+				try {
+					switch ( java.getElementType() ) {
+					case IJavaElement.PACKAGE_FRAGMENT:
+						IPackageFragment fragment= (IPackageFragment) java;
+						return fragment.containsJavaResources();
+					default:
+						throw new IllegalStateException( "Unexpected resource type " + java );
+					}
+				}
+				catch (JavaModelException e) {
+					SigilCore.error( "Failed to inspect java element ", e );
+					return false;
+				}
+			}
+			
+		};
+		
+		final NewPackageExportDialog dialog = new NewPackageExportDialog(shell, multiSelect);
+		dialog.setFilter(selectFilter);
+		
+		dialog.setProjectVersion(project.getVersion());
+		if ( selected != null ) {
+			dialog.setSelectedName(selected.getPackageName());
+			dialog.setVersion(selected.getRawVersion());
+		}
+		
+		IJobRunnable job = new IJobRunnable() {
+			public IStatus run(IProgressMonitor monitor) {
+				try {
+					ArrayList<IPackageFragment> list = new ArrayList<IPackageFragment>(UPDATE_BATCH_SIZE);
+					for ( IJavaElement e : JavaHelper.findTypes(project.getJavaModel(), IJavaElement.PACKAGE_FRAGMENT_ROOT) ) {
+						IPackageFragmentRoot root = (IPackageFragmentRoot) e;
+						if ( project.isInBundleClasspath(root) ) {
+							for ( IJavaElement e1 : JavaHelper.findTypes(root, IJavaElement.PACKAGE_FRAGMENT) ) {
+								list.add((IPackageFragment) e1);
+								if(list.size() >= UPDATE_BATCH_SIZE) {
+									dialog.addElements(list);
+									list.clear();
+								}
+							}
+						}
+					}
+					if(!list.isEmpty()) {
+						dialog.addElements(list);
+					}
+					return Status.OK_STATUS;
+				} catch (JavaModelException e) {
+					return e.getStatus();
+				}
+			}
+		};
+		
+		dialog.addBackgroundJob("Scanning for packages in project", job);
+		
+		return dialog;
+	}
+	
+	public static NewResourceSelectionDialog<IBundleModelElement> createRequiredBundleDialog(Shell shell, String title, final ISigilProjectModel sigil, final IRequiredBundle selected, final Collection<IRequiredBundle> existing) {
+		final Set<String> existingNames = new HashSet<String>();
+		for(IRequiredBundle existingBundle : existing) {
+			existingNames.add(existingBundle.getSymbolicName());
+		}
+		
+		final NewResourceSelectionDialog<IBundleModelElement> dialog = new NewResourceSelectionDialog<IBundleModelElement>(shell, "Bundle:", false);
+		
+		dialog.setDescriptor(new IElementDescriptor<IBundleModelElement>() {
+			public String getLabel(IBundleModelElement element) {
+				return getName(element) + " (" + element.getVersion() + ")";
+			}
+			public String getName(IBundleModelElement element) {
+				return element.getSymbolicName();
+			}
+		});
+		
+		dialog.setLabelProvider(new WrappedContentProposalLabelProvider<IBundleModelElement>(dialog.getDescriptor()));
+		
+		dialog.setFilter(new IFilter<IBundleModelElement>() {
+			public boolean select(IBundleModelElement element) {
+				return !existingNames.contains(element.getSymbolicName());
+			}
+		});
+		
+		dialog.setComparator(new Comparator<IBundleModelElement>() {
+			public int compare(IBundleModelElement o1, IBundleModelElement o2) {
+				return o1.getSymbolicName().compareTo(o2.getSymbolicName());
+			}
+		});
+		
+		if(selected != null) {
+			dialog.setSelectedName(selected.getSymbolicName());
+			dialog.setVersions(selected.getVersions());
+			dialog.setOptional(selected.isOptional());
+		}
+				
+		IJobRunnable job = new IJobRunnable() {
+			public IStatus run(final IProgressMonitor monitor) {
+				final List<IBundleModelElement> bundles = new ArrayList<IBundleModelElement>(UPDATE_BATCH_SIZE);
+				final IModelWalker walker = new IModelWalker() {
+					//int count = 0;
+					public boolean visit(IModelElement element) {
+						if ( element instanceof  IBundleModelElement) {
+							IBundleModelElement b = (IBundleModelElement) element;
+							bundles.add(b);
+
+							if(bundles.size() >= UPDATE_BATCH_SIZE) {
+								dialog.addElements(bundles);
+								bundles.clear();
+							}
+							// no need to recurse further.
+							return false;
+						}
+						return !monitor.isCanceled();
+					}
+				};
+				SigilCore.getRepositoryManager(sigil).visit(walker);
+				if(!bundles.isEmpty()) {
+					dialog.addElements(bundles);
+				}
+				return Status.OK_STATUS;
+			}
+		};
+		
+		dialog.addBackgroundJob("Scanning for bundles in workspace", job);
+		
+		return dialog;
+	}
+}
+
+

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/SingletonSelection.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/SingletonSelection.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/SingletonSelection.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/SingletonSelection.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+@SuppressWarnings("unchecked")
+public class SingletonSelection implements IStructuredSelection {
+
+	private final Object singleton;
+	
+	public SingletonSelection(Object singleton) {
+		this.singleton = singleton;
+	}
+
+	public Object getFirstElement() {
+		return singleton;
+	}
+
+	public Iterator iterator() {
+		return Collections.singleton(singleton).iterator();
+	}
+
+	public int size() {
+		return 1;
+	}
+
+	public Object[] toArray() {
+		return new Object[] { singleton };
+	}
+
+	public List toList() {
+		ArrayList list = new ArrayList(1);
+		list.add( singleton );
+		return list;
+	}
+
+	public boolean isEmpty() {
+		return false;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/WrappedContentProposalLabelProvider.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/WrappedContentProposalLabelProvider.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/WrappedContentProposalLabelProvider.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/util/WrappedContentProposalLabelProvider.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.util;
+
+import org.cauldron.sigil.ui.editors.project.IElementDescriptor;
+import org.cauldron.sigil.ui.editors.project.WrappedContentProposal;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+public class WrappedContentProposalLabelProvider<E> extends LabelProvider {
+	
+	private final IElementDescriptor<? super E> descriptor;
+	private final ModelLabelProvider projectLabelProvider;
+
+	public WrappedContentProposalLabelProvider(IElementDescriptor<? super E> descriptor) {
+		this.descriptor = descriptor;
+		projectLabelProvider = new ModelLabelProvider();
+	}
+	
+	@SuppressWarnings("unchecked")
+	private E adapt(Object element) {
+		E result;
+		if(element instanceof WrappedContentProposal<?>) {
+			WrappedContentProposal<?> proposal = (WrappedContentProposal<?>) element;
+			result = (E) proposal.getElement();
+		} else {
+			result = (E) element;
+		}
+		return result;
+	}
+	
+	@Override
+	public Image getImage(Object element) {
+		Object value = adapt(element);
+		return projectLabelProvider.getImage(value);
+	}
+	
+	@Override
+	public String getText(Object element) {
+		return descriptor.getLabel(adapt(element));
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/ModelElementComparator.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/ModelElementComparator.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/ModelElementComparator.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/ModelElementComparator.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.views;
+
+import org.cauldron.sigil.model.osgi.IPackageExport;
+import org.cauldron.sigil.model.osgi.IPackageImport;
+import org.cauldron.sigil.model.osgi.IRequiredBundle;
+import org.eclipse.jface.viewers.ContentViewer;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+
+public class ModelElementComparator extends ViewerComparator {
+	private static final int EXPORT_GROUP = 0;
+	private static final int IMPORT_GROUP = 1;
+	private static final int REQUIRE_GROUP = 2;
+	private static final int OTHER_GROUP = 4;
+	public int category(Object element) {
+		if ( element instanceof IPackageImport ) {
+			return IMPORT_GROUP;
+		}
+		else if ( element instanceof IPackageExport ) {
+			return EXPORT_GROUP;
+		}
+		else if ( element instanceof IRequiredBundle ) {
+			return REQUIRE_GROUP;
+		}
+		else {
+			return OTHER_GROUP;
+		}
+	}
+	@SuppressWarnings("unchecked")
+	@Override
+	public int compare(Viewer viewer, Object e1, Object e2) {
+        int cat1 = category(e1);
+        int cat2 = category(e2);
+
+        if (cat1 != cat2) {
+			return cat1 - cat2;
+		}
+        
+        if ( cat1 == OTHER_GROUP ) {
+            String name1;
+            String name2;
+
+            if (viewer == null || !(viewer instanceof ContentViewer)) {
+                name1 = e1.toString();
+                name2 = e2.toString();
+            } else {
+                IBaseLabelProvider prov = ((ContentViewer) viewer)
+                        .getLabelProvider();
+                if (prov instanceof ILabelProvider) {
+                    ILabelProvider lprov = (ILabelProvider) prov;
+                    name1 = lprov.getText(e1);
+                    name2 = lprov.getText(e2);
+                } else {
+                    name1 = e1.toString();
+                    name2 = e2.toString();
+                }
+            }
+            if (name1 == null) {
+    			name1 = "";//$NON-NLS-1$
+    		}
+            if (name2 == null) {
+    			name2 = "";//$NON-NLS-1$
+    		}
+
+            // use the comparator to compare the strings
+            return getComparator().compare(name1, name2);
+        }
+        else {
+        	Comparable c1 = (Comparable) e1;
+        	Comparable c2 = (Comparable) e2;
+        	return c1.compareTo(c2);
+        }
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/RepositoryViewPart.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/RepositoryViewPart.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/RepositoryViewPart.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/RepositoryViewPart.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,320 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.views;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.ICompoundModelElement;
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.repository.IRepositoryModel;
+import org.cauldron.sigil.model.util.ModelHelper;
+import org.cauldron.sigil.repository.IBundleRepository;
+import org.cauldron.sigil.repository.IRepositoryChangeListener;
+import org.cauldron.sigil.repository.IRepositoryVisitor;
+import org.cauldron.sigil.repository.RepositoryChangeEvent;
+import org.cauldron.sigil.ui.SigilUI;
+import org.cauldron.sigil.ui.util.DefaultTreeContentProvider;
+import org.cauldron.sigil.ui.util.ModelLabelProvider;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.util.LocalSelectionTransfer;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceAdapter;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.part.ViewPart;
+
+public class RepositoryViewPart extends ViewPart implements IRepositoryChangeListener {
+
+	public class FindUsersAction extends Action {
+		@Override
+		public String getText() {
+			return "Find Uses";
+		}
+
+		@Override
+		public void run() {
+			ISelection s = treeViewer.getSelection();
+			if ( !s.isEmpty() ) {
+				IStructuredSelection sel = (IStructuredSelection) s;
+				IModelElement e = (IModelElement) sel.getFirstElement();
+				List<IModelElement>	users = ModelHelper.findUsers(e);
+				String msg = null;
+				if ( users.isEmpty() ) {
+					msg = "No users of " + e;
+				}
+				else {
+					StringBuilder b = new StringBuilder();	
+					for ( IModelElement u : users ) {
+						ISigilBundle bndl = u.getAncestor(ISigilBundle.class);
+						b.append( bndl );
+						b.append( "->" );
+						b.append( u );
+						b.append( "\n" );
+					}
+					msg = b.toString();
+				}
+				MessageDialog.openInformation(getViewSite().getShell(), "Information", msg );
+			}
+		}
+	}
+
+	class RepositoryAction extends Action {
+		final IBundleRepository rep;
+		final IRepositoryModel model;
+		
+		public RepositoryAction(IBundleRepository rep) {
+			this.rep = rep;
+			this.model = SigilCore.getRepositoryConfiguration().findRepository(rep.getId());
+		}
+		
+		
+		@Override
+		public void run() {
+			treeViewer.setInput(rep);
+			createMenu();
+		}
+
+		@Override
+		public String getText() {
+			String name = model.getName(); 
+			if ( treeViewer.getInput() == rep ) {
+				name = "> " + name;
+			}
+			return name;
+		}
+		
+		@Override
+		public ImageDescriptor getImageDescriptor() {
+			Image img = model.getType().getIcon();
+			if ( img == null ) {
+				return ImageDescriptor.createFromFile(RepositoryViewPart.class, "/icons/jars_obj.png");
+			}
+			else {
+				return ImageDescriptor.createFromImage(img);
+			}
+		}
+	}
+	
+	class RefreshAction extends Action {
+		@Override
+		public void run() {
+			IBundleRepository rep = (IBundleRepository) treeViewer.getInput();
+			if ( rep != null ) {
+				rep.refresh();
+				treeViewer.refresh();
+			}
+		}
+
+		@Override
+		public String getText() {
+			return "Refresh";
+		}
+		
+		@Override
+		public ImageDescriptor getImageDescriptor() {
+			return ImageDescriptor.createFromFile(RepositoryViewPart.class, "/icons/refreshBundle.png");
+		}
+
+	}
+
+	private TreeViewer treeViewer;
+
+	@Override
+	public void createPartControl(Composite parent) {
+		createBody(parent);
+		createMenu();
+		SigilCore.getGlobalRepositoryManager().addRepositoryChangeListener(this);
+	}
+
+	@Override
+	public void dispose() {
+		SigilCore.getGlobalRepositoryManager().removeRepositoryChangeListener(this);
+		super.dispose();
+	}
+
+	private void createMenu() {
+		createTopMenu();
+		createLocalMenu();
+	}
+
+	private void createLocalMenu() {
+		/*MenuManager menuMgr = new MenuManager();
+		menuMgr.add( new FindUsersAction() );
+		Menu menu = menuMgr.createContextMenu(treeViewer.getControl());
+
+		treeViewer.getControl().setMenu(menu);
+		getViewSite().registerContextMenu(menuMgr, treeViewer); */
+		IActionBars bars = getViewSite().getActionBars();
+		IToolBarManager toolBar = bars.getToolBarManager();
+		toolBar.add( new RefreshAction() );
+	}
+
+	private void createTopMenu() {
+		IActionBars bars = getViewSite().getActionBars();
+		IMenuManager menu = bars.getMenuManager();
+		menu.removeAll();
+		for ( final IBundleRepository rep : SigilCore.getGlobalRepositoryManager().getRepositories() ) {
+			if ( treeViewer.getInput() == null ) {
+				treeViewer.setInput(rep);
+			}
+			
+			RepositoryAction action = new RepositoryAction(rep);
+			menu.add( action );			
+		}
+	}
+
+	private void createBody(Composite parent) {
+		// components
+		Composite control = new Composite(parent, SWT.NONE);
+		Tree tree = new Tree(control, SWT.NONE);
+		
+		// layout
+		control.setLayout( new GridLayout(1, false ) );
+		tree.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1) );
+		
+		// viewer
+		treeViewer = new TreeViewer(tree);
+		treeViewer.setContentProvider( new DefaultTreeContentProvider() {
+			public Object[] getChildren(Object parentElement) {
+				if ( parentElement instanceof ICompoundModelElement ) {
+					ICompoundModelElement model = (ICompoundModelElement) parentElement;
+					return model.children();
+				}
+				
+				return null;
+			}
+
+			public Object getParent(Object element) {
+				if ( element instanceof IModelElement ) {
+					IModelElement model = (IModelElement) element;
+					return model.getParent();
+				}
+				
+				return null;
+			}
+
+			public boolean hasChildren(Object element) {
+				if ( element instanceof ICompoundModelElement ) {
+					ICompoundModelElement model = (ICompoundModelElement) element;
+					return model.children().length > 0;
+				}
+				return false;
+			}
+
+			public Object[] getElements(Object inputElement) {
+				IBundleRepository rep = (IBundleRepository) inputElement;
+				return getBundles(rep);
+			}
+		});
+		
+		treeViewer.setComparator( new ModelElementComparator() );
+		
+		treeViewer.setLabelProvider( new ModelLabelProvider() );
+		
+		treeViewer.addDragSupport(DND.DROP_LINK, new Transfer[] { LocalSelectionTransfer.getTransfer() }, new DragSourceAdapter() {
+			@Override
+			public void dragFinished(DragSourceEvent event) {
+				// TODO Auto-generated method stub
+				super.dragFinished(event);
+			}
+
+			@Override
+			public void dragSetData(DragSourceEvent event) {
+				// TODO Auto-generated method stub
+				super.dragSetData(event);
+			}
+
+			@SuppressWarnings("unchecked")
+			@Override
+			public void dragStart(DragSourceEvent event) {
+				if ( treeViewer.getSelection().isEmpty() ) {
+					IStructuredSelection sel = (IStructuredSelection) treeViewer.getSelection();
+					for ( Iterator<IModelElement> i = sel.iterator(); i.hasNext(); ) {
+						IModelElement e = i.next();
+						if ( e instanceof ISigilBundle ) {
+							event.data = e;
+						}
+						else {
+							event.doit = false;
+						}
+					}
+				}
+				else {
+					event.doit = false;
+				}
+			}
+		});
+	}
+
+	@Override
+	public void setFocus() {
+	}
+
+	public void repositoryChanged(RepositoryChangeEvent event) {
+		switch ( event.getType() ) {
+		case ADDED:
+			createTopMenu();
+			break;
+		case CHANGED:
+			if ( event.getRepository() == treeViewer.getInput() ) {
+				SigilUI.runInUI( new Runnable() {
+					public void run() {
+						treeViewer.refresh();
+					} 					
+				} );
+			}
+			break;
+		case REMOVED:
+			if ( event.getRepository() == treeViewer.getInput() ) {
+				treeViewer.setInput(null);
+			}
+			createTopMenu();
+		}
+	}
+	
+	private Object[] getBundles(IBundleRepository repository) {
+		final LinkedList<ISigilBundle> bundles = new LinkedList<ISigilBundle>();
+		repository.accept(new IRepositoryVisitor() {
+			public boolean visit(ISigilBundle bundle) {
+				bundles.add(bundle);
+				return true;
+			}
+		});
+		return bundles.toArray();
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleConnectionHighlighter.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleConnectionHighlighter.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleConnectionHighlighter.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleConnectionHighlighter.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.views.resolution;
+
+import java.util.Set;
+
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.zest.core.widgets.GraphConnection;
+import org.eclipse.zest.core.widgets.GraphItem;
+import org.eclipse.zest.core.widgets.GraphNode;
+
+public class BundleConnectionHighlighter implements ISelectionChangedListener {
+
+	private BundleResolverView view;
+	
+	public BundleConnectionHighlighter(BundleResolverView view) {
+		this.view = view;
+	}
+	
+	public void selectionChanged(SelectionChangedEvent event) {
+		ISelection selection = event.getSelection();
+		if ( !selection.isEmpty() ) {
+			IStructuredSelection str = (IStructuredSelection) selection;
+
+			Object sel = str.getFirstElement();
+			
+			if ( sel instanceof ISigilBundle ) {
+				BundleGraph graph = (BundleGraph) view.getBundlegraph();
+
+				ISigilBundle selected = (ISigilBundle) sel;
+				Set<ISigilBundle> connected = graph.getTargets(selected);
+
+				highlightLinks(graph, selected, connected);
+				highlightBundles(graph, selected, connected);
+			}
+			else if ( sel instanceof Link ) {
+				GraphConnection c = (GraphConnection) findGraphItem(sel);
+				if ( c != null ) {
+					c.unhighlight();
+					c.setHighlightColor(ColorConstants.blue);
+					c.highlight();
+				}
+			}
+		}
+		else {
+			// TODO clear highlights...
+		}
+	}
+
+	private void highlightBundles(BundleGraph graph, ISigilBundle selected, Set<ISigilBundle> connected) {
+		for ( ISigilBundle bundle : graph.getBundles() ) {
+			GraphNode node = (GraphNode) findGraphItem(bundle);
+			if ( node != null ) {
+				node.unhighlight();
+
+				if ( bundle == selected ) {
+					node.setHighlightColor(ColorConstants.yellow);
+					node.highlight();
+				}
+				else if ( view.isDisplayed(BundleResolverView.DEPENDENTS) ) {
+					if ( connected.contains(bundle) ) {
+						node.setHighlightColor(ColorConstants.lightBlue);
+						node.highlight();
+					}
+				}
+			}
+		}
+	}
+	
+	private void highlightLinks(BundleGraph graph, ISigilBundle selected, Set<ISigilBundle> connected) {
+		for ( Link l : graph.getLinks() ) {
+			GraphConnection c = (GraphConnection) findGraphItem(l);
+			if ( c != null ) {
+				c.unhighlight();
+
+				if ( view.isDisplayed(BundleResolverView.DEPENDENTS) ) {
+					if ( l.getSource() == selected && connected.contains( l.getTarget() ) ) {
+						c.setHighlightColor(ColorConstants.lightBlue);
+						c.highlight();
+					}
+				}
+			}
+		}
+	}
+
+	private GraphItem findGraphItem(Object l) {
+		try {
+			return view.getGraphViewer().findGraphItem(l);
+		}
+		catch (ArrayIndexOutOfBoundsException e) {
+			// temporary fix for issue 
+			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=242523
+			return null;
+		}
+	}
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraph.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraph.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraph.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraph.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.views.resolution;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+
+public class BundleGraph {
+
+	private HashMap<ISigilBundle, LinkedList<Link>> lookup = new HashMap<ISigilBundle, LinkedList<Link>>();
+	private LinkedList<Link> links = new LinkedList<Link>();
+	private HashSet<ISigilBundle> bundles = new HashSet<ISigilBundle>();
+	
+	public void startResolution(IModelElement requirement) {
+	}
+
+	public void endResolution(IModelElement requirement, ISigilBundle target) {
+		ISigilBundle source = requirement.getAncestor(ISigilBundle.class);
+
+		bundles.add(source);
+		bundles.add(target);
+
+		LinkedList<Link> links = lookup.get(source);
+
+		if ( links == null ) {
+			links = new LinkedList<Link>();
+			lookup.put(source, links);
+		}
+
+		Link l = null;
+		for ( Link c : links ) {
+			if ( c.getTarget() == target ) {
+				l = c;
+				break;
+			}
+		}
+
+		if ( l == null ) {
+			l = new Link(source, target);
+			links.add(l);
+			this.links.add(l);
+		}
+
+		l.addRequirement(requirement);
+	}
+	
+	public List<Link> getLinks() {
+		return links;
+	}
+
+	public Set<ISigilBundle> getBundles() {
+		return bundles;
+	}
+
+	public Set<ISigilBundle> getTargets(ISigilBundle bundle) {
+		HashSet<ISigilBundle> targets = new HashSet<ISigilBundle>();
+		
+		for ( Link l : getLinks(bundle) ) {
+			targets.add(l.getTarget());
+		}
+		
+		return targets;
+	}
+
+	public List<Link> getLinks(ISigilBundle selected) {
+		List<Link> l = lookup.get(selected);
+		return l == null ? Collections.<Link>emptyList() : l;
+	}
+
+	public List<Link> getDependentLinks(ISigilBundle bundle) {
+		ArrayList<Link> found = new ArrayList<Link>(links.size());
+		
+		for  (Link l : links) {
+			if ( l.getTarget() == bundle ) {
+				found.add( l );
+			}
+		}
+		
+		found.trimToSize();
+		
+		return found;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphContentProvider.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphContentProvider.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphContentProvider.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphContentProvider.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.views.resolution;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.zest.core.viewers.IGraphContentProvider;
+
+public class BundleGraphContentProvider implements IGraphContentProvider {
+
+	public Object[] getElements(Object input) {
+		BundleGraph graph = (BundleGraph) input;
+		return graph.getLinks().toArray();
+	}
+
+	public Object getDestination(Object element) {
+		Link l = (Link) element;
+		return l.isSatisfied() ? l.getTarget() : new Link.Unsatisfied();
+	}
+
+	public Object getSource(Object element) {
+		Link l = (Link) element;
+		return l.getSource();
+	}
+
+	public void dispose() {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		
+	}
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphLabelProvider.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphLabelProvider.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphLabelProvider.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphLabelProvider.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.views.resolution;
+
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.ui.SigilUI;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+public class BundleGraphLabelProvider extends LabelProvider {
+
+	private BundleResolverView view;
+	
+	public BundleGraphLabelProvider(BundleResolverView view) {
+		this.view = view;
+	}
+
+	@Override
+	public String getText(Object element) {
+		if ( element instanceof Link ) {
+			Link l = (Link) element;
+			if ( l.isSatisfied() ) {
+				if ( view.isDisplayed(BundleResolverView.LINK_LABELS) ) {
+					return view.getLinkText((Link) element);
+				}
+				else {
+					return "";
+				}
+			}
+			else {
+				return view.getLinkText((Link) element);				
+			}
+		}
+		else if ( element instanceof ISigilBundle ) {
+			ISigilBundle b = (ISigilBundle) element;
+			return b.getBundleInfo().getSymbolicName() + ": " + b.getBundleInfo().getVersion();
+		}
+		else if ( element instanceof Link.Unsatisfied ) {
+			return "unsatisfied";
+		}
+		else {
+			return "unknown:" + element;
+		}
+	}
+	
+	@Override
+	public Image getImage(Object element) {
+		Image result = null;
+		if ( element instanceof ISigilBundle ) {
+			result = SigilUI.cacheImage("icons/jar_obj.png", BundleGraphLabelProvider.class.getClassLoader());
+		}
+		else if ( element instanceof Link.Unsatisfied ) {
+			result = SigilUI.cacheImage("icons/error.gif", BundleGraphLabelProvider.class.getClassLoader());
+		}
+		
+		return result;
+	}	
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphViewFilter.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphViewFilter.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphViewFilter.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleGraphViewFilter.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.views.resolution;
+
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+public class BundleGraphViewFilter extends ViewerFilter {
+
+	private BundleResolverView view;
+	
+	public BundleGraphViewFilter(BundleResolverView view) {
+		this.view = view;
+	}
+
+	@Override
+	public boolean select(Viewer viewer, Object parentElement, Object element) {
+		if ( !view.isDisplayed(BundleResolverView.LOCAL_LINKS) ) {
+			if ( element instanceof Link ) {
+				Link l = (Link) element;
+				return l.getSource() != l.getTarget();
+			}
+		}
+		if ( !view.isDisplayed(BundleResolverView.SATISFIED) ) {
+			if ( element instanceof Link ) {
+				Link l = (Link) element;
+				return !l.isSatisfied();
+			}
+			else if ( element instanceof ISigilBundle ) {
+				ISigilBundle bundle = (ISigilBundle) element;
+				for ( Link l : view.getBundlegraph().getLinks(bundle)) {
+					if ( !l.isSatisfied() ) {
+						return true;
+					}
+				}
+				return false;
+			}
+		}
+		
+		if ( !view.isDisplayed(BundleResolverView.UNSATISFIED) ) {
+			if ( element instanceof Link ) {
+				Link l = (Link) element;
+				return l.isSatisfied();
+			}
+			else if ( element instanceof Link.Unsatisfied ) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleResolverView.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleResolverView.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleResolverView.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/BundleResolverView.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,322 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.views.resolution;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.osgi.IPackageImport;
+import org.cauldron.sigil.model.osgi.IRequiredBundle;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.repository.IRepositoryManager;
+import org.cauldron.sigil.repository.IResolutionMonitor;
+import org.cauldron.sigil.repository.ResolutionConfig;
+import org.cauldron.sigil.repository.ResolutionException;
+import org.cauldron.sigil.repository.ResolutionMonitorAdapter;
+import org.cauldron.sigil.ui.SigilUI;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Label;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IPartService;
+import org.eclipse.ui.part.ViewPart;
+import org.eclipse.zest.core.viewers.GraphViewer;
+import org.eclipse.zest.core.widgets.Graph;
+import org.eclipse.zest.core.widgets.GraphConnection;
+import org.eclipse.zest.layouts.LayoutStyles;
+import org.eclipse.zest.layouts.algorithms.RadialLayoutAlgorithm;
+import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;
+
+public class BundleResolverView extends ViewPart {
+
+	private static final String SHOW_LINK_LABELS = "Show link labels";
+	private static final String HIDE_LINK_LABELS = "Hide link labels";
+	private static final String SHOW_LOCAL_LINKS = "Show local links";
+	private static final String HIDE_LOCAL_LINKS = "Hide local links";
+	private static final String SHOW_DEPENDENTS = "Show dependents";
+	private static final String HIDE_DEPENDENTS = "Hide dependents";
+	private static final String SHOW_SATISFIED = "Show satisfied bundles";
+	private static final String HIDE_SATISFIED = "Hide satisfied bundles";
+	private static final String SHOW_UNSATISFIED = "Show unsatisfied bundles";
+	private static final String HIDE_UNSATISFIED = "Hide unsatisfied bundles";
+	private static final String SHOW_OPTIONAL = "Show optional dependencies";
+	private static final String HIDE_OPTIONAL = "Hide optional dependencies";
+	
+	public static final String LINK_LABELS = "link.labels";
+	public static final String LOCAL_LINKS = "local.links";
+	public static final String DEPENDENTS = "dependents";
+	public static final String SATISFIED = "satisified";
+	public static final String UNSATISFIED = "unsatisfied";
+	public static final String OPTIONAL = "optional";
+
+	private GraphViewer viewer;
+	private IModelElement current;
+	private Job job;
+	private int lastX;
+	private int lastY;	
+	
+	private Map<String, Boolean> displayed = new HashMap<String, Boolean>();
+		
+	private class ToggleDisplayAction extends Action {	
+		private String key;
+		private String showMsg;
+		private String hideMsg;
+
+		ToggleDisplayAction(String key, String showMsg, String hideMsg) {
+			this.key = key;
+			this.showMsg = showMsg;
+			this.hideMsg = hideMsg;
+			setText(BundleResolverView.this.isDisplayed(key) ? hideMsg : showMsg);
+		}
+		
+		@Override
+		public void run() {
+			BundleResolverView.this.setDisplayed( key, !BundleResolverView.this.isDisplayed(key) );
+			setText(BundleResolverView.this.isDisplayed(key) ? hideMsg : showMsg);
+		}
+	}
+	
+	public void setInput(final IModelElement element) {
+		if ( current == null || !current.equals(element) ) {
+			SigilCore.log( "Set input " + element );
+			current = element;
+			redraw();
+		}
+	}
+	
+	public void setDisplayed(String key, boolean b) {
+		displayed.put(key, b);
+		
+		if ( key == DEPENDENTS ) {
+			int style = LayoutStyles.NO_LAYOUT_NODE_RESIZING;
+			viewer.setLayoutAlgorithm( b ? new TreeLayoutAlgorithm(style) : new RadialLayoutAlgorithm(style));
+			redraw();
+		}
+		else if ( key == OPTIONAL ) {
+			redraw();
+		}
+		else if ( key == SATISFIED || key == UNSATISFIED ) {
+			viewer.refresh();
+		}
+	}
+
+	public boolean isDisplayed(String key) {
+		return displayed.get(key);
+	}
+
+	@Override
+	public void setFocus() {
+	}
+	
+	@Override
+    public void createPartControl( Composite parent ) {
+		init();
+		createViewer(parent);
+		createListeners();
+		createMenu();
+    }
+	
+	private void init() {
+		displayed.put(LINK_LABELS, false);
+		displayed.put(LOCAL_LINKS, false);
+		displayed.put(DEPENDENTS, false);
+		displayed.put(OPTIONAL, false);
+		displayed.put(SATISFIED, true);
+		displayed.put(UNSATISFIED, true);
+	}
+
+	public BundleGraph getBundlegraph() {
+		return (BundleGraph) viewer.getInput();
+	}
+
+	GraphViewer getGraphViewer() {
+		return viewer;
+	}
+
+	String getLinkText(Link link) {
+		StringBuffer buf = new StringBuffer();
+
+		for ( IModelElement e : link.getRequirements() ) {
+			if ( buf.length() > 0 ) {
+				buf.append( "\n" );
+			}
+			if ( e instanceof IPackageImport ) {
+				IPackageImport pi = (IPackageImport) e;
+				buf.append( "import " + pi.getPackageName() + " : " + pi.getVersions() + ": " + (pi.isOptional() ? "optional" : "mandatory" ) );
+			}
+			else if ( e instanceof IRequiredBundle ) {
+				IRequiredBundle rb = (IRequiredBundle) e;
+				buf.append( "required bundle " + rb.getSymbolicName() + " : " + rb.getVersions() + ": " + (rb.isOptional() ? "optional" : "mandatory" ) );
+			}
+		}
+		
+		return buf.toString();
+	}	
+
+	private synchronized void redraw() {
+		final IModelElement element = current;
+		if ( job != null ) {
+			job.cancel();
+		}
+		
+		job = new Job("Resolving " + current) {
+			@Override
+			protected IStatus run(IProgressMonitor progress) {
+				try {
+					resolve(element, progress);
+					return Status.OK_STATUS;
+				} catch (CoreException e) {
+					return e.getStatus();
+				}
+			}
+		};
+		job.schedule();
+	}
+
+	private void resolve(IModelElement element, IProgressMonitor progress) throws CoreException {
+		final BundleGraph graph = new BundleGraph();
+		
+		IResolutionMonitor monitor = new ResolutionMonitorAdapter(progress) {
+			@Override
+			public void startResolution(IModelElement requirement) {
+				graph.startResolution(requirement);
+			}
+
+			@Override
+			public void endResolution(IModelElement requirement, ISigilBundle provider) {
+				graph.endResolution(requirement, provider);
+			}
+		};
+
+		ISigilProjectModel project = findProject(element);
+		IRepositoryManager repository = SigilCore.getRepositoryManager(project);
+		
+		int options = ResolutionConfig.IGNORE_ERRORS;
+		
+		if ( isDisplayed(DEPENDENTS) ) {
+			options |= ResolutionConfig.INCLUDE_DEPENDENTS;
+		}
+		if ( isDisplayed(OPTIONAL) ) {
+			options |= ResolutionConfig.INCLUDE_OPTIONAL;
+		}
+		
+		ResolutionConfig config = new ResolutionConfig(options);
+		
+		try {
+			repository.getBundleResolver().resolve(element, config, monitor);
+		} catch (ResolutionException e) {
+			throw SigilCore.newCoreException("Failed to resolve " + element, e);
+		}
+		
+		SigilUI.runInUI( new Runnable() {
+			public void run() {
+				viewer.setInput(graph);
+				addCustomUIElements();
+			}			
+		} );
+	}
+
+	private static ISigilProjectModel findProject(IModelElement element) {
+		if ( element == null ) {
+			return null;
+		}
+		if ( element instanceof ISigilProjectModel ) {
+			return (ISigilProjectModel) element;
+		}
+		
+		return element.getAncestor(ISigilProjectModel.class);
+	}
+
+	@SuppressWarnings("unchecked")
+	private void addCustomUIElements() {
+		if ( !isDisplayed(LINK_LABELS) ) {
+			for ( GraphConnection c : (List<GraphConnection>) viewer.getGraphControl().getConnections() ) {
+				if ( c.getData() instanceof Link ) {
+					c.setTooltip(buildToolTip((Link) c.getData()));
+				}
+			}
+		}
+	}
+
+	private IFigure buildToolTip(Link link) {
+		Label l = new Label();
+		l.setText(getLinkText(link));
+		return l;
+	}
+
+	private void createViewer(Composite parent) {
+		parent.setLayout( new FillLayout() );
+    	viewer = new GraphViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL);
+    	IContentProvider contentProvider = new BundleGraphContentProvider();
+		viewer.setContentProvider(contentProvider);
+		viewer.setLabelProvider(new BundleGraphLabelProvider(this));
+		viewer.addFilter( new BundleGraphViewFilter(this) );
+		
+		
+		int style = LayoutStyles.NO_LAYOUT_NODE_RESIZING;
+		viewer.setLayoutAlgorithm( isDisplayed(DEPENDENTS) ? new TreeLayoutAlgorithm(style) : new RadialLayoutAlgorithm(style));
+		viewer.addSelectionChangedListener( new BundleConnectionHighlighter(this) );
+		viewer.setInput(new BundleGraph());
+	}
+
+	private void createMenu() {
+		IActionBars action = getViewSite().getActionBars(); 
+		action.getMenuManager().add(new ToggleDisplayAction( LINK_LABELS, SHOW_LINK_LABELS, HIDE_LINK_LABELS ));
+		action.getMenuManager().add(new ToggleDisplayAction( LOCAL_LINKS, SHOW_LOCAL_LINKS, HIDE_LOCAL_LINKS ));
+		action.getMenuManager().add(new ToggleDisplayAction( DEPENDENTS, SHOW_DEPENDENTS, HIDE_DEPENDENTS ));
+		action.getMenuManager().add(new ToggleDisplayAction( OPTIONAL, SHOW_OPTIONAL, HIDE_OPTIONAL ));
+		action.getMenuManager().add(new ToggleDisplayAction( SATISFIED, SHOW_SATISFIED, HIDE_SATISFIED ));
+		action.getMenuManager().add(new ToggleDisplayAction( UNSATISFIED, SHOW_UNSATISFIED, HIDE_UNSATISFIED ));
+		action.updateActionBars();
+	}
+
+	private void createListeners() {
+		IPartService ps = (IPartService) getViewSite().getService(IPartService.class);
+		ps.addPartListener( new EditorViewPartListener(this) );
+		viewer.getGraphControl().addControlListener( new ControlAdapter() {
+			@Override
+			public void controlResized(ControlEvent e) {
+				Graph g = (Graph) e.getSource();
+				int x = g.getSize().x;
+				int y = g.getSize().y;
+				if ( lastX != x || lastY != y ) {
+					lastX = x;
+					lastY = y;
+					redraw();
+				}
+			}
+		} );
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/EditorViewPartListener.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/EditorViewPartListener.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/EditorViewPartListener.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/EditorViewPartListener.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.views.resolution;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IPartListener2;
+import org.eclipse.ui.IWorkbenchPartReference;
+
+public class EditorViewPartListener implements IPartListener2 {
+
+	private BundleResolverView bundleResolverView;
+	
+	public EditorViewPartListener(BundleResolverView bundleResolverView) {
+		this.bundleResolverView = bundleResolverView;
+	}
+
+	public void partActivated(IWorkbenchPartReference partRef) {
+		checkRef(partRef);
+	}
+
+	public void partBroughtToTop(IWorkbenchPartReference partRef) {
+		// no action
+	}
+
+	public void partClosed(IWorkbenchPartReference partRef) {
+		// no action
+	}
+
+	public void partDeactivated(IWorkbenchPartReference partRef) {
+		// no action
+	}
+
+	public void partHidden(IWorkbenchPartReference partRef) {
+		// no action
+	}
+
+	public void partInputChanged(IWorkbenchPartReference partRef) {
+		// no action
+	}
+
+	public void partOpened(IWorkbenchPartReference partRef) {
+		// no action
+	}
+
+	public void partVisible(IWorkbenchPartReference partRef) {
+		// no action
+	}
+
+	private void checkRef(IWorkbenchPartReference partRef) {
+		IEditorPart editor = partRef.getPage().getActiveEditor();
+		if ( editor != null ) {
+			IEditorInput input = editor.getEditorInput();
+			if ( input instanceof IFileEditorInput ) {
+				IFileEditorInput f = (IFileEditorInput) input;
+				IProject project = f.getFile().getProject();
+				try {
+					ISigilProjectModel model = SigilCore.create(project);
+					if ( model != null ) {
+						bundleResolverView.setInput(model);
+					}
+				} catch (CoreException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/Link.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/Link.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/Link.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/views/resolution/Link.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.cauldron.sigil.ui.views.resolution;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.osgi.IPackageImport;
+import org.cauldron.sigil.model.osgi.IRequiredBundle;
+
+public class Link {	
+	public static class Unsatisfied {
+
+	}
+
+	private ISigilBundle source;
+	private ISigilBundle target;
+	
+	private LinkedList<IModelElement> requirements = new LinkedList<IModelElement>();
+	private static final Comparator<IModelElement> comparator = new Comparator<IModelElement>() {
+
+		public int compare(IModelElement o1, IModelElement o2) {
+			if (o1 instanceof IRequiredBundle) {
+				if ( o2 instanceof IRequiredBundle) {
+					return compareBundles( (IRequiredBundle) o1, (IRequiredBundle) o2 );
+				}
+				else {
+					return -1;
+				}
+			}
+			else {
+				if ( o2 instanceof IRequiredBundle ) {
+					return 1;
+				}
+				else {
+					return compareNonBundles( o1, o2 );
+				}
+			}
+		}
+
+		private int compareNonBundles(IModelElement o1, IModelElement o2) {
+			if (o1 instanceof IPackageImport) {
+				if ( o2 instanceof IPackageImport) {
+					return compareImports( (IPackageImport) o1, (IPackageImport) o2 );
+				}
+				else {
+					return -1;
+				}
+			}
+			else {
+				if ( o2 instanceof IPackageImport ) {
+					return 1;
+				}
+				else {
+					return 0;
+				}
+			}
+		}
+
+		private int compareImports(IPackageImport o1, IPackageImport o2) {
+			return o1.getPackageName().compareTo( o2.getPackageName() );
+		}
+
+		private int compareBundles(IRequiredBundle o1, IRequiredBundle o2) {
+			return o1.getSymbolicName().compareTo( o2.getSymbolicName() );
+		}
+		
+	};
+	
+	public Link(ISigilBundle source, ISigilBundle target) {
+		this.source = source;
+		this.target = target;
+	}
+
+	public ISigilBundle getSource() {
+		return source;
+	}
+	
+	public ISigilBundle getTarget() {
+		return target;
+	}
+	
+	public boolean isSatisfied() {
+		return target != null;
+	}
+
+	public void addRequirement(IModelElement requirement) {
+		requirements.add(requirement);
+		Collections.sort(requirements, comparator);
+	}
+	
+	public String toString() {
+		return "Link[" + source + "->" + target + "]";
+	}
+
+	public List<IModelElement> getRequirements() {
+		return requirements;
+	}
+
+	public boolean isOptional() {
+		for ( IModelElement e : requirements ) {
+			if ( e instanceof IPackageImport ) {
+				IPackageImport pi = (IPackageImport) e;
+				if ( !pi.isOptional() ) {
+					return false;
+				}
+			}
+			else if ( e instanceof IRequiredBundle ) {
+				IRequiredBundle rb = (IRequiredBundle) e;
+				if ( !rb.isOptional() ) {
+					return false;
+				}
+			}
+		}
+		return true;
+	}
+}