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.renderkit; 021 022 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_HEIGHT; 023 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_ONCLICK; 024 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_WIDTH; 025 import static org.apache.myfaces.tobago.TobagoConstants.FACET_MENUBAR; 026 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_READONLY; 027 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_DISABLED; 028 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_TRANSITION; 029 030 import org.apache.commons.lang.StringUtils; 031 import org.apache.myfaces.tobago.component.ComponentUtil; 032 import org.apache.myfaces.tobago.component.UICell; 033 import org.apache.myfaces.tobago.component.UICommand; 034 import org.apache.myfaces.tobago.renderkit.html.HtmlRendererUtil; 035 import org.apache.myfaces.tobago.util.LayoutUtil; 036 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter; 037 038 import javax.faces.component.UIComponent; 039 import javax.faces.context.FacesContext; 040 import java.awt.Dimension; 041 import java.io.IOException; 042 import java.util.ArrayList; 043 import java.util.Arrays; 044 import java.util.List; 045 import java.util.Map; 046 047 public abstract class LayoutableRendererBase 048 extends RendererBase implements LayoutInformationProvider { 049 050 public int getHeaderHeight( 051 FacesContext facesContext, UIComponent component) { 052 int height = getConfiguredValue(facesContext, component, "headerHeight"); 053 final UIComponent menubar = component.getFacet(FACET_MENUBAR); 054 if (menubar != null) { 055 height += getConfiguredValue(facesContext, menubar, "headerHeight"); 056 } 057 return height; 058 } 059 060 public int getPaddingWidth(FacesContext facesContext, UIComponent component) { 061 return getConfiguredValue(facesContext, component, "paddingWidth"); 062 } 063 064 public int getPaddingHeight( 065 FacesContext facesContext, UIComponent component) { 066 return getConfiguredValue(facesContext, component, "paddingHeight"); 067 } 068 069 public int getComponentExtraWidth( 070 FacesContext facesContext, 071 UIComponent component) { 072 return getConfiguredValue(facesContext, component, "componentExtraWidth"); 073 } 074 075 public int getComponentExtraHeight( 076 FacesContext facesContext, 077 UIComponent component) { 078 return getConfiguredValue(facesContext, component, "componentExtraHeight"); 079 } 080 081 public Dimension getMinimumSize( 082 FacesContext facesContext, UIComponent component) { 083 int width = getConfiguredValue(facesContext, component, "minimumWidth"); 084 if (width == -1) { 085 width = getConfiguredValue(facesContext, component, "fixedWidth"); 086 } 087 int height = getConfiguredValue(facesContext, component, "minimumHeight"); 088 if (height == -1) { 089 height = getConfiguredValue(facesContext, component, "fixedHeight"); 090 } 091 return new Dimension(width, height); 092 } 093 094 public int getFixedWidth(FacesContext facesContext, UIComponent component) { 095 return getFixedSpace(facesContext, component, true); 096 } 097 098 public int getFixedHeight(FacesContext facesContext, UIComponent component) { 099 return getFixedSpace(facesContext, component, false); 100 } 101 102 public int getFixedSpace(FacesContext facesContext, UIComponent component, boolean width) { 103 104 int fixedSpace = 0; 105 106 if (component instanceof UICell) { 107 List children = LayoutUtil.addChildren(new ArrayList(), component); 108 for (Object aChildren : children) { 109 UIComponent child = (UIComponent) aChildren; 110 111 LayoutInformationProvider renderer = ComponentUtil.getRenderer(facesContext, child); 112 if (renderer != null) { 113 if (width) { 114 fixedSpace = Math.max(fixedSpace, renderer.getFixedWidth(facesContext, child)); 115 } else { 116 fixedSpace = Math.max(fixedSpace, renderer.getFixedHeight(facesContext, child)); 117 } 118 } 119 } 120 } else { 121 if (width) { 122 fixedSpace = getFixedSpace(facesContext, component, ATTR_WIDTH, "fixedWidth"); 123 } else { 124 fixedSpace = getFixedSpace(facesContext, component, ATTR_HEIGHT, "fixedHeight"); 125 } 126 } 127 return fixedSpace; 128 } 129 130 private int getFixedSpace(FacesContext facesContext, UIComponent component, 131 String attr, String attrFixed) { 132 int intSpace = -1; 133 String space = null; 134 if (component != null) { 135 space = ComponentUtil.getStringAttribute(component, attr); 136 } 137 if (space != null) { 138 try { 139 intSpace = Integer.parseInt(LayoutUtil.stripNonNumericChars(space)); 140 } catch (NumberFormatException e) { 141 LOG.error("Caught: " + e.getMessage(), e); 142 } 143 } 144 if (intSpace == -1) { 145 return getConfiguredValue(facesContext, component, attrFixed); 146 } else { 147 return intSpace; 148 } 149 } 150 151 protected void checkForCommandFacet(UIComponent component, FacesContext facesContext, TobagoResponseWriter writer) 152 throws IOException { 153 checkForCommandFacet(component, Arrays.asList(component.getClientId(facesContext)), facesContext, writer); 154 } 155 156 protected void checkForCommandFacet(UIComponent component, List<String> clientIds, FacesContext facesContext, 157 TobagoResponseWriter writer) throws IOException { 158 if (ComponentUtil.getBooleanAttribute(component, ATTR_READONLY) 159 || ComponentUtil.getBooleanAttribute(component, ATTR_DISABLED)) { 160 // skip if readonly 161 return; 162 } 163 Map<String, UIComponent> facets = component.getFacets(); 164 for (Map.Entry<String, UIComponent> entry : facets.entrySet()) { 165 if (entry.getValue() instanceof UICommand) { 166 addCommandFacet(clientIds, entry, facesContext, writer); 167 } 168 } 169 } 170 171 // TODO create HtmlRendererBase 172 private void addCommandFacet(List<String> clientIds, Map.Entry<String, UIComponent> facetEntry, 173 FacesContext facesContext, TobagoResponseWriter writer) throws 174 IOException { 175 for (String clientId : clientIds) { 176 writeScriptForClientId(clientId, facetEntry, facesContext, writer); 177 } 178 } 179 180 private void writeScriptForClientId(String clientId, Map.Entry<String, UIComponent> facetEntry, 181 FacesContext facesContext, TobagoResponseWriter writer) throws IOException { 182 if (facetEntry.getValue() instanceof UICommand 183 && ((UICommand) facetEntry.getValue()).getRenderedPartially().length > 0) { 184 String script = 185 "var element = Tobago.element(\"" + clientId + "\");\n" 186 + "if (element) {\n" 187 + " Tobago.addEventListener(element, \"" + facetEntry.getKey() 188 + "\", function(){Tobago.reloadComponent2(this, '" 189 + HtmlRendererUtil.getComponentId(facesContext, facetEntry.getValue(), 190 ((UICommand) facetEntry.getValue()).getRenderedPartially()[0]) + "','" 191 + facetEntry.getValue().getClientId(facesContext) + "', {})});\n" 192 + "}"; 193 writer.writeJavascript(script); 194 } else { 195 UIComponent facetComponent = facetEntry.getValue(); 196 String facetAction = (String) facetComponent.getAttributes().get(ATTR_ONCLICK); 197 if (facetAction == null) { 198 facetAction = "Tobago.submitAction2(this, '" + facetComponent.getClientId(facesContext) + "', " 199 + ComponentUtil.getBooleanAttribute(facetComponent, ATTR_TRANSITION) + ", null, '" + clientId +"')"; 200 } else { 201 // Replace @autoId 202 facetAction = StringUtils.replace(facetAction, "@autoId", facetComponent.getClientId(facesContext)); 203 } 204 String script = 205 "var element = Tobago.element(\"" + clientId + "\");\n" 206 + "if (element) {\n" 207 + " Tobago.addEventListener(element, \"" + facetEntry.getKey() + "\", function(){" 208 + facetAction + "});\n}"; 209 writer.writeJavascript(script); 210 } 211 } 212 }