Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 17abec95063c02caef1f047697ebb80fe1eb8b25 (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
/*****************************************************************************
 * Copyright (c) 2012, 2014 CEA LIST and others.
 *
 *    
 * 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:
 *   CEA LIST - Initial API and implementation
 *   Christian W. Damus (CEA) - fixing issues in sequence diagram test execution
 *
 *****************************************************************************/
package org.eclipse.papyrus.uml.diagram.sequence.tests.bug;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;


public class PopupUtil {

	static boolean menuPopup = false;

	static int clickMenuIndex = 0;

	public static boolean isMenuPopup() {
		return menuPopup;
	}

	public static void addMenuListener(int clickIndex) {
		menuPopup = false;
		clickMenuIndex = clickIndex;
		Display.getDefault().syncExec(new Runnable() {

			public void run() {
				Display.getDefault().addFilter(SWT.Show, menuListener);
				Display.getDefault().addFilter(SWT.Hide, menuListener);
			}
		});
	}

	public static void removeMenuListener() {
		Display.getDefault().syncExec(new Runnable() {

			public void run() {
				Display.getDefault().removeFilter(SWT.Show, menuListener);
				Display.getDefault().removeFilter(SWT.Hide, menuListener);
			}
		});
	}

	public static void click(final Menu bar) {
		click(bar, 0);
	}

	public static void click(final Menu bar, int index) {
		MenuItem[] items = bar.getItems();
		if(items != null && index < items.length) {
			notifyEvent(items[index], SWT.Selection);
		}

		bar.setVisible(false);
		bar.notifyListeners(SWT.Hide, new Event());
		waitForComplete();
	}

	protected static void waitForComplete() {
		boolean run = true;
		while(run) {
			try {
				run = Display.getDefault().readAndDispatch();
			} catch (Exception e) {
				run = true;
			}
		}
	}

	public static void notifyEvent(final Widget menuItem, final int eventType) {
		final Event event = new Event();
		event.time = (int)System.currentTimeMillis();
		event.widget = menuItem;
		event.display = menuItem.getDisplay();
		event.type = eventType;

		Display.getDefault().syncExec(new Runnable() {

			public void run() {
				menuItem.notifyListeners(eventType, event);
			}
		});

		waitForComplete();
	}

	/**
	 * A private class to listen for the show/hide events.
	 */
	static class ShowHideListener implements Listener {

		/**
		 * Handles the event by checking if it is the proper event. If it is a show, then the current context menu is
		 * set. Otherwise it will be set to <code>null</code> if it is a hide event.
		 * 
		 * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
		 * @param event
		 *        the event to check.
		 */
		public void handleEvent(Event event) {
			if(!(event.widget instanceof Menu)) {
				return;
			}
			Menu menu = (Menu)event.widget;
			if(hasStyle(menu, SWT.POP_UP)) {
				if(event.type == SWT.Show) {
					currentContextMenu = menu;
					click(menu, clickMenuIndex);
					menuPopup = true;
				} else if((event.type == SWT.Hide) && (menu == currentContextMenu)) {
					currentContextMenu = null;
					menuPopup = false;
				}
			}
		}
	}

	/**
	 * Checks if the widget has the given style.
	 * 
	 * @param w
	 *        the widget.
	 * @param style
	 *        the style.
	 * @return <code>true</code> if the widget has the specified style bit set. Otherwise <code>false</code>.
	 */
	public static boolean hasStyle(final Widget w, final int style) {
		if((w == null) || w.isDisposed()) {
			return false;
		}
		if(style == SWT.NONE) {
			return true;
		}

		final List<Boolean> list = new ArrayList<Boolean>();
		w.getDisplay().syncExec(new Runnable() {


			public void run() {
				list.add((w.getStyle() & style) != 0);
			}
		});
		return list.get(0);
	}

	private static Menu currentContextMenu;

	private static Listener menuListener = new ShowHideListener();

	private static Listener dialogCloseHandler = new Listener() {

		public void handleEvent(Event event) {
			if(event.widget instanceof Shell) {
				Shell shell = (Shell)event.widget;
				Button defaultButton = shell.isDisposed() ? null : shell.getDefaultButton();
				waitForComplete();

				if((defaultButton != null) && !defaultButton.isDisposed()) {
					notifyEvent(defaultButton, SWT.Selection);
				}
			}
		}
	};

	private static volatile boolean dialogCloseHandlerEngaged = false;

	public static void addDialogCloseHandler() {
		if(!dialogCloseHandlerEngaged) {
			Display.getDefault().syncExec(new Runnable() {

				public void run() {
					Display.getDefault().addFilter(SWT.Show, dialogCloseHandler);
					dialogCloseHandlerEngaged = true;
				}
			});
		}
	}

	public static void removeDialogCloseHandler() {
		Display.getDefault().syncExec(new Runnable() {

			public void run() {
				Display.getDefault().removeFilter(SWT.Show, dialogCloseHandler);
				dialogCloseHandlerEngaged = false;
			}
		});
	}

	/**
	 * Runs the specified {@code runnable}, ensuring that during its execution any dialogs that are opened are not automatically closed
	 * but are managed from within the {@code runnable}.
	 * 
	 * @param runnable
	 *        a runnable that deliberately opens and manages dialogs
	 */
	public static void runWithDialogs(Runnable runnable) {
		if(!dialogCloseHandlerEngaged) {
			// Just run it
			runnable.run();
		} else {
			// First, disengage the dialog close handler
			removeDialogCloseHandler();

			try {
				runnable.run();
			} finally {
				// Re-engage the handler
				addDialogCloseHandler();
			}
		}
	}
}

Back to the top