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}