KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > preference > PreferencePage


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
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  * IBM Corporation - initial API and implementation
10  * Sebastian Davids <sdavids@gmx.de> - Fix for bug 38729 - [Preferences]
11  * NPE PreferencePage isValid.
12  *******************************************************************************/

13 package org.eclipse.jface.preference;
14
15 import org.eclipse.jface.dialogs.Dialog;
16 import org.eclipse.jface.dialogs.DialogPage;
17 import org.eclipse.jface.dialogs.IDialogConstants;
18 import org.eclipse.jface.resource.ImageDescriptor;
19 import org.eclipse.jface.resource.JFaceResources;
20 import org.eclipse.jface.util.IPropertyChangeListener;
21 import org.eclipse.jface.util.PropertyChangeEvent;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.events.DisposeEvent;
24 import org.eclipse.swt.events.DisposeListener;
25 import org.eclipse.swt.events.SelectionAdapter;
26 import org.eclipse.swt.events.SelectionEvent;
27 import org.eclipse.swt.graphics.Font;
28 import org.eclipse.swt.graphics.Point;
29 import org.eclipse.swt.layout.GridData;
30 import org.eclipse.swt.layout.GridLayout;
31 import org.eclipse.swt.widgets.Button;
32 import org.eclipse.swt.widgets.Composite;
33 import org.eclipse.swt.widgets.Control;
34 import org.eclipse.swt.widgets.Event;
35 import org.eclipse.swt.widgets.Label;
36
37 /**
38  * Abstract base implementation for all preference page implementations.
39  * <p>
40  * Subclasses must implement the <code>createControl</code> framework
41  * method to supply the page's main control.
42  * </p>
43  * <p>
44  * Subclasses should extend the <code>doComputeSize</code> framework
45  * method to compute the size of the page's control.
46  * </p>
47  * <p>
48  * Subclasses may override the <code>performOk</code>, <code>performApply</code>,
49  * <code>performDefaults</code>, <code>performCancel</code>, and <code>performHelp</code>
50  * framework methods to react to the standard button events.
51  * </p>
52  * <p>
53  * Subclasses may call the <code>noDefaultAndApplyButton</code> framework
54  * method before the page's control has been created to suppress
55  * the standard Apply and Defaults buttons.
56  * </p>
57  */

