Package org.apache.wicket.markup.repeater.data

Source Code of org.apache.wicket.markup.repeater.data.GridView$ItemsIterator

/*
* 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.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>
   *
   */
  private 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 = 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;
          }
        }
      }
    }

  }
}
TOP

Related Classes of org.apache.wicket.markup.repeater.data.GridView$ItemsIterator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.