View Javadoc
1   package fr.ifremer.tutti.ui.swing.util;
2   
3   /*
4    * #%L
5    * Tutti :: UI
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2012 - 2014 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU General Public License as
13   * published by the Free Software Foundation, either version 3 of the
14   * License, or (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public
22   * License along with this program.  If not, see
23   * <http://www.gnu.org/licenses/gpl-3.0.html>.
24   * #L%
25   */
26  
27  /* ===========================================================
28   * JFreeChart : a free chart library for the Java(tm) platform
29   * ===========================================================
30   *
31   * (C) Copyright 2000-2014, by Object Refinery Limited and Contributors.
32   *
33   * Project Info:  http://www.jfree.org/jfreechart/index.html
34   *
35   * This library is free software; you can redistribute it and/or modify it
36   * under the terms of the GNU Lesser General Public License as published by
37   * the Free Software Foundation; either version 2.1 of the License, or
38   * (at your option) any later version.
39   *
40   * This library is distributed in the hope that it will be useful, but
41   * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
42   * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
43   * License for more details.
44   *
45   * You should have received a copy of the GNU Lesser General Public
46   * License along with this library; if not, write to the Free Software
47   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
48   * USA.
49   *
50   * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
51   * Other names may be trademarks of their respective owners.]
52   *
53   * -------------------------
54   * NumberTickUnitSource.java
55   * -------------------------
56   * (C) Copyright 2014, by Object Refinery Limited.
57   *
58   * Original Author:  David Gilbert (for Object Refinery Limited);
59   * Contributor(s):   -;
60   *
61   * Changes
62   * -------
63   * 18-Mar-2014 : Version 1 (DG);
64   *
65   */
66  
67  import org.jfree.chart.axis.NumberTickUnit;
68  import org.jfree.chart.axis.TickUnit;
69  import org.jfree.chart.axis.TickUnitSource;
70  
71  import java.io.Serializable;
72  import java.text.DecimalFormat;
73  import java.text.NumberFormat;
74  
75  /**
76   * TickUnitSource for the frequency chart
77   *
78   * @author Kevin Morin (Code Lutin)
79   * @since 3.10
80   */
81  public class TuttiNumberTickUnitSource implements TickUnitSource, Serializable {
82  
83      private boolean integers;
84  
85      private int power = 0;
86  
87      private int factor = 1;
88  
89      /**
90       * Creates a new instance.
91       *
92       * @param integers show integers only.
93       */
94      public TuttiNumberTickUnitSource(boolean integers) {
95  
96          this.integers = integers;
97          this.power = 0;
98          this.factor = 1;
99      }
100 
101     @Override
102     public TickUnit getLargerTickUnit(TickUnit unit) {
103         TickUnit t = getCeilingTickUnit(unit);
104         if (t.equals(unit)) {
105             next();
106             t = new NumberTickUnit(getTickSize(), getTickLabelFormat(),
107                                    getMinorTickCount());
108         }
109         return t;
110     }
111 
112     @Override
113     public TickUnit getCeilingTickUnit(TickUnit unit) {
114         return getCeilingTickUnit(unit.getSize());
115     }
116 
117     @Override
118     public TickUnit getCeilingTickUnit(double size) {
119         if (Double.isInfinite(size)) {
120             throw new IllegalArgumentException("Must be finite.");
121         }
122         this.power = (int) Math.ceil(Math.log10(size));
123         if (this.integers) {
124             power = Math.max(this.power, 0);
125         }
126         this.factor = 1;
127         boolean done = false;
128         // step down in size until the current size is too small or there are
129         // no more units
130         while (!done) {
131             done = !previous();
132             if (getTickSize() < size) {
133                 next();
134                 done = true;
135             }
136         }
137         return new NumberTickUnit(getTickSize(), getTickLabelFormat(),
138                                   getMinorTickCount());
139     }
140 
141     private boolean next() {
142         if (factor == 1) {
143             factor = 5;
144             return true;
145         }
146         if (factor == 5) {
147             if (power == 300) {
148                 return false;
149             }
150             power++;
151             factor = 1;
152             return true;
153         }
154         throw new IllegalStateException("We should never get here.");
155     }
156 
157     private boolean previous() {
158         if (factor == 1) {
159             if (this.integers && power == 0 || power == -1) {
160                 return false;
161             }
162             factor = 5;
163             power--;
164             return true;
165         }
166         if (factor == 5) {
167             factor = 1;
168             return true;
169         }
170         throw new IllegalStateException("We should never get here.");
171     }
172 
173     private double getTickSize() {
174         return this.factor * Math.pow(10.0, this.power);
175     }
176 
177     private DecimalFormat dfNeg4 = new DecimalFormat("0.0000");
178 
179     private DecimalFormat dfNeg3 = new DecimalFormat("0.000");
180 
181     private DecimalFormat dfNeg2 = new DecimalFormat("0.00");
182 
183     private DecimalFormat dfNeg1 = new DecimalFormat("0.0");
184 
185     private DecimalFormat df0 = new DecimalFormat("#,##0");
186 
187     private DecimalFormat df = new DecimalFormat("#.######E0");
188 
189     private NumberFormat getTickLabelFormat() {
190         if (power == -4) {
191             return dfNeg4;
192         }
193         if (power == -3) {
194             return dfNeg3;
195         }
196         if (power == -2) {
197             return dfNeg2;
198         }
199         if (power == -1) {
200             return dfNeg1;
201         }
202         if (power >= 0 && power <= 6) {
203             return df0;
204         }
205         return df;
206     }
207 
208     private int getMinorTickCount() {
209         return (int) (getTickSize() * (integers ? 1 : 2));
210     }
211 
212     @Override
213     public boolean equals(Object obj) {
214         if (obj == this) {
215             return true;
216         }
217         if (!(obj instanceof TuttiNumberTickUnitSource)) {
218             return false;
219         }
220         TuttiNumberTickUnitSource that = (TuttiNumberTickUnitSource) obj;
221         if (this.integers != that.integers) {
222             return false;
223         }
224         if (this.power != that.power) {
225             return false;
226         }
227         if (this.factor != that.factor) {
228             return false;
229         }
230         return true;
231     }
232 }
233