KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > swing > tabcontrol > plaf > DefaultTabSelectionModel


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */
/*
19  * DefaultTabSelectionModel.java
20  *
21  * Created on May 26, 2003, 5:37 PM
22  */

23
24 package org.netbeans.swing.tabcontrol.plaf;
25
26 import java.util.ArrayList JavaDoc;
27 import javax.swing.event.ChangeListener JavaDoc;
28 import org.netbeans.swing.tabcontrol.TabDataModel;
29 import org.netbeans.swing.tabcontrol.event.ArrayDiff;
30 import org.netbeans.swing.tabcontrol.event.ComplexListDataEvent;
31 import org.netbeans.swing.tabcontrol.event.ComplexListDataListener;
32 import org.netbeans.swing.tabcontrol.event.VeryComplexListDataEvent;
33
34 import javax.swing.*;
35 import javax.swing.event.ChangeEvent JavaDoc;
36 import javax.swing.event.ListDataEvent JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Set JavaDoc;
39
40 /**
41  * Default implementation of tab selection model. Listens to the supplied data
42  * model and updates the selection appropriately on all add/remove events so that
43  * the actual selection does not change if items are inserted into the model ahead
44  * of the current selection, etc.
45  *
46  * @author Tim Boudreau
47  */

48 final class DefaultTabSelectionModel implements SingleSelectionModel,
49         ComplexListDataListener {
50     TabDataModel dataModel;
51     int sel = -1;
52     /**
53      * Utility field holding list of ChangeListeners.
54      */

55     private transient ArrayList JavaDoc<ChangeListener JavaDoc> changeListenerList;
56
57     /**
58      * Creates a new instance of DefaultTabSelectionModel
59      */

60     public DefaultTabSelectionModel(TabDataModel tdm) {
61         dataModel = tdm;
62         attach();
63     }
64
65     public void attach() {
66         dataModel.addComplexListDataListener(this);
67     }
68
69     public void detach() {
70         dataModel.removeComplexListDataListener(this);
71     }
72
73     public void clearSelection() {
74         sel = -1;
75         fireStateChanged();
76     }
77
78     public int getSelectedIndex() {
79         return sel;
80     }
81
82     public boolean isSelected() {
83         return sel != -1;
84     }
85
86     public void setSelectedIndex(int index) {
87         if (index != sel) {
88             int oldIndex = sel;
89             if ((index < -1) || (index >= dataModel.size())) {
90                 throw new IllegalArgumentException JavaDoc("Selected index set to "
91                    + index
92                    + " but model size is only " + dataModel.size());
93             }
94             sel = index;
95             fireStateChanged();
96         }
97     }
98
99     private void adjustSelectionForEvent(ListDataEvent e) {
100         if (e.getType() == e.CONTENTS_CHANGED || sel == -1) {
101             return;
102         }
103         int start = e.getIndex0();
104         int end = e.getIndex1() + 1;
105         if (e.getType() == e.INTERVAL_REMOVED) {
106             if (sel < start) {
107                 return;
108             } else {
109                 if (sel >= start) {
110                     if (sel > end) {
111                         sel -= end - start;
112                     } else {
113                         sel = start;
114                         if (sel >= dataModel.size()) {
115                             sel = dataModel.size() - 1;
116                         }
117                     }
118                     fireStateChanged();
119                 }
120             }
121         } else {
122             if (sel < start) {
123                 //not affected, do nothing
124
return;
125             }
126             if (sel >= start) {
127                 if (end - 1 == start) {
128                     sel++;
129                 } else if (sel < end) {
130                     sel = (end + (sel - start)) - 1;
131                 } else {
132                     sel += (end - start) - 1;
133                 }
134                 fireStateChanged();
135             }
136         }
137     }
138
139     public void contentsChanged(ListDataEvent e) {
140         adjustSelectionForEvent(e);
141     }
142
143     public void intervalAdded(ListDataEvent e) {
144         adjustSelectionForEvent(e);
145     }
146
147     public void intervalRemoved(ListDataEvent e) {
148         adjustSelectionForEvent(e);
149     }
150
151     public void indicesAdded(ComplexListDataEvent e) {
152         if (sel < 0) return;
153         int[] indices = e.getIndices();
154         java.util.Arrays.sort(indices);
155         int offset = 0;
156         for (int i = 0; i < indices.length; i++) {
157             if (sel >= indices[i]) {
158                 offset++;
159             } else {
160                 break;
161             }
162         }
163         if (offset > 0) {
164             sel += offset;
165             fireStateChanged();
166         }
167     }
168
169     public void indicesRemoved(ComplexListDataEvent e) {
170         if (sel < 0) return;
171         int[] indices = e.getIndices();
172         java.util.Arrays.sort(indices);
173         int offset = -1;
174         for (int i = 0; i < indices.length; i++) {
175             if (sel > indices[i]) {
176                 offset--;
177             } else {
178                 break;
179             }
180         }
181         if (sel == dataModel.size()) {
182             sel -= 1;
183             fireStateChanged();
184             return;
185         }
186         if (dataModel.size() == 0) {
187             sel = -1;
188             fireStateChanged();
189         } else if (offset != 0) {
190             sel = Math.max( -1, Math.min (sel + offset, -1));
191             fireStateChanged();
192         }
193     }
194
195     public void indicesChanged(ComplexListDataEvent e) {
196         if (sel < 0) return;
197         if (e instanceof VeryComplexListDataEvent) { //it always will be
198

199             ArrayDiff dif = ((VeryComplexListDataEvent) e).getDiff();
200
201             boolean changed = false;
202             
203             if (dif == null) {
204                 //no differences
205
return;
206             }
207             
208             //Get the deleted and added indices
209
Set JavaDoc<Integer JavaDoc> deleted = dif.getDeletedIndices();
210             Set JavaDoc<Integer JavaDoc> added = dif.getAddedIndices();
211             
212             //create an Integer to compare
213
Integer JavaDoc idx = new Integer JavaDoc(getSelectedIndex());
214             
215             //Don't iterate if everything was closed, we know what to do
216
if (dataModel.size() == 0) {
217                 sel = -1;
218                 fireStateChanged();
219                 return;
220             }
221             
222             //Iterate all of the deleted items, and count how many were
223
//removed at indices lower than the selection, so we can subtract
224
//that from the selected index to keep selection on the same tab
225
Iterator JavaDoc<Integer JavaDoc> i = deleted.iterator();
226             int offset = 0;
227             Integer JavaDoc curr;
228             while (i.hasNext()) {
229                 curr = i.next();
230                 if (curr.compareTo(idx) <= 0) {
231                     offset++;
232                 }
233             }
234             
235             //Iterate all of the added items, and count how many were added at
236
//indices below the selected index, so we can add that to the selected
237
//index
238
i = added.iterator();
239             while (i.hasNext()) {
240                 curr = i.next();
241                 if (curr.compareTo(idx) >= 0) {
242                     offset--;
243                 }
244             }
245
246             sel -= offset;
247             if (sel < 0) {
248                 //The tab at index 0 was closed, but we always want to show
249
//something if we can, so change it to 0 if possible
250
sel = dataModel.size() > 0 ? 0 : -1;
251             }
252             
253             //Make sure we're not off the end of the array - we could be if the
254
//selection was the last and it and others were removed
255
if (sel >= dataModel.size()) {
256                 sel = dataModel.size() - 1;
257             }
258             
259             if (offset != 0) {
260                 fireStateChanged();
261             }
262         }
263         //do nothing
264
}
265
266     public synchronized void addChangeListener(ChangeListener JavaDoc listener) {
267         if (changeListenerList == null) {
268             changeListenerList = new ArrayList JavaDoc<ChangeListener JavaDoc>();
269         }
270         changeListenerList.add(listener);
271     }
272
273     public synchronized void removeChangeListener(ChangeListener JavaDoc listener) {
274         if (changeListenerList != null) {
275             changeListenerList.remove(listener);
276         }
277     }
278
279     ChangeEvent JavaDoc ce = new ChangeEvent JavaDoc(this);
280
281     private void fireStateChanged() {
282         ArrayList JavaDoc<ChangeListener JavaDoc> list;
283         synchronized (this) {
284             if (changeListenerList == null) {
285                 return;
286             }
287             list = new ArrayList JavaDoc<ChangeListener JavaDoc>( changeListenerList );
288         }
289         for( ChangeListener JavaDoc l : list ) {
290             l.stateChanged(ce);
291         }
292     }
293
294 }
295
Popular Tags