KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > apt > ui > internal > preferences > BaseConfigurationBlock


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 BEA Systems, Inc.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * wharley@bea.com - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.jdt.apt.ui.internal.preferences;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.IdentityHashMap JavaDoc;
17 import java.util.Map JavaDoc;
18 import java.util.StringTokenizer JavaDoc;
19
20 import org.eclipse.core.resources.IProject;
21 import org.eclipse.core.resources.ProjectScope;
22 import org.eclipse.core.runtime.preferences.DefaultScope;
23 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
24 import org.eclipse.core.runtime.preferences.IScopeContext;
25 import org.eclipse.core.runtime.preferences.InstanceScope;
26 import org.eclipse.jdt.apt.core.internal.AptPlugin;
27 import org.eclipse.jdt.apt.core.internal.AptProject;
28 import org.eclipse.jdt.apt.ui.internal.util.ExceptionHandler;
29 import org.eclipse.jdt.core.JavaCore;
30 import org.eclipse.jdt.internal.ui.JavaPlugin;
31 import org.eclipse.jdt.internal.ui.preferences.ScrolledPageContent;
32 import org.eclipse.jdt.internal.ui.util.CoreUtility;
33 import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
34 import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
35 import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
36 import org.eclipse.jface.dialogs.IDialogConstants;
37 import org.eclipse.jface.dialogs.IDialogSettings;
38 import org.eclipse.jface.dialogs.MessageDialog;
39 import org.eclipse.jface.resource.JFaceResources;
40 import org.eclipse.swt.SWT;
41 import org.eclipse.swt.events.ModifyEvent;
42 import org.eclipse.swt.events.ModifyListener;
43 import org.eclipse.swt.events.SelectionEvent;
44 import org.eclipse.swt.events.SelectionListener;
45 import org.eclipse.swt.layout.GridData;
46 import org.eclipse.swt.layout.GridLayout;
47 import org.eclipse.swt.widgets.Button;
48 import org.eclipse.swt.widgets.Combo;
49 import org.eclipse.swt.widgets.Composite;
50 import org.eclipse.swt.widgets.Control;
51 import org.eclipse.swt.widgets.Label;
52 import org.eclipse.swt.widgets.Scrollable;
53 import org.eclipse.swt.widgets.Shell;
54 import org.eclipse.swt.widgets.Text;
55 import org.eclipse.swt.widgets.Widget;
56 import org.eclipse.ui.forms.events.ExpansionAdapter;
57 import org.eclipse.ui.forms.events.ExpansionEvent;
58 import org.eclipse.ui.forms.widgets.ExpandableComposite;
59 import org.eclipse.ui.preferences.WorkingCopyManager;
60 import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
61 import org.eclipse.ui.preferences.IWorkingCopyManager;
62 import org.osgi.service.prefs.BackingStoreException;
63
64 /**
65  * The ConfigurationBlock hierarchy is used to organize controls and keys
66  * within a property/preference page. The implementor derives from this
67  * class and creates dialog controls, layout, and response code.
68  * <p>
69  * This code is largely a copy of OptionsConfigurationBlock (JDT UI), modified
70  * to fix bugs and to improve extensibility for preference pages that contain
71  * a mix of preference-based and externally serialized data.
72  */

