Package ar.com.fdvs.dj.core.layout

Source Code of ar.com.fdvs.dj.core.layout.ClassicLayoutManager

/*
* DynamicJasper: A library for creating reports dynamically by specifying
* columns, groups, styles, etc. at runtime. It also saves a lot of development
* time in many cases! (http://sourceforge.net/projects/dynamicjasper)
*
* Copyright (C) 2008  FDV Solutions (http://www.fdvsolutions.com)
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*
*
*/

package ar.com.fdvs.dj.core.layout;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.jasperreports.crosstabs.design.JRDesignCrosstab;
import net.sf.jasperreports.engine.JRElement;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRGraphicElement;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.design.JRDesignBand;
import net.sf.jasperreports.engine.design.JRDesignBreak;
import net.sf.jasperreports.engine.design.JRDesignElement;
import net.sf.jasperreports.engine.design.JRDesignElementGroup;
import net.sf.jasperreports.engine.design.JRDesignExpression;
import net.sf.jasperreports.engine.design.JRDesignGroup;
import net.sf.jasperreports.engine.design.JRDesignImage;
import net.sf.jasperreports.engine.design.JRDesignRectangle;
import net.sf.jasperreports.engine.design.JRDesignStyle;
import net.sf.jasperreports.engine.design.JRDesignSubreport;
import net.sf.jasperreports.engine.design.JRDesignSubreportParameter;
import net.sf.jasperreports.engine.design.JRDesignTextField;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import ar.com.fdvs.dj.core.CoreException;
import ar.com.fdvs.dj.core.DJConstants;
import ar.com.fdvs.dj.core.FontHelper;
import ar.com.fdvs.dj.core.registration.ColumnsGroupVariablesRegistrationManager;
import ar.com.fdvs.dj.domain.AutoText;
import ar.com.fdvs.dj.domain.DJCalculation;
import ar.com.fdvs.dj.domain.DJCrosstab;
import ar.com.fdvs.dj.domain.DJGroupLabel;
import ar.com.fdvs.dj.domain.DJLabel;
import ar.com.fdvs.dj.domain.DynamicJasperDesign;
import ar.com.fdvs.dj.domain.DynamicReportOptions;
import ar.com.fdvs.dj.domain.ImageBanner;
import ar.com.fdvs.dj.domain.Style;
import ar.com.fdvs.dj.domain.constants.Border;
import ar.com.fdvs.dj.domain.constants.GroupLayout;
import ar.com.fdvs.dj.domain.constants.LabelPosition;
import ar.com.fdvs.dj.domain.constants.Transparency;
import ar.com.fdvs.dj.domain.entities.DJGroup;
import ar.com.fdvs.dj.domain.entities.DJGroupVariable;
import ar.com.fdvs.dj.domain.entities.Subreport;
import ar.com.fdvs.dj.domain.entities.SubreportParameter;
import ar.com.fdvs.dj.domain.entities.columns.AbstractColumn;
import ar.com.fdvs.dj.domain.entities.columns.GlobalGroupColumn;
import ar.com.fdvs.dj.domain.entities.columns.PercentageColumn;
import ar.com.fdvs.dj.domain.entities.columns.PropertyColumn;
import ar.com.fdvs.dj.util.ExpressionUtils;
import ar.com.fdvs.dj.util.LayoutUtils;
import ar.com.fdvs.dj.util.Utils;

/**
* Main Layout Manager recommended for most cases.</br>
* </br>
* It provides DJ full features (styles, groups, conditional styles, </br>
* expressions, group and total variables, etc)
*/
public class ClassicLayoutManager extends AbstractLayoutManager {

  protected static final String PAGE_BREAK_FOR_ = "pageBreak_for_";

  protected static final int SUBREPORT_DEFAULT_HEIGHT = 30;

  private static final Log log = LogFactory.getLog(ClassicLayoutManager.class);

  protected static final String EXPRESSION_TRUE_WHEN_NOT_FIRST_PAGE = "new java.lang.Boolean(((Number)$V{PAGE_NUMBER}).doubleValue() != 1)";
  protected static final String EXPRESSION_TRUE_WHEN_FIRST_PAGE = "new java.lang.Boolean(((Number)$V{PAGE_NUMBER}).doubleValue() == 1)";

  protected Map referencesMap = new HashMap();

  public Map getReferencesMap() {
    return referencesMap;
  }

  protected void startLayout() {
    super.startLayout();
    generateTitleBand();
    generateHeaderBand();
    applyHeaderAutotexts();

    if (getReport().getColumnsGroups() != null)
      layoutGroups();
  }

  /**
   *
   */
  protected void applyHeaderAutotexts() {
    if (getReport().getAutoTexts() == null)
      return;
    /**
     * Apply the autotext in footer if any
     */
    JRDesignBand headerband = (JRDesignBand) getDesign().getPageHeader();
    if (headerband == null ) {
      headerband = new JRDesignBand();
      getDesign().setPageHeader(headerband);
    }

    ArrayList positions = new ArrayList();
    positions.add(HorizontalBandAlignment.LEFT);
    positions.add(HorizontalBandAlignment.CENTER);
    positions.add(HorizontalBandAlignment.RIGHT);

    ArrayList autotexts = new ArrayList(getReport().getAutoTexts());
    Collections.reverse(autotexts);

    int totalYoffset = findTotalOffset(positions,autotexts, AutoText.POSITION_HEADER);
    LayoutUtils.moveBandsElemnts(totalYoffset, headerband);

    for (Iterator iterator = positions.iterator(); iterator.hasNext();) {
      HorizontalBandAlignment currentAlignment = (HorizontalBandAlignment) iterator.next();
      int yOffset = 0;

      for (Iterator iter = getReport().getAutoTexts().iterator(); iter.hasNext();) {
        AutoText text = (AutoText) iter.next();
        if (text.getPosition() == AutoText.POSITION_HEADER && text.getAlignment().equals(currentAlignment)) {
          CommonExpressionsHelper.add(yOffset,(DynamicJasperDesign) getDesign(), this, headerband, text);
          yOffset += text.getHeight().intValue();
        }
      }
    }

    /** END */
  }

  /**
   * Finds the highest sum of height for each possible alignment (left, center, right)
   * @param aligments
   * @param autotexts
   * @return
   */
  protected int findTotalOffset(ArrayList aligments, ArrayList autotexts, byte position) {
    int total = 0;
    for (Iterator iterator = aligments.iterator(); iterator.hasNext();) {
      HorizontalBandAlignment currentAlignment = (HorizontalBandAlignment) iterator.next();
      int aux = 0;
      for (Iterator iter = getReport().getAutoTexts().iterator(); iter.hasNext();) {
        AutoText autotext = (AutoText) iter.next();
        if (autotext.getPosition() == position && currentAlignment.equals(autotext.getAlignment())) {
          aux += autotext.getHeight().intValue();
        }
      }
      if (aux > total)
        total = aux;
    }
    return total;
  }

