001    package org.apache.myfaces.tobago.component;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one or more
005     * contributor license agreements.  See the NOTICE file distributed with
006     * this work for additional information regarding copyright ownership.
007     * The ASF licenses this file to You under the Apache License, Version 2.0
008     * (the "License"); you may not use this file except in compliance with
009     * the License.  You may obtain a copy of the License at
010     *
011     *      http://www.apache.org/licenses/LICENSE-2.0
012     *
013     * Unless required by applicable law or agreed to in writing, software
014     * distributed under the License is distributed on an "AS IS" BASIS,
015     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */
019    
020    import static org.apache.myfaces.tobago.TobagoConstants.ATTR_ALT;
021    import static org.apache.myfaces.tobago.TobagoConstants.ATTR_CALENDAR_DATE_INPUT_ID;
022    import static org.apache.myfaces.tobago.TobagoConstants.ATTR_COLUMNS;
023    import static org.apache.myfaces.tobago.TobagoConstants.ATTR_LABEL;
024    import static org.apache.myfaces.tobago.TobagoConstants.ATTR_POPUP_RESET;
025    import static org.apache.myfaces.tobago.TobagoConstants.ATTR_ROWS;
026    import static org.apache.myfaces.tobago.TobagoConstants.FACET_LAYOUT;
027    import static org.apache.myfaces.tobago.TobagoConstants.FACET_PICKER_POPUP;
028    import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_BOX;
029    import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_BUTTON;
030    import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_CALENDAR;
031    import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_GRID_LAYOUT;
032    import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_HIDDEN;
033    import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_IMAGE;
034    import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_PANEL;
035    import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_POPUP;
036    import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_TIME;
037    import org.apache.myfaces.tobago.context.ResourceManagerUtil;
038    import org.apache.myfaces.tobago.event.DatePickerController;
039    import org.apache.myfaces.tobago.renderkit.html.StyleClasses;
040    import org.apache.myfaces.tobago.TobagoConstants;
041    
042    import javax.faces.component.UIComponent;
043    import javax.faces.component.UIGraphic;
044    import javax.faces.context.FacesContext;
045    import javax.faces.event.FacesEvent;
046    import java.util.Map;
047    
048    /*
049     * Date: 30.05.2006
050     * Time: 19:22:40
051     */
052    public class UIDatePicker extends UILinkCommand implements OnComponentCreated {
053    
054      public static final String COMPONENT_TYPE = "org.apache.myfaces.tobago.DatePicker";
055    
056      private String forComponent;
057    
058      public Object saveState(FacesContext context) {
059        Object[] values = new Object[2];
060        values[0] = super.saveState(context);
061        values[1] = forComponent;
062        return values;
063      }
064    
065      public void restoreState(FacesContext context, Object savedState) {
066        Object[] values = (Object[]) savedState;
067        super.restoreState(context, values[0]);
068        forComponent = (String) values[1];
069      }
070    
071      private UIComponent getUIDateInput(UIComponent parent) {
072        for (Object object : parent.getChildren()) {
073          UIComponent child = (UIComponent) object;
074          if (child instanceof UIDateInput) {
075            return child;
076          }
077        }
078        return null;
079      }
080    
081      public String getFor() {
082        if ("@auto".equals(forComponent)) {
083          UIComponent component = getUIDateInput(getParent());
084          if (component == null && getParent() instanceof UIForm) {
085            component = getUIDateInput(getParent().getParent());
086          }
087          if (component != null) {
088            return component.getId();
089          }
090        }
091        return forComponent;
092      }
093    
094      public UIComponent getForComponent() {
095        if ("@auto".equals(forComponent)) {
096          UIComponent component = getUIDateInput(getParent());
097          if (component == null && getParent() instanceof UIForm) {
098            component = getUIDateInput(getParent().getParent());
099          }
100          return component;
101        } else {
102          return findComponent(forComponent);
103        }
104      }
105    
106      public void setFor(String forComponent) {
107        this.forComponent = forComponent;
108      }
109    
110      public void broadcast(FacesEvent facesEvent) {
111        FacesContext facesContext = FacesContext.getCurrentInstance();
112        UIPopup popup = (UIPopup) getFacets().get(FACET_PICKER_POPUP);
113        String clientId = getForComponent().getClientId(facesContext);
114        UIComponent box = popup.findComponent("box");
115        UIComponent calendar = box.findComponent("calendar");
116        calendar.getAttributes().put(ATTR_CALENDAR_DATE_INPUT_ID, clientId);
117        UIComponent time = box.findComponent("time");
118        if (time != null) {
119          time.getAttributes().put(ATTR_CALENDAR_DATE_INPUT_ID, clientId);
120        }
121        super.broadcast(facesEvent);
122      }
123    
124      public void onComponentCreated() {
125        preparePicker(this);
126      }
127    
128      public void preparePicker(UIDatePicker link) {
129        FacesContext facesContext = FacesContext.getCurrentInstance();
130    
131        if (forComponent == null) {
132          link.setFor("@auto");
133        }
134        link.setImmediate(true);
135        String linkId = link.getId();
136        UIHiddenInput hidden =
137            (UIHiddenInput) ComponentUtil.createComponent(facesContext,
138                UIHiddenInput.COMPONENT_TYPE, RENDERER_TYPE_HIDDEN);
139        if (linkId != null) {
140          hidden.setId(linkId + "hidden");
141        } else {
142          hidden.setId(facesContext.getViewRoot().createUniqueId());
143        }
144        link.getChildren().add(hidden);
145    
146        // create popup
147        final UIPopup popup =
148            (UIPopup) ComponentUtil.createComponent(facesContext, UIPopup.COMPONENT_TYPE,
149                RENDERER_TYPE_POPUP);
150        if (linkId != null) {
151          popup.setId(linkId + "popup");
152        } else {
153          popup.setId(facesContext.getViewRoot().createUniqueId());
154        }
155        popup.getAttributes().put(TobagoConstants.ATTR_ZINDEX, 10);
156          
157        link.getFacets().put(FACET_PICKER_POPUP, popup);
158    
159        popup.setRendered(false);
160    
161        Map<String, Object> attributes = popup.getAttributes();
162        attributes.put(ATTR_POPUP_RESET, Boolean.TRUE);
163        //int popupHeight = ThemeConfig.getValue(facesContext, link, "CalendarPopupHeight");
164        //attributes.put(ATTR_HEIGHT, String.valueOf(popupHeight));
165        final UIComponent box = ComponentUtil.createComponent(
166            facesContext, UIBox.COMPONENT_TYPE, RENDERER_TYPE_BOX);
167        popup.getChildren().add(box);
168        box.setId("box");
169        // TODO: set string resources in renderer
170        box.getAttributes().put(ATTR_LABEL, ResourceManagerUtil.getPropertyNotNull(
171            facesContext, "tobago", "datePickerTitle"));
172        UIComponent layout = ComponentUtil.createComponent(
173            facesContext, UIGridLayout.COMPONENT_TYPE, RENDERER_TYPE_GRID_LAYOUT);
174        box.getFacets().put(FACET_LAYOUT, layout);
175        layout.setId("layout");
176        layout.getAttributes().put(ATTR_ROWS, "*;fixed;fixed");
177    //    layout.getAttributes().put(TobagoConstants.ATTR_BORDER, "1");
178    
179        final UIComponent calendar = ComponentUtil.createComponent(
180            facesContext, javax.faces.component.UIOutput.COMPONENT_TYPE,
181            RENDERER_TYPE_CALENDAR);
182    
183        calendar.setId("calendar");
184        box.getChildren().add(calendar);
185    
186        // add time input
187        final UIComponent timePanel = ComponentUtil.createComponent(
188            facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL);
189        timePanel.setId("timePanel");
190        box.getChildren().add(timePanel);
191        layout = ComponentUtil.createComponent(
192            facesContext, UIGridLayout.COMPONENT_TYPE, RENDERER_TYPE_GRID_LAYOUT);
193        timePanel.getFacets().put(FACET_LAYOUT, layout);
194        layout.setId("timePanelLayout");
195        layout.getAttributes().put(ATTR_COLUMNS, "1*;fixed;1*");
196        UIComponent cell = ComponentUtil.createComponent(
197            facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL);
198        cell.setId("cell1");
199        timePanel.getChildren().add(cell);
200    
201        final UIComponent time = ComponentUtil.createComponent(
202            facesContext,
203            org.apache.myfaces.tobago.component.UITimeInput.COMPONENT_TYPE,
204            RENDERER_TYPE_TIME);
205        timePanel.getChildren().add(time);
206        time.setId("time");
207    
208        cell = ComponentUtil.createComponent(
209            facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL);
210        cell.setId("cell2");
211        timePanel.getChildren().add(cell);
212    
213    
214        UIComponent buttonPanel = ComponentUtil.createComponent(
215            facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL);
216        buttonPanel.setId("buttonPanel");
217        layout = ComponentUtil.createComponent(
218            facesContext, UIGridLayout.COMPONENT_TYPE, RENDERER_TYPE_GRID_LAYOUT);
219        layout.setId("buttonPanelLayout");
220        buttonPanel.getFacets().put(FACET_LAYOUT, layout);
221        layout.getAttributes().put(ATTR_COLUMNS, "*;*");
222    //    layout.getAttributes().put(TobagoConstants.ATTR_BORDER, "1");
223    
224        box.getChildren().add(buttonPanel);
225    
226        final UICommand okButton =
227            (UICommand) ComponentUtil.createComponent(facesContext,
228                org.apache.myfaces.tobago.component.UIButtonCommand.COMPONENT_TYPE,
229                RENDERER_TYPE_BUTTON);
230        buttonPanel.getChildren().add(okButton);
231        okButton.setId("ok" + DatePickerController.CLOSE_POPUP);
232        attributes = okButton.getAttributes();
233        attributes.put(ATTR_LABEL, ResourceManagerUtil.getPropertyNotNull(
234            facesContext, "tobago", "datePickerOk"));
235    
236        final UICommand cancelButton =
237            (UICommand) ComponentUtil.createComponent(facesContext,
238                org.apache.myfaces.tobago.component.UIButtonCommand.COMPONENT_TYPE,
239                RENDERER_TYPE_BUTTON);
240        buttonPanel.getChildren().add(cancelButton);
241        attributes = cancelButton.getAttributes();
242        attributes.put(ATTR_LABEL, ResourceManagerUtil.getPropertyNotNull(
243            facesContext, "tobago", "datePickerCancel"));
244        cancelButton.setId(DatePickerController.CLOSE_POPUP);
245    
246        // create image
247        UIGraphic image = (UIGraphic) ComponentUtil.createComponent(
248            facesContext, UIGraphic.COMPONENT_TYPE, RENDERER_TYPE_IMAGE);
249        image.setRendered(true);
250        if (linkId != null) {
251          image.setId(linkId + "image");
252        } else {
253          image.setId(facesContext.getViewRoot().createUniqueId());
254        }
255        image.setValue("image/date.gif");
256        image.getAttributes().put(ATTR_ALT, ""); //TODO: i18n
257        StyleClasses.ensureStyleClasses(image).addFullQualifiedClass("tobago-input-picker"); // XXX not a standard name
258        link.getChildren().add(image);
259      }
260    
261    }