73 public abstract class BaseConfigurationBlock {
74
75     protected static class ControlData {
76         private Key fKey;
77         private String JavaDoc[] fValues;
78         
79         public ControlData(Key key, String JavaDoc[] values) {
80             fKey= key;
81             fValues= values;
82         }
83         
84         public Key getKey() {
85             return fKey;
86         }
87         
88         public int getSelection(String JavaDoc value) {
89             if (value != null) {
90                 for (int i= 0; i < fValues.length; i++) {
91                     if (value.equals(fValues[i])) {
92                         return i;
93                     }
94                 }
95             }
96             return fValues.length -1; // assume the last option is the least severe
97
}
98         
99         public String JavaDoc getValue(boolean selection) {
100             int index= selection ? 0 : 1;
101             return fValues[index];
102         }
103         
104         public String JavaDoc getValue(int index) {
105             return fValues[index];
106         }
107     }
108     
109     public static final class Key {
110         
111         private String JavaDoc fKey;
112         private String JavaDoc fQualifier;
113         
114         public Key(String JavaDoc qualifier, String JavaDoc key) {
115             fQualifier= qualifier;
116             fKey= key;
117         }
118         
119         public String JavaDoc getName() {
120             return fKey;
121         }
122         
123         private IEclipsePreferences getNode(IScopeContext context, IWorkingCopyManager manager) {
124             IEclipsePreferences node= context.getNode(fQualifier);
125             if (manager != null) {
126                 return manager.getWorkingCopy(node);
127             }
128             return node;
129         }
130         
131         public String JavaDoc getQualifier() {
132             return fQualifier;
133         }
134         
135         public String JavaDoc getStoredValue(IScopeContext context, IWorkingCopyManager manager) {
136             return getNode(context, manager).get(fKey, null);
137         }
138         
139         public String JavaDoc getStoredValue(IScopeContext[] lookupOrder, boolean ignoreTopScope, IWorkingCopyManager manager) {
140             for (int i= ignoreTopScope ? 1 : 0; i < lookupOrder.length; i++) {
141                 String JavaDoc value= getStoredValue(lookupOrder[i], manager);
142                 if (value != null) {
143                     return value;
144                 }
145             }
146             return null;
147         }
148             
149         public void setStoredValue(IScopeContext context, String JavaDoc value, IWorkingCopyManager manager) {
150             if (value != null) {
151                 getNode(context, manager).put(fKey, value);
152             } else {
153                 getNode(context, manager).remove(fKey);
154             }
155         }
156
157         /* (non-Javadoc)
158          * @see java.lang.Object#toString()
159          */

160         public String JavaDoc toString() {
161             return fQualifier + '/' + fKey;
162         }
163
164     }
165     
166     protected class UpdateAdapter implements IDialogFieldListener {
167         
168         public void dialogFieldChanged(DialogField field) {
169             updateModel(field);
170         }
171     }
172     
173     private static final String JavaDoc SETTINGS_EXPANDED= "expanded"; //$NON-NLS-1$
174

175     protected final Key[] fAllKeys;
176     private boolean fOriginallyHadProjectSettings; // updated in cacheOriginalValues
177
private Map JavaDoc<Key, String JavaDoc> fDisabledProjectSettings; // null when project specific settings are turned off
178
protected IScopeContext[] fLookupOrder;
179     protected final IWorkingCopyManager fManager;
180
181     protected final ArrayList JavaDoc<Button> fCheckBoxes;
182     protected final ArrayList JavaDoc<Combo> fComboBoxes;
183     protected final ArrayList JavaDoc<ExpandableComposite> fExpandedComposites;
184     protected final HashMap JavaDoc<Scrollable, Label> fLabels;
185     protected final ArrayList JavaDoc<Text> fTextBoxes;
186     
187     private ModifyListener fTextModifyListener;
188     protected IStatusChangeListener fContext;
189     private SelectionListener fSelectionListener;
190     
191     protected final IProject fProject; // project or null
192
protected final AptProject fAptProject; // null for workspace prefs
193

194     private IWorkbenchPreferenceContainer fContainer;
195     private Shell fShell;
196
197     private Control fBlockControl;
198     
199     protected static Key getKey(String JavaDoc plugin, String JavaDoc name) {
200         return new Key(plugin, name);
201     }
202     
203     public BaseConfigurationBlock(IStatusChangeListener context, IProject project, Key[] keys, IWorkbenchPreferenceContainer container) {
204         fContext= context;
205         fProject= project;
206         fAllKeys= keys;
207         fContainer= container;
208         /*
209         if (container == null) {
210             fManager= new WorkingCopyManager();
211         } else {
212             fManager= container.getWorkingCopyManager();
213         }
214         */

215         // Workaround for Bugzilla 115731 - always use our own WCM.
216
fManager = new WorkingCopyManager();
217         
218         if (fProject != null) {
219             fLookupOrder= new IScopeContext[] {
220                 new ProjectScope(fProject),
221                 new InstanceScope(),
222                 new DefaultScope()
223             };
224             fAptProject = AptPlugin.getAptProject(JavaCore.create(fProject));
225         } else {
226             fLookupOrder= new IScopeContext[] {
227                 new InstanceScope(),
228                 new DefaultScope()
229             };
230             fAptProject = null;
231         }
232         
233         testIfOptionsComplete(keys);
234         if (fProject == null || hasProjectSpecificOptionsNoCache(fProject)) {
235             fDisabledProjectSettings= null;
236         } else {
237             fDisabledProjectSettings= new IdentityHashMap JavaDoc<Key, String JavaDoc>();
238             for (int i= 0; i < keys.length; i++) {
239                 Key curr= keys[i];
240                 fDisabledProjectSettings.put(curr, curr.getStoredValue(fLookupOrder, false, fManager));
241             }
242         }
243         
244         settingsUpdated();
245         
246         fCheckBoxes= new ArrayList JavaDoc<Button>();
247         fComboBoxes= new ArrayList JavaDoc<Combo>();
248         fTextBoxes= new ArrayList JavaDoc<Text>(2);
249         fLabels= new HashMap JavaDoc<Scrollable, Label>();
250         fExpandedComposites= new ArrayList JavaDoc<ExpandableComposite>();
251     }
252     
253     protected Button addCheckBox(Composite parent, String JavaDoc label, Key key, String JavaDoc[] values, int indent) {
254         ControlData data= new ControlData(key, values);
255         
256         GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
257         gd.horizontalSpan= 3;
258         gd.horizontalIndent= indent;
259         
260         Button checkBox= new Button(parent, SWT.CHECK);
261         checkBox.setFont(JFaceResources.getDialogFont());
262         checkBox.setText(label);
263         checkBox.setData(data);
264         checkBox.setLayoutData(gd);
265         checkBox.addSelectionListener(getSelectionListener());
266         
267         makeScrollableCompositeAware(checkBox);
268         
269         String JavaDoc currValue= getValue(key);
270         checkBox.setSelection(data.getSelection(currValue) == 0);
271         
272         fCheckBoxes.add(checkBox);
273         
274         return checkBox;
275     }
276     
277     protected Combo addComboBox(Composite parent, String JavaDoc label, Key key, String JavaDoc[] values, String JavaDoc[] valueLabels, int indent) {
278         GridData gd= new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1);
279         gd.horizontalIndent= indent;
280                 
281         Label labelControl= new Label(parent, SWT.LEFT);
282         labelControl.setFont(JFaceResources.getDialogFont());
283         labelControl.setText(label);
284         labelControl.setLayoutData(gd);
285                 
286         Combo comboBox= newComboControl(parent, key, values, valueLabels);
287         comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
288
289         fLabels.put(comboBox, labelControl);
290         
291         return comboBox;
292     }
293     
294     protected Combo addInversedComboBox(Composite parent, String JavaDoc label, Key key, String JavaDoc[] values, String JavaDoc[] valueLabels, int indent) {
295         GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
296         gd.horizontalIndent= indent;
297         gd.horizontalSpan= 3;
298         
299         Composite composite= new Composite(parent, SWT.NONE);
300         GridLayout layout= new GridLayout();
301         layout.marginHeight= 0;
302         layout.marginWidth= 0;
303         layout.numColumns= 2;
304         composite.setLayout(layout);
305         composite.setLayoutData(gd);
306         
307         Combo comboBox= newComboControl(composite, key, values, valueLabels);
308         comboBox.setFont(JFaceResources.getDialogFont());
309         comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
310         
311         Label labelControl= new Label(composite, SWT.LEFT | SWT.WRAP);
312         labelControl.setText(label);
313         labelControl.setLayoutData(new GridData());
314         
315         fLabels.put(comboBox, labelControl);
316         return comboBox;
317     }
318     
319     protected Text addTextField(Composite parent, String JavaDoc label, Key key, int indent, int widthHint) {
320         Label labelControl= new Label(parent, SWT.WRAP);
321         labelControl.setText(label);
322         labelControl.setFont(JFaceResources.getDialogFont());
323         labelControl.setLayoutData(new GridData());
324                 
325         Text textBox= new Text(parent, SWT.BORDER | SWT.SINGLE);
326         textBox.setData(key);
327         textBox.setLayoutData(new GridData());
328         
329         makeScrollableCompositeAware(textBox);
330         
331         fLabels.put(textBox, labelControl);
332         
333         String JavaDoc currValue= getValue(key);
334         if (currValue != null) {
335             textBox.setText(currValue);
336         }
337         textBox.addModifyListener(getTextModifyListener());
338
339         GridData data= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
340         if (widthHint != 0) {
341             data.widthHint= widthHint;
342         }
343         data.horizontalIndent= indent;
344         data.horizontalSpan= 2;
345         textBox.setLayoutData(data);
346
347         fTextBoxes.add(textBox);
348         return textBox;
349     }
350             
351     protected boolean checkValue(Key key, String JavaDoc value) {
352         return value.equals(getValue(key));
353     }
354     
355     protected void controlChanged(Widget widget) {
356         ControlData data= (ControlData) widget.getData();
357         String JavaDoc newValue= null;
358         if (widget instanceof Button) {
359             newValue= data.getValue(((Button)widget).getSelection());
360         } else if (widget instanceof Combo) {
361             newValue= data.getValue(((Combo)widget).getSelectionIndex());
362         } else {
363             return;
364         }
365         String JavaDoc oldValue= setValue(data.getKey(), newValue);
366         validateSettings(data.getKey(), oldValue, newValue);
367     }
368     
369     /**
370      * Called from BasePreferencePage#createPreferenceContent.
371      */

