1 /* 2 * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.swing; 27 28 import javax.swing.event.*; 29 import java.io.Serializable; 30 import java.util.EventListener; 31 32 /** 33 * The abstract definition for the data model that provides 34 * a <code>List</code> with its contents. 35 * <p> 36 * <strong>Warning:</strong> 37 * Serialized objects of this class will not be compatible with 38 * future Swing releases. The current serialization support is 39 * appropriate for short term storage or RMI between applications running 40 * the same version of Swing. As of 1.4, support for long term storage 41 * of all JavaBeans<sup><font size="-2">TM</font></sup> 42 * has been added to the <code>java.beans</code> package. 43 * Please see {@link java.beans.XMLEncoder}. 44 * 45 * @author Hans Muller 46 */ 47 public abstract class AbstractListModel implements ListModel, Serializable 48 { 49 protected EventListenerList listenerList = new EventListenerList(); 50 51 52 /** 53 * Adds a listener to the list that's notified each time a change 54 * to the data model occurs. 55 * 56 * @param l the <code>ListDataListener</code> to be added 57 */ 58 public void addListDataListener(ListDataListener l) { 59 listenerList.add(ListDataListener.class, l); 60 } 61 62 63 /** 64 * Removes a listener from the list that's notified each time a 65 * change to the data model occurs. 66 * 67 * @param l the <code>ListDataListener</code> to be removed 68 */ 69 public void removeListDataListener(ListDataListener l) { 70 listenerList.remove(ListDataListener.class, l); 71 } 72 73 74 /** 75 * Returns an array of all the list data listeners 76 * registered on this <code>AbstractListModel</code>. 77 * 78 * @return all of this model's <code>ListDataListener</code>s, 79 * or an empty array if no list data listeners 80 * are currently registered 81 * 82 * @see #addListDataListener 83 * @see #removeListDataListener 84 * 85 * @since 1.4 86 */ 87 public ListDataListener[] getListDataListeners() { 88 return listenerList.getListeners(ListDataListener.class); 89 } 90 91 92 /** 93 * <code>AbstractListModel</code> subclasses must call this method 94 * <b>after</b> 95 * one or more elements of the list change. The changed elements 96 * are specified by the closed interval index0, index1 -- the endpoints 97 * are included. Note that 98 * index0 need not be less than or equal to index1. 99 * 100 * @param source the <code>ListModel</code> that changed, typically "this" 101 * @param index0 one end of the new interval 102 * @param index1 the other end of the new interval 103 * @see EventListenerList 104 * @see DefaultListModel 105 */ 106 protected void fireContentsChanged(Object source, int index0, int index1) 107 { 108 Object[] listeners = listenerList.getListenerList(); 109 ListDataEvent e = null; 110 111 for (int i = listeners.length - 2; i >= 0; i -= 2) { 112 if (listeners[i] == ListDataListener.class) { 113 if (e == null) { 114 e = new ListDataEvent(source, ListDataEvent.CONTENTS_CHANGED, index0, index1); 115 } 116 ((ListDataListener)listeners[i+1]).contentsChanged(e); 117 } 118 } 119 } 120 121 122 /** 123 * <code>AbstractListModel</code> subclasses must call this method 124 * <b>after</b> 125 * one or more elements are added to the model. The new elements 126 * are specified by a closed interval index0, index1 -- the enpoints 127 * are included. Note that 128 * index0 need not be less than or equal to index1. 129 * 130 * @param source the <code>ListModel</code> that changed, typically "this" 131 * @param index0 one end of the new interval 132 * @param index1 the other end of the new interval 133 * @see EventListenerList 134 * @see DefaultListModel 135 */ 136 protected void fireIntervalAdded(Object source, int index0, int index1) 137 { 138 Object[] listeners = listenerList.getListenerList(); 139 ListDataEvent e = null; 140 141 for (int i = listeners.length - 2; i >= 0; i -= 2) { 142 if (listeners[i] == ListDataListener.class) { 143 if (e == null) { 144 e = new ListDataEvent(source, ListDataEvent.INTERVAL_ADDED, index0, index1); 145 } 146 ((ListDataListener)listeners[i+1]).intervalAdded(e); 147 } 148 } 149 } 150 151 152 /** 153 * <code>AbstractListModel</code> subclasses must call this method 154 * <b>after</b> one or more elements are removed from the model. 155 * <code>index0</code> and <code>index1</code> are the end points 156 * of the interval that's been removed. Note that <code>index0</code> 157 * need not be less than or equal to <code>index1</code>. 158 * 159 * @param source the <code>ListModel</code> that changed, typically "this" 160 * @param index0 one end of the removed interval, 161 * including <code>index0</code> 162 * @param index1 the other end of the removed interval, 163 * including <code>index1</code> 164 * @see EventListenerList 165 * @see DefaultListModel 166 */ 167 protected void fireIntervalRemoved(Object source, int index0, int index1) 168 { 169 Object[] listeners = listenerList.getListenerList(); 170 ListDataEvent e = null; 171 172 for (int i = listeners.length - 2; i >= 0; i -= 2) { 173 if (listeners[i] == ListDataListener.class) { 174 if (e == null) { 175 e = new ListDataEvent(source, ListDataEvent.INTERVAL_REMOVED, index0, index1); 176 } 177 ((ListDataListener)listeners[i+1]).intervalRemoved(e); 178 } 179 } 180 } 181 182 /** 183 * Returns an array of all the objects currently registered as 184 * <code><em>Foo</em>Listener</code>s 185 * upon this model. 186 * <code><em>Foo</em>Listener</code>s 187 * are registered using the <code>add<em>Foo</em>Listener</code> method. 188 * <p> 189 * You can specify the <code>listenerType</code> argument 190 * with a class literal, such as <code><em>Foo</em>Listener.class</code>. 191 * For example, you can query a list model 192 * <code>m</code> 193 * for its list data listeners 194 * with the following code: 195 * 196 * <pre>ListDataListener[] ldls = (ListDataListener[])(m.getListeners(ListDataListener.class));</pre> 197 * 198 * If no such listeners exist, 199 * this method returns an empty array. 200 * 201 * @param listenerType the type of listeners requested; 202 * this parameter should specify an interface 203 * that descends from <code>java.util.EventListener</code> 204 * @return an array of all objects registered as 205 * <code><em>Foo</em>Listener</code>s 206 * on this model, 207 * or an empty array if no such 208 * listeners have been added 209 * @exception ClassCastException if <code>listenerType</code> doesn't 210 * specify a class or interface that implements 211 * <code>java.util.EventListener</code> 212 * 213 * @see #getListDataListeners 214 * 215 * @since 1.3 216 */ 217 public <T extends EventListener> T[] getListeners(Class<T> listenerType) { 218 return listenerList.getListeners(listenerType); 219 } 220 }