001: /*
002: $Id: StringListParameter.java,v 1.7 2005/02/14 12:06:19 vauclair Exp $
003:
004: Copyright (C) 2002-2005 Sebastien Vauclair
005:
006: This file is part of Extensible Java Profiler.
007:
008: Extensible Java Profiler is free software; you can redistribute it and/or
009: modify it under the terms of the GNU General Public License as published by
010: the Free Software Foundation; either version 2 of the License, or
011: (at your option) any later version.
012:
013: Extensible Java Profiler is distributed in the hope that it will be useful,
014: but WITHOUT ANY WARRANTY; without even the implied warranty of
015: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: GNU General Public License for more details.
017:
018: You should have received a copy of the GNU General Public License
019: along with Extensible Java Profiler; if not, write to the Free Software
020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021: */
022:
023: package ejp.presenter.api.filters.parameters;
024:
025: import java.awt.Dimension;
026: import java.awt.event.ActionEvent;
027: import java.awt.event.ActionListener;
028: import java.awt.event.MouseAdapter;
029: import java.awt.event.MouseEvent;
030: import java.awt.event.WindowAdapter;
031: import java.awt.event.WindowEvent;
032: import java.util.ArrayList;
033: import java.util.Collections;
034: import java.util.Iterator;
035: import java.util.List;
036: import java.util.StringTokenizer;
037: import java.util.Vector;
038:
039: import javax.swing.AbstractAction;
040: import javax.swing.DefaultListModel;
041: import javax.swing.JDialog;
042: import javax.swing.JList;
043: import javax.swing.JMenuItem;
044: import javax.swing.JPopupMenu;
045: import javax.swing.JScrollPane;
046: import javax.swing.JTextField;
047: import javax.swing.ListModel;
048: import javax.swing.ScrollPaneConstants;
049:
050: import ejp.presenter.gui.Utils;
051:
052: /**
053: * A String list parameter, graphically represented as an editable list.
054: *
055: * <p>
056: * TODOC (later)
057: *
058: * @author Sebastien Vauclair
059: * @version <code>$Revision: 1.7 $<br>$Date: 2005/02/14 12:06:19 $</code>
060: */
061: public class StringListParameter extends AbstractParameter {
062: /**
063: * Separator character between strings in text descriptions.
064: */
065: public static final String STRING_SEPARATOR = ";";
066:
067: protected final DefaultListModel m_listModel = new DefaultListModel();
068:
069: public static final int PREFERRED_LIST_WIDTH = 250;
070:
071: protected final JList jlValue;
072:
073: protected final JPopupMenu m_popupMenu;
074:
075: protected final JMenuItem m_jmiRemove;
076:
077: protected final JMenuItem m_jmiEdit;
078:
079: public StringListParameter(String aName, String aTitle,
080: String aToolTipText) {
081: super (aName, aTitle, aToolTipText);
082:
083: jlValue = new JList(m_listModel);
084: Utils.setCommonProperties(jlValue);
085: jlValue.setPreferredSize(new Dimension(PREFERRED_LIST_WIDTH,
086: jlValue.getPreferredSize().height));
087:
088: jlValue.addMouseListener(new MouseAdapter() {
089: public void mouseClicked(MouseEvent e_) {
090: if (e_.getClickCount() == 2) {
091: int idx = jlValue.locationToIndex(e_.getPoint());
092: if (idx == -1) {
093: // nothing to edit
094: return;
095: }
096:
097: doEditItem(idx);
098: }
099: }
100: });
101:
102: m_popupMenu = new JPopupMenu();
103: Utils.setCommonProperties(m_popupMenu);
104:
105: JMenuItem tmpjmi = null;
106:
107: tmpjmi = new JMenuItem(new AbstractAction("Add...") {
108: public void actionPerformed(ActionEvent e_) {
109: PackageNameDialog pnd = new PackageNameDialog("");
110: pnd.setVisible(true);
111: String newText = pnd.getText();
112: if (newText == null) {
113: // cancelled
114: return;
115: }
116:
117: m_listModel.addElement(newText);
118:
119: organizeItems();
120: }
121: });
122: Utils.setCommonProperties(tmpjmi);
123: m_popupMenu.add(tmpjmi);
124:
125: tmpjmi = new JMenuItem(new AbstractAction("Edit") {
126: public void actionPerformed(ActionEvent e_) {
127: int idx = jlValue.getSelectedIndex();
128: if (idx == -1) {
129: // nothing to edit
130: return;
131: }
132:
133: doEditItem(idx);
134: }
135: });
136: Utils.setCommonProperties(tmpjmi);
137: m_popupMenu.add(tmpjmi);
138: m_jmiEdit = tmpjmi;
139:
140: tmpjmi = new JMenuItem(new AbstractAction("Remove") {
141: public void actionPerformed(ActionEvent e_) {
142: int idx = jlValue.getSelectedIndex();
143: if (idx == -1) {
144: // nothing to remove
145: return;
146: }
147: m_listModel.remove(idx);
148: }
149: });
150: Utils.setCommonProperties(tmpjmi);
151: m_popupMenu.add(tmpjmi);
152: m_jmiRemove = tmpjmi;
153:
154: jlValue.addMouseListener(new PopupListener());
155:
156: JScrollPane jsp = new JScrollPane(jlValue);
157: jsp
158: .setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
159:
160: addLine("Packages to hide", "TODO (comment).", jsp, null);
161: }
162:
163: /**
164: * Locks the list's state.
165: */
166: public void setReadOnly() {
167: jlValue.setEnabled(false);
168: }
169:
170: public Object getValue() {
171: ListModel model = jlValue.getModel();
172: int size = model.getSize();
173: Vector result = new Vector(size);
174: for (int i = 0; i < size; i++) {
175: result.add(model.getElementAt(i));
176: }
177: return result;
178: }
179:
180: public void setValue(Object aObject) throws ClassCastException {
181: m_listModel.clear();
182: List l = (List) aObject;
183: for (Iterator it = l.iterator(); it.hasNext();) {
184: m_listModel.addElement(it.next());
185: }
186: }
187:
188: /**
189: * Gets value as text.
190: *
191: * <p>
192: * Strings are separated by {@link #STRING_SEPARATOR}characters.
193: */
194: public String getValueAsText() {
195: ListModel model = jlValue.getModel();
196: int size = model.getSize();
197:
198: StringBuffer buffer = new StringBuffer();
199:
200: for (int i = 0; i < size; i++) {
201: if (i > 0)
202: buffer.append(STRING_SEPARATOR);
203: buffer.append(model.getElementAt(i));
204: }
205:
206: return buffer.toString();
207: }
208:
209: /**
210: * Sets value from text.
211: *
212: * <p>
213: * Input text is tokenized using {@link #STRING_SEPARATOR}.
214: *
215: * @exception IllegalStateException
216: * if an error occurs in the tokenizer.
217: */
218: public void setValueAsText(String aTextValue)
219: throws IllegalStateException {
220: StringTokenizer st = new StringTokenizer(aTextValue,
221: STRING_SEPARATOR, false);
222: int count = st.countTokens();
223:
224: ArrayList items = new ArrayList(count);
225: while (st.hasMoreTokens())
226: items.add(st.nextToken());
227:
228: if (items.size() != count)
229: throw new IllegalStateException("Actual count of strings ("
230: + items.size() + ") is not as expected (" + count
231: + ")");
232:
233: setValue(new ArrayList(items));
234:
235: organizeItems();
236: }
237:
238: public boolean matches(String name_) {
239: ListModel model = jlValue.getModel();
240: int size = model.getSize();
241:
242: for (int i = 0; i < size; i++) {
243: if (name_.startsWith((String) model.getElementAt(i)))
244: return true;
245: }
246: return false;
247: }
248:
249: protected void updatePopupMenu() {
250: boolean enabled = jlValue.getSelectedIndex() != -1;
251: m_jmiRemove.setEnabled(enabled);
252: m_jmiEdit.setEnabled(enabled);
253: }
254:
255: protected void doEditItem(int index_) {
256: PackageNameDialog pnd = new PackageNameDialog(
257: (String) m_listModel.getElementAt(index_));
258: pnd.setVisible(true);
259: String newText = pnd.getText();
260: if (newText == null) {
261: // cancelled
262: return;
263: }
264:
265: m_listModel.setElementAt(newText, index_);
266:
267: organizeItems();
268: }
269:
270: protected void organizeItems() {
271: List items = (List) getValue();
272: Collections.sort(items);
273: setValue(items);
274: }
275:
276: protected class PopupListener extends MouseAdapter {
277: public void mousePressed(MouseEvent e_) {
278: maybeShowPopup(e_);
279: }
280:
281: public void mouseReleased(MouseEvent e_) {
282: maybeShowPopup(e_);
283: }
284:
285: private void maybeShowPopup(MouseEvent e_) {
286: if (e_.isPopupTrigger() && e_.getComponent().isEnabled()) {
287: updatePopupMenu();
288: m_popupMenu.show(e_.getComponent(), e_.getX(), e_
289: .getY());
290: }
291: }
292: }
293:
294: protected class PackageNameDialog extends JDialog {
295: protected String m_text = null;
296:
297: public static final int PREFERRED_WIDTH = 250;
298:
299: protected final JTextField m_textField;
300:
301: public PackageNameDialog(String initial_) {
302: super (dialog, "Package name", true);
303:
304: m_textField = new JTextField(initial_);
305: Utils.setCommonProperties(m_textField);
306: m_textField.setPreferredSize(new Dimension(PREFERRED_WIDTH,
307: m_textField.getPreferredSize().height));
308: getContentPane().add(m_textField);
309:
310: m_textField.addActionListener(new ActionListener() {
311: public void actionPerformed(ActionEvent e_) {
312: m_text = m_textField.getText();
313: dispose();
314: }
315: });
316:
317: pack();
318: Utils.centerDialog(this , dialog);
319: setResizable(false);
320:
321: addWindowListener(new WindowAdapter() {
322: public void windowClosing(WindowEvent e_) {
323: handleWindowClosing();
324: }
325: });
326:
327: }
328:
329: protected String getText() {
330: return m_text;
331: }
332:
333: protected void handleWindowClosing() {
334: m_text = null;
335: dispose();
336: }
337: }
338: }
|