KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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  * Teddy Walker <teddy.walker@googlemail.com>
11  * - Bug 188056 [Preferences] PreferencePages have to less indent in PreferenceDialog
12  *******************************************************************************/

13 package org.eclipse.jface.preference;
14
15 import java.io.IOException JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18
19 import org.eclipse.core.runtime.Assert;
20 import org.eclipse.core.runtime.ISafeRunnable;
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.core.runtime.ListenerList;
23 import org.eclipse.core.runtime.SafeRunner;
24 import org.eclipse.core.runtime.Status;
25 import org.eclipse.jface.dialogs.DialogMessageArea;
26 import org.eclipse.jface.dialogs.IDialogConstants;
27 import org.eclipse.jface.dialogs.IMessageProvider;
28 import org.eclipse.jface.dialogs.IPageChangeProvider;
29 import org.eclipse.jface.dialogs.IPageChangedListener;
30 import org.eclipse.jface.dialogs.MessageDialog;
31 import org.eclipse.jface.dialogs.PageChangedEvent;
32 import org.eclipse.jface.dialogs.TrayDialog;
33 import org.eclipse.jface.resource.JFaceResources;
34 import org.eclipse.jface.util.IPropertyChangeListener;
35 import org.eclipse.jface.util.Policy;
36 import org.eclipse.jface.util.PropertyChangeEvent;
37 import org.eclipse.jface.util.SafeRunnable;
38 import org.eclipse.jface.viewers.ISelection;
39 import org.eclipse.jface.viewers.ISelectionChangedListener;
40 import org.eclipse.jface.viewers.IStructuredSelection;
41 import org.eclipse.jface.viewers.SelectionChangedEvent;
42 import org.eclipse.jface.viewers.StructuredSelection;
43 import org.eclipse.jface.viewers.TreeViewer;
44 import org.eclipse.jface.viewers.ViewerFilter;
45 import org.eclipse.swt.SWT;
46 import org.eclipse.swt.custom.BusyIndicator;
47 import org.eclipse.swt.custom.ScrolledComposite;
48 import org.eclipse.swt.events.ControlAdapter;
49 import org.eclipse.swt.events.ControlEvent;
50 import org.eclipse.swt.events.DisposeEvent;
51 import org.eclipse.swt.events.DisposeListener;
52 import org.eclipse.swt.events.HelpEvent;
53 import org.eclipse.swt.events.HelpListener;
54 import org.eclipse.swt.events.SelectionAdapter;
55 import org.eclipse.swt.events.SelectionEvent;
56 import org.eclipse.swt.events.ShellAdapter;
57 import org.eclipse.swt.events.ShellEvent;
58 import org.eclipse.swt.graphics.Font;
59 import org.eclipse.swt.graphics.Point;
60 import org.eclipse.swt.graphics.Rectangle;
61 import org.eclipse.swt.layout.FormAttachment;
62 import org.eclipse.swt.layout.FormData;
63 import org.eclipse.swt.layout.FormLayout;
64 import org.eclipse.swt.layout.GridData;
65 import org.eclipse.swt.layout.GridLayout;
66 import org.eclipse.swt.widgets.Button;
67 import org.eclipse.swt.widgets.Composite;
68 import org.eclipse.swt.widgets.Control;
69 import org.eclipse.swt.widgets.Event;
70 import org.eclipse.swt.widgets.Label;
71 import org.eclipse.swt.widgets.Layout;
72 import org.eclipse.swt.widgets.Listener;
73 import org.eclipse.swt.widgets.Sash;
74 import org.eclipse.swt.widgets.Shell;
75 import org.eclipse.swt.widgets.Tree;
76
77 /**
78  * A preference dialog is a hierarchical presentation of preference pages. Each
79  * page is represented by a node in the tree shown on the left hand side of the
80  * dialog; when a node is selected, the corresponding page is shown on the right
81  * hand side.
82  */

