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