Skip to main content
summaryrefslogtreecommitdiffstats
blob: 1c6509ed1b30ad24873471a3fd60c833d3c9131a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/*******************************************************************************
 * Copyright (c) 2008, 2009 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 *
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.common.ui.internal.widgets;

import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jpt.common.ui.internal.util.SWTUtil;
import org.eclipse.jpt.common.utility.internal.model.value.SimplePropertyValueModel;
import org.eclipse.jpt.common.utility.internal.node.Node;
import org.eclipse.jpt.common.utility.model.value.PropertyValueModel;
import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.help.IWorkbenchHelpSystem;

/**
 * The abstract implementation of a dialog using a "state object" (model object)
 * for behavior.
 * <p>
 * The main pane of this dialog should be extending <code>DialogPane</code>
 * for creating the right type of widgets and it has the "state object" (subject)
 * behavior built-in.
 *
 * @see Node
 * @see DialogPane
 *
 * @version 2.0
 * @since 2.0
 */
@SuppressWarnings("nls")
public abstract class Dialog<T extends Node> extends TitleAreaDialog
{
	/**
	 * The main content pane of this dialog.
	 */
	private DialogPane<?> pane;

	/**
	 * The holder of the "state object" used by this dialog.
	 */
	private WritablePropertyValueModel<T> subjectHolder;

	/**
	 * Caches the title text until the dialog is created and the dialog's shell
	 * needs to be configured.
	 */
	private String title;

	/**
	 * Creates a new <code>Dialog</code>.
	 *
	 * @param parent The parent shell
	 */
	protected Dialog(Shell parent) {
		this(parent, "");
	}

	/**
	 * Creates a new <code>Dialog</code>.
	 *
	 * @param parent The parent shell
	 * @param title The dialog's title
	 */
	protected Dialog(Shell parent, String title) {
		super(parent);
		this.title = title;
		initialize();
	}

	/**
	 * Initializes the main pane of this dialog. This method is invoked only
	 * when the dialog is requested to show on screen and not during
	 * initialization.
	 *
	 * @param container The container to which the widgets should be added to,
	 * the layout is already set
	 */
	protected abstract DialogPane<?> buildLayout(Composite container);

	/**
	 * Creates the state object (model object) that will be used to keep track
	 * of the information entered in this dialog. The state object will be stored
	 * in the subject holder and can be retrieved using {@link #subject()}.
	 *
	 * @return A new state object
	 */
	protected T buildStateObject() {
		return null;
	}

	/**
	 * Creates the <code>Validator</code> that will be notified when changes are
	 * made to the state object.
	 *
	 * @return The validator that will be set on the state object
	 */
	Node.Validator buildValidator() {
		return Node.NULL_VALIDATOR;
	}

	/*
	 * (non-Javadoc)
	 */
	@Override
	public boolean close() {

		// Dispose the pane in order to remove any listeners that could
		// have been installed outside the scrope of the state object
		if (pane != null) {
			pane.dispose();
			pane = null;
		}

		return super.close();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected void configureShell(Shell shell) {
		super.configureShell(shell);
		shell.setText(getTitle());
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void create() {
		super.create();
		installSubject();
	}

	/*
	 * (non-Javadoc)
	 */
	@Override
	protected Control createContents(Composite parent) {
		if (hasTitleArea()) {
			return super.createContents(parent);
		}

		return createDefaultContent(parent);
	}

	/**
	 * Creates the default main container of this dialog when the title area is
	 * not required. The top part is the dialog area populated by the subclass
	 * and the lower part is the button pane having the OK and Cancel buttons.
	 *
	 * @param parent The parent container
	 * @return The
	 */
	private Composite createDefaultContent(Composite parent) {

		Composite composite = new Composite(parent, SWT.NULL);

		GridLayout layout      = new GridLayout(1, false);
		layout.marginHeight    = 0;
		layout.marginWidth     = 0;
		layout.verticalSpacing = 0;
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.FILL_BOTH));

		applyDialogFont(composite);
		initializeDialogUnits(composite);
		dialogArea = createDialogArea(composite);
		buttonBar  = createButtonBar(composite);

		return composite;
	}