83 public class PreferenceDialog extends TrayDialog implements IPreferencePageContainer, IPageChangeProvider {
84     /**
85      * Layout for the page container.
86      *
87      */

88     private class PageLayout extends Layout {
89         public Point computeSize(Composite composite, int wHint, int hHint, boolean force) {
90             if (wHint != SWT.DEFAULT && hHint != SWT.DEFAULT) {
91                 return new Point(wHint, hHint);
92             }
93             int x = minimumPageSize.x;
94             int y = minimumPageSize.y;
95             Control[] children = composite.getChildren();
96             for (int i = 0; i < children.length; i++) {
97                 Point size = children[i].computeSize(SWT.DEFAULT, SWT.DEFAULT, force);
98                 x = Math.max(x, size.x);
99                 y = Math.max(y, size.y);
100             }
101             
102             //As pages can implement thier own computeSize
103
//take it into account
104
if(currentPage != null){
105                 Point size = currentPage.computeSize();
106                 x = Math.max(x, size.x);
107                 y = Math.max(y, size.y);
108             }
109             
110             if (wHint != SWT.DEFAULT) {
111                 x = wHint;
112             }
113             if (hHint != SWT.DEFAULT) {
114                 y = hHint;
115             }
116             return new Point(x, y);
117         }
118
119         public void layout(Composite composite, boolean force) {
120             Rectangle rect = composite.getClientArea();
121             Control[] children = composite.getChildren();
122             for (int i = 0; i < children.length; i++) {
123                 children[i].setSize(rect.width, rect.height);
124             }
125         }
126     }
127
128     //The id of the last page that was selected
129
private static String JavaDoc lastPreferenceId = null;
130
131     //The last known tree width
132
private static int lastTreeWidth = 180;
133
134     /**
135      * Indentifier for the error image
136      */

137     public static final String JavaDoc PREF_DLG_IMG_TITLE_ERROR = DLG_IMG_MESSAGE_ERROR;
138
139     /**
140      * Title area fields
141      */

142     public static final String JavaDoc PREF_DLG_TITLE_IMG = "preference_dialog_title_image"; //$NON-NLS-1$
143

144     /**
145      * Return code used when dialog failed
146      */

147     protected static final int FAILED = 2;
148     
149     /**
150      * The current preference page, or <code>null</code> if there is none.
151      */

152     private IPreferencePage currentPage;
153
154     private DialogMessageArea messageArea;
155
156     private Point lastShellSize;
157
158     private IPreferenceNode lastSuccessfulNode;
159
160     /**
161      * The minimum page size; 400 by 400 by default.
162      *
163      * @see #setMinimumPageSize(Point)
164      */

165     private Point minimumPageSize = new Point(400, 400);
166
167     /**
168      * The OK button.
169      */

170     private Button okButton;
171
172     /**
173      * The Composite in which a page is shown.
174      */

175     private Composite pageContainer;
176
177     /**
178      * The preference manager.
179      */

180     private PreferenceManager preferenceManager;
181
182     /**
183      * Flag for the presence of the error message.
184      */

185     private boolean showingError = false;
186
187     /**
188      * Preference store, initially <code>null</code> meaning none.
189      *
190      * @see #setPreferenceStore
191      */

192     private IPreferenceStore preferenceStore;
193
194     private Composite titleArea;
195
196     /**
197      * The tree viewer.
198      */

199     private TreeViewer treeViewer;
200     
201     private ListenerList pageChangedListeners = new ListenerList();
202
203     /**
204      * Composite with a FormLayout to contain the title area
205      */

206     Composite formTitleComposite;
207
208     private ScrolledComposite scrolled;
209
210     /**
211      * Creates a new preference dialog under the control of the given preference
212      * manager.
213      *
214      * @param parentShell
215      * the parent shell
216      * @param manager
217      * the preference manager
218      */

219     public PreferenceDialog(Shell parentShell, PreferenceManager manager) {
220         super(parentShell);
221         setShellStyle(getShellStyle() | SWT.RESIZE | SWT.MAX);
222         preferenceManager = manager;
223     }
224
225     /*
226      * (non-Javadoc)
227      *
228      * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
229      */

230     protected void buttonPressed(int buttonId) {
231         switch (buttonId) {
232         case IDialogConstants.OK_ID: {
233             okPressed();
234             return;
235         }
236         case IDialogConstants.CANCEL_ID: {
237             cancelPressed();
238             return;
239         }
240         case IDialogConstants.HELP_ID: {
241             helpPressed();
242             return;
243         }
244         }
245     }
246
247     /*
248      * (non-Javadoc)
249      *
250      * @see org.eclipse.jface.dialogs.Dialog#cancelPressed()
251      */

252     protected void cancelPressed() {
253         // Inform all pages that we are cancelling
254
Iterator JavaDoc nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER).iterator();
255         while (nodes.hasNext()) {
256             final IPreferenceNode node = (IPreferenceNode) nodes.next();
257             if (getPage(node) != null) {
258                 SafeRunnable.run(new SafeRunnable() {
259                     public void run() {
260                         if (!getPage(node).performCancel()) {
261                             return;
262                         }
263                     }
264                 });
265             }
266         }
267         setReturnCode(CANCEL);
268         close();
269     }
270
271     /**
272      * Clear the last selected node. This is so that we not chache the last
273      * selection in case of an error.
274      */

275     void clearSelectedNode() {
276         setSelectedNodePreference(null);
277     }
278
279     /*
280      * (non-Javadoc)
281      *
282      * @see org.eclipse.jface.window.Window#close()
283      */

284     public boolean close() {
285         
286         //Do this is in a SafeRunnable as it may run client code
287
SafeRunnable runnable = new SafeRunnable(){
288             /* (non-Javadoc)
289              * @see org.eclipse.core.runtime.ISafeRunnable#run()
290              */

291             public void run() throws Exception JavaDoc {
292                 List JavaDoc nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER);
293                 for (int i = 0; i < nodes.size(); i++) {
294                     IPreferenceNode node = (IPreferenceNode) nodes.get(i);
295                     node.disposeResources();
296                 }
297                 
298             }
299             
300             /* (non-Javadoc)
301              * @see org.eclipse.jface.util.SafeRunnable#handleException(java.lang.Throwable)
302              */

303             public void handleException(Throwable JavaDoc e) {
304                 super.handleException(e);
305                 clearSelectedNode();//Do not cache a node with problems
306
}
307         };
308         
309         SafeRunner.run(runnable);
310         
311         return super.close();
312     }
313
314     /*
315      * (non-Javadoc)
316      *
317      * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
318      */

319     protected void configureShell(Shell newShell) {
320         super.configureShell(newShell);
321         newShell.setText(JFaceResources.getString("PreferenceDialog.title")); //$NON-NLS-1$
322
newShell.addShellListener(new ShellAdapter() {
323             public void shellActivated(ShellEvent e) {
324                 if (lastShellSize == null) {
325                     lastShellSize = getShell().getSize();
326                 }
327             }
328
329         });
330
331     }
332
333     /*
334      * (non-Javadoc)
335      *
336      * @see org.eclipse.jface.window.Window#constrainShellSize()
337      */

338     protected void constrainShellSize() {
339         super.constrainShellSize();
340         // record opening shell size
341
if (lastShellSize == null) {
342             lastShellSize = getShell().getSize();
343         }
344     }
345
346     /*
347      * (non-Javadoc)
348      *
349      * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
350      */

351     protected void createButtonsForButtonBar(Composite parent) {
352         // create OK and Cancel buttons by default
353
okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
354         getShell().setDefaultButton(okButton);
355         createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
356     }
357
358     /*
359      * (non-Javadoc)
360      *
361      * @see org.eclipse.jface.window.Window#createContents(org.eclipse.swt.widgets.Composite)
362      */

363     protected Control createContents(final Composite parent) {
364         final Control[] control = new Control[1];
365         BusyIndicator.showWhile(getShell().getDisplay(), new Runnable JavaDoc() {
366             public void run() {
367                 control[0] = PreferenceDialog.super.createContents(parent);
368                 // Add the first page
369
selectSavedItem();
370             }
371         });
372
373         return control[0];
374     }
375
376     /*
377      * (non-Javadoc)
378      *
379      * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
380      */

