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