	/*
	 * (non-Javadoc)
	 */
	@Override
	protected Composite createDialogArea(Composite parent) {

		// If the title area needs to be shown, then leave the superclass to
		// create the necessary widgets
		if (hasTitleArea()) {
			parent = (Composite) super.createDialogArea(parent);
		}

		// Create the main area's container
		Composite container = new Composite(parent, SWT.NULL);
		container.setLayout(new GridLayout(1, false));

		GridData gridData = new GridData();
		gridData.horizontalAlignment       = GridData.FILL;
		gridData.verticalAlignment         = GridData.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace   = true;
		container.setLayoutData(gridData);

		// Initialize the content pane
		pane = buildLayout(container);

		// Initialize the UI part, which requires the widgets being created
		initializeUI();

		return parent;
	}

	/**
	 * Determines whether the description area (where a title, description and
	 * image) should be visible or hidden. <code>ValidatingDialog</code>
	 * automatically show the description area in order to show problems.
	 *
	 * @return <code>false</code> by default, which means the methods used to
	 * update the title, description and image shouldn't be called; <code>true</code>
	 * to make the description pane visible
	 */
	protected boolean hasTitleArea() {
		return false;
	}

	/**
	 * Returns the helps system.
	 *
	 * @return The platform's help system
	 *
	 * @category Helper
	 */
	protected final IWorkbenchHelpSystem getHelpSystem() {
		return PlatformUI.getWorkbench().getHelpSystem();
	}

	/**
	 * Initializes this dialog.
	 */
	protected void initialize() {
		this.subjectHolder = new SimplePropertyValueModel<T>();
	}

	/**
	 * Initializes the UI part of this dialog, this is called after the widgets
	 * have been created.
	 */
	protected void initializeUI() {
	}

	/**
	 * Creates the state object, if one is needed and install a <code>Validator</code>
	 * in order to receive notification of changes done to that state object. The
	 * subject can be retrieved from the subject holder.
	 */
	private void installSubject() {

		T subject = buildStateObject();

		if (subject != null) {
			subject.setValidator(buildValidator());
		}

		subjectHolder.setValue(subject);
	}

	/**
	 * Asynchronously launches this dialog in the UI thread.
	 */
	public final void openDialog() {
		SWTUtil.setUserInterfaceActive(false);
		SWTUtil.show(this);
	}

	/**
	 * Asynchronously launches this dialog in the UI thread and invoke the given
	 * <code>PostExecution</code> to perform any post-task.
	 *
	 * @param postExecution This interface let the caller to invoke a piece of
	 * code once the dialog is disposed
	 */
	public final void openDialog(PostExecution<? extends Dialog<T>> execution) {
		SWTUtil.setUserInterfaceActive(false);
		SWTUtil.show(this, execution);
	}

	/**
	 * Gives access to the dialog's main pane.
	 *
	 * @return The pane showing the custom widgets
	 */
	protected DialogPane<?> getPane() {
		return pane;
	}

	/**
	 * Returns the subject of this dialog.
	 *
	 * @return The subject of this dialog or <code>null</code> if no subject was
	 * used
	 */
	public T getSubject() {
		return subjectHolder.getValue();
	}

	/**
	 * Returns the holder of the subject.
	 *
	 * @return The subject holder used to be passed to the dialog pane, which is
	 * an instance of <code>DialogPane</code>
	 */
	protected final PropertyValueModel<T> getSubjectHolder() {
		return subjectHolder;
	}

	/**
	 * Retrieves the dialog's title. The title passed to the constructor will be
	 * returned by default but if it wasn't specified, this method can be used
	 * to return it.
	 *
	 * @return Either the title passed to the constructor or a different title
	 */
	protected String getTitle() {
		return title;
	}

	/**
	 * Determines whether the dialog was cancelled or not.
	 *
	 * @return <code>true</code> if the dialog was cancelled; <code>false</code>
	 * if it was confirmed
	 */
	public final boolean wasCancelled() {
		return getReturnCode() == CANCEL;
	}

	/**
	 * Determines whether the dialog was confirmed or not.
	 *
	 * @return <code>true</code> if the dialog was confirmed; <code>false</code>
	 * if it was cancelled
	 */
	public final boolean wasConfirmed() {
		return getReturnCode() == OK;
	}
}

Back to the top