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 }