001 /*******************************************************************************
002 * Copyright (c) 2000, 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 Corporation - initial API and implementation
010 *******************************************************************************/
011 package org.granite.builder.ui;
012
013 import java.util.ArrayList;
014 import java.util.HashSet;
015 import java.util.Iterator;
016 import java.util.List;
017 import java.util.Set;
018
019 import org.eclipse.core.runtime.IStatus;
020
021 import org.eclipse.core.resources.IContainer;
022
023 import org.eclipse.swt.SWT;
024 import org.eclipse.swt.custom.BusyIndicator;
025 import org.eclipse.swt.events.SelectionAdapter;
026 import org.eclipse.swt.events.SelectionEvent;
027 import org.eclipse.swt.layout.GridData;
028 import org.eclipse.swt.widgets.Button;
029 import org.eclipse.swt.widgets.Composite;
030 import org.eclipse.swt.widgets.Control;
031 import org.eclipse.swt.widgets.Shell;
032 import org.eclipse.swt.widgets.Tree;
033
034 import org.eclipse.jface.viewers.CheckStateChangedEvent;
035 import org.eclipse.jface.viewers.CheckboxTreeViewer;
036 import org.eclipse.jface.viewers.ICheckStateListener;
037 import org.eclipse.jface.viewers.ILabelProvider;
038 import org.eclipse.jface.viewers.ISelectionChangedListener;
039 import org.eclipse.jface.viewers.IStructuredSelection;
040 import org.eclipse.jface.viewers.ITreeContentProvider;
041 import org.eclipse.jface.viewers.SelectionChangedEvent;
042 import org.eclipse.jface.viewers.StructuredSelection;
043 import org.eclipse.jface.viewers.ViewerFilter;
044 import org.eclipse.jface.window.Window;
045
046 import org.eclipse.ui.dialogs.NewFolderDialog;
047 import org.eclipse.ui.dialogs.SelectionStatusDialog;
048
049 import org.eclipse.ui.views.navigator.ResourceComparator;
050
051 import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
052 import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
053
054 /**
055 * Add an option to enable/disable the new folder button.
056 * @author Franck WOLFF (Granite Data Services)
057 */
058 @SuppressWarnings("all")
059 public class MultipleFolderSelectionDialog extends SelectionStatusDialog implements ISelectionChangedListener {
060
061 private CheckboxTreeViewer fViewer;
062
063 private ILabelProvider fLabelProvider;
064 private ITreeContentProvider fContentProvider;
065 private List fFilters;
066
067 private Object fInput;
068 private Button fNewFolderButton;
069 private IContainer fSelectedContainer;
070 private Set fExisting;
071 private Object fFocusElement;
072
073 private boolean enableNewFolder = true;
074
075 public MultipleFolderSelectionDialog(Shell parent, ILabelProvider labelProvider, ITreeContentProvider contentProvider) {
076 this(parent, labelProvider, contentProvider, true);
077 }
078
079 public MultipleFolderSelectionDialog(Shell parent, ILabelProvider labelProvider, ITreeContentProvider contentProvider, boolean enableNewFolder) {
080 super(parent);
081 fLabelProvider= labelProvider;
082 fContentProvider= contentProvider;
083
084 setSelectionResult(null);
085 setStatusLineAboveButtons(true);
086
087 int shellStyle = getShellStyle();
088 setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
089
090 fExisting= null;
091 fFocusElement= null;
092 fFilters= null;
093
094 this.enableNewFolder = enableNewFolder;
095 }
096
097 public void setExisting(Object[] existing) {
098 fExisting= new HashSet();
099 for (int i= 0; i < existing.length; i++) {
100 fExisting.add(existing[i]);
101 }
102 }
103
104 /**
105 * Sets the tree input.
106 * @param input the tree input.
107 */
108 public void setInput(Object input) {
109 fInput = input;
110 }
111
112 /**
113 * Adds a filter to the tree viewer.
114 * @param filter a filter.
115 */
116 public void addFilter(ViewerFilter filter) {
117 if (fFilters == null)
118 fFilters = new ArrayList(4);
119
120 fFilters.add(filter);
121 }
122
123 /**
124 * Handles cancel button pressed event.
125 */
126 protected void cancelPressed() {
127 setSelectionResult(null);
128 super.cancelPressed();
129 }
130
131 /*
132 * @see SelectionStatusDialog#computeResult()
133 */
134 protected void computeResult() {
135 Object[] checked= fViewer.getCheckedElements();
136 if (fExisting == null) {
137 if (checked.length == 0) {
138 checked= null;
139 }
140 } else {
141 ArrayList res= new ArrayList();
142 for (int i= 0; i < checked.length; i++) {
143 Object elem= checked[i];
144 if (!fExisting.contains(elem)) {
145 res.add(elem);
146 }
147 }
148 if (!res.isEmpty()) {
149 checked= res.toArray();
150 } else {
151 checked= null;
152 }
153 }
154 setSelectionResult(checked);
155 }
156
157 private void access$superCreate() {
158 super.create();
159 }
160
161 /*
162 * @see Window#create()
163 */
164 public void create() {
165
166 BusyIndicator.showWhile(null, new Runnable() {
167 public void run() {
168 access$superCreate();
169
170 fViewer.setCheckedElements(
171 getInitialElementSelections().toArray());
172
173 fViewer.expandToLevel(2);
174 if (fExisting != null) {
175 for (Iterator iter= fExisting.iterator(); iter.hasNext();) {
176 fViewer.reveal(iter.next());
177 }
178 }
179
180 updateOKStatus();
181 }
182 });
183
184 }
185
186 /**
187 * Creates the tree viewer.
188 *
189 * @param parent the parent composite
190 * @return the tree viewer
191 */
192 protected CheckboxTreeViewer createTreeViewer(Composite parent) {
193 fViewer = new CheckboxTreeViewer(parent, SWT.BORDER);
194
195 fViewer.setContentProvider(fContentProvider);
196 fViewer.setLabelProvider(fLabelProvider);
197 fViewer.addCheckStateListener(new ICheckStateListener() {
198 public void checkStateChanged(CheckStateChangedEvent event) {
199 updateOKStatus();
200 }
201 });
202
203 fViewer.setComparator(new ResourceComparator(ResourceComparator.NAME));
204 if (fFilters != null) {
205 for (int i = 0; i != fFilters.size(); i++)
206 fViewer.addFilter((ViewerFilter) fFilters.get(i));
207 }
208
209 fViewer.setInput(fInput);
210
211 return fViewer;
212 }
213
214
215
216 /**
217 *
218 */
219 protected void updateOKStatus() {
220 computeResult();
221 if (getResult() != null) {
222 updateStatus(new StatusInfo());
223 } else {
224 updateStatus(new StatusInfo(IStatus.ERROR, "")); //$NON-NLS-1$
225 }
226 }
227
228 /* (non-Javadoc)
229 * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
230 */
231 protected Control createDialogArea(Composite parent) {
232 Composite composite = (Composite) super.createDialogArea(parent);
233
234 createMessageArea(composite);
235 CheckboxTreeViewer treeViewer = createTreeViewer(composite);
236
237 GridData data = new GridData(GridData.FILL_BOTH);
238 data.widthHint = convertWidthInCharsToPixels(60);
239 data.heightHint = convertHeightInCharsToPixels(18);
240
241 Tree treeWidget = treeViewer.getTree();
242 treeWidget.setLayoutData(data);
243 treeWidget.setFont(composite.getFont());
244
245 if (enableNewFolder) {
246 Button button = new Button(composite, SWT.PUSH);
247 button.setText(NewWizardMessages.MultipleFolderSelectionDialog_button);
248 button.addSelectionListener(new SelectionAdapter() {
249 public void widgetSelected(SelectionEvent event) {
250 newFolderButtonPressed();
251 }
252 });
253 button.setFont(composite.getFont());
254
255 fNewFolderButton= button;
256 }
257
258 treeViewer.addSelectionChangedListener(this);
259 if (fExisting != null) {
260 Object[] existing= fExisting.toArray();
261 treeViewer.setGrayedElements(existing);
262 setInitialSelections(existing);
263 }
264 if (fFocusElement != null) {
265 treeViewer.setSelection(new StructuredSelection(fFocusElement), true);
266 }
267 treeViewer.addCheckStateListener(new ICheckStateListener() {
268 public void checkStateChanged(CheckStateChangedEvent event) {
269 forceExistingChecked(event);
270 }
271 });
272
273 applyDialogFont(composite);
274 return composite;
275 }
276
277 protected void forceExistingChecked(CheckStateChangedEvent event) {
278 if (fExisting != null) {
279 Object elem= event.getElement();
280 if (fExisting.contains(elem)) {
281 fViewer.setChecked(elem, true);
282 }
283 }
284 }
285
286 private void updateNewFolderButtonState() {
287 if (enableNewFolder) {
288 IStructuredSelection selection= (IStructuredSelection) fViewer.getSelection();
289 fSelectedContainer= null;
290 if (selection.size() == 1) {
291 Object first= selection.getFirstElement();
292 if (first instanceof IContainer) {
293 fSelectedContainer= (IContainer) first;
294 }
295 }
296 fNewFolderButton.setEnabled(fSelectedContainer != null);
297 }
298 }
299
300 protected void newFolderButtonPressed() {
301 Object createdFolder= createFolder(fSelectedContainer);
302 if (createdFolder != null) {
303 CheckboxTreeViewer treeViewer= fViewer;
304 treeViewer.refresh(fSelectedContainer);
305 treeViewer.reveal(createdFolder);
306 treeViewer.setChecked(createdFolder, true);
307 treeViewer.setSelection(new StructuredSelection(createdFolder));
308 updateOKStatus();
309 }
310 }
311
312 protected Object createFolder(IContainer container) {
313 NewFolderDialog dialog= new NewFolderDialog(getShell(), container);
314 if (dialog.open() == Window.OK) {
315 return dialog.getResult()[0];
316 }
317 return null;
318 }
319
320 /* (non-Javadoc)
321 * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
322 */
323 public void selectionChanged(SelectionChangedEvent event) {
324 updateNewFolderButtonState();
325 }
326
327 public void setInitialFocus(Object focusElement) {
328 fFocusElement= focusElement;
329 }
330 }