  protected void endLayout() {
    super.endLayout();
    applyBanners();
    applyFooterAutotexts();
    setBandsFinalHeight();
  }

  protected void applyFooterAutotexts() {
    if (getReport().getAutoTexts() == null)
      return;

    JRDesignBand footerband = (JRDesignBand) getDesign().getPageFooter();
    if (footerband == null ) {
      footerband = new JRDesignBand();
      getDesign().setPageFooter(footerband);
    }

    ArrayList positions = new ArrayList();
    positions.add(HorizontalBandAlignment.LEFT);
    positions.add(HorizontalBandAlignment.CENTER);
    positions.add(HorizontalBandAlignment.RIGHT);

    for (Iterator iterator = positions.iterator(); iterator.hasNext();) {
      HorizontalBandAlignment currentAlignment = (HorizontalBandAlignment) iterator.next();
      int yOffset = 0;
      /**
       * Apply the autotext in footer if any
       */
      for (Iterator iter = getReport().getAutoTexts().iterator(); iter.hasNext();) {
        AutoText autotext = (AutoText) iter.next();
        if (autotext.getPosition() == AutoText.POSITION_FOOTER && autotext.getAlignment().equals(currentAlignment) ) {
          CommonExpressionsHelper.add(yOffset,(DynamicJasperDesign) getDesign(), this, footerband, autotext);
          yOffset += autotext.getHeight().intValue();
        }
      }

    }
  }

  /**
   * Returns a list with the columns that are visible.
   * Invisible column are the one whose group is configured with hideColumn = true (in the GroupLayout)
   * @return
   */
  protected List getVisibleColumns() {
    List visibleColums = new ArrayList(getReport().getColumns());
    for (Iterator iterator = getReport().getColumnsGroups().iterator(); iterator.hasNext();) {
      DJGroup group = (DJGroup) iterator.next();
      if (group.getLayout().isHideColumn()){
        visibleColums.remove(group.getColumnToGroupBy());
      }
    }
    return visibleColums;
  }

  /**
   * Create the image elements for the banners tha goes into the
   * title and header bands depending on the case
   *
   */
  protected void applyBanners() {
    /**
     * First create image banners for the first page only
     */
    JRDesignBand title = (JRDesignBand) getDesign().getTitle();
    //if there is no title band, but there are banner images for the first page, we create a title band
    if (title == null && !getReport().getOptions().getFirstPageImageBanners().isEmpty()){
      title = new JRDesignBand();
      getDesign().setTitle(title);
    }
    applyImageBannersToBand(title,getReport().getOptions().getFirstPageImageBanners().values(),null);

    /**
     * Now create image banner for the rest of the pages
     */
    JRDesignBand pageHeader = (JRDesignBand) getDesign().getPageHeader();
    //if there is no title band, but there are banner images for the first page, we create a title band
    if (pageHeader == null && !getReport().getOptions().getImageBanners().isEmpty()){
      pageHeader = new JRDesignBand();
      getDesign().setPageHeader(pageHeader);
    }
    JRDesignExpression printWhenExpression = null;
    if (!getReport().getOptions().getFirstPageImageBanners().isEmpty()){
      printWhenExpression = new JRDesignExpression();
      printWhenExpression.setValueClass(Boolean.class);
      printWhenExpression.setText(EXPRESSION_TRUE_WHEN_NOT_FIRST_PAGE);
    }
    applyImageBannersToBand(pageHeader,getReport().getOptions().getImageBanners().values(),printWhenExpression);


  }
  /**
   * Create the image elements for the banners tha goes into the
   * title band
   * @param printWhenExpression
   *
   */
  protected void applyImageBannersToBand(JRDesignBand band, Collection imageBanners, JRDesignExpression printWhenExpression ) {
    int maxHeight = 0;
    for (Iterator iter = imageBanners.iterator(); iter.hasNext();) {
      ImageBanner imageBanner = (ImageBanner) iter.next();
      if (imageBanner.getHeight() > maxHeight)
        maxHeight = imageBanner.getHeight();
    }

    if (band != null){
      //move everything down
      for (Iterator iter =band.getChildren().iterator(); iter.hasNext();) {
        JRDesignElement element = (JRDesignElement) iter.next();
        element.setY(element.getY() + maxHeight);
      }

      for (Iterator iter = imageBanners.iterator(); iter.hasNext();) {
        ImageBanner imageBanner = (ImageBanner) iter.next();
        String path = "\"" + imageBanner.getImagePath().replaceAll("\\\\", "/") + "\"";
        JRDesignImage image = new JRDesignImage(new JRDesignStyle().getDefaultStyleProvider());
        JRDesignExpression imageExp = new JRDesignExpression();
        imageExp.setText(path);

        imageExp.setValueClass(String.class);
        image.setExpression(imageExp);
        image.setHeight(imageBanner.getHeight());
        image.setWidth(imageBanner.getWidth());
        image.setPrintWhenExpression(printWhenExpression);
        image.setRemoveLineWhenBlank(true);
        image.setScaleImage(imageBanner.getScaleMode().getValue());
       
        if (imageBanner.getAlign() == ImageBanner.ALIGN_LEFT)
          image.setX(0);
        else if (imageBanner.getAlign() == ImageBanner.ALIGN_RIGHT)
          image.setX(getReport().getOptions().getPage().getWidth() -  getReport().getOptions().getLeftMargin().intValue() - getReport().getOptions().getRightMargin().intValue() - imageBanner.getWidth());
        else if (imageBanner.getAlign() == ImageBanner.ALIGN_CENTER){
          int x = (getReport().getOptions().getPage().getWidth() -
              getReport().getOptions().getRightMargin().intValue() -
              getReport().getOptions().getLeftMargin().intValue() - imageBanner.getWidth()) / 2;
          image.setX(getReport().getOptions().getLeftMargin().intValue() + x);
        }

        image.setY(0);
        band.addElement(image);

      }
      band.setHeight(band.getHeight() + maxHeight);
    }
  }

