001    package org.apache.tapestry.dojo.form;
002    
003    import org.apache.tapestry.IMarkupWriter;
004    import org.apache.tapestry.IRequestCycle;
005    import org.apache.tapestry.IScript;
006    import org.apache.tapestry.TapestryUtils;
007    import org.apache.tapestry.form.TranslatedField;
008    import org.apache.tapestry.form.TranslatedFieldSupport;
009    import org.apache.tapestry.form.ValidatableFieldSupport;
010    import org.apache.tapestry.json.JSONLiteral;
011    import org.apache.tapestry.json.JSONObject;
012    import org.apache.tapestry.valid.ValidatorException;
013    
014    import java.util.*;
015    
016    /**
017     * Implementation of an html form input field that has a dynamic drop down selection list of
018     * time segments displayed in the {@link org.apache.tapestry.IPage}'s {@link java.util.Locale}.
019     */
020    public abstract class GTimePicker  extends AbstractFormWidget implements TranslatedField
021    {
022        /**
023         * For a full day - broken up in to half hour segments.
024         */
025        static final int TIME_SEGMENT_LENGTH = 48;
026    
027        /**
028         * Core value used to place input in to.
029         * @return The current bound value, may be null.
030         */
031        public abstract Object getValue();
032    
033        public abstract void setValue(Object value);
034    
035        public abstract boolean isDisabled();
036    
037        /**
038         * {@inheritDoc}
039         */
040        protected void renderFormWidget(IMarkupWriter writer, IRequestCycle cycle)
041        {
042            String value = getTranslatedFieldSupport().format(this, getValue());
043    
044            renderDelegatePrefix(writer, cycle);
045    
046            writer.beginEmpty("input");
047    
048            writer.attribute("type", "text");
049            
050            writer.attribute("autocomplete", "off");
051    
052            writer.attribute("name", getName());
053    
054            if (isDisabled())
055                writer.attribute("disabled", "disabled");
056    
057            if (value != null)
058                writer.attribute("value", value);
059    
060            renderIdAttribute(writer, cycle);
061    
062            renderDelegateAttributes(writer, cycle);
063    
064            getTranslatedFieldSupport().renderContributions(this, writer, cycle);
065            getValidatableFieldSupport().renderContributions(this, writer, cycle);
066    
067            renderInformalParameters(writer, cycle);
068    
069            writer.closeTag();
070    
071            renderDelegateSuffix(writer, cycle);
072    
073            // Build up options value list
074    
075            Locale locale = getPage().getLocale();
076            
077            GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance(getPage().getLocale());
078            cal.set(Calendar.HOUR, 0);
079            cal.set(Calendar.AM_PM, Calendar.AM);
080    
081            StringBuffer optStr = new StringBuffer("[");
082    
083            int selectedIndex = -1;
084            
085            for(int i=0, hour=0; i < TIME_SEGMENT_LENGTH; i++)
086            {
087                if (i != 0)
088                {
089                    optStr.append(",");
090                }
091                
092                if (i == 24)
093                {
094                    hour = 0;
095                    cal.set(Calendar.AM_PM, Calendar.PM);
096                }
097                
098                cal.set(Calendar.HOUR,  hour);
099                cal.set(Calendar.MINUTE, (i % 2 > 0) ? 30 : 0);
100    
101                String option = getTranslator().format(this, locale, cal.getTime());
102    
103                optStr.append("\"").append(option).append("\"");
104                
105                if (selectedIndex < 0 && value != null && value.equals(option))
106                {
107                    selectedIndex = i;
108                }
109    
110                if (i % 2 > 0)
111                {
112                    hour++;
113                }
114            }
115    
116            optStr.append("]");
117            
118            // now create widget parms
119    
120            JSONObject json = new JSONObject();
121            json.put("inputNodeId", getClientId());
122            json.put("optionValues", new JSONLiteral(optStr.toString()));
123    
124            if (selectedIndex > -1)
125            {
126                json.put("selectedIndex", selectedIndex);
127            }
128    
129            Map parms = new HashMap();
130            parms.put("clientId", getClientId());
131            parms.put("props", json.toString());
132            parms.put("widget", this);
133    
134            getScript().execute(this, cycle, TapestryUtils.getPageRenderSupport(cycle, this), parms);
135        }
136    
137        /**
138         * @see org.apache.tapestry.form.AbstractFormComponent#rewindFormComponent(org.apache.tapestry.IMarkupWriter, org.apache.tapestry.IRequestCycle)
139         */
140        protected void rewindFormWidget(IMarkupWriter writer, IRequestCycle cycle)
141        {
142            String value = cycle.getParameter(getName());
143    
144            try
145            {
146                Object translated = getTranslatedFieldSupport().parse(this, value);
147    
148                getValidatableFieldSupport().validate(this, writer, cycle, translated);
149    
150                setValue(translated);
151            }
152            catch (ValidatorException e)
153            {
154                getForm().getDelegate().record(e);
155            }
156        }
157    
158        /**
159         * @see org.apache.tapestry.form.AbstractFormComponent#isRequired()
160         */
161        public boolean isRequired()
162        {
163            return getValidatableFieldSupport().isRequired(this);
164        }
165    
166        /** Injected. */
167        public abstract IScript getScript();
168    
169        /** Injected. */
170        public abstract TranslatedFieldSupport getTranslatedFieldSupport();
171    
172        /** Injected. */
173        public abstract ValidatableFieldSupport getValidatableFieldSupport();
174    
175    }