381     protected Control createDialogArea(Composite parent) {
382         final Composite composite = (Composite) super.createDialogArea(parent);
383         GridLayout parentLayout = ((GridLayout) composite.getLayout());
384         parentLayout.numColumns = 4;
385         parentLayout.marginHeight = 0;
386         parentLayout.marginWidth = 0;
387         parentLayout.verticalSpacing = 0;
388         parentLayout.horizontalSpacing = 0;
389         
390         composite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
391         
392         Control treeControl = createTreeAreaContents(composite);
393         createSash(composite,treeControl);
394         
395         Label versep = new Label(composite, SWT.SEPARATOR | SWT.VERTICAL);
396         GridData verGd = new GridData(GridData.FILL_VERTICAL | GridData.GRAB_VERTICAL);
397     
398         versep.setLayoutData(verGd);
399         versep.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, true));
400         
401         Composite pageAreaComposite = new Composite(composite, SWT.NONE);
402         pageAreaComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
403         GridLayout layout = new GridLayout(1, true);
404         layout.marginHeight = 0;
405         layout.marginWidth = 0;
406         layout.verticalSpacing = 0;
407         pageAreaComposite.setLayout(layout);
408         
409         formTitleComposite = new Composite(pageAreaComposite, SWT.NONE);
410         FormLayout titleLayout = new FormLayout();
411         titleLayout.marginWidth = 0;
412         titleLayout.marginHeight = 0;
413         formTitleComposite.setLayout(titleLayout);
414         
415         GridData titleGridData = new GridData(GridData.FILL_HORIZONTAL);
416         titleGridData.horizontalIndent = IDialogConstants.HORIZONTAL_MARGIN;
417         formTitleComposite.setLayoutData(titleGridData);
418         
419         // Build the title area and separator line
420
Composite titleComposite = new Composite(formTitleComposite, SWT.NONE);
421         layout = new GridLayout();
422         layout.marginBottom = 5;
423         layout.marginHeight = 0;
424         layout.marginWidth = 0;
425         layout.horizontalSpacing = 0;
426         titleComposite.setLayout(layout);
427         
428         FormData titleFormData = new FormData();
429         titleFormData.top = new FormAttachment(0,0);
430         titleFormData.left = new FormAttachment(0,0);
431         titleFormData.right = new FormAttachment(100,0);
432         titleFormData.bottom = new FormAttachment(100,0);
433         
434         titleComposite.setLayoutData(titleFormData);
435         createTitleArea(titleComposite);
436         
437         Label separator = new Label(pageAreaComposite, SWT.HORIZONTAL | SWT.SEPARATOR);
438
439         separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
440         
441         
442         // Build the Page container
443
pageContainer = createPageContainer(pageAreaComposite);
444         GridData pageContainerData = new GridData(GridData.FILL_BOTH);
445         pageContainerData.horizontalIndent = IDialogConstants.HORIZONTAL_MARGIN;
446         pageContainer.setLayoutData(pageContainerData);
447         // Build the separator line
448
Label bottomSeparator = new Label(parent, SWT.HORIZONTAL | SWT.SEPARATOR);
449         bottomSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
450         return composite;
451     }
452
453     /**
454      * Create the sash with right control on the right. Note
455      * that this method assumes GridData for the layout data
456      * of the rightControl.
457      * @param composite
458      * @param rightControl
459      * @return Sash
460      *
461      * @since 3.1
462      */

463     protected Sash createSash(final Composite composite, final Control rightControl) {
464         final Sash sash = new Sash(composite, SWT.VERTICAL);
465         sash.setLayoutData(new GridData(GridData.FILL_VERTICAL));
466         sash.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
467         // the following listener resizes the tree control based on sash deltas.
468
// If necessary, it will also grow/shrink the dialog.
469
sash.addListener(SWT.Selection, new Listener() {
470             /*
471              * (non-Javadoc)
472              *
473              * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
474              */

475             public void handleEvent(Event event) {
476                 if (event.detail == SWT.DRAG) {
477                     return;
478                 }
479                 int shift = event.x - sash.getBounds().x;
480                 GridData data = (GridData) rightControl.getLayoutData();
481                 int newWidthHint = data.widthHint + shift;
482                 if (newWidthHint < 20) {
483                     return;
484                 }
485                 Point computedSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
486                 Point currentSize = getShell().getSize();
487                 // if the dialog wasn't of a custom size we know we can shrink
488
// it if necessary based on sash movement.
489
boolean customSize = !computedSize.equals(currentSize);
490                 data.widthHint = newWidthHint;
491                 setLastTreeWidth(newWidthHint);
492                 composite.layout(true);
493                 // recompute based on new widget size
494
computedSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
495                 // if the dialog was of a custom size then increase it only if
496
// necessary.
497
if (customSize) {
498                     computedSize.x = Math.max(computedSize.x, currentSize.x);
499                 }
500                 computedSize.y = Math.max(computedSize.y, currentSize.y);
501                 if (computedSize.equals(currentSize)) {
502                     return;
503                 }
504                 setShellSize(computedSize.x, computedSize.y);
505                 lastShellSize = getShell().getSize();
506             }
507         });
508         return sash;
509     }
510
511     /**
512      * Creates the inner page container.
513      *
514      * @param parent
515      * @return Composite
516      */

517     protected Composite createPageContainer(Composite parent) {
518     
519         Composite outer = new Composite(parent, SWT.NONE);
520         
521         GridData outerData = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL
522                 | GridData.GRAB_VERTICAL);
523         outerData.horizontalIndent = IDialogConstants.HORIZONTAL_MARGIN;
524                 
525         outer.setLayout(new GridLayout());
526         outer.setLayoutData(outerData);
527         
528         //Create an outer composite for spacing
529
scrolled = new ScrolledComposite(outer, SWT.V_SCROLL | SWT.H_SCROLL);
530
531         scrolled.setExpandHorizontal(true);
532         scrolled.setExpandVertical(true);
533         
534         GridData scrolledData = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL
535                 | GridData.GRAB_VERTICAL);
536                 
537         scrolled.setLayoutData(scrolledData);
538         
539         Composite result = new Composite(scrolled, SWT.NONE);
540         
541         GridData resultData = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL
542                 | GridData.GRAB_VERTICAL);
543                 
544         result.setLayout(getPageLayout());
545         result.setLayoutData(resultData);
546         
547         scrolled.setContent(result);
548         
549         return result;
550     }
551
552     /**
553      * Return the layout for the composite that contains
554      * the pages.
555      * @return PageLayout
556      *
557      * @since 3.1
558      */

