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.scarborough.standard.tag;
21  
22  import org.apache.myfaces.tobago.internal.component.AbstractUISplitLayout;
23  import org.apache.myfaces.tobago.internal.layout.LayoutUtils;
24  import org.apache.myfaces.tobago.renderkit.css.Style;
25  import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
26  import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
27  import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
28  import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
29  import org.apache.myfaces.tobago.renderkit.html.MarkupLanguageAttributes;
30  import org.apache.myfaces.tobago.renderkit.html.standard.standard.tag.GridLayoutRenderer;
31  import org.apache.myfaces.tobago.renderkit.util.RenderUtils;
32  import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  import javax.faces.component.UIComponent;
37  import javax.faces.context.FacesContext;
38  import java.io.IOException;
39  import java.util.List;
40  import java.util.Map;
41  
42  public class SplitLayoutRenderer extends GridLayoutRenderer {
43  
44    private static final Logger LOG = LoggerFactory.getLogger(SplitLayoutRenderer.class);
45    private static final String POSITION_ID_POSTFIX = "_spLP";
46  
47    // todo: put as enum to DataAttributes, when moved from sandbox to core
48    private static final MarkupLanguageAttributes SPLIT_LAYOUT = DataAttributes.dynamic("tobago-split-layout");
49  
50    // todo: put as enum to DataAttributes, when moved from sandbox to core
51    private static final MarkupLanguageAttributes SPLIT_LAYOUT_CONTAINMENT
52        = DataAttributes.dynamic("data-tobago-split-layout-containment");
53  
54    @Override
55    public void decode(final FacesContext facesContext, final UIComponent component) {
56      final String sourceId = facesContext.getExternalContext().getRequestParameterMap().get("javax.faces.source");
57      final String clientId = component.getClientId();
58      if (clientId.equals(sourceId)) {
59        // only decode and update layout at resize request
60        final Map<String, String> parameterMap = facesContext.getExternalContext().getRequestParameterMap();
61        final String position = parameterMap.get(clientId + POSITION_ID_POSTFIX);
62        ((AbstractUISplitLayout) component).updateLayout(Integer.parseInt(position));
63      }
64    }
65  
66    @Override
67    public void encodeChildren(final FacesContext facesContext, final UIComponent component) throws IOException {
68      final UIComponent parent = component.getParent();
69      if (parent.isRendered()) {
70        final List<UIComponent> components = LayoutUtils.findLayoutChildren(parent);
71        if (components.size() != 2) {
72          LOG.warn("Illegal component count in splitLayout: {}", components.size());
73        }
74        RenderUtils.encode(facesContext, components.get(0));
75        RenderUtils.encode(facesContext, components.get(1));
76        if (components.get(0).isRendered() && components.get(1).isRendered()) {
77          // only when both components are rendered
78          encodeHandle(facesContext, (AbstractUISplitLayout) component);
79        }
80      }
81    }
82  
83    protected void encodeHandle(final FacesContext facesContext, final AbstractUISplitLayout layout) throws IOException {
84      final String id = layout.getClientId(facesContext);
85  
86      final TobagoResponseWriter writer = getResponseWriter(facesContext);
87      writer.startElement(HtmlElements.SPAN);
88      writer.writeIdAttribute(id);
89      writer.writeAttribute(SPLIT_LAYOUT, layout.getOrientation().name(), false);
90      writer.writeAttribute(SPLIT_LAYOUT_CONTAINMENT, createDraggableContainment(layout), true);
91  /* XXX todo not implemented currently
92      final Style style = calculateHandleStyle(layout);
93      writer.writeStyleAttribute(style);
94      writer.writeClassAttribute(Classes.create(layout, layout.getOrientation().name()));
95  
96      final int position;
97      if (layout.getOrientation() == Orientation.horizontal) {
98        position = style.getLeft().getPixel();
99      } else {
100       position = style.getTop().getPixel();
101     }
102 */
103     writer.startElement(HtmlElements.INPUT);
104     writer.writeIdAttribute(id + POSITION_ID_POSTFIX);
105     writer.writeNameAttribute(id + POSITION_ID_POSTFIX);
106     writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
107 //    writer.writeAttribute(HtmlAttributes.value, Integer.toString(position), false);
108     writer.endElement(HtmlElements.INPUT);
109     writer.endElement(HtmlElements.SPAN);
110   }
111 
112   private String createDraggableContainment(final AbstractUISplitLayout layout) {
113 /* XXX todo not implemented currently
114     final UIComponent parent = layout.getParent();
115     final LayoutContainer container = (LayoutContainer) parent;
116     final List<UIComponent> components = LayoutUtils.findLayoutChildren(parent);
117     final Style firstComponent = ((Visual) components.get(0)).getStyle();
118     final Style secondComponent = ((Visual) components.get(1)).getStyle();
119 
120     Measure minimum;
121 
122     if (layout.getOrientation() == Orientation.horizontal) {
123       minimum = firstComponent.getMinWidth();
124       final int minimumSize1 = minimum != null ? minimum.getPixel() : 0;
125       minimum = secondComponent.getMinWidth();
126       final int minimumSize2 = minimum != null ? minimum.getPixel() : 0;
127       final int totalSize = container.getWidth().getPixel();
128       return "[" + minimumSize1 + ", 0, " + (totalSize - minimumSize2) + ", 0]";
129     } else {
130       minimum = firstComponent.getMinHeight();
131       final int minimumSize1 = minimum != null ? minimum.getPixel() : 0;
132       minimum = secondComponent.getMinHeight();
133       final int minimumSize2 = minimum != null ? minimum.getPixel() : 0;
134       final int totalSize = container.getHeight().getPixel();
135       return "[0, " + minimumSize1 + ", 0, " + (totalSize - minimumSize2) + "]";
136     }
137 */
138     return "";
139   }
140 
141   private Style calculateHandleStyle(final AbstractUISplitLayout layout) {
142 /* XXX todo not implemented currently
143     final UIComponent parent = layout.getParent();
144     final LayoutContainer container = (LayoutContainer) parent;
145     final LayoutComponent secondComponent = (LayoutComponent) LayoutUtils.findLayoutChildren(parent).get(1);
146     final Style style = new Style();
147 
148     if (layout.getOrientation() == Orientation.horizontal) {
149       style.setWidth(Measure.valueOf(5));
150       style.setHeight(container.getCurrentHeight());
151       style.setLeft(Measure.valueOf(secondComponent.getLeft().subtract(5)));
152       style.setTop(Measure.valueOf(0));
153     } else {
154       style.setWidth(container.getCurrentWidth());
155       style.setHeight(Measure.valueOf(5));
156       style.setLeft(Measure.valueOf(0));
157       style.setTop(Measure.valueOf(Measure.valueOf(secondComponent.getTop().subtract(5))));
158     }
159     // todo: use CSS class
160     style.setDisplay(Display.block);
161     style.setPosition(Position.absolute);
162     return style;
163 */
164     return null;
165   }
166 }