372     public final Control createPreferenceContent(Composite parent) {
373         fBlockControl = createContents(parent);
374         if (fBlockControl != null) {
375             cacheOriginalValues();
376             initContents();
377         }
378         return fBlockControl;
379     }
380
381     /**
382      * Derived classes must override this in order to create
383      * their visual content. After this is called, initContents()
384      * will be called.
385      * @return a Composite representing the entire pane.
386      */

387     protected abstract Control createContents(Composite parent);
388
389     /**
390      * This will be called when settings are first loaded and
391      * whenever changes are applied.
392      * Derived classes may use this to cache the saved settings
393      * values, for later comparison to see if anything changed.
394      */

395     protected void cacheOriginalValues() {
396         fOriginallyHadProjectSettings= hasProjectSpecificOptionsNoCache(fProject);
397     }
398
399     /**
400      * This will be called exactly once during initialization, after
401      * createContents() and cacheOriginalValues().
402      * Derived classes may override this to initialize any fields
403      * that are not based on a Key.
404      */

405     protected void initContents() {
406         // Base method does nothing.
407
}
408
409     protected ExpandableComposite createStyleSection(Composite parent, String JavaDoc label, int nColumns) {
410         ExpandableComposite excomposite= new ExpandableComposite(parent, SWT.NONE, ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT);
411         excomposite.setText(label);
412         excomposite.setExpanded(false);
413         excomposite.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT));
414         excomposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, nColumns, 1));
415         excomposite.addExpansionListener(new ExpansionAdapter() {
416             public void expansionStateChanged(ExpansionEvent e) {
417                 expandedStateChanged((ExpandableComposite) e.getSource());
418             }
419         });
420         fExpandedComposites.add(excomposite);
421         makeScrollableCompositeAware(excomposite);
422         return excomposite;
423     }
424
425     /**
426      * Called from BasePreferencePage#dispose().
427      * Derived classes may override.
428      */

