Mercurial > projects > dwt2
comparison org.eclipse.jface/src/org/eclipse/jface/preference/PreferenceDialog.d @ 12:bc29606a740c
Added dwt-addons in original directory structure of eclipse.org
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 14 Mar 2009 18:23:29 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
11:43904fec5dca | 12:bc29606a740c |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2000, 2008 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 * Port to the D programming language: | |
13 * Frank Benoit <benoit@tionex.de> | |
14 *******************************************************************************/ | |
15 module org.eclipse.jface.preference.PreferenceDialog; | |
16 | |
17 import org.eclipse.jface.preference.IPreferencePageContainer; | |
18 import org.eclipse.jface.preference.IPreferencePage; | |
19 import org.eclipse.jface.preference.IPreferenceNode; | |
20 import org.eclipse.jface.preference.IPreferenceStore; | |
21 import org.eclipse.jface.preference.IPersistentPreferenceStore; | |
22 import org.eclipse.jface.preference.PreferenceManager; | |
23 import org.eclipse.jface.preference.PreferencePage; | |
24 import org.eclipse.jface.preference.PreferenceLabelProvider; | |
25 import org.eclipse.jface.preference.PreferenceContentProvider; | |
26 | |
27 import org.eclipse.swt.SWT; | |
28 import org.eclipse.swt.custom.BusyIndicator; | |
29 import org.eclipse.swt.custom.ScrolledComposite; | |
30 import org.eclipse.swt.events.ControlAdapter; | |
31 import org.eclipse.swt.events.ControlEvent; | |
32 import org.eclipse.swt.events.DisposeEvent; | |
33 import org.eclipse.swt.events.DisposeListener; | |
34 import org.eclipse.swt.events.HelpEvent; | |
35 import org.eclipse.swt.events.HelpListener; | |
36 import org.eclipse.swt.events.SelectionAdapter; | |
37 import org.eclipse.swt.events.SelectionEvent; | |
38 import org.eclipse.swt.events.ShellAdapter; | |
39 import org.eclipse.swt.events.ShellEvent; | |
40 import org.eclipse.swt.graphics.Font; | |
41 import org.eclipse.swt.graphics.Point; | |
42 import org.eclipse.swt.graphics.Rectangle; | |
43 import org.eclipse.swt.layout.FormAttachment; | |
44 import org.eclipse.swt.layout.FormData; | |
45 import org.eclipse.swt.layout.FormLayout; | |
46 import org.eclipse.swt.layout.GridData; | |
47 import org.eclipse.swt.layout.GridLayout; | |
48 import org.eclipse.swt.widgets.Button; | |
49 import org.eclipse.swt.widgets.Composite; | |
50 import org.eclipse.swt.widgets.Control; | |
51 import org.eclipse.swt.widgets.Event; | |
52 import org.eclipse.swt.widgets.Label; | |
53 import org.eclipse.swt.widgets.Layout; | |
54 import org.eclipse.swt.widgets.Listener; | |
55 import org.eclipse.swt.widgets.Sash; | |
56 import org.eclipse.swt.widgets.Shell; | |
57 import org.eclipse.swt.widgets.Tree; | |
58 import org.eclipse.core.runtime.Assert; | |
59 import org.eclipse.core.runtime.ISafeRunnable; | |
60 import org.eclipse.core.runtime.IStatus; | |
61 import org.eclipse.core.runtime.ListenerList; | |
62 import org.eclipse.core.runtime.SafeRunner; | |
63 import org.eclipse.core.runtime.Status; | |
64 import org.eclipse.jface.dialogs.DialogMessageArea; | |
65 import org.eclipse.jface.dialogs.IDialogConstants; | |
66 import org.eclipse.jface.dialogs.IMessageProvider; | |
67 import org.eclipse.jface.dialogs.IPageChangeProvider; | |
68 import org.eclipse.jface.dialogs.IPageChangedListener; | |
69 import org.eclipse.jface.dialogs.MessageDialog; | |
70 import org.eclipse.jface.dialogs.PageChangedEvent; | |
71 import org.eclipse.jface.dialogs.TrayDialog; | |
72 import org.eclipse.jface.resource.JFaceResources; | |
73 import org.eclipse.jface.util.IPropertyChangeListener; | |
74 import org.eclipse.jface.util.Policy; | |
75 import org.eclipse.jface.util.PropertyChangeEvent; | |
76 import org.eclipse.jface.util.SafeRunnable; | |
77 import org.eclipse.jface.viewers.ISelection; | |
78 import org.eclipse.jface.viewers.ISelectionChangedListener; | |
79 import org.eclipse.jface.viewers.IStructuredSelection; | |
80 import org.eclipse.jface.viewers.SelectionChangedEvent; | |
81 import org.eclipse.jface.viewers.StructuredSelection; | |
82 import org.eclipse.jface.viewers.TreeViewer; | |
83 import org.eclipse.jface.viewers.ViewerComparator; | |
84 import org.eclipse.jface.viewers.ViewerFilter; | |
85 | |
86 import java.lang.all; | |
87 import java.util.List; | |
88 import java.util.Iterator; | |
89 import java.util.Set; | |
90 | |
91 /** | |
92 * A preference dialog is a hierarchical presentation of preference pages. Each | |
93 * page is represented by a node in the tree shown on the left hand side of the | |
94 * dialog; when a node is selected, the corresponding page is shown on the right | |
95 * hand side. | |
96 */ | |
97 public class PreferenceDialog : TrayDialog, IPreferencePageContainer, IPageChangeProvider { | |
98 /** | |
99 * Layout for the page container. | |
100 * | |
101 */ | |
102 private class PageLayout : Layout { | |
103 public override Point computeSize(Composite composite, int wHint, int hHint, bool force) { | |
104 if (wHint !is SWT.DEFAULT && hHint !is SWT.DEFAULT) { | |
105 return new Point(wHint, hHint); | |
106 } | |
107 int x = minimumPageSize.x; | |
108 int y = minimumPageSize.y; | |
109 Control[] children = composite.getChildren(); | |
110 for (int i = 0; i < children.length; i++) { | |
111 Point size = children[i].computeSize(SWT.DEFAULT, SWT.DEFAULT, force); | |
112 x = Math.max(x, size.x); | |
113 y = Math.max(y, size.y); | |
114 } | |
115 | |
116 //As pages can implement thier own computeSize | |
117 //take it into account | |
118 if(currentPage !is null){ | |
119 Point size = currentPage.computeSize(); | |
120 x = Math.max(x, size.x); | |
121 y = Math.max(y, size.y); | |
122 } | |
123 | |
124 if (wHint !is SWT.DEFAULT) { | |
125 x = wHint; | |
126 } | |
127 if (hHint !is SWT.DEFAULT) { | |
128 y = hHint; | |
129 } | |
130 return new Point(x, y); | |
131 } | |
132 | |
133 public override void layout(Composite composite, bool force) { | |
134 Rectangle rect = composite.getClientArea(); | |
135 Control[] children = composite.getChildren(); | |
136 for (int i = 0; i < children.length; i++) { | |
137 children[i].setSize(rect.width, rect.height); | |
138 } | |
139 } | |
140 } | |
141 | |
142 //The id of the last page that was selected | |
143 private static String lastPreferenceId = null; | |
144 | |
145 //The last known tree width | |
146 private static int lastTreeWidth = 180; | |
147 | |
148 /** | |
149 * Indentifier for the error image | |
150 */ | |
151 public static const String PREF_DLG_IMG_TITLE_ERROR = DLG_IMG_MESSAGE_ERROR; | |
152 | |
153 /** | |
154 * Title area fields | |
155 */ | |
156 public static const String PREF_DLG_TITLE_IMG = "preference_dialog_title_image"; //$NON-NLS-1$ | |
157 | |
158 /** | |
159 * Return code used when dialog failed | |
160 */ | |
161 protected static const int FAILED = 2; | |
162 | |
163 /** | |
164 * The current preference page, or <code>null</code> if there is none. | |
165 */ | |
166 private IPreferencePage currentPage; | |
167 | |
168 private DialogMessageArea messageArea; | |
169 | |
170 private Point lastShellSize; | |
171 | |
172 private IPreferenceNode lastSuccessfulNode; | |
173 | |
174 /** | |
175 * The minimum page size; 400 by 400 by default. | |
176 * | |
177 * @see #setMinimumPageSize(Point) | |
178 */ | |
179 private Point minimumPageSize; | |
180 | |
181 /** | |
182 * The OK button. | |
183 */ | |
184 private Button okButton; | |
185 | |
186 /** | |
187 * The Composite in which a page is shown. | |
188 */ | |
189 private Composite pageContainer; | |
190 | |
191 /** | |
192 * The preference manager. | |
193 */ | |
194 private PreferenceManager preferenceManager; | |
195 | |
196 /** | |
197 * Flag for the presence of the error message. | |
198 */ | |
199 private bool showingError = false; | |
200 | |
201 /** | |
202 * Preference store, initially <code>null</code> meaning none. | |
203 * | |
204 * @see #setPreferenceStore | |
205 */ | |
206 private IPreferenceStore preferenceStore; | |
207 | |
208 private Composite titleArea; | |
209 | |
210 /** | |
211 * The tree viewer. | |
212 */ | |
213 private TreeViewer treeViewer; | |
214 | |
215 private ListenerList pageChangedListeners; | |
216 | |
217 /** | |
218 * Composite with a FormLayout to contain the title area | |
219 */ | |
220 Composite formTitleComposite; | |
221 | |
222 private ScrolledComposite scrolled; | |
223 | |
224 /** | |
225 * Creates a new preference dialog under the control of the given preference | |
226 * manager. | |
227 * | |
228 * @param parentShell | |
229 * the parent shell | |
230 * @param manager | |
231 * the preference manager | |
232 */ | |
233 public this(Shell parentShell, PreferenceManager manager) { | |
234 minimumPageSize = new Point(400, 400); | |
235 pageChangedListeners = new ListenerList(); | |
236 super(parentShell); | |
237 preferenceManager = manager; | |
238 } | |
239 | |
240 /* | |
241 * (non-Javadoc) | |
242 * | |
243 * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int) | |
244 */ | |
245 protected override void buttonPressed(int buttonId) { | |
246 switch (buttonId) { | |
247 case IDialogConstants.OK_ID: { | |
248 okPressed(); | |
249 return; | |
250 } | |
251 case IDialogConstants.CANCEL_ID: { | |
252 cancelPressed(); | |
253 return; | |
254 } | |
255 case IDialogConstants.HELP_ID: { | |
256 helpPressed(); | |
257 return; | |
258 } | |
259 default: | |
260 } | |
261 } | |
262 | |
263 /* | |
264 * (non-Javadoc) | |
265 * | |
266 * @see org.eclipse.jface.dialogs.Dialog#cancelPressed() | |
267 */ | |
268 protected override void cancelPressed() { | |
269 // Inform all pages that we are cancelling | |
270 Iterator nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER).iterator(); | |
271 while (nodes.hasNext()) { | |
272 IPreferenceNode node = cast(IPreferenceNode) nodes.next(); | |
273 if (getPage(node) !is null) { | |
274 | |
275 // this_: strange workaround for compiler error with dmd 1.028 in run() | |
276 SafeRunnable.run(dgSafeRunnable((IPreferenceNode node_, PreferenceDialog this_) { | |
277 if (!this_.getPage(node_).performCancel()) { | |
278 return; | |
279 } | |
280 }, cast(IPreferenceNode)node, this )); | |
281 } | |
282 } | |
283 setReturnCode(CANCEL); | |
284 close(); | |
285 } | |
286 | |
287 /** | |
288 * Clear the last selected node. This is so that we not chache the last | |
289 * selection in case of an error. | |
290 */ | |
291 void clearSelectedNode() { | |
292 setSelectedNodePreference(null); | |
293 } | |
294 | |
295 /* | |
296 * (non-Javadoc) | |
297 * | |
298 * @see org.eclipse.jface.window.Window#close() | |
299 */ | |
300 public override bool close() { | |
301 | |
302 //Do this is in a SafeRunnable as it may run client code | |
303 SafeRunnable runnable = new class SafeRunnable{ | |
304 /* (non-Javadoc) | |
305 * @see org.eclipse.core.runtime.ISafeRunnable#run() | |
306 */ | |
307 public void run() { | |
308 auto nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER); | |
309 for (int i = 0; i < nodes.size(); i++) { | |
310 IPreferenceNode node = cast(IPreferenceNode) nodes.get(i); | |
311 node.disposeResources(); | |
312 } | |
313 | |
314 } | |
315 | |
316 /* (non-Javadoc) | |
317 * @see org.eclipse.jface.util.SafeRunnable#handleException(java.lang.Throwable) | |
318 */ | |
319 public void handleException(Exception e) { | |
320 super.handleException(e); | |
321 clearSelectedNode();//Do not cache a node with problems | |
322 } | |
323 }; | |
324 | |
325 SafeRunner.run(runnable); | |
326 | |
327 return super.close(); | |
328 } | |
329 | |
330 /* | |
331 * (non-Javadoc) | |
332 * | |
333 * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) | |
334 */ | |
335 protected override void configureShell(Shell newShell) { | |
336 super.configureShell(newShell); | |
337 newShell.setText(JFaceResources.getString("PreferenceDialog.title")); //$NON-NLS-1$ | |
338 newShell.addShellListener(new class ShellAdapter { | |
339 public void shellActivated(ShellEvent e) { | |
340 if (lastShellSize is null) { | |
341 lastShellSize = getShell().getSize(); | |
342 } | |
343 } | |
344 | |
345 }); | |
346 | |
347 } | |
348 | |
349 /* | |
350 * (non-Javadoc) | |
351 * | |
352 * @see org.eclipse.jface.window.Window#constrainShellSize() | |
353 */ | |
354 protected override void constrainShellSize() { | |
355 super.constrainShellSize(); | |
356 // record opening shell size | |
357 if (lastShellSize is null) { | |
358 lastShellSize = getShell().getSize(); | |
359 } | |
360 } | |
361 | |
362 /* | |
363 * (non-Javadoc) | |
364 * | |
365 * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) | |
366 */ | |
367 protected override void createButtonsForButtonBar(Composite parent) { | |
368 // create OK and Cancel buttons by default | |
369 okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); | |
370 getShell().setDefaultButton(okButton); | |
371 createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); | |
372 } | |
373 | |
374 /* | |
375 * (non-Javadoc) | |
376 * | |
377 * @see org.eclipse.jface.window.Window#createContents(org.eclipse.swt.widgets.Composite) | |
378 */ | |
379 protected override Control createContents(Composite parent) { | |
380 Control[1] control; | |
381 BusyIndicator.showWhile(getShell().getDisplay(), new class(parent,control) Runnable { | |
382 Composite parent_; | |
383 Control[] control_; | |
384 this(Composite a,Control[] b){ | |
385 parent_=a; | |
386 control_=b; | |
387 } | |
388 public void run() { | |
389 control_[0] = callSuperCreateContents(parent_); | |
390 // Add the first page | |
391 selectSavedItem(); | |
392 } | |
393 }); | |
394 | |
395 return control[0]; | |
396 } | |
397 private Control callSuperCreateContents( Composite c ){ | |
398 return super.createContents( c ); | |
399 } | |
400 /* | |
401 * (non-Javadoc) | |
402 * | |
403 * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) | |
404 */ | |
405 protected override Control createDialogArea(Composite parent) { | |
406 final Composite composite = cast(Composite) super.createDialogArea(parent); | |
407 GridLayout parentLayout = (cast(GridLayout) composite.getLayout()); | |
408 parentLayout.numColumns = 4; | |
409 parentLayout.marginHeight = 0; | |
410 parentLayout.marginWidth = 0; | |
411 parentLayout.verticalSpacing = 0; | |
412 parentLayout.horizontalSpacing = 0; | |
413 | |
414 composite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); | |
415 | |
416 Control treeControl = createTreeAreaContents(composite); | |
417 createSash(composite,treeControl); | |
418 | |
419 Label versep = new Label(composite, SWT.SEPARATOR | SWT.VERTICAL); | |
420 GridData verGd = new GridData(GridData.FILL_VERTICAL | GridData.GRAB_VERTICAL); | |
421 | |
422 versep.setLayoutData(verGd); | |
423 versep.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, true)); | |
424 | |
425 Composite pageAreaComposite = new Composite(composite, SWT.NONE); | |
426 pageAreaComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); | |
427 GridLayout layout = new GridLayout(1, true); | |
428 layout.marginHeight = 0; | |
429 layout.marginWidth = 0; | |
430 layout.verticalSpacing = 0; | |
431 pageAreaComposite.setLayout(layout); | |
432 | |
433 formTitleComposite = new Composite(pageAreaComposite, SWT.NONE); | |
434 FormLayout titleLayout = new FormLayout(); | |
435 titleLayout.marginWidth = 0; | |
436 titleLayout.marginHeight = 0; | |
437 formTitleComposite.setLayout(titleLayout); | |
438 | |
439 GridData titleGridData = new GridData(GridData.FILL_HORIZONTAL); | |
440 titleGridData.horizontalIndent = IDialogConstants.HORIZONTAL_MARGIN; | |
441 formTitleComposite.setLayoutData(titleGridData); | |
442 | |
443 // Build the title area and separator line | |
444 Composite titleComposite = new Composite(formTitleComposite, SWT.NONE); | |
445 layout = new GridLayout(); | |
446 layout.marginBottom = 5; | |
447 layout.marginHeight = 0; | |
448 layout.marginWidth = 0; | |
449 layout.horizontalSpacing = 0; | |
450 titleComposite.setLayout(layout); | |
451 | |
452 FormData titleFormData = new FormData(); | |
453 titleFormData.top = new FormAttachment(0,0); | |
454 titleFormData.left = new FormAttachment(0,0); | |
455 titleFormData.right = new FormAttachment(100,0); | |
456 titleFormData.bottom = new FormAttachment(100,0); | |
457 | |
458 titleComposite.setLayoutData(titleFormData); | |
459 createTitleArea(titleComposite); | |
460 | |
461 Label separator = new Label(pageAreaComposite, SWT.HORIZONTAL | SWT.SEPARATOR); | |
462 | |
463 separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); | |
464 | |
465 | |
466 // Build the Page container | |
467 pageContainer = createPageContainer(pageAreaComposite); | |
468 GridData pageContainerData = new GridData(GridData.FILL_BOTH); | |
469 pageContainerData.horizontalIndent = IDialogConstants.HORIZONTAL_MARGIN; | |
470 pageContainer.setLayoutData(pageContainerData); | |
471 // Build the separator line | |
472 Label bottomSeparator = new Label(parent, SWT.HORIZONTAL | SWT.SEPARATOR); | |
473 bottomSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); | |
474 return composite; | |
475 } | |
476 | |
477 /** | |
478 * Create the sash with right control on the right. Note | |
479 * that this method assumes GridData for the layout data | |
480 * of the rightControl. | |
481 * @param composite | |
482 * @param rightControl | |
483 * @return Sash | |
484 * | |
485 * @since 3.1 | |
486 */ | |
487 protected Sash createSash(Composite composite, Control rightControl) { | |
488 Sash sash = new Sash(composite, SWT.VERTICAL); | |
489 sash.setLayoutData(new GridData(GridData.FILL_VERTICAL)); | |
490 sash.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); | |
491 // the following listener resizes the tree control based on sash deltas. | |
492 // If necessary, it will also grow/shrink the dialog. | |
493 sash.addListener(SWT.Selection, new class(composite,rightControl,sash) Listener { | |
494 Composite composite_; | |
495 Control rightControl_; | |
496 Sash sash_; | |
497 this(Composite a,Control b,Sash c){ | |
498 composite_=a; | |
499 rightControl_=b; | |
500 sash_=c; | |
501 } | |
502 /* | |
503 * (non-Javadoc) | |
504 * | |
505 * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) | |
506 */ | |
507 public void handleEvent(Event event) { | |
508 if (event.detail is SWT.DRAG) { | |
509 return; | |
510 } | |
511 int shift = event.x - sash_.getBounds().x; | |
512 GridData data = cast(GridData) rightControl_.getLayoutData(); | |
513 int newWidthHint = data.widthHint + shift; | |
514 if (newWidthHint < 20) { | |
515 return; | |
516 } | |
517 Point computedSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT); | |
518 Point currentSize = getShell().getSize(); | |
519 // if the dialog wasn't of a custom size we know we can shrink | |
520 // it if necessary based on sash movement. | |
521 bool customSize = !computedSize.opEquals(currentSize); | |
522 data.widthHint = newWidthHint; | |
523 setLastTreeWidth(newWidthHint); | |
524 composite_.layout(true); | |
525 // recompute based on new widget size | |
526 computedSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT); | |
527 // if the dialog was of a custom size then increase it only if | |
528 // necessary. | |
529 if (customSize) { | |
530 computedSize.x = Math.max(computedSize.x, currentSize.x); | |
531 } | |
532 computedSize.y = Math.max(computedSize.y, currentSize.y); | |
533 if (computedSize.opEquals(currentSize)) { | |
534 return; | |
535 } | |
536 setShellSize(computedSize.x, computedSize.y); | |
537 lastShellSize = getShell().getSize(); | |
538 } | |
539 }); | |
540 return sash; | |
541 } | |
542 | |
543 /** | |
544 * Creates the inner page container. | |
545 * | |
546 * @param parent | |
547 * @return Composite | |
548 */ | |
549 protected Composite createPageContainer(Composite parent) { | |
550 | |
551 Composite outer = new Composite(parent, SWT.NONE); | |
552 | |
553 GridData outerData = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | |
554 | GridData.GRAB_VERTICAL); | |
555 outerData.horizontalIndent = IDialogConstants.HORIZONTAL_MARGIN; | |
556 | |
557 outer.setLayout(new GridLayout()); | |
558 outer.setLayoutData(outerData); | |
559 | |
560 //Create an outer composite for spacing | |
561 scrolled = new ScrolledComposite(outer, SWT.V_SCROLL | SWT.H_SCROLL); | |
562 | |
563 scrolled.setExpandHorizontal(true); | |
564 scrolled.setExpandVertical(true); | |
565 | |
566 GridData scrolledData = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | |
567 | GridData.GRAB_VERTICAL); | |
568 | |
569 scrolled.setLayoutData(scrolledData); | |
570 | |
571 Composite result = new Composite(scrolled, SWT.NONE); | |
572 | |
573 GridData resultData = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | |
574 | GridData.GRAB_VERTICAL); | |
575 | |
576 result.setLayout(getPageLayout()); | |
577 result.setLayoutData(resultData); | |
578 | |
579 scrolled.setContent(result); | |
580 | |
581 return result; | |
582 } | |
583 | |
584 /** | |
585 * Return the layout for the composite that contains | |
586 * the pages. | |
587 * @return PageLayout | |
588 * | |
589 * @since 3.1 | |
590 */ | |
591 protected Layout getPageLayout() { | |
592 return new PageLayout(); | |
593 } | |
594 | |
595 /** | |
596 * Creates the wizard's title area. | |
597 * | |
598 * @param parent | |
599 * the SWT parent for the title area composite. | |
600 * @return the created title area composite. | |
601 */ | |
602 protected Composite createTitleArea(Composite parent) { | |
603 // Create the title area which will contain | |
604 // a title, message, and image. | |
605 int margins = 2; | |
606 titleArea = new Composite(parent, SWT.NONE); | |
607 FormLayout layout = new FormLayout(); | |
608 layout.marginHeight = 0; | |
609 layout.marginWidth = margins; | |
610 titleArea.setLayout(layout); | |
611 | |
612 | |
613 GridData layoutData = new GridData(GridData.FILL_HORIZONTAL); | |
614 layoutData.verticalAlignment = SWT.TOP; | |
615 titleArea.setLayoutData(layoutData); | |
616 | |
617 // Message label | |
618 messageArea = new DialogMessageArea(); | |
619 messageArea.createContents(titleArea); | |
620 | |
621 titleArea.addControlListener(new class ControlAdapter { | |
622 /* (non-Javadoc) | |
623 * @see org.eclipse.swt.events.ControlAdapter#controlResized(org.eclipse.swt.events.ControlEvent) | |
624 */ | |
625 public void controlResized(ControlEvent e) { | |
626 updateMessage(); | |
627 } | |
628 }); | |
629 | |
630 IPropertyChangeListener fontListener = new class IPropertyChangeListener { | |
631 public void propertyChange(PropertyChangeEvent event) { | |
632 if (JFaceResources.BANNER_FONT.equals(event.getProperty())) { | |
633 updateMessage(); | |
634 } | |
635 if (JFaceResources.DIALOG_FONT.equals(event.getProperty())) { | |
636 updateMessage(); | |
637 Font dialogFont = JFaceResources.getDialogFont(); | |
638 updateTreeFont(dialogFont); | |
639 Control[] children = (cast(Composite) buttonBar).getChildren(); | |
640 for (int i = 0; i < children.length; i++) { | |
641 children[i].setFont(dialogFont); | |
642 } | |
643 } | |
644 } | |
645 }; | |
646 | |
647 titleArea.addDisposeListener(new class(fontListener) DisposeListener { | |
648 IPropertyChangeListener fontListener_; | |
649 this(IPropertyChangeListener a){ | |
650 fontListener_=a; | |
651 } | |
652 public void widgetDisposed(DisposeEvent event) { | |
653 JFaceResources.getFontRegistry().removeListener(fontListener_); | |
654 } | |
655 }); | |
656 JFaceResources.getFontRegistry().addListener(fontListener); | |
657 messageArea.setTitleLayoutData(createMessageAreaData()); | |
658 messageArea.setMessageLayoutData(createMessageAreaData()); | |
659 return titleArea; | |
660 } | |
661 | |
662 /** | |
663 * Create the layout data for the message area. | |
664 * | |
665 * @return FormData for the message area. | |
666 */ | |
667 private FormData createMessageAreaData() { | |
668 FormData messageData = new FormData(); | |
669 messageData.top = new FormAttachment(0); | |
670 messageData.bottom = new FormAttachment(100); | |
671 messageData.right = new FormAttachment(100); | |
672 messageData.left = new FormAttachment(0); | |
673 return messageData; | |
674 } | |
675 | |
676 /** | |
677 * @param parent | |
678 * the SWT parent for the tree area controls. | |
679 * @return the new <code>Control</code>. | |
680 * @since 3.0 | |
681 */ | |
682 protected Control createTreeAreaContents(Composite parent) { | |
683 // Build the tree an put it into the composite. | |
684 treeViewer = createTreeViewer(parent); | |
685 treeViewer.setInput(getPreferenceManager()); | |
686 updateTreeFont(JFaceResources.getDialogFont()); | |
687 layoutTreeAreaControl(treeViewer.getControl()); | |
688 return treeViewer.getControl(); | |
689 } | |
690 | |
691 /** | |
692 * Create a new <code>TreeViewer</code>. | |
693 * | |
694 * @param parent | |
695 * the parent <code>Composite</code>. | |
696 * @return the <code>TreeViewer</code>. | |
697 * @since 3.0 | |
698 */ | |
699 protected TreeViewer createTreeViewer(Composite parent) { | |
700 final TreeViewer viewer = new TreeViewer(parent, SWT.NONE); | |
701 addListeners(viewer); | |
702 viewer.setLabelProvider(new PreferenceLabelProvider()); | |
703 viewer.setContentProvider(new PreferenceContentProvider()); | |
704 return viewer; | |
705 } | |
706 | |
707 /** | |
708 * Add the listeners to the tree viewer. | |
709 * @param viewer | |
710 * | |
711 * @since 3.1 | |
712 */ | |
713 protected void addListeners(TreeViewer viewer) { | |
714 viewer.addPostSelectionChangedListener(new class(viewer) ISelectionChangedListener { | |
715 TreeViewer viewer_; | |
716 this(TreeViewer a){ | |
717 viewer_=a; | |
718 } | |
719 private void handleError() { | |
720 try { | |
721 // remove the listener temporarily so that the events caused | |
722 // by the error handling dont further cause error handling | |
723 // to occur. | |
724 viewer_.removePostSelectionChangedListener(this); | |
725 showPageFlippingAbortDialog(); | |
726 selectCurrentPageAgain(); | |
727 clearSelectedNode(); | |
728 } finally { | |
729 viewer_.addPostSelectionChangedListener(this); | |
730 } | |
731 } | |
732 | |
733 public void selectionChanged(SelectionChangedEvent event) { | |
734 Object selection = cast(Object) getSingleSelection(event.getSelection()); | |
735 if (cast(IPreferenceNode)selection ) { | |
736 BusyIndicator.showWhile(getShell().getDisplay(), new class(selection) Runnable { | |
737 Object selection_; | |
738 this(Object o){ selection_=o; } | |
739 public void run() { | |
740 if (!isCurrentPageValid()) { | |
741 handleError(); | |
742 } else if (!showPage(cast(IPreferenceNode) selection_)) { | |
743 // Page flipping wasn't successful | |
744 handleError(); | |
745 } else { | |
746 // Everything went well | |
747 lastSuccessfulNode = cast(IPreferenceNode) selection_; | |
748 } | |
749 } | |
750 }); | |
751 } | |
752 } | |
753 }); | |
754 (cast(Tree) viewer.getControl()).addSelectionListener(new class(viewer) SelectionAdapter { | |
755 TreeViewer viewer_; | |
756 this(TreeViewer a){ | |
757 viewer_=a; | |
758 } | |
759 public void widgetDefaultSelected(SelectionEvent event) { | |
760 ISelection selection = viewer_.getSelection(); | |
761 if (selection.isEmpty()) { | |
762 return; | |
763 } | |
764 IPreferenceNode singleSelection = getSingleSelection(selection); | |
765 bool expanded = viewer_.getExpandedState(cast(Object)singleSelection); | |
766 viewer_.setExpandedState(cast(Object)singleSelection, !expanded); | |
767 } | |
768 }); | |
769 //Register help listener on the tree to use context sensitive help | |
770 viewer.getControl().addHelpListener(new class HelpListener { | |
771 public void helpRequested(HelpEvent event) { | |
772 // call perform help on the current page | |
773 if (currentPage !is null) { | |
774 currentPage.performHelp(); | |
775 } | |
776 } | |
777 }); | |
778 } | |
779 | |
780 /** | |
781 * Find the <code>IPreferenceNode</code> that has data the same id as the | |
782 * supplied value. | |
783 * | |
784 * @param nodeId | |
785 * the id to search for. | |
786 * @return <code>IPreferenceNode</code> or <code>null</code> if not | |
787 * found. | |
788 */ | |
789 protected IPreferenceNode findNodeMatching(String nodeId) { | |
790 List nodes = preferenceManager.getElements(PreferenceManager.POST_ORDER); | |
791 for (Iterator i = nodes.iterator(); i.hasNext();) { | |
792 IPreferenceNode node = cast(IPreferenceNode) i.next(); | |
793 if (node.getId().equals(nodeId)) { | |
794 return node; | |
795 } | |
796 } | |
797 return null; | |
798 } | |
799 | |
800 /** | |
801 * Get the last known right side width. | |
802 * | |
803 * @return the width. | |
804 */ | |
805 protected int getLastRightWidth() { | |
806 return lastTreeWidth; | |
807 } | |
808 | |
809 /** | |
810 * Returns the preference mananger used by this preference dialog. | |
811 * | |
812 * @return the preference mananger | |
813 */ | |
814 public PreferenceManager getPreferenceManager() { | |
815 return preferenceManager; | |
816 } | |
817 | |
818 /* | |
819 * (non-Javadoc) | |
820 * | |
821 * @see org.eclipse.jface.preference.IPreferencePageContainer#getPreferenceStore() | |
822 */ | |
823 public IPreferenceStore getPreferenceStore() { | |
824 return preferenceStore; | |
825 } | |
826 | |
827 /** | |
828 * Get the name of the selected item preference | |
829 * | |
830 * @return String | |
831 */ | |
832 protected String getSelectedNodePreference() { | |
833 return lastPreferenceId; | |
834 } | |
835 | |
836 /** | |
837 * @param selection | |
838 * the <code>ISelection</code> to examine. | |
839 * @return the first element, or null if empty. | |
840 */ | |
841 protected IPreferenceNode getSingleSelection(ISelection selection) { | |
842 if (!selection.isEmpty()) { | |
843 IStructuredSelection structured = cast(IStructuredSelection) selection; | |
844 if (cast(IPreferenceNode)structured.getFirstElement() ) { | |
845 return cast(IPreferenceNode) structured.getFirstElement(); | |
846 } | |
847 } | |
848 return null; | |
849 } | |
850 | |
851 /** | |
852 * @return the <code>TreeViewer</code> for this dialog. | |
853 * @since 3.3 | |
854 */ | |
855 public TreeViewer getTreeViewer() { | |
856 return treeViewer; | |
857 } | |
858 | |
859 /** | |
860 * Save the values specified in the pages. | |
861 * <p> | |
862 * The default implementation of this framework method saves all pages of | |
863 * type <code>PreferencePage</code> (if their store needs saving and is a | |
864 * <code>PreferenceStore</code>). | |
865 * </p> | |
866 * <p> | |
867 * Subclasses may override. | |
868 * </p> | |
869 */ | |
870 protected void handleSave() { | |
871 Iterator nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER).iterator(); | |
872 while (nodes.hasNext()) { | |
873 IPreferenceNode node = cast(IPreferenceNode) nodes.next(); | |
874 IPreferencePage page = node.getPage(); | |
875 if (cast(PreferencePage)page ) { | |
876 // Save now in case tbe workbench does not shutdown cleanly | |
877 IPreferenceStore store = (cast(PreferencePage) page).getPreferenceStore(); | |
878 if (store !is null && store.needsSaving() | |
879 && cast(IPersistentPreferenceStore)store ) { | |
880 try { | |
881 (cast(IPersistentPreferenceStore) store).save(); | |
882 } catch (IOException e) { | |
883 String message =JFaceResources.format( | |
884 "PreferenceDialog.saveErrorMessage", [ page.getTitle(), e.msg ]); //$NON-NLS-1$ | |
885 Policy.getStatusHandler().show( | |
886 new Status(IStatus.ERROR, Policy.JFACE, message, e), | |
887 JFaceResources.getString("PreferenceDialog.saveErrorTitle")); //$NON-NLS-1$ | |
888 | |
889 } | |
890 } | |
891 } | |
892 } | |
893 } | |
894 | |
895 /** | |
896 * Notifies that the window's close button was pressed, the close menu was | |
897 * selected, or the ESCAPE key pressed. | |
898 * <p> | |
899 * The default implementation of this framework method sets the window's | |
900 * return code to <code>CANCEL</code> and closes the window using | |
901 * <code>close</code>. Subclasses may extend or reimplement. | |
902 * </p> | |
903 */ | |
904 protected override void handleShellCloseEvent() { | |
905 // handle the same as pressing cancel | |
906 cancelPressed(); | |
907 } | |
908 | |
909 /** | |
910 * Notifies of the pressing of the Help button. | |
911 * <p> | |
912 * The default implementation of this framework method calls | |
913 * <code>performHelp</code> on the currently active page. | |
914 * </p> | |
915 */ | |
916 protected /+override+/ void helpPressed() { | |
917 if (currentPage !is null) { | |
918 currentPage.performHelp(); | |
919 } | |
920 } | |
921 | |
922 /** | |
923 * Returns whether the current page is valid. | |
924 * | |
925 * @return <code>false</code> if the current page is not valid, or or | |
926 * <code>true</code> if the current page is valid or there is no | |
927 * current page | |
928 */ | |
929 protected bool isCurrentPageValid() { | |
930 if (currentPage is null) { | |
931 return true; | |
932 } | |
933 return currentPage.isValid(); | |
934 } | |
935 | |
936 /** | |
937 * @param control | |
938 * the <code>Control</code> to lay out. | |
939 * @since 3.0 | |
940 */ | |
941 protected void layoutTreeAreaControl(Control control) { | |
942 GridData gd = new GridData(GridData.FILL_VERTICAL); | |
943 gd.widthHint = getLastRightWidth(); | |
944 gd.verticalSpan = 1; | |
945 control.setLayoutData(gd); | |
946 } | |
947 | |
948 /** | |
949 * The preference dialog implementation of this <code>Dialog</code> | |
950 * framework method sends <code>performOk</code> to all pages of the | |
951 * preference dialog, then calls <code>handleSave</code> on this dialog to | |
952 * save any state, and then calls <code>close</code> to close this dialog. | |
953 */ | |
954 protected override void okPressed() { | |
955 SafeRunnable.run(new class SafeRunnable { | |
956 private bool errorOccurred; | |
957 | |
958 /* | |
959 * (non-Javadoc) | |
960 * | |
961 * @see org.eclipse.core.runtime.ISafeRunnable#run() | |
962 */ | |
963 public void run() { | |
964 getButton(IDialogConstants.OK_ID).setEnabled(false); | |
965 errorOccurred = false; | |
966 bool hasFailedOK = false; | |
967 try { | |
968 // Notify all the pages and give them a chance to abort | |
969 Iterator nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER) | |
970 .iterator(); | |
971 while (nodes.hasNext()) { | |
972 IPreferenceNode node = cast(IPreferenceNode) nodes.next(); | |
973 IPreferencePage page = node.getPage(); | |
974 if (page !is null) { | |
975 if (!page.performOk()){ | |
976 hasFailedOK = true; | |
977 return; | |
978 } | |
979 } | |
980 } | |
981 } catch (Exception e) { | |
982 handleException(e); | |
983 } finally { | |
984 //Don't bother closing if the OK failed | |
985 if(hasFailedOK){ | |
986 setReturnCode(FAILED); | |
987 getButton(IDialogConstants.OK_ID).setEnabled(true); | |
988 //return; | |
989 } | |
990 else{ | |
991 | |
992 if (!errorOccurred) { | |
993 //Give subclasses the choice to save the state of the | |
994 //preference pages. | |
995 handleSave(); | |
996 } | |
997 setReturnCode(OK); | |
998 close(); | |
999 } | |
1000 } | |
1001 } | |
1002 | |
1003 /* | |
1004 * (non-Javadoc) | |
1005 * | |
1006 * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable) | |
1007 */ | |
1008 public void handleException(Exception e) { | |
1009 errorOccurred = true; | |
1010 | |
1011 Policy.getLog().log(new Status(IStatus.ERROR, Policy.JFACE, 0, e.toString(), e)); | |
1012 | |
1013 clearSelectedNode(); | |
1014 String message = JFaceResources.getString("SafeRunnable.errorMessage"); //$NON-NLS-1$ | |
1015 | |
1016 Policy.getStatusHandler().show( | |
1017 new Status(IStatus.ERROR, Policy.JFACE, message, e), | |
1018 JFaceResources.getString("Error")); //$NON-NLS-1$ | |
1019 | |
1020 } | |
1021 }); | |
1022 } | |
1023 | |
1024 /** | |
1025 * Selects the page determined by <code>lastSuccessfulNode</code> in the | |
1026 * page hierarchy. | |
1027 */ | |
1028 void selectCurrentPageAgain() { | |
1029 if (lastSuccessfulNode is null) { | |
1030 return; | |
1031 } | |
1032 getTreeViewer().setSelection(new StructuredSelection(cast(Object)lastSuccessfulNode)); | |
1033 currentPage.setVisible(true); | |
1034 } | |
1035 | |
1036 /** | |
1037 * Selects the saved item in the tree of preference pages. If it cannot do | |
1038 * this it saves the first one. | |
1039 */ | |
1040 protected void selectSavedItem() { | |
1041 IPreferenceNode node = findNodeMatching(getSelectedNodePreference()); | |
1042 if (node is null) { | |
1043 IPreferenceNode[] nodes = preferenceManager.getRootSubNodes(); | |
1044 ViewerComparator comparator = getTreeViewer().getComparator(); | |
1045 if (comparator !is null) { | |
1046 comparator.sort(null, arraycast!(Object)(nodes)); | |
1047 } | |
1048 ViewerFilter[] filters = getTreeViewer().getFilters(); | |
1049 for (int i = 0; i < nodes.length; i++) { | |
1050 IPreferenceNode selectedNode = nodes[i]; | |
1051 // See if it passes all filters | |
1052 for (int j = 0; j < filters.length; j++) { | |
1053 if (!filters[j].select(this.treeViewer, cast(Object)preferenceManager | |
1054 .getRoot_package(), cast(Object)selectedNode)) { | |
1055 selectedNode = null; | |
1056 break; | |
1057 } | |
1058 } | |
1059 // if it passes all filters select it | |
1060 if (selectedNode !is null) { | |
1061 node = selectedNode; | |
1062 break; | |
1063 } | |
1064 } | |
1065 } | |
1066 if (node !is null) { | |
1067 getTreeViewer().setSelection(new StructuredSelection(cast(Object)node), true); | |
1068 // Keep focus in tree. See bugs 2692, 2621, and 6775. | |
1069 getTreeViewer().getControl().setFocus(); | |
1070 } | |
1071 } | |
1072 | |
1073 /** | |
1074 * Display the given error message. The currently displayed message is saved | |
1075 * and will be redisplayed when the error message is set to | |
1076 * <code>null</code>. | |
1077 * | |
1078 * @param newErrorMessage | |
1079 * the errorMessage to display or <code>null</code> | |
1080 */ | |
1081 public void setErrorMessage(String newErrorMessage) { | |
1082 if (newErrorMessage is null) { | |
1083 messageArea.clearErrorMessage(); | |
1084 } else { | |
1085 messageArea.updateText(newErrorMessage, IMessageProvider.ERROR); | |
1086 } | |
1087 } | |
1088 | |
1089 /** | |
1090 * Save the last known tree width. | |
1091 * | |
1092 * @param width | |
1093 * the width. | |
1094 */ | |
1095 private void setLastTreeWidth(int width) { | |
1096 lastTreeWidth = width; | |
1097 } | |
1098 | |
1099 /** | |
1100 * Set the message text. If the message line currently displays an error, | |
1101 * the message is stored and will be shown after a call to clearErrorMessage | |
1102 * <p> | |
1103 * Shortcut for <code>setMessage(newMessage, NONE)</code> | |
1104 * </p> | |
1105 * | |
1106 * @param newMessage | |
1107 * the message, or <code>null</code> to clear the message | |
1108 */ | |
1109 public void setMessage(String newMessage) { | |
1110 setMessage(newMessage, IMessageProvider.NONE); | |
1111 } | |
1112 | |
1113 /** | |
1114 * Sets the message for this dialog with an indication of what type of | |
1115 * message it is. | |
1116 * <p> | |
1117 * The valid message types are one of <code>NONE</code>, | |
1118 * <code>INFORMATION</code>,<code>WARNING</code>, or | |
1119 * <code>ERROR</code>. | |
1120 * </p> | |
1121 * <p> | |
1122 * Note that for backward compatibility, a message of type | |
1123 * <code>ERROR</code> is different than an error message (set using | |
1124 * <code>setErrorMessage</code>). An error message overrides the current | |
1125 * message until the error message is cleared. This method replaces the | |
1126 * current message and does not affect the error message. | |
1127 * </p> | |
1128 * | |
1129 * @param newMessage | |
1130 * the message, or <code>null</code> to clear the message | |
1131 * @param newType | |
1132 * the message type | |
1133 * @since 2.0 | |
1134 */ | |
1135 public void setMessage(String newMessage, int newType) { | |
1136 messageArea.updateText(newMessage, newType); | |
1137 } | |
1138 | |
1139 /** | |
1140 * Sets the minimum page size. | |
1141 * | |
1142 * @param minWidth | |
1143 * the minimum page width | |
1144 * @param minHeight | |
1145 * the minimum page height | |
1146 * @see #setMinimumPageSize(Point) | |
1147 */ | |
1148 public void setMinimumPageSize(int minWidth, int minHeight) { | |
1149 minimumPageSize.x = minWidth; | |
1150 minimumPageSize.y = minHeight; | |
1151 } | |
1152 | |
1153 /** | |
1154 * Sets the minimum page size. | |
1155 * | |
1156 * @param size | |
1157 * the page size encoded as <code>new Point(width,height)</code> | |
1158 * @see #setMinimumPageSize(int,int) | |
1159 */ | |
1160 public void setMinimumPageSize(Point size) { | |
1161 minimumPageSize.x = size.x; | |
1162 minimumPageSize.y = size.y; | |
1163 } | |
1164 | |
1165 /** | |
1166 * Sets the preference store for this preference dialog. | |
1167 * | |
1168 * @param store | |
1169 * the preference store | |
1170 * @see #getPreferenceStore | |
1171 */ | |
1172 public void setPreferenceStore(IPreferenceStore store) { | |
1173 Assert.isNotNull(cast(Object)store); | |
1174 preferenceStore = store; | |
1175 } | |
1176 | |
1177 /** | |
1178 * Save the currently selected node. | |
1179 */ | |
1180 private void setSelectedNode() { | |
1181 String storeValue = null; | |
1182 IStructuredSelection selection = cast(IStructuredSelection) getTreeViewer().getSelection(); | |
1183 if (selection.size() is 1) { | |
1184 IPreferenceNode node = cast(IPreferenceNode) selection.getFirstElement(); | |
1185 storeValue = node.getId(); | |
1186 } | |
1187 setSelectedNodePreference(storeValue); | |
1188 } | |
1189 | |
1190 /** | |
1191 * Sets the name of the selected item preference. Public equivalent to | |
1192 * <code>setSelectedNodePreference</code>. | |
1193 * | |
1194 * @param pageId | |
1195 * The identifier for the page | |
1196 * @since 3.0 | |
1197 */ | |
1198 public void setSelectedNode(String pageId) { | |
1199 setSelectedNodePreference(pageId); | |
1200 } | |
1201 | |
1202 /** | |
1203 * Sets the name of the selected item preference. | |
1204 * | |
1205 * @param pageId | |
1206 * The identifier for the page | |
1207 */ | |
1208 protected void setSelectedNodePreference(String pageId) { | |
1209 lastPreferenceId = pageId; | |
1210 } | |
1211 | |
1212 /** | |
1213 * Changes the shell size to the given size, ensuring that it is no larger | |
1214 * than the display bounds. | |
1215 * | |
1216 * @param width | |
1217 * the shell width | |
1218 * @param height | |
1219 * the shell height | |
1220 */ | |
1221 private void setShellSize(int width, int height) { | |
1222 Rectangle preferred = getShell().getBounds(); | |
1223 preferred.width = width; | |
1224 preferred.height = height; | |
1225 getShell().setBounds(getConstrainedShellBounds(preferred)); | |
1226 } | |
1227 | |
1228 /** | |
1229 * Shows the preference page corresponding to the given preference node. | |
1230 * Does nothing if that page is already current. | |
1231 * | |
1232 * @param node | |
1233 * the preference node, or <code>null</code> if none | |
1234 * @return <code>true</code> if the page flip was successful, and | |
1235 * <code>false</code> is unsuccessful | |
1236 */ | |
1237 protected bool showPage(IPreferenceNode node) { | |
1238 if (node is null) { | |
1239 return false; | |
1240 } | |
1241 // Create the page if nessessary | |
1242 if (node.getPage() is null) { | |
1243 createPage(node); | |
1244 } | |
1245 if (node.getPage() is null) { | |
1246 return false; | |
1247 } | |
1248 IPreferencePage newPage = getPage(node); | |
1249 if (newPage is currentPage) { | |
1250 return true; | |
1251 } | |
1252 if (currentPage !is null) { | |
1253 if (!currentPage.okToLeave()) { | |
1254 return false; | |
1255 } | |
1256 } | |
1257 IPreferencePage oldPage = currentPage; | |
1258 currentPage = newPage; | |
1259 // Set the new page's container | |
1260 currentPage.setContainer(this); | |
1261 // Ensure that the page control has been created | |
1262 // (this allows lazy page control creation) | |
1263 if (currentPage.getControl() is null) { | |
1264 bool[1] failed; failed[0] = false; | |
1265 SafeRunnable.run(new class(failed) ISafeRunnable { | |
1266 bool[] failed_; | |
1267 this(bool[] a){ | |
1268 this.failed_=a; | |
1269 } | |
1270 public void handleException(Exception e) { | |
1271 this.failed_[0] = true; | |
1272 } | |
1273 | |
1274 public void run() { | |
1275 createPageControl(currentPage, pageContainer); | |
1276 } | |
1277 }); | |
1278 if (failed[0]) { | |
1279 return false; | |
1280 } | |
1281 // the page is responsible for ensuring the created control is | |
1282 // accessable | |
1283 // via getControl. | |
1284 Assert.isNotNull(currentPage.getControl()); | |
1285 } | |
1286 // Force calculation of the page's description label because | |
1287 // label can be wrapped. | |
1288 Point[1] size; | |
1289 Point failed = new Point(-1, -1); | |
1290 SafeRunnable.run(new class(size,failed) ISafeRunnable { | |
1291 Point[] size_; | |
1292 Point failed_; | |
1293 this(Point[] a,Point b){ | |
1294 size_=a; | |
1295 failed_=b; | |
1296 } | |
1297 public void handleException(Exception e) { | |
1298 size_[0] = failed_; | |
1299 } | |
1300 | |
1301 public void run() { | |
1302 size_[0] = currentPage.computeSize(); | |
1303 } | |
1304 }); | |
1305 if (size[0].opEquals(failed)) { | |
1306 return false; | |
1307 } | |
1308 Point contentSize = size[0]; | |
1309 // Do we need resizing. Computation not needed if the | |
1310 // first page is inserted since computing the dialog's | |
1311 // size is done by calling dialog.open(). | |
1312 // Also prevent auto resize if the user has manually resized | |
1313 Shell shell = getShell(); | |
1314 Point shellSize = shell.getSize(); | |
1315 if (oldPage !is null) { | |
1316 Rectangle rect = pageContainer.getClientArea(); | |
1317 Point containerSize = new Point(rect.width, rect.height); | |
1318 int hdiff = contentSize.x - containerSize.x; | |
1319 int vdiff = contentSize.y - containerSize.y; | |
1320 if ((hdiff > 0 || vdiff > 0) && shellSize.opEquals(lastShellSize)) { | |
1321 hdiff = Math.max(0, hdiff); | |
1322 vdiff = Math.max(0, vdiff); | |
1323 setShellSize(shellSize.x + hdiff, shellSize.y + vdiff); | |
1324 lastShellSize = shell.getSize(); | |
1325 if (currentPage.getControl().getSize().x is 0) { | |
1326 currentPage.getControl().setSize(containerSize); | |
1327 } | |
1328 | |
1329 } else { | |
1330 currentPage.setSize(containerSize); | |
1331 } | |
1332 } | |
1333 | |
1334 scrolled.setMinSize(contentSize); | |
1335 // Ensure that all other pages are invisible | |
1336 // (including ones that triggered an exception during | |
1337 // their creation). | |
1338 Control[] children = pageContainer.getChildren(); | |
1339 Control currentControl = currentPage.getControl(); | |
1340 for (int i = 0; i < children.length; i++) { | |
1341 if (children[i] !is currentControl) { | |
1342 children[i].setVisible(false); | |
1343 } | |
1344 } | |
1345 // Make the new page visible | |
1346 currentPage.setVisible(true); | |
1347 if (oldPage !is null) { | |
1348 oldPage.setVisible(false); | |
1349 } | |
1350 // update the dialog controls | |
1351 update(); | |
1352 return true; | |
1353 } | |
1354 | |
1355 /** | |
1356 * Create the page for the node. | |
1357 * @param node | |
1358 * | |
1359 * @since 3.1 | |
1360 */ | |
1361 protected void createPage(IPreferenceNode node) { | |
1362 node.createPage(); | |
1363 } | |
1364 | |
1365 /** | |
1366 * Get the page for the node. | |
1367 * @param node | |
1368 * @return IPreferencePage | |
1369 * | |
1370 * @since 3.1 | |
1371 */ | |
1372 protected IPreferencePage getPage(IPreferenceNode node) { | |
1373 return node.getPage(); | |
1374 } | |
1375 | |
1376 /** | |
1377 * Shows the "Page Flipping abort" dialog. | |
1378 */ | |
1379 void showPageFlippingAbortDialog() { | |
1380 MessageDialog.openError(getShell(), JFaceResources | |
1381 .getString("AbortPageFlippingDialog.title"), //$NON-NLS-1$ | |
1382 JFaceResources.getString("AbortPageFlippingDialog.message")); //$NON-NLS-1$ | |
1383 } | |
1384 | |
1385 /** | |
1386 * Updates this dialog's controls to reflect the current page. | |
1387 */ | |
1388 protected void update() { | |
1389 // Update the title bar | |
1390 updateTitle(); | |
1391 // Update the message line | |
1392 updateMessage(); | |
1393 // Update the buttons | |
1394 updateButtons(); | |
1395 //Saved the selected node in the preferences | |
1396 setSelectedNode(); | |
1397 firePageChanged(new PageChangedEvent(this, cast(Object)getCurrentPage())); | |
1398 } | |
1399 | |
1400 /* | |
1401 * (non-Javadoc) | |
1402 * | |
1403 * @see org.eclipse.jface.preference.IPreferencePageContainer#updateButtons() | |
1404 */ | |
1405 public void updateButtons() { | |
1406 okButton.setEnabled(isCurrentPageValid()); | |
1407 } | |
1408 | |
1409 /* | |
1410 * (non-Javadoc) | |
1411 * | |
1412 * @see org.eclipse.jface.preference.IPreferencePageContainer#updateMessage() | |
1413 */ | |
1414 public void updateMessage() { | |
1415 String message = null; | |
1416 String errorMessage = null; | |
1417 if(currentPage !is null){ | |
1418 message = currentPage.getMessage(); | |
1419 errorMessage = currentPage.getErrorMessage(); | |
1420 } | |
1421 int messageType = IMessageProvider.NONE; | |
1422 if (message !is null && cast(IMessageProvider)currentPage ) { | |
1423 messageType = (cast(IMessageProvider) currentPage).getMessageType(); | |
1424 } | |
1425 | |
1426 if (errorMessage is null){ | |
1427 if (showingError) { | |
1428 // we were previously showing an error | |
1429 showingError = false; | |
1430 } | |
1431 } | |
1432 else { | |
1433 message = errorMessage; | |
1434 messageType = IMessageProvider.ERROR; | |
1435 if (!showingError) { | |
1436 // we were not previously showing an error | |
1437 showingError = true; | |
1438 } | |
1439 } | |
1440 messageArea.updateText(message,messageType); | |
1441 } | |
1442 | |
1443 /* | |
1444 * (non-Javadoc) | |
1445 * | |
1446 * @see org.eclipse.jface.preference.IPreferencePageContainer#updateTitle() | |
1447 */ | |
1448 public void updateTitle() { | |
1449 if(currentPage is null) { | |
1450 return; | |
1451 } | |
1452 messageArea.showTitle(currentPage.getTitle(), currentPage.getImage()); | |
1453 } | |
1454 | |
1455 /** | |
1456 * Update the tree to use the specified <code>Font</code>. | |
1457 * | |
1458 * @param dialogFont | |
1459 * the <code>Font</code> to use. | |
1460 * @since 3.0 | |
1461 */ | |
1462 protected void updateTreeFont(Font dialogFont) { | |
1463 getTreeViewer().getControl().setFont(dialogFont); | |
1464 } | |
1465 | |
1466 /** | |
1467 * Returns the currentPage. | |
1468 * @return IPreferencePage | |
1469 * @since 3.1 | |
1470 */ | |
1471 protected IPreferencePage getCurrentPage() { | |
1472 return currentPage; | |
1473 } | |
1474 | |
1475 /** | |
1476 * Sets the current page. | |
1477 * @param currentPage | |
1478 * | |
1479 * @since 3.1 | |
1480 */ | |
1481 protected void setCurrentPage(IPreferencePage currentPage) { | |
1482 this.currentPage = currentPage; | |
1483 } | |
1484 | |
1485 /** | |
1486 * Set the treeViewer. | |
1487 * @param treeViewer | |
1488 * | |
1489 * @since 3.1 | |
1490 */ | |
1491 protected void setTreeViewer(TreeViewer treeViewer) { | |
1492 this.treeViewer = treeViewer; | |
1493 } | |
1494 | |
1495 /** | |
1496 * Get the composite that is showing the page. | |
1497 * | |
1498 * @return Composite. | |
1499 * | |
1500 * @since 3.1 | |
1501 */ | |
1502 protected Composite getPageContainer() { | |
1503 return this.pageContainer; | |
1504 } | |
1505 | |
1506 /** | |
1507 * Set the composite that is showing the page. | |
1508 * @param pageContainer Composite | |
1509 * | |
1510 * @since 3.1 | |
1511 */ | |
1512 protected void setPageContainer(Composite pageContainer) { | |
1513 this.pageContainer = pageContainer; | |
1514 } | |
1515 /** | |
1516 * Create the page control for the supplied page. | |
1517 * | |
1518 * @param page - the preference page to be shown | |
1519 * @param parent - the composite to parent the page | |
1520 * | |
1521 * @since 3.1 | |
1522 */ | |
1523 protected void createPageControl(IPreferencePage page, Composite parent) { | |
1524 page.createControl(parent); | |
1525 } | |
1526 | |
1527 /** | |
1528 * @see org.eclipse.jface.dialogs.IPageChangeProvider#getSelectedPage() | |
1529 * | |
1530 * @since 3.1 | |
1531 */ | |
1532 public Object getSelectedPage() { | |
1533 return cast(Object)getCurrentPage(); | |
1534 } | |
1535 | |
1536 /** | |
1537 * @see org.eclipse.jface.dialogs.IPageChangeProvider#addPageChangedListener(org.eclipse.jface.dialogs.IPageChangedListener) | |
1538 * @since 3.1 | |
1539 */ | |
1540 public void addPageChangedListener(IPageChangedListener listener) { | |
1541 pageChangedListeners.add(cast(Object)listener); | |
1542 } | |
1543 | |
1544 /** | |
1545 * @see org.eclipse.jface.dialogs.IPageChangeProvider#removePageChangedListener(org.eclipse.jface.dialogs.IPageChangedListener) | |
1546 * @since 3.1 | |
1547 */ | |
1548 public void removePageChangedListener(IPageChangedListener listener) { | |
1549 pageChangedListeners.remove(cast(Object)listener); | |
1550 | |
1551 } | |
1552 | |
1553 /** | |
1554 * Notifies any selection changed listeners that the selected page | |
1555 * has changed. | |
1556 * Only listeners registered at the time this method is called are notified. | |
1557 * | |
1558 * @param event a selection changed event | |
1559 * | |
1560 * @see IPageChangedListener#pageChanged | |
1561 * | |
1562 * @since 3.1 | |
1563 */ | |
1564 protected void firePageChanged(PageChangedEvent event) { | |
1565 Object[] listeners = pageChangedListeners.getListeners(); | |
1566 for (int i = 0; i < listeners.length; i++) { | |
1567 SafeRunnable.run(new class(event,cast(IPageChangedListener) listeners[i]) SafeRunnable { | |
1568 PageChangedEvent event_; | |
1569 IPageChangedListener l; | |
1570 this(PageChangedEvent a,IPageChangedListener b){ | |
1571 event_=a; | |
1572 l =b ; | |
1573 } | |
1574 public void run() { | |
1575 l.pageChanged(event_); | |
1576 } | |
1577 }); | |
1578 } | |
1579 } | |
1580 | |
1581 /* | |
1582 * (non-Javadoc) | |
1583 * @see org.eclipse.jface.dialogs.Dialog#isResizable() | |
1584 */ | |
1585 protected bool isResizable() { | |
1586 return true; | |
1587 } | |
1588 | |
1589 } |