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