559     protected Layout getPageLayout() {
560         return new PageLayout();
561     }
562
563     /**
564      * Creates the wizard's title area.
565      *
566      * @param parent
567      * the SWT parent for the title area composite.
568      * @return the created title area composite.
569      */

570     protected Composite createTitleArea(Composite parent) {
571         // Create the title area which will contain
572
// a title, message, and image.
573
int margins = 2;
574         titleArea = new Composite(parent, SWT.NONE);
575         FormLayout layout = new FormLayout();
576         layout.marginHeight = 0;
577         layout.marginWidth = margins;
578         titleArea.setLayout(layout);
579
580         
581         GridData layoutData = new GridData(GridData.FILL_HORIZONTAL);
582         layoutData.verticalAlignment = SWT.TOP;
583         titleArea.setLayoutData(layoutData);
584
585         // Message label
586
messageArea = new DialogMessageArea();
587         messageArea.createContents(titleArea);
588
589         titleArea.addControlListener(new ControlAdapter() {
590             /* (non-Javadoc)
591              * @see org.eclipse.swt.events.ControlAdapter#controlResized(org.eclipse.swt.events.ControlEvent)
592              */

593             public void controlResized(ControlEvent e) {
594                 updateMessage();
595             }
596         });
597
598         final IPropertyChangeListener fontListener = new IPropertyChangeListener() {
599             public void propertyChange(PropertyChangeEvent event) {
600                 if (JFaceResources.BANNER_FONT.equals(event.getProperty())) {
601                     updateMessage();
602                 }
603                 if (JFaceResources.DIALOG_FONT.equals(event.getProperty())) {
604                     updateMessage();
605                     Font dialogFont = JFaceResources.getDialogFont();
606                     updateTreeFont(dialogFont);
607                     Control[] children = ((Composite) buttonBar).getChildren();
608                     for (int i = 0; i < children.length; i++) {
609                         children[i].setFont(dialogFont);
610                     }
611                 }
612             }
613         };
614
615         titleArea.addDisposeListener(new DisposeListener() {
616             public void widgetDisposed(DisposeEvent event) {
617                 JFaceResources.getFontRegistry().removeListener(fontListener);
618             }
619         });
620         JFaceResources.getFontRegistry().addListener(fontListener);
621         messageArea.setTitleLayoutData(createMessageAreaData());
622         messageArea.setMessageLayoutData(createMessageAreaData());
623         return titleArea;
624     }
625
626     /**
627      * Create the layout data for the message area.
628      *
629      * @return FormData for the message area.
630      */

631     private FormData createMessageAreaData() {
632         FormData messageData = new FormData();
633         messageData.top = new FormAttachment(0);
634         messageData.bottom = new FormAttachment(100);
635         messageData.right = new FormAttachment(100);
636         messageData.left = new FormAttachment(0);
637         return messageData;
638     }
639
640     /**
641      * @param parent
642      * the SWT parent for the tree area controls.
643      * @return the new <code>Control</code>.
644      * @since 3.0
645      */

646     protected Control createTreeAreaContents(Composite parent) {
647         // Build the tree an put it into the composite.
648
treeViewer = createTreeViewer(parent);
649         treeViewer.setInput(getPreferenceManager());
650         updateTreeFont(JFaceResources.getDialogFont());
651         layoutTreeAreaControl(treeViewer.getControl());
652         return treeViewer.getControl();
653     }
654
655     /**
656      * Create a new <code>TreeViewer</code>.
657      *
658      * @param parent
659      * the parent <code>Composite</code>.
660      * @return the <code>TreeViewer</code>.
661      * @since 3.0
662      */

663     protected TreeViewer createTreeViewer(Composite parent) {
664         final TreeViewer viewer = new TreeViewer(parent, SWT.NONE);
665         addListeners(viewer);
666         viewer.setLabelProvider(new PreferenceLabelProvider());
667         viewer.setContentProvider(new PreferenceContentProvider());
668         return viewer;
669     }
670
671     /**
672      * Add the listeners to the tree viewer.
673      * @param viewer
674      *
675      * @since 3.1
676      */

677     protected void addListeners(final TreeViewer viewer) {
678         viewer.addPostSelectionChangedListener(new ISelectionChangedListener() {
679             private void handleError() {
680                 try {
681                     // remove the listener temporarily so that the events caused
682
// by the error handling dont further cause error handling
683
// to occur.
684
viewer.removePostSelectionChangedListener(this);
685                     showPageFlippingAbortDialog();
686                     selectCurrentPageAgain();
687                     clearSelectedNode();
688                 } finally {
689                     viewer.addPostSelectionChangedListener(this);
690                 }
691             }
692
693             public void selectionChanged(SelectionChangedEvent event) {
694                 Object JavaDoc selection = getSingleSelection(event.getSelection());
695                 if (selection instanceof IPreferenceNode) {
696                     if (!isCurrentPageValid()) {
697                         handleError();
698                     } else if (!showPage((IPreferenceNode) selection)) {
699                         // Page flipping wasn't successful
700
handleError();
701                     } else {
702                         // Everything went well
703
lastSuccessfulNode = (IPreferenceNode) selection;
704                     }
705                 }
706             }
707         });
708         ((Tree) viewer.getControl()).addSelectionListener(new SelectionAdapter() {
709             public void widgetDefaultSelected(final SelectionEvent event) {
710                 ISelection selection = viewer.getSelection();
711                 if (selection.isEmpty()) {
712                     return;
713                 }
714                 IPreferenceNode singleSelection = getSingleSelection(selection);
715                 boolean expanded = viewer.getExpandedState(singleSelection);
716                 viewer.setExpandedState(singleSelection, !expanded);
717             }
718         });
719         //Register help listener on the tree to use context sensitive help
720
viewer.getControl().addHelpListener(new HelpListener() {
721             public void helpRequested(HelpEvent event) {
722                 // call perform help on the current page
723
if (currentPage != null) {
724                     currentPage.performHelp();
725                 }
726             }
727         });
728     }
729
730     /**
731      * Find the <code>IPreferenceNode</code> that has data the same id as the
732      * supplied value.
733      *
734      * @param nodeId
735      * the id to search for.
736      * @return <code>IPreferenceNode</code> or <code>null</code> if not
737      * found.
738      */

