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    
041    import javax.faces.component.UIComponent;
042    import javax.faces.component.UIGraphic;
043    import javax.faces.context.FacesContext;
044    import javax.faces.event.FacesEvent;
045    import java.util.Map;
046    
047    /*
048     * Date: 30.05.2006
049     * Time: 19:22:40
050     */
051    public class UIDatePicker extends UILinkCommand implements OnComponentCreated {
052    
053      public static final String COMPONENT_TYPE = "org.apache.myfaces.tobago.DatePicker";
054    
055      private String forComponent;
056    
057      public Object saveState(FacesContext context) {
058        Object[] values = new Object[2];
059        values[0] = super.saveState(context);
060        values[1] = forComponent;
061        return values;
062      }
063    
064      public void restoreState(FacesContext context, Object savedState) {
065        Object[] values = (Object[]) savedState;
066        super.restoreState(context, values[0]);
067        forComponent = (String) values[1];
068      }
069    
070      private UIComponent getUIDateInput(UIComponent parent) {
071        for (Object object : parent.getChildren()) {
072          UIComponent child = (UIComponent) object;
073          if (child instanceof UIDateInput) {
074            return child;
075          }
076        }
077        return null;
078      }
079    
080      public String getFor() {
081        if ("@auto".equals(forComponent)) {
082          UIComponent component = getUIDateInput(getParent());
083          if (component == null && getParent() instanceof UIForm) {
084            component = getUIDateInput(getParent().getParent());
085          }
086          if (component != null) {
087            return component.getId();
088          }
089        }
090        return forComponent;
091      }
092    
093      public UIComponent getForComponent() {
094        if ("@auto".equals(forComponent)) {
095          UIComponent component = getUIDateInput(getParent());
096          if (component == null && getParent() instanceof UIForm) {
097            component = getUIDateInput(getParent().getParent());
098          }
099          return component;
100        } else {
101          return findComponent(forComponent);
102        }
103      }
104    
105      public void setFor(String forComponent) {
106        this.forComponent = forComponent;
107      }
108    
109      public void broadcast(FacesEvent facesEvent) {
110        FacesContext facesContext = FacesContext.getCurrentInstance();
111        UIPopup popup = (UIPopup) getFacets().get(FACET_PICKER_POPUP);
112        String clientId = getForComponent().getClientId(facesContext);
113        UIComponent box = popup.findComponent("box");
114        UIComponent calendar = box.findComponent("calendar");
115        calendar.getAttributes().put(ATTR_CALENDAR_DATE_INPUT_ID, clientId);
116        UIComponent time = box.findComponent("time");
117        if (time != null) {
118          time.getAttributes().put(ATTR_CALENDAR_DATE_INPUT_ID, clientId);
119        }
120        super.broadcast(facesEvent);
121      }
122    
123      public void onComponentCreated() {
124        preparePicker(this);
125      }
126    
127      public void preparePicker(UIDatePicker link) {
128        FacesContext facesContext = FacesContext.getCurrentInstance();
129    
130        if (forComponent == null) {
131          link.setFor("@auto");
132        }
133        link.setImmediate(true);
134    
135        UIHiddenInput hidden =
136            (UIHiddenInput) ComponentUtil.createComponent(facesContext,
137                UIHiddenInput.COMPONENT_TYPE, RENDERER_TYPE_HIDDEN);
138        link.getChildren().add(hidden);
139    
140        // create popup
141        final UIPopup popup =
142            (UIPopup) ComponentUtil.createComponent(facesContext, UIPopup.COMPONENT_TYPE,
143                RENDERER_TYPE_POPUP);
144        //popup.setId(link.getId() + "popup");
145        link.getFacets().put(FACET_PICKER_POPUP, popup);
146    
147        popup.setRendered(false);
148    
149        Map<String, Object> attributes = popup.getAttributes();
150        attributes.put(ATTR_POPUP_RESET, Boolean.TRUE);
151        //int popupHeight = ThemeConfig.getValue(facesContext, link, "CalendarPopupHeight");
152        //attributes.put(ATTR_HEIGHT, String.valueOf(popupHeight));
153        final UIComponent box = ComponentUtil.createComponent(
154            facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_BOX);
155        popup.getChildren().add(box);
156        box.setId("box");
157        // TODO: set string resources in renderer
158        box.getAttributes().put(ATTR_LABEL, ResourceManagerUtil.getPropertyNotNull(
159            facesContext, "tobago", "datePickerTitle"));
160        UIComponent layout = ComponentUtil.createComponent(
161            facesContext, UIGridLayout.COMPONENT_TYPE, RENDERER_TYPE_GRID_LAYOUT);
162        box.getFacets().put(FACET_LAYOUT, layout);
163        layout.setId("layout");
164        layout.getAttributes().put(ATTR_ROWS, "*;fixed;fixed");
165    //    layout.getAttributes().put(TobagoConstants.ATTR_BORDER, "1");
166    
167        final UIComponent calendar = ComponentUtil.createComponent(
168            facesContext, javax.faces.component.UIOutput.COMPONENT_TYPE,
169            RENDERER_TYPE_CALENDAR);
170    
171        calendar.setId("calendar");
172        box.getChildren().add(calendar);
173    
174        // add time input
175        final UIComponent timePanel = ComponentUtil.createComponent(
176            facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL);
177        timePanel.setId("timePanel");
178        box.getChildren().add(timePanel);
179        layout = ComponentUtil.createComponent(
180            facesContext, UIGridLayout.COMPONENT_TYPE, RENDERER_TYPE_GRID_LAYOUT);
181        timePanel.getFacets().put(FACET_LAYOUT, layout);
182        layout.setId("timePanelLayout");
183        layout.getAttributes().put(ATTR_COLUMNS, "1*;fixed;1*");
184        UIComponent cell = ComponentUtil.createComponent(
185            facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL);
186        cell.setId("cell1");
187        timePanel.getChildren().add(cell);
188    
189        final UIComponent time = ComponentUtil.createComponent(
190            facesContext,
191            org.apache.myfaces.tobago.component.UITimeInput.COMPONENT_TYPE,
192            RENDERER_TYPE_TIME);
193        timePanel.getChildren().add(time);
194        time.setId("time");
195    
196        cell = ComponentUtil.createComponent(
197            facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL);
198        cell.setId("cell2");
199        timePanel.getChildren().add(cell);
200    
201    
202        UIComponent buttonPanel = ComponentUtil.createComponent(
203            facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL);
204        buttonPanel.setId("buttonPanel");
205        layout = ComponentUtil.createComponent(
206            facesContext, UIGridLayout.COMPONENT_TYPE, RENDERER_TYPE_GRID_LAYOUT);
207        buttonPanel.getFacets().put(FACET_LAYOUT, layout);
208        layout.getAttributes().put(ATTR_COLUMNS, "*;*");
209    //    layout.getAttributes().put(TobagoConstants.ATTR_BORDER, "1");
210    
211        box.getChildren().add(buttonPanel);
212    
213        final UICommand okButton =
214            (UICommand) ComponentUtil.createComponent(facesContext,
215                org.apache.myfaces.tobago.component.UIButtonCommand.COMPONENT_TYPE,
216                RENDERER_TYPE_BUTTON);
217        buttonPanel.getChildren().add(okButton);
218        okButton.setId("ok" + DatePickerController.CLOSE_POPUP);
219        attributes = okButton.getAttributes();
220        attributes.put(ATTR_LABEL, ResourceManagerUtil.getPropertyNotNull(
221            facesContext, "tobago", "datePickerOk"));
222    
223        final UICommand cancelButton =
224            (UICommand) ComponentUtil.createComponent(facesContext,
225                org.apache.myfaces.tobago.component.UIButtonCommand.COMPONENT_TYPE,
226                RENDERER_TYPE_BUTTON);
227        buttonPanel.getChildren().add(cancelButton);
228        attributes = cancelButton.getAttributes();
229        attributes.put(ATTR_LABEL, ResourceManagerUtil.getPropertyNotNull(
230            facesContext, "tobago", "datePickerCancel"));
231        cancelButton.setId(DatePickerController.CLOSE_POPUP);
232    
233        // create image
234        UIGraphic image = (UIGraphic) ComponentUtil.createComponent(
235            facesContext, UIGraphic.COMPONENT_TYPE, RENDERER_TYPE_IMAGE);
236        image.setRendered(true);
237        image.setValue("image/date.gif");
238        image.getAttributes().put(ATTR_ALT, ""); //TODO: i18n
239        StyleClasses.ensureStyleClasses(image).addFullQualifiedClass("tobago-input-picker"); // XXX not a standard name
240        link.getChildren().add(image);
241      }
242    
243    }