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