  /**
   * Adds title and subtitle to the TitleBand when it applies.
   * If title is not present then subtitle will be ignored
   */
  protected void generateTitleBand() {
    log.debug("Generating title band...");
    JRDesignBand band = (JRDesignBand) getDesign().getPageHeader();
    int yOffset = 0;

    //If title is not present then subtitle will be ignored
    if (getReport().getTitle() == null)
      return;

    if (band != null && !getDesign().isTitleNewPage()){
      //Title and subtitle comes afer the page header
      yOffset = band.getHeight();

    } else {
      band = (JRDesignBand) getDesign().getTitle();
      if (band == null){
        band = new JRDesignBand();
        getDesign().setTitle(band);
      }
    }

    JRDesignExpression printWhenExpression = new JRDesignExpression();
    printWhenExpression.setValueClass(Boolean.class);
    printWhenExpression.setText(EXPRESSION_TRUE_WHEN_FIRST_PAGE);

    JRDesignTextField title = new JRDesignTextField();
    JRDesignExpression exp = new JRDesignExpression();
    if (getReport().isTitleIsJrExpression()){
      exp.setText(getReport().getTitle());
    }else {
      exp.setText("\"" + Utils.escapeTextForExpression( getReport().getTitle()) + "\"");
    }
    exp.setValueClass(String.class);
    title.setExpression(exp);
    title.setWidth(getReport().getOptions().getPrintableWidth());
    title.setHeight(getReport().getOptions().getTitleHeight().intValue());
    title.setY(yOffset);   
    title.setPrintWhenExpression(printWhenExpression);
    title.setRemoveLineWhenBlank(true);
    applyStyleToElement(getReport().getTitleStyle(), title);
    title.setStretchType(JRGraphicElement.STRETCH_TYPE_NO_STRETCH);
    band.addElement(title);

    JRDesignTextField subtitle = new JRDesignTextField();
    if (getReport().getSubtitle() != null) {
      JRDesignExpression exp2 = new JRDesignExpression();
      exp2.setText("\"" + getReport().getSubtitle() + "\"");
      exp2.setValueClass(String.class);
      subtitle.setExpression(exp2);
      subtitle.setWidth(getReport().getOptions().getPrintableWidth());
      subtitle.setHeight(getReport().getOptions().getSubtitleHeight().intValue());
      subtitle.setY(title.getY() + title.getHeight());
      subtitle.setPrintWhenExpression(printWhenExpression);
      subtitle.setRemoveLineWhenBlank(true);
      applyStyleToElement(getReport().getSubtitleStyle(), subtitle);
      title.setStretchType(JRGraphicElement.STRETCH_TYPE_NO_STRETCH);
      band.addElement(subtitle);
    }

  }

  /**
   * Layout columns in groups by reading the corresponding report options.
   * @throws LayoutException
   */
  protected void layoutGroups() {
    log.debug("Starting groups layout...");
    for (Iterator iter = getReport().getColumnsGroups().iterator(); iter.hasNext();) {
      DJGroup columnsGroup = (DJGroup) iter.next();
      JRDesignGroup jgroup = getJRGroupFromDJGroup(columnsGroup);

      jgroup.setStartNewPage(columnsGroup.getStartInNewPage().booleanValue());
      jgroup.setStartNewColumn(columnsGroup.getStartInNewColumn().booleanValue());
      jgroup.setReprintHeaderOnEachPage(columnsGroup.getReprintHeaderOnEachPage().booleanValue());

      JRDesignBand header = (JRDesignBand) jgroup.getGroupHeader();
      JRDesignBand footer = (JRDesignBand) jgroup.getGroupFooter();
     
      //double check to prevent NPE
      if (header == null){
        header = new JRDesignBand();
        jgroup.setGroupHeader(header);
      }
      if (footer == null){
        footer = new JRDesignBand();
        jgroup.setGroupFooter(footer);
      }
     
      header.setHeight(columnsGroup.getHeaderHeight().intValue());
//      footer.setHeight( getFooterVariableHeight(columnsGroup));
      footer.setHeight( columnsGroup.getFooterHeight().intValue());

      header.setSplitAllowed(columnsGroup.isAllowHeaderSplit());
      footer.setSplitAllowed(columnsGroup.isAllowFooterSplit());

      if (columnsGroup.getLayout().isPrintHeaders()) {
        boolean found = false;
        boolean skipPreviousGroupHeaders = false;
        int groupIdx = getReport().getColumnsGroups().indexOf(columnsGroup);
        if (groupIdx>0){
          DJGroup prevG =  (DJGroup) getReport().getColumnsGroups().get(groupIdx-1);
                    if(!(prevG.getColumnToGroupBy() instanceof GlobalGroupColumn))
                        skipPreviousGroupHeaders = !prevG.getLayout().isShowValueForEachRow();
        }
        for (Iterator iterator =  getVisibleColumns().iterator(); iterator.hasNext();) {
          AbstractColumn col = (AbstractColumn) iterator.next();

          //If in a nested group, header for column prior to this groups column
          //depends on configuration

          if (col.equals(columnsGroup.getColumnToGroupBy())) {
            found = true;
          }

          if (!found && skipPreviousGroupHeaders){
            continue;
          }

          JRDesignTextField designTextField = createColumnNameTextField(columnsGroup, col);
          designTextField.setPositionType(JRDesignElement.POSITION_TYPE_FLOAT); //XXX changed to see what happens  (must come from the column position property)
          designTextField.setStretchType(JRDesignElement.STRETCH_TYPE_NO_STRETCH); //XXX changed to see what happens (must come from the column property)
          header.addElement(designTextField);
        }
      }
      DJGroupLabel label = columnsGroup.getFooterLabel()
      if (label != null /*&& !footerVariables.isEmpty()*/) {
        List footerVariables = columnsGroup.getFooterVariables();
        PropertyColumn col = columnsGroup.getColumnToGroupBy();
        JRDesignBand band = (JRDesignBand)jgroup.getGroupFooter();
        int x = 0, y = 0;
        //max width
        int width = getDesign().getPageWidth() - getDesign().getLeftMargin() - getDesign().getRightMargin();
        int height = label.getHeight();
        int yOffset = 0;
        if (label.getLabelPosition() == LabelPosition.LEFT) {
          DJGroupVariable lmvar = findLeftMostColumn(footerVariables);
       
          x = col.getPosX().intValue(); //label starts in the column-to-group-by x position
          y = findYOffsetForGroupLabel(band);
          if (lmvar != null) {
            AbstractColumn lmColumn = lmvar.getColumnToApplyOperation();
            width = lmColumn.getPosX().intValue() - x;
          }
          else
            width -= x;
          height = getFooterVariableHeight(columnsGroup);
        }
        else if (label.getLabelPosition() == LabelPosition.RIGHT) {
          DJGroupVariable rmvar = findRightMostColumn(footerVariables);         
         
          if (rmvar != null) {
            AbstractColumn rmColumn = rmvar.getColumnToApplyOperation();
            x = rmColumn.getPosX().intValue() + rmColumn.getWidth().intValue();
          }
          else
            x = col.getPosX().intValue(); //label starts in the column-to-group-by x position
          y = findYOffsetForGroupLabel(band);
          width -= x;
          height = getFooterVariableHeight(columnsGroup);
        }
        else if (label.getLabelPosition() == LabelPosition.TOP) {
          x = col.getPosX().intValue(); //label starts in the column-to-group-by x position
          width -= x;
          yOffset = height;
        }
        else if (label.getLabelPosition() == LabelPosition.BOTTOM) {
          x = col.getPosX().intValue(); //label starts in the column-to-group-by x position
          y = getFooterVariableHeight(columnsGroup);
          width -= x;
        }
        layoutGroupFooterLabels(columnsGroup, jgroup, x, y, width, height);
        layoutGroupVariables(columnsGroup, jgroup, yOffset);
      }
      else {
        layoutGroupVariables(columnsGroup, jgroup, 0);
      }
     
      layoutGroupSubreports(columnsGroup, jgroup);
      layoutGroupCrosstabs(columnsGroup, jgroup);
    }
  }

