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