1 /* 2 * Copyright (c) 1998, 2010, 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.text; 27 28 import java.io.Serializable; 29 30 /** 31 * A TabSet is comprised of many TabStops. It offers methods for locating the 32 * closest TabStop to a given position and finding all the potential TabStops. 33 * It is also immutable. 34 * <p> 35 * <strong>Warning:</strong> 36 * Serialized objects of this class will not be compatible with 37 * future Swing releases. The current serialization support is 38 * appropriate for short term storage or RMI between applications running 39 * the same version of Swing. As of 1.4, support for long term storage 40 * of all JavaBeans™ 41 * has been added to the <code>java.beans</code> package. 42 * Please see {@link java.beans.XMLEncoder}. 43 * 44 * @author Scott Violet 45 */ 46 public class TabSet implements Serializable 47 { 48 /** TabStops this TabSet contains. */ 49 private TabStop[] tabs; 50 /** 51 * Since this class is immutable the hash code could be 52 * calculated once. MAX_VALUE means that it was not initialized 53 * yet. Hash code shouldn't has MAX_VALUE value. 54 */ 55 private int hashCode = Integer.MAX_VALUE; 56 57 /** 58 * Creates and returns an instance of TabSet. The array of Tabs 59 * passed in must be sorted in ascending order. 60 */ 61 public TabSet(TabStop[] tabs) { 62 // PENDING(sky): If this becomes a problem, make it sort. 63 if(tabs != null) { 64 int tabCount = tabs.length; 65 66 this.tabs = new TabStop[tabCount]; 67 System.arraycopy(tabs, 0, this.tabs, 0, tabCount); 68 } 69 else 70 this.tabs = null; 71 } 72 73 /** 74 * Returns the number of Tab instances the receiver contains. 75 */ 76 public int getTabCount() { 77 return (tabs == null) ? 0 : tabs.length; 78 } 79 80 /** 81 * Returns the TabStop at index <code>index</code>. This will throw an 82 * IllegalArgumentException if <code>index</code> is outside the range 83 * of tabs. 84 */ 85 public TabStop getTab(int index) { 86 int numTabs = getTabCount(); 87 88 if(index < 0 || index >= numTabs) 89 throw new IllegalArgumentException(index + 90 " is outside the range of tabs"); 91 return tabs[index]; 92 } 93 94 /** 95 * Returns the Tab instance after <code>location</code>. This will 96 * return null if there are no tabs after <code>location</code>. 97 */ 98 public TabStop getTabAfter(float location) { 99 int index = getTabIndexAfter(location); 100 101 return (index == -1) ? null : tabs[index]; 102 } 103 104 /** 105 * @return the index of the TabStop <code>tab</code>, or -1 if 106 * <code>tab</code> is not contained in the receiver. 107 */ 108 public int getTabIndex(TabStop tab) { 109 for(int counter = getTabCount() - 1; counter >= 0; counter--) 110 // should this use .equals? 111 if(getTab(counter) == tab) 112 return counter; 113 return -1; 114 } 115 116 /** 117 * Returns the index of the Tab to be used after <code>location</code>. 118 * This will return -1 if there are no tabs after <code>location</code>. 119 */ 120 public int getTabIndexAfter(float location) { 121 int current, min, max; 122 123 min = 0; 124 max = getTabCount(); 125 while(min != max) { 126 current = (max - min) / 2 + min; 127 if(location > tabs[current].getPosition()) { 128 if(min == current) 129 min = max; 130 else 131 min = current; 132 } 133 else { 134 if(current == 0 || location > tabs[current - 1].getPosition()) 135 return current; 136 max = current; 137 } 138 } 139 // no tabs after the passed in location. 140 return -1; 141 } 142 143 /** 144 * Indicates whether this <code>TabSet</code> is equal to another one. 145 * @param o the <code>TabSet</code> instance which this instance 146 * should be compared to. 147 * @return <code>true</code> if <code>o</code> is the instance of 148 * <code>TabSet</code>, has the same number of <code>TabStop</code>s 149 * and they are all equal, <code>false</code> otherwise. 150 * 151 * @since 1.5 152 */ 153 public boolean equals(Object o) { 154 if (o == this) { 155 return true; 156 } 157 if (o instanceof TabSet) { 158 TabSet ts = (TabSet) o; 159 int count = getTabCount(); 160 if (ts.getTabCount() != count) { 161 return false; 162 } 163 for (int i=0; i < count; i++) { 164 TabStop ts1 = getTab(i); 165 TabStop ts2 = ts.getTab(i); 166 if ((ts1 == null && ts2 != null) || 167 (ts1 != null && !getTab(i).equals(ts.getTab(i)))) { 168 return false; 169 } 170 } 171 return true; 172 } 173 return false; 174 } 175 176 /** 177 * Returns a hashcode for this set of TabStops. 178 * @return a hashcode value for this set of TabStops. 179 * 180 * @since 1.5 181 */ 182 public int hashCode() { 183 if (hashCode == Integer.MAX_VALUE) { 184 hashCode = 0; 185 int len = getTabCount(); 186 for (int i = 0; i < len; i++) { 187 TabStop ts = getTab(i); 188 hashCode ^= ts != null ? getTab(i).hashCode() : 0; 189 } 190 if (hashCode == Integer.MAX_VALUE) { 191 hashCode -= 1; 192 } 193 } 194 return hashCode; 195 } 196 197 /** 198 * Returns the string representation of the set of tabs. 199 */ 200 public String toString() { 201 int tabCount = getTabCount(); 202 StringBuilder buffer = new StringBuilder("[ "); 203 204 for(int counter = 0; counter < tabCount; counter++) { 205 if(counter > 0) 206 buffer.append(" - "); 207 buffer.append(getTab(counter).toString()); 208 } 209 buffer.append(" ]"); 210 return buffer.toString(); 211 } 212 }