  /**
   * Creates needed textfields for general label in footer groups.
   * @param djgroup
   * @param jgroup
   */
  protected void layoutGroupFooterLabels(DJGroup djgroup, JRDesignGroup jgroup, int x, int y, int width, int height) {
    //List footerVariables = djgroup.getFooterVariables();
    DJGroupLabel label = djgroup.getFooterLabel();
   
    //if (label == null || footerVariables.isEmpty())
      //return;
   
    //PropertyColumn col = djgroup.getColumnToGroupBy();
    JRDesignBand band = (JRDesignBand)jgroup.getGroupFooter();

//    log.debug("Adding footer group label for group " + djgroup);
   
    /*DJGroupVariable lmvar = findLeftMostColumn(footerVariables);
    AbstractColumn lmColumn = lmvar.getColumnToApplyOperation();
    int width = lmColumn.getPosX().intValue()  - col.getPosX().intValue();
   
    int yOffset = findYOffsetForGroupLabel(band);*/
   
    JRDesignExpression labelExp;
    if (label.isJasperExpression()) //a text with things like "$F{myField}"
      labelExp = ExpressionUtils.createStringExpression(label.getText());
    else if (label.getLabelExpression() != null){
      labelExp = ExpressionUtils.createExpression(jgroup.getName() + "_labelExpression", label.getLabelExpression());
    } else //a simple text
      //labelExp = ExpressionUtils.createStringExpression("\""+ Utils.escapeTextForExpression(label.getText())+ "\"");   
      labelExp = ExpressionUtils.createStringExpression("\""+ label.getText() + "\"");
    JRDesignTextField labelTf = new JRDesignTextField();
    labelTf.setExpression(labelExp);
    labelTf.setWidth(width);
    labelTf.setHeight(height);
    labelTf.setX(x);
    labelTf.setY(y);
    //int yOffsetGlabel = labelTf.getHeight();       
    labelTf.setPositionType(JRDesignElement.POSITION_TYPE_FIX_RELATIVE_TO_TOP);
    applyStyleToElement(label.getStyle(), labelTf);
    band.addElement(labelTf);   
  }

  /**
   * Used to ensure that the general footer label will be at the same Y position as the variables in the band.
   * @param band
   * @return
   */
  private int findYOffsetForGroupLabel(JRDesignBand band) {
    int offset = 0;
    for (Iterator iterator = band.getChildren().iterator(); iterator.hasNext();) {
      JRDesignElement elem = (JRDesignElement) iterator.next();
      if (elem.getKey() != null && elem.getKey().startsWith("variable_for_column_")){
        offset = elem.getY();
        break;
      }
    }
    return offset;
  }

  /**
   * Looks for crosstabs in the groups, if any, it does the layout
   *
   * @param columnsGroup
   * @param jgroup
   */
  protected void layoutGroupCrosstabs(DJGroup columnsGroup,  JRDesignGroup jgroup) {
    for (Iterator iterator = columnsGroup.getHeaderCrosstabs().iterator(); iterator.hasNext();) {
      DJCrosstab djcross = (DJCrosstab) iterator.next();

      Dj2JrCrosstabBuilder djcb = new Dj2JrCrosstabBuilder();

      JRDesignCrosstab crosst = djcb.createCrosstab(djcross,this);
      JRDesignBand band = (JRDesignBand) jgroup.getGroupHeader();
      if (djcross.getBottomSpace() != 0){
        JRDesignRectangle rect = createBlankRectableCrosstab(djcross.getBottomSpace(), 0);
        LayoutUtils.moveBandsElemnts(rect.getHeight(), band);
        band.addElement(rect);
      }
     
      LayoutUtils.moveBandsElemnts(crosst.getHeight(), band);
      band.addElement(crosst);
      DJLabel caption = djcross.getCaption();
      if (caption!=null){
        JRDesignExpression captExp = null;
        if (caption.isJasperExpression()) //a text with things like "$F{myField}"
          captExp = ExpressionUtils.createStringExpression(caption.getText());
        else if (caption.getLabelExpression() != null){
          String name = "expression_for_label_at_header_of_group[" + getReport().getColumnsGroups().indexOf(columnsGroup)+"]_crosstab["+columnsGroup.getHeaderCrosstabs().indexOf(djcross)+"]";
          LayoutUtils.registerCustomExpressionParameter((DynamicJasperDesign) getDesign(), name , caption.getLabelExpression());
          captExp =   ExpressionUtils.createExpression(ExpressionUtils.createCustomExpressionInvocationText(name), caption.getLabelExpression().getClassName()) ;
          log.debug(ExpressionUtils.createCustomExpressionInvocationText(name));
        } else //a simple text
          captExp = ExpressionUtils.createStringExpression("\""+ Utils.escapeTextForExpression(caption.getText())+ "\"");
       
        JRDesignTextField captTf = new JRDesignTextField();
        captTf.setExpression(captExp );
        captTf.setHeight(caption.getHeight());
        captTf.setWidth(getReport().getOptions().getPrintableWidth());
        LayoutUtils.moveBandsElemnts(caption.getHeight(), band);
        band.addElement(captTf);
      }

      if (djcross.getTopSpace() != 0){
        LayoutUtils.moveBandsElemnts(djcross.getTopSpace(), band);
        JRDesignRectangle rect = createBlankRectableCrosstab(djcross.getBottomSpace(), 0);
        band.addElement(rect);
      }
    }

    for (Iterator iterator = columnsGroup.getFooterCrosstabs().iterator(); iterator.hasNext();) {
      DJCrosstab djcross = (DJCrosstab) iterator.next();

      Dj2JrCrosstabBuilder djcb = new Dj2JrCrosstabBuilder();

      JRDesignCrosstab crosst = djcb.createCrosstab(djcross,this);
      JRDesignBand band = (JRDesignBand) jgroup.getGroupFooter();
      int yOffset = LayoutUtils.findVerticalOffset(band);
      if (djcross.getTopSpace() != 0){
//        moveBandsElemnts(djcross.getTopSpace(), band);
        JRDesignRectangle rect = createBlankRectableCrosstab(djcross.getBottomSpace(), yOffset);
        rect.setPositionType(JRDesignElement.POSITION_TYPE_FIX_RELATIVE_TO_TOP);
        band.addElement(rect);
        crosst.setY(rect.getY() + rect.getHeight());
      }

      band.addElement(crosst);


      if (djcross.getBottomSpace() != 0){
        JRDesignRectangle rect = createBlankRectableCrosstab(djcross.getBottomSpace(), crosst.getY() + crosst.getHeight());
        band.addElement(rect);
      }
    }


  }

