| /******************************************************************************* |
| * 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; |
| |
| import java.util.TreeSet; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.resources.IWorkspaceDescription; |
| import org.eclipse.core.resources.IncrementalProjectBuilder; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.List; |
| import org.eclipse.swt.widgets.Text; |
| |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.preference.FieldEditor; |
| import org.eclipse.jface.preference.IntegerFieldEditor; |
| import org.eclipse.jface.preference.PreferencePage; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.jface.viewers.ILabelProvider; |
| import org.eclipse.jface.viewers.LabelProvider; |
| |
| import org.eclipse.ui.IWorkbench; |
| import org.eclipse.ui.IWorkbenchPreferencePage; |
| import org.eclipse.ui.actions.GlobalBuildAction; |
| import org.eclipse.ui.dialogs.ListSelectionDialog; |
| import org.eclipse.ui.help.WorkbenchHelp; |
| import org.eclipse.ui.internal.ide.IHelpContextIds; |
| import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; |
| |
| /** |
| * Page used to determine what order projects will be built in |
| * by the workspace. |
| */ |
| public class BuildOrderPreferencePage |
| extends PreferencePage |
| implements IWorkbenchPreferencePage { |
| |
| private IWorkbench workbench; |
| |
| private Button defaultOrderButton; |
| private Label buildLabel; |
| private List buildList; |
| private Composite buttonComposite; |
| private IntegerFieldEditor maxItersField; |
| |
| private String[] defaultBuildOrder; |
| private String[] customBuildOrder; |
| |
| //Boolean to indicate if we have looked it up |
| private boolean notCheckedBuildOrder = true; |
| |
| private final String UP_LABEL = IDEWorkbenchMessages.getString("BuildOrderPreference.up"); //$NON-NLS-1$ |
| private final String DOWN_LABEL = IDEWorkbenchMessages.getString("BuildOrderPreference.down"); //$NON-NLS-1$ |
| private final String ADD_LABEL = IDEWorkbenchMessages.getString("BuildOrderPreference.add"); //$NON-NLS-1$ |
| private final String REMOVE_LABEL = IDEWorkbenchMessages.getString("BuildOrderPreference.remove"); //$NON-NLS-1$ |
| private final String PROJECT_SELECTION_MESSAGE = IDEWorkbenchMessages.getString("BuildOrderPreference.selectOtherProjects"); //$NON-NLS-1$ |
| private final String DEFAULTS_LABEL = IDEWorkbenchMessages.getString("BuildOrderPreference.useDefaults"); //$NON-NLS-1$ |
| private final String LIST_LABEL = IDEWorkbenchMessages.getString("BuildOrderPreference.projectBuildOrder"); //$NON-NLS-1$ |
| private final String NOTE_LABEL = IDEWorkbenchMessages.getString("Preference.note"); //$NON-NLS-1$ |
| private final String REMOVE_MESSAGE = IDEWorkbenchMessages.getString("BuildOrderPreference.removeNote"); //$NON-NLS-1$ |
| |
| // whether or not the use defaults option was selected when Apply (or OK) was last pressed |
| // (or when the preference page was opened). This represents the most recent applied state. |
| private boolean defaultOrderInitiallySelected; |
| |
| private IPropertyChangeListener validityChangeListener = |
| new IPropertyChangeListener() { |
| public void propertyChange(PropertyChangeEvent event) { |
| if (event.getProperty().equals(FieldEditor.IS_VALID)) |
| updateValidState(); |
| } |
| }; |
| |
| /** |
| * Add another project to the list at the end. |
| */ |
| private void addProject() { |
| |
| String[] currentItems = this.buildList.getItems(); |
| |
| IProject[] allProjects = getWorkspace().getRoot().getProjects(); |
| |
| ILabelProvider labelProvider = new LabelProvider() { |
| public String getText(Object element) { |
| return (String) element; |
| } |
| }; |
| |
| SimpleListContentProvider contentsProvider = |
| new SimpleListContentProvider(); |
| contentsProvider.setElements( |
| sortedDifference(allProjects, currentItems)); |
| |
| ListSelectionDialog dialog = |
| new ListSelectionDialog( |
| this.getShell(), |
| this, |
| contentsProvider, |
| labelProvider, |
| PROJECT_SELECTION_MESSAGE); |
| |
| if (dialog.open() != Dialog.OK) |
| return; |
| |
| Object[] result = dialog.getResult(); |
| |
| int currentItemsLength = currentItems.length; |
| int resultLength = result.length; |
| String[] newItems = new String[currentItemsLength + resultLength]; |
| |
| System.arraycopy(currentItems, 0, newItems, 0, currentItemsLength); |
| System.arraycopy( |
| result, |
| 0, |
| newItems, |
| currentItemsLength, |
| result.length); |
| this.buildList.setItems(newItems); |
| } |
| |
| /** |
| * Updates the valid state of the page. |
| */ |
| private void updateValidState() { |
| setValid(maxItersField.isValid()); |
| } |
| |
| /** |
| * Create the list of build paths. If the current build order is empty make the list empty |
| * and disable it. |
| * @param composite - the parent to create the list in |
| * @param - enabled - the boolean that indcates if the list will be sensitive initially or not |
| */ |
| private void createBuildOrderList(Composite composite, boolean enabled) { |
| |
| Font font = composite.getFont(); |
| |
| this.buildLabel = new Label(composite, SWT.NONE); |
| this.buildLabel.setText(LIST_LABEL); |
| this.buildLabel.setEnabled(enabled); |
| GridData gridData = new GridData(); |
| gridData.horizontalAlignment = GridData.FILL; |
| gridData.horizontalSpan = 2; |
| this.buildLabel.setLayoutData(gridData); |
| this.buildLabel.setFont(font); |
| |
| this.buildList = |
| new List( |
| composite, |
| SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); |
| this.buildList.setEnabled(enabled); |
| GridData data = new GridData(); |
| //Set heightHint with a small value so the list size will be defined by |
| //the space available in the dialog instead of resizing the dialog to |
| //fit all the items in the list. |
| data.heightHint = buildList.getItemHeight(); |
| data.verticalAlignment = GridData.FILL; |
| data.horizontalAlignment = GridData.FILL; |
| data.grabExcessHorizontalSpace = true; |
| data.grabExcessVerticalSpace = true; |
| this.buildList.setLayoutData(data); |
| this.buildList.setFont(font); |
| } |
| /** |
| * Create the widgets that are used to determine the build order. |
| * |
| * @param parent the parent composite |
| * @return the new control |
| */ |
| protected Control createContents(Composite parent) { |
| |
| WorkbenchHelp.setHelp( |
| parent, |
| IHelpContextIds.BUILD_ORDER_PREFERENCE_PAGE); |
| |
| Font font = parent.getFont(); |
| |
| //The main composite |
| Composite composite = new Composite(parent, SWT.NULL); |
| GridLayout layout = new GridLayout(); |
| layout.numColumns = 2; |
| layout.marginWidth = 0; |
| layout.marginHeight = 0; |
| composite.setLayout(layout); |
| GridData data = new GridData(); |
| data.verticalAlignment = GridData.FILL; |
| data.horizontalAlignment = GridData.FILL; |
| composite.setLayoutData(data); |
| composite.setFont(font); |
| |
| String[] buildOrder = getCurrentBuildOrder(); |
| boolean useDefault = (buildOrder == null); |
| |
| createDefaultPathButton(composite, useDefault); |
| // List always enabled so user can scroll list. |
| // Only the buttons need to be disabled. |
| createBuildOrderList(composite, true); |
| createListButtons(composite, !useDefault); |
| |
| Composite noteComposite = |
| createNoteComposite(font, composite, NOTE_LABEL, REMOVE_MESSAGE); |
| GridData noteData = new GridData(); |
| noteData.horizontalSpan = 2; |
| noteComposite.setLayoutData(noteData); |
| |
| createSpacer(composite); |
| |
| createMaxIterationsField(composite); |
| |
| createSpacer(composite); |
| |
| if (useDefault) { |
| this.buildList.setItems(getDefaultProjectOrder()); |
| } else { |
| this.buildList.setItems(buildOrder); |
| } |
| |
| return composite; |
| |
| } |
| |
| /** |
| * Adds in a spacer. |
| * |
| * @param composite the parent composite |
| */ |
| private void createSpacer(Composite composite) { |
| Label spacer = new Label(composite, SWT.NONE); |
| GridData spacerData = new GridData(); |
| spacerData.horizontalSpan = 2; |
| spacer.setLayoutData(spacerData); |
| } |
| /** |
| * Create the default path button. Set it to selected based on the current workspace |
| * build path. |
| * @param composite org.eclipse.swt.widgets.Composite |
| * @param selected - the boolean that indicates the buttons initial state |
| */ |
| private void createDefaultPathButton( |
| Composite composite, |
| boolean selected) { |
| |
| defaultOrderInitiallySelected = selected; |
| |
| this.defaultOrderButton = new Button(composite, SWT.LEFT | SWT.CHECK); |
| this.defaultOrderButton.setSelection(selected); |
| this.defaultOrderButton.setText(DEFAULTS_LABEL); |
| SelectionListener listener = new SelectionAdapter() { |
| public void widgetSelected(SelectionEvent e) { |
| defaultsButtonSelected(defaultOrderButton.getSelection()); |
| } |
| }; |
| this.defaultOrderButton.addSelectionListener(listener); |
| |
| GridData gridData = new GridData(); |
| gridData.horizontalAlignment = GridData.FILL; |
| gridData.horizontalSpan = 2; |
| this.defaultOrderButton.setLayoutData(gridData); |
| this.defaultOrderButton.setFont(composite.getFont()); |
| } |
| /** |
| * Create the buttons used to manipulate the list. These Add, Remove and Move Up or Down |
| * the list items. |
| * @param composite the parent of the buttons |
| * @param enableComposite - boolean that indicates if a composite should be enabled |
| */ |
| private void createListButtons( |
| Composite composite, |
| boolean enableComposite) { |
| |
| Font font = composite.getFont(); |
| |
| //Create an intermeditate composite to keep the buttons in the same column |
| this.buttonComposite = new Composite(composite, SWT.RIGHT); |
| GridLayout layout = new GridLayout(); |
| layout.marginWidth = 0; |
| layout.marginHeight = 0; |
| this.buttonComposite.setLayout(layout); |
| GridData gridData = new GridData(); |
| gridData.verticalAlignment = GridData.FILL; |
| gridData.horizontalAlignment = GridData.FILL; |
| this.buttonComposite.setLayoutData(gridData); |
| this.buttonComposite.setFont(font); |
| |
| Button upButton = |
| new Button(this.buttonComposite, SWT.CENTER | SWT.PUSH); |
| upButton.setText(UP_LABEL); |
| upButton.setEnabled(enableComposite); |
| upButton.setFont(font); |
| setButtonLayoutData(upButton); |
| |
| SelectionListener listener = new SelectionAdapter() { |
| public void widgetSelected(SelectionEvent e) { |
| moveSelectionUp(); |
| } |
| }; |
| upButton.addSelectionListener(listener); |
| |
| Button downButton = |
| new Button(this.buttonComposite, SWT.CENTER | SWT.PUSH); |
| downButton.setText(DOWN_LABEL); |
| downButton.setEnabled(enableComposite); |
| listener = new SelectionAdapter() { |
| public void widgetSelected(SelectionEvent e) { |
| moveSelectionDown(); |
| } |
| }; |
| downButton.addSelectionListener(listener); |
| downButton.setFont(font); |
| setButtonLayoutData(downButton); |
| |
| Button addButton = |
| new Button(this.buttonComposite, SWT.CENTER | SWT.PUSH); |
| addButton.setText(ADD_LABEL); |
| listener = new SelectionAdapter() { |
| public void widgetSelected(SelectionEvent e) { |
| addProject(); |
| } |
| }; |
| addButton.addSelectionListener(listener); |
| addButton.setEnabled(enableComposite); |
| addButton.setFont(font); |
| setButtonLayoutData(addButton); |
| |
| Button removeButton = |
| new Button(this.buttonComposite, SWT.CENTER | SWT.PUSH); |
| removeButton.setText(REMOVE_LABEL); |
| listener = new SelectionAdapter() { |
| public void widgetSelected(SelectionEvent e) { |
| removeSelection(); |
| } |
| }; |
| removeButton.addSelectionListener(listener); |
| removeButton.setEnabled(enableComposite); |
| removeButton.setFont(font); |
| setButtonLayoutData(removeButton); |
| |
| } |
| |
| /** |
| * Create the field for the maximum number of iterations in the presence |
| * of cycles. |
| */ |
| private void createMaxIterationsField(Composite composite) { |
| Composite maxItersComposite = new Composite(composite, SWT.NONE); |
| GridData gd = new GridData(GridData.FILL_HORIZONTAL); |
| maxItersComposite.setLayoutData(gd); |
| maxItersComposite.setFont(composite.getFont()); |
| |
| maxItersField = new IntegerFieldEditor("", IDEWorkbenchMessages.getString("BuildOrderPreference.maxIterationsLabel"), maxItersComposite) { //$NON-NLS-1$ //$NON-NLS-2$ |
| protected void doLoad() { |
| Text text = getTextControl(); |
| if (text != null) { |
| int value = |
| getWorkspace().getDescription().getMaxBuildIterations(); |
| text.setText(Integer.toString(value)); |
| } |
| } |
| protected void doLoadDefault() { |
| Text text = getTextControl(); |
| if (text != null) { |
| int value = |
| ResourcesPlugin |
| .getPlugin() |
| .getPluginPreferences() |
| .getDefaultInt( |
| ResourcesPlugin.PREF_MAX_BUILD_ITERATIONS); |
| text.setText(Integer.toString(value)); |
| } |
| valueChanged(); |
| } |
| protected void doStore() { |
| // handled specially in performOK() |
| throw new UnsupportedOperationException(); |
| } |
| }; |
| maxItersField.setValidRange(1, Integer.MAX_VALUE); |
| maxItersField.setPreferencePage(this); |
| maxItersField.setPreferenceStore(getPreferenceStore()); |
| maxItersField.setPropertyChangeListener(validityChangeListener); |
| maxItersField.load(); |
| } |
| |
| /** |
| * The defaults button has been selected - update the other widgets as required. |
| * @param selected - whether or not the defaults button got selected |
| */ |
| private void defaultsButtonSelected(boolean selected) { |
| if (selected) { |
| setBuildOrderWidgetsEnablement(false); |
| //Cache the current value as the custom order |
| customBuildOrder = buildList.getItems(); |
| buildList.setItems(getDefaultProjectOrder()); |
| |
| } else { |
| setBuildOrderWidgetsEnablement(true); |
| String[] buildOrder = getCurrentBuildOrder(); |
| if (buildOrder == null) |
| buildList.setItems(getDefaultProjectOrder()); |
| else |
| buildList.setItems(buildOrder); |
| } |
| } |
| /** |
| * Get the project names for the current custom build |
| * order stored in the workspace description. |
| * |
| * @return java.lang.String[] or null if there is no setting |
| */ |
| private String[] getCurrentBuildOrder() { |
| if (notCheckedBuildOrder) { |
| customBuildOrder = getWorkspace().getDescription().getBuildOrder(); |
| notCheckedBuildOrder = false; |
| } |
| |
| return customBuildOrder; |
| } |
| /** |
| * Get the project names in the default build order |
| * based on the current Workspace settings. |
| * |
| * @return java.lang.String[] |
| */ |
| private String[] getDefaultProjectOrder() { |
| if (defaultBuildOrder == null) { |
| IWorkspace workspace = getWorkspace(); |
| IWorkspace.ProjectOrder projectOrder = |
| getWorkspace().computeProjectOrder( |
| workspace.getRoot().getProjects()); |
| IProject[] foundProjects = projectOrder.projects; |
| defaultBuildOrder = new String[foundProjects.length]; |
| int foundSize = foundProjects.length; |
| for (int i = 0; i < foundSize; i++) { |
| defaultBuildOrder[i] = foundProjects[i].getName(); |
| } |
| } |
| |
| return defaultBuildOrder; |
| } |
| /** |
| * Return the Workspace the build order is from. |
| * @return org.eclipse.core.resources.IWorkspace |
| */ |
| private IWorkspace getWorkspace() { |
| return ResourcesPlugin.getWorkspace(); |
| } |
| /** |
| * Return whether or not searchElement is in testArray. |
| */ |
| private boolean includes(String[] testArray, String searchElement) { |
| |
| for (int i = 0; i < testArray.length; i++) { |
| if (searchElement.equals(testArray[i])) |
| return true; |
| } |
| return false; |
| |
| } |
| /** |
| * See IWorkbenchPreferencePage. This class does nothing with he Workbench. |
| */ |
| public void init(IWorkbench workbench) { |
| this.workbench = workbench; |
| setPreferenceStore(workbench.getPreferenceStore()); |
| } |
| /** |
| * Move the current selection in the build list down. |
| */ |
| private void moveSelectionDown() { |
| |
| //Only do this operation on a single selection |
| if (this.buildList.getSelectionCount() == 1) { |
| int currentIndex = this.buildList.getSelectionIndex(); |
| if (currentIndex < this.buildList.getItemCount() - 1) { |
| String elementToMove = this.buildList.getItem(currentIndex); |
| this.buildList.remove(currentIndex); |
| this.buildList.add(elementToMove, currentIndex + 1); |
| this.buildList.select(currentIndex + 1); |
| } |
| } |
| } |
| /** |
| * Move the current selection in the build list up. |
| */ |
| private void moveSelectionUp() { |
| |
| int currentIndex = this.buildList.getSelectionIndex(); |
| |
| //Only do this operation on a single selection |
| if (currentIndex > 0 && this.buildList.getSelectionCount() == 1) { |
| String elementToMove = this.buildList.getItem(currentIndex); |
| this.buildList.remove(currentIndex); |
| this.buildList.add(elementToMove, currentIndex - 1); |
| this.buildList.select(currentIndex - 1); |
| } |
| } |
| /** |
| * Performs special processing when this page's Defaults button has been pressed. |
| * In this case change the defaultOrderButton to have it's selection set to true. |
| */ |
| protected void performDefaults() { |
| this.defaultOrderButton.setSelection(true); |
| defaultsButtonSelected(true); |
| maxItersField.loadDefault(); |
| super.performDefaults(); |
| } |
| /** |
| * OK has been pressed. If the defualt button is pressed then reset the build order to false; |
| * otherwise set it to the contents of the list. |
| */ |
| public boolean performOk() { |
| |
| String[] buildOrder = null; |
| boolean useDefault = defaultOrderButton.getSelection(); |
| |
| // if use defaults is turned off |
| if (!useDefault) |
| buildOrder = buildList.getItems(); |
| |
| //Get a copy of the description from the workspace, set the build order and then |
| //apply it to the workspace. |
| IWorkspaceDescription description = getWorkspace().getDescription(); |
| description.setBuildOrder(buildOrder); |
| description.setMaxBuildIterations(maxItersField.getIntValue()); |
| try { |
| getWorkspace().setDescription(description); |
| } catch (CoreException exception) { |
| //failed - return false |
| return false; |
| } |
| |
| // Perform auto-build if use default is off (because |
| // order could have changed) or if use default setting |
| // was changed. |
| if (!useDefault || (useDefault != defaultOrderInitiallySelected)) { |
| defaultOrderInitiallySelected = useDefault; |
| // If auto build is turned on, then do a global incremental |
| // build on all the projects. |
| if (ResourcesPlugin.getWorkspace().isAutoBuilding()) { |
| GlobalBuildAction action = |
| new GlobalBuildAction( |
| workbench.getActiveWorkbenchWindow(), |
| IncrementalProjectBuilder.INCREMENTAL_BUILD); |
| action.doBuild(); |
| } |
| } |
| |
| // Clear the custom build order cache |
| customBuildOrder = null; |
| |
| return true; |
| } |
| /** |
| * Remove the current selection in the build list. |
| */ |
| private void removeSelection() { |
| |
| this.buildList.remove(this.buildList.getSelectionIndices()); |
| } |
| /** |
| * Set the widgets that select build order to be enabled or diabled. |
| * @param value boolean |
| */ |
| private void setBuildOrderWidgetsEnablement(boolean value) { |
| |
| // Only change enablement of buttons. Leave list alone |
| // because you can't scroll it when disabled. |
| Control[] children = this.buttonComposite.getChildren(); |
| for (int i = 0; i < children.length; i++) { |
| children[i].setEnabled(value); |
| } |
| } |
| |
| /** |
| * Return a sorted array of the names of the projects that are already in the currently |
| * displayed names. |
| * @return String[] |
| * @param allProjects - all of the projects in the workspace |
| * @param currentlyDisplayed - the names of the projects already being displayed |
| */ |
| private String[] sortedDifference( |
| IProject[] allProjects, |
| String[] currentlyDisplayed) { |
| |
| TreeSet difference = new TreeSet(); |
| |
| for (int i = 0; i < allProjects.length; i++) { |
| if (!includes(currentlyDisplayed, allProjects[i].getName())) |
| difference.add(allProjects[i].getName()); |
| } |
| |
| String[] returnValue = new String[difference.size()]; |
| difference.toArray(returnValue); |
| return returnValue; |
| } |
| } |