comparison dwtx/jface/preference/FieldEditorPreferencePage.d @ 34:b3c8e32d406f

preference
author Frank Benoit <benoit@tionex.de>
date Sat, 05 Apr 2008 01:45:47 +0200
parents
children ea8ff534f622
comparison
equal deleted inserted replaced
33:f25582573129 34:b3c8e32d406f
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 * Chris Tilt (chris@tilts.net) - Bug 38547 - [Preferences] Changing preferences
11 * ignored after "Restore defaults" pressed.
12 * Port to the D programming language:
13 * Frank Benoit <benoit@tionex.de>
14 *******************************************************************************/
15 module dwtx.jface.preference.FieldEditorPreferencePage;
16
17 import dwtx.jface.preference.PreferencePage;
18 import dwtx.jface.preference.FieldEditor;
19 import dwtx.jface.preference.FieldEditorPreferencePage;
20
21 import tango.util.collection.ArraySeq;
22 import tango.util.collection.model.Seq;
23 // import java.util.Iterator;
24 // import java.util.List;
25
26 import dwt.DWT;
27 import dwt.layout.GridData;
28 import dwt.layout.GridLayout;
29 import dwt.widgets.Composite;
30 import dwt.widgets.Control;
31 import dwtx.jface.resource.ImageDescriptor;
32 import dwtx.jface.util.IPropertyChangeListener;
33 import dwtx.jface.util.PropertyChangeEvent;
34
35 import dwt.dwthelper.utils;
36
37 /**
38 * A special abstract preference page to host field editors.
39 * <p>
40 * Subclasses must implement the <code>createFieldEditors</code> method
41 * and should override <code>createLayout</code> if a special layout of the field
42 * editors is needed.
43 * </p>
44 */
45 public abstract class FieldEditorPreferencePage : PreferencePage,
46 IPropertyChangeListener {
47
48 /**
49 * Layout constant (value <code>0</code>) indicating that
50 * each field editor is handled as a single component.
51 */
52 public static const int FLAT = 0;
53
54 /**
55 * Layout constant (value <code>1</code>) indicating that
56 * the field editors' basic controls are put into a grid layout.
57 */
58 public static const int GRID = 1;
59
60 /**
61 * The vertical spacing used by layout styles <code>FLAT</code>
62 * and <code>GRID</code>.
63 */
64 protected static const int VERTICAL_SPACING = 10;
65
66 /**
67 * The margin width used by layout styles <code>FLAT</code>
68 * and <code>GRID</code>.
69 */
70 protected static const int MARGIN_WIDTH = 0;
71
72 /**
73 * The margin height used by layout styles <code>FLAT</code>
74 * and <code>GRID</code>.
75 */
76 protected static const int MARGIN_HEIGHT = 0;
77
78 /**
79 * The field editors, or <code>null</code> if not created yet.
80 */
81 private Seq!(Object) fields = null;
82
83 /**
84 * The layout style; either <code>FLAT</code> or <code>GRID</code>.
85 */
86 private int style;
87
88 /**
89 * The first invalid field editor, or <code>null</code>
90 * if all field editors are valid.
91 */
92 private FieldEditor invalidFieldEditor = null;
93
94 /**
95 * The parent composite for field editors
96 */
97 private Composite fieldEditorParent;
98
99 /**
100 * Create a new instance of the reciever.
101 */
102 public this() {
103 this(FLAT);
104 }
105
106 /**
107 * Creates a new field editor preference page with the given style,
108 * an empty title, and no image.
109 *
110 * @param style either <code>GRID</code> or <code>FLAT</code>
111 */
112 protected this(int style) {
113 super();
114 this.style = style;
115 }
116
117 /**
118 * Creates a new field editor preference page with the given title
119 * and style, but no image.
120 *
121 * @param title the title of this preference page
122 * @param style either <code>GRID</code> or <code>FLAT</code>
123 */
124 protected this(String title, int style) {
125 super(title);
126 this.style = style;
127 }
128
129 /**
130 * Creates a new field editor preference page with the given title,
131 * image, and style.
132 *
133 * @param title the title of this preference page
134 * @param image the image for this preference page, or
135 * <code>null</code> if none
136 * @param style either <code>GRID</code> or <code>FLAT</code>
137 */
138 protected this(String title, ImageDescriptor image,
139 int style) {
140 super(title, image);
141 this.style = style;
142 }
143
144 /**
145 * Adds the given field editor to this page.
146 *
147 * @param editor the field editor
148 */
149 protected void addField(FieldEditor editor) {
150 if (fields is null) {
151 fields = new ArraySeq!(Object);
152 }
153 fields.append(editor);
154 }
155
156 /**
157 * Adjust the layout of the field editors so that
158 * they are properly aligned.
159 */
160 protected void adjustGridLayout() {
161 int numColumns = calcNumberOfColumns();
162 (cast(GridLayout) fieldEditorParent.getLayout()).numColumns = numColumns;
163 if (fields !is null) {
164 for (int i = 0; i < fields.size(); i++) {
165 FieldEditor fieldEditor = cast(FieldEditor) fields.get(i);
166 fieldEditor.adjustForNumColumns_package(numColumns);
167 }
168 }
169 }
170
171 /**
172 * Applys the font to the field editors managed by this page.
173 */
174 protected void applyFont() {
175 if (fields !is null) {
176 foreach( e; fields ){
177 FieldEditor pe = cast(FieldEditor) e;
178 pe.applyFont_package();
179 }
180 }
181 }
182
183 /**
184 * Calculates the number of columns needed to host all field editors.
185 *
186 * @return the number of columns
187 */
188 private int calcNumberOfColumns() {
189 int result = 0;
190 if (fields !is null) {
191 foreach( e; fields ){
192 FieldEditor pe = cast(FieldEditor) e;
193 result = Math.max(result, pe.getNumberOfControls());
194 }
195 }
196 return result;
197 }
198
199 /**
200 * Recomputes the page's error state by calling <code>isValid</code> for
201 * every field editor.
202 */
203 protected void checkState() {
204 bool valid = true;
205 invalidFieldEditor = null;
206 // The state can only be set to true if all
207 // field editors contain a valid value. So we must check them all
208 if (fields !is null) {
209 int size = fields.size();
210 for (int i = 0; i < size; i++) {
211 FieldEditor editor = cast(FieldEditor) fields.get(i);
212 valid = valid && editor.isValid();
213 if (!valid) {
214 invalidFieldEditor = editor;
215 break;
216 }
217 }
218 }
219 setValid(valid);
220 }
221
222 /* (non-Javadoc)
223 * Method declared on PreferencePage.
224 */
225 protected Control createContents(Composite parent) {
226 fieldEditorParent = new Composite(parent, DWT.NULL);
227 GridLayout layout = new GridLayout();
228 layout.numColumns = 1;
229 layout.marginHeight = 0;
230 layout.marginWidth = 0;
231 fieldEditorParent.setLayout(layout);
232 fieldEditorParent.setFont(parent.getFont());
233
234 createFieldEditors();
235
236 if (style is GRID) {
237 adjustGridLayout();
238 }
239
240 initialize();
241 checkState();
242 return fieldEditorParent;
243 }
244
245 /**
246 * Creates the page's field editors.
247 * <p>
248 * The default implementation of this framework method
249 * does nothing. Subclass must implement this method to
250 * create the field editors.
251 * </p>
252 * <p>
253 * Subclasses should call <code>getFieldEditorParent</code>
254 * to obtain the parent control for each field editor.
255 * This same parent should not be used for more than
256 * one editor as the parent may change for each field
257 * editor depending on the layout style of the page
258 * </p>
259 */
260 protected abstract void createFieldEditors();
261
262 /**
263 * The field editor preference page implementation of an <code>IDialogPage</code>
264 * method disposes of this page's controls and images.
265 * Subclasses may override to release their own allocated DWT
266 * resources, but must call <code>super.dispose</code>.
267 */
268 public void dispose() {
269 super.dispose();
270 if (fields !is null) {
271 foreach( e; fields ){
272 FieldEditor pe = cast(FieldEditor) e;
273 pe.setPage(null);
274 pe.setPropertyChangeListener(null);
275 pe.setPreferenceStore(null);
276 }
277 }
278 }
279
280 /**
281 * Returns a parent composite for a field editor.
282 * <p>
283 * This value must not be cached since a new parent
284 * may be created each time this method called. Thus
285 * this method must be called each time a field editor
286 * is constructed.
287 * </p>
288 *
289 * @return a parent
290 */
291 protected Composite getFieldEditorParent() {
292 if (style is FLAT) {
293 // Create a new parent for each field editor
294 Composite parent = new Composite(fieldEditorParent, DWT.NULL);
295 parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
296 return parent;
297 }
298 // Just return the parent
299 return fieldEditorParent;
300 }
301
302 /**
303 * Initializes all field editors.
304 */
305 protected void initialize() {
306 if (fields !is null) {
307 foreach( e; fields ){
308 FieldEditor pe = cast(FieldEditor) e;
309 pe.setPage(this);
310 pe.setPropertyChangeListener(this);
311 pe.setPreferenceStore(getPreferenceStore());
312 pe.load();
313 }
314 }
315 }
316
317 /**
318 * The field editor preference page implementation of a <code>PreferencePage</code>
319 * method loads all the field editors with their default values.
320 */
321 protected void performDefaults() {
322 if (fields !is null) {
323 foreach( e; fields ){
324 FieldEditor pe = cast(FieldEditor) e;
325 pe.loadDefault();
326 }
327 }
328 // Force a recalculation of my error state.
329 checkState();
330 super.performDefaults();
331 }
332
333 /**
334 * The field editor preference page implementation of this
335 * <code>PreferencePage</code> method saves all field editors by
336 * calling <code>FieldEditor.store</code>. Note that this method
337 * does not save the preference store itself; it just stores the
338 * values back into the preference store.
339 *
340 * @see FieldEditor#store()
341 */
342 public bool performOk() {
343 if (fields !is null) {
344 foreach( e; fields ){
345 FieldEditor pe = cast(FieldEditor) e;
346 pe.store();
347 pe.setPresentsDefaultValue_package(false);
348 }
349 }
350 return true;
351 }
352
353 /**
354 * The field editor preference page implementation of this <code>IPreferencePage</code>
355 * (and <code>IPropertyChangeListener</code>) method intercepts <code>IS_VALID</code>
356 * events but passes other events on to its superclass.
357 */
358 public void propertyChange(PropertyChangeEvent event) {
359
360 if (event.getProperty().equals(FieldEditor.IS_VALID)) {
361 bool newValue = (cast(ValueWrapperBool) event.getNewValue()).value;
362 // If the new value is true then we must check all field editors.
363 // If it is false, then the page is invalid in any case.
364 if (newValue) {
365 checkState();
366 } else {
367 invalidFieldEditor = cast(FieldEditor) event.getSource();
368 setValid(newValue);
369 }
370 }
371 }
372
373 /* (non-Javadoc)
374 * Method declared on IDialog.
375 */
376 public void setVisible(bool visible) {
377 super.setVisible(visible);
378 if (visible && invalidFieldEditor !is null) {
379 invalidFieldEditor.setFocus();
380 }
381 }
382 }