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            writer.attribute("type", "text");
048            writer.attribute("autocomplete", "off");
049            writer.attribute("name", getName());
050    
051            if (isDisabled())
052                writer.attribute("disabled", "disabled");
053    
054            if (value != null)
055                writer.attribute("value", value);
056    
057            renderIdAttribute(writer, cycle);
058            renderDelegateAttributes(writer, cycle);
059    
060            getTranslatedFieldSupport().renderContributions(this, writer, cycle);
061            getValidatableFieldSupport().renderContributions(this, writer, cycle);
062    
063            renderInformalParameters(writer, cycle);
064    
065            writer.closeTag();
066    
067            renderDelegateSuffix(writer, cycle);
068    
069            // Build up options value list
070    
071            Locale locale = getPage().getLocale();
072            
073            GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance(getPage().getLocale());
074            cal.set(Calendar.HOUR, 0);
075            cal.set(Calendar.AM_PM, Calendar.AM);
076    
077            StringBuffer optStr = new StringBuffer("[");
078            int selectedIndex = -1;
079            
080            for(int i=0, hour=0; i < TIME_SEGMENT_LENGTH; i++)
081            {
082                if (i != 0)
083                {
084                    optStr.append(",");
085                }
086                
087                if (i == 24)
088                {
089                    hour = 0;
090                    cal.set(Calendar.AM_PM, Calendar.PM);
091                }
092                
093                cal.set(Calendar.HOUR,  hour);
094                cal.set(Calendar.MINUTE, (i % 2 > 0) ? 30 : 0);
095    
096                String option = getTranslator().format(this, locale, cal.getTime());
097    
098                optStr.append("\"").append(option).append("\"");
099                
100                if (selectedIndex < 0 && value != null && value.equals(option))
101                {
102                    selectedIndex = i;
103                }
104    
105                if (i % 2 > 0)
106                {
107                    hour++;
108                }
109            }
110    
111            optStr.append("]");
112            
113            // now create widget parms
114    
115            JSONObject json = new JSONObject();
116            json.put("inputNodeId", getClientId());
117            json.put("optionValues", new JSONLiteral(optStr.toString()));
118    
119            if (selectedIndex > -1)
120            {
121                json.put("selectedIndex", selectedIndex);
122            }
123    
124            Map parms = new HashMap();
125            parms.put("clientId", getClientId());
126            parms.put("props", json.toString());
127            parms.put("widget", this);
128    
129            getScript().execute(this, cycle, TapestryUtils.getPageRenderSupport(cycle, this), parms);
130        }
131    
132        /**
133         * @see org.apache.tapestry.form.AbstractFormComponent#rewindFormComponent(org.apache.tapestry.IMarkupWriter, org.apache.tapestry.IRequestCycle)
134         */
135        protected void rewindFormWidget(IMarkupWriter writer, IRequestCycle cycle)
136        {
137            String value = cycle.getParameter(getName());
138    
139            try
140            {
141                Object translated = getTranslatedFieldSupport().parse(this, value);
142    
143                getValidatableFieldSupport().validate(this, writer, cycle, translated);
144    
145                setValue(translated);
146            }
147            catch (ValidatorException e)
148            {
149                getForm().getDelegate().record(e);
150            }
151        }
152    
153        /**
154         * @see org.apache.tapestry.form.AbstractFormComponent#isRequired()
155         */
156        public boolean isRequired()
157        {
158            return getValidatableFieldSupport().isRequired(this);
159        }
160    
161        /** Injected. */
162        public abstract IScript getScript();
163    
164        /** Injected. */
165        public abstract TranslatedFieldSupport getTranslatedFieldSupport();
166    
167        /** Injected. */
168        public abstract ValidatableFieldSupport getValidatableFieldSupport();
169    
170    }