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
55 * setting up an options configuration page.
59 public abstract class OptionsConfigurationBlock {
61 protected static class ControlData {
64 private String[] fValues;
66 public ControlData(String key, String[] values) {
71 public String getKey() {
75 public String getValue(boolean selection) {
76 int index = selection ? 0 : 1;
77 return fValues[index];
80 public String getValue(int index) {
81 return fValues[index];
84 public int getSelection(String value) {
86 for (int i = 0; i < fValues.length; i++) {
87 if (value.equals(fValues[i])) {
92 return fValues.length - 1; // assume the last option is the least
97 protected Map fWorkingValues;
99 protected ArrayList fCheckBoxes;
101 protected ArrayList fComboBoxes;
103 protected ArrayList fTextBoxes;
105 protected HashMap fLabels;
107 private SelectionListener fSelectionListener;
109 private ModifyListener fTextModifyListener;
111 protected IStatusChangeListener fContext;
113 protected IJavaProject fProject; // project or null
115 protected String[] fAllKeys;
117 private Shell fShell;
119 public OptionsConfigurationBlock(IStatusChangeListener context,
120 IJavaProject project, String[] allKeys) {
125 fWorkingValues = getOptions(true);
126 testIfOptionsComplete(fWorkingValues, allKeys);
128 fCheckBoxes = new ArrayList();
129 fComboBoxes = new ArrayList();
130 fTextBoxes = new ArrayList(2);
131 fLabels = new HashMap();
134 private void testIfOptionsComplete(Map workingValues, String[] allKeys) {
135 for (int i = 0; i < allKeys.length; i++) {
136 if (workingValues.get(allKeys[i]) == null) {
138 .logErrorMessage("preference option missing: " + allKeys[i] + " (" + this.getClass().getName() + ')'); //$NON-NLS-1$//$NON-NLS-2$
143 protected Map getOptions(boolean inheritJavaCoreOptions) {
144 if (fProject != null) {
145 return fProject.getOptions(inheritJavaCoreOptions);
147 return JavaCore.getOptions();
151 protected Map getDefaultOptions() {
152 return JavaCore.getDefaultOptions();
155 public final boolean hasProjectSpecificOptions() {
156 if (fProject != null) {
157 Map settings = fProject.getOptions(false);
158 String[] allKeys = fAllKeys;
159 for (int i = 0; i < allKeys.length; i++) {
160 if (settings.get(allKeys[i]) != null) {
168 protected void setOptions(Map map) {
169 if (fProject != null) {
170 Map oldOptions = fProject.getOptions(false);
171 fProject.setOptions(map);
172 firePropertyChangeEvents(oldOptions, map);
174 JavaCore.setOptions((Hashtable) map);
179 * Computes the differences between the given old and new options and fires
180 * corresponding property change events on the Java plugin's mockup
188 private void firePropertyChangeEvents(Map oldOptions, Map newOptions) {
189 oldOptions = new HashMap(oldOptions);
190 Object source = fProject.getProject();
191 MockupPreferenceStore store = PHPeclipsePlugin.getDefault()
192 .getMockupPreferenceStore();
193 Iterator iter = newOptions.entrySet().iterator();
194 while (iter.hasNext()) {
195 Entry entry = (Entry) iter.next();
197 String name = (String) entry.getKey();
198 Object oldValue = oldOptions.get(name);
199 Object newValue = entry.getValue();
201 if ((oldValue != null && !oldValue.equals(newValue))
202 || (oldValue == null && newValue != null))
203 store.firePropertyChangeEvent(source, name, oldValue, newValue);
204 oldOptions.remove(name);
207 iter = oldOptions.entrySet().iterator();
208 while (iter.hasNext()) {
209 Entry entry = (Entry) iter.next();
210 store.firePropertyChangeEvent(source, (String) entry.getKey(),
211 entry.getValue(), null);
215 protected Shell getShell() {
219 protected void setShell(Shell shell) {
223 protected abstract Control createContents(Composite parent);
225 protected Button addCheckBox(Composite parent, String label, String key,
226 String[] values, int indent) {
227 ControlData data = new ControlData(key, values);
229 GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
230 gd.horizontalSpan = 3;
231 gd.horizontalIndent = indent;
233 Button checkBox = new Button(parent, SWT.CHECK);
234 checkBox.setText(label);
235 checkBox.setData(data);
236 checkBox.setLayoutData(gd);
237 checkBox.addSelectionListener(getSelectionListener());
239 String currValue = (String) fWorkingValues.get(key);
240 checkBox.setSelection(data.getSelection(currValue) == 0);
242 fCheckBoxes.add(checkBox);
247 protected Combo addComboBox(Composite parent, String label, String key,
248 String[] values, String[] valueLabels, int indent) {
249 ControlData data = new ControlData(key, values);
251 GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
252 gd.horizontalIndent = indent;
254 Label labelControl = new Label(parent, SWT.LEFT | SWT.WRAP);
255 labelControl.setText(label);
256 labelControl.setLayoutData(gd);
258 Combo comboBox = new Combo(parent, SWT.READ_ONLY);
259 comboBox.setItems(valueLabels);
260 comboBox.setData(data);
261 comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
262 comboBox.addSelectionListener(getSelectionListener());
264 fLabels.put(comboBox, labelControl);
266 Label placeHolder = new Label(parent, SWT.NONE);
267 placeHolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
269 String currValue = (String) fWorkingValues.get(key);
270 comboBox.select(data.getSelection(currValue));
272 fComboBoxes.add(comboBox);
276 protected void addInversedComboBox(Composite parent, String label,
277 String key, String[] values, String[] valueLabels, int indent) {
278 ControlData data = new ControlData(key, values);
280 GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
281 gd.horizontalIndent = indent;
282 gd.horizontalSpan = 3;
284 Composite composite = new Composite(parent, SWT.NONE);
285 GridLayout layout = new GridLayout();
286 layout.marginHeight = 0;
287 layout.marginWidth = 0;
288 layout.numColumns = 2;
289 composite.setLayout(layout);
290 composite.setLayoutData(gd);
292 Combo comboBox = new Combo(composite, SWT.READ_ONLY);
293 comboBox.setItems(valueLabels);
294 comboBox.setData(data);
295 comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
296 comboBox.addSelectionListener(getSelectionListener());
298 Label labelControl = new Label(composite, SWT.LEFT | SWT.WRAP);
299 labelControl.setText(label);
300 labelControl.setLayoutData(new GridData());
302 fLabels.put(comboBox, labelControl);
304 String currValue = (String) fWorkingValues.get(key);
305 comboBox.select(data.getSelection(currValue));
307 fComboBoxes.add(comboBox);
310 protected Text addTextField(Composite parent, String label, String key,
311 int indent, int widthHint) {
312 Label labelControl = new Label(parent, SWT.NONE);
313 labelControl.setText(label);
314 labelControl.setLayoutData(new GridData());
316 Text textBox = new Text(parent, SWT.BORDER | SWT.SINGLE);
317 textBox.setData(key);
318 textBox.setLayoutData(new GridData());
320 fLabels.put(textBox, labelControl);
322 String currValue = (String) fWorkingValues.get(key);
323 if (currValue != null) {
324 textBox.setText(currValue);
326 textBox.addModifyListener(getTextModifyListener());
328 GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
329 if (widthHint != 0) {
330 data.widthHint = widthHint;
332 data.horizontalIndent = indent;
333 data.horizontalSpan = 2;
334 textBox.setLayoutData(data);
336 fTextBoxes.add(textBox);
340 protected SelectionListener getSelectionListener() {
341 if (fSelectionListener == null) {
342 fSelectionListener = new SelectionListener() {
343 public void widgetDefaultSelected(SelectionEvent e) {
346 public void widgetSelected(SelectionEvent e) {
347 controlChanged(e.widget);
351 return fSelectionListener;
354 protected ModifyListener getTextModifyListener() {
355 if (fTextModifyListener == null) {
356 fTextModifyListener = new ModifyListener() {
357 public void modifyText(ModifyEvent e) {
358 textChanged((Text) e.widget);
362 return fTextModifyListener;
365 protected void controlChanged(Widget widget) {
366 ControlData data = (ControlData) widget.getData();
367 String newValue = null;
368 if (widget instanceof Button) {
369 newValue = data.getValue(((Button) widget).getSelection());
370 } else if (widget instanceof Combo) {
371 newValue = data.getValue(((Combo) widget).getSelectionIndex());
375 fWorkingValues.put(data.getKey(), newValue);
377 validateSettings(data.getKey(), newValue);
380 protected void textChanged(Text textControl) {
381 String key = (String) textControl.getData();
382 String number = textControl.getText();
383 fWorkingValues.put(key, number);
384 validateSettings(key, number);
387 protected boolean checkValue(String key, String value) {
388 return value.equals(fWorkingValues.get(key));
392 * (non-javadoc) Update fields and validate. @param changedKey Key that
393 * changed, or null, if all changed.
395 protected abstract void validateSettings(String changedKey, String newValue);
397 protected String[] getTokens(String text, String separator) {
398 StringTokenizer tok = new StringTokenizer(text, separator); //$NON-NLS-1$
399 int nTokens = tok.countTokens();
400 String[] res = new String[nTokens];
401 for (int i = 0; i < res.length; i++) {
402 res[i] = tok.nextToken().trim();
407 public boolean performOk(boolean enabled) {
408 String[] allKeys = fAllKeys;
409 Map actualOptions = getOptions(false);
411 // preserve other options
412 boolean hasChanges = false;
413 for (int i = 0; i < allKeys.length; i++) {
414 String key = allKeys[i];
415 String oldVal = (String) actualOptions.get(key);
418 val = (String) fWorkingValues.get(key);
419 if (val != null && !val.equals(oldVal)) {
421 actualOptions.put(key, val);
424 if (oldVal != null) {
425 actualOptions.remove(key);
432 boolean doBuild = false;
433 String[] strings = getFullBuildDialogStrings(fProject == null);
434 if (strings != null) {
435 MessageDialog dialog = new MessageDialog(getShell(),
436 strings[0], null, strings[1], MessageDialog.QUESTION,
437 new String[] { IDialogConstants.YES_LABEL,
438 IDialogConstants.NO_LABEL,
439 IDialogConstants.CANCEL_LABEL }, 2);
440 int res = dialog.open();
443 } else if (res != 1) {
444 return false; // cancel pressed
447 setOptions(actualOptions);
449 boolean res = doFullBuild();
458 protected abstract String[] getFullBuildDialogStrings(
459 boolean workspaceSettings);
461 protected boolean doFullBuild() {
463 Job buildJob = new Job(PreferencesMessages
464 .getString("OptionsConfigurationBlock.job.title")) { //$NON-NLS-1$
468 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
470 protected IStatus run(IProgressMonitor monitor) {
472 if (fProject != null) {
474 .setTaskName(PreferencesMessages
476 "OptionsConfigurationBlock.buildproject.taskname", fProject.getElementName())); //$NON-NLS-1$
477 fProject.getProject().build(
478 IncrementalProjectBuilder.FULL_BUILD,
479 new SubProgressMonitor(monitor, 1));
480 PHPeclipsePlugin.getWorkspace().build(
481 IncrementalProjectBuilder.INCREMENTAL_BUILD,
482 new SubProgressMonitor(monitor, 1));
485 .setTaskName(PreferencesMessages
486 .getString("OptionsConfigurationBlock.buildall.taskname")); //$NON-NLS-1$
487 PHPeclipsePlugin.getWorkspace().build(
488 IncrementalProjectBuilder.FULL_BUILD,
489 new SubProgressMonitor(monitor, 2));
491 } catch (CoreException e) {
492 return e.getStatus();
493 } catch (OperationCanceledException e) {
494 return Status.CANCEL_STATUS;
498 return Status.OK_STATUS;
501 public boolean belongsTo(Object family) {
502 return ResourcesPlugin.FAMILY_MANUAL_BUILD == family;
506 buildJob.setRule(ResourcesPlugin.getWorkspace().getRuleFactory()
508 buildJob.setUser(true);
513 public void performDefaults() {
514 fWorkingValues = getDefaultOptions();
516 validateSettings(null, null);
519 protected void updateControls() {
521 for (int i = fCheckBoxes.size() - 1; i >= 0; i--) {
522 updateCheckBox((Button) fCheckBoxes.get(i));
524 for (int i = fComboBoxes.size() - 1; i >= 0; i--) {
525 updateCombo((Combo) fComboBoxes.get(i));
527 for (int i = fTextBoxes.size() - 1; i >= 0; i--) {
528 updateText((Text) fTextBoxes.get(i));
532 protected void updateCombo(Combo curr) {
533 ControlData data = (ControlData) curr.getData();
535 String currValue = (String) fWorkingValues.get(data.getKey());
536 curr.select(data.getSelection(currValue));
539 protected void updateCheckBox(Button curr) {
540 ControlData data = (ControlData) curr.getData();
542 String currValue = (String) fWorkingValues.get(data.getKey());
543 curr.setSelection(data.getSelection(currValue) == 0);
546 protected void updateText(Text curr) {
547 String key = (String) curr.getData();
549 String currValue = (String) fWorkingValues.get(key);
550 if (currValue != null) {
551 curr.setText(currValue);
555 protected Button getCheckBox(String key) {
556 for (int i = fCheckBoxes.size() - 1; i >= 0; i--) {
557 Button curr = (Button) fCheckBoxes.get(i);
558 ControlData data = (ControlData) curr.getData();
559 if (key.equals(data.getKey())) {
566 protected Combo getComboBox(String key) {
567 for (int i = fComboBoxes.size() - 1; i >= 0; i--) {
568 Combo curr = (Combo) fComboBoxes.get(i);
569 ControlData data = (ControlData) curr.getData();
570 if (key.equals(data.getKey())) {
577 protected void setComboEnabled(String key, boolean enabled) {
578 Combo combo = getComboBox(key);
579 Label label = (Label) fLabels.get(combo);
580 combo.setEnabled(enabled);
581 label.setEnabled(enabled);