/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* Licensed 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.kie.workbench.common.forms.adf.engine.shared.formGeneration.layout;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.Dependent;
import org.kie.workbench.common.forms.adf.definitions.settings.ColSpan;
import org.kie.workbench.common.forms.adf.service.definitions.layout.LayoutColumnDefinition;
import org.kie.workbench.common.forms.adf.service.definitions.layout.LayoutSettings;
import org.uberfire.ext.layout.editor.api.editor.LayoutColumn;
import org.uberfire.ext.layout.editor.api.editor.LayoutComponent;
import org.uberfire.ext.layout.editor.api.editor.LayoutRow;
import org.uberfire.ext.layout.editor.api.editor.LayoutTemplate;
@Dependent
public class LayoutGenerator {
public static final int MAX_SPAN = 12;
private ColSpan[] structure;
private List<Row> rows = new ArrayList<>();
private Row currentRow;
public void init(LayoutColumnDefinition[] structure) {
currentRow = null;
rows.clear();
int autoCount = 0;
int maxSpan = 0;
for (LayoutColumnDefinition col : structure) {
if (col.getSpan().equals(ColSpan.AUTO)) {
autoCount++;
} else {
maxSpan += col.getSpan().getSpan();
}
}
if (maxSpan > MAX_SPAN) {
throw new IllegalArgumentException("Max SPAN allowed for all layout columns is 12.");
}
if (maxSpan < MAX_SPAN && autoCount == 0) {
throw new IllegalArgumentException("Wrong layout definition, the columns total span must be 12");
}
if (maxSpan + autoCount > MAX_SPAN) {
throw new IllegalArgumentException("There's not enough space for all columns in layout.");
}
int freeSpan = MAX_SPAN - maxSpan;
int freeOffset = 0;
int freeAVGSpan = 0;
if (freeSpan > 0) {
freeOffset = freeSpan % autoCount;
freeAVGSpan = Math.floorDiv(freeSpan,
autoCount);
}
List<ColSpan> spans = new ArrayList<>();
for (LayoutColumnDefinition definition : structure) {
if (definition.getSpan().equals(ColSpan.AUTO)) {
int span = freeAVGSpan;
if (freeOffset > 0) {
span++;
freeOffset--;
}
spans.add(ColSpan.calculateSpan(span));
} else {
spans.add(definition.getSpan());
}
}
this.structure = spans.toArray(new ColSpan[spans.size()]);
newRow();
}
public void addComponent(LayoutComponent component,
LayoutSettings settings) {
if (currentRow.isFull()) {
newRow();
}
if (!currentRow.addComponent(component,
settings)) {
newRow();
currentRow.addComponent(component,
settings);
}
}
public LayoutTemplate build() {
LayoutTemplate template = new LayoutTemplate();
rows.forEach(row -> {
LayoutRow layoutRow = new LayoutRow();
template.addRow(layoutRow);
row.cells.forEach(cell -> {
LayoutColumn layoutColumn = new LayoutColumn(String.valueOf(cell.horizontalSpan));
layoutRow.add(layoutColumn);
if (cell.getComponentsCount() == 0) {
return;
} else if (cell.getComponentsCount() == 1) {
layoutColumn.add(cell.components.get(0));
} else {
cell.components.forEach(component -> {
LayoutRow nestedRow = new LayoutRow();
layoutColumn.addRow(nestedRow);
LayoutColumn nestedColumn = new LayoutColumn(String.valueOf(MAX_SPAN));
nestedRow.add(nestedColumn);
nestedColumn.add(component);
});
}
});
});
return template;
}
protected void newRow() {
List<Cell> cells = new ArrayList<>();
for (ColSpan span : structure) {
cells.add(new Cell(span.getSpan()));
}
currentRow = new Row(cells);
rows.add(currentRow);
}
private class Row {
List<Cell> cells;
int currentIndex = 0;
public Row(List<Cell> cells) {
this.cells = cells;
}
boolean isFull() {
return currentIndex == cells.size() || (currentIndex > 0 && cells.get(currentIndex - 1).wrap);
}
public boolean addComponent(LayoutComponent component,
LayoutSettings settings) {
int horizontalSpan = settings.getHorizontalSpan();
Cell currentCell = cells.get(currentIndex);
currentCell.wrap = settings.isWrap();
currentCell.addLayoutComponent(component);
if (horizontalSpan > 1) {
while (horizontalSpan > 1 && cells.size() > currentIndex + 1) {
Cell cell = cells.remove(currentIndex + 1);
currentCell.horizontalSpan += cell.horizontalSpan;
}
}
currentIndex++;
return true;
}
}
private class Cell {
private int horizontalSpan = 1;
private int verticalSpan = 1;
private boolean wrap;
private List<LayoutComponent> components = new ArrayList<>();
public Cell(int horizontalSpan) {
this.horizontalSpan = horizontalSpan;
}
private void addLayoutComponent(LayoutComponent component) {
components.add(component);
}
private int getComponentsCount() {
return components.size();
}
public int getVerticalSpan() {
return verticalSpan;
}
public void setVerticalSpan(int verticalSpan) {
this.verticalSpan = verticalSpan;
}
}
}