Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 247818 | Differences between
and this patch

Collapse All | Expand All

(-)Eclipse UI/org/eclipse/ui/statushandlers/WorkbenchStatusDialogManager.java (-1 / +34 lines)
Lines 222-227 Link Here
222
	 */
222
	 */
223
	private class InternalDialog extends TrayDialog {
223
	private class InternalDialog extends TrayDialog {
224
224
225
		/* (non-Javadoc)
226
		 * @see org.eclipse.jface.dialogs.TrayDialog#close()
227
		 */
228
		public boolean close() {
229
			boolean result = super.close();
230
			if (listener != null && !modalitySwitch) {
231
				listener.statusDialogClosed();
232
			}
233
			return result;
234
		}
235
225
		private WorkbenchStatusDialogManager statusDialog;
236
		private WorkbenchStatusDialogManager statusDialog;
226
237
227
		/**
238
		/**
Lines 1006-1011 Link Here
1006
	 */
1017
	 */
1007
	private Composite titleArea;
1018
	private Composite titleArea;
1008
1019
1020
	private IStatusDialogListener listener;
1021
1009
	/**
1022
	/**
1010
	 * Creates workbench status dialog.
1023
	 * Creates workbench status dialog.
1011
	 * 
1024
	 * 
Lines 1659-1665 Link Here
1659
	/**
1672
	/**
1660
	 * Returns the shell of the dialog.
1673
	 * Returns the shell of the dialog.
1661
	 */
1674
	 */
1662
	Shell getShell() {
1675
	private Shell getShell() {
1663
		if (this.dialog == null) return null;
1676
		if (this.dialog == null) return null;
1664
		return this.dialog.getShell();
1677
		return this.dialog.getShell();
1665
	}
1678
	}
Lines 2196-2199 Link Here
2196
		}
2209
		}
2197
		titleArea.layout();
2210
		titleArea.layout();
2198
	}
2211
	}
2212
2213
	/**
2214
	 * This method adds a listener to the dialog. Listener will be notified
2215
	 * about dialog state changes. There can be only one listener set.
2216
	 * <p>
2217
	 * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
2218
	 * part of a work in progress. There is a guarantee neither that this API
2219
	 * will work nor that it will remain the same. Please do not use this API
2220
	 * without consulting with the Platform/UI team.
2221
	 * </p>
2222
	 * 
2223
	 * @see IStatusDialogListener
2224
	 * @param listener
2225
	 *            A listener to be set. <code>null</code> can be used to clear
2226
	 *            the listener.
2227
	 * @since 3.5
2228
	 */
2229
	public void setStatusDialogListener(IStatusDialogListener listener) {
2230
		this.listener = listener;
2231
	}
2199
}
2232
}
(-)Eclipse UI/org/eclipse/ui/statushandlers/WorkbenchErrorHandler.java (-5 / +15 lines)
Lines 14-20 Link Here
14
import org.eclipse.core.runtime.IStatus;
14
import org.eclipse.core.runtime.IStatus;
15
import org.eclipse.core.runtime.Status;
15
import org.eclipse.core.runtime.Status;
16
import org.eclipse.swt.widgets.Display;
16
import org.eclipse.swt.widgets.Display;
17
import org.eclipse.swt.widgets.Shell;
18
import org.eclipse.ui.PlatformUI;
17
import org.eclipse.ui.PlatformUI;
19
import org.eclipse.ui.application.WorkbenchAdvisor;
18
import org.eclipse.ui.application.WorkbenchAdvisor;
20
import org.eclipse.ui.internal.WorkbenchPlugin;
19
import org.eclipse.ui.internal.WorkbenchPlugin;
Lines 26-31 Link Here
26
 * @since 3.3
25
 * @since 3.3
27
 */
26
 */
