001: /*******************************************************************************
002: * Copyright (c) 2004, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM - Initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.ide.dialogs;
011:
012: import org.eclipse.core.resources.IProject;
013: import org.eclipse.core.resources.IncrementalProjectBuilder;
014: import org.eclipse.core.resources.ResourcesPlugin;
015: import org.eclipse.core.resources.WorkspaceJob;
016: import org.eclipse.core.runtime.CoreException;
017: import org.eclipse.core.runtime.IProgressMonitor;
018: import org.eclipse.core.runtime.IStatus;
019: import org.eclipse.core.runtime.Status;
020: import org.eclipse.core.runtime.SubProgressMonitor;
021: import org.eclipse.jface.dialogs.IDialogConstants;
022: import org.eclipse.jface.dialogs.IDialogSettings;
023: import org.eclipse.jface.dialogs.MessageDialog;
024: import org.eclipse.jface.viewers.CheckStateChangedEvent;
025: import org.eclipse.jface.viewers.CheckboxTableViewer;
026: import org.eclipse.jface.viewers.ICheckStateListener;
027: import org.eclipse.jface.viewers.Viewer;
028: import org.eclipse.jface.viewers.ViewerFilter;
029: import org.eclipse.swt.SWT;
030: import org.eclipse.swt.events.SelectionAdapter;
031: import org.eclipse.swt.events.SelectionEvent;
032: import org.eclipse.swt.events.SelectionListener;
033: import org.eclipse.swt.graphics.Point;
034: import org.eclipse.swt.layout.GridData;
035: import org.eclipse.swt.layout.GridLayout;
036: import org.eclipse.swt.widgets.Button;
037: import org.eclipse.swt.widgets.Composite;
038: import org.eclipse.swt.widgets.Control;
039: import org.eclipse.swt.widgets.Shell;
040: import org.eclipse.ui.IWorkbenchWindow;
041: import org.eclipse.ui.actions.GlobalBuildAction;
042: import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
043: import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
044: import org.eclipse.ui.internal.ide.actions.BuildUtilities;
045: import org.eclipse.ui.model.WorkbenchContentProvider;
046: import org.eclipse.ui.model.WorkbenchLabelProvider;
047:
048: /**
049: * Dialog that asks the user to confirm a clean operation, and to configure
050: * settings in relation to the clean. Clicking ok in the dialog will perform the
051: * clean operation.
052: *
053: * @since 3.0
054: */
055: public class CleanDialog extends MessageDialog {
056:
057: private static final String DIALOG_SETTINGS_SECTION = "CleanDialogSettings"; //$NON-NLS-1$
058: private static final String DIALOG_ORIGIN_X = "DIALOG_X_ORIGIN"; //$NON-NLS-1$
059: private static final String DIALOG_ORIGIN_Y = "DIALOG_Y_ORIGIN"; //$NON-NLS-1$
060: private static final String DIALOG_WIDTH = "DIALOG_WIDTH"; //$NON-NLS-1$
061: private static final String DIALOG_HEIGHT = "DIALOG_HEIGHT"; //$NON-NLS-1$
062: private static final String TOGGLE_SELECTED = "TOGGLE_SELECTED"; //$NON-NLS-1$
063: private static final String BUILD_NOW = "BUILD_NOW"; //$NON-NLS-1$
064:
065: private Button allButton, selectedButton, buildNowButton;
066:
067: private CheckboxTableViewer projectNames;
068:
069: private Object[] selection;
070:
071: private IWorkbenchWindow window;
072:
073: /**
074: * Gets the text of the clean dialog, depending on whether the
075: * workspace is currently in autobuild mode.
076: * @return String the question the user will be asked.
077: */
078: private static String getQuestion() {
079: boolean autoBuilding = ResourcesPlugin.getWorkspace()
080: .isAutoBuilding();
081: if (autoBuilding) {
082: return IDEWorkbenchMessages.CleanDialog_buildCleanAuto;
083: }
084: return IDEWorkbenchMessages.CleanDialog_buildCleanManual;
085: }
086:
087: /**
088: * Creates a new clean dialog.
089: *
090: * @param window the window to create it in
091: * @param selection the currently selected projects (may be empty)
092: */
093: public CleanDialog(IWorkbenchWindow window, IProject[] selection) {
094: super (window.getShell(),
095: IDEWorkbenchMessages.CleanDialog_title, null,
096: getQuestion(), QUESTION, new String[] {
097: IDialogConstants.OK_LABEL,
098: IDialogConstants.CANCEL_LABEL }, 0);
099: this .window = window;
100: this .selection = selection;
101: if (this .selection == null) {
102: this .selection = new Object[0];
103: }
104: }
105:
106: /*
107: * (non-Javadoc)
108: *
109: * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
110: */
111: protected void buttonPressed(int buttonId) {
112: final boolean cleanAll = allButton.getSelection();
113: final boolean buildAll = buildNowButton != null
114: && buildNowButton.getSelection();
115: super .buttonPressed(buttonId);
116: if (buttonId != IDialogConstants.OK_ID) {
117: return;
118: }
119: //save all dirty editors
120: BuildUtilities.saveEditors(null);
121: //batching changes ensures that autobuild runs after cleaning
122: WorkspaceJob cleanJob = new WorkspaceJob(
123: IDEWorkbenchMessages.CleanDialog_taskName) {
124: public boolean belongsTo(Object family) {
125: return ResourcesPlugin.FAMILY_MANUAL_BUILD
126: .equals(family);
127: }
128:
129: public IStatus runInWorkspace(IProgressMonitor monitor)
130: throws CoreException {
131: doClean(cleanAll, monitor);
132: //see if a build was requested
133: if (buildAll) {
134: //start an immediate workspace build
135: GlobalBuildAction build = new GlobalBuildAction(
136: window,
137: IncrementalProjectBuilder.INCREMENTAL_BUILD);
138: build.doBuild();
139: }
140: return Status.OK_STATUS;
141: }
142: };
143: cleanJob.setRule(ResourcesPlugin.getWorkspace()
144: .getRuleFactory().buildRule());
145: cleanJob.setUser(true);
146: cleanJob.schedule();
147: }
148:
149: /* (non-Javadoc)
150: * @see org.eclipse.jface.dialogs.MessageDialog#createCustomArea(org.eclipse.swt.widgets.Composite)
151: */
152: protected Control createCustomArea(Composite parent) {
153: Composite area = new Composite(parent, SWT.NONE);
154: GridLayout layout = new GridLayout();
155: layout.marginWidth = layout.marginHeight = 0;
156: layout.numColumns = 2;
157: layout.makeColumnsEqualWidth = true;
158: area.setLayout(layout);
159: area.setLayoutData(new GridData(GridData.FILL_BOTH));
160: SelectionListener updateEnablement = new SelectionAdapter() {
161: public void widgetSelected(SelectionEvent e) {
162: updateEnablement();
163: }
164: };
165:
166: IDialogSettings settings = getDialogSettings(DIALOG_SETTINGS_SECTION);
167: boolean selectSelectedButton = settings
168: .getBoolean(TOGGLE_SELECTED);
169: //first row
170: allButton = new Button(area, SWT.RADIO);
171: allButton
172: .setText(IDEWorkbenchMessages.CleanDialog_cleanAllButton);
173: allButton.setSelection(!selectSelectedButton);
174: allButton.addSelectionListener(updateEnablement);
175: selectedButton = new Button(area, SWT.RADIO);
176: selectedButton
177: .setText(IDEWorkbenchMessages.CleanDialog_cleanSelectedButton);
178: selectedButton.setSelection(selectSelectedButton);
179: selectedButton.addSelectionListener(updateEnablement);
180:
181: //second row
182: createProjectSelectionTable(area);
183:
184: //third row
185: //only prompt for immediate build if autobuild is off
186: if (!ResourcesPlugin.getWorkspace().isAutoBuilding()) {
187: buildNowButton = new Button(parent, SWT.CHECK);
188: buildNowButton
189: .setText(IDEWorkbenchMessages.CleanDialog_buildNowButton);
190: String buildNow = settings.get(BUILD_NOW);
191: buildNowButton.setSelection(buildNow == null
192: || Boolean.valueOf(buildNow).booleanValue());
193: buildNowButton.setLayoutData(new GridData(
194: GridData.HORIZONTAL_ALIGN_BEGINNING));
195: }
196: projectNames.getTable().setEnabled(selectSelectedButton);
197: return area;
198: }
199:
200: private void createProjectSelectionTable(Composite radioGroup) {
201: projectNames = CheckboxTableViewer.newCheckList(radioGroup,
202: SWT.BORDER);
203: projectNames.setContentProvider(new WorkbenchContentProvider());
204: projectNames.setLabelProvider(new WorkbenchLabelProvider());
205: projectNames.setComparator(new ResourceComparator(
206: ResourceComparator.NAME));
207: projectNames.addFilter(new ViewerFilter() {
208: private final IProject[] projectHolder = new IProject[1];
209:
210: public boolean select(Viewer viewer, Object parentElement,
211: Object element) {
212: if (!(element instanceof IProject)) {
213: return false;
214: }
215: IProject project = (IProject) element;
216: if (!project.isAccessible()) {
217: return false;
218: }
219: projectHolder[0] = project;
220: return BuildUtilities.isEnabled(projectHolder,
221: IncrementalProjectBuilder.CLEAN_BUILD);
222: }
223: });
224: projectNames.setInput(ResourcesPlugin.getWorkspace().getRoot());
225: GridData data = new GridData(GridData.FILL_BOTH);
226: data.horizontalSpan = 2;
227: data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
228: data.heightHint = IDialogConstants.ENTRY_FIELD_WIDTH;
229: projectNames.getTable().setLayoutData(data);
230: projectNames.setCheckedElements(selection);
231: //table is disabled to start because all button is selected
232: projectNames.getTable().setEnabled(
233: selectedButton.getSelection());
234: projectNames.addCheckStateListener(new ICheckStateListener() {
235: public void checkStateChanged(CheckStateChangedEvent event) {
236: selection = projectNames.getCheckedElements();
237: updateEnablement();
238: }
239: });
240: }
241:
242: /**
243: * Performs the actual clean operation.
244: * @param cleanAll if <code>true</true> clean all projects
245: * @param monitor The monitor that the build will report to
246: * @throws CoreException thrown if there is a problem from the
247: * core builder.
248: */
249: protected void doClean(boolean cleanAll, IProgressMonitor monitor)
250: throws CoreException {
251: if (cleanAll) {
252: ResourcesPlugin.getWorkspace().build(
253: IncrementalProjectBuilder.CLEAN_BUILD, monitor);
254: } else {
255: try {
256: monitor.beginTask(
257: IDEWorkbenchMessages.CleanDialog_taskName,
258: selection.length);
259: for (int i = 0; i < selection.length; i++) {
260: ((IProject) selection[i]).build(
261: IncrementalProjectBuilder.CLEAN_BUILD,
262: new SubProgressMonitor(monitor, 1));
263: }
264: } finally {
265: monitor.done();
266: }
267: }
268: }
269:
270: /**
271: * Updates the enablement of the dialog's ok button based
272: * on the current choices in the dialog.
273: */
274: protected void updateEnablement() {
275: projectNames.getTable().setEnabled(
276: selectedButton.getSelection());
277: boolean enabled = allButton.getSelection()
278: || selection.length > 0;
279: getButton(OK).setEnabled(enabled);
280: }
281:
282: /* (non-Javadoc)
283: * @see org.eclipse.jface.window.Window#close()
284: */
285: public boolean close() {
286: persistDialogSettings(getShell(), DIALOG_SETTINGS_SECTION);
287: return super .close();
288: }
289:
290: /* (non-Javadoc)
291: * @see org.eclipse.jface.window.Window#getInitialLocation(org.eclipse.swt.graphics.Point)
292: */
293: protected Point getInitialLocation(Point initialSize) {
294: Point p = getInitialLocation(DIALOG_SETTINGS_SECTION);
295: return p != null ? p : super .getInitialLocation(initialSize);
296: }
297:
298: /* (non-Javadoc)
299: * @see org.eclipse.jface.window.Window#getInitialSize()
300: */
301: protected Point getInitialSize() {
302: Point p = super .getInitialSize();
303: return getInitialSize(DIALOG_SETTINGS_SECTION, p);
304: }
305:
306: /**
307: * Returns the initial location which is persisted in the Ant UI Plugin dialog settings
308: * under the provided dialog setttings section name.
309: * If location is not persisted in the settings, the <code>null</code> is returned.
310: *
311: * @param dialogSettingsSectionName The name of the dialog settings section
312: * @return The initial location or <code>null</code>
313: */
314: public Point getInitialLocation(String dialogSettingsSectionName) {
315: IDialogSettings settings = getDialogSettings(dialogSettingsSectionName);
316: try {
317: int x = settings.getInt(DIALOG_ORIGIN_X);
318: int y = settings.getInt(DIALOG_ORIGIN_Y);
319: return new Point(x, y);
320: } catch (NumberFormatException e) {
321: }
322: return null;
323: }
324:
325: private IDialogSettings getDialogSettings(
326: String dialogSettingsSectionName) {
327: IDialogSettings settings = IDEWorkbenchPlugin.getDefault()
328: .getDialogSettings();
329: IDialogSettings section = settings
330: .getSection(dialogSettingsSectionName);
331: if (section == null) {
332: section = settings.addNewSection(dialogSettingsSectionName);
333: }
334: return section;
335: }
336:
337: /**
338: * Persists the location and dimensions of the shell and other user settings in the
339: * plugin's dialog settings under the provided dialog settings section name
340: *
341: * @param shell The shell whose geometry is to be stored
342: * @param dialogSettingsSectionName The name of the dialog settings section
343: */
344: private void persistDialogSettings(Shell shell,
345: String dialogSettingsSectionName) {
346: Point shellLocation = shell.getLocation();
347: Point shellSize = shell.getSize();
348: IDialogSettings settings = getDialogSettings(dialogSettingsSectionName);
349: settings.put(DIALOG_ORIGIN_X, shellLocation.x);
350: settings.put(DIALOG_ORIGIN_Y, shellLocation.y);
351: settings.put(DIALOG_WIDTH, shellSize.x);
352: settings.put(DIALOG_HEIGHT, shellSize.y);
353:
354: if (buildNowButton != null) {
355: settings.put(BUILD_NOW, buildNowButton.getSelection());
356: }
357: settings.put(TOGGLE_SELECTED, selectedButton.getSelection());
358: }
359:
360: /**
361: * Returns the initial size which is the larger of the <code>initialSize</code> or
362: * the size persisted in the Ant UI Plugin dialog settings under the provided dialog setttings section name.
363: * If no size is persisted in the settings, the <code>initialSize</code> is returned.
364: *
365: * @param initialSize The initialSize to compare against
366: * @param dialogSettingsSectionName The name of the dialog settings section
367: * @return the initial size
368: */
369: private Point getInitialSize(String dialogSettingsSectionName,
370: Point initialSize) {
371: IDialogSettings settings = getDialogSettings(dialogSettingsSectionName);
372: try {
373: int x, y;
374: x = settings.getInt(DIALOG_WIDTH);
375: y = settings.getInt(DIALOG_HEIGHT);
376: return new Point(Math.max(x, initialSize.x), Math.max(y,
377: initialSize.y));
378: } catch (NumberFormatException e) {
379: }
380: return initialSize;
381: }
382:
383: /*
384: * (non-Javadoc)
385: * @see org.eclipse.jface.dialogs.Dialog#isResizable()
386: */
387: protected boolean isResizable() {
388: return true;
389: }
390: }
|