⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tablegridlayout.java

📁 Java的Web报表库
💻 JAVA
字号:
/**
 * ========================================
 * JFreeReport : a free Java report library
 * ========================================
 *
 * Project Info:  http://www.jfree.org/jfreereport/index.html
 * Project Lead:  Thomas Morgner;
 *
 * (C) Copyright 2000-2003, by Simba Management Limited and Contributors.
 *
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation;
 * either version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * --------------------
 * TableGridLayout.java
 * --------------------
 * (C)opyright 2003, by Thomas Morgner and Contributors.
 *
 * Original Author:  Thomas Morgner;
 * Contributor(s):   David Gilbert (for Simba Management Limited);
 *
 * $Id: TableGridLayout.java,v 1.13.2.1 2003/08/24 14:18:13 taqua Exp $
 *
 * Changes
 * -------
 * 25-Jan-2003 : Initial version
 * 24-Feb-2003 : Fixed Checkstyle issues (DG);
 *
 */
package com.jrefinery.report.targets.table;

import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * The table grid layout is used to layout the collected TableCellData object from
 * the TableGrid into the table. The cells position is calculated by comparing the cell
 * bounds with the collected x and y-cuts.
 *
 * @author Thomas Morgner
 */
public class TableGridLayout
{
  /**
   * The Element class encapsulates all TableCellData-object within a single grid cell.
   * When the report is badly designed, cells may overlay. This will cause trouble when
   * the table is printed later, so we do not accept multiple non-background
   * TableCellData objects.
   * <p>
   * TableCellData backgrounds can be combined to create complex
   * background structures. Usually, the cell backgrounds must be merged before the
   * cellbackground can be applied to the generated table. As this is dependent
   * on the table implementation, we do not assume anything here, and just collect all
   * backgrounds in the list.
   *
   * @see TableCellData#isBackground
   */
  public static class Element
  {
    /** The root position, a data carrying TableCellData. */
    private TableGridPosition root;
    /** The backgrounds for the data cell. */
    private ArrayList backGrounds;

    /**
     * Creates a new element. The element has no initial background or
     * cell data.
     */
    public Element()
    {
      backGrounds = new ArrayList();
    }

    /**
     * Adds a new TableGridPosition to the element.
     * <p>
     * If the new position contains a data cell: <br>
     * if no data cell has been set so far, the cell is added as new
     * data element. if there is a data cell already set, the new cell data
     * is ignored.
     * <p>
     * If the new position contains a background information: <br>
     * if no data cell has been set so far, the cell is added to the list of
     * available backgrounds. When a new data cell is added, the backgrounds
     * are validated. A cell background is valid, if it fully contains the
     * data cell area. <br>
     * If there is a data cell already set, the background is validated imediatly
     * and added if valid.
     * <p>
     * Invalid backgrounds or duplicate data cells are discarded.
     *
     * @param pos the new TableGridPosition to be added to this element.
     * @throws NullPointerException if the given position is null
     */
    public void add(final TableGridPosition pos)
    {
      if (pos == null)
      {
        throw new NullPointerException();
      }

      if (root == null)
      {
        if (pos.getElement().isBackground())
        {
          backGrounds.add(0, pos);
          //Log.debug ("backGrounds -> added " + backGrounds.size());
        }
        else
        {
          root = pos;
          final Iterator it = backGrounds.iterator();
          while (it.hasNext())
          {
            final TableGridPosition gpos = (TableGridPosition) it.next();
            if (gpos.contains(root) == false)
            {
              it.remove();
            }
          }
        }
      }
      else
      {
        if (pos.getElement().isBackground())
        {
          if (pos.contains(root))
          {
            backGrounds.add(0, pos);
          }
        }
        else
        {
          /*
          Log.warn (new Log.SimpleMessage("Root already added: " , pos.getElement().getBounds()));
          Log.warn (new Log.SimpleMessage("+            added: " , root.getElement().getBounds()));
          Log.warn (new Log.SimpleMessage("+            added: " , pos.getElement().debugChunk));
          Log.warn (new Log.SimpleMessage("+            added: Col=" , new Integer(root.getCol()),
                                                            "  Row=" , new Integer(root.getRow())));
          */
          pos.setInvalidCell(true);
        }
      }
    }

    /**
     * Returns the list of backgrounds of this element.
     *
     * @return the collected backgrounds of the element.
     */
    public List getBackground()
    {
      return backGrounds;
    }

