001    /* ===========================================================
002     * JFreeChart : a free chart library for the Java(tm) platform
003     * ===========================================================
004     *
005     * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006     *
007     * Project Info:  http://www.jfree.org/jfreechart/index.html
008     *
009     * This library is free software; you can redistribute it and/or modify it 
010     * under the terms of the GNU Lesser General Public License as published by 
011     * the Free Software Foundation; either version 2.1 of the License, or 
012     * (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but 
015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
017     * License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this library; if not, write to the Free Software
021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
022     * USA.  
023     *
024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
025     * in the United States and other countries.]
026     *
027     * --------------
028     * TickUnits.java
029     * --------------
030     * (C) Copyright 2001-2005, by Object Refinery Limited.
031     *
032     * Original Author:  David Gilbert (for Object Refinery Limited);
033     * Contributor(s):   -;
034     *
035     * $Id: TickUnits.java,v 1.4.2.2 2005/10/25 20:37:34 mungady Exp $
036     *
037     * Changes
038     * -------
039     * 23-Nov-2001 : Version 1 (DG);
040     * 18-Feb-2002 : Fixed bug in getNearestTickUnit (thanks to Mario Inchiosa for 
041     *               reporting this, SourceForge bug id 518073) (DG);
042     * 25-Feb-2002 : Moved createStandardTickUnits() method from NumberAxis, and 
043     *               added createIntegerTickUnits() method (DG);
044     * 01-May-2002 : Updated for changes to the TickUnit class (DG);
045     * 18-Sep-2002 : Added standardTickUnit methods which take a Locale 
046     *               instance (AS);
047     * 26-Sep-2002 : Fixed errors reported by Checkstyle (DG);
048     * 08-Nov-2002 : Moved to new package com.jrefinery.chart.axis (DG);
049     * 26-Mar-2003 : Implemented Serializable (DG);
050     * 13-Aug-2003 : Implemented Cloneable (DG);
051     * 23-Sep-2003 : Implemented TickUnitSource interface (DG);
052     * 03-Dec-2003 : Adding null values now throws exceptions (TM);
053     * 11-Jan-2005 : Removed deprecated methods in preparation for 1.0.0 
054     *               release (DG);
055     * 
056     */
057    
058    package org.jfree.chart.axis;
059    
060    import java.io.Serializable;
061    import java.text.NumberFormat;
062    import java.util.ArrayList;
063    import java.util.Collections;
064    import java.util.List;
065    
066    /**
067     * A collection of tick units, used by the {@link DateAxis} and 
068     * {@link NumberAxis} classes.
069     */
070    public class TickUnits implements TickUnitSource, Cloneable, Serializable {
071    
072        /** For serialization. */
073        private static final long serialVersionUID = 1134174035901467545L;
074        
075        /** Storage for the tick units. */
076        private List tickUnits;
077    
078        /**
079         * Constructs a new collection of tick units.
080         */
081        public TickUnits() {
082            this.tickUnits = new ArrayList();
083        }
084    
085        /**
086         * Adds a tick unit to the collection.
087         * <P>
088         * The tick units are maintained in ascending order.
089         *
090         * @param unit  the tick unit to add.
091         */
092        public void add(TickUnit unit) {
093    
094            if (unit == null) {
095                throw new NullPointerException("Null 'unit' argument.");
096            }
097            this.tickUnits.add(unit);
098            Collections.sort(this.tickUnits);
099    
100        }
101    
102        /**
103         * Returns the number of tick units in this collection.
104         * <P>
105         * This method is required for the XML writer.
106         *
107         * @return The number of units in this collection.
108         */
109        public int size() {
110            return this.tickUnits.size();
111        }
112    
113        /**
114         * Returns the tickunit on the given position.
115         * <P>
116         * This method is required for the XML writer.
117         *
118         * @param pos the position in the list.
119         * 
120         * @return The tickunit.
121         */
122        public TickUnit get(int pos) {
123            return (TickUnit) this.tickUnits.get(pos);
124        }
125    
126        /**
127         * Returns a tick unit that is larger than the supplied unit.
128         *
129         * @param unit   the unit.
130         *
131         * @return A tick unit that is larger than the supplied unit.
132         */
133        public TickUnit getLargerTickUnit(TickUnit unit) {
134    
135            int index = Collections.binarySearch(this.tickUnits, unit);
136            if (index >= 0) {
137                index = index + 1;
138            }
139            else {
140                index = -index;
141            }
142    
143            return (TickUnit) this.tickUnits.get(
144                Math.min(index, this.tickUnits.size() - 1)
145            );
146    
147        }
148    
149        /**
150         * Returns the tick unit in the collection that is greater than or equal
151         * to (in size) the specified unit.
152         *
153         * @param unit  the unit.
154         *
155         * @return A unit from the collection.
156         */
157        public TickUnit getCeilingTickUnit(TickUnit unit) {
158    
159            int index = Collections.binarySearch(this.tickUnits, unit);
160            if (index >= 0) {
161                return (TickUnit) this.tickUnits.get(index);
162            }
163            else {
164                index = -(index + 1);
165                return (TickUnit) this.tickUnits.get(
166                    Math.min(index, this.tickUnits.size() - 1)
167                );
168            }
169    
170        }
171    
172        /**
173         * Returns the tick unit in the collection that is greater than or equal
174         * to the specified size.
175         *
176         * @param size  the size.
177         *
178         * @return A unit from the collection.
179         */
180        public TickUnit getCeilingTickUnit(double size) {
181            return getCeilingTickUnit(new NumberTickUnit(size, 
182                    NumberFormat.getInstance()));
183        }
184    
185        /**
186         * Returns a clone of the collection.
187         *
188         * @return A clone.
189         *
190         * @throws CloneNotSupportedException if an item in the collection does not 
191         *         support cloning.
192         */
193        public Object clone() throws CloneNotSupportedException {
194            TickUnits clone = (TickUnits) super.clone();
195            clone.tickUnits = new java.util.ArrayList(this.tickUnits);
196            return clone;
197        }
198    
199        /**
200         * Tests an object for equality with this instance.
201         *
202         * @param object  the object to test.
203         *
204         * @return A boolean.
205         */
206        public boolean equals(Object object) {
207            if (object == null) {
208                return false;
209            }
210            if (object == this) {
211                return true;
212            }
213            if (object instanceof TickUnits) {
214                TickUnits tu = (TickUnits) object;
215                return tu.tickUnits.equals(this.tickUnits);
216            }
217            return false;
218        }
219    
220    }