KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > swing > tabcontrol > DefaultTabDataModel


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  * DefaultTabDataModel.java
20  *
21  * Created on May 26, 2003, 3:41 PM
22  */

23
24 package org.netbeans.swing.tabcontrol;
25
26 import javax.swing.event.ChangeListener JavaDoc;
27 import org.netbeans.swing.tabcontrol.event.ComplexListDataEvent;
28 import org.netbeans.swing.tabcontrol.event.ComplexListDataListener;
29 import org.netbeans.swing.tabcontrol.event.VeryComplexListDataEvent;
30
31 import javax.swing.*;
32 import javax.swing.event.ChangeEvent JavaDoc;
33 import javax.swing.event.ListDataEvent JavaDoc;
34 import java.util.*;
35
36 /**
37  * Default implementation of TabDataModel.
38  *
39  * @author Tim Boudreau
40  */

41 public class DefaultTabDataModel implements TabDataModel {
42     /**
43      * Utility field holding list of ChangeListeners.
44      */

45     private transient ArrayList<ComplexListDataListener> listenerList;
46
47     private class L extends ArrayList<TabData> {
48         public void removeRange(int fromIndex, int toIndex) {
49             super.removeRange(fromIndex, toIndex);
50         }
51     }
52
53     private L list = new L();
54
55     /**
56      * Utility field holding list of ChangeListeners.
57      */

58     private transient ArrayList<ChangeListener JavaDoc> changeListenerList;
59
60     /**
61      * Creates a new instance of DefaultTabDataModel
62      */

63     public DefaultTabDataModel() {
64     }
65
66     /**
67      * Testing constructor
68      */

69     public DefaultTabDataModel(TabData[] data) {
70         list.addAll(Arrays.asList(data));
71     }
72
73     public java.util.List JavaDoc<TabData> getTabs() {
74         return Collections.unmodifiableList(list);
75     }
76
77     public TabData getTab(int index) {
78         return (TabData) list.get(index);
79     }
80
81     public void setTabs(TabData[] data) {
82
83         TabData[] oldContents = new TabData[list.size()];
84         oldContents = (TabData[]) list.toArray(oldContents);
85         
86         //No change, Peter says this will be the typical case
87
if (Arrays.equals(data, oldContents)) {
88             return;
89         }
90
91         List newContents = Arrays.asList(data);
92
93         list.clear();
94         list.addAll(Arrays.asList(data));
95
96         VeryComplexListDataEvent vclde = new VeryComplexListDataEvent(this,
97                                                                       oldContents,
98                                                                       data);
99         fireIndicesChanged(vclde);
100     }
101
102     public void setIcon(int index, Icon i) {
103         boolean[] widthChanged = new boolean[]{false};
104
105         boolean fireChange = _setIcon(index, i, widthChanged);
106         if (fireChange) {
107             ComplexListDataEvent clde = new ComplexListDataEvent(this,
108                                                                  ComplexListDataEvent.CONTENTS_CHANGED,
109                                                                  index, index,
110                                                                  widthChanged[0]);
111             fireContentsChanged(clde);
112         }
113     }
114
115     private boolean _setIcon(int index, Icon i, final boolean[] widthChanged) {
116         if (i == null) {
117             i = TabData.NO_ICON;
118         }
119         TabData data = getTab(index);
120         if (i != data.getIcon()) {
121             widthChanged[0] = data.getIcon().getIconWidth()
122                     != i.getIconWidth();
123             data.icon = i;
124             return true;
125         } else {
126             return false;
127         }
128     }
129
130     public void setText(int index, String JavaDoc txt) {
131         boolean[] widthChanged = new boolean[]{false};
132         boolean fireChange = _setText(index, txt, widthChanged);
133         if (fireChange) {
134             ComplexListDataEvent clde = new ComplexListDataEvent(this,
135                                                                  ComplexListDataEvent.CONTENTS_CHANGED,
136                                                                  index, index,
137                                                                  widthChanged[0]);
138             fireContentsChanged(clde);
139         }
140     }
141
142     private int[] _setText(int[] indices, String JavaDoc[] txt,
143                            final boolean[] widthChanged) {
144         widthChanged[0] = false;
145         boolean fireChange = false;
146         boolean[] changed = new boolean[indices.length];
147         int changedCount = 0;
148         Arrays.fill(changed, false);
149         for (int i = 0; i < indices.length; i++) {
150             boolean[] currWidthChanged = new boolean[]{false};
151             fireChange |=
152                     _setText(indices[i], txt[i], currWidthChanged);
153             widthChanged[0] |= currWidthChanged[0];
154             if (currWidthChanged[0])
155                 changedCount++;
156             changed[i] = currWidthChanged[0];
157         }
158         int[] toFire;
159         if (widthChanged[0] || fireChange) {
160             if (changedCount == indices.length) {
161                 toFire = indices;
162             } else {
163                 toFire = new int[changedCount];
164                 int idx = 0;
165                 for (int i = 0; i < indices.length; i++) {
166                     if (changed[i]) {
167                         toFire[idx] = indices[i];
168                         idx++;
169                     }
170                 }
171             }
172             return toFire;
173         }
174         return null;
175     }
176
177     private int[] _setIcon(int[] indices, Icon[] icons,
178                            final boolean[] widthChanged) {
179         widthChanged[0] = false;
180         boolean fireChange = false;
181         boolean[] changed = new boolean[indices.length];
182         int changedCount = 0;
183         Arrays.fill(changed, false);
184         boolean[] currWidthChanged = new boolean[]{false};
185         boolean currChanged = false;
186         for (int i = 0; i < indices.length; i++) {
187             currChanged =
188                     _setIcon(indices[i], icons[i], currWidthChanged);
189             fireChange |= currChanged;
190             widthChanged[0] |= currWidthChanged[0];
191             if (currChanged)
192                 changedCount++;
193             changed[i] = currChanged;
194         }
195         int[] toFire;
196         if (widthChanged[0] || fireChange) {
197             if (changedCount == indices.length) {
198                 toFire = indices;
199             } else {
200                 toFire = new int[changedCount];
201                 int idx = 0;
202                 for (int i = 0; i < indices.length; i++) {
203                     if (changed[i]) {
204                         toFire[idx] = indices[i];
205                         idx++;
206                     }
207                 }
208             }
209             return toFire;
210         }
211         return null;
212     }
213
214     public void setIconsAndText(int[] indices, String JavaDoc[] txt, Icon[] icons) {
215         boolean[] iconWidthsChanged = new boolean[]{false};
216         boolean[] txtWidthsChanged = new boolean[]{false};
217         int[] iconsToFire = _setIcon(indices, icons, iconWidthsChanged);
218         int[] txtToFire = _setText(indices, txt, txtWidthsChanged);
219         boolean widthChanged = iconWidthsChanged[0] || txtWidthsChanged[0];
220         boolean fire = widthChanged || iconsToFire != null
221                 || txtToFire != null;
222         if (fire) {
223             if ((indices == iconsToFire) && (indices == txtToFire)) {
224                 //if all icons/txt changed, optimize and don't calculate a merge
225
ComplexListDataEvent clde = new ComplexListDataEvent(this,
226                                                                      ComplexListDataEvent.CONTENTS_CHANGED,
227                                                                      indices,
228                                                                      widthChanged);
229                 fireContentsChanged(clde);
230             } else {
231                 //okay, there are differences in what was set to what. Build a
232
//merge of the change data and fire that
233
int size = (iconsToFire != null ? iconsToFire.length : 0)
234                         + (txtToFire != null ? txtToFire.length : 0);
235                 Set<Integer JavaDoc> allIndicesToFire = new HashSet<Integer JavaDoc>(size);
236                 Integer JavaDoc[] o;
237                 if (iconsToFire != null) {
238                     o = toObjectArray(iconsToFire);
239                     allIndicesToFire.addAll(Arrays.asList(o));
240                 }
241                 if (txtToFire != null) {
242                     o = toObjectArray(txtToFire);
243                     allIndicesToFire.addAll(Arrays.asList(o));
244                 }
245                 Integer JavaDoc[] all = new Integer JavaDoc[allIndicesToFire.size()];
246                 all = (Integer JavaDoc[]) allIndicesToFire.toArray(all);
247                 int[] allPrimitive = toPrimitiveArray(all);
248                 ComplexListDataEvent clde = new ComplexListDataEvent(this,
249                                                                      ComplexListDataEvent.CONTENTS_CHANGED,
250                                                                      allPrimitive,
251                                                                      widthChanged);
252                 fireContentsChanged(clde);
253             }
254         }
255     }
256
257     public void setIcon(int[] indices, Icon[] icons) {
258         boolean[] widthChanged = new boolean[]{false};
259         int[] toFire = _setIcon(indices, icons, widthChanged);
260         if (toFire != null) {
261             ComplexListDataEvent clde = new ComplexListDataEvent(this,
262                                                                  ComplexListDataEvent.CONTENTS_CHANGED,
263                                                                  toFire,
264                                                                  widthChanged[0]);
265             fireContentsChanged(clde);
266         }
267     }
268
269     public void setText(int[] indices, String JavaDoc[] txt) {
270         boolean[] widthChanged = new boolean[]{false};
271         int[] toFire = _setText(indices, txt, widthChanged);
272         if (toFire != null) {
273             ComplexListDataEvent clde = new ComplexListDataEvent(this,
274                                                                  ComplexListDataEvent.CONTENTS_CHANGED,
275                                                                  toFire,
276                                                                  widthChanged[0]);
277             fireContentsChanged(clde);
278         }
279     }
280
281     private boolean _setText(int index, String JavaDoc txt,
282                              final boolean[] widthChanged) {
283         TabData data = getTab(index);
284         if (txt != data.txt) {
285             widthChanged[0] = data.getText() != txt;
286             data.txt = txt;
287             return true;
288         } else {
289             return false;
290         }
291     }
292
293     public void setTab(int index, TabData data) {
294         if (!data.equals(getTab(index))) {
295             TabData olddata = getTab(index);
296             boolean txtChg = data.getText().equals(olddata.getText());
297             boolean compChg = data.getUserObject() != olddata.getUserObject();
298             list.set(index, data);
299             ComplexListDataEvent lde = new ComplexListDataEvent(this,
300                                                                 ListDataEvent.CONTENTS_CHANGED,
301                                                                 index, index,
302                                                                 txtChg,
303                                                                 compChg);
304             lde.setAffectedItems(new TabData[]{data});
305             fireContentsChanged(lde);
306         }
307     }
308
309     public void addTab(int index, TabData data) {
310         list.add(index, data);
311         ComplexListDataEvent lde = new ComplexListDataEvent(this,
312                                                             ComplexListDataEvent.INTERVAL_ADDED,
313                                                             index, index, true);
314         lde.setAffectedItems(new TabData[]{data});
315         fireIntervalAdded(lde);
316     }
317
318     public void addTabs(int start, TabData[] data) {
319         list.addAll(start, Arrays.asList(data));
320         ComplexListDataEvent lde = new ComplexListDataEvent(this, ListDataEvent.INTERVAL_ADDED, start, start
321                                                                                                        + data.length
322                                                                                                        - 1, true);
323         lde.setAffectedItems(data);
324         fireIntervalAdded(lde);
325     }
326
327     public void removeTab(int index) {
328         TabData[] td = new TabData[]{(TabData) list.get(index)};
329         list.remove(index);
330         ComplexListDataEvent lde = new ComplexListDataEvent(this,
331                                                             ListDataEvent.INTERVAL_REMOVED,
332                                                             index, index);
333         lde.setAffectedItems(td);
334         fireIntervalRemoved(lde);
335     }
336
337     /**
338      * Remove a range of tabs from <code>start</code> up to <i>and including</i>
339      * <code>finish</code>.
340      */

341     public void removeTabs(int start, int end) {
342         java.util.List JavaDoc affected = list.subList(start, end);
343         if (start == end) {
344             list.remove(start);
345         } else {
346             list.removeRange(start, end + 1);
347         }
348         ComplexListDataEvent lde = new ComplexListDataEvent(this,
349                                                             ListDataEvent.INTERVAL_REMOVED,
350                                                             start, end);
351         lde.setAffectedItems((TabData[]) list.toArray(new TabData[0]));
352         fireIntervalRemoved(lde);
353     }
354
355     public void addTabs(int[] indices, TabData[] data) {
356         Map<Integer JavaDoc,TabData> m = new HashMap<Integer JavaDoc,TabData>(data.length);
357         for (int i = 0; i < data.length; i++) {
358             m.put(new Integer JavaDoc(indices[i]), data[i]);
359         }
360         Arrays.sort(indices);
361         for (int i = 0; i < indices.length; i++) {
362             Integer JavaDoc key = new Integer JavaDoc(indices[i]);
363             TabData currData = m.get(key);
364             list.add(indices[i], currData);
365         }
366         ComplexListDataEvent clde = new ComplexListDataEvent(this,
367                                                              ComplexListDataEvent.ITEMS_ADDED,
368                                                              indices, true);
369         clde.setAffectedItems(data);
370         fireIndicesAdded(clde);
371     }
372
373     public void removeTabs(int[] indices) {
374         Arrays.sort(indices);
375         TabData[] affected = new TabData[indices.length];
376         for (int i = indices.length - 1; i >= 0; i--) {
377             affected[i] = (TabData) list.remove(indices[i]);
378         }
379         ComplexListDataEvent clde = new ComplexListDataEvent(this,
380                                                              ComplexListDataEvent.ITEMS_REMOVED,
381                                                              indices, true);
382         clde.setAffectedItems(affected);
383         fireIndicesRemoved(clde);
384     }
385
386     public int size() {
387         return list.size();
388     }
389
390     public synchronized void addComplexListDataListener(
391             ComplexListDataListener listener) {
392         if (listenerList == null) {
393             listenerList = new ArrayList<ComplexListDataListener>();
394         }
395         listenerList.add(listener);
396     }
397
398     public synchronized void removeComplexListDataListener(
399             ComplexListDataListener listener) {
400         listenerList.remove(listener);
401     }
402
403     private void fireIntervalAdded(ListDataEvent event) {
404         if (listenerList == null) {
405             return;
406         }
407         int max = listenerList.size();
408         for (int i = 0; i < max; i++) {
409             ComplexListDataListener l = (ComplexListDataListener) listenerList.get(
410                     i);
411             l.intervalAdded(event);
412         }
413         fireChange();
414     }
415
416     private void fireIntervalRemoved(ListDataEvent event) {
417         if (listenerList == null)
418             return;
419         int max = listenerList.size();
420         for (int i = 0; i < max; i++) {
421             ComplexListDataListener l = (ComplexListDataListener) listenerList.get(
422                     i);
423             l.intervalRemoved(event);
424         }
425         fireChange();
426     }
427
428     private void fireContentsChanged(ListDataEvent event) {
429         if (listenerList == null)
430             return;
431         int max = listenerList.size();
432         for (int i = 0; i < max; i++) {
433             ComplexListDataListener l = (ComplexListDataListener) listenerList.get(
434                     i);
435             l.contentsChanged(event);
436         }
437         fireChange();
438     }
439
440     private void fireIndicesAdded(ComplexListDataEvent event) {
441         if (listenerList == null)
442             return;
443         int max = listenerList.size();
444         for (int i = 0; i < max; i++) {
445             ComplexListDataListener l = (ComplexListDataListener) listenerList.get(
446                     i);
447             l.indicesAdded(event);
448         }
449         fireChange();
450     }
451
452     private void fireIndicesRemoved(ComplexListDataEvent event) {
453         if (listenerList == null)
454             return;
455         int max = listenerList.size();
456         for (int i = 0; i < max; i++) {
457             ComplexListDataListener l = (ComplexListDataListener) listenerList.get(
458                     i);
459             l.indicesRemoved(event);
460         }
461         fireChange();
462     }
463
464     private void fireIndicesChanged(ComplexListDataEvent event) {
465         if (listenerList == null)
466             return;
467         int max = listenerList.size();
468         for (int i = 0; i < max; i++) {
469             ComplexListDataListener l = (ComplexListDataListener) listenerList.get(
470                     i);
471             l.indicesChanged(event);
472         }
473         fireChange();
474     }
475
476     public String JavaDoc toString() {
477         StringBuffer JavaDoc out = new StringBuffer JavaDoc(getClass().getName());
478         out.append(" size =");
479         int max = size();
480         out.append(max);
481         out.append(" - ");
482         for (int i = 0; i < max; i++) {
483             TabData td = getTab(i);
484             out.append(td.toString());
485             if (i != max - 1) {
486                 out.append(',');
487             }
488         }
489         return out.toString();
490     }
491     
492     //===========================
493
//XXX remove ChangeListener support and handle the ComplexNNN events so nothing is repainted
494
//if not displayed on screen!
495

496     
497     /**
498      * Registers ChangeListener to receive events.
499      *
500      * @param listener The listener to register.
501      */

502     public synchronized void addChangeListener(ChangeListener JavaDoc listener) {
503         if (changeListenerList == null) {
504             changeListenerList = new ArrayList<ChangeListener JavaDoc>();
505         }
506         changeListenerList.add(listener);
507     }
508
509     /**
510      * Removes ChangeListener from the list of listeners.
511      *
512      * @param listener The listener to remove.
513      */

514     public synchronized void removeChangeListener(
515             javax.swing.event.ChangeListener JavaDoc listener) {
516         if (changeListenerList != null) {
517             changeListenerList.remove(listener);
518         }
519     }
520
521     ChangeEvent JavaDoc event = null;
522
523     private void fireChange() {
524         java.util.ArrayList JavaDoc list;
525         synchronized (this) {
526             if (changeListenerList == null)
527                 return;
528             list = (java.util.ArrayList JavaDoc) changeListenerList.clone();
529         }
530         if (event == null) {
531             event = new ChangeEvent JavaDoc(this);
532         }
533         for (int i = 0; i < list.size(); i++) {
534             ((javax.swing.event.ChangeListener JavaDoc) list.get(i)).stateChanged(
535                     event);
536         }
537     }
538
539     public int indexOf(TabData td) {
540         return list.indexOf(td);
541     }
542
543     private Integer JavaDoc[] toObjectArray(int[] o) {
544         Integer JavaDoc[] result = new Integer JavaDoc[o.length];
545         for (int i = 0; i < o.length; i++) {
546             result[i] = new Integer JavaDoc(o[i]);
547         }
548         return result;
549     }
550
551     private int[] toPrimitiveArray(Integer JavaDoc[] o) {
552         int[] result = new int[o.length];
553         for (int i = 0; i < o.length; i++) {
554             result[i] = o[i].intValue();
555         }
556         return result;
557     }
558
559 }
560
Popular Tags