  /**
   * @param djcross
   * @param crosst
   * @return
   */
  protected JRDesignRectangle createBlankRectableCrosstab(int amount,int yOffset) {
    JRDesignRectangle rect = new JRDesignRectangle();
    rect.setPen(Border.NO_BORDER.getValue());
    rect.setMode(Transparency.TRANSPARENT.getValue());
//    rect.setMode(Transparency.OPAQUE.getValue());
//    rect.setBackcolor(Color.RED);
    rect.setWidth(getReport().getOptions().getPrintableWidth());
    rect.setHeight(amount);
    rect.setY(yOffset);
    rect.setPositionType(JRDesignElement.POSITION_TYPE_FLOAT);
    return rect;
  }

  /**
   * @param columnsGroup
   * @param col
   * @return
   */
  protected JRDesignTextField createColumnNameTextField(DJGroup columnsGroup, AbstractColumn col) {
    JRDesignTextField designStaticText = new JRDesignTextField();
    JRDesignExpression exp = new JRDesignExpression();
    exp.setText("\"" + col.getTitle() + "\"");
    exp.setValueClass(String.class);
    designStaticText.setExpression(exp);
    designStaticText.setHeight(columnsGroup.getHeaderHeight().intValue());
    designStaticText.setWidth(col.getWidth().intValue());
    designStaticText.setX(col.getPosX().intValue());
    designStaticText.setY(col.getPosY().intValue());

    Style headerStyle = columnsGroup.getColumnHeaderStyle(col);
    if (headerStyle == null)
      headerStyle = columnsGroup.getDefaultColumnHeaederStyle();
    if (headerStyle == null)
      headerStyle = col.getHeaderStyle();

    applyStyleToElement(headerStyle, designStaticText);
    return designStaticText;
  }

  /**
   * If there is a SubReport on a Group, we do the layout here
   * @param columnsGroup
   * @param jgroup
   */
  protected void layoutGroupSubreports(DJGroup columnsGroup, JRDesignGroup jgroup) {
    log.debug("Starting subreport layout...");
    JRDesignBand footerBand = (JRDesignBand) jgroup.getGroupFooter();
    JRDesignBand headerBand = (JRDesignBand) jgroup.getGroupHeader();

    layOutSubReportInBand(columnsGroup, headerBand, DJConstants.HEADER);
    layOutSubReportInBand(columnsGroup, footerBand, DJConstants.FOOTER);

  }

  /**
   * @param columnsGroup
   * @param band
   * @param position
   */
  protected void layOutSubReportInBand(DJGroup columnsGroup, JRDesignBand band, String position) {

    List subreportsList = DJConstants.FOOTER.equals(position)
        ? columnsGroup.getFooterSubreports()
        : columnsGroup.getHeaderSubreports();

    for (Iterator iterator = subreportsList.iterator(); iterator.hasNext();) {
      Subreport sr = (Subreport) iterator.next();
      JRDesignSubreport subreport = new JRDesignSubreport(new JRDesignStyle().getDefaultStyleProvider());

      //The data source
      int dataSourceOrigin = sr.getDatasource().getDataSourceOrigin();
      if (DJConstants.DATA_SOURCE_ORIGIN_USE_REPORT_CONNECTION == dataSourceOrigin){
        JRDesignExpression connectionExpression = ExpressionUtils.getReportConnectionExpression();
        subreport.setConnectionExpression(connectionExpression);
      } else if (DJConstants.DATA_SOURCE_TYPE_SQL_CONNECTION == sr.getDatasource().getDataSourceType()) {
        JRDesignExpression connectionExpression = ExpressionUtils.getConnectionExpression(sr.getDatasource());
        subreport.setConnectionExpression(connectionExpression);
      } else {
        JRDesignExpression dataSourceExpression = ExpressionUtils.getDataSourceExpression(sr.getDatasource());
        subreport.setDataSourceExpression(dataSourceExpression);
      }

//      int random_ = subReportRandom.nextInt();
      //the subreport design
      String paramname = sr.getReport().toString(); //TODO ensure this name is unique among all possible subreports
      ((DynamicJasperDesign)getDesign()).getParametersWithValues().put(paramname, sr.getReport());
      String expText = "("+JasperReport.class.getName()+")$P{REPORT_PARAMETERS_MAP}.get( \""+ paramname +"\" )";
      JRDesignExpression srExpression = ExpressionUtils.createExpression(expText, JasperReport.class);
      subreport.setExpression(srExpression );


      //set the parameters
      subreport.setParametersMapExpression(ExpressionUtils.getParameterExpression(sr));
      for (Iterator subreportParamsIter = sr.getParameters().iterator(); subreportParamsIter.hasNext();) {
        SubreportParameter srparam = (SubreportParameter) subreportParamsIter.next();
        JRDesignSubreportParameter subreportParameter = new JRDesignSubreportParameter();
        subreportParameter.setName(srparam.getName());
        JRExpression expression2 = ExpressionUtils.createExpression(getDesign(), srparam);
        subreportParameter.setExpression(expression2);
        try {
          subreport.addParameter(subreportParameter );
        } catch (JRException e) {
          log.error("Error registering parameter for subreport, there must be another parameter with the same name");
          throw new CoreException(e.getMessage(),e);
        }
      }

      //some other options (cosmetic)
      //subreport.setStretchType(JRDesignElement.STRETCH_TYPE_NO_STRETCH);
      int offset = LayoutUtils.findVerticalOffset(band);
      subreport.setY(offset);
      subreport.setX(-getReport().getOptions().getLeftMargin().intValue());
      subreport.setWidth(getReport().getOptions().getPage().getWidth());
      subreport.setHeight(SUBREPORT_DEFAULT_HEIGHT);
      subreport.setPositionType(JRElement.POSITION_TYPE_FLOAT);
      subreport.setStretchType(JRElement.STRETCH_TYPE_NO_STRETCH);
      subreport.setRemoveLineWhenBlank(true); //No subreport, no reserved space

      band.setHeight(offset + subreport.getHeight());
     
      if (sr.getStyle() != null)
        applyStyleToElement(sr.getStyle(), subreport);

      //adding to the band
      if (sr.isStartInNewPage()) {
        JRDesignGroup jrgroup = getJRGroupFromDJGroup(columnsGroup);
        JRDesignBand targetBand = null;
        int idx = getDesign().getGroupsList().indexOf(jrgroup);
        if (DJConstants.HEADER.equals(position)) {
//          if (idx == 0){
//            if (getDesign().getColumnHeader() != null)
//              targetBand = (JRDesignBand) getDesign().getColumnHeader();
//            else if (getDesign().getPageHeader() != null)
//              targetBand = (JRDesignBand) getDesign().getPageHeader();
//            else
//              targetBand = band;
//          }
//          else
//            targetBand = (JRDesignBand) ((JRDesignGroup) getDesign().getGroupsList().get(idx-1)).getGroupHeader();
        }
        else { //footer subreport (and concatenated report)
          if (idx+1 <  getDesign().getGroupsList().size())
            idx++;
          targetBand = (JRDesignBand) ((JRDesignGroup) getDesign().getGroupsList().get(idx)).getGroupFooter();
        }

        /**
         * There is no meaning in adding a page-break in header sub reports since
         * they will be placed right after the group header
         */
        if (DJConstants.FOOTER.equals(position)){
          JRDesignBreak pageBreak = new JRDesignBreak(new JRDesignStyle().getDefaultStyleProvider());
          pageBreak.setKey(PAGE_BREAK_FOR_ + jrgroup.toString()); //set up a name to recognize the item later
          pageBreak.setY(0);
          pageBreak.setPositionType(JRDesignElement.POSITION_TYPE_FLOAT);
          targetBand.addElement(pageBreak);
        }

      }
      band.addElement(subreport);
     
      sendPageBreakToBottom(band);

      /**
       * A subreport is placed in a group header or footer. This option configures the group's
       * header/footer band to allow it contents to be split. I'm not sure splitting logic works
       * inside complex object such as sub-reports since it has it's own bands inside
       */
      band.setSplitAllowed(sr.isSplitAllowed());
    }
  }