429     public void dispose() {
430     }
431     
432     protected final void expandedStateChanged(ExpandableComposite expandable) {
433         ScrolledPageContent parentScrolledComposite= getParentScrolledComposite(expandable);
434         if (parentScrolledComposite != null) {
435             parentScrolledComposite.reflow(true);
436         }
437     }
438
439     protected Control findControl(Key key) {
440         Combo comboBox= getComboBox(key);
441         if (comboBox != null) {
442             return comboBox;
443         }
444         Button checkBox= getCheckBox(key);
445         if (checkBox != null) {
446             return checkBox;
447         }
448         Text text= getTextControl(key);
449         if (text != null) {
450             return text;
451         }
452         return null;
453     }
454     
455     protected boolean getBooleanValue(Key key) {
456         return Boolean.valueOf(getValue(key)).booleanValue();
457     }
458     
459     protected Button getCheckBox(Key key) {
460         for (int i= fCheckBoxes.size() - 1; i >= 0; i--) {
461             Button curr= fCheckBoxes.get(i);
462             ControlData data= (ControlData) curr.getData();
463             if (key.equals(data.getKey())) {
464                 return curr;
465             }
466         }
467         return null;
468     }
469     
470     protected Combo getComboBox(Key key) {
471         for (int i= fComboBoxes.size() - 1; i >= 0; i--) {
472             Combo curr= fComboBoxes.get(i);
473             ControlData data= (ControlData) curr.getData();
474             if (key.equals(data.getKey())) {
475                 return curr;
476             }
477         }
478         return null;
479     }
480     
481     /**
482      * Provide the strings needed to ask the user whether to rebuild.
483      * Derived classes can override this to change the strings, or to
484      * return null, in which case the dialog will not be shown and the
485      * rebuild will not be triggered.
486      * @param workspaceSettings true if workspace settings have changed,
487      * false if only project-specific settings have changed.
488      * @return an array whose first entry is the dialog title, and whose
489      * second entry is a query asking the user whether to rebuild.
490      */