    /**
     * Returns the data cell for this element. This can be null if no data cell
     * has been defined.
     *
     * @return the data cell or null, if this element does not have any data defined.
     */
    public TableGridPosition getRoot()
    {
      return root;
    }

    /**
     * Creates a string representation of this Element.
     *
     * @return a string representation of the element for debugging purposes.
     */
    public String toString()
    {
      final StringBuffer buffer = new StringBuffer();
      buffer.append("TableGridLayout.Element={root=");
      buffer.append(root);
      buffer.append(", backgrounds=");
      buffer.append(backGrounds);
      buffer.append("}");
      return buffer.toString();
    }
  }

  /** The table data as table. */
  private Object data[][];
  /** the collected xcuts, sorted. */
  private int[] xCuts;
  /** the collected ycuts, sorted. */
  private int[] yCuts;
  /** the maximum horizontal position the table ever reached. */
  private int maxX;
  /** the maximum vertical position the table ever reached. */
  private int maxY;

  /**
   * Creates a new TableGridLayout.
   *
   * @param pxCuts the collected horizontal cell bounds from the TableGrid,.
   * @param pyCuts the collected vertical cell bounds from the TableGrid.
   * @param positions the positions collected by the table grid.
   */
  public TableGridLayout(final int[] pxCuts, final int[] pyCuts, final TableCellData[] positions)
  {
    this.xCuts = new int[pxCuts.length];
    this.yCuts = new int[pyCuts.length];

    System.arraycopy(pxCuts, 0, xCuts, 0, pxCuts.length);
    System.arraycopy(pyCuts, 0, yCuts, 0, pyCuts.length);

    Arrays.sort(xCuts);
    Arrays.sort(yCuts);

    // +1 for outer boundry ...
    final int width = xCuts.length;
    final int height = yCuts.length;
/*
    Log.info ("Created GridLayout with " + width + ", " + height);

    for (int i = 0; i < xCuts.length; i++)
    {
      Log.info ("X-Cuts: " + xCuts[i]);
    }
*/
    data = new Object[width][height];

    for (int i = 0; i < positions.length; i++)
    {
      final TableCellData pos = positions[i];
      add(pos);
    }
  }

  /**
   * Adds the table cell data position into the table grid. The coordinates are
   * calculated by using the sorted x- and y-cuts.
   *
   * @param pos the new position that should be added into the grid
   */
  protected void add(final TableCellData pos)
  {
    final Rectangle2D bounds = pos.getBounds();

    final int maxBoundsX = (int) (bounds.getX() + bounds.getWidth());
    final int maxBoundsY = (int) (bounds.getY() + bounds.getHeight());

    final int col = findBoundary(xCuts, (int) bounds.getX());
    final int row = findBoundary(yCuts, (int) bounds.getY());
    final int colspan = Math.max(1, findBoundary(xCuts, maxBoundsX, true) - col);
    final int rowspan = Math.max(1, findBoundary(yCuts, maxBoundsY, true) - row);
    final TableGridPosition gPos = new TableGridPosition(pos, col, row, colspan, rowspan);

/*
    Log.info ("AddTablePos: Col=" + gPos.getCol() +
              "; Row= " + gPos.getRow() +
              "; ColSpan=" + gPos.getColSpan() +
              "; RowSpan=" + gPos.getRowSpan() + "; -> " + pos.debugChunk + " Bounds: "+ bounds);
*/
/*
    if (pos instanceof TableBandArea)
    {
      Log.debug ("DebugChunk: " + pos.debugChunk);
      Log.debug ("gPos.getCol: " + gPos.getCol() + " -> " + getColumnStart(gPos.getCol()));
      Log.debug ("gPos.getRow: " + gPos.getRow() + " -> " + getRowStart(gPos.getRow()));
      Log.debug ("gPos.getColSpan: " + gPos.getColSpan() + " -> "
                 + getColumnEnd(gPos.getColSpan() + gPos.getCol() - 1));
      Log.debug ("gPos.getRowSpan: " + gPos.getRowSpan() + " -> "
                 + getRowEnd(gPos.getRowSpan() + gPos.getRow() - 1));
    }
*/
    final int startY = gPos.getRow();
    final int endY = gPos.getRow() + gPos.getRowSpan();
    // calculated the x and y position in the table, now add it to the element.
    for (int posY = startY; posY < endY; posY++)
    {
      final int startX = gPos.getCol();
      final int endX = gPos.getCol() + gPos.getColSpan();
      for (int posX = startX; posX < endX; posX++)
      {
        addToGrid(posX, posY, gPos);
      }
    }

    this.maxX = Math.max(this.maxX, maxBoundsX);
    this.maxY = Math.max(this.maxY, maxBoundsY);
  }

