Skip to main content
summaryrefslogtreecommitdiffstats
blob: f03c817c1cb3b535e60dad9fef059c32076768d9 (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
package org.eclipse.swt.custom;

/*
 * Licensed Materials - Property of IBM,
 * WebSphere Studio Workbench
 * (c) Copyright IBM Corp 2000
 */
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* A PopupList is a list of selectable items that appears in its own shell positioned above
* its parent shell.  It it used for selecting items when editing a Table cell (similar to the
* list that appears when you open a Combo box).
*
* The list will be positioned so that does not run off the screen and the largest number of items
* are visible.  It may appear above the current cursor location or below it depending how close you 
* are to the edge of the screen.
*/
public class PopupList {
	private Shell  shell;
	private List   list;
	private int    minimumWidth;
/** 
* Creates a PopupList above the specified shell.
*/
public PopupList(Shell parent) {

	shell = new Shell(parent, 0);
	
	list = new List(shell, SWT.SINGLE | SWT.V_SCROLL);	

	// close dialog if user selects outside of the shell
	shell.addListener(SWT.Deactivate, new Listener() {
		public void handleEvent(Event e){	
			shell.setVisible (false);
		};
	});
	
	// resize shell when list resizes
	shell.addControlListener(new ControlListener() {
		public void controlMoved(ControlEvent e){}
		public void controlResized(ControlEvent e){
			Rectangle shellSize = shell.getClientArea();
			list.setSize(shellSize.width, shellSize.height);
		}
	});
	
	// return list selection on Mouse Up or Carriage Return
	list.addMouseListener(new MouseListener() {
		public void mouseDoubleClick(MouseEvent e){};
		public void mouseDown(MouseEvent e){};
		public void mouseUp(MouseEvent e){
			shell.setVisible (false);
		};
	});
	list.addKeyListener(new KeyListener() {
		public void keyReleased(KeyEvent e){};
		public void keyPressed(KeyEvent e){
			if (e.character == '\r'){
				shell.setVisible (false);
			}
		};
	});
	
}
/**
* Gets the widget font.
* <p>
* @return the widget font
*
* @exception SWTError <ul>
*		<li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
*		<li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
*	</ul>
*/
public Font getFont () {
	return list.getFont();
}
/**
* Gets the items.
* <p>
* This operation will fail if the items cannot
* be queried from the OS.
*
* @return the items in the widget
*
* @exception SWTError <ul>
*		<li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
*		<li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
* 		<li>ERROR_CANNOT_GET_ITEM when the operation fails</li>
*	</ul>
*/
public String[] getItems () {
	return list.getItems();
}
/**
* Gets the minimum width of the list.
*
* @return the minimum width of the list
*/
public int getMinimumWidth () {
	return minimumWidth;
}
/**
* Launches the Popup List, waits for an item to be selected and then closes PopupList.
*
* @param rect the initial size and location of the PopupList; the dialog will be
*        positioned so that it does not run off the screen and the largest number of items are visible
*
* @return the text of the selected item or null if no item is selected
*/
public String open (Rectangle rect) {

	Point listSize = list.computeSize (rect.width, SWT.DEFAULT);
	Rectangle screenSize = shell.getDisplay().getBounds();

	// Position the dialog so that it does not run off the screen and the largest number of items are visible
	int spaceBelow = screenSize.height - (rect.y + rect.height) - 30;
	int spaceAbove = rect.y - 30;

	int y = 0;
	if (spaceAbove > spaceBelow && listSize.y > spaceBelow) {
		// place popup list above table cell
		if (listSize.y > spaceAbove){
			listSize.y = spaceAbove;
		} else {
			listSize.y += 2;
		}
		y = rect.y - listSize.y;
		
	} else {
		// place popup list below table cell
		if (listSize.y > spaceBelow){
			listSize.y = spaceBelow;
		} else {
			listSize.y += 2;
		}
		y = rect.y + rect.height;
	}
	
	// Make dialog as wide as the cell
	listSize.x = rect.width;
	// dialog width should not be les than minimumwidth
	if (listSize.x < minimumWidth)
		listSize.x = minimumWidth;
	
	// Align right side of dialog with right side of cell
	int x = rect.x + rect.width - listSize.x;
	
	shell.setBounds(x, y, listSize.x, listSize.y);
	
	shell.open();
	list.setFocus();

	Display display = shell.getDisplay();
	while (!shell.isDisposed () && shell.isVisible ()) {
		if (!display.readAndDispatch()) display.sleep();
	}
	
	String result = null;
	if (!shell.isDisposed ()) {
		String [] strings = list.getSelection ();
		shell.dispose();
		if (strings.length != 0) result = strings [0];
	}
	return result;
}
/**
* Selects an item with text that starts with specified String.
* <p>
* If the item is not currently selected, it is selected.  
* If the item at an index is selected, it remains selected.  
* If the string is not matched, it is ignored.
*
* @param string the text of the item
*
* @exception SWTError <ul>
*		<li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
*		<li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
*	</ul>
*/
public void select(String string) {
	String[] items = list.getItems();

	// find the first entry in the list that starts with the
	// specified string
	if (string != null){
		for (int i = 0; i < items.length; i++) {
			if (items[i].startsWith(string)){
				int index = list.indexOf(items[i]);
				list.select(index);
				break;
			}
		}
	}
}
/**
* Sets the widget font.
* <p>
* When new font is null, the font reverts
* to the default system font for the widget.
*
* @param font the new font (or null)
* 
* @exception SWTError <ul>
*		<li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
*		<li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
*	</ul>
*/
public void setFont (Font font) {
	list.setFont(font);
}
/**
* Sets all items.
* <p>
* The previous selection is cleared.
* The previous items are deleted.
* The new items are added.
* The top index is set to 0.
*
* @param items the array of items
*
* This operation will fail when an item is null
* or could not be added in the OS.
*
* @exception SWTError <ul>
*		<li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
*		<li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
*		<li>ERROR_NULL_ARGUMENT when items is null</li>
*		<li>ERROR_ITEM_NOT_ADDED when the operation fails</li>
*	</ul>
*/
public void setItems (String[] strings) {
	list.setItems(strings);
}
/**
* Sets the minimum width of the list.
*
* @param width the minimum width of the list
*/
public void setMinimumWidth (int width) {
	if (width < 0)
		throw new SWTError(SWT.ERROR_INVALID_ARGUMENT);
		
	minimumWidth = width;
}
}

Back to the top