491     protected String JavaDoc[] getFullBuildDialogStrings(boolean workspaceSettings) {
492         String JavaDoc[] strings= new String JavaDoc[2];
493         strings[0] = Messages.BaseConfigurationBlock_settingsChanged;
494         if (workspaceSettings) {
495             strings[1]= Messages.BaseConfigurationBlock_fullRebuildRequired;
496         }
497         else {
498             strings[1]= Messages.BaseConfigurationBlock_rebuildRequired;
499         }
500         return strings;
501     }
502     
503     protected ExpandableComposite getParentExpandableComposite(Control control) {
504         Control parent= control.getParent();
505         while (!(parent instanceof ExpandableComposite) && parent != null) {
506             parent= parent.getParent();
507         }
508         if (parent instanceof ExpandableComposite) {
509             return (ExpandableComposite) parent;
510         }
511         return null;
512     }
513     
514     protected ScrolledPageContent getParentScrolledComposite(Control control) {
515         Control parent= control.getParent();
516         while (!(parent instanceof ScrolledPageContent) && parent != null) {
517             parent= parent.getParent();
518         }
519         if (parent instanceof ScrolledPageContent) {
520             return (ScrolledPageContent) parent;
521         }
522         return null;
523     }
524     
525     protected final IWorkbenchPreferenceContainer getPreferenceContainer() {
526         return fContainer;
527     }
528     
529     protected SelectionListener getSelectionListener() {
530         if (fSelectionListener == null) {
531             fSelectionListener= new SelectionListener() {
532                 public void widgetDefaultSelected(SelectionEvent e) {}
533     
534                 public void widgetSelected(SelectionEvent e) {
535                     controlChanged(e.widget);
536                 }
537             };
538         }
539         return fSelectionListener;
540     }
541     
542     protected Shell getShell() {
543         return fShell;
544     }
545     
546     /**
547      * Retuens the value as actually stored in the preference store.
548      * @param key
549      * @return the value as actually stored in the preference store.
550      */

551     protected String JavaDoc getStoredValue(Key key) {
552         return key.getStoredValue(fLookupOrder, false, fManager);
553     }
554     
555     protected Text getTextControl(Key key) {
556         for (int i= fTextBoxes.size() - 1; i >= 0; i--) {
557             Text curr= fTextBoxes.get(i);
558             ControlData data= (ControlData) curr.getData();
559             if (key.equals(data.getKey())) {
560                 return curr;
561             }
562         }
563         return null;
564     }
565
566     protected ModifyListener getTextModifyListener() {
567         if (fTextModifyListener == null) {
568             fTextModifyListener= new ModifyListener() {
569                 public void modifyText(ModifyEvent e) {
570                     textChanged((Text) e.widget);
571                 }
572             };
573         }
574         return fTextModifyListener;
575     }
576     
577     protected String JavaDoc[] getTokens(String JavaDoc text, String JavaDoc separator) {
578         StringTokenizer JavaDoc tok= new StringTokenizer JavaDoc(text, separator);
579         int nTokens= tok.countTokens();
580         String JavaDoc[] res= new String JavaDoc[nTokens];
581         for (int i= 0; i < res.length; i++) {
582             res[i]= tok.nextToken().trim();
583         }
584         return res;
585     }
586     
587     protected String JavaDoc getValue(Key key) {
588         if (fDisabledProjectSettings != null) {
589             return fDisabledProjectSettings.get(key);
590         }
591         return key.getStoredValue(fLookupOrder, false, fManager);
592     }
593     
594     /**
595      * TODO: this method is a workaround for Bugzilla 111144 and 106111. When
596      * 111144 is fixed, remove this method and call hasProjectSpecificOptions()
597      * instead. The difference is that this one does not cause project prefs nodes
598      * to be cached in the WorkingCopyManager.
599      * @return true if the project has project-specific options.
600      */

