001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020 package org.apache.myfaces.tobago.component;
021
022 import org.apache.myfaces.tobago.context.ResourceManagerUtil;
023 import org.apache.myfaces.tobago.renderkit.html.StyleClasses;
024
025 import javax.faces.component.UIComponent;
026 import javax.faces.component.UIGraphic;
027 import javax.faces.context.FacesContext;
028 import javax.faces.event.FacesEvent;
029 import java.util.Map;
030
031 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_ALT;
032 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_CALENDAR_DATE_INPUT_ID;
033 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_COLUMNS;
034 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_LABEL;
035 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_POPUP_RESET;
036 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_ROWS;
037 import static org.apache.myfaces.tobago.TobagoConstants.FACET_LAYOUT;
038 import static org.apache.myfaces.tobago.TobagoConstants.FACET_PICKER_POPUP;
039 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_BOX;
040 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_BUTTON;
041 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_CALENDAR;
042 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_GRID_LAYOUT;
043 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_HIDDEN;
044 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_IMAGE;
045 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_PANEL;
046 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_POPUP;
047 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_TIME;
048
049 public class UIDatePicker extends UILinkCommand implements OnComponentCreated {
050
051 public static final String COMPONENT_TYPE = "org.apache.myfaces.tobago.DatePicker";
052
053 public static final String OPEN_POPUP = "openPopup";
054 public static final String CLOSE_POPUP = "closePopup";
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 javax.faces.component.UIViewRoot viewRoot = facesContext.getViewRoot();
137 UIHiddenInput hidden =
138 (UIHiddenInput) ComponentUtil.createComponent(facesContext,
139 UIHiddenInput.COMPONENT_TYPE, RENDERER_TYPE_HIDDEN,
140 (linkId != null ? linkId + "hidden" : viewRoot.createUniqueId()));
141 link.getChildren().add(hidden);
142
143 // create popup
144 final UIPopup popup =
145 (UIPopup) ComponentUtil.createComponent(facesContext, UIPopup.COMPONENT_TYPE,
146 RENDERER_TYPE_POPUP, (linkId != null ? linkId + "popup" : viewRoot.createUniqueId()));
147 link.getFacets().put(FACET_PICKER_POPUP, popup);
148
149 popup.setRendered(false);
150
151 Map<String, Object> attributes = popup.getAttributes();
152 attributes.put(ATTR_POPUP_RESET, Boolean.TRUE);
153 //int popupHeight = ThemeConfig.getValue(facesContext, link, "CalendarPopupHeight");
154 //attributes.put(ATTR_HEIGHT, String.valueOf(popupHeight));
155 final UIComponent box = ComponentUtil.createComponent(
156 facesContext, UIBox.COMPONENT_TYPE, RENDERER_TYPE_BOX);
157 popup.getChildren().add(box);
158 box.setId("box");
159 // TODO: set string resources in renderer
160 box.getAttributes().put(ATTR_LABEL, ResourceManagerUtil.getPropertyNotNull(
161 facesContext, "tobago", "datePickerTitle"));
162 UIComponent layout = ComponentUtil.createComponent(
163 facesContext, UIGridLayout.COMPONENT_TYPE, RENDERER_TYPE_GRID_LAYOUT, "layout");
164 box.getFacets().put(FACET_LAYOUT, layout);
165 layout.getAttributes().put(ATTR_ROWS, "*;fixed;fixed");
166 // layout.getAttributes().put(TobagoConstants.ATTR_BORDER, "1");
167
168 final UIComponent calendar = ComponentUtil.createComponent(
169 facesContext, javax.faces.component.UIOutput.COMPONENT_TYPE,
170 RENDERER_TYPE_CALENDAR, "calendar");
171 box.getChildren().add(calendar);
172
173 // add time input
174 final UIComponent timePanel = ComponentUtil.createComponent(
175 facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL, "timePanel");
176 box.getChildren().add(timePanel);
177 layout = ComponentUtil.createComponent(
178 facesContext, UIGridLayout.COMPONENT_TYPE, RENDERER_TYPE_GRID_LAYOUT, "timePanelLayout");
179 timePanel.getFacets().put(FACET_LAYOUT, layout);
180 layout.getAttributes().put(ATTR_COLUMNS, "1*;fixed;1*");
181 UIComponent cell = ComponentUtil.createComponent(
182 facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL, "cell1");
183 timePanel.getChildren().add(cell);
184
185 final UIComponent time = ComponentUtil.createComponent(
186 facesContext,
187 org.apache.myfaces.tobago.component.UITimeInput.COMPONENT_TYPE,
188 RENDERER_TYPE_TIME, "time");
189 timePanel.getChildren().add(time);
190
191 cell = ComponentUtil.createComponent(
192 facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL, "cell2");
193 timePanel.getChildren().add(cell);
194
195
196 UIComponent buttonPanel = ComponentUtil.createComponent(
197 facesContext, UIPanel.COMPONENT_TYPE, RENDERER_TYPE_PANEL, "buttonPanel");
198 layout = ComponentUtil.createComponent(
199 facesContext, UIGridLayout.COMPONENT_TYPE, RENDERER_TYPE_GRID_LAYOUT, "buttonPanelLayout");
200 buttonPanel.getFacets().put(FACET_LAYOUT, layout);
201 layout.getAttributes().put(ATTR_COLUMNS, "*;*");
202 layout.getAttributes().put(ATTR_ROWS, "fixed");
203 // layout.getAttributes().put(TobagoConstants.ATTR_BORDER, "1");
204
205 box.getChildren().add(buttonPanel);
206
207 final UICommand okButton =
208 (UICommand) ComponentUtil.createComponent(facesContext,
209 org.apache.myfaces.tobago.component.UIButtonCommand.COMPONENT_TYPE,
210 RENDERER_TYPE_BUTTON, "ok" + CLOSE_POPUP);
211 buttonPanel.getChildren().add(okButton);
212 attributes = okButton.getAttributes();
213 attributes.put(ATTR_LABEL, ResourceManagerUtil.getPropertyNotNull(
214 facesContext, "tobago", "datePickerOk"));
215
216 final UICommand cancelButton =
217 (UICommand) ComponentUtil.createComponent(facesContext,
218 org.apache.myfaces.tobago.component.UIButtonCommand.COMPONENT_TYPE,
219 RENDERER_TYPE_BUTTON, CLOSE_POPUP);
220 buttonPanel.getChildren().add(cancelButton);
221 attributes = cancelButton.getAttributes();
222 attributes.put(ATTR_LABEL, ResourceManagerUtil.getPropertyNotNull(
223 facesContext, "tobago", "datePickerCancel"));
224
225 // create image
226 UIGraphic image = (UIGraphic) ComponentUtil.createComponent(
227 facesContext, UIGraphic.COMPONENT_TYPE, RENDERER_TYPE_IMAGE,
228 (linkId != null ? linkId + "image" : viewRoot.createUniqueId()));
229 image.setRendered(true);
230 image.setValue("image/date.gif");
231 image.getAttributes().put(ATTR_ALT, ""); //TODO: i18n
232 StyleClasses.ensureStyleClasses(image).addFullQualifiedClass("tobago-input-picker"); // XXX not a standard name
233 link.getChildren().add(image);
234 }
235
236 }