/* * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing.text; import java.io.Serializable; /** {@collect.stats} * A TabSet is comprised of many TabStops. It offers methods for locating the * closest TabStop to a given position and finding all the potential TabStops. * It is also immutable. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @author Scott Violet */ public class TabSet implements Serializable { /** {@collect.stats} TabStops this TabSet contains. */ private TabStop[] tabs; /** {@collect.stats} * Since this class is immutable the hash code could be * calculated once. MAX_VALUE means that it was not initialized * yet. Hash code shouldn't has MAX_VALUE value. */ private int hashCode = Integer.MAX_VALUE; /** {@collect.stats} * Creates and returns an instance of TabSet. The array of Tabs * passed in must be sorted in ascending order. */ public TabSet(TabStop[] tabs) { // PENDING(sky): If this becomes a problem, make it sort. if(tabs != null) { int tabCount = tabs.length; this.tabs = new TabStop[tabCount]; System.arraycopy(tabs, 0, this.tabs, 0, tabCount); } else this.tabs = null; } /** {@collect.stats} * Returns the number of Tab instances the receiver contains. */ public int getTabCount() { return (tabs == null) ? 0 : tabs.length; } /** {@collect.stats} * Returns the TabStop at index <code>index</code>. This will throw an * IllegalArgumentException if <code>index</code> is outside the range * of tabs. */ public TabStop getTab(int index) { int numTabs = getTabCount(); if(index < 0 || index >= numTabs) throw new IllegalArgumentException(index + " is outside the range of tabs"); return tabs[index]; } /** {@collect.stats} * Returns the Tab instance after <code>location</code>. This will * return null if there are no tabs after <code>location</code>. */ public TabStop getTabAfter(float location) { int index = getTabIndexAfter(location); return (index == -1) ? null : tabs[index]; } /** {@collect.stats} * @return the index of the TabStop <code>tab</code>, or -1 if * <code>tab</code> is not contained in the receiver. */ public int getTabIndex(TabStop tab) { for(int counter = getTabCount() - 1; counter >= 0; counter--) // should this use .equals? if(getTab(counter) == tab) return counter; return -1; } /** {@collect.stats} * Returns the index of the Tab to be used after <code>location</code>. * This will return -1 if there are no tabs after <code>location</code>. */ public int getTabIndexAfter(float location) { int current, min, max; min = 0; max = getTabCount(); while(min != max) { current = (max - min) / 2 + min; if(location > tabs[current].getPosition()) { if(min == current) min = max; else min = current; } else { if(current == 0 || location > tabs[current - 1].getPosition()) return current; max = current; } } // no tabs after the passed in location. return -1; } /** {@collect.stats} * Indicates whether this <code>TabSet</code> is equal to another one. * @param o the <code>TabSet</code> instance which this instance * should be compared to. * @return <code>true</code> if <code>o</code> is the instance of * <code>TabSet</code>, has the same number of <code>TabStop</code>s * and they are all equal, <code>false</code> otherwise. * * @since 1.5 */ public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof TabSet) { TabSet ts = (TabSet) o; int count = getTabCount(); if (ts.getTabCount() != count) { return false; } for (int i=0; i < count; i++) { TabStop ts1 = getTab(i); TabStop ts2 = ts.getTab(i); if ((ts1 == null && ts2 != null) || (ts1 != null && !getTab(i).equals(ts.getTab(i)))) { return false; } } return true; } return false; } /** {@collect.stats} * Returns a hashcode for this set of TabStops. * @return a hashcode value for this set of TabStops. * * @since 1.5 */ public int hashCode() { if (hashCode == Integer.MAX_VALUE) { hashCode = 0; int len = getTabCount(); for (int i = 0; i < len; i++) { TabStop ts = getTab(i); hashCode ^= ts != null ? getTab(i).hashCode() : 0; } if (hashCode == Integer.MAX_VALUE) { hashCode -= 1; } } return hashCode; } /** {@collect.stats} * Returns the string representation of the set of tabs. */ public String toString() { int tabCount = getTabCount(); StringBuffer buffer = new StringBuffer("[ "); for(int counter = 0; counter < tabCount; counter++) { if(counter > 0) buffer.append(" - "); buffer.append(getTab(counter).toString()); } buffer.append(" ]"); return buffer.toString(); } }