All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opensingular.lib.wicket.util.datatable.BSFlexDataTable Maven / Gradle / Ivy

There is a newer version: 1.9.7
Show newest version
/*
 * 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> columns, ISortableDataProvider dataProvider) {
        super(id, columns, dataProvider);
        setStripedRows(false);
        setHoverRows(false);
    }

    @Override
    protected DataGridView newDataGridView(String id, List> 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> 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 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) 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