Index: .project =================================================================== RCS file: /home/eclipse/org.eclipse.ui.ide/.project,v retrieving revision 1.11 diff -u -r1.11 .project --- .project 13 Feb 2004 19:49:38 -0000 1.11 +++ .project 4 Mar 2004 21:46:53 -0000 @@ -4,13 +4,8 @@ org.eclipse.core.resources - org.eclipse.core.runtime.compatibility - org.eclipse.help org.eclipse.jface - org.eclipse.ui - org.eclipse.ui.views org.eclipse.ui.workbench - org.eclipse.update.core Index: plugin.properties =================================================================== RCS file: /home/eclipse/org.eclipse.ui.ide/plugin.properties,v retrieving revision 1.12 diff -u -r1.12 plugin.properties --- plugin.properties 26 Feb 2004 17:59:39 -0000 1.12 +++ plugin.properties 4 Mar 2004 21:46:53 -0000 @@ -85,6 +85,7 @@ Views.IntroAdapter = Intro WorkingSets.resource = Resource +WorkingSets.project = Project AddBookmark.label=Add Boo&kmark... AddBookmark.tooltip=Add Bookmark... AddTask.label=Add &Task... Index: plugin.xml =================================================================== RCS file: /home/eclipse/org.eclipse.ui.ide/plugin.xml,v retrieving revision 1.35 diff -u -r1.35 plugin.xml --- plugin.xml 3 Mar 2004 15:10:48 -0000 1.35 +++ plugin.xml 4 Mar 2004 21:46:54 -0000 @@ -214,6 +214,14 @@ class="org.eclipse.ui.internal.ide.dialogs.WelcomeEditorInputFactory" id="org.eclipse.ui.internal.dialogs.WelcomeEditorInputFactory"> + + + + @@ -222,6 +230,12 @@ pageClass="org.eclipse.ui.internal.ide.dialogs.ResourceWorkingSetPage" icon="icons/full/obj16/workset.gif" id="org.eclipse.ui.resourceWorkingSetPage"> + + +ProjectWorkingSetPage.button.AllProjects= All &Projects --> +ProjectWorkingSetPage.button.Remove=<-- &Remove +ProjectWorkingSetPage.button.RemoveAll=<-- Remo&ve All +ProjectWorkingSetPage.button.Swap=<-- &Swap --> +ProjectWorkingSetPage.formatted.count={0,number,integer} of {1,number,integer} selected + WorkingSetSelectionDialog.title= Select Working Set WorkingSetSelectionDialog.title.multiSelect= Select Working Sets WorkingSetSelectionDialog.message= &Select a working set: @@ -1568,5 +1588,9 @@ DecorationScheduler.UpdatingTask=Updating DecorationScheduler.CalculatingTask=Calculating DecorationScheduler.DecoratingSubtask=Decorating {0} +<<<<<<< messages.properties +ProjectWorkingSetPage.18={0,number,integer} of {1,number,integer} selected +======= GlobalBuildAction.BuildRunningTitle=Build Is Running GlobalBuildAction.BuildRunningMessage=A build is currently running. Do you wish to cancel it? +>>>>>>> 1.15 Index: src/org/eclipse/ui/internal/ide/dialogs/PixelConverter.java =================================================================== RCS file: src/org/eclipse/ui/internal/ide/dialogs/PixelConverter.java diff -N src/org/eclipse/ui/internal/ide/dialogs/PixelConverter.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/ide/dialogs/PixelConverter.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.ide.dialogs; +/** + * @version 1.0 + * @author + */ +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.widgets.Control; + +import org.eclipse.jface.dialogs.Dialog; + +public class PixelConverter { + + private FontMetrics fFontMetrics; + + public PixelConverter(Control control) { + GC gc = new GC(control); + gc.setFont(control.getFont()); + fFontMetrics= gc.getFontMetrics(); + gc.dispose(); + } + + + /** + * @see DialogPage#convertHeightInCharsToPixels + */ + public int convertHeightInCharsToPixels(int chars) { + return Dialog.convertHeightInCharsToPixels(fFontMetrics, chars); + } + + /** + * @see DialogPage#convertHorizontalDLUsToPixels + */ + public int convertHorizontalDLUsToPixels(int dlus) { + return Dialog.convertHorizontalDLUsToPixels(fFontMetrics, dlus); + } + + /** + * @see DialogPage#convertVerticalDLUsToPixels + */ + public int convertVerticalDLUsToPixels(int dlus) { + return Dialog.convertVerticalDLUsToPixels(fFontMetrics, dlus); + } + + /** + * @see DialogPage#convertWidthInCharsToPixels + */ + public int convertWidthInCharsToPixels(int chars) { + return Dialog.convertWidthInCharsToPixels(fFontMetrics, chars); + } + +} + Index: src/org/eclipse/ui/internal/ide/dialogs/ProjectWorkingSetPage.java =================================================================== RCS file: src/org/eclipse/ui/internal/ide/dialogs/ProjectWorkingSetPage.java diff -N src/org/eclipse/ui/internal/ide/dialogs/ProjectWorkingSetPage.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/ide/dialogs/ProjectWorkingSetPage.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,652 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.ide.dialogs; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +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.Table; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.IWorkingSetManager; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.IWorkingSetPage; +import org.eclipse.ui.help.WorkbenchHelp; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.internal.IHelpContextIds; +import org.eclipse.ui.internal.WorkbenchPlugin; +import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages; +import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; +import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; +import org.eclipse.ui.internal.ide.model.ProjectWorkingSet; + + +/** + * ProjectWorkingSetPage provides an edit page for the New and Edit Working Set + * Wizard for "Project" workings sets. These working sets are for top-level + * projects and also allow nested definitions that include other existing + * Project working sets. + *

+ * This wizard can be included in the Eclipse UI by extending the + * org.eclipse.ui.workingSets extension point, as shown in the following + * example. + *

+ *  
+ *     
+ *     
+ *  
+ * 
+ * + * @since 3.0 + */ +public class ProjectWorkingSetPage extends WizardPage implements IWorkingSetPage { + static final int LIST_WIDTH_HINT = 200; + static final int LIST_HEIGHT_HINT = 250; + + private Text text; + private Label countLabel; + private TableViewer availableListViewer; + private TableViewer inclusionListViewer; + private ProjectWorkingSet workingSet; + private IAdaptable[] availableList; + private boolean firstCheck = true; + + + /** + * Creates a new instance of the receiver. + */ + public ProjectWorkingSetPage() { + super("projectWorkingSetPage", //$NON-NLS-1$ + IDEWorkbenchMessages.getString("ProjectWorkingSetPage.title"), //$NON-NLS-1$ + IDEInternalWorkbenchImages.getImageDescriptor( + IDEInternalWorkbenchImages.IMG_WIZBAN_NEWPRJ_WIZ)); + setDescription(IDEWorkbenchMessages.getString("ProjectWorkingSetPage.description")); //$NON-NLS-1$ + workingSet = new ProjectWorkingSet("", new IProject[0]); //$NON-NLS-1$ + } + + /** + * Get available projects and project-sets from workspace. + */ + private IAdaptable[] getAvailableList() { + List available = new ArrayList(); + List /* */ projects = getWorkspaceProjects(); + List /* */ sets = getWorkspaceProjectWorkingSets(); + available.addAll(sets); + available.addAll(projects); + IAdaptable[] target = new IAdaptable[available.size()]; + Iterator iter = available.iterator(); + int i = 0; + while (iter.hasNext()) { + target[i++] = (IAdaptable) iter.next(); + } + return target; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.dialogs.IWorkingSetPage#finish() + */ + public void finish() { + if (workingSet != null) + workingSet.setElements(getElementsFromViewer(inclusionListViewer)); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.dialogs.IWorkingSetPage#getSelection() + */ + public IWorkingSet getSelection() { + return workingSet; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.dialogs.IWorkingSetPage#setSelection(org.eclipse.ui.IWorkingSet) + */ + public void setSelection(IWorkingSet workingSet) { + if (workingSet == null) { + throw new IllegalArgumentException("Working set must not be null"); //$NON-NLS-1$ + } + this.workingSet = (ProjectWorkingSet) workingSet; + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) + */ + public void createControl(Composite parent) { + + Font font = parent.getFont(); + Composite composite= new Composite(parent, SWT.NULL); + composite.setLayout(new GridLayout()); + composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + setControl(composite); + + // TODO: fix help context + WorkbenchHelp.setHelp(composite, IHelpContextIds.WORKING_SET_RESOURCE_PAGE); + Label label = new Label(composite, SWT.WRAP); + label.setText(IDEWorkbenchMessages.getString("ProjectWorkingSetPage.message")); //$NON-NLS-1$ + GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER); + label.setLayoutData(data); + label.setFont(font); + + text = new Text(composite, SWT.SINGLE | SWT.BORDER); + text.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); + text.setFont(font); + text.addModifyListener( + new ModifyListener() { + public void modifyText(ModifyEvent e) { + validateInput(); + } + } + ); + text.setFocus(); + + Composite container = new Composite(composite, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 3; + layout.horizontalSpacing = 5; + layout.verticalSpacing = 10; + container.setLayout(layout); + + // left-side viewer + Object[] components = createViewerList(container, IDEWorkbenchMessages.getString("ProjectWorkingSetPage.label.available")); //$NON-NLS-1$ + ((Composite) components[0]).setLayoutData(new GridData(GridData.FILL_BOTH)); + availableListViewer = (TableViewer) components[1]; + // buttons + createButtonArea(container); + // right-side viewer + components = createViewerList(container, IDEWorkbenchMessages.getString("ProjectWorkingSetPage.label.included")); //$NON-NLS-1$ + ((Composite) components[0]).setLayoutData(new GridData(GridData.FILL_BOTH)); + inclusionListViewer = (TableViewer) components[1]; + + addViewerListeners(); + + setControl(composite); + Dialog.applyDialogFont(composite); + + initializeSets(); + if (workingSet != null) { + text.setText(workingSet.getName()); + } + setPageComplete(false); + } + + /* + * Add handlers for single and double click that add/remove projects from the table viewers + */ + private void addViewerListeners() { + availableListViewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + handleAdd(); + } + }); + + inclusionListViewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + handleRemove(); + } + }); + } + + + /** + * Create a Project/Set list viewer and return both the new Composite and the inner + * TableViewer in the Object array. This is used to created both the left and right + * side selection tables. + * + * @param parent should be the top-level control + * @param labelText a heading for the table viewer + */ + private Object[] createViewerList(Composite parent, String labelText) { + Object[] result = new Object[2]; + Composite container = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; + container.setLayout(layout); + container.setLayoutData(new GridData(GridData.FILL_BOTH)); + + Label label = new Label(container, SWT.NONE); + label.setText(labelText); //$NON-NLS-1$ + + Table table = new Table(container, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); + GridData gd = new GridData(GridData.FILL_BOTH); + gd.widthHint = LIST_WIDTH_HINT; + gd.heightHint = LIST_HEIGHT_HINT; + table.setLayoutData(gd); + + TableViewer viewer = new TableViewer(table); + viewer.setLabelProvider(new DefaultLabelProvider()); + viewer.setContentProvider(new ContentProvider()); + viewer.setInput(getWorkingSetManager()); + viewer.setSorter(new ProjectWorkingSetSorter()); + + result[0] = container; + result[1] = viewer; + return result; + } + + /** + * Provide Content for the list of available Projects and ProjectWorkingSets + */ + private class ContentProvider extends SimpleListContentProvider { + public Object[] getElements(Object element) { + return new Object[0]; + //return (availableList == null) ? getAvailableList() : availableList; + } + } + + /** + * Label provider for Project, ProjectWorkingSet, and ProjectWorkingSetReference + */ + class DefaultLabelProvider extends LabelProvider { + public Image getImage(Object element) { + if (element instanceof IProject) { + return PlatformUI.getWorkbench().getSharedImages().getImage(IDE.SharedImages.IMG_OBJ_PROJECT); + } else if (element instanceof ProjectWorkingSetReference || element instanceof ProjectWorkingSet) { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT); + } else { + return super.getImage(element); + } + } + public String getText(Object element) { + if (element instanceof IProject) { + IProject project = (IProject) element; + return project.getName(); + } else if (element instanceof ProjectWorkingSetReference) { + ProjectWorkingSetReference reference = (ProjectWorkingSetReference) element; + return reference.getName(); + } else if (element instanceof ProjectWorkingSet) { + ProjectWorkingSet set = (ProjectWorkingSet) element; + return set.getName(); + } else { + return super.getText(element); + } + } + } + + // center console buttons + private Composite createButtonArea(Composite parent) { + Composite comp = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginWidth = layout.marginHeight = 0; + comp.setLayout(layout); + comp.setLayoutData(new GridData(GridData.FILL_VERTICAL)); + + Composite container = new Composite(comp, SWT.NONE); + layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 30; + container.setLayout(layout); + GridData gd = new GridData(GridData.FILL_BOTH); + gd.widthHint = 100; + container.setLayoutData(gd); + + // All Projects + Button button = new Button(container, SWT.PUSH); + button.setText(IDEWorkbenchMessages.getString("ProjectWorkingSetPage.button.AllProjects")); //$NON-NLS-1$ + button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + handleAllProjects(); + } + }); + SWTUtil.setButtonDimensionHint(button); + + // Add + button = new Button(container, SWT.PUSH); + button.setText(IDEWorkbenchMessages.getString("ProjectWorkingSetPage.button.Add")); //$NON-NLS-1$ + button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + handleAdd(); + } + }); + SWTUtil.setButtonDimensionHint(button); + + // Remove + button = new Button(container, SWT.PUSH); + button.setText(IDEWorkbenchMessages.getString("ProjectWorkingSetPage.button.Remove")); //$NON-NLS-1$ + button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + handleRemove(); + } + }); + SWTUtil.setButtonDimensionHint(button); + + // Remove All + button = new Button(container, SWT.PUSH); + button.setText(IDEWorkbenchMessages.getString("ProjectWorkingSetPage.button.RemoveAll")); //$NON-NLS-1$ + button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + handleRemoveAll(); + } + }); + SWTUtil.setButtonDimensionHint(button); + + button = new Button(container, SWT.PUSH); + button.setText(IDEWorkbenchMessages.getString("ProjectWorkingSetPage.button.Swap")); //$NON-NLS-1$ + button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + handleSwap(); + } + }); + SWTUtil.setButtonDimensionHint(button); + + //new Label(container, SWT.NONE); // spacer + +/* build path limits us from supporting this feature... + button = new Button(container, SWT.PUSH); + button.setText("Shared Projects"); //$NON-NLS-1$ + button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + handleShared(); + } + }); + SWTUtil.setButtonDimensionHint(button); +*/ + // "X of Y selected" + countLabel = new Label(comp, SWT.NONE); + countLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER)); + return container; + } + + protected void pageChanged() { + updateCount(); + validateInput(); // sets page complete if OK + } + + /* + * extract items from a table viewer as IAdaptable(s) + */ + private static IAdaptable[] getElementsFromViewer(TableViewer viewer) { + TableItem[] items = viewer.getTable().getItems(); + ArrayList result = new ArrayList(); + for (int i = 0; i < items.length; i++) { + result.add(items[i].getData()); + } + return (IAdaptable[]) result.toArray(new IAdaptable[result.size()]); + } + + /* + * Update the "X of Y Selected" count indication text. + */ + private void updateCount() { + countLabel.setText( + java.text.MessageFormat.format(IDEWorkbenchMessages.getString("ProjectWorkingSetPage.formatted.count"), //$NON-NLS-1$ + new Object[] { + new Integer(inclusionListViewer.getTable().getItemCount()), + new Integer(availableList.length)})); + countLabel.getParent().layout(); + } + + private void handleAdd() { + IStructuredSelection ssel = (IStructuredSelection)availableListViewer.getSelection(); + if (ssel.size() > 0) { + Table table = availableListViewer.getTable(); + int index = table.getSelectionIndices()[0]; + availableListViewer.remove(ssel.toArray()); + inclusionListViewer.add(ssel.toArray()); + table.setSelection(index < table.getItemCount() ? index : table.getItemCount() -1); + pageChanged(); + } + } + + private void handleRemove() { + IStructuredSelection ssel = (IStructuredSelection)inclusionListViewer.getSelection(); + if (ssel.size() > 0) { + Table table = inclusionListViewer.getTable(); + int index = table.getSelectionIndices()[0]; + inclusionListViewer.remove(ssel.toArray()); + availableListViewer.add(ssel.toArray()); + table.setSelection(index < table.getItemCount() ? index : table.getItemCount() -1); + pageChanged(); + } + } + + private void handleRemoveAll() { + TableItem[] items = inclusionListViewer.getTable().getItems(); + + ArrayList data = new ArrayList(); + for (int i = 0; i < items.length; i++) { + data.add(items[i].getData()); + } + if (data.size() > 0) { + availableListViewer.add(data.toArray()); + inclusionListViewer.remove(data.toArray()); + pageChanged(); + } + } + + private void handleSwap() { + TableItem[] aItems = availableListViewer.getTable().getItems(); + TableItem[] iItems = inclusionListViewer.getTable().getItems(); + + ArrayList data = new ArrayList(); + for (int i = 0; i < iItems.length; i++) { + data.add(iItems[i].getData()); + } + if (data.size() > 0) { + availableListViewer.add(data.toArray()); + inclusionListViewer.remove(data.toArray()); + } + + data.clear(); + for (int i = 0; i < aItems.length; i++) { + data.add(aItems[i].getData()); + } + if (data.size() > 0) { + inclusionListViewer.add(data.toArray()); + availableListViewer.remove(data.toArray()); + } + pageChanged(); + } + + private void handleAllProjects() { + handleRemoveAll(); + ArrayList result = new ArrayList(); + List /* */ projects = getWorkspaceProjects(); + Iterator iter = projects.iterator(); + while (iter.hasNext()) { + IProject project = (IProject) iter.next(); + if (project.isOpen()) { + result.add(project); + } + } + if (result.size() > 0) { + inclusionListViewer.add(result.toArray()); + availableListViewer.remove(result.toArray()); + } + pageChanged(); + } +/* + * Team is not on our build path, so we can't support this + * feature from within this package. + * + private void handleShared() { + handleRemoveAll(false); + ArrayList result = new ArrayList(); + IProject[] projects = getWorkspaceProjects(); + for (int i = 0; i < projects.length; i++) { + IProject project = projects[i]; + if (project.isOpen() + && RepositoryProvider.isShared(project)) { + result.add(project); + } + } + if (result.size() > 0) { + inclusionListViewer.add(result.toArray()); + availableListViewer.remove(result.toArray()); + } + pageChanged(); + }*/ + + /** + * Initialize the list of available projects and if we are editing an + * existing working set, then also initialize the selected project list. + * Primes the Table Viewers, so we have to have UI componenets before + * calling this method. + */ + private void initializeSets() { + List available = Arrays.asList(getAvailableList()); + List elements = Arrays.asList(workingSet.getElements()); + if (elements.size() > 0) { + inclusionListViewer.add(elements.toArray()); + } + if (available.size() > 0) { + // source is "available"-"elements" + List source = new ArrayList(); + source.addAll(available); + source.removeAll(elements); + + availableList = adaptableArrayOfList (source); + availableListViewer.add(availableList); + } + updateCount(); + } + + /* + * Convert a list of adaptables to an array. Java compiler doesn't + * handle this very nicely. + */ + private IAdaptable[] adaptableArrayOfList (List list) { + IAdaptable[] result = new IAdaptable[list.size()]; + Iterator iter = list.iterator(); + int i = 0; + while (iter.hasNext()) { + IAdaptable element = (IAdaptable) iter.next(); + result[i++] = element; + } + return result; + } + /** + * Validates the working set name and the set of Projects and ProjectWorkingSet references. + * Working sets may not reference themselves; this is enforced by filtering the new working + * set name out of the "available" list and also by disallowing a new working set to have a + * name that already exists. + */ + private void validateInput() { + String errorMessage = null; //$NON-NLS-1$ + String newText = text.getText(); + + if (newText.equals(newText.trim()) == false) { + errorMessage = IDEWorkbenchMessages.getString("ProjectWorkingSetPage.warning.nameWhitespace"); //$NON-NLS-1$ + } else if (firstCheck) { + firstCheck = false; + return; + } + if (newText.equals("")) { //$NON-NLS-1$ + errorMessage = IDEWorkbenchMessages.getString("ProjectWorkingSetPage.warning.nameMustNotBeEmpty"); //$NON-NLS-1$ + } + if (errorMessage == null && (workingSet == null || newText.equals(workingSet.getName()) == false)) { + IWorkingSet[] workingSets = PlatformUI.getWorkbench().getWorkingSetManager().getWorkingSets(); + for (int i = 0; i < workingSets.length; i++) { + if (newText.equals(workingSets[i].getName())) { + errorMessage = IDEWorkbenchMessages.getString("ProjectWorkingSetPage.warning.workingSetExists"); //$NON-NLS-1$ + } + } + } + + // save working set name if we got this far + if (errorMessage == null) { + workingSet.setName(newText); + } + if (errorMessage == null && inclusionListViewer.getTable().getItemCount() == 0) { + errorMessage = IDEWorkbenchMessages.getString("ProjectWorkingSetPage.warning.projectMustBeIncluded"); //$NON-NLS-1$ + } + setErrorMessage(errorMessage); + setPageComplete(errorMessage == null); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean) + */ + public void setVisible(boolean visible) { + super.setVisible(visible); + setPageComplete(visible && inclusionListViewer.getTable().getItemCount() > 0); + } + + /* + * get the list of projects from the workspace + */ + protected List /* */ getWorkspaceProjects() { + IProject[] projects = getWorkspaceRoot().getProjects(); + return Arrays.asList(projects); + } + + /* + * Build a list of proxies to existing project working sets. + * If the current working set is already named, then it's own + * name will not appear in the list. + */ + protected List getWorkspaceProjectWorkingSets() { + IWorkingSet[] sets = getWorkingSetManager().getWorkingSets(); + List list = new ArrayList(); + for (int i=0; i + * Performs late binding containment check and detects and avoids + * circular references in working set references. + *

+ * @since 3.0 + * + */ +public class ProjectWorkingSetReference + implements + IPersistableElement, + IAdaptable, + IContainmentAdapter { + + static final String FACTORY_ID = "org.eclipse.ui.ide.ProjectWorkingSetReferenceFactory"; //$NON-NLS-1$ + protected String name; // name of the referenced project working set + + /** + * Creates a new project working set reference from a memento. + * + * @param name the name of the new working set. Should not have + * leading or trailing whitespace. + * @param memento persistence memento containing the elements of + * the working set. + */ + public ProjectWorkingSetReference(String name) { + this.name = name; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IPersistableElement#getFactoryId() + */ + public String getFactoryId() { + return FACTORY_ID; + } + /* (non-Javadoc) + * @see org.eclipse.ui.IPersistableElement#saveState(org.eclipse.ui.IMemento) + */ + public void saveState(IMemento memento) { + memento.putString(IWorkbenchConstants.TAG_NAME, name); + } + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) + */ + public Object getAdapter(Class adapter) { + if (adapter == IContainmentAdapter.class || adapter == IPersistableElement.class) { + return this; + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IContainmentAdapter#contains(java.lang.Object, java.lang.Object, int) + */ + public boolean contains(Object parentName, Object element, int flags) { + // TODO instantiate the reference ProjectWorkingSet if it exists and + // follow all references. The context is an array that holds the names of all + // previsouly visited Working Sets so that we don't get stuck in a cycle. + + if (element == null) return false; + + // accumulation list of all sub-sets already checked + List /* */ visited = new ArrayList(); + if (parentName != null) + visited.add(parentName); // don't recurse back to parent + + return contains(visited, this, element); + } + + /* + * Do all of the recursion by hand because we need to keep a "visited" list to avoid cycles. + */ + protected static boolean contains(List /* */ visited, IAdaptable container, Object element) { + if (container instanceof IProject && element instanceof IProject) { + // for project element, just compare the full project name + IProject wsProject = (IProject) container; + IProject project = (IProject) element; + return wsProject.getFullPath().equals(project.getFullPath()); + } else if (container instanceof ProjectWorkingSetReference){ + // get the real definition of ourself from the WorkingSetManager + ProjectWorkingSetReference reference = (ProjectWorkingSetReference) container; + ProjectWorkingSet self = (ProjectWorkingSet) WorkbenchPlugin.getDefault().getWorkingSetManager().getWorkingSet(reference.getName()); + if (self == null) return false; + if (visited.contains(self.getName())) return false; // deja vous + visited.add(self.getName()); // reminder to self...don't contemplate our own navel + // test our sub elements for containment, passing our visited context to avoid cycles + IAdaptable[] elements = self.getElements(); + for (int i=0; i < elements.length; i++) { + IAdaptable adaptable = (IAdaptable) elements[i]; + if (contains(visited, adaptable, element)) { + return true; + } + } + } + return false; + } + /** + * @return Returns the name. + */ + public String getName() { + return name; + } + /** + * @param name The name to set. + */ + public void setName(String name) { + this.name = name; + } + + public String toString() { + return getName(); + } + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (name == null) return super.equals(obj); + else return name.equals(obj.toString()); + } +} Index: src/org/eclipse/ui/internal/ide/dialogs/ProjectWorkingSetSorter.java =================================================================== RCS file: src/org/eclipse/ui/internal/ide/dialogs/ProjectWorkingSetSorter.java diff -N src/org/eclipse/ui/internal/ide/dialogs/ProjectWorkingSetSorter.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/ide/dialogs/ProjectWorkingSetSorter.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials! + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation +*************************************************************************/ +package org.eclipse.ui.internal.ide.dialogs; + +import java.text.Collator; + +import org.eclipse.core.resources.IProject; +import org.eclipse.jface.viewers.ViewerSorter; + +/** + * Sort elements of type IProject and others. IProjects are sorted + * as group first, and followed by others. + */ +public class ProjectWorkingSetSorter extends ViewerSorter { + /** + * + */ + public ProjectWorkingSetSorter() { + super(); + // TODO Auto-generated constructor stub + } + /** + * @param collator + */ + public ProjectWorkingSetSorter(Collator collator) { + super(collator); + // TODO Auto-generated constructor stub + } + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerSorter#category(java.lang.Object) + */ + public int category(Object element) { + return (element instanceof IProject) ? 1 : 0; + } +} Index: src/org/eclipse/ui/internal/ide/dialogs/SWTUtil.java =================================================================== RCS file: src/org/eclipse/ui/internal/ide/dialogs/SWTUtil.java diff -N src/org/eclipse/ui/internal/ide/dialogs/SWTUtil.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/ide/dialogs/SWTUtil.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.ide.dialogs; +/** + * @version 1.0 + * @author + */ +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.util.Assert; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DragSource; +import org.eclipse.swt.dnd.DropTarget; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Caret; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.ScrollBar; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Widget; + + +/** + * Utility class to simplify access to some SWT resources. + */ +public class SWTUtil { + + /** + * Returns the standard display to be used. The method first checks, if + * the thread calling this method has an associated disaply. If so, this + * display is returned. Otherwise the method returns the default display. + */ + public static Display getStandardDisplay() { + Display display; + display = Display.getCurrent(); + if (display == null) + display = Display.getDefault(); + return display; + } + + /** + * Returns the shell for the given widget. If the widget doesn't represent + * a SWT object that manage a shell, null is returned. + * + * @return the shell for the given widget + */ + public static Shell getShell(Widget widget) { + if (widget instanceof Control) + return ((Control) widget).getShell(); + if (widget instanceof Caret) + return ((Caret) widget).getParent().getShell(); + if (widget instanceof DragSource) + return ((DragSource) widget).getControl().getShell(); + if (widget instanceof DropTarget) + return ((DropTarget) widget).getControl().getShell(); + if (widget instanceof Menu) + return ((Menu) widget).getParent().getShell(); + if (widget instanceof ScrollBar) + return ((ScrollBar) widget).getParent().getShell(); + + return null; + } + + /** + * Returns a width hint for a button control. + */ + public static int getButtonWidthHint(Button button) { + if (button.getFont().equals(JFaceResources.getDefaultFont())) + button.setFont(JFaceResources.getDialogFont()); + PixelConverter converter= new PixelConverter(button); + int widthHint= converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); + return Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); + } + + /** + * Returns a height hint for a button control. + */ + public static int getButtonHeigthHint(Button button) { + if (button.getFont().equals(JFaceResources.getDefaultFont())) + button.setFont(JFaceResources.getDialogFont()); + PixelConverter converter= new PixelConverter(button); + return converter.convertVerticalDLUsToPixels(IDialogConstants.BUTTON_HEIGHT); + } + + /** + * Sets width and height hint for the button control. + * Note: This is a NOP if the button's layout data is not + * an instance of GridData. + * + * @param the button for which to set the dimension hint + */ + public static void setButtonDimensionHint(Button button) { + Assert.isNotNull(button); + Object gd = button.getLayoutData(); + if (gd instanceof GridData) { + ((GridData) gd).heightHint = getButtonHeigthHint(button); + ((GridData) gd).widthHint = getButtonWidthHint(button); + } + } + + public static void setDialogSize(Dialog dialog, int width, int height) { + Point computedSize = + dialog.getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT); + width = Math.max(computedSize.x, width); + height = Math.max(computedSize.y, height); + dialog.getShell().setSize(width, height); + } +} Index: src/org/eclipse/ui/internal/ide/model/ProjectWorkingSet.java =================================================================== RCS file: src/org/eclipse/ui/internal/ide/model/ProjectWorkingSet.java diff -N src/org/eclipse/ui/internal/ide/model/ProjectWorkingSet.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/ide/model/ProjectWorkingSet.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.ide.model; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.IContainmentAdapter; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IPersistableElement; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.internal.WorkingSet; +import org.eclipse.ui.internal.ide.dialogs.ProjectWorkingSetReference; + +/** + * A ProjectWorkingSet is a WorkingSet that holds projects and nested sub-sets. + *

+ * Each element of the ProjectWorkingSet implents the IAdaptable + * interface as needed by IWorkingSet. In addition, ProjectWorkingSet + * implements the IContainmentAdapter interface which allows it to + * answer questions about elements contained by the working set. This is + * what allows ProjectWorkingSet to hold projects nested within sub-sets without + * exposing that structure to clients of the IWorkingSet interface. + *

+ * The contains method is eventually called by the WorkingSetFilter + * classes within the workbench to decide if this WorkingSet contains projects + * that should be included or excluded by the filter. + *

+ * A ProjectWorkingSet defines a working set as a set of Projects and ProjectWorkingSets. + * Projects are the usual workspace projects. ProjectWorkingSets that are included in a + * definition are proxied by a ProjectWorkingSetReference and all usage of the working + * set is evaluated as lazily (late) as possible. The actual project working set that + * is refered to is not instantiated until the working set is used via the + * contains method. This allows the definition of referenced sub-sets to + * change and result in changed run-time behavior of the parent working set. + *

+ * ProjectWorkingSet(s) may contain references to other ProjectWorkingSet(s), which + * makes it possible to have circular references between sets. The only restrictions + * placed on defintions of ProjectWorkingSets is that they may not reference themselves. + * Circular references are detected at evaluation time in the contains + * method so that working sets are only tested once. It is important to allow these + * cycles because the definer of a working set has not control over what other sets + * may include her working sets. Also, because sets will be persisted, imported, and + * exported, these evaluations must be done as late as possible. References to sets + * that do not exist are quietly ignored at evaluation time. This ensures robust + * operation in environments of large working groups with hundreds of projects, + * tens of working sets, and frequent sharing/importing of working set definitions. + *

+ * ProjectWorkingSet(s) and their proxies are persistable via the IPersitableElement + * interface, which allows them to be saved as part of the existing WorkingSet + * infrastructure (@see WorkingSetManager). They are re-created from their persisted + * content via a ProjectWorkingSetFactory class that is registered in the + * plugin XML specification under the extension point "org.eclipse.ui.elementFactories". + * The ProjectWorkingSetReference also has a factory. + */ +public class ProjectWorkingSet extends WorkingSet implements IContainmentAdapter { + static final String FACTORY_ID = "org.eclipse.ui.ide.ProjectWorkingSetFactory"; //$NON-NLS-1$ + + /** + * Construct a ProjectWorkingSet from a previously persisted + * IMemento. This is meant to be called by an element + * factory that restores saved working set definitions. + * + * @param name the name of the new working set. Should not have + * leading or trailing whitespace. + * @param memento persistence memento containing the elements of + * the working set. + */ + public ProjectWorkingSet(String name, IMemento memento) { + super(name, memento); + } + + /** + * Construct a ProjectWorkingSet from it's name and the memebers of its set. + * Set members implement the IAdaptable interface, and presently + * include IProject and ProjectWorkingSetReference. + * + * @param name + * @param elements + */ + public ProjectWorkingSet(String name, IAdaptable[] elements) { + super(name, elements); + } + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkingSet#getId() + */ + public String getId() { + return "org.eclipse.ui.ide.projectWorkingSetPage"; //$NON-NLS-1$ + } + /* (non-Javadoc) + * @see org.eclipse.ui.IPersistableElement + */ + public String getFactoryId() { + return FACTORY_ID; + } + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkingSet#getImage() + */ + public ImageDescriptor getImage() { + return PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJ_ELEMENT); + } + + /** + * Returns the receiver if the requested type is either IWorkingSet + * or IPersistableElement or IContainmentAdapter. In the later case, + * we answer questions about sub-sets and projects contained within + * this working set. + * + * @param adapter the requested type + * @return the receiver if the requested type is either IWorkingSet + * or IPersistableElement or IContainmentAdapter. + */ + public Object getAdapter(Class adapter) { + if (adapter == IContainmentAdapter.class || adapter == IWorkingSet.class || adapter == IPersistableElement.class) { + return this; + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IContainmentAdapter#contains(java.lang.Object, java.lang.Object, int) + */ + public boolean contains(Object workingSetElement, Object element, int flags) { + if (element == null) return false; + if (workingSetElement == element) return true; + if (workingSetElement instanceof IProject) { + // for project element, just compare the full project name + IProject wsProject = (IProject) workingSetElement; + IProject project = (IProject) element; + return wsProject.getFullPath().equals(project.getFullPath()); + } else if (workingSetElement instanceof ProjectWorkingSetReference) { + // for workingset references, we ask the reference to answer the question + // because it needs to provide cycle detection. Pass the name of the top-level + // working set as a "context" so that the down-stream search can avoid cycling + // back into the parent. + ProjectWorkingSetReference reference = (ProjectWorkingSetReference) workingSetElement; + return reference.contains(getName(), element, flags); + } else { + // workingSetElement wasn't a type we understand + return false; + } + } +} Index: src/org/eclipse/ui/internal/ide/model/ProjectWorkingSetFactory.java =================================================================== RCS file: src/org/eclipse/ui/internal/ide/model/ProjectWorkingSetFactory.java diff -N src/org/eclipse/ui/internal/ide/model/ProjectWorkingSetFactory.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/ide/model/ProjectWorkingSetFactory.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.ide.model; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.ui.IElementFactory; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.internal.IWorkbenchConstants; + +/** + * A ProjectWorkingSetFactory is used to recreate a persisted ProjectWorkingSet + * object. + */ +public class ProjectWorkingSetFactory implements IElementFactory { + + /* (non-Javadoc) + * @see org.eclipse.ui.IElementFactory + */ + public IAdaptable createElement(IMemento memento) { + String workingSetName = memento.getString(IWorkbenchConstants.TAG_NAME); + String workingSetEditPageId = memento.getString(IWorkbenchConstants.TAG_EDIT_PAGE_ID); + + if (workingSetName == null) + return null; + + ProjectWorkingSet workingSet = new ProjectWorkingSet(workingSetName, memento); + if (workingSetEditPageId != null) { + workingSet.setId(workingSetEditPageId); + } + else { + // working sets created with builds 20020418 and 20020419 will not + // have an edit page id. fix this automatically. + workingSet.setId("org.eclipse.ui.ide.projectWorkingSetPage"); //$NON-NLS-1$ + } + return workingSet; + } +} Index: src/org/eclipse/ui/internal/ide/model/ProjectWorkingSetReferenceFactory.java =================================================================== RCS file: src/org/eclipse/ui/internal/ide/model/ProjectWorkingSetReferenceFactory.java diff -N src/org/eclipse/ui/internal/ide/model/ProjectWorkingSetReferenceFactory.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/ide/model/ProjectWorkingSetReferenceFactory.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.ide.model; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.ui.IElementFactory; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.internal.IWorkbenchConstants; +import org.eclipse.ui.internal.ide.dialogs.ProjectWorkingSetReference; + +/** + * A ProjectWorkingSetReferenceFactory is used to recreate a persisted + * ProjectWorkingSetReference object. + */ +public class ProjectWorkingSetReferenceFactory implements IElementFactory { + + /* (non-Javadoc) + * @see org.eclipse.ui.IElementFactory + */ + public IAdaptable createElement(IMemento memento) { + String workingSetName = memento.getString(IWorkbenchConstants.TAG_NAME); + + if (workingSetName == null) + return null; + + ProjectWorkingSetReference workingSet = new ProjectWorkingSetReference(workingSetName); + return workingSet; + } +}