601     public boolean hasProjectSpecificOptionsNoCache(IProject project) {
602         if (project != null) {
603             IScopeContext projectContext= new ProjectScope(project);
604             Key[] allKeys= fAllKeys;
605             for (int i= 0; i < allKeys.length; i++) {
606                 if (allKeys[i].getStoredValue(projectContext, null) != null) {
607                     return true;
608                 }
609             }
610         }
611         return false;
612     }
613
614     private void makeScrollableCompositeAware(Control control) {
615         ScrolledPageContent parentScrolledComposite= getParentScrolledComposite(control);
616         if (parentScrolledComposite != null) {
617             parentScrolledComposite.adaptChild(control);
618         }
619     }
620     
621     protected Combo newComboControl(Composite composite, Key key, String JavaDoc[] values, String JavaDoc[] valueLabels) {
622         ControlData data= new ControlData(key, values);
623         
624         Combo comboBox= new Combo(composite, SWT.READ_ONLY);
625         comboBox.setItems(valueLabels);
626         comboBox.setData(data);
627         comboBox.addSelectionListener(getSelectionListener());
628         comboBox.setFont(JFaceResources.getDialogFont());
629             
630         makeScrollableCompositeAware(comboBox);
631         
632         String JavaDoc currValue= getValue(key);
633         comboBox.select(data.getSelection(currValue));
634         
635         fComboBoxes.add(comboBox);
636         return comboBox;
637     }
638
639     public boolean performApply() {
640         return processChanges(null); // apply directly
641
}
642     
643     
644     public void performDefaults() {
645         IScopeContext[] lookupOrder; // not same as fLookupOrder! Starts one layer deeper.
646
if (fProject != null) {
647             lookupOrder= new IScopeContext[] {
648                 new InstanceScope(),
649                 new DefaultScope()
650             };
651         } else {
652             lookupOrder= new IScopeContext[] {
653                 new DefaultScope()
654             };
655         }
656
657         for (int i= 0; i < fAllKeys.length; i++) {
658             Key curr= fAllKeys[i];
659             String JavaDoc defValue= curr.getStoredValue(lookupOrder, false, null);
660             setValue(curr, defValue);
661         }
662         
663         settingsUpdated();
664         updateControls();
665         validateSettings(null, null, null);
666     }
667     
668     public boolean performOk() {
669         return processChanges(fContainer);
670     }
671     
672     /**
673      * @since 3.1
674      */

675     public void performRevert() {
676         for (int i= 0; i < fAllKeys.length; i++) {
677             Key curr= fAllKeys[i];
678             String JavaDoc origValue= curr.getStoredValue(fLookupOrder, false, null);
679             setValue(curr, origValue);
680         }
681         
682         settingsUpdated();
683         updateControls();
684         validateSettings(null, null, null);
685     }
686     
687     /**
688      * If there are changed settings, save them and ask user whether to rebuild.
689      * This is called by performOk() and performApply().
690      * @param container null when called from performApply().
691      * @return false to abort exiting the preference pane.
692      */

