001: package com.salmonllc.html;
002:
003: /////////////////////////
004: //$Archive: /SOFIA/SourceCode/com/salmonllc/html/HtmlDecimalComponent.java $
005: //$Author: Dan $
006: //$Revision: 24 $
007: //$Modtime: 3/17/04 2:08p $
008: /////////////////////////
009:
010: import java.text.DecimalFormat;
011: import java.util.Hashtable;
012:
013: import com.salmonllc.html.events.ValueChangedEvent;
014:
015: /**
016: * Implements a two-part entry field for a decimal number.
017: */
018: public class HtmlDecimalComponent extends HtmlFormComponent {
019: protected HtmlTextEdit _edit1;
020: protected HtmlTextEdit _edit2;
021: protected int _precision;
022: protected int _scale;
023: protected double _decimalFactor = 0.0;
024: protected DecimalFormat _scaleFormat;
025: protected HtmlText _dot;
026: protected DecimalFormat _valueFormat;
027: protected HtmlContainer _cont;
028:
029: /** addColumn flags parameter: Field is required. */
030: public static final int NO_PADDING = 1 << 0;
031:
032: protected int _flag = NO_PADDING;
033:
034: /**
035: * DecimalComponent constructor comment.
036: *
037: * @param name Name of component.
038: * @param p Page containing component.
039: * @param precision Total number of digits.
040: * @param scale Number of decimal places (digits to right of decimal point).
041: */
042: public HtmlDecimalComponent(String name, HtmlPage p, int precision,
043: int scale) {
044: this (name, p, precision, scale, null);
045: }
046:
047: /**
048: * DecimalComponent constructor comment.
049: *
050: * @param name Name of component.
051: * @param p Page containing component.
052: * @param precision Total number of digits.
053: * @param scale Number of decimal places (digits to right of decimal point).
054: * @param preText Component to display before the entry fields, such as a currency sign.
055: */
056: public HtmlDecimalComponent(String name, HtmlPage p, int precision,
057: int scale, HtmlComponent preText) {
058: super (name, p);
059: _cont = new HtmlContainer(name, p);
060: // Consistency check
061: if (precision < 0)
062: precision = 0;
063: else if (scale < 0)
064: scale = 0;
065: if (precision < scale)
066: scale = precision;
067: _precision = precision;
068: _scale = scale;
069: _decimalFactor = 1.0;
070: int n = scale;
071: while (n-- > 0)
072: _decimalFactor = _decimalFactor / 10.0;
073: // Initialize the fields
074: if (preText != null)
075: _cont.add(preText);
076: _cont.add(_edit1 = new HtmlTextEdit("left", p));
077: _edit1.setGenerateNewline(false);
078: _edit1.setSize(precision - scale);
079: _edit1.setMaxLength(precision - scale);
080: String valueFormatPattern;
081: _edit2 = new HtmlTextEdit("right", p);
082: _edit2.setGenerateNewline(false);
083: if (scale > 0) {
084: _cont.add(_dot = new HtmlText(".", HtmlText.FONT_EMPHASIS,
085: p));
086: _cont.add(_edit2);
087: _edit2.setSize(scale);
088: _edit2.setMaxLength(scale);
089: String s = "";
090: n = scale;
091: while (n-- > 0)
092: s += '0';
093: _scaleFormat = new DecimalFormat(s);
094: valueFormatPattern = "#0." + s;
095: } else {
096: _scaleFormat = new DecimalFormat();
097: valueFormatPattern = "#0";
098: }
099: _valueFormat = new DecimalFormat(valueFormatPattern);
100: }
101:
102: /**
103: * DecimalComponent constructor comment.
104: *
105: * @param name Name of component.
106: * @param p Page containing component.
107: * @param precision Total number of digits.
108: * @param scale Number of decimal places (digits to right of decimal point).
109: * @param preText Component to display before the entry fields, such as a currency sign.
110: */
111: public HtmlDecimalComponent(String name, HtmlPage p, int precision,
112: int scale, HtmlComponent preText, int flag) {
113: this (name, p, precision, scale, preText);
114: _flag = flag;
115: }
116:
117: public void generateHTML(java.io.PrintWriter p, int row)
118: throws Exception {
119: // It is essential to call getValue() here because there may be a ValueChanged
120: // event in the queue for this object, which needs to be removed, which getValue()
121: // does. The secondary calls to getValue() from the container will not
122: // do this because there are no events associated with them.
123: String val = getValue(row, true);
124: if (val == null) {
125: _edit1.setValue(null, row);
126: _edit2.setValue(null, row);
127: } else {
128: try {
129: Double dVal;
130: if (_dsBuff != null) {
131: if (row >= 0)
132: dVal = new Double(_dsBuff.getDouble(row,
133: _dsColNo));
134: else
135: dVal = new Double(_dsBuff.getDouble(_dsColNo));
136: } else
137: dVal = Double.valueOf(val);
138: int integerPart = dVal.intValue();
139: String sIntegerPart = Integer.toString(integerPart);
140: // Pad left side with spaces, i.e. right-justify the number.
141: StringBuffer buf = new StringBuffer();
142: if ((_flag & NO_PADDING) == 0) {
143: int n = _precision - _scale - sIntegerPart.length();
144: while (n-- > 0)
145: buf.append(' ');
146: }
147:
148: buf.append(sIntegerPart);
149: _edit1.setValue(buf.toString());
150: if (_scale > 0) {
151: double fractionalPart = (dVal.doubleValue() - (double) integerPart)
152: / _decimalFactor;
153: if (fractionalPart < 0) {
154: if (integerPart == 0) {
155: _edit1.setValue("-0");
156: }
157: fractionalPart = -fractionalPart;
158: }
159: _edit2.setValue(_scaleFormat.format((int) Math
160: .round(fractionalPart)), row);
161: }
162: } catch (NumberFormatException e) {
163: // This should never happen
164: _edit1.setValue(null, row);
165: _edit2.setValue(null, row);
166: }
167: }
168: _cont.generateHTML(p, row);
169: if (_visible && _enabled)
170: p.println("");
171: }
172:
173: /**
174: * Returns the sub-component to be used for setting focus.
175: * @return com.salmonllc.html.HtmlComponent
176: */
177: public HtmlComponent getFocus() {
178: return _edit1;
179: }
180:
181: /**
182: * Returns whether the Integer Portion is not padded to the right or not
183: * @return boolean
184: */
185: public boolean getNoPadding() {
186: if (_flag == NO_PADDING)
187: return true;
188: else
189: return false;
190: }
191:
192: public boolean processParms(Hashtable parms, int rowNo)
193: throws Exception {
194:
195: if (!getVisible() || !getEnabled())
196: return false;
197:
198: // Determine the old value from both edit fields.
199:
200: String oldValue;
201: if (_dsBuff == null) {
202: oldValue = _edit1.getValue();
203: if ((oldValue != null) && (_scale > 0)) {
204: if (_edit2.getValue() != null)
205: oldValue += "." + _edit2.getValue();
206: }
207: } else {
208: Number n;
209: if (rowNo > -1)
210: n = (Number) _dsBuff.getAny(rowNo, _dsColNo);
211: else
212: n = (Number) _dsBuff.getAny(_dsColNo);
213: if (n == null)
214: oldValue = null;
215: else
216: oldValue = _valueFormat.format(n.doubleValue());
217: }
218:
219: // Determine the new value from both edit fields.
220:
221: String newValue;
222: String name1 = _edit1.getFullName();
223: if (rowNo > -1)
224: name1 += "_" + rowNo;
225: String val[] = (String[]) parms.get(name1);
226: if (val != null) {
227: newValue = val[0].trim();
228: if (newValue.equals(""))
229: newValue = null;
230: } else
231: newValue = null;
232:
233: if (_scale > 0) {
234: String name2 = _edit2.getFullName();
235: if (rowNo > -1)
236: name2 += "_" + rowNo;
237: val = (String[]) parms.get(name2);
238: if (val != null) {
239: String s = val[0].trim();
240: if (!s.equals("")) {
241: if (newValue == null)
242: newValue = "";
243: newValue += "." + s;
244: }
245: }
246: }
247:
248: // Compare old and new values and possibly create a ValueChangedEvent.
249: if (!valuesEqual(oldValue, newValue)) {
250: ValueChangedEvent e = new ValueChangedEvent(getPage(),
251: this , getName(), getFullName(), oldValue, newValue,
252: rowNo, _dsColNo, _dsBuff);
253: addEvent(e);
254: }
255: return false;
256: }
257:
258: /**
259: * This method will clear all pending events from the event queue for this component.
260: */
261: public void reset() {
262: super .reset();
263: _cont.reset();
264: }
265:
266: /**
267: * Specifies the Style Class to be used for the Decimal Component.
268: * Creation date: (7/19/01 8:41:20 AM)
269: * @param sClass java.lang.String A name of a class in Html to be used by this component
270: */
271: public void setClassName(String sClass) {
272: super .setClassName(sClass);
273: _edit1.setClassName(sClass);
274: _edit2.setClassName(sClass);
275: }
276:
277: /**
278: * Sets the font end tag for disabled mode.
279: * @param tag java.lang.String
280: */
281: public void setDisabledFontEndTag(String tag) {
282:
283: _edit1.setDisabledFontEndTag(tag);
284: _edit2.setDisabledFontEndTag(tag);
285: _dot.setFontEndTag(tag);
286: }
287:
288: /**
289: * Sets the font tag for disabled mode.
290: * @param tag java.lang.String
291: */
292: public void setDisabledFontStartTag(String tag) {
293: _edit1.setDisabledFontStartTag(tag);
294: _edit2.setDisabledFontStartTag(tag);
295: _dot.setFontStartTag(tag);
296: }
297:
298: /**
299: * Enables or disables the ability of this component to respond to user input.
300: * @param enabled boolean
301: */
302: public void setEnabled(boolean enabled) {
303: super .setEnabled(enabled);
304: _cont.setEnabled(enabled);
305: }
306:
307: /**
308: * Specify whether to pad integer portion to the right.
309: * @param bNoPadding boolean
310: */
311: public void setNoPadding(boolean bNoPadding) {
312: if (bNoPadding)
313: _flag = NO_PADDING;
314: else
315: _flag = 0;
316: }
317:
318: /**
319: * Specifies the parent component for this Decimal Component.
320: * Creation date: (7/19/01 8:41:20 AM)
321: * @param parent The parent component
322: */
323: public void setParent(HtmlComponent parent) {
324: super .setParent(parent);
325: // This is necessary for the name to be generated correctly, else the leading
326: // sequence of parent names will be lost.
327: _cont.setParent(parent);
328: }
329:
330: /**
331: * Sets the visibility of the component.
332: * Creation date: (7/19/01 8:41:20 AM)
333: * @param bVisible boolean Indicates the visibility of the component
334: */
335: public void setVisible(boolean bVisible) {
336: super .setVisible(bVisible);
337: if (_scale > 0 && _dot != null)
338: _dot.setVisible(bVisible);
339: _edit1.setVisible(bVisible);
340: _edit2.setVisible(bVisible);
341: }
342:
343: /**
344: * This method will set the edit focus to this component.
345: */
346: public void setFocus() {
347: _edit1.setFocus();
348: }
349:
350: /**
351: * This method will set the edit focus to this component for a particular row in a datastore.
352: */
353: public void setFocus(int row) {
354: _edit1.setFocus(row);
355: }
356:
357: /**
358: * @returns the access key html attribute
359: */
360: public String getAccessKey() {
361: return _edit1.getAccessKey();
362: }
363:
364: /**
365: * @returns the read only html attribute
366: */
367: public boolean getReadOnly() {
368: return _edit1.getReadOnly();
369: }
370:
371: /**
372: * @returns the tab index html attribute
373: */
374: public int getTabIndex() {
375: return _edit1.getTabIndex();
376: }
377:
378: /**
379: * @param sets the access key html attribute
380: */
381: public void setAccessKey(String val) {
382: _edit1.setAccessKey(val);
383: }
384:
385: /**
386: * @param sets the read only html attribute
387: */
388: public void setReadOnly(boolean val) {
389: _edit1.setReadOnly(val);
390: _edit2.setReadOnly(val);
391: }
392:
393: /**
394: * @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
395: */
396: public void setTabIndex(int val) {
397: _edit1.setTabIndex(val);
398: _edit2.setTabIndex(val + 1);
399: }
400: }
|