1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.renderkit.html.scarborough.standard.tag;
21
22 import org.apache.myfaces.tobago.component.Attributes;
23 import org.apache.myfaces.tobago.component.Facets;
24 import org.apache.myfaces.tobago.component.RendererTypes;
25 import org.apache.myfaces.tobago.component.UIBox;
26 import org.apache.myfaces.tobago.component.UIButton;
27 import org.apache.myfaces.tobago.component.UICalendar;
28 import org.apache.myfaces.tobago.component.UIDate;
29 import org.apache.myfaces.tobago.component.UIDatePicker;
30 import org.apache.myfaces.tobago.component.UIGridLayout;
31 import org.apache.myfaces.tobago.component.UIPanel;
32 import org.apache.myfaces.tobago.component.UIPopup;
33 import org.apache.myfaces.tobago.component.UITime;
34 import org.apache.myfaces.tobago.event.PopupActionListener;
35 import org.apache.myfaces.tobago.internal.util.DateFormatUtils;
36 import org.apache.myfaces.tobago.internal.util.FacesContextUtils;
37 import org.apache.myfaces.tobago.layout.Measure;
38 import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
39 import org.apache.myfaces.tobago.util.ComponentUtils;
40 import org.apache.myfaces.tobago.util.CreateComponentUtils;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 import javax.el.ELContext;
45 import javax.el.ExpressionFactory;
46 import javax.el.ValueExpression;
47 import javax.faces.component.UIComponent;
48 import javax.faces.context.FacesContext;
49 import javax.faces.convert.Converter;
50 import javax.faces.convert.DateTimeConverter;
51 import java.io.IOException;
52 import java.util.TimeZone;
53
54 public class DatePickerRenderer extends LinkRenderer {
55
56 private static final Logger LOG = LoggerFactory.getLogger(DatePickerRenderer.class);
57
58 @Override
59 public void onComponentCreated(FacesContext facesContext, UIComponent component, UIComponent parent) {
60 final UIDatePicker picker = (UIDatePicker) component;
61 if (picker.getFor() == null) {
62 picker.setFor("@auto");
63 }
64 picker.setImmediate(true);
65 final String linkId = picker.getId();
66 picker.setImage("image/date.gif");
67
68
69 final String popupId = linkId != null ? linkId + "popup" : facesContext.getViewRoot().createUniqueId();
70 final UIPopup popup = (UIPopup) CreateComponentUtils.createComponent(
71 facesContext, UIPopup.COMPONENT_TYPE, RendererTypes.POPUP, popupId);
72 final UIGridLayout layoutOfPopup = (UIGridLayout) CreateComponentUtils.createComponent(
73 facesContext, UIGridLayout.COMPONENT_TYPE, RendererTypes.GRID_LAYOUT, "layoutPopup");
74 layoutOfPopup.setColumns("auto");
75 layoutOfPopup.setRows("auto");
76 popup.getFacets().put(Facets.LAYOUT, layoutOfPopup);
77 popup.getAttributes().put(Attributes.Z_INDEX, 10);
78 picker.getFacets().put(Facets.POPUP, popup);
79 picker.onComponentPopulated(facesContext, parent);
80 popup.setRendered(false);
81 popup.onComponentPopulated(facesContext, picker);
82
83 final ExpressionFactory expressionFactory = facesContext.getApplication().getExpressionFactory();
84 final ELContext elContext = facesContext.getELContext();
85 popup.setValueExpression(Attributes.LEFT, expressionFactory.createValueExpression(
86 elContext, "#{tobagoContext.actionPosition.right.pixel + 5}", Object.class));
87 popup.setValueExpression(Attributes.TOP, expressionFactory.createValueExpression(
88 elContext, "#{tobagoContext.actionPosition.top.pixel}", Object.class));
89
90 final UIBox box = (UIBox) CreateComponentUtils.createComponent(
91 facesContext, UIBox.COMPONENT_TYPE, RendererTypes.BOX, "box");
92 popup.getChildren().add(box);
93 box.setValueExpression(Attributes.LABEL, expressionFactory.createValueExpression(
94 elContext, "#{tobagoContext.resourceBundle.datePickerTitle}", String.class));
95 final UIGridLayout layoutOfBox = (UIGridLayout) CreateComponentUtils.createComponent(
96 facesContext, UIGridLayout.COMPONENT_TYPE, RendererTypes.GRID_LAYOUT, "layout");
97 box.getFacets().put(Facets.LAYOUT, layoutOfBox);
98 layoutOfBox.setRows("*;auto;auto");
99
100 final UICalendar calendar = (UICalendar) CreateComponentUtils.createComponent(
101 facesContext, UICalendar.COMPONENT_TYPE, RendererTypes.CALENDAR, "calendar");
102 box.getChildren().add(calendar);
103
104
105 final Measure width = getResourceManager().getThemeMeasure(facesContext, calendar, "minimumWidth");
106 layoutOfBox.setColumns(width.serialize());
107
108
109 final UIPanel timePanel = (UIPanel) CreateComponentUtils.createComponent(
110 facesContext, UIPanel.COMPONENT_TYPE, RendererTypes.PANEL, "timePanel");
111 box.getChildren().add(timePanel);
112 final UIGridLayout layoutOfTime = (UIGridLayout) CreateComponentUtils.createComponent(
113 facesContext, UIGridLayout.COMPONENT_TYPE, RendererTypes.GRID_LAYOUT, "timePanelLayout");
114 timePanel.getFacets().put(Facets.LAYOUT, layoutOfTime);
115 layoutOfTime.setColumns("1*;auto;1*");
116 final UIPanel cell1 = (UIPanel) CreateComponentUtils.createComponent(
117 facesContext, UIPanel.COMPONENT_TYPE, RendererTypes.PANEL, "cell1");
118 cell1.onComponentPopulated(facesContext, parent);
119 timePanel.getChildren().add(cell1);
120
121 final UITime time = (UITime) CreateComponentUtils.createComponent(
122 facesContext, UITime.COMPONENT_TYPE, RendererTypes.TIME, "time");
123 timePanel.getChildren().add(time);
124
125 final UIPanel cell2 = (UIPanel) CreateComponentUtils.createComponent(
126 facesContext, UIPanel.COMPONENT_TYPE, RendererTypes.PANEL, "cell2");
127 cell2.onComponentPopulated(facesContext, parent);
128 timePanel.getChildren().add(cell2);
129
130 timePanel.onComponentPopulated(facesContext, parent);
131
132
133 final UIPanel buttonPanel = (UIPanel) CreateComponentUtils.createComponent(
134 facesContext, UIPanel.COMPONENT_TYPE, RendererTypes.PANEL, "buttonPanel");
135 final UIGridLayout layoutOfButtons = (UIGridLayout) CreateComponentUtils.createComponent(
136 facesContext, UIGridLayout.COMPONENT_TYPE, RendererTypes.GRID_LAYOUT, "buttonPanelLayout");
137 buttonPanel.setLayoutManager(layoutOfButtons);
138 layoutOfButtons.setColumns("*;*");
139 layoutOfButtons.setRows("auto");
140
141 box.getChildren().add(buttonPanel);
142 box.onComponentPopulated(facesContext, parent);
143
144 final UIButton okButton = (UIButton) CreateComponentUtils.createComponent(
145 facesContext, UIButton.COMPONENT_TYPE, RendererTypes.BUTTON, "ok");
146 buttonPanel.getChildren().add(okButton);
147 okButton.setValueExpression(Attributes.LABEL, expressionFactory.createValueExpression(
148 elContext, "#{tobagoContext.resourceBundle.datePickerOk}", String.class));
149 ComponentUtils.putDataAttributeWithPrefix(okButton, DataAttributes.DATEPICKEROK, true);
150 okButton.getAttributes().put(Attributes.POPUP_CLOSE, "afterSubmit");
151 okButton.getAttributes().put(Attributes.ONCLICK, "/* fixme: avoid submit */");
152 final UIButton cancelButton = (UIButton) CreateComponentUtils.createComponent(
153 facesContext, UIButton.COMPONENT_TYPE, RendererTypes.BUTTON, "cancel");
154 buttonPanel.getChildren().add(cancelButton);
155 cancelButton.setValueExpression(Attributes.LABEL, expressionFactory.createValueExpression(
156 elContext, "#{tobagoContext.resourceBundle.datePickerCancel}", String.class));
157 cancelButton.getAttributes().put(Attributes.POPUP_CLOSE, "immediate");
158
159 buttonPanel.onComponentPopulated(facesContext, parent);
160 }
161
162 @Override
163 public void prepareRender(FacesContext facesContext, UIComponent component) throws IOException {
164 UIDatePicker picker = (UIDatePicker) component;
165
166
167 picker.getAttributes().put(
168 Attributes.LAYOUT_WIDTH,
169 getResourceManager().getThemeMeasure(facesContext, picker, "pickerWidth").getPixel());
170
171 FacesContextUtils.addPopup(facesContext, (UIPopup) picker.getFacets().get(Facets.POPUP));
172
173 super.prepareRender(facesContext, picker);
174 }
175
176 @Override
177 public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
178 UIDatePicker picker = (UIDatePicker) component;
179 UIDate dateInput = (UIDate) picker.getForComponent();
180 if (dateInput == null) {
181 LOG.error("The required UIDate component wasn't found for component id='" + component.getId());
182 return;
183 }
184
185 final ValueExpression readonlyExpression = dateInput.getValueExpression(Attributes.READONLY);
186 if (readonlyExpression != null) {
187 picker.setValueExpression(Attributes.DISABLED, readonlyExpression);
188 } else {
189 final ValueExpression disabledExpression = dateInput.getValueExpression(Attributes.DISABLED);
190 if (disabledExpression != null) {
191 picker.setValueExpression(Attributes.DISABLED, disabledExpression);
192 } else {
193 picker.setDisabled(dateInput.isReadonly() || dateInput.isDisabled());
194 }
195 }
196 UIPopup popup = (UIPopup) picker.getFacets().get(Facets.POPUP);
197 picker.setRenderedPartially(new String[] {popup.getId()});
198 Converter converter = getConverter(facesContext, dateInput);
199 String converterPattern = "yyyy-MM-dd";
200 if (converter instanceof DateTimeConverter) {
201 converterPattern = DateFormatUtils.findPattern((DateTimeConverter) converter);
202 } else {
203
204
205 }
206
207 applyConverterPattern(facesContext, popup, converterPattern);
208
209 if (!ComponentUtils.containsPopupActionListener(picker)) {
210 picker.addActionListener(new PopupActionListener(popup.getId()));
211 }
212 super.encodeBegin(facesContext, component);
213 }
214
215 private void applyConverterPattern(FacesContext facesContext, UIPopup popup, String converterPattern) {
216 UIComponent box = popup.getChildren().get(0);
217 UIComponent timePanel = box.findComponent("timePanel");
218 if (converterPattern != null && (converterPattern.indexOf('h') > -1 || converterPattern.indexOf('H') > -1)) {
219 UITime time = (UITime) timePanel.findComponent("time");
220 DateTimeConverter dateTimeConverter
221 = (DateTimeConverter) facesContext.getApplication().createConverter(DateTimeConverter.CONVERTER_ID);
222 if (converterPattern.indexOf('s') > -1) {
223 dateTimeConverter.setPattern("HH:mm:ss");
224 } else {
225 dateTimeConverter.setPattern("HH:mm");
226 }
227 dateTimeConverter.setTimeZone(TimeZone.getDefault());
228 time.setConverter(dateTimeConverter);
229 } else {
230 timePanel.setRendered(false);
231 }
232 }
233
234 @Override
235 public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
236 UIDatePicker link = (UIDatePicker) component;
237 UIDate dateInput = (UIDate) link.getForComponent();
238 if (dateInput != null) {
239 super.encodeEnd(facesContext, component);
240 } else {
241 LOG.error("The required UIDate component wasn't found for component id='" + component.getId());
242 }
243 }
244 }