28
public class WorkbenchErrorHandler extends AbstractStatusHandler {
27
public class WorkbenchErrorHandler extends AbstractStatusHandler {
28
	
29
	private boolean dialogClosed = false;
30
	private IStatusDialogListener listener = new IStatusDialogListener(){
31
32
		public void statusDialogClosed() {
33
			dialogClosed = true;
34
		}
35
		
36
	};
29
37
30
	private WorkbenchStatusDialogManager statusDialog;
38
	private WorkbenchStatusDialogManager statusDialog;
31
39
Lines 110-119 Link Here
110
		getStatusDialogManager().addStatusAdapter(statusAdapter, block);
118
		getStatusDialogManager().addStatusAdapter(statusAdapter, block);
111
119
112
		if (block) {
120
		if (block) {
113
			Shell shell;
121
			// this variable will be set to true if and only if user closes the
114
			while ((shell = getStatusDialogManager().getShell()) != null
122
			// dialog
115
					&& !getStatusDialogManager().getShell().isDisposed()) {
123
			dialogClosed = false;
116
				if (!shell.getDisplay().readAndDispatch()) {
124
			while (!dialogClosed) {
125
				if (!Display.getDefault().readAndDispatch()) {
117
					Thread.yield();
126
					Thread.yield();
118
				}
127
				}
119
			}
128
			}
Lines 159-163 Link Here
159
	private void initStatusDialogManager() {
168
	private void initStatusDialogManager() {
160
		statusDialog = new WorkbenchStatusDialogManager(null);
169
		statusDialog = new WorkbenchStatusDialogManager(null);
161
		configureStatusDialog(statusDialog);
170
		configureStatusDialog(statusDialog);
171
		statusDialog.setStatusDialogListener(listener);
162
	}
172
	}
163
}
173
}
(-)Eclipse (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 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
 ******************************************************************************/
11
12
package org.eclipse.ui.statushandlers;
13
14
/**
15
 * This interface allows for listening to dialog state changes. The dialog is
16
 * managed by {@link WorkbenchStatusDialogManager}.
17
 * 
18
 * <p>
19
 * <strong>EXPERIMENTAL</strong>. This class or interface has been added as part
20
 * of a work in progress. There is a guarantee neither that this API will work
21
 * nor that it will remain the same. Please do not use this API without
22
 * consulting with the Platform/UI team.
23
 * </p>
24
 * 
25
 * @since 3.5
26
 */
27
public interface IStatusDialogListener {
28
	/**
29
	 * This method is called when the status dialog is closed by user.
30
	 */
31
	public void statusDialogClosed();
32
}
(-)Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/StatusDialogManagerTest.java (+146 lines)
Lines 31-36 Link Here
31
import org.eclipse.swt.widgets.Button;
31
import org.eclipse.swt.widgets.Button;
32
import org.eclipse.swt.widgets.Composite;
32
import org.eclipse.swt.widgets.Composite;
33
import org.eclipse.swt.widgets.Control;
33
import org.eclipse.swt.widgets.Control;
34
import org.eclipse.swt.widgets.Display;
34
import org.eclipse.swt.widgets.Event;
35
import org.eclipse.swt.widgets.Event;
35
import org.eclipse.swt.widgets.Label;
36
import org.eclipse.swt.widgets.Label;
36
import org.eclipse.swt.widgets.Shell;
37
import org.eclipse.swt.widgets.Shell;
Lines 41-47 Link Here
41
import org.eclipse.ui.progress.IProgressConstants;
42
import org.eclipse.ui.progress.IProgressConstants;
42
import org.eclipse.ui.statushandlers.AbstractStatusAreaProvider;
43
import org.eclipse.ui.statushandlers.AbstractStatusAreaProvider;
43
import org.eclipse.ui.statushandlers.IStatusAdapterConstants;
44
import org.eclipse.ui.statushandlers.IStatusAdapterConstants;
45
import org.eclipse.ui.statushandlers.IStatusDialogListener;
44
import org.eclipse.ui.statushandlers.StatusAdapter;
46
import org.eclipse.ui.statushandlers.StatusAdapter;
47
import org.eclipse.ui.statushandlers.StatusManager;
48
import org.eclipse.ui.statushandlers.WorkbenchErrorHandler;
45
import org.eclipse.ui.statushandlers.WorkbenchStatusDialogManager;
49
import org.eclipse.ui.statushandlers.WorkbenchStatusDialogManager;
46
50
47
public class StatusDialogManagerTest extends TestCase {
51
public class StatusDialogManagerTest extends TestCase {
Lines 51-56 Link Here
51
	private static final String THROWABLE = "throwable";
55
	private static final String THROWABLE = "throwable";
52
	private final static String MESSAGE_1 = "TEST_MESSAGE_1";
56
	private final static String MESSAGE_1 = "TEST_MESSAGE_1";
53
	private final static String MESSAGE_2 = "TEST_MESSAGE_2";
57
	private final static String MESSAGE_2 = "TEST_MESSAGE_2";
58
	private final static String MESSAGE_3 = "TEST_MESSAGE_2";
54
	private final static String TITLE = "TEST_TITLE";
59
	private final static String TITLE = "TEST_TITLE";
55
	private final static NullPointerException NPE = new NullPointerException();
60
	private final static NullPointerException NPE = new NullPointerException();
56
	private final static NullPointerException NPE_WITH_MESSAGE = new NullPointerException(
61
	private final static NullPointerException NPE_WITH_MESSAGE = new NullPointerException(
Lines 73-78 Link Here
73
		assertNotNull(shell);
78
		assertNotNull(shell);
74
		assertTrue((shell.getStyle() & SWT.APPLICATION_MODAL) == SWT.APPLICATION_MODAL);
79
		assertTrue((shell.getStyle() & SWT.APPLICATION_MODAL) == SWT.APPLICATION_MODAL);
75
	}
80
	}
81
	
82
	/**
83
	 * This test checks if the calling thread is really blocked. It opens a
84
	 * dialog with the BLOCK flag in UI thread, and then monitors in the
85
	 * background thread that the dialog really appears (in 50 tries, 50
86
	 * milliseconds each). After the dialog appears, "OK" selection is emulated,
87
	 * the dialog is closed and the handle method returns. At this point there
88
	 * can be no shell.
89
	 */
90
	public void testBlockingBehavior1() {
91
		WorkbenchErrorHandler weh = new WorkbenchErrorHandler();
92
		Thread thread = new Thread(new Runnable(){
93
			public void run() {
94
				int count = 50;
95
				final boolean opened[] = new boolean[]{false};
96
				while (!opened[0] && count-- != 0) {
97
					try {
98
						Thread.sleep(50);
99
					} catch (InterruptedException e) {
100
						e.printStackTrace();
101
					}
102
					Display.getDefault().syncExec(new Runnable() {
103
						public void run() {
104
							opened[0] = StatusDialogUtil.getStatusShell() != null;
105
							if(opened[0]){
106
								selectWidget(StatusDialogUtil.getOkButton());
107
							}
108
						}
109
					});
110
				}
111
				assertTrue("Dialog should appear!", count > 0);
112
				
113
			}
114
		});
115
		thread.start();
116
		weh.handle(createStatusAdapter(MESSAGE_1), StatusManager.BLOCK);
117
		assertNull("Dialog should block the calling thread!", StatusDialogUtil
118
				.getStatusShell());
119
	}
120
121
	/**
122
	 * This is more advanced version of testBlockingBehavior1. We have 2
123
	 * background threads that raise statuses. UI thread also raises one. No
124
	 * thread can proceed until "OK" is emulated (and this will happen if the
125
	 * dialog is opened and three statuses were reported).
126
	 */
127
	public void testBlockingBehavior2() {
128
		final WorkbenchErrorHandler weh = new WorkbenchErrorHandler();
129
		Thread thread1 = new Thread(new Runnable() {
130
			public void run() {
131
				weh.handle(createStatusAdapter(MESSAGE_1), StatusManager.BLOCK);
132
				Display.getDefault().syncExec(new Runnable() {
133
					public void run() {
134
						assertNull("Dialog should block the calling thread!",
135
								StatusDialogUtil.getStatusShell());
136
					}
137
				});
138
			}
139
140
		});
141
		thread1.start();
142
		Thread thread2 = new Thread(new Runnable() {
143
			public void run() {
144
				weh.handle(createStatusAdapter(MESSAGE_2), StatusManager.BLOCK);
145
				Display.getDefault().syncExec(new Runnable() {
146
					public void run() {
147
						assertNull("Dialog should block the calling thread!",
148
								StatusDialogUtil.getStatusShell());
149
					}
150
				});
151
			}
152
		});
153
		thread2.start();
154
		Thread checker = new Thread(new Runnable() {
155
			public void run() {
156
				int count = 50;
157
				final boolean statusesShown[] = new boolean[] { false };
158
				while (!statusesShown[0] && count-- != 0) {
159
					try {
160
						Thread.sleep(50);
161
					} catch (InterruptedException e) {
162
						e.printStackTrace();
163
					}
164
					Display.getDefault().syncExec(new Runnable() {
165
						public void run() {
166
							boolean dialogVisible = StatusDialogUtil
167
									.getStatusShell() != null;
168
							statusesShown[0] = dialogVisible
169
									&& StatusDialogUtil.getTable()
170
											.getItemCount() == 3;
171
							if (statusesShown[0]) {
172
								selectWidget(StatusDialogUtil.getOkButton());
173
							}
174
						}
175
					});
176
				}
177
				assertTrue(
178
						"Dialog should appear and all statuses should be shown",
179
						count > 0);
180
			}
181
		});
182
		checker.start();
183
		weh.handle(createStatusAdapter(MESSAGE_3), StatusManager.BLOCK);
184
		assertNull("Dialog should block the calling thread!", StatusDialogUtil
185
				.getStatusShell());
186
	}
76
187
77
	public void testNonBlockingAppearance() {
188
	public void testNonBlockingAppearance() {
78
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
189
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
Lines 80-85 Link Here
80
		assertNotNull(shell);
191
		assertNotNull(shell);
81
		assertFalse((shell.getStyle() & SWT.APPLICATION_MODAL) == SWT.APPLICATION_MODAL);
192
		assertFalse((shell.getStyle() & SWT.APPLICATION_MODAL) == SWT.APPLICATION_MODAL);
82
	}
193
	}
194
	
195
	/**
196
	 * Check that listener is notified about dialog closure when the dialog is
197
	 * closed by the user.
198
	 */
199
	public void testListener1(){
200
		final boolean[] dialogClosedInvoked = new boolean[]{false};
201
		wsdm.setStatusDialogListener(new IStatusDialogListener(){
202
			public void statusDialogClosed() {
203
				dialogClosedInvoked[0] = true;
204
			}
205
		});
206
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
207
		selectWidget(StatusDialogUtil.getOkButton());
208
		assertTrue(dialogClosedInvoked[0]);
209
	}
210
	
211
	/**
212
	 * Check that listener is not notified about dialog closure when the
213
	 * modality is switched.
214
	 */
215
	public void testListener2(){
216
		final boolean[] dialogClosedInvoked = new boolean[]{false};
217
		wsdm.setStatusDialogListener(new IStatusDialogListener(){
218
			public void statusDialogClosed() {
219
				dialogClosedInvoked[0] = true;
220
			}
221
		});
222
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
223
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), true);
224
		assertFalse(dialogClosedInvoked[0]);
225
		selectWidget(StatusDialogUtil.getOkButton());
226
		// now should be notified
227
		assertTrue(dialogClosedInvoked[0]);
228
	}
83
229
84
	public void testModalitySwitch1() {
230
	public void testModalitySwitch1() {
85
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
231
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);

Return to bug 247818