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