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