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 [18/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/editors/project/PropertiesForm.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/PropertiesForm.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/PropertiesForm.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/PropertiesForm.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,49 @@
+/*
+ * 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.editors.project;
+
+
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.propertiesfileeditor.IPropertiesFilePartitions;
+import org.eclipse.jdt.internal.ui.propertiesfileeditor.PropertiesFileSourceViewerConfiguration;
+import org.eclipse.jdt.ui.text.JavaTextTools;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+@SuppressWarnings("restriction")
+public class PropertiesForm extends SigilSourcePage {
+
+    public static final String PAGE_ID = "properties";
+    
+	public PropertiesForm(SigilProjectEditorPart editor, ISigilProjectModel project) {
+		super(PAGE_ID);
+		JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools();
+		IPreferenceStore store= JavaPlugin.getDefault().getCombinedPreferenceStore();
+		setPreferenceStore(store);
+		setSourceViewerConfiguration(new PropertiesFileSourceViewerConfiguration(textTools.getColorManager(), store, this, IPropertiesFilePartitions.PROPERTIES_FILE_PARTITIONING));
+        /*IFileEditorInput fileInput = (IFileEditorInput) editor.getEditorInput();
+		this.setDocumentProvider(fileInput);*/
+	}
+
+	@Override
+	public boolean isSaveAsAllowed() {
+		return false;
+	}	
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/RequiresBundleSection.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/RequiresBundleSection.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/RequiresBundleSection.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/RequiresBundleSection.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,135 @@
+/*
+ * 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.editors.project;
+
+
+import java.util.Iterator;
+import java.util.Set;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.ModelElementFactory;
+import org.cauldron.sigil.model.ModelElementFactoryException;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.osgi.IBundleModelElement;
+import org.cauldron.sigil.model.osgi.IRequiredBundle;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.ui.form.SigilPage;
+import org.cauldron.sigil.ui.util.DefaultTableProvider;
+import org.cauldron.sigil.ui.util.ResourcesDialogHelper;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+public class RequiresBundleSection extends BundleDependencySection {
+	
+	public RequiresBundleSection(SigilPage page, Composite parent, ISigilProjectModel project, Set<IModelElement> unresolvedElements) throws CoreException {
+		super( page, parent, project, unresolvedElements );
+	}
+	
+	@Override
+	protected String getTitle() {
+		return "Requires Bundles";
+	}
+	
+	@Override
+	protected Label createLabel(Composite parent, FormToolkit toolkit) {
+		return toolkit.createLabel( parent, "Specify which bundles this bundle depends on." );
+	}
+	
+	@Override
+	protected IContentProvider getContentProvider() {
+		return new DefaultTableProvider() {
+			public Object[] getElements(Object inputElement) {
+				return getBundle().getBundleInfo().getRequiredBundles().toArray();
+			}
+		};
+	}
+
+	protected ISigilBundle getBundle() {
+		return getProjectModel().getBundle();
+	}
+
+	@Override
+	protected void handleAdd() {
+		try {
+			NewResourceSelectionDialog<IBundleModelElement> dialog = ResourcesDialogHelper.createRequiredBundleDialog( getSection().getShell(), "Add Required Bundle", getProjectModel(), null, getBundle().getBundleInfo().getRequiredBundles() );
+			
+			if (dialog.open() == Window.OK) {
+				IRequiredBundle required = ModelElementFactory.getInstance().newModelElement( IRequiredBundle.class );
+				required.setSymbolicName(dialog.getSelectedName());
+				required.setVersions(dialog.getSelectedVersions());
+				required.setOptional(dialog.isOptional());
+				
+				getBundle().getBundleInfo().addRequiredBundle(required);
+				refresh();
+				markDirty();
+			}
+		}
+		catch (ModelElementFactoryException e) {
+			SigilCore.error( "Failed to build required bundle", e );
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	protected void handleEdit() {
+		IStructuredSelection selection = (IStructuredSelection) getSelection();
+		
+		boolean changed = false;
+		
+		if ( !selection.isEmpty() ) {
+			for ( Iterator<IRequiredBundle> i = selection.iterator(); i.hasNext(); ) {	
+				IRequiredBundle requiredBundle = i.next();
+				NewResourceSelectionDialog<IBundleModelElement> dialog = ResourcesDialogHelper.createRequiredBundleDialog(getSection().getShell(), "Edit Imported Package", getProjectModel(), requiredBundle, getBundle().getBundleInfo().getRequiredBundles() );
+				if ( dialog.open() == Window.OK ) {
+					changed = true;
+					requiredBundle.setSymbolicName(dialog.getSelectedName());
+					requiredBundle.setVersions(dialog.getSelectedVersions());
+					requiredBundle.setOptional(dialog.isOptional());
+				}
+			}					
+		}
+		
+		if ( changed ) {
+			refresh();
+			markDirty();
+		}
+	}
+	
+	@SuppressWarnings("unchecked")
+	@Override
+	protected void handleRemoved() {
+		IStructuredSelection selection = (IStructuredSelection) getSelection();
+
+		if ( !selection.isEmpty() ) {
+			for ( Iterator<IRequiredBundle> i = selection.iterator(); i.hasNext(); ) {			
+				getBundle().getBundleInfo().removeRequiredBundle( i.next() );
+			}		
+			
+			refresh();
+			markDirty();
+		}
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceBuildSection.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceBuildSection.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceBuildSection.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceBuildSection.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,169 @@
+/*
+ * 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.editors.project;
+
+
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.ui.SigilUI;
+import org.cauldron.sigil.ui.form.SigilPage;
+import org.cauldron.sigil.ui.util.ModelLabelProvider;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.Section;
+import org.eclipse.ui.forms.widgets.TableWrapData;
+
+/**
+ * @author dave
+ *
+ */
+public class ResourceBuildSection extends AbstractResourceSection implements ICheckStateListener, IResourceChangeListener, IPropertyChangeListener {
+
+	private ExcludedResourcesFilter resourcesFilter;
+
+	/**
+	 * @param page
+	 * @param parent
+	 * @param project
+	 * @throws CoreException 
+	 */
+	public ResourceBuildSection(SigilPage page, Composite parent, ISigilProjectModel project) throws CoreException {
+		super( page, parent, project );
+	}
+
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.ui.editors.project.SigilSection#createSection(org.eclipse.ui.forms.widgets.Section, org.eclipse.ui.forms.widgets.FormToolkit)
+	 */
+	@Override
+	protected void createSection(Section section, FormToolkit toolkit) {
+		setTitle( "Resources" );
+		
+		Composite body = createTableWrapBody(1, toolkit);
+
+        toolkit.createLabel( body, "Specify which resources are included in the bundle." );
+		
+		tree = toolkit.createTree( body, SWT.CHECK | SWT.BORDER );
+		Link link = new Link(body, SWT.WRAP);
+		link.setText("Some resources may be filtered according to preferences. <a href=\"excludedResourcePrefs\">Click here</a> to edit the list of exclusions.");
+		
+		TableWrapData data = new TableWrapData( TableWrapData.FILL_GRAB);
+		data.heightHint = 200;
+		tree.setLayoutData( data );
+		
+		viewer = new CheckboxTreeViewer( tree );
+		IProject base = getProjectModel().getProject();
+		viewer.setContentProvider( new ContainerTreeProvider() );
+		viewer.setLabelProvider( new ModelLabelProvider() );
+		viewer.addCheckStateListener( this );
+		resourcesFilter = new ExcludedResourcesFilter();
+		viewer.addFilter(resourcesFilter);
+		viewer.setInput(base);
+		
+		link.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				if("excludedResourcePrefs".equals(event.text)) {
+					PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(getPage().getEditorSite().getShell(), SigilCore.EXCLUDED_RESOURCES_PREFERENCES_ID, null, null);
+					dialog.open();
+				}
+			}
+		});
+		
+		SigilCore.getDefault().getPreferenceStore().addPropertyChangeListener(this);
+		
+		startWorkspaceListener(base.getWorkspace());
+	}
+
+	@Override
+	public void commit(boolean onSave) {
+		ISigilBundle bundle = getProjectModel().getBundle();
+		
+		bundle.clearSourcePaths();
+		
+		SigilUI.runInUISync( new Runnable() {
+			public void run() {
+				for ( Object o : viewer.getCheckedElements() ) {
+					if ( !viewer.getGrayed(o) ) {
+						IResource r = (IResource) o;
+						getProjectModel().getBundle().addSourcePath( r.getProjectRelativePath() );
+					}
+				}
+			}			
+		});
+		
+		super.commit(onSave);
+	}
+
+	@Override
+	protected void refreshSelections()  {
+		// zero the state
+		for ( IPath path : getProjectModel().getBundle().getSourcePaths() ) {
+			IResource r = findResource( path );
+			if ( r != null ) {
+				viewer.expandToLevel(r, 0);
+				viewer.setChecked( r, true );
+				viewer.setGrayed( r, false );
+				handleStateChanged(r, true, false, false);
+			}
+			else {
+				SigilCore.error( "Unknown path " + path );
+			}
+		}
+	}
+	
+	@Override
+	protected void syncResourceModel(IResource element, boolean checked) {
+		if ( checked ) {
+			getProjectModel().getBundle().addSourcePath( element.getProjectRelativePath() );
+		}
+		else {
+			getProjectModel().getBundle().removeSourcePath( element.getProjectRelativePath() );
+		}
+		
+		markDirty();
+	}
+	
+	@Override
+	public void dispose() {
+		super.dispose();
+		SigilCore.getDefault().getPreferenceStore().removePropertyChangeListener(this);
+	}
+
+	public void propertyChange(PropertyChangeEvent event) {
+		resourcesFilter.loadExclusions();
+		viewer.refresh();
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceImportDialog.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceImportDialog.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceImportDialog.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceImportDialog.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,89 @@
+/*
+ * 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.editors.project;
+
+import org.cauldron.sigil.model.ModelElementFactory;
+import org.cauldron.sigil.model.common.VersionRange;
+import org.cauldron.sigil.model.osgi.IPackageImport;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+
+public class ResourceImportDialog extends ResourceSelectDialog implements VersionsChangeListener {
+
+	private VersionRangeComponent versions;
+	private VersionRange range;
+	
+	public ResourceImportDialog(Shell parentShell, String title, String label, IContentProvider content, ViewerFilter filter, Object scope ) {
+		super(parentShell, content, filter, scope, title, label, true);
+	}
+
+	public VersionRange getVersions() {
+		return range;
+	}
+
+	@Override
+	protected void createCustom(Composite body) {
+		versions = new VersionRangeComponent(body, SWT.BORDER );
+		versions.addVersionChangeListener(this);
+		versions.setVersions(range);
+		
+		GridData data = new GridData( SWT.LEFT, SWT.TOP, true, true );
+		data.horizontalSpan = 2;
+		data.widthHint = 300;
+		data.heightHint = 200;
+		versions.setLayoutData(data);
+	}
+
+	@Override
+	protected void selectionChanged(SelectionChangedEvent event) {
+		if ( event.getSelection().isEmpty() ) {
+			versions.setEnabled(false);
+		}
+		else {
+			versions.setEnabled(true);
+		}
+	}
+
+	public void versionsChanged(VersionRange range) {
+		this.range = range; 
+		if ( range == null ) {
+			setErrorMessage( "Invalid version" );
+		}
+		else {
+			setErrorMessage( null );
+		}
+	}
+
+	public void setVersions(VersionRange range) {
+		this.range = range;
+	}
+
+	public IPackageImport getImport() {
+		IPackageImport packageImport = ModelElementFactory.getInstance().newModelElement( IPackageImport.class );
+		packageImport.setPackageName( (String) getSelected()[0] );
+		packageImport.setVersions( getVersions() );
+		return packageImport;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceSelectDialog.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceSelectDialog.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceSelectDialog.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ResourceSelectDialog.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,372 @@
+/*
+ * 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.editors.project;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.cauldron.sigil.ui.util.ModelLabelProvider;
+import org.cauldron.sigil.ui.util.SingletonSelection;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.resource.StringConverter;
+import org.eclipse.jface.viewers.ComboViewer;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+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.StructuredViewer;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Text;
+
+public class ResourceSelectDialog extends Dialog {
+
+	private AtomicInteger keyCheck = new AtomicInteger();
+	private ScheduledExecutorService background = Executors.newSingleThreadScheduledExecutor();
+	
+	private class UpdateViewerRunnable implements Runnable {
+		private int check;
+		public UpdateViewerRunnable(int check) {
+			this.check = check;
+		}
+
+		public void run() {
+			if ( check == keyCheck.get() ) {
+				try {
+					viewer.refresh();
+				}
+				catch (SWTException e) {
+					// discard
+				}
+			}
+		}
+	}
+
+	private static final ISelection EMPTY_SELECTION = new ISelection() {
+		public boolean isEmpty() {
+			return true;
+		}
+	};
+	
+	private Job job;
+	
+	private boolean isCombo;
+	private String title;
+	private String selectionText;
+
+	private StructuredViewer viewer;
+	private Combo resourceNameCombo;
+	private Table resourceNameTable;
+	private Text errorMessageText;
+	private String errorMessage;
+	
+	private ViewerFilter filter;
+	private Object[] selected;
+	
+	private Object scope;	
+	private IContentProvider content;
+	private ILabelProvider labelProvider;
+
+	public ResourceSelectDialog(Shell parentShell, IContentProvider content, ViewerFilter filter, Object scope, String title, String selectionText, boolean isCombo) {
+		super(parentShell);
+		this.title = title;
+		this.selectionText = selectionText;
+		this.content = content;
+		this.filter = filter;
+		this.scope = scope;
+		this.isCombo = isCombo;
+	}
+	
+	public void setJob(Job job) {
+		this.job = job;
+	}
+	
+	public void refreshResources() {
+		try {
+			getShell().getDisplay().asyncExec( new Runnable() {
+				public void run() {
+					try {
+						viewer.refresh();
+					}
+					catch (SWTException e) {
+						// attempt to exec after dialog closed - discard
+					}
+				}
+			});
+		}
+		catch (NullPointerException e) {
+			// attempt to exec after dialog closed - discard
+		}
+		catch (SWTException e) {
+			// attempt to exec after dialog closed - discard
+		}
+	}
+
+	/*
+     * (non-Javadoc)
+     * 
+     * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
+     */
+    protected void configureShell(Shell shell) {
+        super.configureShell(shell);
+        if (title != null) {
+			shell.setText(title);
+		}        
+    }
+
+	@Override
+	public void create() {
+		super.create();
+		if ( getItemCount() == 0 ) {
+			setErrorMessage( "No resources available" );
+			getButton(IDialogConstants.OK_ID).setEnabled(false);
+		}
+		else {
+			ISelection selection = selected == null ? EMPTY_SELECTION : new SingletonSelection( selected );
+			setSelected( new SelectionChangedEvent( viewer, selection ), true );
+		}
+		
+		if ( job != null ) {
+			job.schedule();
+		}
+	}
+
+	@Override
+	public boolean close() {
+		if ( job != null ) {
+			job.cancel();
+		}
+		background.shutdownNow();
+		return super.close();
+	}
+
+	private int getItemCount() {
+		if ( isCombo ) {
+			return resourceNameCombo.getItemCount();
+		}
+		else {
+			return resourceNameTable.getItemCount();
+		}
+	}
+
+	@Override
+	protected Control createDialogArea(Composite parent) {
+		Composite body = (Composite) super.createDialogArea(parent);
+		
+		GridLayout layout = (GridLayout) body.getLayout();
+		layout.numColumns = 2;
+		GridData data;
+		
+		labelProvider = new ModelLabelProvider();
+		
+		Label l = new Label( body, SWT.LEFT );
+		l.setText( selectionText );
+		data = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+		if ( !isCombo ) {
+			data.horizontalSpan = 2;
+		}
+		l.setLayoutData( data );
+	
+		if ( isCombo ) {
+			createCombo( body );
+		}
+		else {
+			createTable( body );
+		}
+		
+		viewer.addFilter( filter );
+		viewer.setContentProvider(content);
+		viewer.setLabelProvider( getLabelProvider() );
+		viewer.setComparator( new ViewerComparator() );
+		viewer.setInput( scope );
+		
+		viewer.addSelectionChangedListener( new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				setSelected(event, false);
+			}			
+		});
+	    createCustom( body );
+	    
+		errorMessageText = new Text(body, SWT.READ_ONLY | SWT.WRAP);
+		data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL);
+		data.horizontalSpan = 2;
+	    errorMessageText.setLayoutData(data);
+	    errorMessageText.setBackground(errorMessageText.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
+	    setErrorMessage(errorMessage);
+	    
+		return body;
+	}
+	
+    protected void createCustom(Composite body) {
+	}
+
+	private void createCombo(Composite body) {
+		resourceNameCombo = new Combo( body, SWT.SINGLE | SWT.BORDER );
+		GridData data = new GridData( GridData.HORIZONTAL_ALIGN_END);
+		data.widthHint = 200;
+		resourceNameCombo.setLayoutData( data );
+		
+		viewer = new ComboViewer(resourceNameCombo);
+	}
+
+	private void createTable(Composite body) {
+		final Text txtFilter = new Text(body, SWT.BORDER);
+		GridData data = new GridData( GridData.HORIZONTAL_ALIGN_END);
+		data.horizontalSpan = 2;
+		data.widthHint = 400;
+		txtFilter.setLayoutData(data);
+		
+		resourceNameTable = new Table( body, SWT.MULTI | SWT.BORDER );
+		data = new GridData( GridData.HORIZONTAL_ALIGN_END);
+		data.widthHint = 400;
+		data.heightHint = 400;
+		resourceNameTable.setLayoutData( data );
+		
+		viewer = new TableViewer(resourceNameTable);
+
+		txtFilter.addKeyListener( new KeyAdapter() {
+			@Override
+			public void keyReleased(KeyEvent e) {
+				switch ( e.keyCode ) {
+				case SWT.ARROW_UP:
+					scrollTable(-1);
+					break;
+				case SWT.ARROW_DOWN:
+					scrollTable(+1);
+					break;
+				default:
+					Runnable r = new UpdateViewerRunnable(keyCheck.incrementAndGet());
+					background.schedule(r, 100, TimeUnit.MILLISECONDS);
+					break;
+				}
+			}
+		});
+		
+		ViewerFilter filter = new ViewerFilter() {
+			@Override
+			public boolean select(Viewer viewer, Object parentElement,
+					Object element) {
+				return getLabelProvider().getText(element).startsWith( txtFilter.getText() );
+			}
+		};
+		
+		viewer.addFilter(filter);
+	}
+	
+	private void scrollTable(int delta) {
+		int i = resourceNameTable.getSelectionIndex();
+		
+		if ( i == -1 ) {
+			if ( delta < 0 ) { 
+				i = resourceNameTable.getItemCount() - 1;
+			}
+			else {
+				i = 0;
+			}
+		}
+		else {
+			i+=delta;
+		}
+		
+		if ( i > -1 && i < resourceNameTable.getItemCount() ) {
+			Item item = resourceNameTable.getItem(i);
+			resourceNameTable.select(i);
+			selected = new Object[] { item.getData() };
+			ISelection selection = new SingletonSelection( selected );
+			selectionChanged(new SelectionChangedEvent(viewer, selection));
+			viewer.reveal(selected);
+		}
+	}
+
+	private void setSelected(SelectionChangedEvent event, boolean reveal) {
+		if ( event.getSelection().isEmpty() ) {
+			selected = null;
+			setErrorMessage( "No resource selected" );
+		}
+		else {
+			selected = ((IStructuredSelection) event.getSelection()).toArray();
+			setErrorMessage( null );
+		}
+		
+		selectionChanged(event);
+		
+		if ( reveal && !event.getSelection().isEmpty() ) {
+			if ( resourceNameCombo != null ) {
+				IStructuredSelection sel = (IStructuredSelection) event.getSelection();
+				resourceNameCombo.select(resourceNameCombo.indexOf((String) sel.getFirstElement()));
+			}
+			else {
+				viewer.setSelection(event.getSelection(), true);
+			}
+		}
+	}
+
+	protected ILabelProvider getLabelProvider() {
+		return labelProvider;
+	}
+
+	public Object[] getSelected() {
+    	return selected;
+    }
+	
+	public void setSelected(Object[] selected) {
+		this.selected = selected;
+	}
+	
+	protected void selectionChanged(SelectionChangedEvent event) {
+	}
+
+	public void setErrorMessage(String errorMessage) {
+		this.errorMessage = errorMessage;
+		if (errorMessageText != null && !errorMessageText.isDisposed()) {
+			errorMessageText.setText(errorMessage == null ? " \n " : errorMessage); 
+			boolean hasError = errorMessage != null && (StringConverter.removeWhiteSpaces(errorMessage)).length() > 0;
+			errorMessageText.setEnabled(hasError);
+			errorMessageText.setVisible(hasError);
+			errorMessageText.getParent().update();
+			Control ok = getButton(IDialogConstants.OK_ID);
+			if (ok != null) {
+				ok.setEnabled(!hasError);
+			}
+		}
+	}
+
+}
\ No newline at end of file

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/SigilProjectEditorPart.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/SigilProjectEditorPart.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/SigilProjectEditorPart.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/SigilProjectEditorPart.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,299 @@
+/*
+ * 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.editors.project;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.ModelElementFactory;
+import org.cauldron.sigil.model.common.VersionRange;
+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.ui.SigilUI;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.IFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.IFormPage;
+
+public class SigilProjectEditorPart extends FormEditor implements IResourceChangeListener {
+
+	private final Set<IModelElement> unresolvedElements = Collections.synchronizedSet(new HashSet<IModelElement>());
+	private ISigilProjectModel project;
+	private volatile boolean saving = false;
+	private int dependenciesPageIndex;
+	
+	// XXX-FIXME-XXX
+	private Image errorImage = null; //SigilUI.imageDescriptorFromPlugin(SigilUI.PLUGIN_ID, "icons/error.gif").createImage();
+	private PropertiesForm textPage;
+	
+    public IProject getProject() {
+        IFileEditorInput fileInput = (IFileEditorInput) getEditorInput();
+        return fileInput.getFile().getProject();
+    }
+    
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor)
+     */
+    @Override
+    public void doSave(IProgressMonitor monitor) {
+		monitor.beginTask("Saving", IProgressMonitor.UNKNOWN);
+		try {
+			saving = true;
+			new ProgressMonitorDialog(getSite().getShell()).run(true, true, new IRunnableWithProgress() {
+				public void run(final IProgressMonitor monitor) throws InvocationTargetException,
+						InterruptedException {
+					try {
+						if ( textPage.isDirty() ) {
+							SigilUI.runInUISync(new Runnable() {
+								public void run() {
+									textPage.doSave(monitor);
+								}								
+							});
+							project.setBundle(null);
+						}
+						else if ( isDirty() ) {
+							commitPages(true);
+							project.save(monitor);
+							SigilUI.runInUISync(new Runnable() {
+								public void run() {
+									editorDirtyStateChanged();
+								}								
+							});
+						}
+						
+						monitor.done();
+					} catch (CoreException e) {
+						throw new InvocationTargetException(e);
+					}
+				}
+			});
+		} catch (InvocationTargetException e) {
+			SigilCore.error("Failed to save " + project, e.getTargetException());
+		} catch (InterruptedException e) {
+			monitor.setCanceled(true);
+			return;
+		} finally {
+			saving = false;
+		}
+		monitor.done();		
+    }
+    
+	/* (non-Javadoc)
+     * @see org.eclipse.ui.forms.editor.FormEditor#addPages()
+     */
+    @Override
+    protected void addPages() {
+        try {
+            addPage(new OverviewForm(this, project));
+			addPage(new ContentsForm(this, project));
+			dependenciesPageIndex = addPage(new DependenciesForm(this, project, unresolvedElements));
+			addPage(new ExportsForm(this, project));
+			textPage = new PropertiesForm(this, project);
+			addPage(textPage, getEditorInput());
+			setPartName(project.getSymbolicName());
+			
+			refreshTabImages();
+        }
+        catch (PartInitException e) {
+        	SigilCore.error( "Failed to build " + this, e );
+		}
+    }
+    
+    protected void refreshTabImages() {
+	    if(unresolvedElements.isEmpty()) {
+	    	setPageImage(dependenciesPageIndex, null);
+	    } else {
+	    	setPageImage(dependenciesPageIndex, errorImage);
+	    }
+    }
+    
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.EditorPart#doSaveAs()
+     */
+    @Override
+    public void doSaveAs() {
+    	// save as not allowed
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed()
+     */
+    @Override
+    public boolean isSaveAsAllowed() {
+        return false;
+    }
+    
+    @Override
+    public void dispose() {
+    	ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+    	errorImage.dispose();
+    	super.dispose();
+    }
+
+	public void resourceChanged(IResourceChangeEvent event) {
+		IResourceDelta delta = event.getDelta();
+		final IFile editorFile = ((IFileEditorInput) getEditorInput()).getFile();
+		try {
+			delta.accept(new IResourceDeltaVisitor() {
+				public boolean visit(IResourceDelta delta) throws CoreException {
+					int kind = delta.getKind();
+					IResource resource = delta.getResource();
+					if(resource instanceof IProject) {
+						if(!editorFile.getProject().equals(resource)) {
+							return false;
+						}
+						if(kind == IResourceDelta.CHANGED && (delta.getFlags() & IResourceDelta.MARKERS) > 0) {
+							loadUnresolvedDependencies();
+							refreshAllPages();
+						}
+						return true;
+					}
+					
+					if(resource instanceof IFile) {
+						IFile affectedFile = (IFile) resource;
+							if(affectedFile.equals(editorFile)) {
+							switch (kind) {
+							case IResourceDelta.REMOVED:
+								close(false);
+								break;
+							case IResourceDelta.CHANGED:
+								if(!saving) {
+									reload();
+								}
+								SigilUI.runInUISync( new Runnable() {
+									public void run() {
+										setPartName(project.getSymbolicName());								
+									} 									
+								} );
+								break;
+							}
+						}
+						// Recurse no more
+						return false;
+					}
+					
+					return true;
+				}
+			});
+		} catch (CoreException e) {
+			ErrorDialog.openError(getSite().getShell(), "Error", null, e.getStatus());
+		}
+	}
+	
+	protected void refreshAllPages() {
+		Runnable op = new Runnable() {
+			public void run() {
+				for(Iterator<?> iter = pages.iterator(); iter.hasNext(); ) {
+					IFormPage page = (IFormPage) iter.next();
+					if(page != null) {
+						IManagedForm managedForm = page.getManagedForm();
+						if(managedForm != null) {
+							managedForm.refresh();
+							IFormPart[] parts = managedForm.getParts();
+							for (IFormPart part : parts) {
+								part.refresh();
+							}
+						}
+					}
+				}
+				firePropertyChange(IEditorPart.PROP_DIRTY);
+				setPartName(project.getSymbolicName());
+				refreshTabImages();
+			}
+		};
+		getSite().getShell().getDisplay().syncExec(op);
+	}
+	
+	protected void reload() {
+		project.setBundle(null);
+		refreshAllPages();
+	}
+	
+	@Override
+	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+		super.init(site, input);
+		
+        try {
+			this.project = SigilCore.create(getProject());
+		} catch (CoreException e) {
+			throw new PartInitException("Error creating Sigil project", e);
+		}
+		
+    	ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
+		
+		if(input instanceof IFileEditorInput) {
+			try {
+				loadUnresolvedDependencies();
+			} catch (CoreException e) {
+				throw new PartInitException("Error retrieving dependency markers", e);
+			}
+		}
+	}
+
+	private void loadUnresolvedDependencies() throws CoreException {
+		ModelElementFactory factory = ModelElementFactory.getInstance();
+		IMarker[] markers = getProject().findMarkers(SigilCore.MARKER_UNRESOLVED_DEPENDENCY, true, IResource.DEPTH_ONE);
+		unresolvedElements.clear();
+		
+		for (IMarker marker : markers) {
+			String elementName = (String) marker.getAttribute("element");
+			String versionRangeStr = (String) marker.getAttribute("versionRange");
+			if(elementName != null && versionRangeStr != null) {
+				if(marker.getType().equals(SigilCore.MARKER_UNRESOLVED_IMPORT_PACKAGE)) {
+					IPackageImport pkgImport = factory.newModelElement(IPackageImport.class);
+					pkgImport.setPackageName(elementName);
+					pkgImport.setVersions(VersionRange.parseVersionRange(versionRangeStr));
+					unresolvedElements.add(pkgImport);
+				} else if(marker.getType().equals(SigilCore.MARKER_UNRESOLVED_REQUIRE_BUNDLE)) {
+					IRequiredBundle req = factory.newModelElement(IRequiredBundle.class);
+					req.setSymbolicName(elementName);
+					req.setVersions(VersionRange.parseVersionRange(versionRangeStr));
+					unresolvedElements.add(req);
+				}
+			}
+		}
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/SigilSourcePage.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/SigilSourcePage.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/SigilSourcePage.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/SigilSourcePage.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,115 @@
+/*
+ * 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.editors.project;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextInputListener;
+import org.eclipse.jface.text.ITextListener;
+import org.eclipse.jface.text.TextEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.ide.IDE;
+
+public class SigilSourcePage extends TextEditor implements IFormPage {
+	private final String id;
+	private int index;
+	private SigilProjectEditorPart editor;
+	private boolean active;
+	private Control control;
+	
+	public SigilSourcePage(String id) {
+		this.id = id;
+	}
+
+	@Override
+	public void createPartControl(Composite parent) {
+		super.createPartControl(parent);
+		Control[] children = parent.getChildren();
+		control = children[children.length - 1];
+		getSourceViewer().addTextListener( new ITextListener() {
+			public void textChanged(TextEvent event) {
+				if ( editor != null ) {
+					editor.refreshAllPages();
+				}
+			}
+		});
+		//PlatformUI.getWorkbench().getHelpSystem().setHelp(fControl, IHelpContextIds.MANIFEST_SOURCE_PAGE);
+	}
+
+	public void initialize(FormEditor editor) {
+		this.editor = (SigilProjectEditorPart) editor;
+	}
+
+	public FormEditor getEditor() {
+		return editor;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public int getIndex() {
+		return index;
+	}
+	
+	public void setIndex(int index) {
+		this.index = index;
+	}	
+
+	public boolean isActive() {
+		return active;
+	}
+
+	public void setActive(boolean active) {
+		this.active = active;
+	}
+	
+	public Control getPartControl() {
+		return control;
+	}
+
+	public boolean selectReveal(Object object) {
+		if (object instanceof IMarker) {
+			IDE.gotoMarker(this, (IMarker) object);
+			return true;
+		}
+		return false;
+	}
+
+	// static impls
+	public boolean isEditor() {
+		return true;
+	}
+
+	public boolean canLeaveThePage() {
+		return true;
+	}
+
+	public IManagedForm getManagedForm() {
+		// this is not a form
+		return null;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/TestingSection.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/TestingSection.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/TestingSection.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/TestingSection.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,96 @@
+/*
+ * 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.editors.project;
+
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.ui.form.SigilPage;
+import org.cauldron.sigil.ui.form.SigilSection;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.debug.ui.ILaunchShortcut;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.events.HyperlinkEvent;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.Hyperlink;
+import org.eclipse.ui.forms.widgets.Section;
+
+public class TestingSection extends SigilSection {
+	
+	public TestingSection(SigilPage page, Composite parent, ISigilProjectModel project) throws CoreException {
+		super( page, parent, project );
+	}    
+
+    protected void createSection(Section section,FormToolkit toolkit ) {
+        setTitle("Testing");
+        
+		Composite body = createTableWrapBody(1, toolkit);
+
+        toolkit.createLabel( body, "Test this project by launching a separate Newton application:" );
+        
+        Hyperlink launch = toolkit.createHyperlink( body, "Launch a newton container", SWT.NULL );
+        launch.setHref( "launchShortcut.run.org.cauldron.sigil.launching.shortcut" );
+        launch.addHyperlinkListener(this);
+        
+        Hyperlink debug = toolkit.createHyperlink( body, "Debug a newton container", SWT.NULL );
+        debug.setHref( "launchShortcut.debug.org.cauldron.sigil.launching.shortcut" );
+        debug.addHyperlinkListener(this);
+    }
+
+	public void linkActivated(HyperlinkEvent e) {
+		String href = (String) e.getHref();
+		if (href.startsWith("launchShortcut.")) { //$NON-NLS-1$
+			href = href.substring(15);
+			int index = href.indexOf('.');
+			if (index < 0)
+				return;  // error.  Format of href should be launchShortcut.<mode>.<launchShortcutId>
+			String mode = href.substring(0, index);
+			String id = href.substring(index + 1); 
+
+			//getEditor().doSave(null);
+			
+			IExtensionRegistry registry = Platform.getExtensionRegistry();
+			IConfigurationElement[] elements = registry.getConfigurationElementsFor("org.eclipse.debug.ui.launchShortcuts"); //$NON-NLS-1$
+			for (int i = 0; i < elements.length; i++) {
+				if (id.equals(elements[i].getAttribute("id"))) //$NON-NLS-1$
+					try {
+						ILaunchShortcut shortcut = (ILaunchShortcut)elements[i].createExecutableExtension("class"); //$NON-NLS-1$
+						// preLaunch();
+						shortcut.launch(new StructuredSelection(getLaunchObject()), mode);
+					} catch (CoreException e1) {
+						e1.printStackTrace();
+					}
+			}
+		}
+	}
+
+	private Object getLaunchObject() {
+		return getProjectModel().getProject();
+	}
+
+	public void linkEntered(HyperlinkEvent e) {
+	}
+
+	public void linkExited(HyperlinkEvent e) {
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ToolsSection.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ToolsSection.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ToolsSection.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/ToolsSection.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,82 @@
+/*
+ * 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.editors.project;
+
+import org.cauldron.sigil.actions.PruneProjectDependenciesAction;
+import org.cauldron.sigil.actions.ResolveProjectDependenciesAction;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.ui.form.SigilPage;
+import org.cauldron.sigil.ui.form.SigilSection;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.events.HyperlinkEvent;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.Hyperlink;
+import org.eclipse.ui.forms.widgets.Section;
+
+public class ToolsSection extends SigilSection {
+	
+	public ToolsSection(SigilPage page, Composite parent, ISigilProjectModel project) throws CoreException {
+		super( page, parent, project );
+	}    
+
+    protected void createSection(Section section,FormToolkit toolkit ) {
+        setTitle("Tools");
+        
+		Composite body = createTableWrapBody(1, toolkit);
+
+        toolkit.createLabel( body, "Tools to help manage this project:" );
+        
+        Hyperlink launch = toolkit.createHyperlink( body, "Resolve missing dependencies", SWT.NULL );
+        launch.setHref( "resolve" );
+        launch.addHyperlinkListener(this);
+        
+        Hyperlink debug = toolkit.createHyperlink( body, "Prune unused dependencies", SWT.NULL );
+        debug.setHref( "prune" );
+        debug.addHyperlinkListener(this);
+    }
+
+	public void linkActivated(HyperlinkEvent e) {
+		String href = (String) e.getHref();
+		if ( "resolve".equals( href ) ) {
+			handleResolve();
+		}
+		else if ( "prune".equals( href ) ) {
+			handlePrune();
+		}
+	}
+
+	private void handlePrune() {
+		new PruneProjectDependenciesAction(getProjectModel()).run();
+	}
+
+	private void handleResolve() {
+		final ISigilProjectModel project = getProjectModel();
+		new ResolveProjectDependenciesAction(project, true).run();
+	}
+
+	public void linkEntered(HyperlinkEvent e) {
+	}
+
+	public void linkExited(HyperlinkEvent e) {
+	}
+	
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/VersionRangeComponent.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/VersionRangeComponent.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/VersionRangeComponent.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/VersionRangeComponent.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,251 @@
+/*
+ * 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.editors.project;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.cauldron.sigil.model.common.VersionRange;
+import org.cauldron.sigil.ui.util.IValidationListener;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+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.Label;
+import org.eclipse.swt.widgets.Text;
+import org.osgi.framework.Version;
+
+public class VersionRangeComponent extends Composite {
+	private VersionRange versions = VersionRange.ANY_VERSION;
+	
+	private Button specificButton;
+	
+	private Text specificText;
+	private Button rangeButton;
+	private Text minimumText;
+	private Text maximumText;
+	private Button minInclusiveButton;
+	private Button maxInclusiveButton;
+	
+	private Set<VersionsChangeListener> listeners = new HashSet<VersionsChangeListener>();
+	private Set<IValidationListener> validationListeners = new HashSet<IValidationListener>();
+	
+	public VersionRangeComponent(Composite parent, int style) {
+		super( parent, style );
+		createComponents(this);
+	}
+	
+	public void addVersionChangeListener(VersionsChangeListener listener) {
+		synchronized(listeners) {
+			listeners.add( listener );
+		}
+	}
+	
+	public void removeVersionChangeListener(VersionsChangeListener listener) {
+		synchronized(listeners) {
+			listeners.remove( listener );
+		}
+	}
+	
+	public void addValidationListener(IValidationListener listener) {
+		validationListeners.add(listener);
+	}
+	
+	public void removeValidationListener(IValidationListener listener) {
+		validationListeners.remove(listener);
+	}
+	
+	@Override
+	public void setEnabled(boolean enabled) {
+		super.setEnabled(enabled);
+		specificButton.setEnabled(enabled);
+		rangeButton.setEnabled(enabled);
+		if ( enabled ) {
+			specificButton.setSelection(versions.isPointVersion());
+			setSpecific();
+		}
+		else {
+			minimumText.setEnabled(enabled);
+			maximumText.setEnabled(enabled);
+			minInclusiveButton.setEnabled(enabled);
+			maxInclusiveButton.setEnabled(enabled);
+		}
+	}
+
+
+	public VersionRange getVersions() {
+		return versions;
+	}
+	
+	public void setVersions(VersionRange versions) {
+		this.versions = versions == null ? VersionRange.ANY_VERSION : versions;
+		updateFields();
+	}
+
+	private void updateFields() {
+		if ( versions.isPointVersion() ) {
+			specificButton.setSelection(true);
+			specificText.setText( versions.getCeiling() == VersionRange.INFINITE_VERSION ? "*" : versions.getFloor().toString() );
+		}
+		else {
+			rangeButton.setSelection( true );
+			minimumText.setText( versions.getFloor().toString() );
+			minInclusiveButton.setSelection( !versions.isOpenFloor() );
+			maximumText.setText( versions.getCeiling() == VersionRange.INFINITE_VERSION ? "*" : versions.getCeiling().toString() );
+			maxInclusiveButton.setSelection( !versions.isOpenCeiling() );
+		}
+		
+		setSpecific();		
+	}
+
+	private void createComponents(Composite body) {
+		setLayout( new GridLayout( 3, false ) );
+		
+		specificButton = new Button( body, SWT.RADIO );
+		specificButton.setText( "Specific:" );
+		specificButton.addSelectionListener( new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				setSpecific();
+			}			
+		});
+		
+		new Label( body, SWT.NONE ).setText("Version:");
+		
+		specificText = new Text( body, SWT.BORDER );
+		specificText.addKeyListener( new KeyAdapter() {
+			@Override
+			public void keyReleased(KeyEvent e) {
+				setVersions();
+			}			
+		});
+		
+		rangeButton = new Button( body, SWT.RADIO );
+		rangeButton.setText( "Range:" );
+		
+		new Label(body, SWT.NONE).setText("Minimum:");
+		
+		minimumText = new Text( body, SWT.BORDER );
+		minimumText.addKeyListener( new KeyAdapter() {
+			@Override
+			public void keyReleased(KeyEvent e) {
+				setVersions();
+			}			
+		});
+		
+		minInclusiveButton = new Button( body, SWT.CHECK );
+		minInclusiveButton.setText( "inclusive" );
+		minInclusiveButton.setSelection(true);
+		minInclusiveButton.addSelectionListener( new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				setVersions();
+			}
+		});
+		
+		new Label( body, SWT.NONE ).setText("Maximum:");
+		maximumText = new Text( body, SWT.BORDER );
+		maximumText.addKeyListener( new KeyAdapter() {
+			@Override
+			public void keyReleased(KeyEvent e) {
+				setVersions();
+			}			
+		});
+
+		maxInclusiveButton = new Button( body, SWT.CHECK );
+		maxInclusiveButton.setText( "inclusive" );
+		maxInclusiveButton.setSelection(false);
+		maxInclusiveButton.addSelectionListener( new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				setVersions();
+			}
+		});
+		
+		// Layout
+		specificButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1));
+		specificText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
+		rangeButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1));
+		minimumText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		maximumText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+
+		updateFields();
+	}
+	
+	private void setVersions() {
+		try {
+			if ( specificButton.getSelection() ) {
+				if ( "*".equals( specificText.getText() ) ) {
+					versions = VersionRange.ANY_VERSION;
+				}
+				else if ( specificText.getText().trim().length() == 0 ) {
+					versions = null;
+				}
+				else {
+					Version v = Version.parseVersion( specificText.getText().trim() );
+					versions = new VersionRange( false, v, v, false);
+				}
+			}
+			else {
+				Version min = Version.parseVersion( minimumText.getText() );
+				Version max = "*".equals( maximumText.getText() ) ? VersionRange.INFINITE_VERSION : Version.parseVersion( maximumText.getText() );
+				versions = new VersionRange( !minInclusiveButton.getSelection(), min, max, !maxInclusiveButton.getSelection() );
+			}
+			fireValidationMessage(null, IMessageProvider.NONE);
+		}
+		catch (IllegalArgumentException e) {
+			versions = null;
+			fireValidationMessage("Invalid version", IMessageProvider.ERROR);
+		}
+
+		fireVersionChange();
+	}
+	
+	private void fireVersionChange() {
+		synchronized( listeners ) {
+			for ( VersionsChangeListener l : listeners ) {
+				l.versionsChanged(versions);
+			}
+		}
+	}
+
+	private void fireValidationMessage(String message, int level) {
+		for (IValidationListener validationListener : validationListeners) {
+			validationListener.validationMessage(message, level);
+		}
+	}
+
+	private void setSpecific() {
+		boolean specific = specificButton.getSelection();
+		specificButton.setSelection(specific);
+		specificText.setEnabled(specific);
+		minimumText.setEnabled(!specific);
+		maximumText.setEnabled(!specific);
+		minInclusiveButton.setEnabled(!specific);
+		maxInclusiveButton.setEnabled(!specific);
+		setVersions();
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/VersionsChangeListener.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/VersionsChangeListener.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/VersionsChangeListener.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/VersionsChangeListener.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.editors.project;
+
+import org.cauldron.sigil.model.common.VersionRange;
+
+public interface VersionsChangeListener {
+	void versionsChanged(VersionRange range);
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/WrappedContentProposal.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/WrappedContentProposal.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/WrappedContentProposal.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/editors/project/WrappedContentProposal.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,62 @@
+/*
+ * 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.editors.project;
+
+import org.eclipse.jface.fieldassist.IContentProposal;
+
+public class WrappedContentProposal<T> implements IContentProposal {
+	
+	private final T element;
+	private final IElementDescriptor<? super T> descriptor;
+
+	private WrappedContentProposal(T element, IElementDescriptor<? super T> descriptor) {
+		this.element = element;
+		this.descriptor = descriptor;
+	}
+	
+	public static <T> WrappedContentProposal<T> newInstance(T element, IElementDescriptor<? super T> descriptor) {
+		return new WrappedContentProposal<T>(element, descriptor);
+	}
+
+	public String getContent() {
+		return descriptor.getName(element);
+	}
+
+	public int getCursorPosition() {
+		return 0;
+	}
+
+	public String getDescription() {
+		return null;
+	}
+
+	public String getLabel() {
+		return descriptor.getLabel(element);
+	}
+
+	public T getElement() {
+		return element;
+	}
+
+	@Override
+	public String toString() {
+		return getLabel();
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/IFormValueConverter.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/IFormValueConverter.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/IFormValueConverter.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/IFormValueConverter.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,25 @@
+/*
+ * 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.form;
+
+public interface IFormValueConverter {
+	String getLabel(Object value);
+	Object getValue(String label);
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/ISigilFormEntryListener.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/ISigilFormEntryListener.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/ISigilFormEntryListener.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/ISigilFormEntryListener.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,25 @@
+/*
+ * 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.form;
+
+public interface ISigilFormEntryListener {
+	void browseButtonSelected(SigilFormEntry form);
+	void textValueChanged(SigilFormEntry form);
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilFormEntry.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilFormEntry.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilFormEntry.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilFormEntry.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,173 @@
+/*
+ * 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.form;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+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.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.IFormColors;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+public class SigilFormEntry {
+	private static final IFormValueConverter NULL_DESCRIPTOR = new IFormValueConverter() {
+		public String getLabel(Object value) {
+			return (String) value;
+		}
+
+		public Object getValue(String label) {
+			return label;
+		}
+	};
+	
+	private Label lbl;
+	private Text txt;
+	private Button btn;
+	private IFormValueConverter descriptor;
+	private boolean freeText = true;
+	
+	private Object value;
+	private ISigilFormEntryListener listener;
+	
+	public SigilFormEntry(Composite parent, FormToolkit toolkit, String title) {
+		this(parent, toolkit, title, null, null);
+	}
+	
+	public SigilFormEntry(Composite parent, FormToolkit toolkit, String title, String browse, IFormValueConverter descriptor) {
+		this.descriptor = descriptor == null ? NULL_DESCRIPTOR : descriptor;
+		createComponent(parent, title, browse, toolkit);
+	}
+	
+	public void setFormEntryListener(ISigilFormEntryListener listener) {
+		this.listener = listener;
+	}
+	
+	public void setValue(Object value) {
+		this.value = value;
+		String text = descriptor.getLabel(value);
+		if ( text == null ) {
+			text = "";
+		}
+		txt.setText(text);
+		handleValueChanged();
+	}
+	
+	public Object getValue() {
+		return value;
+	}
+
+	public void setFreeText(boolean freeText) {
+		this.freeText = freeText;
+	}
+	
+	public void setEditable(boolean editable) {
+		lbl.setEnabled(editable);
+		txt.setEditable(editable);
+		if ( btn != null ) {
+			btn.setEnabled(editable);
+		}
+	}	
+		
+	private void createComponent(Composite parent, String title, String browse, FormToolkit toolkit) {
+		lbl = toolkit.createLabel(parent, title);
+		lbl.setForeground(toolkit.getColors().getColor(IFormColors.TITLE));
+		
+		txt = toolkit.createText(parent, "", SWT.SINGLE | SWT.BORDER);
+		txt.addKeyListener( new KeyAdapter() {
+			@Override
+			public void keyPressed(KeyEvent e) {
+				if ( freeText ) {
+					switch ( e.character ) {
+					case '\r': handleValueChanged(); 
+					}
+				}
+				else {
+					switch ( e.character ) {
+					case '\b': 
+						setValue(null); 
+						handleValueChanged(); 
+					default:
+						e.doit = false;
+						break;
+					}
+				}
+			}
+		});
+		txt.addFocusListener( new FocusAdapter() {
+			@Override
+			public void focusLost(FocusEvent e) {
+				handleValueChanged();
+			}
+		});
+		
+		if ( browse != null ) {
+			btn = toolkit.createButton(parent, browse, SWT.PUSH);
+			btn.addSelectionListener( new SelectionAdapter() {
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					handleBrowseSelected();
+				}
+			});
+		}
+		
+		fillIntoGrid(parent);
+	}
+
+	private void handleBrowseSelected() {
+		if ( listener != null ) {
+			listener.browseButtonSelected(this);
+		}
+	}
+
+	private void handleValueChanged() {
+		if ( freeText ) {
+			this.value = descriptor.getValue(txt.getText());
+		}
+		if ( listener != null ) {
+			listener.textValueChanged(this);
+		}
+	}
+
+	private void fillIntoGrid(Composite parent) {
+		if ( parent.getLayout() instanceof GridLayout ) {
+			GridLayout layout = (GridLayout) parent.getLayout();
+			
+			int cols = layout.numColumns;
+			
+			lbl.setLayoutData( new GridData(SWT.LEFT, SWT.CENTER, false, false) );
+			
+			if ( btn == null ) {
+				txt.setLayoutData( new GridData(SWT.FILL, SWT.CENTER, true, false, Math.max(1, cols - 1), 1 ) );
+			}
+			else {
+				txt.setLayoutData( new GridData(SWT.FILL, SWT.CENTER, true, false, Math.max(1, cols - 2), 1 ) );
+			}
+		}
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilFormEntryAdapter.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilFormEntryAdapter.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilFormEntryAdapter.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilFormEntryAdapter.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,28 @@
+/*
+ * 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.form;
+
+public class SigilFormEntryAdapter implements ISigilFormEntryListener{
+	public void browseButtonSelected(SigilFormEntry form) {
+	}
+
+	public void textValueChanged(SigilFormEntry form) {
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilPage.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilPage.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilPage.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilPage.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,31 @@
+/*
+ * 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.form;
+
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+
+public class SigilPage extends FormPage {
+
+	public SigilPage(FormEditor editor, String id, String title) {
+		super(editor, id, title);
+	}
+	
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilSection.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilSection.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilSection.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/form/SigilSection.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,150 @@
+/*
+ * 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.form;
+
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.pde.internal.ui.editor.FormLayoutFactory;
+import org.eclipse.pde.internal.ui.parts.FormEntry;
+import org.eclipse.pde.internal.ui.parts.IFormEntryListener;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.forms.IFormPart;
+import org.eclipse.ui.forms.IPartSelectionListener;
+import org.eclipse.ui.forms.SectionPart;
+import org.eclipse.ui.forms.events.HyperlinkEvent;
+import org.eclipse.ui.forms.widgets.ExpandableComposite;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.Section;
+import org.eclipse.ui.forms.widgets.TableWrapData;
+import org.eclipse.ui.forms.widgets.TableWrapLayout;
+
+@SuppressWarnings("restriction")
+public abstract class SigilSection extends SectionPart implements IFormEntryListener, IPartSelectionListener {
+
+	private SigilPage page;
+	private ISigilProjectModel project;
+	
+	public SigilSection(SigilPage page, Composite parent, ISigilProjectModel project) throws CoreException {
+		super(parent, page.getManagedForm().getToolkit(), ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED );
+		this.project = project;
+		this.page = page;
+		createSection( getSection(), page.getManagedForm().getToolkit() );		
+	}
+
+	public ISigilProjectModel getProjectModel() {
+		return project;
+	}
+	
+	public SigilPage getPage() {
+		return page;
+	}
+	
+	public void setExpanded( boolean expanded ) {
+		getSection().setExpanded(expanded);
+	}
+	
+	protected abstract void createSection(Section section,FormToolkit toolkit ) throws CoreException;
+	
+	protected void setTitle( String title ) {
+			Section section = getSection();
+	        section.setText( title );
+			section.setLayout(FormLayoutFactory.createClearTableWrapLayout(false, 1));
+			TableWrapData data = new TableWrapData(TableWrapData.FILL_GRAB);
+			section.setLayoutData(data);				
+	}
+	
+	protected void setMarker(String type, String message, int priority, int severity) throws CoreException {
+		IFileEditorInput file = (IFileEditorInput) getPage().getEditor().getEditorInput();
+		IMarker marker = file.getFile().createMarker(type);
+		marker.setAttribute( IMarker.MESSAGE, message );
+		marker.setAttribute(IMarker.PRIORITY, priority);
+		marker.setAttribute( IMarker.SEVERITY, severity );
+	}
+	
+	protected void clearMarkers() throws CoreException {
+		IFileEditorInput file = (IFileEditorInput) getPage().getEditor().getEditorInput();
+		file.getFile().deleteMarkers(null, true, IResource.DEPTH_INFINITE );
+	}
+	
+	protected Composite createTableWrapBody( int columns, FormToolkit toolkit ) {
+		Section section = getSection();
+        Composite client = toolkit.createComposite(section);
+        
+        TableWrapLayout layout = new TableWrapLayout();
+        layout.leftMargin = layout.rightMargin = toolkit.getBorderStyle() != SWT.NULL ? 0 : 2;
+        layout.numColumns = columns;
+        client.setLayout(layout);
+        client.setLayoutData( new TableWrapData( TableWrapData.FILL_GRAB) );
+		
+        section.setClient(client);
+        
+        return client;
+	}
+	
+	protected Composite createGridBody( int columns, boolean columnsSameWidth, FormToolkit toolkit ) {
+		Section section = getSection();
+        Composite client = toolkit.createComposite(section);
+        
+		GridLayout layout = new GridLayout();
+		
+		layout.makeColumnsEqualWidth = columnsSameWidth;
+		layout.numColumns = columns;
+        client.setLayout(layout);
+        
+        client.setLayoutData( new TableWrapData( TableWrapData.FILL_GRAB) );
+		
+        section.setClient(client);
+        
+        return client;
+	}
+	
+	public void browseButtonSelected(FormEntry entry) {
+	}
+
+	public void focusGained(FormEntry entry) {
+	}
+
+	public void selectionChanged(FormEntry entry) {
+	}
+
+	public void textDirty(FormEntry entry) {
+	}
+
+	public void textValueChanged(FormEntry entry) {
+	}
+
+	public void linkActivated(HyperlinkEvent e) {
+	}
+
+	public void linkEntered(HyperlinkEvent e) {
+	}
+
+	public void linkExited(HyperlinkEvent e) {
+	}
+
+	public void selectionChanged(IFormPart part, ISelection selection) {
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/FileSystemRepositoryWizard.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/FileSystemRepositoryWizard.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/FileSystemRepositoryWizard.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/FileSystemRepositoryWizard.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,29 @@
+/*
+ * 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.internal.repository;
+
+import org.cauldron.sigil.ui.wizard.repository.RepositoryWizard;
+
+public class FileSystemRepositoryWizard extends RepositoryWizard {
+	@Override
+	public void addPages() {
+		addPage( new FileSystemRepositoryWizardPage(this) );
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/FileSystemRepositoryWizardPage.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/FileSystemRepositoryWizardPage.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/FileSystemRepositoryWizardPage.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/FileSystemRepositoryWizardPage.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,71 @@
+/*
+ * 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.internal.repository;
+
+import java.io.File;
+
+import org.cauldron.sigil.ui.wizard.repository.RepositoryWizard;
+import org.cauldron.sigil.ui.wizard.repository.RepositoryWizardPage;
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.DirectoryFieldEditor;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+
+public class FileSystemRepositoryWizardPage extends RepositoryWizardPage
+		implements IWizardPage {
+
+	private DirectoryFieldEditor dirEditor;
+
+	protected FileSystemRepositoryWizardPage(RepositoryWizard parent) {
+		super("File System Repository", parent);
+	}
+
+	@Override
+	public void createFieldEditors() {
+		dirEditor = new DirectoryFieldEditor("dir", "Directory:", getFieldEditorParent() );
+		dirEditor.getTextControl( getFieldEditorParent() ).addModifyListener( new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				checkPageComplete();
+			} 
+		} );
+		
+		addField( dirEditor );
+		addField(new BooleanFieldEditor("recurse", "Recurse:", getFieldEditorParent() ) );
+	}
+
+	@Override
+	protected void checkPageComplete() {
+		super.checkPageComplete();
+		if ( isPageComplete() ) {
+			setPageComplete(dirEditor.getStringValue().length() > 0);
+			if ( isPageComplete() ) {
+				if ( new File( dirEditor.getStringValue()).isDirectory() ) {
+					setPageComplete(true);
+					setErrorMessage(null);
+				}
+				else {
+					setPageComplete(false);
+					setErrorMessage("Invalid directory");
+				}
+			}
+		}
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/OSGiInstallRepositoryWizard.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/OSGiInstallRepositoryWizard.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/OSGiInstallRepositoryWizard.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.ui/src/org/cauldron/sigil/ui/internal/repository/OSGiInstallRepositoryWizard.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,29 @@
+/*
+ * 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.internal.repository;
+
+import org.cauldron.sigil.ui.wizard.repository.RepositoryWizard;
+
+public class OSGiInstallRepositoryWizard extends RepositoryWizard {
+	@Override
+	public void addPages() {
+		addPage( new OSGiInstallRepositoryWizardPage(this) );
+	}
+}