  /**
   * page breaks should be near the bottom of the band, this method used while adding subreports
   * which has the "start on new page" option.
   * @param band
   */
  protected void sendPageBreakToBottom(JRDesignBand band) {
    JRElement[] elems = band.getElements();
    JRElement aux = null;
    for (int i = 0; i < elems.length; i++) {
      if ((""+elems[i].getKey()).startsWith(PAGE_BREAK_FOR_)){
        aux = elems[i];
        break;
      }
    }
    if (aux != null)
      ((JRDesignElement)aux).setY(band.getHeight());
  }

  /**
   * If variables are present for a given group, they are placed in it's
   * header/footer band.
   * @param DJGroup group
   * @param JRDesignGroup jgroup
   * @param int labelOffset
   * @throws LayoutException
   */
  protected void layoutGroupVariables(DJGroup group, JRDesignGroup jgroup, int labelOffset) {
    log.debug("Starting groups variables layout...");
   
    JRDesignBand headerBand = (JRDesignBand) jgroup.getGroupHeader();
    if (headerBand == null){
      headerBand = new JRDesignBand();
      jgroup.setGroupHeader(headerBand);
    }
   
    JRDesignBand footerBand = (JRDesignBand) jgroup.getGroupFooter();
    if (footerBand == null){
      footerBand = new JRDesignBand();
      jgroup.setGroupFooter(footerBand);
    }
   
    int headerOffset = 0;

    //Show the current value above the column name
    int yOffset = 0;
    GroupLayout layout = group.getLayout();
    //Only the value in header
    PropertyColumn column = group.getColumnToGroupBy();

    Integer height = group.getHeaderVariablesHeight()!=null
    ? group.getHeaderVariablesHeight()
        :getReport().getOptions().getDetailHeight();
   
    //VALUE_IN_HEADER,
    //VALUE_IN_HEADER_WITH_HEADERS,
    //VALUE_IN_HEADER_AND_FOR_EACH,
    //VALUE_IN_HEADER_AND_FOR_EACH_WITH_HEADERS
    if (layout.isShowValueInHeader() && layout.isHideColumn() && !layout.isShowColumnName()){
      //textfield for the current value
      JRDesignTextField currentValue = generateTextFieldFromColumn(column, height.intValue(), group);
      currentValue.setPositionType(JRDesignElement.POSITION_TYPE_FIX_RELATIVE_TO_TOP);
     
      //The width will be all the page, except for the width of the header variables
            int headerVariablesWidth = getReport().getOptions().getPrintableWidth();
           
            if (!group.getHeaderVariables().isEmpty()){
              DJGroupVariable leftmostcol = findLeftMostColumn(group.getHeaderVariables());
              headerVariablesWidth = leftmostcol.getColumnToApplyOperation().getPosX().intValue();
              if (groupLabelsPresent(group.getHeaderVariables())){
                currentValue.setY(height.intValue());
                currentValue.setHeight(getHeaderVariablesHeight(group));
              }
            }
            currentValue.setWidth(headerVariablesWidth);
           
      //fix the height depending on the font size
//      currentValue.setHeight(FontHelper.getHeightFor(column.getStyle().getFont())); //XXX CAREFULL
      yOffset += currentValue.getHeight();

      //Move down existing elements in the band.
      LayoutUtils.moveBandsElemnts(yOffset-1, headerBand); //Don't know why, but without the "-1" it wont show the headers
     
      if (group.getLayout().isPrintHeaders()){
        headerOffset += group.getHeaderHeight().intValue() + getReport().getOptions().getDetailHeight().intValue();
      }
     
      headerBand.addElement(currentValue);
    }
    //DEFAULT and DEFAULT_WITH_HEADER
    else if (layout.isShowValueInHeader() && !layout.isHideColumn() && !layout.isShowColumnName()){
      headerOffset = changeHeaderBandHeightForVariables(headerBand, group);
      insertValueInHeader(headerBand, group, headerOffset);
    }
    //VALUE_IN_HEADER_WITH_HEADERS_AND_COLUMN_NAME
    else if (layout.isShowValueInHeader() && layout.isHideColumn() && layout.isShowColumnName()){
      //Create the element for the column name
      JRDesignTextField columnNameTf = createColumnNameTextField(group, column);
      columnNameTf.setY(columnNameTf.getY() + headerOffset);

      //textfield for the current value
      JRDesignTextField currentValue = generateTextFieldFromColumn(column, height.intValue(), group);

      //The width will be (width of the page) - (column name width)
      currentValue.setWidth(getReport().getOptions().getPrintableWidth() - columnNameTf.getWidth());
      //The x position for the current value is right next to the column name
      currentValue.setX(columnNameTf.getWidth());

      //fix the height depending on the font size
      currentValue.setHeight(FontHelper.getHeightFor(column.getStyle().getFont()));
      columnNameTf.setHeight(currentValue.getHeight());

      yOffset += currentValue.getHeight();

      //Move down existing elements in the band.
      LayoutUtils.moveBandsElemnts(yOffset, headerBand);

      headerBand.addElement(columnNameTf);
      headerBand.addElement(currentValue);
    }

    placeVariableInBand(group.getHeaderVariables(), group, jgroup, DJConstants.HEADER, headerBand, headerOffset);
    placeVariableInBand(group.getFooterVariables(), group, jgroup, DJConstants.FOOTER, footerBand, labelOffset);
  }

 
  /**
   *
   * @param groupVariables
   * @return
   */
  protected boolean groupLabelsPresent(List groupVariables) {
    for (Iterator iterator = groupVariables.iterator(); iterator.hasNext();) {
      DJGroupVariable var = (DJGroupVariable) iterator.next();
      if (var.getLabel() != null)
        return true;
     
    }
    return false;
  }

