001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 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 Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.workingsets;
011:
012: import java.util.Arrays;
013: import java.util.HashSet;
014:
015: import org.eclipse.core.runtime.Assert;
016: import org.eclipse.core.runtime.IAdaptable;
017:
018: import org.eclipse.core.resources.IProject;
019: import org.eclipse.core.resources.IResource;
020:
021: import org.eclipse.swt.SWT;
022: import org.eclipse.swt.events.ModifyEvent;
023: import org.eclipse.swt.events.ModifyListener;
024: import org.eclipse.swt.events.SelectionAdapter;
025: import org.eclipse.swt.events.SelectionEvent;
026: import org.eclipse.swt.layout.GridData;
027: import org.eclipse.swt.layout.GridLayout;
028: import org.eclipse.swt.widgets.Button;
029: import org.eclipse.swt.widgets.Composite;
030: import org.eclipse.swt.widgets.Label;
031: import org.eclipse.swt.widgets.Text;
032: import org.eclipse.swt.widgets.TreeItem;
033:
034: import org.eclipse.jface.dialogs.Dialog;
035: import org.eclipse.jface.resource.ImageDescriptor;
036: import org.eclipse.jface.viewers.DoubleClickEvent;
037: import org.eclipse.jface.viewers.IDoubleClickListener;
038: import org.eclipse.jface.viewers.ISelectionChangedListener;
039: import org.eclipse.jface.viewers.IStructuredContentProvider;
040: import org.eclipse.jface.viewers.IStructuredSelection;
041: import org.eclipse.jface.viewers.ITreeContentProvider;
042: import org.eclipse.jface.viewers.SelectionChangedEvent;
043: import org.eclipse.jface.viewers.TableViewer;
044: import org.eclipse.jface.viewers.TreeViewer;
045: import org.eclipse.jface.viewers.Viewer;
046: import org.eclipse.jface.viewers.ViewerFilter;
047: import org.eclipse.jface.wizard.WizardPage;
048:
049: import org.eclipse.ui.IWorkingSet;
050: import org.eclipse.ui.IWorkingSetManager;
051: import org.eclipse.ui.PlatformUI;
052: import org.eclipse.ui.dialogs.IWorkingSetPage;
053:
054: /**
055: * A tree viewer on the left is used to show the workspace content, a table viewer on the
056: * right is used to show the working set content. Buttons to move content from right
057: * to left and vice versa are available between the two viewers. A text field allows to
058: * set/change the working sets name.
059: *
060: * @since 3.1
061: */
062: public abstract class AbstractWorkingSetWizardPage extends WizardPage
063: implements IWorkingSetPage {
064:
065: private final class AddedElementsFilter extends ViewerFilter {
066:
067: /* (non-Javadoc)
068: * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
069: */
070: public boolean select(Viewer viewer, Object parentElement,
071: Object element) {
072: return !fSelectedElements.contains(element);
073: }
074:
075: }
076:
077: private Text fWorkingSetName;
078: private TreeViewer fTree;
079: private TableViewer fTable;
080: private ITreeContentProvider fTreeContentProvider;
081:
082: private boolean fFirstCheck;
083: private final HashSet fSelectedElements;
084: private IWorkingSet fWorkingSet;
085:
086: protected AbstractWorkingSetWizardPage(String pageName,
087: String title, ImageDescriptor titleImage) {
088: super (pageName, title, titleImage);
089:
090: fSelectedElements = new HashSet();
091: fFirstCheck = true;
092: }
093:
094: /**
095: * Configure the tree viewer used on the left side of the dialog.
096: *
097: * Implementors must set:
098: * <ul>
099: * <li>The content provider</li>
100: * <li>The label provider</li>
101: * <li>The viewers input</li>
102: * </ul>
103: * They may also set:
104: * <ul>
105: * <li>The viewer comparator</li>
106: * <li>Any viewer filter</li>
107: * <li>The selection</li>
108: * </ul>
109: *
110: * @param tree the tree to configure
111: */
112: protected abstract void configureTree(TreeViewer tree);
113:
114: /**
115: * Configure the table viewer used on the right side of the dialog.
116: *
117: * Implementors must set:
118: * <ul>
119: * <li>The label provider</li>
120: * </ul>
121: * They may also set:
122: * <ul>
123: * <li>The viewer comparator</li>
124: * </ul>
125: * They must not set:
126: * <ul>
127: * <li>The viewers content provider</li>
128: * <li>The viewers input</li>
129: * <li>Any viewer filter</li>
130: * </ul>
131: *
132: * @param table the table to configure
133: */
134: protected abstract void configureTable(TableViewer table);
135:
136: /**
137: * Returns the elements which are shown in the table initially. Return an empty
138: * array if the table should be empty. The given working set is the working set
139: * which will be configured by this dialog, or <b>null</b> if it does not yet
140: * exist.
141: *
142: * @param workingSet the working set to configure or <b>null</b> if not yet exist
143: * @return the elements to show in the table
144: */
145: protected abstract Object[] getInitialWorkingSetElements(
146: IWorkingSet workingSet);
147:
148: /*
149: * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
150: */
151: public void createControl(Composite parent) {
152: initializeDialogUnits(parent);
153:
154: Composite composite = new Composite(parent, SWT.NONE);
155: composite.setLayout(new GridLayout());
156: composite.setLayoutData(new GridData(
157: GridData.HORIZONTAL_ALIGN_FILL));
158: setControl(composite);
159:
160: Label label = new Label(composite, SWT.WRAP);
161: label
162: .setText(WorkingSetMessages.JavaWorkingSetPage_workingSet_name);
163: GridData gd = new GridData(GridData.GRAB_HORIZONTAL
164: | GridData.HORIZONTAL_ALIGN_FILL
165: | GridData.VERTICAL_ALIGN_CENTER);
166: label.setLayoutData(gd);
167:
168: fWorkingSetName = new Text(composite, SWT.SINGLE | SWT.BORDER);
169: fWorkingSetName.setLayoutData(new GridData(
170: GridData.GRAB_HORIZONTAL
171: | GridData.HORIZONTAL_ALIGN_FILL));
172: fWorkingSetName.addModifyListener(new ModifyListener() {
173: public void modifyText(ModifyEvent e) {
174: validateInput();
175: }
176: });
177:
178: Composite leftCenterRightComposite = new Composite(composite,
179: SWT.NONE);
180: GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
181: gridData.heightHint = convertHeightInCharsToPixels(20);
182: leftCenterRightComposite.setLayoutData(gridData);
183: GridLayout gridLayout = new GridLayout(3, false);
184: gridLayout.marginHeight = 0;
185: gridLayout.marginWidth = 0;
186: leftCenterRightComposite.setLayout(gridLayout);
187:
188: Composite leftComposite = new Composite(
189: leftCenterRightComposite, SWT.NONE);
190: gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
191: gridData.widthHint = convertWidthInCharsToPixels(40);
192: leftComposite.setLayoutData(gridData);
193: gridLayout = new GridLayout(1, false);
194: gridLayout.marginHeight = 0;
195: gridLayout.marginWidth = 0;
196: leftComposite.setLayout(gridLayout);
197:
198: Composite centerComposite = new Composite(
199: leftCenterRightComposite, SWT.NONE);
200: gridLayout = new GridLayout(1, false);
201: gridLayout.marginHeight = 0;
202: gridLayout.marginWidth = 0;
203: centerComposite.setLayout(gridLayout);
204: centerComposite.setLayoutData(new GridData(SWT.CENTER, SWT.TOP,
205: false, false));
206:
207: Composite rightComposite = new Composite(
208: leftCenterRightComposite, SWT.NONE);
209: gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
210: gridData.widthHint = convertWidthInCharsToPixels(40);
211: rightComposite.setLayoutData(gridData);
212: gridLayout = new GridLayout(1, false);
213: gridLayout.marginHeight = 0;
214: gridLayout.marginWidth = 0;
215: rightComposite.setLayout(gridLayout);
216:
217: createTree(leftComposite);
218: createTable(rightComposite);
219:
220: if (fWorkingSet != null)
221: fWorkingSetName.setText(fWorkingSet.getName());
222:
223: initializeSelectedElements();
224: validateInput();
225:
226: fTable.setInput(fSelectedElements);
227: fTable.refresh(true);
228: fTree.refresh(true);
229:
230: createButtonBar(centerComposite);
231:
232: fWorkingSetName.setFocus();
233: fWorkingSetName.setSelection(0, fWorkingSetName.getText()
234: .length());
235:
236: Dialog.applyDialogFont(composite);
237: }
238:
239: private void createTree(Composite parent) {
240:
241: Label label = new Label(parent, SWT.NONE);
242: label.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false,
243: false));
244: label
245: .setText(WorkingSetMessages.JavaWorkingSetPage_workspace_content);
246:
247: fTree = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL
248: | SWT.V_SCROLL | SWT.MULTI);
249: fTree.getControl().setLayoutData(
250: new GridData(SWT.FILL, SWT.FILL, true, true));
251:
252: fTree.addFilter(new AddedElementsFilter());
253: fTree.setUseHashlookup(true);
254:
255: configureTree(fTree);
256:
257: fTreeContentProvider = (ITreeContentProvider) fTree
258: .getContentProvider();
259: }
260:
261: private void createButtonBar(Composite parent) {
262: Label spacer = new Label(parent, SWT.NONE);
263: spacer.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true,
264: false));
265:
266: final Button addButton = new Button(parent, SWT.PUSH);
267: addButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true,
268: false));
269: addButton
270: .setText(WorkingSetMessages.JavaWorkingSetPage_add_button);
271: addButton.setEnabled(!fTree.getSelection().isEmpty());
272:
273: final Button addAllButton = new Button(parent, SWT.PUSH);
274: addAllButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP,
275: true, false));
276: addAllButton
277: .setText(WorkingSetMessages.JavaWorkingSetPage_addAll_button);
278: addAllButton.setEnabled(fTree.getTree().getItems().length > 0);
279:
280: final Button removeButton = new Button(parent, SWT.PUSH);
281: removeButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP,
282: true, false));
283: removeButton
284: .setText(WorkingSetMessages.JavaWorkingSetPage_remove_button);
285: removeButton.setEnabled(!fTable.getSelection().isEmpty());
286:
287: final Button removeAllButton = new Button(parent, SWT.PUSH);
288: removeAllButton.setLayoutData(new GridData(SWT.CENTER, SWT.TOP,
289: false, false));
290: removeAllButton
291: .setText(WorkingSetMessages.JavaWorkingSetPage_removeAll_button);
292: removeAllButton.setEnabled(!fSelectedElements.isEmpty());
293:
294: fTree
295: .addSelectionChangedListener(new ISelectionChangedListener() {
296: public void selectionChanged(
297: SelectionChangedEvent event) {
298: addButton.setEnabled(!event.getSelection()
299: .isEmpty());
300: }
301: });
302:
303: addButton.addSelectionListener(new SelectionAdapter() {
304: public void widgetSelected(SelectionEvent e) {
305: addTreeSelection();
306:
307: removeAllButton.setEnabled(true);
308: addAllButton
309: .setEnabled(fTree.getTree().getItems().length > 0);
310: }
311: });
312:
313: fTree.addDoubleClickListener(new IDoubleClickListener() {
314: public void doubleClick(DoubleClickEvent event) {
315: addTreeSelection();
316:
317: removeAllButton.setEnabled(true);
318: addAllButton
319: .setEnabled(fTree.getTree().getItems().length > 0);
320: }
321: });
322:
323: fTable
324: .addSelectionChangedListener(new ISelectionChangedListener() {
325: public void selectionChanged(
326: SelectionChangedEvent event) {
327: removeButton.setEnabled(!event.getSelection()
328: .isEmpty());
329: }
330: });
331:
332: removeButton.addSelectionListener(new SelectionAdapter() {
333: public void widgetSelected(SelectionEvent e) {
334: removeTableSelection();
335:
336: addAllButton.setEnabled(true);
337: removeAllButton
338: .setEnabled(!fSelectedElements.isEmpty());
339: }
340: });
341:
342: fTable.addDoubleClickListener(new IDoubleClickListener() {
343: public void doubleClick(DoubleClickEvent event) {
344: removeTableSelection();
345:
346: addAllButton.setEnabled(true);
347: removeAllButton
348: .setEnabled(!fSelectedElements.isEmpty());
349: }
350: });
351:
352: addAllButton.addSelectionListener(new SelectionAdapter() {
353: /* (non-Javadoc)
354: * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
355: */
356: public void widgetSelected(SelectionEvent e) {
357: TreeItem[] items = fTree.getTree().getItems();
358: for (int i = 0; i < items.length; i++) {
359: fSelectedElements.add(items[i].getData());
360: }
361: fTable.refresh();
362: fTree.refresh();
363:
364: addAllButton.setEnabled(false);
365: removeAllButton.setEnabled(true);
366: }
367: });
368:
369: removeAllButton.addSelectionListener(new SelectionAdapter() {
370: /* (non-Javadoc)
371: * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
372: */
373: public void widgetSelected(SelectionEvent e) {
374: fSelectedElements.clear();
375:
376: fTable.refresh();
377: fTree.refresh();
378:
379: removeAllButton.setEnabled(false);
380: addAllButton.setEnabled(true);
381: }
382: });
383:
384: }
385:
386: /**
387: * Moves selected elements in the tree into the table
388: */
389: private void addTreeSelection() {
390: IStructuredSelection selection = (IStructuredSelection) fTree
391: .getSelection();
392: fSelectedElements.addAll(selection.toList());
393: Object[] selectedElements = selection.toArray();
394: fTable.add(selectedElements);
395: fTree.remove(selectedElements);
396: fTable.setSelection(selection);
397: fTable.getControl().setFocus();
398: validateInput();
399: }
400:
401: /**
402: * Moves the selected elements in the table into the tree
403: */
404: private void removeTableSelection() {
405: IStructuredSelection selection = (IStructuredSelection) fTable
406: .getSelection();
407: fSelectedElements.removeAll(selection.toList());
408: Object[] selectedElements = selection.toArray();
409: fTable.remove(selectedElements);
410: try {
411: fTree.getTree().setRedraw(false);
412: for (int i = 0; i < selectedElements.length; i++) {
413: fTree.refresh(fTreeContentProvider
414: .getParent(selectedElements[i]), true);
415: }
416: } finally {
417: fTree.getTree().setRedraw(true);
418: }
419: fTree.setSelection(selection);
420: fTree.getControl().setFocus();
421: validateInput();
422: }
423:
424: private void createTable(Composite parent) {
425: Label label = new Label(parent, SWT.WRAP);
426: label
427: .setText(WorkingSetMessages.JavaWorkingSetPage_workingSet_content);
428: label
429: .setLayoutData(new GridData(SWT.FILL, SWT.TOP, true,
430: false));
431:
432: fTable = new TableViewer(parent, SWT.BORDER | SWT.H_SCROLL
433: | SWT.V_SCROLL | SWT.MULTI);
434:
435: GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
436: fTable.getControl().setLayoutData(gd);
437:
438: fTable.setUseHashlookup(true);
439:
440: configureTable(fTable);
441:
442: fTable.setContentProvider(new IStructuredContentProvider() {
443:
444: public Object[] getElements(Object inputElement) {
445: return fSelectedElements.toArray();
446: }
447:
448: public void dispose() {
449: }
450:
451: public void inputChanged(Viewer viewer, Object oldInput,
452: Object newInput) {
453: }
454:
455: });
456: }
457:
458: /*
459: * Implements method from IWorkingSetPage
460: */
461: public IWorkingSet getSelection() {
462: return fWorkingSet;
463: }
464:
465: /*
466: * Implements method from IWorkingSetPage
467: */
468: public void setSelection(IWorkingSet workingSet) {
469: Assert.isNotNull(workingSet, "Working set must not be null"); //$NON-NLS-1$
470: fWorkingSet = workingSet;
471: if (getContainer() != null && getShell() != null
472: && fWorkingSetName != null) {
473: fFirstCheck = false;
474: fWorkingSetName.setText(fWorkingSet.getName());
475: initializeSelectedElements();
476: validateInput();
477: }
478: }
479:
480: /*
481: * Implements method from IWorkingSetPage
482: */
483: public void finish() {
484: String workingSetName = fWorkingSetName.getText();
485: HashSet elements = fSelectedElements;
486: if (fWorkingSet == null) {
487: IWorkingSetManager workingSetManager = PlatformUI
488: .getWorkbench().getWorkingSetManager();
489: fWorkingSet = workingSetManager.createWorkingSet(
490: workingSetName, (IAdaptable[]) elements
491: .toArray(new IAdaptable[elements.size()]));
492: } else {
493: // Add inaccessible resources
494: IAdaptable[] oldItems = fWorkingSet.getElements();
495: HashSet closedWithChildren = new HashSet(elements.size());
496: for (int i = 0; i < oldItems.length; i++) {
497: IResource oldResource = null;
498: if (oldItems[i] instanceof IResource) {
499: oldResource = (IResource) oldItems[i];
500: } else {
501: oldResource = (IResource) oldItems[i]
502: .getAdapter(IResource.class);
503: }
504: if (oldResource != null
505: && oldResource.isAccessible() == false) {
506: IProject project = oldResource.getProject();
507: if (closedWithChildren.contains(project)
508: || elements.contains(project)) {
509: elements.add(oldItems[i]);
510: elements.remove(project);
511: closedWithChildren.add(project);
512: }
513: }
514: }
515: fWorkingSet.setName(workingSetName);
516: fWorkingSet.setElements((IAdaptable[]) elements
517: .toArray(new IAdaptable[elements.size()]));
518: }
519: }
520:
521: private void validateInput() {
522: String errorMessage = null;
523: String infoMessage = null;
524: String newText = fWorkingSetName.getText();
525:
526: if (newText.equals(newText.trim()) == false)
527: errorMessage = WorkingSetMessages.JavaWorkingSetPage_warning_nameWhitespace;
528: if (newText.equals("")) { //$NON-NLS-1$
529: if (fFirstCheck) {
530: setPageComplete(false);
531: fFirstCheck = false;
532: return;
533: } else
534: errorMessage = WorkingSetMessages.JavaWorkingSetPage_warning_nameMustNotBeEmpty;
535: }
536:
537: fFirstCheck = false;
538:
539: if (errorMessage == null
540: && (fWorkingSet == null || newText.equals(fWorkingSet
541: .getName()) == false)) {
542: IWorkingSet[] workingSets = PlatformUI.getWorkbench()
543: .getWorkingSetManager().getWorkingSets();
544: for (int i = 0; i < workingSets.length; i++) {
545: if (newText.equals(workingSets[i].getName())) {
546: errorMessage = WorkingSetMessages.JavaWorkingSetPage_warning_workingSetExists;
547: }
548: }
549: }
550:
551: if (!hasSelectedElement())
552: infoMessage = WorkingSetMessages.JavaWorkingSetPage_warning_resourceMustBeChecked;
553:
554: setMessage(infoMessage, INFORMATION);
555: setErrorMessage(errorMessage);
556: setPageComplete(errorMessage == null);
557: }
558:
559: private boolean hasSelectedElement() {
560: return !fSelectedElements.isEmpty();
561: }
562:
563: private void initializeSelectedElements() {
564: fSelectedElements.addAll(Arrays
565: .asList(getInitialWorkingSetElements(fWorkingSet)));
566: }
567:
568: }
|