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 *******************************************************************************/
011package org.granite.builder.ui;
012
013import java.util.ArrayList;
014import java.util.HashSet;
015import java.util.Iterator;
016import java.util.List;
017import java.util.Set;
018
019import org.eclipse.core.runtime.IStatus;
020
021import org.eclipse.core.resources.IContainer;
022
023import org.eclipse.swt.SWT;
024import org.eclipse.swt.custom.BusyIndicator;
025import org.eclipse.swt.events.SelectionAdapter;
026import org.eclipse.swt.events.SelectionEvent;
027import org.eclipse.swt.layout.GridData;
028import org.eclipse.swt.widgets.Button;
029import org.eclipse.swt.widgets.Composite;
030import org.eclipse.swt.widgets.Control;
031import org.eclipse.swt.widgets.Shell;
032import org.eclipse.swt.widgets.Tree;
033
034import org.eclipse.jface.viewers.CheckStateChangedEvent;
035import org.eclipse.jface.viewers.CheckboxTreeViewer;
036import org.eclipse.jface.viewers.ICheckStateListener;
037import org.eclipse.jface.viewers.ILabelProvider;
038import org.eclipse.jface.viewers.ISelectionChangedListener;
039import org.eclipse.jface.viewers.IStructuredSelection;
040import org.eclipse.jface.viewers.ITreeContentProvider;
041import org.eclipse.jface.viewers.SelectionChangedEvent;
042import org.eclipse.jface.viewers.StructuredSelection;
043import org.eclipse.jface.viewers.ViewerFilter;
044import org.eclipse.jface.window.Window;
045
046import org.eclipse.ui.dialogs.NewFolderDialog;
047import org.eclipse.ui.dialogs.SelectionStatusDialog;
048
049import org.eclipse.ui.views.navigator.ResourceComparator;
050
051import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
052import 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")
059public 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}