  /**
   * Adds the gridposition into the table, positionated at the cell (posX, posY).
   *
   * @param posX the x position within the tablegrid.
   * @param posY the y position within the tablegrid.
   * @param gPos the TableGridPosition that should be added to the table.
   *
   * @throws IndexOutOfBoundsException if posX or posY are invalid.
   * @throws NullPointerException if the given table grid position is invalid
   */
  protected void addToGrid(final int posX, final int posY, final TableGridPosition gPos)
  {
    if (gPos == null)
    {
      throw new NullPointerException();
    }

    if (posX >= getWidth() || posX < 0)
    {
      throw new IndexOutOfBoundsException("X: " + posX + " > " + getWidth());
    }
    if (posY >= getHeight() || posY < 0)
    {
      throw new IndexOutOfBoundsException("Y: " + posY + " > " + getHeight());
    }
    final Object o = data[posX][posY];
    if (o == null)
    {
      final Element e = new Element();
      e.add(gPos);
      data[posX][posY] = e;

    }
    else
    {
      final Element e = (Element) o;
      e.add(gPos);
    }
  }

  /**
   * Returns the element located in the specified cell.
   *
   * @param x the table column
   * @param y the table row
   * @return the element, or null, if there is no element defined.
   */
  public Element getData(final int x, final int y)
  {
    return (Element) data[x][y];
  }

  /**
   * Returns the number of columns of the table.
   *
   * @return the width of the table, the number of columns.
   */
  public int getWidth()
  {
    return xCuts.length;
  }

  /**
   * Returns the number of rows of the table.
   *
   * @return the height of the table, the number of rows.
   */
  public int getHeight()
  {
    return yCuts.length;
  }

  /**
   * Returns the start position of the given column in points.
   *
   * @param column the column
   * @return the position of the column in points
   */
  public int getColumnStart(final int column)
  {
    return xCuts[column];
  }

  /**
   * Returns the start position of the given row in points.
   *
   * @param row the row
   * @return the position of the row in points
   */
  public int getRowStart(final int row)
  {
    return yCuts[row];
  }

  /**
   * Returns the end position of the given column in points.
   *
   * @param column the column
   * @return the end position of the column in points
   */
  public int getColumnEnd(final int column)
  {
    if (column == xCuts.length - 1)
    {
      return maxX;
    }
    else
    {
      return getColumnStart(column + 1);
    }
  }

  /**
   * Returns the start position of the given row in points.
   *
   * @param row the row
   * @return the end position of the column in points
   */
  public int getRowEnd(final int row)
  {
    if (row == yCuts.length - 1)
    {
      return maxY;
    }
    else
    {
      return getRowStart(row + 1);
    }
  }

  /**
   * Tries to find the cell position of the value <code>value</code>. If the position
   * was not found in the data array, then the next lower position is returned.
   *
   * @param data the data where to find the value
   * @param value the value that is searched in the data array.
   * @return the position of the value in the array or the next lower position.
   */
  private static int findBoundary(final int[] data, final int value)
  {
    return findBoundary(data, value, false);
  }

  /**
   * Tries to find the cell position of the value <code>value</code>. If the position
   * was not found in the data array, then the position of the first element greater or
   * equal or the value is returned.
   *
   * @param data the data where to find the value
   * @param value the value that is searched in the data array.
   * @param upperLimit set to true, if index of the first element greater or equal to
   * the given value is returned, else the first element lesser or equal the value is
   * returned.
   * @return the position of the value in the array or the next lower position.
   */
  private static int findBoundary(final int[] data, final int value, final boolean upperLimit)
  {
    for (int i = 0; i < data.length; i++)
    {
      final int dV = data[i];
      if (dV == value)
      {
        return i;
      }
      if (dV > value)
      {
        if (i == 0)
        {
          return 0;
        }
        else
        {
          if (upperLimit)
          {
            return i;
          }
          else
          {
            return i - 1;
          }
        }
      }
    }
    return data.length;
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -