blob: 3f3337e429e44954b07f8c0c95eb8f2a5d87ce8b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.tobago.internal.layout;
import org.apache.myfaces.tobago.layout.Measure;
import org.apache.myfaces.tobago.layout.MeasureList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
/**
* @deprecated since 4.0.0
*/
@Deprecated
public class Grid {
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
// TODO: check if it is faster with arrays.
/**
* The rectangular data as a 1-dim list
*/
private List<Cell> cells;
private MeasureList columns;
private MeasureList rows;
private int columnCount;
private int rowCount;
private int columnCursor;
private int rowCursor;
private List<Integer> errorIndexes;
public Grid(final MeasureList columns, final MeasureList rows) {
assert columns.getSize() > 0;
assert rows.getSize() > 0;
this.columnCount = columns.getSize();
this.rowCount = rows.getSize();
this.columns = columns;
this.rows = rows;
final int size = columnCount * rowCount;
this.cells = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
this.cells.add(null);
}
}
public void add(final OriginCell cell, final int columnSpan, final int rowSpan) {
assert columnSpan > 0;
assert rowSpan > 0;
int iterator = columnSpan;
boolean error = false;
if (iterator + columnCursor > columnCount) {
LOG.warn("The columnSpan is to large for the actual position in the grid. Will be fixed. "
+ "columnSpan='" + iterator + "' columnCursor='" + columnCursor + "' columnCount='" + columnCount + "'");
iterator = columnCount - columnCursor;
error = true;
}
cell.setColumnSpan(iterator);
cell.setRowSpan(rowSpan);
for (int i = 1; i < iterator; i++) {
if (getCell(i + columnCursor, rowCursor) != null) {
LOG.warn("The columnSpan is to large for the actual position in the grid. Will be fixed. "
+ "columnSpan='" + iterator + "' columnCursor='" + columnCursor + "' columnCount='" + columnCount + "'");
iterator = i - 1;
error = true;
}
}
for (int j = 0; j < rowSpan; j++) {
for (int i = 0; i < iterator; i++) {
final Cell actualCell;
if (i == 0 && j == 0) {
actualCell = cell;
} else {
actualCell = new SpanCell(cell, i == 0, j == 0);
}
assert getCell(i + columnCursor, j + rowCursor) == null : "Position in the cell must be free.";
setCell(i + columnCursor, j + rowCursor, actualCell);
if (error) {
addError(i + columnCursor, j + rowCursor);
}
}
}
findNextFreeCell();
}
public Cell getCell(final int column, final int row) {
assert column >= 0 && column < columnCount : "column=" + column + " columnCount=" + columnCount;
assert row >= 0 : "row=" + row;
if (row >= rowCount) {
return null;
} else {
return cells.get(column + row * columnCount);
}
}
public void setCell(final int column, final int row, final Cell cell) {
if (row >= rowCount) {
enlarge(row - rowCount + 1);
}
cells.set(column + row * columnCount, cell);
}
private void findNextFreeCell() {
for (; rowCursor < rowCount; rowCursor++) {
for (; columnCursor < columnCount; columnCursor++) {
if (getCell(columnCursor, rowCursor) == null) {
return;
}
}
columnCursor = 0;
}
}
protected MeasureList getColumns() {
return columns;
}
protected MeasureList getRows() {
return rows;
}
private void enlarge(final int newRows) {
// process cells
for (int i = 0; i < newRows; i++) {
for (int j = 0; j < columnCount; j++) {
cells.add(null);
}
}
// process heads
for (int i = rowCount; i < rowCount + newRows; i++) {
rows.add(Measure.FRACTION1);
}
rowCount += newRows;
}
public void addError(final int i, final int j) {
if (errorIndexes == null) {
errorIndexes = new ArrayList<>();
}
errorIndexes.add(j * columnCount + i);
}
public boolean hasError(final int i, final int j) {
if (errorIndexes == null) {
return false;
}
return errorIndexes.contains(j * columnCount + i);
}
public int getColumnCount() {
return columnCount;
}
public int getRowCount() {
return rowCount;
}
/**
* Prints the state of the grid as an Unicode shape like this:
* ┏━┳━┳━┳━┯━┓
* ┃█┃█┃█┃█│➞┃
* ┠─╂─╊━╇━┿━┫
* ┃⬇┃⬇┃█│➞│➞┃
* ┣━╉─╊━╈━╈━┫
* ┃█┃⬇┃█┃█┃█┃
* ┣━╇━╇━╉─╊━┩
* ┃█│➞│➞┃⬇┃◌│
* ┡━┿━┿━╉─╂─┤
* │◌│◌│◌┃⬇┃◌│
* └─┴─┴─┺━┹─┘
*/
public String gridAsString() {
final StringBuilder builder = new StringBuilder();
// top of grid
for (int i = 0; i < columnCount; i++) {
if (i == 0) {
if (getCell(i, 0) != null) {
builder.append("┏");
} else {
builder.append("┌");
}
} else {
final Cell c = getCell(i - 1, 0);
final Cell d = getCell(i, 0);
if (c == null && d == null) {
builder.append("┬");
} else {
if (connected(c, d)) {
builder.append("┯");
} else {
if (c == null) {
builder.append("┲");
} else if (d == null) {
builder.append("┱");
} else {
builder.append("┳");
}
}
}
}
if (getCell(i, 0) != null) {
builder.append("━");
} else {
builder.append("─");
}
}
if (getCell(columnCount - 1, 0) != null) {
builder.append("┓");
} else {
builder.append("┐");
}
builder.append("\n");
for (int j = 0; j < rowCount; j++) {
// between the cells
if (j != 0) {
for (int i = 0; i < columnCount; i++) {
if (i == 0) {
final Cell b = getCell(0, j - 1);
final Cell d = getCell(0, j);
if (b == null && d == null) {
builder.append("├");
} else {
if (connected(b, d)) {
builder.append("┠");
} else {
if (b == null) {
builder.append("┢");
} else if (d == null) {
builder.append("┡");
} else {
builder.append("┣");
}
}
}
} else {
final Cell a = getCell(i - 1, j - 1);
final Cell b = getCell(i, j - 1);
final Cell c = getCell(i - 1, j);
final Cell d = getCell(i, j);
// a│b
// ─┼─
// c│d
if (connected(a, b)) {
if (connected(c, d)) {
if (connected(a, c)) {
builder.append("┼");
} else {
builder.append("┿");
}
} else {
builder.append("╈");
}
} else {
if (connected(c, d)) {
if (connected(a, c)) {
builder.append("╄");
} else if (connected(b, d)) {
builder.append("╃");
} else {
builder.append("╇");
}
} else {
if (connected(a, c)) {
if (connected(b, d)) {
builder.append("╂");
} else {
builder.append("╊");
}
} else {
if (connected(b, d)) {
builder.append("╉");
} else {
builder.append("╋");
}
}
}
}
}
final Cell a = getCell(i, j - 1);
final Cell c = getCell(i, j);
if (connected(a, c)) {
builder.append("─");
} else {
builder.append("━");
}
}
final Cell a = getCell(columnCount - 1, j - 1);
final Cell c = getCell(columnCount - 1, j);
if (a == null && c == null) {
builder.append("┤");
} else {
if (connected(a, c)) {
builder.append("┨");
} else {
if (a == null) {
builder.append("┪");
} else if (c == null) {
builder.append("┩");
} else {
builder.append("┫");
}
}
}
builder.append("\n");
}
// cell
for (int i = 0; i < columnCount; i++) {
if (i == 0) {
if (getCell(i, j) != null) {
builder.append("┃");
} else {
builder.append("│");
}
} else {
final Cell c = getCell(i - 1, j);
final Cell d = getCell(i, j);
if (connected(c, d)) {
builder.append("│");
} else {
builder.append("┃");
}
}
if (hasError(i, j)) {
builder.append("✖"); //↯
} else {
if (getCell(i, j) instanceof OriginCell) {
builder.append("█");
} else if (getCell(i, j) instanceof SpanCell) {
if (j == 0) {
builder.append("➞");
} else {
final Cell a = getCell(i, j - 1);
final Cell c = getCell(i, j);
if (connected(a, c)) {
builder.append("⬇");
} else {
builder.append("➞");
}
}
} else {
builder.append("◌");
}
}
}
if (getCell(columnCount - 1, j) != null) {
builder.append("┃");
} else {
builder.append("│");
}
builder.append("\n");
}
//last bottom
for (int i = 0; i < columnCount; i++) {
if (i == 0) {
if (getCell(0, rowCount - 1) != null) {
builder.append("┗");
} else {
builder.append("└");
}
} else {
final Cell a = getCell(i - 1, rowCount - 1);
final Cell b = getCell(i, rowCount - 1);
if (a == null && b == null) {
builder.append("┴");
} else {
if (connected(a, b)) {
builder.append("┷");
} else {
if (a == null) {
builder.append("┺");
} else if (b == null) {
builder.append("┹");
} else {
builder.append("┻");
}
}
}
}
if (getCell(i, rowCount - 1) != null) {
builder.append("━");
} else {
builder.append("─");
}
}
if (getCell(columnCount - 1, rowCount - 1) != null) {
builder.append("┛");
} else {
builder.append("┘");
}
builder.append("\n");
return builder.toString();
}
@Override
public String toString() {
return gridAsString() + "columns=" + columns + '\n' + "rows=" + rows + "\n";
}
private boolean connected(final Cell a, final Cell b) {
if (a == null && b == null) {
return true;
}
if (a == null || b == null) {
return false;
}
return a.getOrigin().equals(b.getOrigin());
}
}