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 }