001: /*
002: * Copyright Javelin Software, All rights reserved.
003: */
004:
005: package com.javelin.swinglets;
006:
007: import java.awt.*;
008: import java.awt.event.*;
009: import java.util.*;
010: import java.io.*;
011:
012: import javax.swing.*;
013:
014: import com.javelin.swinglets.plaf.*;
015:
016: /**
017: * SList defines a list.
018: * <p>
019: * The .toString() is displayed as the string value.
020: *
021: * @author Robin Sharp
022: */
023:
024: public class SList extends SComponent {
025: /**
026: * Construct a SList that displays the elements in the specified,
027: * non-null model. All SList constructors delegate to this one.
028: */
029: public SList(ListModel model) {
030: setModel(model);
031:
032: this .selectionModel = createSelectionModel();
033: }
034:
035: /**
036: * Creates a SList that contains the elements in the specified array.
037: */
038: public SList(final Object[] items) {
039: this (new AbstractListModel() {
040: public int getSize() {
041: return items.length;
042: }
043:
044: public Object getElementAt(int index) {
045: return items[index];
046: }
047: });
048: }
049:
050: /**
051: * Creates a SList that contains the elements in the specified vector.
052: */
053: public SList(final Vector vector) {
054: this (new AbstractListModel() {
055: public int getSize() {
056: return vector.size();
057: }
058:
059: public Object getElementAt(int index) {
060: return vector.elementAt(index);
061: }
062: });
063: }
064:
065: /**
066: * Creates a SList unslected.
067: */
068: public SList() {
069: this (new AbstractListModel() {
070: public int getSize() {
071: return 0;
072: }
073:
074: public Object getElementAt(int i) {
075: return "No Data Model";
076: }
077: });
078: }
079:
080: /**
081: * Returns the name of the L&F class that renders this component.
082: */
083: public Class getUIClass() {
084: return SList.class;
085: }
086:
087: /**
088: * Return the preferred number of visible rows.
089: */
090: public int getVisibleRowCount() {
091: return visibleRowCount;
092: }
093:
094: /**
095: * Set the preferred number of rows in the list that can be displayed
096: * without a scollbar, as determined by the nearest JViewport ancestor,
097: * if any.
098: */
099: public SList setVisibleRowCount(int visibleRowCount) {
100: firePropertyChange("visibleRowCount", this .visibleRowCount,
101: this .visibleRowCount = visibleRowCount);
102: return this ;
103: }
104:
105: /**
106: * Returns the data model that holds the list of items displayed
107: * by the SList component.
108: */
109: public ListModel getModel() {
110: return model;
111: }
112:
113: /**
114: * Sets the model that represents the contents or "value" of the
115: * list and clears the list selection after notifying PropertyChangeListeners.
116: * <p>
117: * This is a JavaBeans bound property.
118: *
119: * @param model the ListModel that provides the list of items for display
120: * @see #getModel
121: * @beaninfo
122: * bound: true
123: * attribute: visualUpdate true
124: * description: The object that contains the data to be drawn by this JList.
125: */
126: public SList setModel(ListModel model) {
127: if (model == null) {
128: throw new IllegalArgumentException(
129: "Model must be non null.");
130: }
131:
132: firePropertyChange("model", this .model, this .model = model);
133:
134: return this ;
135: }
136:
137: /**
138: * A convenience method that constructs a ListModel from an array of Objects
139: * and then applies setModel to it.
140: */
141: public SList setListData(final Object[] array) {
142: setModel(new AbstractListModel() {
143: public int getSize() {
144: return array.length;
145: }
146:
147: public Object getElementAt(int i) {
148: return array[i];
149: }
150: });
151:
152: return this ;
153: }
154:
155: /**
156: * A convenience method that constructs a ListModel from a Vector
157: * and then applies setModel to it.
158: */
159: public SList setListData(final Vector vector) {
160: setModel(new AbstractListModel() {
161: public int getSize() {
162: return vector.size();
163: }
164:
165: public Object getElementAt(int i) {
166: return vector.elementAt(i);
167: }
168: });
169:
170: return this ;
171: }
172:
173: /**
174: * Returns an instance of DefaultListSelectionModel. This
175: * method is used by the constructor to initialize the
176: * selectionModel property.
177: */
178: protected ListSelectionModel createSelectionModel() {
179: return new DefaultListSelectionModel();
180: }
181:
182: /**
183: * Returns the value of the current selection model. The selection
184: * model handles the task of making single selections, selections
185: * of contiguous ranges, and non-contiguous selections.
186: */
187: public ListSelectionModel getSelectionModel() {
188: return selectionModel;
189: }
190:
191: /**
192: * Determines whether single-item or multiple-item
193: * selections are allowed.
194: * The following selectionMode values are allowed:
195: * <ul>
196: * <li> <code>SINGLE_SELECTION</code>
197: * Only one list index can be selected at a time. In this
198: * mode the setSelectionInterval and addSelectionInterval
199: * methods are equivalent, and they only the first index
200: * argument is used.
201: * <li> <code>MULTIPLE_INTERVAL_SELECTION</code>
202: * In this mode, there's no restriction on what can be selected.
203: * </ul>
204: */
205: public SList setSelectionMode(int selectionMode) {
206: getSelectionModel().setSelectionMode(selectionMode);
207:
208: return this ;
209: }
210:
211: /**
212: * Returns whether single-item or multiple-item selections are allowed.
213: */
214: public int getSelectionMode() {
215: return getSelectionModel().getSelectionMode();
216: }
217:
218: /**
219: * Returns the number of items in the list.
220: */
221: public int getElementCount() {
222: return getModel().getSize();
223: }
224:
225: /**
226: * Returns the nth item in the list.
227: */
228: public Object getElementAt(int index) {
229: return getModel().getElementAt(index);
230: }
231:
232: /**
233: * Returns the first index argument from the most recent addSelectionInterval
234: * or setSelectionInterval call.
235: */
236: public int getAnchorSelectionIndex() {
237: return getSelectionModel().getAnchorSelectionIndex();
238: }
239:
240: /**
241: * Returns the second index argument from the most recent addSelectionInterval
242: * or setSelectionInterval call.
243: */
244: public int getLeadSelectionIndex() {
245: return getSelectionModel().getLeadSelectionIndex();
246: }
247:
248: /**
249: * Returns the lisSelectionModelallest selected cell index.
250: * This is a convenience method that just delegates to the selectionModel.
251: */
252: public int getMinSelectionIndex() {
253: return getSelectionModel().getMinSelectionIndex();
254: }
255:
256: /**
257: * Returns the largest selected cell index.
258: */
259: public int getMaxSelectionIndex() {
260: return getSelectionModel().getMaxSelectionIndex();
261: }
262:
263: /**
264: * Returns true if the specified index is selected.
265: */
266: public boolean isSelectedIndex(int index) {
267: return getSelectionModel().isSelectedIndex(index);
268: }
269:
270: /**
271: * Returns true if nothing is selected
272: */
273: public boolean isSelectionEmpty() {
274: return getSelectionModel().isSelectionEmpty();
275: }
276:
277: /**
278: * Clears the selection - after calling this method isSelectionEmpty()
279: * will return true.
280: */
281: public void clearSelection() {
282: getSelectionModel().clearSelection();
283: }
284:
285: /**
286: * Select the specified interval. Both the anchor and lead indices are
287: * included. It's not neccessary for anchor to be less than lead.
288: */
289: public SList setSelectionInterval(int anchor, int lead) {
290: getSelectionModel().setSelectionInterval(anchor, lead);
291:
292: return this ;
293: }
294:
295: /**
296: * Set the selection to be the union of the specified interval with current
297: * selection. Both the anchor and lead indices are
298: * included. It's not neccessary for anchor to be less than lead.
299: */
300: public void addSelectionInterval(int anchor, int lead) {
301: getSelectionModel().addSelectionInterval(anchor, lead);
302: }
303:
304: /**
305: * Set the selection to be the set difference of the specified interval
306: * and the current selection. Both the anchor and lead indices are
307: * removed. It's not neccessary for anchor to be less than lead.
308: */
309: public void removeSelectionInterval(int index0, int index1) {
310: getSelectionModel().removeSelectionInterval(index0, index1);
311: }
312:
313: /**
314: * Return an array of all of the selected indices in increasing
315: * order.
316: */
317: public int[] getSelectedIndices() {
318: int minIndex = getSelectionModel().getMinSelectionIndex();
319: int maxIndex = getSelectionModel().getMaxSelectionIndex();
320:
321: if (minIndex < 0 || maxIndex < 0) {
322: return new int[0];
323: }
324:
325: int[] tempArray = new int[1 + (maxIndex - minIndex)];
326: int count = 0;
327: for (int index = minIndex; index <= maxIndex; index++) {
328: if (getSelectionModel().isSelectedIndex(index)) {
329: tempArray[count++] = index;
330: }
331: }
332: int[] intArray = new int[count];
333: System.arraycopy(tempArray, 0, intArray, 0, count);
334: return intArray;
335: }
336:
337: /**
338: * Select a single cell.
339: */
340: public SList setSelectedIndex(int index) {
341: getSelectionModel().setSelectionInterval(index, index);
342:
343: return this ;
344: }
345:
346: /**
347: * Select a set of cells.
348: */
349: public SList setSelectedIndices(int[] indices) {
350: getSelectionModel().clearSelection();
351: for (int index = 0; index < indices.length; index++) {
352: getSelectionModel().addSelectionInterval(indices[index],
353: indices[index]);
354: }
355:
356: return this ;
357: }
358:
359: /**
360: * Return an array of the values for the selected cells.
361: * The returned values are sorted in increasing index order.
362: */
363: public Object[] getSelectedValues() {
364: int minIndex = getSelectionModel().getMinSelectionIndex();
365: int maxIndex = getSelectionModel().getMaxSelectionIndex();
366:
367: if (minIndex < 0 || maxIndex < 0) {
368: return new Object[0];
369: }
370:
371: Object[] tempArray = new Object[1 + (maxIndex - minIndex)];
372: int count = 0;
373: for (int index = minIndex; index <= maxIndex; index++) {
374: if (getSelectionModel().isSelectedIndex(index)) {
375: tempArray[count++] = getModel().getElementAt(index);
376: }
377: }
378: Object[] array = new Object[count];
379: System.arraycopy(tempArray, 0, array, 0, count);
380: return array;
381: }
382:
383: /**
384: * A convenience method that returns the first selected index.
385: * Returns -1 if there is no selected item.
386: */
387: public int getSelectedIndex() {
388: return getMinSelectionIndex();
389: }
390:
391: /**
392: * A convenience method that returns the first selected value
393: * or null, if the selection is empty.
394: */
395: public Object getSelectedValue() {
396: int index = getMinSelectionIndex();
397: return index == -1 ? null : getModel().getElementAt(index);
398: }
399:
400: /**
401: * Set the value as Text. This sets the text property. It is
402: * assumes that the text is the index.
403: */
404: public SComponent setValueAsText(String text) {
405: try {
406: StringTokenizer st = new StringTokenizer(text, ",");
407: int[] values = new int[st.countTokens()];
408: for (int index = 0; index < values.length; index++) {
409: values[index] = Integer.parseInt(st.nextToken());
410: }
411:
412: if (values.length == 1) {
413: setSelectedIndex(values[0]);
414: } else {
415: setSelectedIndices(values);
416: }
417: } catch (Exception e) {
418: //Fail silently
419: }
420:
421: return this ;
422: }
423:
424: // LISTENERS ////////////////////////////////////////////////////////////
425:
426: /**
427: * Adds the specified item listener to receive item events from
428: * this list.
429: */
430: public synchronized SList addItemListener(ItemListener listener) {
431: getUI().addListener(listener);
432: return this ;
433: }
434:
435: /**
436: * Removes the specified item listener so that it no longer
437: * receives item events from this list.
438: */
439: public synchronized SList removeItemListener(ItemListener listener) {
440: getUI().removeListener(listener);
441: return this ;
442: }
443:
444: // PRIVATE /////////////////////////////////////////////////////////////
445:
446: protected ListModel model;
447: protected ListSelectionModel selectionModel;
448:
449: protected int visibleRowCount = 10;
450:
451: }
|