org.dominokit.domino.ui.datatable.TableRow Maven / Gradle / Ivy
/*
* Copyright © 2019 Dominokit
*
* 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.dominokit.domino.ui.datatable;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static org.dominokit.domino.ui.datatable.ColumnUtils.fixElementWidth;
import static org.jboss.elemento.Elements.*;
import elemental2.dom.HTMLTableCellElement;
import elemental2.dom.HTMLTableRowElement;
import java.util.*;
import org.dominokit.domino.ui.datatable.events.RowRecordUpdatedEvent;
import org.dominokit.domino.ui.datatable.events.TableDataUpdatedEvent;
import org.dominokit.domino.ui.forms.validations.ValidationResult;
import org.dominokit.domino.ui.utils.BaseDominoElement;
import org.dominokit.domino.ui.utils.DominoElement;
import org.dominokit.domino.ui.utils.Selectable;
public class TableRow extends BaseDominoElement>
implements Selectable {
private T record;
private boolean selected = false;
private final int index;
private DataTable dataTable;
private final Map> rowCells = new HashMap<>();
private Map flags = new HashMap<>();
private Map metaObjects = new HashMap<>();
private HTMLTableRowElement element = tr().element();
private List> selectionHandlers = new ArrayList<>();
private List> listeners = new ArrayList<>();
private boolean editable = false;
private RowRenderer rowRenderer = new DefaultRowRenderer<>();
private TableRow parent;
private List> children = new ArrayList<>();
public TableRow(T record, int index, DataTable dataTable) {
this.record = record;
this.index = index;
this.dataTable = dataTable;
init(this);
}
public void setRecord(T record) {
this.record = record;
}
public T getDirtyRecord() {
T dirtyRecord = dataTable.getTableConfig().getDirtyRecordProvider().createDirtyRecord(record);
getRowCells().forEach((s, rowCell) -> rowCell.getCellInfo().updateDirtyRecord(dirtyRecord));
return dirtyRecord;
}
@Override
public T select() {
return doSelect(true);
}
private T doSelect(boolean selectChildren) {
if (!hasFalg(DataTable.DATA_TABLE_ROW_FILTERED)) {
this.selected = true;
if (selectChildren) {
getChildren().forEach(TableRow::select);
}
Optional.ofNullable(parent)
.ifPresent(
tableRow -> {
if (tableRow.shouldBeSelected()) {
tableRow.doSelect(false);
}
});
selectionHandlers.forEach(
selectionHandler -> selectionHandler.onSelectionChanged(TableRow.this));
}
return record;
}
private boolean shouldBeSelected() {
return getChildren().stream().allMatch(TableRow::isSelected);
}
@Override
public T deselect() {
return doDeselect(true, true);
}
private T doDeselect(boolean deselectParent, boolean deselectChildren) {
this.selected = false;
if (deselectChildren) {
getChildren().forEach(tableRow -> tableRow.doDeselect(false, true));
}
if (deselectParent) {
Optional.ofNullable(parent).ifPresent(tableRow -> tableRow.doDeselect(true, false));
}
selectionHandlers.forEach(
selectionHandler -> selectionHandler.onSelectionChanged(TableRow.this));
return record;
}
@Override
public T select(boolean silent) {
this.selected = true;
return record;
}
@Override
public T deselect(boolean silent) {
this.selected = false;
return record;
}
@Override
public boolean isSelected() {
return selected;
}
public T getRecord() {
return record;
}
public DataTable getDataTable() {
return dataTable;
}
@Override
public void addSelectionHandler(SelectionHandler selectionHandler) {
this.selectionHandlers.add(selectionHandler);
}
public void addRowListener(RowListener listener) {
listeners.add(listener);
}
public void removeListener(RowListener listener) {
listeners.remove(listener);
}
public void fireUpdate() {
listeners.forEach(listener -> listener.onChange(TableRow.this));
}
@Override
public HTMLTableRowElement element() {
return element;
}
public void setFlag(String name, String value) {
flags.put(name, value);
}
public String getFlag(String name) {
return flags.get(name);
}
public void addMetaObject(RowMetaObject metaObject) {
metaObjects.put(metaObject.getKey(), metaObject);
}
public E getMetaObject(String key) {
return (E) metaObjects.get(key);
}
public void removeFlag(String name) {
flags.remove(name);
}
public boolean hasFalg(String name) {
return flags.containsKey(name);
}
public void addCell(RowCell rowCell) {
rowCells.put(rowCell.getColumnConfig().getName(), rowCell);
}
public RowCell getCell(String name) {
return rowCells.get(name);
}
public int getIndex() {
return index;
}
public void updateRow() {
updateRow(this.record);
}
public void updateRow(T record) {
this.record = record;
rowCells.values().forEach(RowCell::updateCell);
this.dataTable.fireTableEvent(new RowRecordUpdatedEvent<>(this));
this.dataTable.fireTableEvent(
new TableDataUpdatedEvent<>(
new ArrayList<>(dataTable.getData()), dataTable.getData().size()));
}
public ValidationResult validate() {
Optional first =
getRowCells().values().stream()
.map(tRowCell -> tRowCell.getCellInfo().validate())
.filter(result -> !result.isValid())
.findFirst();
if (first.isPresent()) {
return ValidationResult.invalid("");
} else {
return ValidationResult.valid();
}
}
public Map> getRowCells() {
return Collections.unmodifiableMap(rowCells);
}
public void render() {
rowRenderer.render(dataTable, this);
}
/**
* An interface to implement listeners for Table row changes
*
* @param the type of the data table records
*/
@FunctionalInterface
public interface RowListener {
/** @param tableRow the changed {@link TableRow} */
void onChange(TableRow tableRow);
}
/**
* this interface is used to implement custom meta object for rows with a unique key then later
* these meta object can be added to the row and can be used for any kind of logic.
*/
public interface RowMetaObject {
/** @return String, a unique key for the meta object */
String getKey();
}
/** Convert the row the editable mode */
public void edit() {
setEditable(true);
updateRow();
}
/** Save the editable row changes and switch to normal mode */
public void save() {
if (validate().isValid()) {
dataTable
.getTableConfig()
.getSaveDirtyRecordHandler()
.saveDirtyRecord(record, getDirtyRecord());
this.setEditable(false);
updateRow();
}
}
/** Cancel the current edit operation and switch to the normal mode */
public void cancelEditing() {
this.setEditable(false);
updateRow();
}
/** @return boolean, true if the row is editable, otherwise false */
public boolean isEditable() {
return editable;
}
/** @param editable boolean, true if this row should be editable, otherwise it is not */
private void setEditable(boolean editable) {
this.editable = editable;
}
public void setRowRenderer(RowRenderer rowRenderer) {
if (isNull(rowRenderer)) {
this.rowRenderer = new DefaultRowRenderer<>();
} else {
this.rowRenderer = rowRenderer;
}
}
public void renderCell(ColumnConfig columnConfig) {
HTMLTableCellElement cellElement;
if (columnConfig.isHeader()) {
cellElement = DominoElement.of(th()).css("dt-th-cell").element();
} else {
cellElement = DominoElement.of(td()).css("dt-td-cell").element();
}
if (dataTable.getTableConfig().isFixed() || columnConfig.isFixed()) {
fixElementWidth(
columnConfig, cellElement, dataTable.getTableConfig().getFixedDefaultColumnWidth());
}
RowCell rowCell =
new RowCell<>(new CellRenderer.CellInfo<>(this, cellElement), columnConfig);
rowCell.updateCell();
addCell(rowCell);
columnConfig.applyScreenMedia(cellElement);
columnConfig.applyCellStyle(cellElement);
if (columnConfig.isHidden()) {
DominoElement.of(cellElement).hide();
}
element().appendChild(cellElement);
columnConfig.addShowHideListener(DefaultColumnShowHideListener.of(cellElement));
}
public TableRow getParent() {
return parent;
}
public void setParent(TableRow parent) {
this.parent = parent;
}
public List> getChildren() {
return children;
}
public void setChildren(List> children) {
if (nonNull(children)) {
this.children = children;
}
}
public boolean isParent() {
return !getChildren().isEmpty();
}
public boolean isChild() {
return nonNull(parent);
}
public boolean isRoot() {
return isNull(parent);
}
public interface RowRenderer {
void render(DataTable dataTable, TableRow tableRow);
}
private static class DefaultRowRenderer implements RowRenderer {
@Override
public void render(DataTable dataTable, TableRow tableRow) {
dataTable.getTableConfig().getColumns().forEach(tableRow::renderCell);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy