001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.swing.tabcontrol;
043:
044: import java.awt.Component;
045: import java.awt.Graphics;
046: import java.util.Arrays;
047: import java.util.EventObject;
048: import javax.swing.Icon;
049: import javax.swing.JLabel;
050: import javax.swing.event.ListDataEvent;
051: import junit.framework.TestCase;
052: import org.netbeans.swing.tabcontrol.event.ComplexListDataEvent;
053: import org.netbeans.swing.tabcontrol.event.ComplexListDataListener;
054:
055: /** Some basic tests for DefaultTabDataModel, etc. Can be fleshed out into proper
056: * unit tests later.
057: *
058: * @author Tim Boudreau
059: */
060: public class DataModelTest extends TestCase implements
061: ComplexListDataListener {
062: ComplexListDataEvent lastEvent = null;
063: String lastListenerCall = null;
064:
065: public DataModelTest(String testName) {
066: super (testName);
067: }
068:
069: TabDataModel mdl = null;
070: Icon ic = new Icon() {
071: public int getIconWidth() {
072: return 16;
073: }
074:
075: public int getIconHeight() {
076: return 16;
077: }
078:
079: public void paintIcon(Component c, Graphics g, int x, int y) {
080: //do nothing
081: }
082: };
083:
084: Icon sameSizeIcon = new Icon() {
085: public int getIconWidth() {
086: return 16;
087: }
088:
089: public int getIconHeight() {
090: return 16;
091: }
092:
093: public void paintIcon(Component c, Graphics g, int x, int y) {
094: //do nothing
095: }
096: };
097:
098: Icon biggerIcon = new Icon() {
099: public int getIconWidth() {
100: return 22;
101: }
102:
103: public int getIconHeight() {
104: return 22;
105: }
106:
107: public void paintIcon(Component c, Graphics g, int x, int y) {
108: //do nothing
109: }
110: };
111:
112: public void setUp() {
113: prepareModel();
114: mdl.addComplexListDataListener(this );
115: }
116:
117: /** Weird, but this class was adapted from a standalone test written
118: * long ago and rescued from cvs history. It didn't use JUnit, and
119: * the assertTrue argument order was reversed. So in the interest of
120: * laziness... */
121: private void assertPravda(boolean val, String msg) {
122: assertTrue(msg, val);
123: }
124:
125: private void assertText(String name, int index) {
126: TabData td = mdl.getTab(index);
127: assertPravda(td.getText().equals(name), "Text at " + index
128: + " was not " + name + " it was " + td.getText());
129: }
130:
131: private void assertData(int index, TabData data) {
132: TabData other = mdl.getTab(index);
133: assertPravda(data.equals(other), "TabData at " + index
134: + " is not " + data + " it is " + other);
135: }
136:
137: private void assertListenerCall(String call) {
138: assertPravda(lastEvent != null,
139: "Last listener call should be non-null");
140: assertPravda(call.equals(lastListenerCall),
141: "Last listener call should have been " + call
142: + " but was " + lastListenerCall);
143: }
144:
145: private void assertEventIndices(int indices[]) {
146: assertPravda(lastEvent != null,
147: "Last event should have been fired but is null");
148: int[] ids = lastEvent.getIndices();
149: Arrays.sort(indices);
150: Arrays.sort(ids);
151: assertPravda(ids.length == indices.length,
152: "Indices length in last change should be "
153: + indices.length + " but is " + ids.length
154: + " expected indices: " + arrToStr(indices)
155: + " actual indices " + arrToStr(ids));
156: for (int i = 0; i < ids.length; i++) {
157: assertPravda(ids[i] == indices[i],
158: "Event indices should be " + arrToStr(indices)
159: + " but are " + arrToStr(ids));
160: }
161: }
162:
163: private void assertEventIndices(int start, int end) {
164: assertPravda(lastEvent != null,
165: "Last event should have been fired but is null");
166: assertPravda(start == lastEvent.getIndex0(),
167: "Event start index should be " + start + " but is "
168: + lastEvent.getIndex0());
169: assertPravda(end == lastEvent.getIndex1(),
170: "Event end index should be " + end + " but is "
171: + lastEvent.getIndex1());
172: }
173:
174: private void assertWidthChanged() {
175: assertPravda(lastEvent != null,
176: "Last event should have been fired but is null");
177: assertPravda(lastEvent.isTextChanged(),
178: "Last event should have been a text change event but wasn't");
179: }
180:
181: private void assertWidthNotChanged() {
182: assertPravda(lastEvent != null,
183: "Last event should have been fired but is null");
184: assertPravda(!lastEvent.isTextChanged(),
185: "Last event should not have been a text change event but was");
186: }
187:
188: /**
189: * Since this test was written in non-junit style, the order of the tests
190: * is important, so we have one junit method for all of the actual tests.
191: */
192: public void testEverything() {
193: doTestContentsValid();
194: doTestAdd();
195: doTestRemove();
196: doTestAddContiguous();
197: doTestRemoveContiguous();
198: doTestAddNonContiguous();
199: doTestRemoveNonContiguous();
200: doTestSetTab();
201: doTestSetTextNonContiguous();
202: doTestSetIconNonContiguous();
203: doTestSetIconAndTextNonContiguous();
204: System.err.println("All tests passed");
205: }
206:
207: public void doTestContentsValid() {
208: System.err.println("testContentsValid");
209: _testContentsValid();
210: }
211:
212: private void _testContentsValid() {
213: int ct = 0;
214: for (char c = 'a'; c < 'z'; c++) {
215: TabData td = mdl.getTab(ct);
216: assertPravda(td.getText().charAt(0) == c, "Name at " + ct
217: + " is not " + c + " it is " + td.getText());
218: ct++;
219: }
220: }
221:
222: public void doTestAdd() {
223: System.err.println("testAdd");
224: TabData td = new TabData(new JLabel("testAdd"), ic, "testAdd",
225: "Tip:testAdd");
226: mdl.addTabs(0, new TabData[] { td });
227: assertData(0, td);
228: }
229:
230: public void doTestRemove() {
231: System.err.println("testRemove");
232: mdl.removeTab(0);
233: assertText("a", 0);
234: }
235:
236: public void doTestAddContiguous() {
237: System.err.println("testAddContiguous");
238: int formerSize = mdl.size();
239: TabData[] td = new TabData[10];
240: for (int i = 0; i < 10; i++) {
241: String name = Integer.toString(i);
242: Component comp = new JLabel();
243: td[i] = new TabData(comp, ic, name, "Tip:" + name);
244: }
245: mdl.addTabs(10, td);
246: int expectedSize = formerSize + 10;
247: assertPravda(mdl.size() == expectedSize,
248: "Model size should be " + expectedSize
249: + " after adding 10 items, but is "
250: + mdl.size());
251: for (int i = 10; i < 20; i++) {
252: assertData(i, td[i - 10]);
253: }
254: }
255:
256: public void doTestRemoveContiguous() {
257: System.err.println("testRemoveContiguous");
258: int formerSize = mdl.size();
259: mdl.removeTabs(10, 19);
260: int expectedSize = formerSize - 10;
261: assertPravda(mdl.size() == expectedSize,
262: "Model size should be " + expectedSize
263: + " after removing 10 items, but is "
264: + mdl.size());
265: try {
266: _testContentsValid();
267: } catch (RuntimeException e) {
268: e.printStackTrace();
269: fail("After removing 10 items, contents should be original contents, but are "
270: + mdl.toString());
271: }
272: }
273:
274: TabData[] data = null;
275:
276: public void doTestAddNonContiguous() {
277: System.err.println("testAddNonContiguous");
278: int[] indices = new int[] { 3, 1, 5 };
279: data = new TabData[3];
280: for (int i = 0; i < indices.length; i++) {
281: String name = Integer.toString(indices[i]);
282: data[i] = new TabData(new JLabel(), ic, name, "Tip:" + name);
283: }
284: mdl.addTabs(indices, data);
285: assertData(3, data[0]);
286: assertData(1, data[1]);
287: assertData(5, data[2]);
288: Arrays.sort(indices);
289: assertEventIndices(indices);
290: assertListenerCall("indicesAdded");
291: }
292:
293: public void doTestRemoveNonContiguous() {
294: int[] indices = new int[] { 5, 1, 3 };
295: mdl.removeTabs(indices);
296: try {
297: _testContentsValid();
298: } catch (RuntimeException e) {
299: System.err
300: .println("After non-contiguous removal of "
301: + arrToStr(indices)
302: + ", contents should be original contents, but are "
303: + mdl.toString());
304: throw e;
305: }
306: Arrays.sort(indices);
307: assertEventIndices(indices);
308: assertListenerCall("indicesRemoved");
309: }
310:
311: public void doTestSetTab() {
312: System.err.println("testSetTab");
313: TabData former = mdl.getTab(22);
314: TabData nue = new TabData(new JLabel(), ic, "foo", "Tip:foo");
315: mdl.setTab(22, nue);
316: assertData(22, nue);
317: mdl.setTab(22, former);
318: assertListenerCall("contentsChanged");
319: assertEventIndices(22, 22);
320: //Make sure an event is not generated for changes that should not generate one
321: noEvent = true;
322: mdl.setTab(22, former);
323: mdl.setText(22, former.getText());
324: mdl.setIcon(22, ic);
325: noEvent = false;
326: }
327:
328: public void doTestSetTextNonContiguous() {
329: System.err.println("testSetTextNonContiguous");
330: String[] names = new String[5];
331: int[] indices = new int[] { 22, 11, 15, 8, 3 };
332: for (int i = 0; i < names.length; i++) {
333: names[i] = mdl.getTab(indices[i]).getText();
334: }
335: noEvent = true;
336: //should produce no event since the names haven't changed
337: mdl.setText(indices, names);
338: noEvent = false;
339: String[] s = new String[names.length];
340: for (int i = 0; i < s.length; i++) {
341: s[i] = names[i] + "modified";
342: }
343: mdl.setText(indices, s);
344: for (int i = 0; i < s.length; i++) {
345: assertText(s[i], indices[i]);
346: }
347: Arrays.sort(indices);
348: assertEventIndices(indices);
349: assertListenerCall("contentsChanged");
350: assertWidthChanged();
351: //restore the original text
352: mdl.setText(indices, names);
353: }
354:
355: public void doTestSetIcon() {
356: System.err.println("testSetIcon");
357: TabData td = mdl.getTab(20);
358: noEvent = true;
359: mdl.setIcon(20, td.getIcon());
360: noEvent = false;
361:
362: mdl.setIcon(20, sameSizeIcon);
363: assertEventIndices(20, 20);
364: assertListenerCall("contentsChanged");
365: assertPravda(td.getIcon() == sameSizeIcon,
366: "Icon was changed but same old still returned from TabData");
367: assertWidthNotChanged();
368: EventObject last = lastEvent;
369:
370: mdl.setIcon(20, biggerIcon);
371: assertWidthChanged();
372: assertPravda(last != lastEvent,
373: "Icon changed but no event fired");
374:
375: //restore the state
376: mdl.setIcon(20, ic);
377: }
378:
379: public void doTestSetIconNonContiguous() {
380: System.err.println("testSetIconNonContiguous");
381: Icon[] icons = new Icon[5];
382: int[] indices = new int[] { 22, 11, 15, 8, 3 };
383: for (int i = 0; i < icons.length; i++) {
384: icons[i] = mdl.getTab(indices[i]).getIcon();
385: }
386: noEvent = true;
387: //should produce no event since the names haven't changed
388: mdl.setIcon(indices, icons);
389: noEvent = false;
390:
391: EventObject last = lastEvent;
392:
393: Arrays.fill(icons, sameSizeIcon);
394: mdl.setIcon(indices, icons);
395: assertPravda(last != lastEvent,
396: "Icons changed but no event fired");
397: last = lastEvent;
398: assertListenerCall("contentsChanged");
399: assertWidthNotChanged();
400:
401: Arrays.fill(icons, biggerIcon);
402: icons[2] = sameSizeIcon;
403: int[] expectedIndices = new int[] { 3, 8, 22, 11 };
404:
405: mdl.setIcon(indices, icons);
406: assertPravda(last != lastEvent,
407: "Icons changed but no event fired");
408: assertListenerCall("contentsChanged");
409: assertWidthChanged();
410: assertEventIndices(expectedIndices);
411:
412: Arrays.fill(icons, ic);
413: //restore the original text
414: mdl.setIcon(indices, icons);
415: }
416:
417: public void doTestSetIconAndTextNonContiguous() {
418: System.err.println("testSetIconAndTextNonContiguous");
419: int indices[] = new int[] { 3, 10, 5 };
420: Icon[] icons = new Icon[3];
421: Arrays.fill(icons, ic);
422: String[] sts = new String[3];
423: for (int i = 0; i < 3; i++) {
424: sts[i] = mdl.getTab(i).getText();
425: }
426: //ensure expected results
427: mdl.setIconsAndText(indices, sts, icons);
428:
429: noEvent = true;
430: mdl.setIconsAndText(indices, sts, icons);
431: noEvent = false;
432: String[] realText = new String[sts.length];
433: System.arraycopy(sts, 0, realText, 0, sts.length);
434: EventObject last = lastEvent;
435:
436: icons[0] = sameSizeIcon;
437: mdl.setIconsAndText(indices, sts, icons);
438: assertPravda(last != lastEvent,
439: "Icons and text changed but no event fired");
440: assertWidthNotChanged();
441: assertEventIndices(new int[] { 3 });
442: last = lastEvent;
443:
444: icons[0] = biggerIcon;
445: sts[1] = "foobar";
446: mdl.setIconsAndText(indices, sts, icons);
447: assertPravda(last != lastEvent,
448: "Icons and text changed but no event fired");
449: assertWidthChanged();
450: assertEventIndices(new int[] { 3, 10 });
451: last = lastEvent;
452:
453: //Also test the simpler firing code for when all changed icons have changed text
454: icons[0] = ic;
455: sts[1] = "boo";
456: mdl.setIconsAndText(indices, sts, icons);
457: assertPravda(last != lastEvent,
458: "Icons and text changed but no event fired");
459: assertWidthChanged();
460: assertEventIndices(new int[] { 3, 10 });
461:
462: //restore the state
463: Arrays.fill(icons, ic);
464: mdl.setIconsAndText(indices, realText, icons);
465: }
466:
467: static String arrToStr(int[] ints) {
468: if (ints == null)
469: return "null";
470: StringBuffer out = new StringBuffer(ints.length * 3);
471: for (int i = 0; i < ints.length; i++) {
472: out.append(ints[i]);
473: if (i != ints.length - 1) {
474: out.append(",");
475: }
476: }
477: return out.toString();
478: }
479:
480: static String arrToStr(Object[] o) {
481: if (o == null)
482: return "null";
483: StringBuffer out = new StringBuffer(o.length * 3);
484: for (int i = 0; i < o.length; i++) {
485: out.append(o[i]);
486: if (i != o.length - 1) {
487: out.append(",");
488: }
489: }
490: return out.toString();
491: }
492:
493: private void prepareModel() {
494: if (mdl != null) {
495: mdl.removeComplexListDataListener(this );
496: }
497: TabData[] td = new TabData[25];
498: int ct = 0;
499: for (char c = 'a'; c < 'z'; c++) {
500: String name = new String(new char[] { c });
501: Component comp = new JLabel(name);
502: comp.setName(name);
503: td[ct] = new TabData(comp, ic, name, "tip:" + name);
504: ct++;
505: }
506: mdl = new DefaultTabDataModel(td);
507: }
508:
509: /**
510: * @param args the command line arguments
511: */
512: public static void main(String[] args) {
513: new DataModelTest("foo").run();
514: }
515:
516: public void contentsChanged(ListDataEvent e) {
517: lastListenerCall = "contentsChanged";
518: lastEvent = (ComplexListDataEvent) e;
519: if (noEvent) {
520: assertPravda(false, "No event expected but " + e
521: + " receieved");
522: }
523: }
524:
525: public void indicesAdded(ComplexListDataEvent e) {
526: lastListenerCall = "indicesAdded";
527: lastEvent = e;
528: if (noEvent) {
529: assertPravda(false, "No event expected but " + e
530: + " receieved");
531: }
532: }
533:
534: public void indicesChanged(ComplexListDataEvent e) {
535: lastListenerCall = "indicesChanged";
536: lastEvent = e;
537: if (noEvent) {
538: assertPravda(false, "No event expected but " + e
539: + " receieved");
540: }
541: }
542:
543: public void indicesRemoved(ComplexListDataEvent e) {
544: lastListenerCall = "indicesRemoved";
545: lastEvent = e;
546: if (noEvent) {
547: assertPravda(false, "No event expected but " + e
548: + " receieved");
549: }
550: }
551:
552: public void intervalAdded(ListDataEvent e) {
553: lastListenerCall = "intervalAdded";
554: assertPravda(e.getIndex0() <= e.getIndex1(),
555: "Event start index > end index");
556:
557: lastEvent = (ComplexListDataEvent) e;
558: if (noEvent) {
559: assertPravda(false, "No event expected but " + e
560: + " receieved");
561: }
562: }
563:
564: public void intervalRemoved(ListDataEvent e) {
565: lastListenerCall = "intervalRemoved";
566: lastEvent = (ComplexListDataEvent) e;
567: if (noEvent) {
568: assertPravda(false, "No event expected but " + e
569: + " receieved");
570: }
571: }
572:
573: boolean noEvent = false;
574: }
|