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