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.layout.Measure;
23  import org.apache.myfaces.tobago.layout.MeasureList;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  
27  import java.util.ArrayList;
28  import java.util.List;
29  
30  /**
31   * @deprecated since 4.0.0
32   */
33  @Deprecated
34  public class Grid {
35  
36    private static final Logger LOG = LoggerFactory.getLogger(Grid.class);
37  
38    // TODO: check if it is faster with arrays.
39    /**
40     * The rectangular data as a 1-dim list
41     */
42    private List<Cell> cells;
43  
44    private MeasureList columns;
45    private MeasureList rows;
46  
47    private int columnCount;
48    private int rowCount;
49  
50    private int columnCursor;
51    private int rowCursor;
52  
53    private List<Integer> errorIndexes;
54  
55    public Grid(final MeasureList columns, final MeasureList rows) {
56      assert columns.getSize() > 0;
57      assert rows.getSize() > 0;
58  
59      this.columnCount = columns.getSize();
60      this.rowCount = rows.getSize();
61  
62      this.columns = columns;
63      this.rows = rows;
64  
65      final int size = columnCount * rowCount;
66      this.cells = new ArrayList<>(size);
67      for (int i = 0; i < size; i++) {
68        this.cells.add(null);
69      }
70    }
71  
72    public void add(final OriginCell cell, final int columnSpan, final int rowSpan) {
73  
74      assert columnSpan > 0;
75      assert rowSpan > 0;
76  
77      int iterator = columnSpan;
78      boolean error = false;
79  
80      if (iterator + columnCursor > columnCount) {
81        LOG.warn("The columnSpan is to large for the actual position in the grid. Will be fixed. "
82            + "columnSpan='" + iterator + "' columnCursor='" + columnCursor + "' columnCount='" + columnCount + "'");
83        iterator = columnCount - columnCursor;
84        error = true;
85      }
86  
87      cell.setColumnSpan(iterator);
88      cell.setRowSpan(rowSpan);
89  
90      for (int i = 1; i < iterator; i++) {
91        if (getCell(i + columnCursor, rowCursor) != null) {
92          LOG.warn("The columnSpan is to large for the actual position in the grid. Will be fixed. "
93              + "columnSpan='" + iterator + "' columnCursor='" + columnCursor + "' columnCount='" + columnCount + "'");
94          iterator = i - 1;
95          error = true;
96        }
97      }
98  
99      for (int j = 0; j < rowSpan; j++) {
100       for (int i = 0; i < iterator; i++) {
101         final Cell actualCell;
102         if (i == 0 && j == 0) {
103           actualCell = cell;
104         } else {
105           actualCell = new SpanCell(cell, i == 0, j == 0);
106         }
107         assert getCell(i + columnCursor, j + rowCursor) == null : "Position in the cell must be free.";
108         setCell(i + columnCursor, j + rowCursor, actualCell);
109         if (error) {
110           addError(i + columnCursor, j + rowCursor);
111         }
112       }
113     }
114 
115     findNextFreeCell();
116   }
117 
118   public Cell getCell(final int column, final int row) {
119     assert column >= 0 && column < columnCount : "column=" + column + " columnCount=" + columnCount;
120     assert row >= 0 : "row=" + row;
121 
122     if (row >= rowCount) {
123       return null;
124     } else {
125       return cells.get(column + row * columnCount);
126     }
127   }
128 
129   public void setCell(final int column, final int row, final Cell cell) {
130     if (row >= rowCount) {
131       enlarge(row - rowCount + 1);
132     }
133     cells.set(column + row * columnCount, cell);
134   }
135 
136   private void findNextFreeCell() {
137     for (; rowCursor < rowCount; rowCursor++) {
138       for (; columnCursor < columnCount; columnCursor++) {
139         if (getCell(columnCursor, rowCursor) == null) {
140           return;
141         }
142       }
143       columnCursor = 0;
144     }
145   }
146 
147   protected MeasureList getColumns() {
148     return columns;
149   }
150 
151   protected MeasureList getRows() {
152     return rows;
153   }
154 
155   private void enlarge(final int newRows) {
156 
157     // process cells
158     for (int i = 0; i < newRows; i++) {
159       for (int j = 0; j < columnCount; j++) {
160         cells.add(null);
161       }
162     }
163 
164     // process heads
165     for (int i = rowCount; i < rowCount + newRows; i++) {
166       rows.add(Measure.FRACTION1);
167     }
168 
169     rowCount += newRows;
170   }
171 
172   public void addError(final int i, final int j) {
173     if (errorIndexes == null) {
174       errorIndexes = new ArrayList<>();
175     }
176     errorIndexes.add(j * columnCount + i);
177   }
178 
179   public boolean hasError(final int i, final int j) {
180     if (errorIndexes == null) {
181       return false;
182     }
183     return errorIndexes.contains(j * columnCount + i);
184   }
185 
186   public int getColumnCount() {
187     return columnCount;
188   }
189 
190   public int getRowCount() {
191     return rowCount;
192   }
193 
194   /**
195    * Prints the state of the grid as an Unicode shape like this:
196    * ┏━┳━┳━┳━┯━┓
197    * ┃█┃█┃█┃█│➞┃
198    * ┠─╂─╊━╇━┿━┫
199    * ┃⬇┃⬇┃█│➞│➞┃
200    * ┣━╉─╊━╈━╈━┫
201    * ┃█┃⬇┃█┃█┃█┃
202    * ┣━╇━╇━╉─╊━┩
203    * ┃█│➞│➞┃⬇┃◌│
204    * ┡━┿━┿━╉─╂─┤
205    * │◌│◌│◌┃⬇┃◌│
206    * └─┴─┴─┺━┹─┘
207    */
208   public String gridAsString() {
209 
210     final StringBuilder builder = new StringBuilder();
211 
212     // top of grid
213     for (int i = 0; i < columnCount; i++) {
214       if (i == 0) {
215         if (getCell(i, 0) != null) {
216           builder.append("┏");
217         } else {
218           builder.append("┌");
219         }
220       } else {
221         final Cell c = getCell(i - 1, 0);
222         final Cell d = getCell(i, 0);
223         if (c == null && d == null) {
224           builder.append("┬");
225         } else {
226           if (connected(c, d)) {
227             builder.append("┯");
228           } else {
229             if (c == null) {
230               builder.append("┲");
231             } else if (d == null) {
232               builder.append("┱");
233             } else {
234               builder.append("┳");
235             }
236           }
237         }
238       }
239       if (getCell(i, 0) != null) {
240         builder.append("━");
241       } else {
242         builder.append("─");
243       }
244 
245     }
246     if (getCell(columnCount - 1, 0) != null) {
247       builder.append("┓");
248     } else {
249       builder.append("┐");
250     }
251     builder.append("\n");
252 
253     for (int j = 0; j < rowCount; j++) {
254 
255       // between the cells
256       if (j != 0) {
257         for (int i = 0; i < columnCount; i++) {
258           if (i == 0) {
259             final Cell b = getCell(0, j - 1);
260             final Cell d = getCell(0, j);
261             if (b == null && d == null) {
262               builder.append("├");
263             } else {
264               if (connected(b, d)) {
265                 builder.append("┠");
266               } else {
267                 if (b == null) {
268                   builder.append("┢");
269                 } else if (d == null) {
270                   builder.append("┡");
271                 } else {
272                   builder.append("┣");
273                 }
274               }
275             }
276           } else {
277             final Cell a = getCell(i - 1, j - 1);
278             final Cell b = getCell(i, j - 1);
279             final Cell c = getCell(i - 1, j);
280             final Cell d = getCell(i, j);
281 //            a│b
282 //            ─┼─
283 //            c│d
284             if (connected(a, b)) {
285               if (connected(c, d)) {
286                 if (connected(a, c)) {
287                   builder.append("┼");
288                 } else {
289                   builder.append("┿");
290                 }
291               } else {
292                 builder.append("╈");
293               }
294             } else {
295               if (connected(c, d)) {
296                 if (connected(a, c)) {
297                   builder.append("╄");
298                 } else if (connected(b, d)) {
299                   builder.append("╃");
300                 } else {
301                   builder.append("╇");
302                 }
303               } else {
304                 if (connected(a, c)) {
305                   if (connected(b, d)) {
306                     builder.append("╂");
307                   } else {
308                     builder.append("╊");
309                   }
310                 } else {
311                   if (connected(b, d)) {
312                     builder.append("╉");
313                   } else {
314                     builder.append("╋");
315                   }
316                 }
317               }
318             }
319           }
320           final Cell a = getCell(i, j - 1);
321           final Cell c = getCell(i, j);
322           if (connected(a, c)) {
323             builder.append("─");
324           } else {
325             builder.append("━");
326           }
327         }
328         final Cell a = getCell(columnCount - 1, j - 1);
329         final Cell c = getCell(columnCount - 1, j);
330         if (a == null && c == null) {
331           builder.append("┤");
332         } else {
333           if (connected(a, c)) {
334             builder.append("┨");
335           } else {
336             if (a == null) {
337               builder.append("┪");
338             } else if (c == null) {
339               builder.append("┩");
340             } else {
341               builder.append("┫");
342             }
343           }
344         }
345         builder.append("\n");
346       }
347 
348       // cell
349       for (int i = 0; i < columnCount; i++) {
350         if (i == 0) {
351           if (getCell(i, j) != null) {
352             builder.append("┃");
353           } else {
354             builder.append("│");
355           }
356         } else {
357           final Cell c = getCell(i - 1, j);
358           final Cell d = getCell(i, j);
359           if (connected(c, d)) {
360             builder.append("│");
361           } else {
362             builder.append("┃");
363           }
364         }
365         if (hasError(i, j)) {
366           builder.append("✖"); //↯
367         } else {
368           if (getCell(i, j) instanceof OriginCell) {
369             builder.append("█");
370           } else if (getCell(i, j) instanceof SpanCell) {
371             if (j == 0) {
372               builder.append("➞");
373             } else {
374               final Cell a = getCell(i, j - 1);
375               final Cell c = getCell(i, j);
376               if (connected(a, c)) {
377                 builder.append("⬇");
378               } else {
379                 builder.append("➞");
380               }
381             }
382           } else {
383             builder.append("◌");
384           }
385         }
386       }
387       if (getCell(columnCount - 1, j) != null) {
388         builder.append("┃");
389       } else {
390         builder.append("│");
391       }
392       builder.append("\n");
393     }
394 
395     //last bottom
396     for (int i = 0; i < columnCount; i++) {
397       if (i == 0) {
398         if (getCell(0, rowCount - 1) != null) {
399           builder.append("┗");
400         } else {
401           builder.append("└");
402         }
403       } else {
404         final Cell a = getCell(i - 1, rowCount - 1);
405         final Cell b = getCell(i, rowCount - 1);
406         if (a == null && b == null) {
407           builder.append("┴");
408         } else {
409           if (connected(a, b)) {
410             builder.append("┷");
411           } else {
412             if (a == null) {
413               builder.append("┺");
414             } else if (b == null) {
415               builder.append("┹");
416             } else {
417               builder.append("┻");
418             }
419           }
420         }
421       }
422       if (getCell(i, rowCount - 1) != null) {
423         builder.append("━");
424       } else {
425         builder.append("─");
426       }
427     }
428     if (getCell(columnCount - 1, rowCount - 1) != null) {
429       builder.append("┛");
430     } else {
431       builder.append("┘");
432     }
433     builder.append("\n");
434 
435     return builder.toString();
436   }
437 
438   @Override
439   public String toString() {
440     return gridAsString() + "columns=" + columns + '\n' + "rows=" + rows + "\n";
441   }
442 
443   private boolean connected(final Cell a, final Cell b) {
444     if (a == null && b == null) {
445       return true;
446     }
447     if (a == null || b == null) {
448       return false;
449     }
450     return a.getOrigin().equals(b.getOrigin());
451   }
452 }