001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2003 Jennifer Lhotak
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: */
019:
020: package ca.mcgill.sable.soot.ui;
021:
022: import org.eclipse.swt.SWT;
023: import org.eclipse.swt.events.*;
024: import org.eclipse.swt.graphics.Color;
025: import org.eclipse.swt.graphics.Point;
026: import org.eclipse.swt.graphics.RGB;
027: import org.eclipse.swt.graphics.Rectangle;
028: import org.eclipse.swt.widgets.*;
029:
030: import ca.mcgill.sable.soot.SootPlugin;
031:
032: public class PopupListSelector {
033: private Shell shell;
034: private List list;
035: private String selected;
036: private int minimumWidth;
037:
038: public PopupListSelector(Shell parent) {
039:
040: shell = new Shell(parent, 0);
041:
042: list = new List(shell, SWT.SINGLE | SWT.V_SCROLL);
043: list.setBackground(SootPlugin.getDefault().getColorManager()
044: .getColor(new RGB(255, 255, 255)));
045: list.setFont(SootPlugin.getDefault().getSootFont());
046:
047: // close dialog if user selects outside of the shell
048: shell.addListener(SWT.Deactivate, new Listener() {
049: public void handleEvent(Event e) {
050: shell.setVisible(false);
051: };
052: });
053:
054: // resize shell when list resizes
055: shell.addControlListener(new ControlListener() {
056: public void controlMoved(ControlEvent e) {
057: }
058:
059: public void controlResized(ControlEvent e) {
060: Rectangle shellSize = shell.getClientArea();
061: list.setSize(shellSize.width, shellSize.height);
062: }
063: });
064:
065: // return list selection on Mouse Up or Carriage Return
066: list.addMouseListener(new MouseListener() {
067: public void mouseDoubleClick(MouseEvent e) {
068: };
069:
070: public void mouseDown(MouseEvent e) {
071: };
072:
073: public void mouseUp(MouseEvent e) {
074: setSelected(list.getSelection()[0]);
075: shell.setVisible(false);
076: };
077: });
078:
079: list.addKeyListener(new KeyListener() {
080: public void keyReleased(KeyEvent e) {
081: };
082:
083: public void keyPressed(KeyEvent e) {
084: if (e.character == '\r') {
085: shell.setVisible(false);
086: }
087: };
088: });
089:
090: }
091:
092: public String open(Rectangle rect) {
093:
094: Point listSize = getList().computeSize(rect.width, SWT.DEFAULT);
095: Rectangle screenSize = getShell().getDisplay().getBounds();
096:
097: // Position the dialog so that it does not run off the screen and the largest number of items are visible
098: int spaceBelow = screenSize.height - (rect.y + rect.height)
099: - 30;
100: int spaceAbove = rect.y - 30;
101:
102: int y = 0;
103: if (spaceAbove > spaceBelow && listSize.y > spaceBelow) {
104: // place popup list above table cell
105: if (listSize.y > spaceAbove) {
106: listSize.y = spaceAbove;
107: } else {
108: listSize.y += 2;
109: }
110: y = rect.y - listSize.y;
111:
112: } else {
113: // place popup list below table cell
114: if (listSize.y > spaceBelow) {
115: listSize.y = spaceBelow;
116: } else {
117: listSize.y += 2;
118: }
119: y = rect.y + rect.height;
120: }
121:
122: // Make dialog as wide as the cell
123: listSize.x = rect.width;
124: // dialog width should not be les than minimumwidth
125: if (listSize.x < getMinimumWidth())
126: listSize.x = getMinimumWidth();
127:
128: // Align right side of dialog with right side of cell
129: int x = rect.x + rect.width - listSize.x;
130: y = 0;
131: if (spaceAbove <= spaceBelow) {
132: y = spaceAbove + rect.y;
133: } else {
134: y = rect.y - spaceBelow;
135: }
136:
137: y = (rect.y * 16) + 85;
138:
139: getShell().setBounds(rect.x, y, listSize.x, listSize.y);
140:
141: shell.open();
142: list.setFocus();
143:
144: Display display = shell.getDisplay();
145: while (!shell.isDisposed() && shell.isVisible()) {
146: if (!display.readAndDispatch())
147: display.sleep();
148: }
149:
150: String result = null;
151: if (!shell.isDisposed()) {
152: String[] strings = list.getSelection();
153: shell.dispose();
154: if (strings.length != 0)
155: result = strings[0];
156: }
157: return result;
158: }
159:
160: public void setItems(String[] strings) {
161: list.setItems(strings);
162: }
163:
164: /**
165: * Sets the minimum width of the list.
166: *
167: * @param width the minimum width of the list
168: */
169: public void setMinimumWidth(int width) {
170: minimumWidth = width;
171: }
172:
173: /**
174: * @return
175: */
176: public List getList() {
177: return list;
178: }
179:
180: /**
181: * @return
182: */
183: public Shell getShell() {
184: return shell;
185: }
186:
187: /**
188: * @param list
189: */
190: public void setList(List list) {
191: this .list = list;
192: }
193:
194: /**
195: * @param shell
196: */
197: public void setShell(Shell shell) {
198: this .shell = shell;
199: }
200:
201: /**
202: * @return
203: */
204: public String getSelected() {
205: return selected;
206: }
207:
208: /**
209: * @param string
210: */
211: public void setSelected(String string) {
212: selected = string;
213: }
214:
215: /**
216: * @return
217: */
218: public int getMinimumWidth() {
219: return minimumWidth;
220: }
221:
222: }
|