693     protected boolean processChanges(IWorkbenchPreferenceContainer container) {
694         
695         boolean projectSpecificnessChanged = false;
696         boolean isProjectSpecific= (fProject != null) && fBlockControl.getEnabled();
697         if (fOriginallyHadProjectSettings ^ isProjectSpecific) {
698             // the project-specificness changed.
699
projectSpecificnessChanged= true;
700         } else if ((fProject != null) && !isProjectSpecific) {
701             // no project specific data, and there never was, and this
702
// is a project preferences pane, so nothing could have changed.
703
return true;
704         }
705
706         if (!projectSpecificnessChanged && !settingsChanged(fLookupOrder[0])) {
707             return true;
708         }
709         
710         int response= 1; // "NO" rebuild unless we put up the dialog.
711
String JavaDoc[] strings= getFullBuildDialogStrings(fProject == null);
712         if (strings != null) {
713             MessageDialog dialog= new MessageDialog(
714                     getShell(),
715                     strings[0],
716                     null,
717                     strings[1],
718                     MessageDialog.QUESTION,
719                     new String JavaDoc[] {
720                         IDialogConstants.YES_LABEL,
721                         IDialogConstants.NO_LABEL,
722                         IDialogConstants.CANCEL_LABEL
723                     },
724                     2);
725             response= dialog.open();
726         }
727         if (response == 0 || response == 1) { // "YES" or "NO" - either way, save.
728
saveSettings();
729             if (container == null) {
730                 // we're doing an Apply, so update the reference values.
731
cacheOriginalValues();
732             }
733         }
734         if (response == 0) { // "YES", rebuild
735
if (container != null) {
736                 // build after dialog exits
737
container.registerUpdateJob(CoreUtility.getBuildJob(fProject));
738             } else {
739                 // build immediately
740
CoreUtility.getBuildJob(fProject).schedule();
741             }
742         } else if (response != 1) { // "CANCEL" - no save, no rebuild.
743
return false;
744         }
745         return true;
746     }
747
748     /**
749      * Save dialog information to persistent storage.
750      * Derived classes should override this if they have settings
751      * that are managed using means other than the Key infrastructure.
752      */

753     protected void saveSettings() {
754         try {
755             fManager.applyChanges();
756         } catch (BackingStoreException e) {
757             ExceptionHandler.log(e, "Unable to save preferences"); //$NON-NLS-1$
758
}
759     }
760
761     protected void restoreSectionExpansionStates(IDialogSettings settings) {
762         for (int i= 0; i < fExpandedComposites.size(); i++) {
763             ExpandableComposite excomposite= fExpandedComposites.get(i);
764             if (settings == null) {
765                 excomposite.setExpanded(i == 0); // only expand the first node by default
766
} else {
767                 excomposite.setExpanded(settings.getBoolean(SETTINGS_EXPANDED + String.valueOf(i)));
768             }
769         }
770     }
771     
772     public void selectOption(Key key) {
773         Control control= findControl(key);
774         if (control != null) {
775             if (!fExpandedComposites.isEmpty()) {
776                 ExpandableComposite expandable= getParentExpandableComposite(control);
777                 if (expandable != null) {
778                     for (int i= 0; i < fExpandedComposites.size(); i++) {
779                         ExpandableComposite curr= fExpandedComposites.get(i);
780                         curr.setExpanded(curr == expandable);
781                     }
782                     expandedStateChanged(expandable);
783                 }
784             }
785             control.setFocus();
786         }
787     }
788     
789     public void selectOption(String JavaDoc key, String JavaDoc qualifier) {
790         for (int i= 0; i < fAllKeys.length; i++) {
791             Key curr= fAllKeys[i];
792             if (curr.getName().equals(key) && curr.getQualifier().equals(qualifier)) {
793                 selectOption(curr);
794             }
795         }
796     }
797     
798     protected void setComboEnabled(Key key, boolean enabled) {
799         Combo combo= getComboBox(key);
800         Label label= fLabels.get(combo);
801         combo.setEnabled(enabled);
802         label.setEnabled(enabled);
803     }
804     
805     protected void setShell(Shell shell) {
806         fShell= shell;
807     }
808     
809     /**
810      * Checks the state of all Keys in the dialog to see whether there have been changes.
811      * Derived classes which include settings managed outside of the Key infrastructure
812      * should override this method, in order to check whether the additional settings have changed.
813      * @return true if there is anything that needs to be saved.
814      */

