View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.renderkit.html.speyside.standard.tag;
21  
22  import org.apache.myfaces.tobago.component.Attributes;
23  import org.apache.myfaces.tobago.component.Facets;
24  import org.apache.myfaces.tobago.component.RendererTypes;
25  import org.apache.myfaces.tobago.component.UIBox;
26  import org.apache.myfaces.tobago.component.UIMenuBar;
27  import org.apache.myfaces.tobago.layout.Measure;
28  import org.apache.myfaces.tobago.renderkit.BoxRendererBase;
29  import org.apache.myfaces.tobago.renderkit.css.Classes;
30  import org.apache.myfaces.tobago.renderkit.css.Style;
31  import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
32  import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
33  import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils;
34  import org.apache.myfaces.tobago.renderkit.util.RenderUtils;
35  import org.apache.myfaces.tobago.util.ComponentUtils;
36  import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
37  
38  import javax.faces.component.UIComponent;
39  import javax.faces.component.UIPanel;
40  import javax.faces.context.FacesContext;
41  import java.io.IOException;
42  
43  public class BoxRenderer extends BoxRendererBase {
44  
45    /*
46    
47  with shadow
48    
49  <div class="tobago-box" style="width: 100px; height: 100px">
50    <div class="tobago-box-shadow" style="width: 99px; height: 99px">
51      <div class="tobago-box-border" style="width: 97px; height: 97px">
52        <div class="tobago-box-header">Label</div>
53      </div>
54    </div>
55  
56    <div style="position: absolute; top: 26px; left: 6px; width: 87px; height: 67px; background-color: blue;">
57      Content
58    </div>
59  </div>
60  
61  without shadow
62  
63  <div class="tobago-box" style="width: 100px; height: 100px">
64    <span class="tobago-box-header">Label</span>
65  
66    <div style="position: absolute; top: 26px; left: 6px; width: 87px; height: 67px; background-color: blue;">
67      Content
68    </div>
69  </div>
70  
71     */
72    @Override
73    public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
74  
75      final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
76      final UIBox box = (UIBox) component;
77  
78      final String clientId = box.getClientId(facesContext);
79      writer.startElement(HtmlElements.DIV, box);
80      writer.writeClassAttribute(Classes.create(box));
81      writer.writeIdAttribute(clientId);
82      final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, box);
83      if (title != null) {
84        writer.writeAttribute(HtmlAttributes.TITLE, title, true);
85      }
86      HtmlRendererUtils.writeDataAttributes(facesContext, writer, box);
87      writer.writeStyleAttribute(new Style(facesContext, box));
88      encodeBox(facesContext, writer, box);
89    }
90  
91    private void encodeBox(final FacesContext facesContext, final TobagoResponseWriter writer, final UIBox box)
92        throws IOException {
93  
94      // todo: shadow = 0px means, that shadow is disabled, but it may be better, if we can set a boolean in the config.
95      // todo: this is possible after fixing 
96      final Measure measure = getResourceManager().getThemeMeasure(facesContext, box, "shadow");
97      final boolean hasShadow = measure.greaterThan(Measure.ZERO);
98  
99      if (hasShadow) {
100       // shadow begin
101       writer.startElement(HtmlElements.DIV, box);
102       writer.writeClassAttribute(Classes.create(box, "shadow"));
103 
104       final Style shadow = new Style();
105       shadow.setWidth(box.getCurrentWidth().subtract(1));
106       shadow.setHeight(box.getCurrentHeight().subtract(1));
107       writer.writeStyleAttribute(shadow);
108 
109       // border begin
110       writer.startElement(HtmlElements.DIV, box);
111       writer.writeClassAttribute(Classes.create(box, "border"));
112 
113       final Style border = new Style();
114       border.setWidth(box.getCurrentWidth().subtract(3));
115       border.setHeight(box.getCurrentHeight().subtract(3));
116       writer.writeStyleAttribute(border);
117     }
118 
119     final UIComponent label = box.getFacet(Facets.LABEL);
120     writer.startElement(HtmlElements.DIV, null);
121     writer.writeClassAttribute(Classes.create(box, "header"));
122     final String labelString = (String) box.getAttributes().get(Attributes.LABEL);
123     if (label != null) {
124       RenderUtils.encode(facesContext, label);
125     } else if (labelString != null) {
126       writer.writeText(labelString);
127     }
128     writer.endElement(HtmlElements.DIV);
129 
130     final UIMenuBar menuBar = ComponentUtils.findFacetDescendant(box, Facets.MENUBAR, UIMenuBar.class);
131     if (menuBar != null) {
132       RenderUtils.encode(facesContext, menuBar);
133     }
134 
135     final UIPanel toolbar = (UIPanel) box.getFacet(Facets.TOOL_BAR);
136     if (toolbar != null) {
137       renderToolbar(facesContext, writer, box, toolbar);
138     }
139     
140     if (hasShadow) {
141       // border end
142       writer.endElement(HtmlElements.DIV);
143       // shadow end
144       writer.endElement(HtmlElements.DIV);
145     }
146 
147     writer.startElement(HtmlElements.DIV, null);
148     writer.writeClassAttribute(Classes.create(box, "content")); // needed to be scrollable inside of the box
149     final Style style = new Style(facesContext, box);
150     final Measure borderLeft = box.getBorderLeft();
151     final Measure borderRight = box.getBorderRight();
152     final Measure borderTop = box.getBorderTop();
153     final Measure borderBottom = box.getBorderBottom();
154     style.setWidth(style.getWidth().subtract(borderLeft).subtract(borderRight));
155     style.setHeight(style.getHeight().subtract(borderTop).subtract(borderBottom));
156     style.setLeft(borderLeft);
157     style.setTop(borderTop);
158     writer.writeStyleAttribute(style);
159   }
160 
161   @Override
162   public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
163     final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
164     writer.endElement(HtmlElements.DIV);
165     writer.endElement(HtmlElements.DIV);
166   }
167 
168   protected void renderToolbar(
169       final FacesContext facesContext, final TobagoResponseWriter writer, final UIBox box, final UIPanel toolbar)
170       throws IOException {
171     writer.startElement(HtmlElements.DIV, null);
172     writer.writeClassAttribute(Classes.create(box, "headerToolBar"));
173     toolbar.setRendererType(RendererTypes.BOX_TOOL_BAR);
174     RenderUtils.encode(facesContext, toolbar);
175     writer.endElement(HtmlElements.DIV);
176   }
177 }