org.opensingular.lib.wicket.util.datatable.BSFlexDataTable Maven / Gradle / Ivy
/*
* Copyright (C) 2016 Singular Studios (a.k.a Atom Tecnologia) - www.opensingular.com
*
* 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.opensingular.lib.wicket.util.datatable;
import static org.opensingular.lib.wicket.util.util.WicketUtils.*;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import org.apache.wicket.Component;
import org.apache.wicket.MetaDataKey;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.DataGridView;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IStyledColumn;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.repeater.IItemFactory;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.markup.repeater.data.IDataProvider;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.string.Strings;
import org.opensingular.lib.wicket.util.datatable.column.IRowMergeableColumn;
public class BSFlexDataTable extends BSDataTable {
private static final MetaDataKey ROWSPAN_KEY = new MetaDataKey() {
};
private transient Object[] lastMergingIds;
private transient Item>[] lastVisibleCellItems;
public BSFlexDataTable(String id, List extends IColumn> columns, ISortableDataProvider dataProvider) {
super(id, columns, dataProvider);
setStripedRows(false);
setHoverRows(false);
}
@Override
protected DataGridView newDataGridView(String id, List extends IColumn> columns, IDataProvider dataProvider) {
return new DefaultDataGridView(id, columns, dataProvider);
}
@Override
protected void onDetach() {
super.onDetach();
this.lastMergingIds = null;
this.lastVisibleCellItems = null;
}
@SuppressWarnings("unchecked")
private boolean checkAndSetColumnMergingIdSameAsLast(int columnIndex, IModel currentRowModel) {
final IColumn column = getColumns().get(columnIndex);
if (!(column instanceof IRowMergeableColumn)) {
return false;
}
final Object lastId = lastMergingIds()[columnIndex];
final Object currentId = ((IRowMergeableColumn) column).getRowMergeId(currentRowModel);
if (!Objects.equals(lastId, currentId)) {
lastMergingIds()[columnIndex] = currentId;
}
boolean mergingIdSameAsLast = (lastId != null) && (currentId != null) && Objects.equals(lastId, currentId);
return mergingIdSameAsLast;
}
protected void postPopulateCellItem(Item> cellItem, int columnIndex, IModel model) {
boolean visible = !checkAndSetColumnMergingIdSameAsLast(columnIndex, model);
cellItem.setVisible(visible);
if (visible) {
lastVisibleCellItems()[columnIndex] = cellItem;
lastVisibleCellItems()[columnIndex].setMetaData(ROWSPAN_KEY, 1);
cellItem.add($b.attr("rowspan", $m.get(() -> cellItem.getMetaData(ROWSPAN_KEY))));
} else {
lastVisibleCellItems()[columnIndex].setMetaData(ROWSPAN_KEY, lastVisibleCellItems()[columnIndex].getMetaData(ROWSPAN_KEY) + 1);
cellItem.removeAll();
}
}
private Object[] lastMergingIds() {
if (lastMergingIds == null) {
lastMergingIds = new Object[getColumns().size()];
}
return lastMergingIds;
}
@SuppressWarnings("unchecked")
private Item>[] lastVisibleCellItems() {
if (lastVisibleCellItems == null) {
lastVisibleCellItems = new Item[getColumns().size()];
}
return lastVisibleCellItems;
}
private class DefaultDataGridView extends DataGridView {
public DefaultDataGridView(String id, List extends IColumn> columns, IDataProvider dataProvider) {
super(id, columns, dataProvider);
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Item newCellItem(final String id, final int columnIndex, final IModel model) {
Item item = BSFlexDataTable.this.newCellItem(id, columnIndex, model);
final IColumn column = BSFlexDataTable.this.getColumns().get(columnIndex);
if (column instanceof IStyledColumn) {
item.add(new Behavior() {
@Override
public void onComponentTag(final Component component, final ComponentTag tag) {
String className = ((IStyledColumn) column).getCssClass();
if (!Strings.isEmpty(className)) {
tag.append("class", className, " ");
}
}
});
}
return item;
}
@Override
protected Item newRowItem(final String id, final int index, final IModel model) {
return BSFlexDataTable.this.newRowItem(id, index, model);
}
@Override
protected void addItems(Iterator- > items) {
super.addItems(items);
}
@Override
protected Iterator
> getItemModels() {
long offset = getFirstItemOffset();
long size = getViewSize();
return new ModelIterator(this.getDataProvider(), offset, size);
}
private final class ModelIterator implements Iterator> {
private final Iterator extends T> items;
private final IDataProvider dataProvider;
@SuppressWarnings("unchecked")
public ModelIterator(IDataProvider dataProvider, long offset, long count) {
this.dataProvider = dataProvider;
items = count > 0 ? dataProvider.iterator(offset, count) : (Iterator extends T>) Collections.emptyList().iterator();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public boolean hasNext() {
return items != null && items.hasNext();
}
@Override
public IModel next() {
return dataProvider.model(items.next());
}
}
@Override
@SuppressWarnings("unchecked")
protected IItemFactory newItemFactory() {
return (index, model) -> {
String id = DefaultDataGridView.this.newChildId();
Item item = DefaultDataGridView.this.newItem(id, index, model);
DefaultDataGridView.this.populateItem(item);
RepeatingView cells = (RepeatingView) item.get("cells");
int columnIndex = 0;
for (Iterator it = cells.iterator(); it.hasNext(); ) {
Item> cellItem = (Item>) it.next();
postPopulateCellItem(cellItem, columnIndex, model);
columnIndex++;
}
return item;
};
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy