1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.preferences;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.Hashtable;
16 import java.util.Iterator;
18 import java.util.StringTokenizer;
19 import java.util.Map.Entry;
21 import net.sourceforge.phpdt.core.IJavaProject;
22 import net.sourceforge.phpdt.core.JavaCore;
23 import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
24 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
26 import org.eclipse.core.resources.IncrementalProjectBuilder;
27 import org.eclipse.core.resources.ResourcesPlugin;
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.IStatus;
31 import org.eclipse.core.runtime.OperationCanceledException;
32 import org.eclipse.core.runtime.Status;
33 import org.eclipse.core.runtime.SubProgressMonitor;
34 import org.eclipse.core.runtime.jobs.Job;
35 import org.eclipse.jface.dialogs.IDialogConstants;
36 import org.eclipse.jface.dialogs.MessageDialog;
37 import org.eclipse.swt.SWT;
38 import org.eclipse.swt.events.ModifyEvent;
39 import org.eclipse.swt.events.ModifyListener;
40 import org.eclipse.swt.events.SelectionEvent;
41 import org.eclipse.swt.events.SelectionListener;
42 import org.eclipse.swt.layout.GridData;
43 import org.eclipse.swt.layout.GridLayout;
44 import org.eclipse.swt.widgets.Button;
45 import org.eclipse.swt.widgets.Combo;
46 import org.eclipse.swt.widgets.Composite;
47 import org.eclipse.swt.widgets.Control;
48 import org.eclipse.swt.widgets.Label;
49 import org.eclipse.swt.widgets.Shell;
50 import org.eclipse.swt.widgets.Text;
51 import org.eclipse.swt.widgets.Widget;
54 * Abstract options configuration block providing a general implementation for setting up
55 * an options configuration page.
59 public abstract class OptionsConfigurationBlock {
61 protected static class ControlData {
63 private String[] fValues;
65 public ControlData(String key, String[] values) {
70 public String getKey() {
74 public String getValue(boolean selection) {
75 int index= selection ? 0 : 1;
76 return fValues[index];
79 public String getValue(int index) {
80 return fValues[index];
83 public int getSelection(String value) {
85 for (int i= 0; i < fValues.length; i++) {
86 if (value.equals(fValues[i])) {
91 return fValues.length -1; // assume the last option is the least severe
96 protected Map fWorkingValues;
98 protected ArrayList fCheckBoxes;
99 protected ArrayList fComboBoxes;
100 protected ArrayList fTextBoxes;
101 protected HashMap fLabels;
103 private SelectionListener fSelectionListener;
104 private ModifyListener fTextModifyListener;
106 protected IStatusChangeListener fContext;
107 protected IJavaProject fProject; // project or null
108 protected String[] fAllKeys;
110 private Shell fShell;
112 public OptionsConfigurationBlock(IStatusChangeListener context, IJavaProject project, String[] allKeys) {
117 fWorkingValues= getOptions(true);
118 testIfOptionsComplete(fWorkingValues, allKeys);
120 fCheckBoxes= new ArrayList();
121 fComboBoxes= new ArrayList();
122 fTextBoxes= new ArrayList(2);
123 fLabels= new HashMap();
126 private void testIfOptionsComplete(Map workingValues, String[] allKeys) {
127 for (int i= 0; i < allKeys.length; i++) {
128 if (workingValues.get(allKeys[i]) == null) {
129 PHPeclipsePlugin.logErrorMessage("preference option missing: " + allKeys[i] + " (" + this.getClass().getName() +')'); //$NON-NLS-1$//$NON-NLS-2$
134 protected Map getOptions(boolean inheritJavaCoreOptions) {
135 if (fProject != null) {
136 return fProject.getOptions(inheritJavaCoreOptions);
138 return JavaCore.getOptions();
142 protected Map getDefaultOptions() {
143 return JavaCore.getDefaultOptions();
146 public final boolean hasProjectSpecificOptions() {
147 if (fProject != null) {
148 Map settings= fProject.getOptions(false);
149 String[] allKeys= fAllKeys;
150 for (int i= 0; i < allKeys.length; i++) {
151 if (settings.get(allKeys[i]) != null) {
159 protected void setOptions(Map map) {
160 if (fProject != null) {
161 Map oldOptions= fProject.getOptions(false);
162 fProject.setOptions(map);
163 firePropertyChangeEvents(oldOptions, map);
165 JavaCore.setOptions((Hashtable) map);
170 * Computes the differences between the given old and new options and fires corresponding
171 * property change events on the Java plugin's mockup preference store.
172 * @param oldOptions The old options
173 * @param newOptions The new options
175 private void firePropertyChangeEvents(Map oldOptions, Map newOptions) {
176 oldOptions= new HashMap(oldOptions);
177 Object source= fProject.getProject();
178 MockupPreferenceStore store= PHPeclipsePlugin.getDefault().getMockupPreferenceStore();
179 Iterator iter= newOptions.entrySet().iterator();
180 while (iter.hasNext()) {
181 Entry entry= (Entry) iter.next();
183 String name= (String) entry.getKey();
184 Object oldValue= oldOptions.get(name);
185 Object newValue= entry.getValue();
187 if ((oldValue != null && !oldValue.equals(newValue)) || (oldValue == null && newValue != null))
188 store.firePropertyChangeEvent(source, name, oldValue, newValue);
189 oldOptions.remove(name);
192 iter= oldOptions.entrySet().iterator();
193 while (iter.hasNext()) {
194 Entry entry= (Entry) iter.next();
195 store.firePropertyChangeEvent(source, (String) entry.getKey(), entry.getValue(), null);
199 protected Shell getShell() {
203 protected void setShell(Shell shell) {
207 protected abstract Control createContents(Composite parent);
209 protected Button addCheckBox(Composite parent, String label, String key, String[] values, int indent) {
210 ControlData data= new ControlData(key, values);
212 GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
213 gd.horizontalSpan= 3;
214 gd.horizontalIndent= indent;
216 Button checkBox= new Button(parent, SWT.CHECK);
217 checkBox.setText(label);
218 checkBox.setData(data);
219 checkBox.setLayoutData(gd);
220 checkBox.addSelectionListener(getSelectionListener());
222 String currValue= (String)fWorkingValues.get(key);
223 checkBox.setSelection(data.getSelection(currValue) == 0);
225 fCheckBoxes.add(checkBox);
230 protected Combo addComboBox(Composite parent, String label, String key, String[] values, String[] valueLabels, int indent) {
231 ControlData data= new ControlData(key, values);
233 GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
234 gd.horizontalIndent= indent;
236 Label labelControl= new Label(parent, SWT.LEFT | SWT.WRAP);
237 labelControl.setText(label);
238 labelControl.setLayoutData(gd);
240 Combo comboBox= new Combo(parent, SWT.READ_ONLY);
241 comboBox.setItems(valueLabels);
242 comboBox.setData(data);
243 comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
244 comboBox.addSelectionListener(getSelectionListener());
246 fLabels.put(comboBox, labelControl);
248 Label placeHolder= new Label(parent, SWT.NONE);
249 placeHolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
251 String currValue= (String)fWorkingValues.get(key);
252 comboBox.select(data.getSelection(currValue));
254 fComboBoxes.add(comboBox);
258 protected void addInversedComboBox(Composite parent, String label, String key, String[] values, String[] valueLabels, int indent) {
259 ControlData data= new ControlData(key, values);
261 GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
262 gd.horizontalIndent= indent;
263 gd.horizontalSpan= 3;
265 Composite composite= new Composite(parent, SWT.NONE);
266 GridLayout layout= new GridLayout();
267 layout.marginHeight= 0;
268 layout.marginWidth= 0;
269 layout.numColumns= 2;
270 composite.setLayout(layout);
271 composite.setLayoutData(gd);
273 Combo comboBox= new Combo(composite, SWT.READ_ONLY);
274 comboBox.setItems(valueLabels);
275 comboBox.setData(data);
276 comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
277 comboBox.addSelectionListener(getSelectionListener());
279 Label labelControl= new Label(composite, SWT.LEFT | SWT.WRAP);
280 labelControl.setText(label);
281 labelControl.setLayoutData(new GridData());
283 fLabels.put(comboBox, labelControl);
285 String currValue= (String)fWorkingValues.get(key);
286 comboBox.select(data.getSelection(currValue));
288 fComboBoxes.add(comboBox);
291 protected Text addTextField(Composite parent, String label, String key, int indent, int widthHint) {
292 Label labelControl= new Label(parent, SWT.NONE);
293 labelControl.setText(label);
294 labelControl.setLayoutData(new GridData());
296 Text textBox= new Text(parent, SWT.BORDER | SWT.SINGLE);
297 textBox.setData(key);
298 textBox.setLayoutData(new GridData());
300 fLabels.put(textBox, labelControl);
302 String currValue= (String) fWorkingValues.get(key);
303 if (currValue != null) {
304 textBox.setText(currValue);
306 textBox.addModifyListener(getTextModifyListener());
308 GridData data= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
309 if (widthHint != 0) {
310 data.widthHint= widthHint;
312 data.horizontalIndent= indent;
313 data.horizontalSpan= 2;
314 textBox.setLayoutData(data);
316 fTextBoxes.add(textBox);
320 protected SelectionListener getSelectionListener() {
321 if (fSelectionListener == null) {
322 fSelectionListener= new SelectionListener() {
323 public void widgetDefaultSelected(SelectionEvent e) {}
325 public void widgetSelected(SelectionEvent e) {
326 controlChanged(e.widget);
330 return fSelectionListener;
333 protected ModifyListener getTextModifyListener() {
334 if (fTextModifyListener == null) {
335 fTextModifyListener= new ModifyListener() {
336 public void modifyText(ModifyEvent e) {
337 textChanged((Text) e.widget);
341 return fTextModifyListener;
344 protected void controlChanged(Widget widget) {
345 ControlData data= (ControlData) widget.getData();
346 String newValue= null;
347 if (widget instanceof Button) {
348 newValue= data.getValue(((Button)widget).getSelection());
349 } else if (widget instanceof Combo) {
350 newValue= data.getValue(((Combo)widget).getSelectionIndex());
354 fWorkingValues.put(data.getKey(), newValue);
356 validateSettings(data.getKey(), newValue);
359 protected void textChanged(Text textControl) {
360 String key= (String) textControl.getData();
361 String number= textControl.getText();
362 fWorkingValues.put(key, number);
363 validateSettings(key, number);
366 protected boolean checkValue(String key, String value) {
367 return value.equals(fWorkingValues.get(key));
371 * Update fields and validate.
372 * @param changedKey Key that changed, or null, if all changed.
374 protected abstract void validateSettings(String changedKey, String newValue);
377 protected String[] getTokens(String text, String separator) {
378 StringTokenizer tok= new StringTokenizer(text, separator); //$NON-NLS-1$
379 int nTokens= tok.countTokens();
380 String[] res= new String[nTokens];
381 for (int i= 0; i < res.length; i++) {
382 res[i]= tok.nextToken().trim();
388 public boolean performOk(boolean enabled) {
389 String[] allKeys= fAllKeys;
390 Map actualOptions= getOptions(false);
392 // preserve other options
393 boolean hasChanges= false;
394 for (int i= 0; i < allKeys.length; i++) {
395 String key= allKeys[i];
396 String oldVal= (String) actualOptions.get(key);
399 val= (String) fWorkingValues.get(key);
400 if (val != null && !val.equals(oldVal)) {
402 actualOptions.put(key, val);
405 if (oldVal != null) {
406 actualOptions.remove(key);
414 boolean doBuild= false;
415 String[] strings= getFullBuildDialogStrings(fProject == null);
416 if (strings != null) {
417 MessageDialog dialog= new MessageDialog(getShell(), strings[0], null, strings[1], MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, 2);
418 int res= dialog.open();
421 } else if (res != 1) {
422 return false; // cancel pressed
425 setOptions(actualOptions);
427 boolean res= doFullBuild();
436 protected abstract String[] getFullBuildDialogStrings(boolean workspaceSettings);
438 protected boolean doFullBuild() {
440 Job buildJob = new Job(PreferencesMessages.getString("OptionsConfigurationBlock.job.title")){ //$NON-NLS-1$
442 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
444 protected IStatus run(IProgressMonitor monitor) {
446 if (fProject != null) {
447 monitor.setTaskName(PreferencesMessages.getFormattedString("OptionsConfigurationBlock.buildproject.taskname", fProject.getElementName())); //$NON-NLS-1$
448 fProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD, new SubProgressMonitor(monitor,1));
449 PHPeclipsePlugin.getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, new SubProgressMonitor(monitor,1));
451 monitor.setTaskName(PreferencesMessages.getString("OptionsConfigurationBlock.buildall.taskname")); //$NON-NLS-1$
452 PHPeclipsePlugin.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, new SubProgressMonitor(monitor, 2));
454 } catch (CoreException e) {
455 return e.getStatus();
456 } catch (OperationCanceledException e) {
457 return Status.CANCEL_STATUS;
462 return Status.OK_STATUS;
464 public boolean belongsTo(Object family) {
465 return ResourcesPlugin.FAMILY_MANUAL_BUILD == family;
469 buildJob.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
470 buildJob.setUser(true);
475 public void performDefaults() {
476 fWorkingValues= getDefaultOptions();
478 validateSettings(null, null);
481 protected void updateControls() {
483 for (int i= fCheckBoxes.size() - 1; i >= 0; i--) {
484 updateCheckBox((Button) fCheckBoxes.get(i));
486 for (int i= fComboBoxes.size() - 1; i >= 0; i--) {
487 updateCombo((Combo) fComboBoxes.get(i));
489 for (int i= fTextBoxes.size() - 1; i >= 0; i--) {
490 updateText((Text) fTextBoxes.get(i));
494 protected void updateCombo(Combo curr) {
495 ControlData data= (ControlData) curr.getData();
497 String currValue= (String) fWorkingValues.get(data.getKey());
498 curr.select(data.getSelection(currValue));
501 protected void updateCheckBox(Button curr) {
502 ControlData data= (ControlData) curr.getData();
504 String currValue= (String) fWorkingValues.get(data.getKey());
505 curr.setSelection(data.getSelection(currValue) == 0);
508 protected void updateText(Text curr) {
509 String key= (String) curr.getData();
511 String currValue= (String) fWorkingValues.get(key);
512 if (currValue != null) {
513 curr.setText(currValue);
517 protected Button getCheckBox(String key) {
518 for (int i= fCheckBoxes.size() - 1; i >= 0; i--) {
519 Button curr= (Button) fCheckBoxes.get(i);
520 ControlData data= (ControlData) curr.getData();
521 if (key.equals(data.getKey())) {
528 protected Combo getComboBox(String key) {
529 for (int i= fComboBoxes.size() - 1; i >= 0; i--) {
530 Combo curr= (Combo) fComboBoxes.get(i);
531 ControlData data= (ControlData) curr.getData();
532 if (key.equals(data.getKey())) {
539 protected void setComboEnabled(String key, boolean enabled) {
540 Combo combo= getComboBox(key);
541 Label label= (Label) fLabels.get(combo);
542 combo.setEnabled(enabled);
543 label.setEnabled(enabled);