org.apache.wicket.markup.repeater.data.GridView.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.wicket.markup.repeater.data.GridView.java

Source

/*
 * 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.wicket.markup.repeater.data;

import java.util.Iterator;

import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.lang.Generics;

/**
 * A pageable DataView which breaks the data in the IDataProvider into a number of data-rows,
 * depending on the column size. A typical use case is to show items in a table with ie 3 columns
 * where the table is filled left to right top-down so that for each third item a new row is
 * created.
 * <p>
 * Example
 * 
 * <pre>
 *   &lt;tbody&gt;
 *     &lt;tr wicket:id=&quot;rows&quot; class&quot;even&quot;&gt;
 *       &lt;td wicket:id=&quot;cols&quot;&gt;
 *         &lt;span wicket:id=&quot;id&quot;&gt;Test ID&lt;/span&gt;
 *       &lt;/td&gt;
 *     &lt;/tr&gt;
 *   &lt;/tbody&gt;
 * </pre>
 * 
 * and in java:
 * 
 * <pre>
 * add(new GridView(&quot;rows&quot;, dataProvider).setColumns(3));
 * </pre>
 * 
 * @author Igor Vaynberg
 * @author Christian Essl
 * @param <T>
 * 
 */
public abstract class GridView<T> extends DataViewBase<T> {
    private static final long serialVersionUID = 1L;

    private int columns = 1;
    private int rows = Integer.MAX_VALUE;

    /**
     * @param id
     *            component id
     * @param dataProvider
     *            data provider
     */
    public GridView(String id, IDataProvider<T> dataProvider) {
        super(id, dataProvider);
    }

    /**
     * @return number of columns
     */
    public int getColumns() {
        return columns;
    }

    /**
     * Sets number of columns
     * 
     * @param cols
     *            number of columns
     * @return this for chaining
     */
    public GridView<T> setColumns(int cols) {
        if (cols < 1) {
            throw new IllegalArgumentException();
        }

        if (columns != cols) {
            if (isVersioned()) {
                addStateChange();
            }
            columns = cols;
        }
        updateItemsPerPage();
        return this;
    }

    /**
     * @return number of rows per page
     */
    public int getRows() {
        return rows;
    }

    /**
     * Sets number of rows per page
     * 
     * @param rows
     *            number of rows
     * @return this for chaining
     */
    public GridView<T> setRows(int rows) {
        if (rows < 1) {
            throw new IllegalArgumentException();
        }

        if (this.rows != rows) {
            if (isVersioned()) {
                addStateChange();
            }
            this.rows = rows;
        }

        // TODO Post 1.2: Performance: Can this be moved into the this.rows != rows if
        // block for optimization?
        updateItemsPerPage();
        return this;
    }

    private void updateItemsPerPage() {
        long items = Long.MAX_VALUE;

        long result = (long) rows * (long) columns;

        // overflow check
        int desiredHiBits = -((int) (result >>> 31) & 1);
        int actualHiBits = (int) (result >>> 32);

        if (desiredHiBits == actualHiBits) {
            items = (int) result;
        }
        setItemsPerPage(items);
    }

    @Override
    protected void addItems(Iterator<Item<T>> items) {
        if (items.hasNext()) {
            final int cols = getColumns();

            int row = 0;

            do {
                // Build a row
                Item<?> rowItem = newRowItem(newChildId(), row);
                RepeatingView rowView = new RepeatingView("cols");
                rowItem.add(rowView);
                add(rowItem);

                // Populate the row
                for (int index = 0; index < cols; index++) {
                    final Item<T> cellItem;
                    if (items.hasNext()) {
                        cellItem = items.next();
                    } else {
                        cellItem = newEmptyItem(newChildId(), index);
                        populateEmptyItem(cellItem);
                    }
                    rowView.add(cellItem);
                }

                // increase row
                row++;

            } while (items.hasNext());
        }

    }

    /**
     * @return data provider
     */
    public IDataProvider<T> getDataProvider() {
        return internalGetDataProvider();
    }

    /**
     * @see org.apache.wicket.markup.repeater.AbstractPageableView#getItems()
     */
    @Override
    public Iterator<Item<T>> getItems() {
        Iterator<MarkupContainer> rows = Generics.iterator(iterator());
        return new ItemsIterator<T>(rows);
    }

    /**
     * Add component to an Item for which there is no model anymore and is shown in a cell
     * 
     * @param item
     *            Item object
     */
    abstract protected void populateEmptyItem(Item<T> item);

    /**
     * Create a Item which represents an empty cell (there is no model for it in the DataProvider)
     * 
     * @param id
     * @param index
     * @return created item
     */
    protected Item<T> newEmptyItem(String id, int index) {
        return new Item<T>(id, index, null);
    }

    /**
     * Create a new Item which will hold a row.
     * 
     * @param id
     * @param index
     * @return created Item
     */
    protected Item<?> newRowItem(String id, int index) {
        return new Item<Object>(id, index, null);
    }

    /**
     * Iterator that iterates over all items in the cells
     * 
     * @author igor
     * @param <T>
     */
    public static class ItemsIterator<T> implements Iterator<Item<T>> {
        private final Iterator<MarkupContainer> rows;
        private Iterator<Item<T>> cells;

        private Item<T> next;

        /**
         * @param rows
         *            iterator over child row views
         */
        public ItemsIterator(Iterator<MarkupContainer> rows) {
            this.rows = Args.notNull(rows, "rows");
            findNext();
        }

        /**
         * @see java.util.Iterator#remove()
         */
        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }

        /**
         * @see java.util.Iterator#hasNext()
         */
        @Override
        public boolean hasNext() {
            return next != null;
        }

        /**
         * @see java.util.Iterator#next()
         */
        @Override
        public Item<T> next() {
            Item<T> item = next;
            findNext();
            return item;
        }

        private void findNext() {
            next = null;

            if (cells != null && cells.hasNext()) {
                next = cells.next();
            } else {
                while (rows.hasNext()) {
                    MarkupContainer row = rows.next();

                    final Iterator<? extends Component> rawCells;
                    rawCells = ((MarkupContainer) row.iterator().next()).iterator();
                    cells = Generics.iterator(rawCells);
                    if (cells.hasNext()) {
                        next = cells.next();
                        break;
                    }
                }
            }
        }

    }
}