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     renderBoxHeader(facesContext, writer, box);
120 
121     final UIMenuBar menuBar = ComponentUtils.findFacetDescendant(box, Facets.MENUBAR, UIMenuBar.class);
122     if (menuBar != null) {
123       RenderUtils.encode(facesContext, menuBar);
124     }
125 
126     final UIPanel toolbar = (UIPanel) box.getFacet(Facets.TOOL_BAR);
127     if (toolbar != null) {
128       renderToolbar(facesContext, writer, box, toolbar);
129     }
130     
131     if (hasShadow) {
132       // border end
133       writer.endElement(HtmlElements.DIV);
134       // shadow end
135       writer.endElement(HtmlElements.DIV);
136     }
137 
138     writer.startElement(HtmlElements.DIV, null);
139     writer.writeClassAttribute(Classes.create(box, "content")); // needed to be scrollable inside of the box
140     final Style style = new Style(facesContext, box);
141     final Measure borderLeft = box.getBorderLeft();
142     final Measure borderRight = box.getBorderRight();
143     final Measure borderTop = box.getBorderTop();
144     final Measure borderBottom = box.getBorderBottom();
145     style.setWidth(style.getWidth().subtract(borderLeft).subtract(borderRight));
146     style.setHeight(style.getHeight().subtract(borderTop).subtract(borderBottom));
147     style.setLeft(borderLeft);
148     style.setTop(borderTop);
149     writer.writeStyleAttribute(style);
150   }
151 
152   protected void renderBoxHeader(FacesContext facesContext, TobagoResponseWriter writer, UIComponent box)
153       throws IOException {
154     final UIComponent label = box.getFacet(Facets.LABEL);
155     writer.startElement(HtmlElements.DIV, null);
156     writer.writeClassAttribute(Classes.create(box, "header"));
157     final String labelString = (String) box.getAttributes().get(Attributes.LABEL);
158     if (label != null) {
159       RenderUtils.encode(facesContext, label);
160     } else if (labelString != null) {
161       writer.writeText(labelString);
162     }
163     writer.endElement(HtmlElements.DIV);
164   }
165 
166   @Override
167   public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
168     final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
169     writer.endElement(HtmlElements.DIV);
170     writer.endElement(HtmlElements.DIV);
171   }
172 
173   protected void renderToolbar(
174       final FacesContext facesContext, final TobagoResponseWriter writer, final UIBox box, final UIPanel toolbar)
175       throws IOException {
176     writer.startElement(HtmlElements.DIV, null);
177     writer.writeClassAttribute(Classes.create(box, "headerToolBar"));
178     toolbar.setRendererType(RendererTypes.BOX_TOOL_BAR);
179     RenderUtils.encode(facesContext, toolbar);
180     writer.endElement(HtmlElements.DIV);
181   }
182 }