Package org.pentaho.reporting.designer.core.actions.elements

Source Code of org.pentaho.reporting.designer.core.actions.elements.SelectCrosstabBandAction

/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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.
*
* Copyright (c) 2002-2013 Pentaho Corporation..  All rights reserved.
*/

package org.pentaho.reporting.designer.core.actions.elements;

import java.awt.event.ActionEvent;
import java.util.ArrayList;
import javax.swing.Action;

import org.pentaho.reporting.designer.core.ReportDesignerContext;
import org.pentaho.reporting.designer.core.actions.AbstractDesignerContextAction;
import org.pentaho.reporting.designer.core.actions.ActionMessages;
import org.pentaho.reporting.designer.core.actions.ToggleStateAction;
import org.pentaho.reporting.designer.core.editor.ReportDocumentContext;
import org.pentaho.reporting.designer.core.model.selection.DocumentContextSelectionModel;
import org.pentaho.reporting.designer.core.util.IconLoader;
import org.pentaho.reporting.engine.classic.core.AbstractReportDefinition;
import org.pentaho.reporting.engine.classic.core.Band;
import org.pentaho.reporting.engine.classic.core.CrosstabCell;
import org.pentaho.reporting.engine.classic.core.CrosstabCellBody;
import org.pentaho.reporting.engine.classic.core.CrosstabColumnGroup;
import org.pentaho.reporting.engine.classic.core.CrosstabColumnGroupBody;
import org.pentaho.reporting.engine.classic.core.CrosstabElement;
import org.pentaho.reporting.engine.classic.core.CrosstabGroup;
import org.pentaho.reporting.engine.classic.core.CrosstabHeader;
import org.pentaho.reporting.engine.classic.core.CrosstabOtherGroup;
import org.pentaho.reporting.engine.classic.core.CrosstabOtherGroupBody;
import org.pentaho.reporting.engine.classic.core.CrosstabRowGroup;
import org.pentaho.reporting.engine.classic.core.CrosstabRowGroupBody;
import org.pentaho.reporting.engine.classic.core.CrosstabSummaryHeader;
import org.pentaho.reporting.engine.classic.core.CrosstabTitleHeader;
import org.pentaho.reporting.engine.classic.core.Element;
import org.pentaho.reporting.engine.classic.core.Group;
import org.pentaho.reporting.engine.classic.core.GroupBody;
import org.pentaho.reporting.engine.classic.core.GroupHeader;

/**
* This class handle the select crosstab action.  This action is invoked from the Crosstab subreport toolbar.
* Each time user clicks on the button, a different section of the crosstab is selected where all elements
* inside the section are selected,
*
* @author Sulaiman Karmali
*/
public class SelectCrosstabBandAction extends AbstractDesignerContextAction implements ToggleStateAction
{
  private DocumentContextSelectionModel selectionModel;

  private ArrayList<Element> otherGroupBodyList;
  private ArrayList<Element> rowGroupBodyList;
  private ArrayList<Element> columnGroupBodyList;
  private ArrayList<Element> cellBodyList;
  private ArrayList<Element> noneList;
  private ArrayList<Element> allElementsList;

  private CrosstabSelectionBandState selectionBandState;

  private enum CrosstabSelectionBandState
  {
    NONE()    {public CrosstabSelectionBandState getNextState() {return OTHER;}
               public CrosstabSelectionBandState getCurrentState() {return NONE;}},
    OTHER()   {public CrosstabSelectionBandState getNextState() {return ROW;}
               public CrosstabSelectionBandState getCurrentState() {return OTHER;}},
    ROW()     {public CrosstabSelectionBandState getNextState() {return COLUMN;}
               public CrosstabSelectionBandState getCurrentState() {return ROW;}},
    COLUMN()  {public CrosstabSelectionBandState getNextState() {return CELL;}
               public CrosstabSelectionBandState getCurrentState() {return COLUMN;}},
    CELL()    {public CrosstabSelectionBandState getNextState() {return ALL;}
               public CrosstabSelectionBandState getCurrentState() {return CELL;}},
    ALL()     {public CrosstabSelectionBandState getNextState() {return NONE;}
               public CrosstabSelectionBandState getCurrentState() {return ALL;}};

