001: package com.salmonllc.html;
002:
003: /////////////////////////
004: //$Archive: /SOFIA/SourceCode/com/salmonllc/html/HtmlFractionComponent.java $
005: //$Author: Dan $
006: //$Revision: 14 $
007: //$Modtime: 10/20/03 3:48p $
008: /////////////////////////
009: import java.util.Hashtable;
010:
011: import com.salmonllc.html.events.ValueChangedEvent;
012:
013: /**
014: * Implements a two-part entry field for a decimal number.
015: */
016: public class HtmlFractionComponent extends HtmlFormComponent {
017: protected HtmlTextEdit _edit1;
018: protected double _decimalFactor = 0.0;
019: protected HtmlContainer _cont;
020: protected int _size, _scale;
021: protected HtmlDropDownList _fraction;
022: protected boolean _noPadding;
023:
024: /**
025: * FractionComponent constructor comment.
026: *
027: * @param name Name of component.
028: * @param p Page containing component.
029: * @param size number of palces for integer portion.
030: * @param scale the highest fraction proportion, e.g 64 for 1/64 .. 63/64.
031: */
032: public HtmlFractionComponent(String name, HtmlPage p, int size,
033: int scale) {
034: this (name, p, size, scale, null);
035: }
036:
037: /**
038: * FractionComponent constructor comment.
039: *
040: * @param name Name of component.
041: * @param p Page containing component.
042: * @param size number of palces for integer portion.
043: * @param scale the highest fraction proportion, e.g 64 for 1/64 .. 63/64.
044: * @param preText Component to display before the entry fields, such as a currency sign.
045: */
046: public HtmlFractionComponent(String name, HtmlPage p, int size,
047: int scale, HtmlComponent preText) {
048: super (name, p);
049: _cont = new HtmlContainer(name, p);
050: _decimalFactor = 1.0;
051: // Initialize the fields
052: if (size < 0)
053: size = 0;
054: if (scale < 0)
055: scale = 1;
056: _size = size;
057: if (preText != null)
058: _cont.add(preText);
059: _cont.add(_edit1 = new HtmlTextEdit("left", p));
060: _edit1.setGenerateNewline(false);
061: _edit1.setSize(size);
062: _edit1.setMaxLength(size);
063: _fraction = new HtmlDropDownList("right", p);
064: _cont.add(_fraction);
065: _scale = scale;
066: _fraction.addOption(" ", " ");
067: for (int i = 1; i < _scale; i++) {
068: if (i % 2 != 0) {
069: if (_scale % i == 0)
070: _fraction.addOption(i + "/" + _scale, "1/" + _scale
071: / i);
072: else
073: _fraction.addOption(i + "/" + _scale, i + "/"
074: + _scale);
075: } else {
076: if (_scale % i == 0)
077: _fraction.addOption(i + "/" + _scale, "1/" + _scale
078: / i);
079: else {
080: int j = 1;
081: while ((i / (2 * j)) % 2 == 0)
082: j++;
083: _fraction.addOption(i + "/" + _scale, (i / (2 * j))
084: + "/" + _scale / (2 * j));
085: }
086: }
087: }
088:
089: }
090:
091: public void generateHTML(java.io.PrintWriter p, int row)
092: throws Exception {
093: // It is essential to call getValue() here because there may be a ValueChanged
094: // event in the queue for this object, which needs to be removed, which getValue()
095: // does. The secondary calls to getValue() from the container will not
096: // do this because there are no events associated with them.
097: String val = getValue(row, true);
098: if (val == null) {
099: _edit1.setValue(null, row);
100: _fraction.setValue(null, row);
101: } else {
102: try {
103: Double dVal;
104: if (_dsBuff != null) {
105: if (row >= 0)
106: dVal = new Double(_dsBuff.getDouble(row,
107: _dsColNo));
108: else
109: dVal = new Double(_dsBuff.getDouble(_dsColNo));
110: } else
111: dVal = Double.valueOf(val);
112: int integerPart = dVal.intValue();
113: String sIntegerPart = Integer.toString(integerPart);
114: // Pad left side with spaces, i.e. right-justify the number.
115: StringBuffer buf = new StringBuffer();
116: if (!_noPadding) {
117: int n = _size - sIntegerPart.length();
118: while (n-- > 0)
119: buf.append(' ');
120: }
121: buf.append(sIntegerPart);
122: _edit1.setValue(buf.toString());
123: if (_scale > 0) {
124: long top = (long) ((dVal.doubleValue() - (double) integerPart) * _scale);
125: _fraction.setValue(top + "/" + _scale);
126: }
127: } catch (NumberFormatException e) {
128: // This should never happen
129: _edit1.setValue(null, row);
130: _fraction.setValue(null, row);
131: }
132: }
133: _cont.generateHTML(p, row);
134: if (_visible && _enabled)
135: p.println("");
136: }
137:
138: /**
139: * Returns the sub-component to be used for setting focus.
140: * @return com.salmonllc.html.HtmlComponent
141: */
142: public HtmlComponent getFocus() {
143: return _edit1;
144: }
145:
146: /**
147: * Returns a double representation of a passed string fraction.
148: * @return double
149: * @param sFraction java.lang.String
150: */
151: public static double getFractionValue(String sFraction) {
152: int iDivide = sFraction.indexOf('/');
153: long top = new Long(sFraction.substring(0, iDivide))
154: .longValue();
155: long bottom = new Long(sFraction.substring(iDivide + 1))
156: .longValue();
157: double value = (double) top / (double) bottom;
158: return value;
159: }
160:
161: /**
162: * Returns whether the Integer Portion is not padded to the right or not
163: * @return boolean
164: */
165: public boolean getNoPadding() {
166: return _noPadding;
167: }
168:
169: public boolean processParms(Hashtable parms, int rowNo)
170: throws Exception {
171:
172: if (!getVisible() || !getEnabled())
173: return false;
174:
175: // Determine the old value from both edit fields.
176:
177: String oldValue;
178: if (_dsBuff == null) {
179: oldValue = _edit1.getValue();
180: if ((oldValue != null) && (_scale > 0)) {
181: if (_fraction.getValue() != null) {
182: String sFraction = _fraction.getValue();
183: int iDivide = sFraction.indexOf('/');
184: long top = new Long(sFraction.substring(0, iDivide))
185: .longValue();
186: double value = (double) top / (double) _scale;
187: String sValue = "" + value;
188: sValue = sValue.substring(1);
189: oldValue += sValue;
190: }
191: }
192: } else {
193: Number n;
194: if (rowNo > -1)
195: n = (Number) _dsBuff.getAny(rowNo, _dsColNo);
196: else
197: n = (Number) _dsBuff.getAny(_dsColNo);
198: if (n == null)
199: oldValue = null;
200: else
201: oldValue = "" + n.doubleValue();
202: }
203:
204: // Determine the new value from both edit fields.
205:
206: String newValue;
207: String name1 = _edit1.getFullName();
208: if (rowNo > -1)
209: name1 += "_" + rowNo;
210: String val[] = (String[]) parms.get(name1);
211: if (val != null) {
212: newValue = val[0].trim();
213: if (newValue.equals(""))
214: newValue = null;
215: } else
216: newValue = null;
217:
218: if (_scale > 0) {
219: String name2 = _fraction.getFullName();
220: if (rowNo > -1)
221: name2 += "_" + rowNo;
222: val = (String[]) parms.get(name2);
223: if (val != null) {
224: String s = val[0].trim();
225: if (!s.equals("")) {
226: if (newValue == null)
227: newValue = "";
228: int iDivide = s.indexOf('/');
229: long top = new Long(s.substring(0, iDivide))
230: .longValue();
231: double value = (double) top / (double) _scale;
232: String sValue = "" + value;
233: sValue = sValue.substring(1);
234: newValue += sValue;
235: }
236: }
237: }
238:
239: // Compare old and new values and possibly create a ValueChangedEvent.
240: if (!valuesEqual(oldValue, newValue)) {
241: ValueChangedEvent e = new ValueChangedEvent(getPage(),
242: this , getName(), getFullName(), oldValue, newValue,
243: rowNo, _dsColNo, _dsBuff);
244: addEvent(e);
245: }
246: return false;
247: }
248:
249: /**
250: * This method will clear all pending events from the event queue for this component.
251: */
252: public void reset() {
253: super .reset();
254: _cont.reset();
255: }
256:
257: /**
258: * Specifies the Style Class to be used for the Component.
259: * Creation date: (7/19/01 8:41:20 AM)
260: * @param sClass java.lang.String A name of a class in Html to be used by this component
261: */
262: public void setClassName(String sClass) {
263: super .setClassName(sClass);
264: _edit1.setClassName(sClass);
265: _fraction.setClassName(sClass);
266: }
267:
268: /**
269: * Sets the font end tag for disabled mode.
270: * @param tag java.lang.String
271: */
272: public void setDisabledFontEndTag(String tag) {
273: _edit1.setDisabledFontEndTag(tag);
274: _fraction.setDisabledFontEndTag(tag);
275: }
276:
277: /**
278: * Sets the font tag for disabled mode.
279: * @param tag java.lang.String
280: */
281: public void setDisabledFontStartTag(String tag) {
282: _edit1.setDisabledFontStartTag(tag);
283: _fraction.setDisabledFontStartTag(tag);
284: }
285:
286: /**
287: * Enables or disables the ability of this component to respond to user input.
288: * @param editable boolean
289: */
290: public void setEnabled(boolean enabled) {
291: super .setEnabled(enabled);
292: _cont.setEnabled(enabled);
293: }
294:
295: /**
296: * Specify whether to pad integer portion to the right.
297: * @param bNoPadding boolean
298: */
299: public void setNoPadding(boolean bNoPadding) {
300: _noPadding = bNoPadding;
301: }
302:
303: /**
304: * Specifies the parent component for this Component.
305: * Creation date: (7/19/01 8:41:20 AM)
306: * @param sClass java.lang.String A name of a class in Html to be used by this component
307: */
308: public void setParent(HtmlComponent parent) {
309: super .setParent(parent);
310: // This is necessary for the name to be generated correctly, else the leading
311: // sequence of parent names will be lost.
312: _cont.setParent(parent);
313: }
314:
315: /**
316: * @returns the tab index html attribute
317: */
318: public int getTabIndex() {
319: return _edit1.getTabIndex();
320: }
321:
322: /**
323: * @param sets the access key html attribute
324: */
325: public String getAccessKey() {
326: return _edit1.getAccessKey();
327: }
328:
329: /**
330: * @param sets the access key html attribute
331: */
332: public void setAccessKey(String val) {
333: _edit1.setAccessKey(val);
334: }
335:
336: /**
337: * @param sets the tab index html attribute. You can also pass TAB_INDEX_DEFAULT to use the default tab index for the component or TAB_INDEX_NONE to keep this component from being tabbed to
338: */
339: public void setTabIndex(int val) {
340: _edit1.setTabIndex(val);
341: _fraction.setTabIndex(val + 1);
342: }
343: }
|