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_ONCLICK;
021    import static org.apache.myfaces.tobago.TobagoConstants.ATTR_HEIGHT;
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      public int getFixedHeight(FacesContext facesContext, UIComponent component) {
091        return getFixedSpace(facesContext, component, false);
092      }
093      public int getFixedSpace(FacesContext facesContext, UIComponent component, boolean width) {
094    
095        int fixedSpace = 0;
096    
097        if (component instanceof UICell) {
098          List children = LayoutUtil.addChildren(new ArrayList(), component);
099          for (Object aChildren : children) {
100            UIComponent child = (UIComponent) aChildren;
101    
102            LayoutInformationProvider renderer = ComponentUtil.getRenderer(facesContext, child);
103            if (renderer != null) {
104              if (width) {
105                fixedSpace = Math.max(fixedSpace, renderer.getFixedWidth(facesContext, child));
106              } else {
107                fixedSpace = Math.max(fixedSpace, renderer.getFixedHeight(facesContext, child));
108              }
109            }
110          }
111        } else {
112          if (width) {
113            fixedSpace = getFixedSpace(facesContext, component, ATTR_WIDTH, "fixedWidth");
114          } else {
115            fixedSpace = getFixedSpace(facesContext, component, ATTR_HEIGHT, "fixedHeight");
116          }
117        }
118        return fixedSpace;
119      }
120    
121      private int getFixedSpace(FacesContext facesContext, UIComponent component,
122                                String attr, String attrFixed) {
123        int intSpace = -1;
124        String space = null;
125        if (component != null) {
126          space = ComponentUtil.getStringAttribute(component, attr);
127        }
128        if (space != null) {
129          try {
130            intSpace = Integer.parseInt(space.replaceAll("\\D", ""));
131          } catch (NumberFormatException e) {
132            LOG.error("Catched: " + e.getMessage(), e);
133          }
134        }
135        if (intSpace == -1) {
136          return getConfiguredValue(facesContext, component, attrFixed);
137        } else {
138          return intSpace;
139        }
140      }
141    
142      protected void checkForCommandFacet(UIComponent component, FacesContext facesContext, TobagoResponseWriter writer)
143          throws IOException {
144        checkForCommandFacet(component, Arrays.asList(component.getClientId(facesContext)) , facesContext, writer);
145      }
146    
147      protected void checkForCommandFacet(UIComponent component, List<String> clientIds, FacesContext facesContext,
148          TobagoResponseWriter writer) throws IOException {
149        Map<String, UIComponent> facets = component.getFacets();
150        for (Map.Entry<String, UIComponent> entry: facets.entrySet()) {
151          if (entry.getValue() instanceof UICommand) {
152            addCommandFacet(clientIds, entry, facesContext, writer);
153          }
154        }
155      }
156    
157      // TODO create HtmlRendererBase
158      private void addCommandFacet(List<String> clientIds, Map.Entry<String, UIComponent> facetEntry,
159          FacesContext facesContext, TobagoResponseWriter writer) throws
160          IOException {
161        for (String clientId: clientIds) {
162          writeScriptForClientId(clientId, facetEntry, facesContext, writer);
163        }
164      }
165    
166      private void writeScriptForClientId(String clientId, Map.Entry<String, UIComponent> facetEntry,
167          FacesContext facesContext, TobagoResponseWriter writer) throws IOException {
168        if (facetEntry.getValue() instanceof UICommand
169            && ((UICommand) facetEntry.getValue()).getRenderedPartially().length > 0) {
170          String script =
171              "var element = Tobago.element(\"" + clientId  + "\");\n"
172                  + "if (element) {\n"
173                  + "   Tobago.addEventListener(element, \"" + facetEntry.getKey()
174                  + "\", function(){Tobago.reloadComponent('"
175                  + HtmlRendererUtil.getComponentId(facesContext, facetEntry.getValue(), 
176                  ((UICommand) facetEntry.getValue()).getRenderedPartially()[0]) + "','"
177                  + facetEntry.getValue().getClientId(facesContext)  + "', {})});\n"
178                  + "}";
179          writer.writeJavascript(script);
180        } else {
181          UIComponent facetComponent = facetEntry.getValue();
182          String facetAction = (String) facetComponent.getAttributes().get(ATTR_ONCLICK);
183          if (facetAction == null) {
184            facetAction = "Tobago.submitAction('" + facetComponent.getClientId(facesContext) + "')";
185          }
186          String script =
187              "var element = Tobago.element(\"" + clientId  + "\");\n"
188                  + "if (element) {\n"
189                  + "   Tobago.addEventListener(element, \"" + facetEntry.getKey() + "\", function(){"
190                  + facetAction + "});\n}";
191          writer.writeJavascript(script);
192        }
193      }
194    }