    public abstract CrosstabSelectionBandState getNextState();
    public abstract CrosstabSelectionBandState getCurrentState();
  }

  public SelectCrosstabBandAction()
  {
    putValue(Action.SELECTED_KEY, Boolean.TRUE);
    putValue(Action.NAME, ActionMessages.getString("SelectCrosstabBandAction.Text"));
    putValue(Action.SHORT_DESCRIPTION, ActionMessages.getString("SelectCrosstabBandAction.Description"));
    putValue(Action.MNEMONIC_KEY, ActionMessages.getOptionalMnemonic("SelectCrosstabBandAction.Mnemonic"));
    putValue(Action.SMALL_ICON, IconLoader.getInstance().getSelectCrosstabBandCommand());
    putValue(Action.ACCELERATOR_KEY, ActionMessages.getOptionalKeyStroke("SelectCrosstabBandAction.Accelerator"));

    selectionBandState = CrosstabSelectionBandState.NONE;

    otherGroupBodyList = new ArrayList<Element>();
    rowGroupBodyList = new ArrayList<Element>();
    columnGroupBodyList = new ArrayList<Element>();
    cellBodyList = new ArrayList<Element>();
    noneList = new ArrayList<Element>();    // This will always be empty
    allElementsList = new ArrayList<Element>();

    setEnabled(true);
  }

  private ArrayList<Element> getNextSelectionList()
  {
    selectionBandState = selectionBandState.getNextState();
    switch (selectionBandState)
    {
      case NONE:
        return noneList;
      case OTHER:
        return otherGroupBodyList;
      case ROW:
        return rowGroupBodyList;
      case COLUMN:
        return columnGroupBodyList;
      case CELL:
        return cellBodyList;
      case ALL:
        return allElementsList;
    }

    return noneList;
  }


  public boolean isSelected()
  {
    return Boolean.TRUE.equals(getValue(Action.SELECTED_KEY));
  }

  public void setSelected(final boolean selected)
  {
    putValue(Action.SELECTED_KEY, selected);
  }


  public void initialize()
  {
    allElementsList.clear();
    otherGroupBodyList.clear();
    rowGroupBodyList.clear();
    columnGroupBodyList.clear();
    cellBodyList.clear();
  }

  private DocumentContextSelectionModel getSelectionModel()
  {
    if (selectionModel == null)
    {
      final ReportDesignerContext reportDesignerContext = getReportDesignerContext();
      final ReportDocumentContext activeContext = reportDesignerContext.getActiveContext();
      selectionModel = activeContext.getSelectionModel();
    }

    return selectionModel;
  }

  public ArrayList<Element> getOtherGroupBodyList()
  {
    return otherGroupBodyList;
  }

  public void buildCrosstabLists()
  {
    final ReportDesignerContext reportDesignerContext = getReportDesignerContext();
    if (reportDesignerContext == null)
    {
      return;
    }

    // Clear lists just in case something changed.
    initialize();

    final ReportDocumentContext activeContext = reportDesignerContext.getActiveContext();
    selectionModel = getSelectionModel();

    final AbstractReportDefinition reportDefinition = activeContext.getReportDefinition();
    if (reportDefinition instanceof CrosstabElement)
    {
      final CrosstabElement crosstabElement = (CrosstabElement)reportDefinition;
      final Group group = crosstabElement.getRootGroup();
      if (group instanceof CrosstabGroup)
      {
        final CrosstabGroup crosstabGroup = (CrosstabGroup)group;
        final GroupBody crosstabGroupBody = crosstabGroup.getBody();

        // Start with the other group and work our way deeper recursively.
        // Note: Other Group is optional.
        if (crosstabGroupBody instanceof CrosstabOtherGroupBody)
        {
          final CrosstabOtherGroup crosstabOtherGroup = ((CrosstabOtherGroupBody)crosstabGroupBody).getGroup();
          buildCrosstabOtherRowGroupBands(crosstabOtherGroup);
        }
        else if (crosstabGroupBody instanceof CrosstabRowGroupBody)
        {
          final CrosstabRowGroupBody crosstabRowGroupBody = (CrosstabRowGroupBody)crosstabGroup.getBody();
          buildCrosstabRowGroupBands(crosstabRowGroupBody);
        }

        // Create an array of all elements.
        allElementsList.addAll(otherGroupBodyList);
        allElementsList.addAll(rowGroupBodyList);
        allElementsList.addAll(columnGroupBodyList);
        allElementsList.addAll(cellBodyList);
      }
    }
  }