739     protected IPreferenceNode findNodeMatching(String JavaDoc nodeId) {
740         List JavaDoc nodes = preferenceManager.getElements(PreferenceManager.POST_ORDER);
741         for (Iterator JavaDoc i = nodes.iterator(); i.hasNext();) {
742             IPreferenceNode node = (IPreferenceNode) i.next();
743             if (node.getId().equals(nodeId)) {
744                 return node;
745             }
746         }
747         return null;
748     }
749
750     /**
751      * Get the last known right side width.
752      *
753      * @return the width.
754      */

755     protected int getLastRightWidth() {
756         return lastTreeWidth;
757     }
758
759     /**
760      * Returns the preference mananger used by this preference dialog.
761      *
762      * @return the preference mananger
763      */

764     public PreferenceManager getPreferenceManager() {
765         return preferenceManager;
766     }
767
768     /*
769      * (non-Javadoc)
770      *
771      * @see org.eclipse.jface.preference.IPreferencePageContainer#getPreferenceStore()
772      */

773     public IPreferenceStore getPreferenceStore() {
774         return preferenceStore;
775     }
776
777     /**
778      * Get the name of the selected item preference
779      *
780      * @return String
781      */

782     protected String JavaDoc getSelectedNodePreference() {
783         return lastPreferenceId;
784     }
785
786     /**
787      * @param selection
788      * the <code>ISelection</code> to examine.
789      * @return the first element, or null if empty.
790      */

791     protected IPreferenceNode getSingleSelection(ISelection selection) {
792         if (!selection.isEmpty()) {
793             IStructuredSelection structured = (IStructuredSelection) selection;
794             if (structured.getFirstElement() instanceof IPreferenceNode) {
795                 return (IPreferenceNode) structured.getFirstElement();
796             }
797         }
798         return null;
799     }
800
801     /**
802      * @return the <code>TreeViewer</code> for this dialog.
803      * @since 3.3
804      */

805     public TreeViewer getTreeViewer() {
806         return treeViewer;
807     }
808
809     /**
810      * Save the values specified in the pages.
811      * <p>
812      * The default implementation of this framework method saves all pages of
813      * type <code>PreferencePage</code> (if their store needs saving and is a
814      * <code>PreferenceStore</code>).
815      * </p>
816      * <p>
817      * Subclasses may override.
818      * </p>
819      */

820     protected void handleSave() {
821         Iterator JavaDoc nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER).iterator();
822         while (nodes.hasNext()) {
823             IPreferenceNode node = (IPreferenceNode) nodes.next();
824             IPreferencePage page = node.getPage();
825             if (page instanceof PreferencePage) {
826                 // Save now in case tbe workbench does not shutdown cleanly
827
IPreferenceStore store = ((PreferencePage) page).getPreferenceStore();
828                 if (store != null && store.needsSaving()
829                         && store instanceof IPersistentPreferenceStore) {
830                     try {
831                         ((IPersistentPreferenceStore) store).save();
832                     } catch (IOException JavaDoc e) {
833                         MessageDialog
834                                 .openError(
835                                         getShell(),
836                                         JFaceResources.getString("PreferenceDialog.saveErrorTitle"), //$NON-NLS-1$
837
JFaceResources
838                                                 .format(
839                                                         "PreferenceDialog.saveErrorMessage", new Object JavaDoc[] { page.getTitle(), e.getMessage() })); //$NON-NLS-1$
840
}
841                 }
842             }
843         }
844     }
845
846     /**
847      * Notifies that the window's close button was pressed, the close menu was
848      * selected, or the ESCAPE key pressed.
849      * <p>
850      * The default implementation of this framework method sets the window's
851      * return code to <code>CANCEL</code> and closes the window using
852      * <code>close</code>. Subclasses may extend or reimplement.
853      * </p>
854      */

855     protected void handleShellCloseEvent() {
856         // handle the same as pressing cancel
857
cancelPressed();
858     }
859
860     /**
861      * Notifies of the pressing of the Help button.
862      * <p>
863      * The default implementation of this framework method calls
864      * <code>performHelp</code> on the currently active page.
865      * </p>
866      */

867     protected void helpPressed() {
868         if (currentPage != null) {
869             currentPage.performHelp();
870         }
871     }
872
873     /**
874      * Returns whether the current page is valid.
875      *
876      * @return <code>false</code> if the current page is not valid, or or
877      * <code>true</code> if the current page is valid or there is no
878      * current page
879      */

880     protected boolean isCurrentPageValid() {
881         if (currentPage == null) {
882             return true;
883         }
884         return currentPage.isValid();
885     }
886
887     /**
888      * @param control
889      * the <code>Control</code> to lay out.
890      * @since 3.0
891      */

892     protected void layoutTreeAreaControl(Control control) {
893         GridData gd = new GridData(GridData.FILL_VERTICAL);
894         gd.widthHint = getLastRightWidth();
895         gd.verticalSpan = 1;
896         control.setLayoutData(gd);
897     }
898
899     /**
900      * The preference dialog implementation of this <code>Dialog</code>
901      * framework method sends <code>performOk</code> to all pages of the
902      * preference dialog, then calls <code>handleSave</code> on this dialog to
903      * save any state, and then calls <code>close</code> to close this dialog.
904      */

905     protected void okPressed() {
906         SafeRunnable.run(new SafeRunnable() {
907             private boolean errorOccurred;
908
909             /*
910              * (non-Javadoc)
911              *
912              * @see org.eclipse.core.runtime.ISafeRunnable#run()
913              */

914             public void run() {
915                 getButton(IDialogConstants.OK_ID).setEnabled(false);
916                 errorOccurred = false;
917                 boolean hasFailedOK = false;
918                 try {
919                     // Notify all the pages and give them a chance to abort
920
Iterator JavaDoc nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER)
921                             .iterator();
922                     while (nodes.hasNext()) {
923                         IPreferenceNode node = (IPreferenceNode) nodes.next();
924                         IPreferencePage page = node.getPage();
925                         if (page != null) {
926                             if (!page.performOk()){
927                                 hasFailedOK = true;
928                                 return;
929                             }
930                         }
931                     }
932                 } catch (Exception JavaDoc e) {
933                     handleException(e);
934                 } finally {
935                     //Don't bother closing if the OK failed
936
if(hasFailedOK){
937                         setReturnCode(FAILED);
938                         getButton(IDialogConstants.OK_ID).setEnabled(true);
939                         return;
940                     }
941                     
942                     if (!errorOccurred) {
943                         //Give subclasses the choice to save the state of the
944
//preference pages.
945
handleSave();
946                     }
947                     setReturnCode(OK);
948                     close();
949                 }
950             }
951
952             /*
953              * (non-Javadoc)
954              *
955              * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
956              */

957             public void handleException(Throwable JavaDoc e) {
958                 errorOccurred = true;
959                 
960                 Policy.getLog().log(new Status(IStatus.ERROR, Policy.JFACE, 0, e.toString(), e));
961
962                 clearSelectedNode();
963                 String JavaDoc message = JFaceResources.getString("SafeRunnable.errorMessage"); //$NON-NLS-1$
964
MessageDialog.openError(getShell(), JFaceResources.getString("Error"), message); //$NON-NLS-1$
965

966             }
967         });
968     }
969
970     /**
971      * Selects the page determined by <code>lastSuccessfulNode</code> in the
972      * page hierarchy.
973      */

974     void selectCurrentPageAgain() {
975         if (lastSuccessfulNode == null) {
976             return;
977         }
978         getTreeViewer().setSelection(new StructuredSelection(lastSuccessfulNode));
979         currentPage.setVisible(true);
980     }
981
982     /**
983      * Selects the saved item in the tree of preference pages. If it cannot do
984      * this it saves the first one.
985      */

986     protected void selectSavedItem() {
987         IPreferenceNode node = findNodeMatching(getSelectedNodePreference());
988         if (node == null) {
989             IPreferenceNode[] nodes = preferenceManager.getRootSubNodes();
990             ViewerFilter[] filters = getTreeViewer().getFilters();
991             for (int i = 0; i < nodes.length; i++) {
992                 IPreferenceNode selectedNode = nodes[i];
993                 // See if it passes all filters
994
for (int j = 0; j < filters.length; j++) {
995                     if (!filters[j].select(this.treeViewer, preferenceManager
996                             .getRoot(), selectedNode)) {
997                         selectedNode = null;
998                         break;
999                     }
1000                }
1001                // if it passes all filters select it
1002
if (selectedNode != null) {
1003                    node = selectedNode;
1004                    break;
1005                }
1006            }
1007        }
1008        if (node != null) {
1009            getTreeViewer().setSelection(new StructuredSelection(node), true);
1010            // Keep focus in tree. See bugs 2692, 2621, and 6775.
1011
getTreeViewer().getControl().setFocus();
1012        }
1013    }
1014
1015    /**
1016     * Display the given error message. The currently displayed message is saved
1017     * and will be redisplayed when the error message is set to
1018     * <code>null</code>.
1019     *
1020     * @param newErrorMessage
1021     * the errorMessage to display or <code>null</code>
1022     */

1023    public void setErrorMessage(String JavaDoc newErrorMessage) {
1024        if (newErrorMessage == null) {
1025            messageArea.clearErrorMessage();
1026        } else {
1027            messageArea.updateText(newErrorMessage, IMessageProvider.ERROR);
1028        }
1029    }
1030
1031    /**
1032     * Save the last known tree width.
1033     *
1034     * @param width
1035     * the width.
1036     */

1037    private void setLastTreeWidth(int width) {
1038        lastTreeWidth = width;
1039    }
1040
1041    /**
1042     * Set the message text. If the message line currently displays an error,
1043     * the message is stored and will be shown after a call to clearErrorMessage
1044     * <p>
1045     * Shortcut for <code>setMessage(newMessage, NONE)</code>
1046     * </p>
1047     *
1048     * @param newMessage
1049     * the message, or <code>null</code> to clear the message
1050     */

1051    public void setMessage(String JavaDoc newMessage) {
1052        setMessage(newMessage, IMessageProvider.NONE);
1053    }
1054
1055    /**
1056     * Sets the message for this dialog with an indication of what type of
1057     * message it is.
1058     * <p>
1059     * The valid message types are one of <code>NONE</code>,
1060     * <code>INFORMATION</code>,<code>WARNING</code>, or
1061     * <code>ERROR</code>.
1062     * </p>
1063     * <p>
1064     * Note that for backward compatibility, a message of type
1065     * <code>ERROR</code> is different than an error message (set using
1066     * <code>setErrorMessage</code>). An error message overrides the current
1067     * message until the error message is cleared. This method replaces the
1068     * current message and does not affect the error message.
1069     * </p>
1070     *
1071     * @param newMessage
1072     * the message, or <code>null</code> to clear the message
1073     * @param newType
1074     * the message type
1075     * @since 2.0
1076     */

1077    public void setMessage(String JavaDoc newMessage, int newType) {
1078        messageArea.updateText(newMessage, newType);
1079    }
1080
1081    /**
1082     * Sets the minimum page size.
1083     *
1084     * @param minWidth
1085     * the minimum page width
1086     * @param minHeight
1087     * the minimum page height
1088     * @see #setMinimumPageSize(Point)
1089     */

1090    public void setMinimumPageSize(int minWidth, int minHeight) {
1091        minimumPageSize.x = minWidth;
1092        minimumPageSize.y = minHeight;
1093    }
1094
1095    /**
1096     * Sets the minimum page size.
1097     *
1098     * @param size
1099     * the page size encoded as <code>new Point(width,height)</code>
1100     * @see #setMinimumPageSize(int,int)
1101     */

1102    public void setMinimumPageSize(Point size) {
1103        minimumPageSize.x = size.x;
1104        minimumPageSize.y = size.y;
1105    }
1106
1107    /**
1108     * Sets the preference store for this preference dialog.
1109     *
1110     * @param store
1111     * the preference store
1112     * @see #getPreferenceStore
1113     */

1114    public void setPreferenceStore(IPreferenceStore store) {
1115        Assert.isNotNull(store);
1116        preferenceStore = store;
1117    }
1118
1119    /**
1120     * Save the currently selected node.
1121     */

1122    private void setSelectedNode() {
1123        String JavaDoc storeValue = null;
1124        IStructuredSelection selection = (IStructuredSelection) getTreeViewer().getSelection();
1125        if (selection.size() == 1) {
1126            IPreferenceNode node = (IPreferenceNode) selection.getFirstElement();
1127            storeValue = node.getId();
1128        }
1129        setSelectedNodePreference(storeValue);
1130    }
1131
1132    /**
1133     * Sets the name of the selected item preference. Public equivalent to
1134     * <code>setSelectedNodePreference</code>.
1135     *
1136     * @param pageId
1137     * The identifier for the page
1138     * @since 3.0
1139     */

1140    public void setSelectedNode(String JavaDoc pageId) {
1141        setSelectedNodePreference(pageId);
1142    }
1143
1144    /**
1145     * Sets the name of the selected item preference.
1146     *
1147     * @param pageId
1148     * The identifier for the page
1149     */

1150    protected void setSelectedNodePreference(String JavaDoc pageId) {
1151        lastPreferenceId = pageId;
1152    }
1153
1154    /**
1155     * Changes the shell size to the given size, ensuring that it is no larger
1156     * than the display bounds.
1157     *
1158     * @param width
1159     * the shell width
1160     * @param height
1161     * the shell height
1162     */

1163    private void setShellSize(int width, int height) {
1164        Rectangle preferred = getShell().getBounds();
1165        preferred.width = width;
1166        preferred.height = height;
1167        getShell().setBounds(getConstrainedShellBounds(preferred));
1168    }
1169
1170    /**
1171     * Shows the preference page corresponding to the given preference node.
1172     * Does nothing if that page is already current.
1173     *
1174     * @param node
1175     * the preference node, or <code>null</code> if none
1176     * @return <code>true</code> if the page flip was successful, and
1177     * <code>false</code> is unsuccessful
1178     */

1179    protected boolean showPage(IPreferenceNode node) {
1180        if (node == null) {
1181            return false;
1182        }
1183        // Create the page if nessessary
1184
if (node.getPage() == null) {
1185            createPage(node);
1186        }
1187        if (node.getPage() == null) {
1188            return false;
1189        }
1190        IPreferencePage newPage = getPage(node);
1191        if (newPage == currentPage) {
1192            return true;
1193        }
1194        if (currentPage != null) {
1195            if (!currentPage.okToLeave()) {
1196                return false;
1197            }
1198        }
1199        IPreferencePage oldPage = currentPage;
1200        currentPage = newPage;
1201        // Set the new page's container
1202
currentPage.setContainer(this);
1203        // Ensure that the page control has been created
1204
// (this allows lazy page control creation)
1205
if (currentPage.getControl() == null) {
1206            final boolean[] failed = { false };
1207            SafeRunnable.run(new ISafeRunnable() {
1208                public void handleException(Throwable JavaDoc e) {
1209                    failed[0] = true;
1210                }
1211
1212                public void run() {
1213                    createPageControl(currentPage, pageContainer);
1214                }
1215            });
1216            if (failed[0]) {
1217                return false;
1218            }
1219            // the page is responsible for ensuring the created control is
1220
// accessable
1221
// via getControl.
1222
Assert.isNotNull(currentPage.getControl());
1223        }
1224        // Force calculation of the page's description label because
1225
// label can be wrapped.
1226
final Point[] size = new Point[1];
1227        final Point failed = new Point(-1, -1);
1228        SafeRunnable.run(new ISafeRunnable() {
1229            public void handleException(Throwable JavaDoc e) {
1230                size[0] = failed;
1231            }
1232
1233            public void run() {
1234                size[0] = currentPage.computeSize();
1235            }
1236        });
1237        if (size[0].equals(failed)) {
1238            return false;
1239        }
1240        Point contentSize = size[0];
1241        // Do we need resizing. Computation not needed if the
1242
// first page is inserted since computing the dialog's
1243
// size is done by calling dialog.open().
1244
// Also prevent auto resize if the user has manually resized
1245
Shell shell = getShell();
1246        Point shellSize = shell.getSize();
1247        if (oldPage != null) {
1248            Rectangle rect = pageContainer.getClientArea();
1249            Point containerSize = new Point(rect.width, rect.height);
1250            int hdiff = contentSize.x - containerSize.x;
1251            int vdiff = contentSize.y - containerSize.y;
1252            if ((hdiff > 0 || vdiff > 0) && shellSize.equals(lastShellSize)) {
1253                    hdiff = Math.max(0, hdiff);
1254                    vdiff = Math.max(0, vdiff);
1255                    setShellSize(shellSize.x + hdiff, shellSize.y + vdiff);
1256                    lastShellSize = shell.getSize();
1257                    if (currentPage.getControl().getSize().x == 0) {
1258                        currentPage.getControl().setSize(containerSize);
1259                    }
1260                
1261            } else {
1262                currentPage.setSize(containerSize);
1263            }
1264        }
1265        
1266        scrolled.setMinSize(contentSize);
1267        // Ensure that all other pages are invisible
1268
// (including ones that triggered an exception during
1269
// their creation).
1270
Control[] children = pageContainer.getChildren();
1271        Control currentControl = currentPage.getControl();
1272        for (int i = 0; i < children.length; i++) {
1273            if (children[i] != currentControl) {
1274                children[i].setVisible(false);
1275            }
1276        }
1277        // Make the new page visible
1278
currentPage.setVisible(true);
1279        if (oldPage != null) {
1280            oldPage.setVisible(false);
1281        }
1282        // update the dialog controls
1283
update();
1284        return true;
1285    }
1286
1287    /**
1288     * Create the page for the node.
1289     * @param node
1290     *
1291     * @since 3.1
1292     */

1293    protected void createPage(IPreferenceNode node) {
1294        node.createPage();
1295    }
1296
1297    /**
1298     * Get the page for the node.
1299     * @param node
1300     * @return IPreferencePage
1301     *
1302     * @since 3.1
1303     */

1304    protected IPreferencePage getPage(IPreferenceNode node) {
1305        return node.getPage();
1306    }
1307
1308    /**
1309     * Shows the "Page Flipping abort" dialog.
1310     */