815     protected boolean settingsChanged(IScopeContext currContext) {
816         boolean needsBuild= false;
817         for (int i= 0; i < fAllKeys.length; i++) {
818             Key key= fAllKeys[i];
819             String JavaDoc oldVal= key.getStoredValue(currContext, null);
820             String JavaDoc val= key.getStoredValue(currContext, fManager);
821             if (val == null) {
822                 if (oldVal != null) {
823                     needsBuild |= !oldVal.equals(key.getStoredValue(fLookupOrder, true, fManager));
824                 }
825             } else if (!val.equals(oldVal)) {
826                 needsBuild |= oldVal != null || !val.equals(key.getStoredValue(fLookupOrder, true, fManager));
827             }
828         }
829         return needsBuild;
830     }
831     
832     protected void settingsUpdated() {
833     }
834     
835     protected String JavaDoc setValue(Key key, boolean value) {
836         return setValue(key, String.valueOf(value));
837     }
838     
839     protected String JavaDoc setValue(Key key, String JavaDoc value) {
840         if (fDisabledProjectSettings != null) {
841             return fDisabledProjectSettings.put(key, value);
842         }
843         String JavaDoc oldValue= getValue(key);
844         key.setStoredValue(fLookupOrder[0], value, fManager);
845         return oldValue;
846     }
847     
848     protected void storeSectionExpansionStates(IDialogSettings settings) {
849         for (int i= 0; i < fExpandedComposites.size(); i++) {
850             ExpandableComposite curr= fExpandedComposites.get(i);
851             settings.put(SETTINGS_EXPANDED + String.valueOf(i), curr.isExpanded());
852         }
853     }
854     
855     private void testIfOptionsComplete(Key[] allKeys) {
856         for (int i= 0; i < allKeys.length; i++) {
857             if (allKeys[i].getStoredValue(fLookupOrder, false, fManager) == null) {
858                 JavaPlugin.logErrorMessage("preference option missing: " + allKeys[i] + " (" + this.getClass().getName() +')'); //$NON-NLS-1$//$NON-NLS-2$
859
}
860         }
861     }
862
863     protected void textChanged(Text textControl) {
864         Key key= (Key) textControl.getData();
865         String JavaDoc number= textControl.getText();
866         String JavaDoc oldValue= setValue(key, number);
867         validateSettings(key, oldValue, number);
868     }
869
870     protected void updateCheckBox(Button curr) {
871         ControlData data= (ControlData) curr.getData();
872         
873         String JavaDoc currValue= getValue(data.getKey());
874         curr.setSelection(data.getSelection(currValue) == 0);
875     }
876
877     protected void updateCombo(Combo curr) {
878         ControlData data= (ControlData) curr.getData();
879         
880         String JavaDoc currValue= getValue(data.getKey());
881         curr.select(data.getSelection(currValue));
882     }
883     
884     protected void updateControls() {
885         // update the UI
886
for (int i= fCheckBoxes.size() - 1; i >= 0; i--) {
887             updateCheckBox(fCheckBoxes.get(i));
888         }
889         for (int i= fComboBoxes.size() - 1; i >= 0; i--) {
890             updateCombo(fComboBoxes.get(i));
891         }
892         for (int i= fTextBoxes.size() - 1; i >= 0; i--) {
893             updateText(fTextBoxes.get(i));
894         }
895     }
896
897     protected abstract void updateModel(DialogField field);
898
899     protected void updateText(Text curr) {
900         Key key= (Key) curr.getData();
901         
902         String JavaDoc currValue= getValue(key);
903         if (currValue != null) {
904             curr.setText(currValue);
905         }
906     }
907     
908     public void useProjectSpecificSettings(boolean enable) {
909         boolean hasProjectSpecificOption= fDisabledProjectSettings == null;
910         if (enable != hasProjectSpecificOption && fProject != null) {
911             if (enable) {
912                 for (int i= 0; i < fAllKeys.length; i++) {
913                     Key curr= fAllKeys[i];
914                     String JavaDoc val= fDisabledProjectSettings.get(curr);
915                     curr.setStoredValue(fLookupOrder[0], val, fManager);
916                 }
917                 fDisabledProjectSettings= null;
918                 updateControls();
919             } else {
920                 fDisabledProjectSettings= new IdentityHashMap JavaDoc<Key, String JavaDoc>();
921                 for (int i= 0; i < fAllKeys.length; i++) {
922                     Key curr= fAllKeys[i];
923                     String JavaDoc oldSetting= curr.getStoredValue(fLookupOrder, false, fManager);
924                     fDisabledProjectSettings.put(curr, oldSetting);
925                     curr.setStoredValue(fLookupOrder[0], null, fManager); // clear project settings
926
}
927             }
928         }
929     }
930
931     /* (non-javadoc)
932      * Update fields and validate.
933      * @param changedKey Key that changed, or null, if all changed.
934      */

935     protected abstract void validateSettings(Key changedKey, String JavaDoc oldValue, String JavaDoc newValue);
936 }
937
Popular Tags