  /**
   * Invoked when an action occurs.  We are going to select all the elements inside
   * of a crosstab band (row, column, or cell) every time actionPerformed is called -
   * usually when user clicks on selection icon in subreport toolbar
   */
  public void actionPerformed(final ActionEvent e)
  {
    // We want to build the row, column and cell lists only once.  These lists
    // contain all the elements for a particular section of the crosstab.
    if (allElementsList.isEmpty())
    {
      buildCrosstabLists();
    }

    // Select the next crosstab band
    selectCrosstabElements(getNextSelectionList());
  }

  /**
   * Iterate over the elements in the main Crosstab Cell body.
   * This is where the data of a crosstab is presented in a row/column fashion
   * @param crosstabCellBody - Contains the body of all the crosstab cells
   */
  private void buildCrosstabCellBands(final CrosstabCellBody crosstabCellBody)
  {
    if (crosstabCellBody == null)
    {
      return;
    }

    buildCrosstabElementsList(crosstabCellBody.getHeader(), cellBodyList);

    final int count = crosstabCellBody.getElementCount();
    for (int i = 0; i < count; i++)
    {
      final Element element = crosstabCellBody.getElement(i);
      if (element instanceof CrosstabCell)
      {
        final CrosstabCell cell = (CrosstabCell)element;
        final int cellCount = cell.getElementCount();
        for (int c = 0; c < cellCount; c++)
        {
          final Element cellElement = cell.getElement(c);
          cellBodyList.add(cellElement);
        }
      }
    }
  }

  /**
   * Iterate over the Crosstab's Column Group Body.  This is where the Crosstab column title, column header
   * and column's summary header live ('crosstab-row-group-body')
   * @param crosstabColumnGroupBody
   */
  private void buildCrosstabColumnGroupBands(final CrosstabColumnGroupBody crosstabColumnGroupBody)
  {
    if (crosstabColumnGroupBody == null)
    {
      return;
    }

    final CrosstabColumnGroup crosstabColumnGroup = crosstabColumnGroupBody.getGroup();
    final CrosstabTitleHeader crosstabTitleHeader = crosstabColumnGroup.getTitleHeader();
    final CrosstabHeader crosstabHeader = crosstabColumnGroup.getHeader();
    final CrosstabSummaryHeader crosstabSummaryHeader = crosstabColumnGroup.getSummaryHeader();

    buildCrosstabElementsList(crosstabTitleHeader, columnGroupBodyList);
    buildCrosstabElementsList(crosstabHeader, columnGroupBodyList);
    buildCrosstabElementsList(crosstabSummaryHeader, columnGroupBodyList);

    final GroupBody body = crosstabColumnGroup.getBody();
    if (body instanceof CrosstabColumnGroupBody)
    {
      // Recurse to the next column-group
      buildCrosstabColumnGroupBands((CrosstabColumnGroupBody)body);
    }
    else if (body instanceof CrosstabCellBody)
    {
      // We are done with column-groups, lets start the cell band (row/col of cells containing
      // values of the crosstab).  This is the most granular we go.
      buildCrosstabCellBands((CrosstabCellBody)body);
    }
  }


