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    }