View Javadoc

1   /*
2    * Copyright (c) 2003-2008 by Cosylab d. d.
3    *
4    * This file is part of CosyBeans-Common.
5    *
6    * CosyBeans-Common is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * CosyBeans-Common is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with CosyBeans-Common.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package com.cosylab.gui.components.wheelswitch;
21  
22  
23  
24  /**
25   * Extension of the abstract wheelswitch formatter for formatting numeric strings representing
26   * angular values in format of ddddmmss, where d are angular degrees, m are angular minutes in 
27   * the range of 0-59 and s are angular seconds also in the range of 0-59.
28   * The number of digits representing m and s is fixed to 2 per m and 2 per s, while d are assumed 
29   * to take all the remaining digits up front.
30   * In the format string passed to the formatter all the decimal digits are ingored and only the
31   * leading (integer) digits are counted when determining the right formatted value string.
32   * If the format string does not contain enough integer digits to display the whole number, new digits
33   * are automatically added to the value string.
34   *
35   * @author <a href="mailto:jernej.kamenik@cosylab.com">Jernej Kamenik</a>
36   * @version $id$
37   */
38  public class RadialWheelswitchFormatter extends AbstractWheelswitchFormatter
39  {
40  	/**
41  	 * Constructs the PlainWheelswitchFormatter and sets the format  string.
42  	 *
43  	 * @param newFormatString
44  	 *
45  	 * @see #setFormat(String)
46  	 */
47  	public RadialWheelswitchFormatter(String newFormatString)
48  	{
49  		super(newFormatString);
50  	}
51  
52  	/**
53  	 * Constructs the PlainWheelswitchFormatter with no format string.
54  	 *
55  	 * @see #setFormat(String)
56  	 */
57  	public RadialWheelswitchFormatter()
58  	{
59  		super();
60  	}
61  
62  	/* (non-Javadoc)
63       * @see com.cosylab.gui.components.wheelswitch.AbstractWheelswitchFormatter#setFormat(java.lang.String)
64       */
65      public void setFormat(String newFormatString)
66              throws IllegalArgumentException {
67          if (newFormatString!=null && newFormatString.indexOf('E')>-1) throw new IllegalArgumentException("Exponential format not supported by this formatter.");
68          super.setFormat(newFormatString);
69      }
70  
71      private String parseString(String newValueString, boolean pad) {
72          double newValue = Double.parseDouble(newValueString);
73          
74  		//decreasing of digits has to be handled differently from increasing
75  		boolean reverse = false;
76  		if (Math.abs(value)>Math.abs(newValue)) {
77  		    reverse = true;
78  		}
79  		
80  		//determine the sign and trim the string if necessary
81  		int sign = 0;
82  		if (formatString.startsWith("+")) {
83  		    sign = 1;
84  		}
85  		if (newValueString.startsWith("-")) {
86  		    sign = -1;
87  		    newValueString = newValueString.substring(1);
88  		}
89  		if (newValueString.startsWith("+")) {
90  		    newValueString = newValueString.substring(1);
91  		}
92  		
93  
94  		//the effective string length is up to the decimal digits
95  		int decStrLength = newValueString.length();
96  		int dotIndex = newValueString.indexOf('.');
97  		if (dotIndex>-1) decStrLength = dotIndex;
98  		
99  		//determine secs value string
100 		String secString = "0";
101 		if (decStrLength==1) secString = newValueString;
102 		if (decStrLength>1) secString = newValueString.substring(decStrLength-2);
103 		//determine mins value string
104 		String minString = "0";
105 		if (decStrLength==3) minString = newValueString.substring(0,decStrLength-2);
106 		if (decStrLength>3) minString = newValueString.substring(decStrLength-4,decStrLength-2);
107 		//determine degs value string
108 		String degString = "0";
109 		if (decStrLength>4) degString = newValueString.substring(0,decStrLength-4);
110 		
111 		//determine secs value
112 		double secValue = Double.parseDouble(secString);
113 		//determine secs overflow
114 		int secOff = (int)secValue/60;
115 		//correct the overflow
116 		if (secOff>=1) {
117 		    //if going backwards, there really is no overflow
118 		    //but the value has to be reduced by the difference between
119 		    //the decimal and the angular system
120 		    if (reverse) {
121 		        secValue -= 40;
122 		        secOff = 0;
123 		    }
124 		    else secValue %= 60;
125 		}
126 		//create new secs string (integer valued)
127 		secString = String.valueOf(secValue);
128 		//complete if too short
129 		//the effective string length is up to the decimal digits
130 		decStrLength = secString.length();
131 		dotIndex = secString.indexOf('.');
132 		if (dotIndex>-1) decStrLength = dotIndex;
133 		while (decStrLength<2) {
134 		    secString = "0"+secString;
135 		    decStrLength++;
136 		}
137 		
138 		//the same for mins only account for the secs overflow
139 		int minValue = Integer.parseInt(minString)+secOff;
140 		int minOff = minValue/60;
141 		if (minOff>0) {
142 		    if (reverse) {
143 		        minValue -= 40;
144 		        minOff = 0;
145 		    }
146 		    else minValue %= 60;
147 		}
148 		minString = String.valueOf((int)minValue);
149 		while (minString.length()<2) minString = "0"+minString;
150 		
151 		//the same for degs
152 		double degValue = Double.parseDouble(degString)+minOff;
153 		degString = String.valueOf((int)degValue);
154 		
155 		//assebmle the complete string
156 		newValueString = degString+minString+secString;		
157 				
158 		if (pad) newValueString = padString(newValueString);
159 		
160 		//add back the sign specified by the value or the format
161 		if (sign>0) newValueString = "+" + newValueString;
162 		if (sign<0) newValueString = "-" + newValueString;
163 
164 		return newValueString;
165     }
166     
167 	/*
168 	 * correct string to adhere to format
169      * @param newValueString
170      */
171     private String padString(String newValueString) {
172 		//first determine the number of digits specified by the format
173         int numFormatInteger = formatString.indexOf('.');
174 		int numFormatDecimal = 0;
175 		if (numFormatInteger<0) numFormatInteger = formatString.length();
176 		else numFormatDecimal = formatString.length()-numFormatInteger-1;
177 		if (formatString.startsWith("+")) {
178 			numFormatInteger -= 1;
179 		}
180 
181 		//then determine the number of actual digits currently in the string
182 		int numInteger = newValueString.indexOf('.');
183 		int numDecimal = 0;
184 		if (numInteger<0) numInteger = newValueString.length();
185 		else numDecimal = newValueString.length()-numInteger-1;
186 		
187 		//pad too short strings in front
188 		while (numInteger<numFormatInteger) {
189 		    newValueString = "0"+newValueString;
190 		    numInteger++;
191 		}
192 		//trim too long sring of the front zeros
193 		while (numInteger>numFormatInteger && newValueString.startsWith("0")) {
194 		    newValueString = newValueString.substring(1);
195 		    numInteger--;
196 		}
197 		
198 		//pad too short decimals at the back
199 		if (formatString.indexOf('.')>-1 && newValueString.indexOf('.')<0) newValueString += ".";
200 		while (numDecimal<numFormatDecimal) {
201 		    newValueString += "0";
202 		    numDecimal++;
203 		}
204 		//trim too long decimals of the last digits
205 		//all the rounding should already have been done beforehand, so one should always just trim zeros here
206 		while (numDecimal>numFormatDecimal) {
207 		    newValueString = newValueString.substring(0,newValueString.length()-1);
208 		    numDecimal--;
209 		}
210 
211 		return newValueString;
212     }
213 
214     protected void internalSetString(String newValueString) {
215 		//System.out.println("value recieved = "+newValueString);
216 
217 		//first parse the new value string only to determine the new value
218 		//no padding of digits neccessary
219 		newValueString = parseString(newValueString,false);
220 		//System.out.println("value stored = "+newValueString);
221 		value = Double.parseDouble(newValueString);
222 		
223 		//then parse again after triming unneccessary decimal digits
224 		newValueString = formatter.sprintf(value);
225 		//this is neccessary when no decimals are present
226 		while (newValueString.startsWith(" ")) newValueString = newValueString.substring(1);
227 		//System.out.println("value trimed = "+newValueString);
228 		//this time make proper padding of zero digits
229 		valueString = parseString(newValueString,true);		
230 		//System.out.println("value string = "+valueString);
231 	}
232 }
233 
234 /* __oOo__ */