  /**
   * Iterate over the Crosstab's Row Group Body.  This is where the Crosstab's row title header, row header,
   * and row summary live ('crosstab-row-group-body')
   * @param crosstabRowGroupBody
   */
  private void buildCrosstabRowGroupBands(final CrosstabRowGroupBody crosstabRowGroupBody)
  {
    if (crosstabRowGroupBody == null)
    {
      return;
    }

    final CrosstabRowGroup crosstabRowGroup = crosstabRowGroupBody.getGroup();
    final CrosstabTitleHeader crosstabTitleHeader = crosstabRowGroup.getTitleHeader();
    final CrosstabHeader crosstabHeader = crosstabRowGroup.getHeader();
    final CrosstabSummaryHeader crosstabSummaryHeader = crosstabRowGroup.getSummaryHeader();

    buildCrosstabElementsList(crosstabTitleHeader, rowGroupBodyList);
    buildCrosstabElementsList(crosstabHeader, rowGroupBodyList);
    buildCrosstabElementsList(crosstabSummaryHeader, rowGroupBodyList);

    final GroupBody body = crosstabRowGroup.getBody();
    if (body instanceof CrosstabRowGroupBody)
    {
      // Recurse to add additional row-groups
      buildCrosstabRowGroupBands((CrosstabRowGroupBody)body);
    }
    else if (body instanceof CrosstabColumnGroupBody)
    {
      // We are done with row-groups, let's now deal with column-groups
      buildCrosstabColumnGroupBands((CrosstabColumnGroupBody)body);
    }
  }

  /**
   * Iterate over the Crosstab's Other Group Body.  This is where the Crosstab's Group Header lives ('crosstab-other-group')
   * @param crosstabOtherGroup
   */

  private void buildCrosstabOtherRowGroupBands(final CrosstabOtherGroup crosstabOtherGroup)
  {
    if (crosstabOtherGroup == null)
    {
      return;
    }

    final GroupHeader otherGroupHeader = (GroupHeader)crosstabOtherGroup.getElement(0);
    for (int i = 0; i < otherGroupHeader.getElementCount(); i++)
    {
      final Element element = otherGroupHeader.getElement(i);
      otherGroupBodyList.add(element);
    }

    // We got a Other Group header.  If we have multiple group headers, we recurse.
    // Otherwise we can now get the elements from other parts of the crosstab
    final GroupBody groupBody = crosstabOtherGroup.getBody();
    if (groupBody instanceof CrosstabOtherGroupBody)
    {
      buildCrosstabOtherRowGroupBands(((CrosstabOtherGroupBody)groupBody).getGroup());
    }
    else if (groupBody instanceof CrosstabRowGroupBody)
    {
      buildCrosstabRowGroupBands((CrosstabRowGroupBody)groupBody);
    }
  }

  /**
   * Iterate over a Band's elements selecting each element.
   * @param elementsList - Element list containing a section of the crosstab that we want to select
   */
  private void selectCrosstabElements(final ArrayList<Element> elementsList)
  {
    if (elementsList == null)
    {
      return;
    }

    if (selectionModel == null) {
      selectionModel = getSelectionModel();
    }

    // First clear any previously selected elements
    selectionModel.clearSelection();

    // Select elements
    selectionModel.setSelectedElements(elementsList.toArray());
  }

  /**
   * For caching purposes, we iterate over the elements in a band and add the elements to list
   * @param band
   * @param elementsList - list containing elements that are part of the band.
   */
  private void buildCrosstabElementsList(final Band band, final ArrayList<Element> elementsList)
  {
    if ((band == null) || (elementsList == null))
    {
      return;
    }

    final int count = band.getElementCount();
    for (int i = 0; i < count; i++)
    {
      final Element element = band.getElement(i);
      elementsList.add(element);
    }
  }
}
TOP

Related Classes of org.pentaho.reporting.designer.core.actions.elements.SelectCrosstabBandAction

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.