1311    void showPageFlippingAbortDialog() {
1312        MessageDialog.openError(getShell(), JFaceResources
1313                .getString("AbortPageFlippingDialog.title"), //$NON-NLS-1$
1314
JFaceResources.getString("AbortPageFlippingDialog.message")); //$NON-NLS-1$
1315
}
1316
1317    /**
1318     * Updates this dialog's controls to reflect the current page.
1319     */

1320    protected void update() {
1321        // Update the title bar
1322
updateTitle();
1323        // Update the message line
1324
updateMessage();
1325        // Update the buttons
1326
updateButtons();
1327        //Saved the selected node in the preferences
1328
setSelectedNode();
1329        firePageChanged(new PageChangedEvent(this, getCurrentPage()));
1330    }
1331
1332    /*
1333     * (non-Javadoc)
1334     *
1335     * @see org.eclipse.jface.preference.IPreferencePageContainer#updateButtons()
1336     */

1337    public void updateButtons() {
1338        okButton.setEnabled(isCurrentPageValid());
1339    }
1340
1341    /*
1342     * (non-Javadoc)
1343     *
1344     * @see org.eclipse.jface.preference.IPreferencePageContainer#updateMessage()
1345     */

1346    public void updateMessage() {
1347        String JavaDoc message = null;
1348        String JavaDoc errorMessage = null;
1349        if(currentPage != null){
1350            message = currentPage.getMessage();
1351            errorMessage = currentPage.getErrorMessage();
1352        }
1353        int messageType = IMessageProvider.NONE;
1354        if (message != null && currentPage instanceof IMessageProvider) {
1355            messageType = ((IMessageProvider) currentPage).getMessageType();
1356        }
1357
1358        if (errorMessage == null){
1359            if (showingError) {
1360                // we were previously showing an error
1361
showingError = false;
1362            }
1363        }
1364        else {
1365            message = errorMessage;
1366            messageType = IMessageProvider.ERROR;
1367            if (!showingError) {
1368                // we were not previously showing an error
1369
showingError = true;
1370            }
1371        }
1372        messageArea.updateText(message,messageType);
1373    }
1374
1375    /*
1376     * (non-Javadoc)
1377     *
1378     * @see org.eclipse.jface.preference.IPreferencePageContainer#updateTitle()
1379     */

1380    public void updateTitle() {
1381        if(currentPage == null) {
1382            return;
1383        }
1384        messageArea.showTitle(currentPage.getTitle(), currentPage.getImage());
1385    }
1386
1387    /**
1388     * Update the tree to use the specified <code>Font</code>.
1389     *
1390     * @param dialogFont
1391     * the <code>Font</code> to use.
1392     * @since 3.0
1393     */

1394    protected void updateTreeFont(Font dialogFont) {
1395        getTreeViewer().getControl().setFont(dialogFont);
1396    }
1397
1398    /**
1399     * Returns the currentPage.
1400     * @return IPreferencePage
1401     * @since 3.1
1402     */

1403    protected IPreferencePage getCurrentPage() {
1404        return currentPage;
1405    }
1406
1407    /**
1408     * Sets the current page.
1409     * @param currentPage
1410     *
1411     * @since 3.1
1412     */

1413    protected void setCurrentPage(IPreferencePage currentPage) {
1414        this.currentPage = currentPage;
1415    }
1416
1417    /**
1418     * Set the treeViewer.
1419     * @param treeViewer
1420     *
1421     * @since 3.1
1422     */

1423    protected void setTreeViewer(TreeViewer treeViewer) {
1424        this.treeViewer = treeViewer;
1425    }
1426
1427    /**
1428     * Get the composite that is showing the page.
1429     *
1430     * @return Composite.
1431     *
1432     * @since 3.1
1433     */

1434    protected Composite getPageContainer() {
1435        return this.pageContainer;
1436    }
1437
1438    /**
1439     * Set the composite that is showing the page.
1440     * @param pageContainer Composite
1441     *
1442     * @since 3.1
1443     */

1444    protected void setPageContainer(Composite pageContainer) {
1445        this.pageContainer = pageContainer;
1446    }
1447    /**
1448     * Create the page control for the supplied page.
1449     *
1450     * @param page - the preference page to be shown
1451     * @param parent - the composite to parent the page
1452     *
1453     * @since 3.1
1454     */

1455    protected void createPageControl(IPreferencePage page, Composite parent) {
1456        page.createControl(parent);
1457    }
1458    
1459    /**
1460     * @see org.eclipse.jface.dialogs.IPageChangeProvider#getSelectedPage()
1461     *
1462     * @since 3.1
1463     */

1464    public Object JavaDoc getSelectedPage() {
1465            return getCurrentPage();
1466        }
1467    
1468    /**
1469     * @see org.eclipse.jface.dialogs.IPageChangeProvider#addPageChangedListener(org.eclipse.jface.dialogs.IPageChangedListener)
1470     * @since 3.1
1471     */

1472    public void addPageChangedListener(IPageChangedListener listener) {
1473        pageChangedListeners.add(listener);
1474    }
1475    
1476    /**
1477     * @see org.eclipse.jface.dialogs.IPageChangeProvider#removePageChangedListener(org.eclipse.jface.dialogs.IPageChangedListener)
1478     * @since 3.1
1479     */

1480    public void removePageChangedListener(IPageChangedListener listener) {
1481        pageChangedListeners.remove(listener);
1482        
1483    }
1484
1485    /**
1486     * Notifies any selection changed listeners that the selected page
1487     * has changed.
1488     * Only listeners registered at the time this method is called are notified.
1489     *
1490     * @param event a selection changed event
1491     *
1492     * @see IPageChangedListener#pageChanged
1493     *
1494     * @since 3.1
1495     */

1496    protected void firePageChanged(final PageChangedEvent event) {
1497        Object JavaDoc[] listeners = pageChangedListeners.getListeners();
1498        for (int i = 0; i < listeners.length; i++) {
1499            final IPageChangedListener l = (IPageChangedListener) listeners[i];
1500            SafeRunnable.run(new SafeRunnable() {
1501                public void run() {
1502                    l.pageChanged(event);
1503                }
1504            });
1505        }
1506    }
1507}
1508
Popular Tags