58 public abstract class PreferencePage extends DialogPage implements
59         IPreferencePage {
60
61     /**
62      * Preference store, or <code>null</code>.
63      */

64     private IPreferenceStore preferenceStore;
65
66     /**
67      * Valid state for this page; <code>true</code> by default.
68      *
69      * @see #isValid
70      */

71     private boolean isValid = true;
72
73     /**
74      * Body of page.
75      */

76     private Control body;
77
78     /**
79      * Whether this page has the standard Apply and Defaults buttons;
80      * <code>true</code> by default.
81      *
82      * @see #noDefaultAndApplyButton
83      */

84     private boolean createDefaultAndApplyButton = true;
85
86     /**
87      * Standard Defaults button, or <code>null</code> if none.
88      * This button has id <code>DEFAULTS_ID</code>.
89      */

90     private Button defaultsButton = null;
91
92     /**
93      * The container this preference page belongs to; <code>null</code>
94      * if none.
95      */

96     private IPreferencePageContainer container = null;
97
98     /**
99      * Standard Apply button, or <code>null</code> if none.
100      * This button has id <code>APPLY_ID</code>.
101      */

102     private Button applyButton = null;
103
104     /**
105      * Description label.
106      *
107      * @see #createDescriptionLabel(Composite)
108      */

109     private Label descriptionLabel;
110
111     /**
112      * Caches size of page.
113      */

114     private Point size = null;
115
116    
117     /**
118      * Creates a new preference page with an empty title and no image.
119      */

120     protected PreferencePage() {
121         this(""); //$NON-NLS-1$
122
}
123
124     /**
125      * Creates a new preference page with the given title and no image.
126      *
127      * @param title the title of this preference page
128      */

129     protected PreferencePage(String JavaDoc title) {
130         super(title);
131     }
132
133     /**
134      * Creates a new abstract preference page with the given title and image.
135      *
136      * @param title the title of this preference page
137      * @param image the image for this preference page,
138      * or <code>null</code> if none
139      */

140     protected PreferencePage(String JavaDoc title, ImageDescriptor image) {
141         super(title, image);
142     }
143
144     /**
145      * Computes the size for this page's UI control.
146      * <p>
147      * The default implementation of this <code>IPreferencePage</code>
148      * method returns the size set by <code>setSize</code>; if no size
149      * has been set, but the page has a UI control, the framework
150      * method <code>doComputeSize</code> is called to compute the size.
151      * </p>
152      *
153      * @return the size of the preference page encoded as
154      * <code>new Point(width,height)</code>, or
155      * <code>(0,0)</code> if the page doesn't currently have any UI component
156      */

157     public Point computeSize() {
158         if (size != null) {
159             return size;
160         }
161         Control control = getControl();
162         if (control != null) {
163             size = doComputeSize();
164             return size;
165         }
166         return new Point(0, 0);
167     }
168
169     /**
170      * Contributes additional buttons to the given composite.
171      * <p>
172      * The default implementation of this framework hook method does
173      * nothing. Subclasses should override this method to contribute buttons
174      * to this page's button bar. For each button a subclass contributes,
175      * it must also increase the parent's grid layout number of columns
176      * by one; that is,
177      * <pre>
178      * ((GridLayout) parent.getLayout()).numColumns++);
179      * </pre>
180      * </p>
181      *
182      * @param parent the button bar
183      */

184     protected void contributeButtons(Composite parent) {
185     }
186
187     /**
188      * Creates and returns the SWT control for the customized body
189      * of this preference page under the given parent composite.
190      * <p>
191      * This framework method must be implemented by concrete subclasses. Any
192      * subclass returning a <code>Composite</code> object whose <code>Layout</code>
193      * has default margins (for example, a <code>GridLayout</code>) are expected to
194      * set the margins of this <code>Layout</code> to 0 pixels.
195      * </p>
196      *
197      * @param parent the parent composite
198      * @return the new control
199      */

200     protected abstract Control createContents(Composite parent);
201
202     /**
203      * The <code>PreferencePage</code> implementation of this
204      * <code>IDialogPage</code> method creates a description label
205      * and button bar for the page. It calls <code>createContents</code>
206      * to create the custom contents of the page.
207      * <p>
208      * If a subclass that overrides this method creates a <code>Composite</code>
209      * that has a layout with default margins (for example, a <code>GridLayout</code>)
210      * it is expected to set the margins of this <code>Layout</code> to 0 pixels.
211      */

212     public void createControl(Composite parent){
213
214         GridData gd;
215         Composite content = new Composite(parent, SWT.NONE);
216         setControl(content);
217         GridLayout layout = new GridLayout();
218         layout.marginWidth = 0;
219         layout.marginHeight = 0;
220         content.setLayout(layout);
221         //Apply the font on creation for backward compatibility
222
applyDialogFont(content);
223
224         // initialize the dialog units
225
initializeDialogUnits(content);
226
227         descriptionLabel = createDescriptionLabel(content);
228         if (descriptionLabel != null) {
229             descriptionLabel.setLayoutData(new GridData(
230                     GridData.FILL_HORIZONTAL));
231         }
232
233         body = createContents(content);
234         if (body != null) {
235             // null is not a valid return value but support graceful failure
236
body.setLayoutData(new GridData(GridData.FILL_BOTH));
237         }
238
239         Composite buttonBar = new Composite(content, SWT.NONE);
240         layout = new GridLayout();
241         layout.numColumns = 0;
242         layout.marginHeight = 0;
243         layout.marginWidth = 0;
244         layout.makeColumnsEqualWidth = false;
245         buttonBar.setLayout(layout);
246         
247         gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
248         
249         buttonBar.setLayoutData(gd);
250
251         contributeButtons(buttonBar);
252         
253         if (createDefaultAndApplyButton) {
254             layout.numColumns = layout.numColumns + 2;
255             String JavaDoc[] labels = JFaceResources.getStrings(new String JavaDoc[] {
256                     "defaults", "apply" }); //$NON-NLS-2$//$NON-NLS-1$
257
int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
258             defaultsButton = new Button(buttonBar, SWT.PUSH);
259             defaultsButton.setText(labels[0]);
260             Dialog.applyDialogFont(defaultsButton);
261             GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
262             Point minButtonSize = defaultsButton.computeSize(SWT.DEFAULT,
263                     SWT.DEFAULT, true);
264             data.widthHint = Math.max(widthHint, minButtonSize.x);
265             defaultsButton.setLayoutData(data);
266             defaultsButton.addSelectionListener(new SelectionAdapter() {
267                 public void widgetSelected(SelectionEvent e) {
268                     performDefaults();
269                 }
270             });
271
272             applyButton = new Button(buttonBar, SWT.PUSH);
273             applyButton.setText(labels[1]);
274             Dialog.applyDialogFont(applyButton);
275             data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
276             minButtonSize = applyButton.computeSize(SWT.DEFAULT, SWT.DEFAULT,
277                     true);
278             data.widthHint = Math.max(widthHint, minButtonSize.x);
279             applyButton.setLayoutData(data);
280             applyButton.addSelectionListener(new SelectionAdapter() {
281                 public void widgetSelected(SelectionEvent e) {
282                     performApply();
283                 }
284             });
285             applyButton.setEnabled(isValid());
286             applyDialogFont(buttonBar);
287         } else {
288             /* Check if there are any other buttons on the button bar.
289              * If not, throw away the button bar composite. Otherwise
290              * there is an unusually large button bar.
291              */

292             if (buttonBar.getChildren().length < 1) {
293                 buttonBar.dispose();
294             }
295         }
296     }
297
298     
299
300     /**
301      * Apply the dialog font to the composite and it's children
302      * if it is set. Subclasses may override if they wish to
303      * set the font themselves.
304      * @param composite
305      */

306     protected void applyDialogFont(Composite composite) {
307         Dialog.applyDialogFont(composite);
308     }
309
310     /**
311      * Creates and returns an SWT label under the given composite.
312      *
313      * @param parent the parent composite
314      * @return the new label
315      */

316     protected Label createDescriptionLabel(Composite parent) {
317         Label result = null;
318         String JavaDoc description = getDescription();
319         if (description != null) {
320             result = new Label(parent, SWT.WRAP);
321             result.setFont(parent.getFont());
322             result.setText(description);
323         }
324         return result;
325     }
326
327     /**
328      * Computes the size needed by this page's UI control.
329      * <p>
330      * All pages should override this method and set the appropriate sizes
331      * of their widgets, and then call <code>super.doComputeSize</code>.
332      * </p>
333      *
334      * @return the size of the preference page encoded as
335      * <code>new Point(width,height)</code>
336      */

337     protected Point doComputeSize() {
338         if (descriptionLabel != null && body != null) {
339             Point bodySize = body.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
340             GridData gd = (GridData) descriptionLabel.getLayoutData();
341             gd.widthHint = bodySize.x;
342         }
343         return getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
344     }
345
346     /**
347      * Returns the preference store of this preference page.
348      * <p>
349      * This is a framework hook method for subclasses to return a
350      * page-specific preference store. The default implementation
351      * returns <code>null</code>.
352      * </p>
353      *
354      * @return the preference store, or <code>null</code> if none
355      */

356     protected IPreferenceStore doGetPreferenceStore() {
357         return null;
358     }
359
360     /**
361      * Returns the container of this page.
362      *
363      * @return the preference page container, or <code>null</code> if this
364      * page has yet to be added to a container
365      */

366     public IPreferencePageContainer getContainer() {
367         return container;
368     }
369
370     /**
371      * Returns the preference store of this preference page.
372      *
373      * @return the preference store , or <code>null</code> if none
374      */

375     public IPreferenceStore getPreferenceStore() {
376         if (preferenceStore == null) {
377             preferenceStore = doGetPreferenceStore();
378         }
379         if (preferenceStore != null) {
380             return preferenceStore;
381         } else if (container != null) {
382             return container.getPreferenceStore();
383         }
384         return null;
385     }
386
387     /**
388      * The preference page implementation of an <code>IPreferencePage</code>
389      * method returns whether this preference page is valid. Preference
390      * pages are considered valid by default; call <code>setValid(false)</code>
391      * to make a page invalid.
392      */

393     public boolean isValid() {
394         return isValid;
395     }
396
397     /**
398      * Suppresses creation of the standard Default and Apply buttons
399      * for this page.
400      * <p>
401      * Subclasses wishing a preference page wihthout these buttons
402      * should call this framework method before the page's control
403      * has been created.
404      * </p>
405      */

406     protected void noDefaultAndApplyButton() {
407         createDefaultAndApplyButton = false;
408     }
409
410     /**
411      * The <code>PreferencePage</code> implementation of this
412      * <code>IPreferencePage</code> method returns <code>true</code>
413      * if the page is valid.
414      */

415     public boolean okToLeave() {
416         return isValid();
417     }
418
419     /**
420      * Performs special processing when this page's Apply button has been pressed.
421      * <p>
422      * This is a framework hook method for sublcasses to do special things when
423      * the Apply button has been pressed.
424      * The default implementation of this framework method simply calls
425      * <code>performOk</code> to simulate the pressing of the page's OK button.
426      * </p>
427      *
428      * @see #performOk
429      */

430     protected void performApply() {
431         performOk();
432     }
433
434     /**
435      * The preference page implementation of an <code>IPreferencePage</code>
436      * method performs special processing when this page's Cancel button has
437      * been pressed.
438      * <p>
439      * This is a framework hook method for sublcasses to do special things when
440      * the Cancel button has been pressed. The default implementation of this
441      * framework method does nothing and returns <code>true</code>.
442      */

443     public boolean performCancel() {
444         return true;
445     }
446
447     /**
448      * Performs special processing when this page's Defaults button has been pressed.
449      * <p>
450      * This is a framework hook method for subclasses to do special things when
451      * the Defaults button has been pressed.
452      * Subclasses may override, but should call <code>super.performDefaults</code>.
453      * </p>
454      */

455     protected void performDefaults() {
456         updateApplyButton();
457     }
458
459     /**
460      * Method declared on IPreferencePage.
461      * Subclasses should override
462      */

463     public boolean performOk() {
464         return true;
465     }
466
467     /** (non-Javadoc)
468      * Method declared on IPreferencePage.
469      */

470     public void setContainer(IPreferencePageContainer container) {
471         this.container = container;
472     }
473
474     /**
475      * Sets the preference store for this preference page.
476      * <p>
477      * If preferenceStore is set to null, getPreferenceStore
478      * will invoke doGetPreferenceStore the next time it is called.
479      * </p>
480      *
481      * @param store the preference store, or <code>null</code>
482      * @see #getPreferenceStore
483      */

484     public void setPreferenceStore(IPreferenceStore store) {
485         preferenceStore = store;
486     }
487
488     /* (non-Javadoc)
489      * Method declared on IPreferencePage.
490      */

491     public void setSize(Point uiSize) {
492         Control control = getControl();
493         if (control != null) {
494             control.setSize(uiSize);
495             size = uiSize;
496         }
497     }
498
499     /**
500      * The <code>PreferencePage</code> implementation of this <code>IDialogPage</code>
501      * method extends the <code>DialogPage</code> implementation to update
502      * the preference page container title. Subclasses may extend.
503      */

504     public void setTitle(String JavaDoc title) {
505         super.setTitle(title);
506         if (getContainer() != null) {
507             getContainer().updateTitle();
508         }
509     }
510
511     /**
512      * Sets whether this page is valid.
513      * The enable state of the container buttons and the
514      * apply button is updated when a page's valid state
515      * changes.
516      * <p>
517      *
518      * @param b the new valid state
519      */

520     public void setValid(boolean b) {
521         boolean oldValue = isValid;
522         isValid = b;
523         if (oldValue != isValid) {
524             // update container state
525
if (getContainer() != null) {
526                 getContainer().updateButtons();
527             }
528             // update page state
529
updateApplyButton();
530         }
531     }
532
533     /**
534      * Returns a string suitable for debugging purpose only.
535      */

536     public String JavaDoc toString() {
537         return getTitle();
538     }
539
540     /**
541      * Updates the enabled state of the Apply button to reflect whether
542      * this page is valid.
543      */

544     protected void updateApplyButton() {
545         if (applyButton != null) {
546             applyButton.setEnabled(isValid());
547         }
548     }
549
550     /**
551      * Creates a composite with a highlighted Note entry and a message text.
552      * This is designed to take up the full width of the page.
553      *
554      * @param font the font to use
555      * @param composite the parent composite
556      * @param title the title of the note
557      * @param message the message for the note
558      * @return the composite for the note
559      */

560     protected Composite createNoteComposite(Font font, Composite composite,
561             String JavaDoc title, String JavaDoc message) {
562         Composite messageComposite = new Composite(composite, SWT.NONE);
563         GridLayout messageLayout = new GridLayout();
564         messageLayout.numColumns = 2;
565         messageLayout.marginWidth = 0;
566         messageLayout.marginHeight = 0;
567         messageComposite.setLayout(messageLayout);
568         messageComposite.setLayoutData(new GridData(
569                 GridData.HORIZONTAL_ALIGN_FILL));
570         messageComposite.setFont(font);
571
572         final Label noteLabel = new Label(messageComposite, SWT.BOLD);
573         noteLabel.setText(title);
574         noteLabel.setFont(JFaceResources.getFontRegistry().getBold(
575                 JFaceResources.DEFAULT_FONT));
576         noteLabel
577                 .setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
578
579         final IPropertyChangeListener fontListener = new IPropertyChangeListener() {
580             public void propertyChange(PropertyChangeEvent event) {
581                 if (JFaceResources.BANNER_FONT.equals(event.getProperty())) {
582                     noteLabel.setFont(JFaceResources
583                             .getFont(JFaceResources.BANNER_FONT));
584                 }
585             }
586         };
587         JFaceResources.getFontRegistry().addListener(fontListener);
588         noteLabel.addDisposeListener(new DisposeListener() {
589             public void widgetDisposed(DisposeEvent event) {
590                 JFaceResources.getFontRegistry().removeListener(fontListener);
591             }
592         });
593
594         Label messageLabel = new Label(messageComposite, SWT.WRAP);
595         messageLabel.setText(message);
596         messageLabel.setFont(font);
597         return messageComposite;
598     }
599
600     /**
601      * Returns the Apply button.
602      *
603      * @return the Apply button
604      */

605     protected Button getApplyButton() {
606         return applyButton;
607     }
608
609     /**
610      * Returns the Restore Defaults button.
611      *
612      * @return the Restore Defaults button
613      */

614     protected Button getDefaultsButton() {
615         return defaultsButton;
616     }
617
618     /* (non-Javadoc)
619      * @see org.eclipse.jface.dialogs.IDialogPage#performHelp()
620      */

621     public void performHelp() {
622         getControl().notifyListeners(SWT.Help, new Event());
623     }
624
625     /**
626      * Apply the data to the receiver. By default do nothing.
627      * @param data
628      * @since 3.1
629      */

630     public void applyData(Object JavaDoc data) {
631         
632     }
633     
634     /* (non-Javadoc)
635      * @see org.eclipse.jface.dialogs.DialogPage#setErrorMessage(java.lang.String)
636      */

637     public void setErrorMessage(String JavaDoc newMessage) {
638         super.setErrorMessage(newMessage);
639         if (getContainer() != null) {
640             getContainer().updateMessage();
641         }
642     }
643     
644     /* (non-Javadoc)
645      * @see org.eclipse.jface.dialogs.DialogPage#setMessage(java.lang.String, int)
646      */

647     public void setMessage(String JavaDoc newMessage, int newType) {
648         super.setMessage(newMessage, newType);
649         if (getContainer() != null) {
650             getContainer().updateMessage();
651         }
652     }
653
654 }
655
Popular Tags