  /**
   *
   * @param variables
   * @param djGroup
   * @param jgroup
   * @param type (header or footer)
   * @param band
   * @param yOffset
   */
  protected void placeVariableInBand(List variables, DJGroup djGroup, JRDesignGroup jgroup, String type, JRDesignBand band, int yOffset) {
    if ((variables == null) || (variables.isEmpty())) {
      return;
    }
   
    boolean inFooter = DJConstants.FOOTER.equals(type);
   
    log.debug("Placing variables in "+type+" band for group " + djGroup.getColumnToGroupBy().getTextForExpression());
   
    int height = 0;
    if (inFooter)
      height = getFooterVariableHeight(djGroup);
    else
      height = getHeaderVariablesHeight(djGroup);
   
    Iterator it = variables.iterator();
    int yOffsetGlabel = 0;
    while (it.hasNext()) {
      DJGroupVariable var = (DJGroupVariable) it.next();
      AbstractColumn col = var.getColumnToApplyOperation();

      //Build the expression for the variable
      String variableName = col.getGroupVariableName(type, djGroup.getColumnToGroupBy().getColumnProperty().getProperty());
     
      //Add the group label
      DJGroupLabel label = var.getLabel();
      JRDesignTextField labelTf = null;
      if (label != null){
        JRDesignExpression labelExp;
        if (label.isJasperExpression()) //a text with things like "$F{myField}"
          labelExp = ExpressionUtils.createStringExpression(label.getText());
        else if (label.getLabelExpression() != null){
          labelExp = ExpressionUtils.createExpression(variableName + "_labelExpression", label.getLabelExpression());
        } else //a simple text
          //labelExp = ExpressionUtils.createStringExpression("\""+ Utils.escapeTextForExpression(label.getText())+ "\"");
          labelExp = ExpressionUtils.createStringExpression("\""+ label.getText() + "\"");
        labelTf = new JRDesignTextField();
        labelTf.setExpression(labelExp);
        labelTf.setWidth(col.getWidth().intValue());
        labelTf.setHeight(label.getHeight());
        labelTf.setX(col.getPosX().intValue());
        labelTf.setY(yOffset);
        yOffsetGlabel = labelTf.getHeight();       
        if (inFooter){
          labelTf.setPositionType(JRDesignElement.POSITION_TYPE_FIX_RELATIVE_TO_TOP);
        }
        applyStyleToElement(label.getStyle(), labelTf);
        band.addElement(labelTf);
       
      }

      JRDesignExpression expression = new JRDesignExpression();
      JRDesignTextField textField = new JRDesignTextField();
     
      textField.setEvaluationTime(JRExpression.EVALUATION_TIME_GROUP);
     
      if (var.getValueExpression() != null) {
        expression = ExpressionUtils.createExpression(variableName + "_valueExpression", var.getValueExpression());
      }
      else
        setTextAndClassToExpression(expression,var,col,variableName);
     
      if (var.getOperation() != DJCalculation.COUNT && var.getOperation() != DJCalculation.DISTINCT_COUNT )
        textField.setPattern(col.getPattern());
     
      if (col instanceof PercentageColumn) {
        PercentageColumn pcol = (PercentageColumn) col;
        expression.setText(pcol.getTextForExpression(djGroup, djGroup ,type));
        expression.setValueClassName(pcol.getValueClassNameForExpression());
        textField.setEvaluationTime(JRExpression.EVALUATION_TIME_AUTO);
      } else {
        textField.setEvaluationGroup(jgroup);
      }

      textField.setKey(variableName);
      textField.setExpression(expression);

     
      if (inFooter){
        textField.setPositionType(JRDesignElement.POSITION_TYPE_FIX_RELATIVE_TO_TOP);
      }

      textField.setX(col.getPosX().intValue());
   
      //if (yOffset!=0)
      textField.setY(yOffset + yOffsetGlabel);

      textField.setHeight(0 + height ); //XXX be carefull with the "2+ ..."

      textField.setWidth(col.getWidth().intValue());


      textField.setKey("variable_for_column_"+ getVisibleColumns().indexOf(col) + "_in_group_" + getDesign().getGroupsList().indexOf(jgroup));
     
     
      //Assign the style to the element.
      //First we look for the specific element style, then the default style for the group variables
      //and finally the column style.
      Style defStyle = DJConstants.HEADER.equals(type)
            ? djGroup.getDefaulHeaderVariableStyle()
            : djGroup.getDefaulFooterVariableStyle();

      if (var.getStyle() != null)
        applyStyleToElement(var.getStyle(), textField);
      else if (col.getStyle() != null) {
        //Last resource is to use the column style, but a copy of it because
        //the one in the internal cache can get modified by the layout manager (like in the odd row case)
        Style style = col.getStyle();
        try {
          style = (Style) style.clone();
          style.setName(null); //set to null to make applyStyleToElement(...) assign a name
        } catch (Exception e) {  }
        applyStyleToElement(style, textField);
      }
      else if (defStyle != null)
        applyStyleToElement(defStyle, textField);

      if (var.getPrintWhenExpression() != null) {
        JRDesignExpression exp = ExpressionUtils.createExpression(variableName + "_printWhenExpression", var.getPrintWhenExpression());
        textField.setPrintWhenExpression(exp);
        if (labelTf != null)
          labelTf.setPrintWhenExpression(exp);
      }
     
      band.addElement(textField);

    }

    if (djGroup.getColumnToGroupBy() instanceof GlobalGroupColumn) {
      int totalWidth = 0;

      DJGroupVariable leftmostColumn = findLeftMostColumn(variables);
      totalWidth = leftmostColumn.getColumnToApplyOperation().getPosX().intValue();

      GlobalGroupColumn globalCol = (GlobalGroupColumn) djGroup.getColumnToGroupBy();

      JRDesignTextField globalTextField = new JRDesignTextField();
      JRDesignExpression globalExp = new JRDesignExpression();
      globalExp.setText(globalCol.getTextForExpression());
      globalExp.setValueClassName(globalCol.getValueClassNameForExpression());
      globalTextField.setExpression(globalExp);

//        globalTextField.setHeight(band.getHeight()); //XXX Changed, see if its ok
//      globalTextField.setHeight(2 + getReport().getOptions().getDetailHeight().intValue()); //XXX be carefull with the "2+ ..."
      globalTextField.setHeight(2 + height ); //XXX be carefull with the "2+ ..."
      globalTextField.setWidth(totalWidth);
//        globalTextField.setX(((AbstractColumn)getReport().getColumns().get(0)).getPosX().intValue());
      globalTextField.setX(0);
      if (type.equals(ColumnsGroupVariablesRegistrationManager.HEADER))
        globalTextField.setY(yOffset);
      globalTextField.setKey("global_legend_"+type);

      applyStyleToElement(globalCol.getStyle(), globalTextField);

      band.addElement(globalTextField);
    }
  }

