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.internal.layout;
21  
22  import org.apache.myfaces.tobago.internal.util.StringUtils;
23  import org.apache.myfaces.tobago.internal.component.AbstractUIGridLayout;
24  import org.apache.myfaces.tobago.layout.LayoutBase;
25  import org.apache.myfaces.tobago.layout.LayoutContainer;
26  import org.apache.myfaces.tobago.layout.LayoutManager;
27  import org.apache.myfaces.tobago.layout.Orientation;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  import javax.faces.component.UIComponent;
32  import javax.faces.context.FacesContext;
33  import java.text.DecimalFormat;
34  
35  /*
36  An algorithm for laying out ...
37  
38  - get UIPage
39    - call compute-sizes
40      - get the LayoutManager
41        - go to the PX elements
42          - call compute-sizes (recursively)
43        - go to the Auto elements
44          - call compute-sizes (recursively)
45          - compute the max size of the elements and set it to the row/column
46        - check given size: if not set: warn
47        - calculate remainder = given size - all px sizes - all auto sizes
48        - go to the * elements
49          - partition remainder to this elements (3*;2*)
50          - call compute-sizes (recursively)
51    - call set-positions
52        - compute and set positions of columns/rows
53        - call set-positions for all elements (recursively)
54  
55  todo: describe what happens, when there is a rendered=false (if all in one bank than collapse)
56  todo: describe what happens, when there are too less components (there a free space)
57  todo: describe what happens, when there are too much components (there a rows with * added)
58   */
59  public class LayoutContext {
60  
61    private static final Logger LOG = LoggerFactory.getLogger(LayoutContext.class);
62  
63    private LayoutContainer container;
64  
65    public LayoutContext(LayoutContainer container) {
66      this.container = container;
67    }
68  
69    public void layout() {
70  
71      long begin = 0;
72      final boolean debug = LOG.isDebugEnabled();
73      final boolean trace = LOG.isTraceEnabled();
74      if (debug) {
75        begin = System.nanoTime();
76      }
77  
78      LayoutManager layoutManager = container.getLayoutManager();
79      layoutManager.init();
80      if (trace) {
81        log("after init", true);
82      }
83      layoutManager.fixRelativeInsideAuto(Orientation.VERTICAL, false);
84      if (trace) {
85        log("after fixRelativeInsideAuto vertical", true);
86      }
87      layoutManager.fixRelativeInsideAuto(Orientation.HORIZONTAL, false);
88      if (trace) {
89        log("after fixRelativeInsideAuto horizontal", true);
90      }
91      layoutManager.preProcessing(Orientation.VERTICAL);
92      if (trace) {
93        log("after preProcessing vertical", true);
94      }
95      layoutManager.preProcessing(Orientation.HORIZONTAL);
96      if (trace) {
97        log("after preProcessing horizontal", true);
98      }
99      layoutManager.mainProcessing(Orientation.VERTICAL);
100     if (trace) {
101       log("after mainProcessing vertical", true);
102     }
103     layoutManager.mainProcessing(Orientation.HORIZONTAL);
104     if (trace) {
105       log("after mainProcessing horizontal", true);
106     }
107     layoutManager.postProcessing(Orientation.VERTICAL);
108     if (trace) {
109       log("after postProcessing vertical", true);
110     }
111     layoutManager.postProcessing(Orientation.HORIZONTAL);
112     if (trace) {
113       log("after postProcessing horizontal", true);
114     }
115 
116     if (debug) {
117       LOG.debug("Laying out takes: {} ns", new DecimalFormat("#,##0").format(System.nanoTime() - begin));
118       log("after layout", false);
119     }
120   }
121 
122   private void log(String message, boolean trace) {
123     StringBuffer buffer = new StringBuffer(message + "\n");
124     log(buffer, (UIComponent) container, 0);
125     if (trace) {
126       LOG.trace(buffer.toString());
127     } else {
128       LOG.debug(buffer.toString());
129     }
130   }
131 
132   private void log(StringBuffer buffer, UIComponent component, int depth) {
133     FacesContext facesContext = FacesContext.getCurrentInstance();
134     buffer.append(StringUtils.repeat("  ", depth));
135     buffer.append(component.getClass().getSimpleName());
136     buffer.append("#");
137     buffer.append(component.getClientId(facesContext));
138     if (component instanceof LayoutBase) {
139       buffer.append("(");
140       buffer.append(((LayoutBase) component).getCurrentWidth());
141       buffer.append(", ");
142       buffer.append(((LayoutBase) component).getCurrentHeight());
143       buffer.append(")");
144     }
145     if (component instanceof LayoutContainer) {
146       LayoutManager layoutManager = ((LayoutContainer) component).getLayoutManager();
147       if (layoutManager instanceof AbstractUIGridLayout) {
148         buffer.append("\n");
149         buffer.append(StringUtils.repeat("  ", depth + 4));
150         buffer.append("layout: ");
151         buffer.append(((AbstractUIGridLayout) layoutManager).toString(depth));
152       }
153     }
154     buffer.append("\n");
155     for (UIComponent child : component.getChildren()) {
156       log(buffer, child, depth + 2);
157     }
158   }
159 }