  protected int getHeaderVariablesHeight(DJGroup columnsGroup) {
    Integer height;
    height = columnsGroup.getHeaderVariablesHeight()!=null
          ? columnsGroup.getHeaderVariablesHeight()
          : DynamicReportOptions.DEFAULT_HEADER_VARIABLES_HEIGHT;
    return height.intValue();
  }

  protected int getFooterVariableHeight(DJGroup columnsGroup) {
    Integer height;
    height = columnsGroup.getFooterVariablesHeight()!=null
          ? columnsGroup.getFooterVariablesHeight()
          : DynamicReportOptions.DEFAULT_FOOTER_VARIABLES_HEIGHT;
    return height.intValue();
  }

  /**
   * If a variable has a DJValueFormatter, we must use it in the expression, otherwise, use plain $V{...}
   * @param expression
   * @param var
   * @param col
   * @param variableName
   */
  protected void setTextAndClassToExpression(JRDesignExpression expression, DJGroupVariable var, AbstractColumn col, String variableName) {
   
    if (var.getValueFormatter() != null){
      expression.setText(var.getTextForValueFormatterExpression(variableName));
      expression.setValueClassName(var.getValueFormatter().getClassName());
    }
    else if (col.getTextFormatter() != null) {
     
      expression.setText("$V{" + variableName + "}");
      expression.setValueClassName(col.getVariableClassName(var.getOperation()));
    }
    else {
      expression.setText("$V{" + variableName + "}");
      expression.setValueClassName(col.getVariableClassName(var.getOperation()));
    }
  }

  protected DJGroupVariable findLeftMostColumn(List variables) {
    int mostLeftX = Integer.MAX_VALUE;
    DJGroupVariable mostLeftColumn =  null;
    for (Iterator iterator = variables.iterator(); iterator.hasNext();) {
      DJGroupVariable currentCol = (DJGroupVariable) iterator.next();
      if (currentCol.getColumnToApplyOperation().getPosX().intValue() <= mostLeftX) {
        mostLeftColumn = currentCol;
                mostLeftX = mostLeftColumn.getColumnToApplyOperation().getPosX().intValue();
            }
        }
    return mostLeftColumn;
  }

  protected DJGroupVariable findRightMostColumn(List variables) {
    int mostRightX = Integer.MIN_VALUE;
    DJGroupVariable mostRightColumn =  null;
    for (Iterator iterator = variables.iterator(); iterator.hasNext();) {
      DJGroupVariable currentCol = (DJGroupVariable) iterator.next();
      if (currentCol.getColumnToApplyOperation().getPosX().intValue() >= mostRightX) {
        mostRightColumn = currentCol;
                mostRightX = mostRightColumn.getColumnToApplyOperation().getPosX().intValue();
            }
        }
    return mostRightColumn;
  }
 
  protected void insertValueInHeader(JRDesignBand headerBand, DJGroup djgroup, int headerOffset) {
//    JRDesignTextField textField = generateTextFieldFromColumn(columnsGroup.getColumnToGroupBy(), columnsGroup.getHeaderHeight().intValue(), columnsGroup);
    int height = getReport().getOptions().getDetailHeight().intValue();
   
    if (!djgroup.getHeaderVariables().isEmpty())
      height = djgroup.getHeaderVariablesHeight()!=null
            ? djgroup.getHeaderVariablesHeight().intValue()
            :getReport().getOptions().getDetailHeight().intValue();   
   
    JRDesignTextField textField = generateTextFieldFromColumn(djgroup.getColumnToGroupBy(), height, djgroup);
    textField.setHorizontalAlignment(djgroup.getColumnToGroupBy().getStyle().getHorizontalAlign().getValue());
    textField.setStretchType(JRDesignElement.STRETCH_TYPE_NO_STRETCH); //XXX this is a patch for subreports, ensure it works well.
    textField.setY(textField.getY() + headerOffset);
    headerBand.addElement(textField);
  }

  protected int changeHeaderBandHeightForVariables(JRDesignBand headerBand, DJGroup columnsGroup) {
    int result = 0;
    if (!headerBand.getChildren().isEmpty()) {
      int acu = headerBand.getHeight();
      headerBand.setHeight(headerBand.getHeight() + columnsGroup.getHeaderHeight().intValue());
      result = acu;
    } else
      headerBand.setHeight(getReport().getOptions().getHeaderVariablesHeight().intValue());
    return result;
  }

  protected void generateHeaderBand() {
    log.debug("generating header band...");
    JRDesignBand header = (JRDesignBand) getDesign().getColumnHeader();
    if (header == null) {
      header = new JRDesignBand();
      getDesign().setColumnHeader(header);
    }


    /**
     * Note: Te column names, when in header, are printed at the begining of every page.
     * You may dont want this option if you have groups that prints column names.
     */
    if (getReport().getOptions().isPrintColumnNames()){
      generateHeaderBand(header);
    }

//    if (!DynamicJasperHelper.existsGroupWithColumnNames(getReport().getColumnsGroups()))
//      generateHeaderBand(header);
  }

  protected void transformDetailBandTextField(AbstractColumn column, JRDesignTextField textField) {
    //TODO: Set default characters when null values are found.
//    log.debug("transforming detail band text field...");
    DJGroup group = getDJGroup(column);
    if (group!=null&&!group.getLayout().isShowValueForEachRow()) {
      textField.setExpression(null); //this way, the textfield is not added to the band
    }
  }
 


}
TOP

Related Classes of ar.com.fdvs.dj.core.layout.ClassicLayoutManager

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.