Package cli_fmw.report.implemenatation

Source Code of cli_fmw.report.implemenatation.JasperTableBuilder

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package cli_fmw.report.implemenatation;

import cli_fmw.report.TableReportOptions;
import cli_fmw.report.ReporterFactory;
import javax.swing.table.TableModel;
import net.sf.jasperreports.engine.JRElement;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRField;
import net.sf.jasperreports.engine.JRLineBox;
import net.sf.jasperreports.engine.JRPen;
import net.sf.jasperreports.engine.design.JRDesignBand;
import net.sf.jasperreports.engine.design.JRDesignField;
import net.sf.jasperreports.engine.design.JRDesignStyle;
import net.sf.jasperreports.engine.design.JRDesignTextField;

/**
*
* @author finder
*/
public class JasperTableBuilder implements JasperDetailBuilder {

  /**
   * Тип добовляемого поля, для функции создания новых полей, влияет на формат.
   */
 
  static enum FieldTypes {
    other,
    tableHeader,
    table,
  }
  /**
   * Минимальный размер колонки, если колонка меньше этого разера,
   * то она будет растянута засчет других колонок.
   */
  static final int        MINIMUM_COLOUMN_SIZE = 12;
  /**
   * Общие опции генерации отчета
   */
  TableReportOptions          options;
  /**
   * ссылка на модель таблицы, если отчет содержит таблицу
   */
  TableModel            table;
  /**
   * Ссылка на итерфейс изменяющий геренацию отчета, для коррекции внешнего вида,
   * в процессе построения шаблона отчета, этот интерфейс прифодится к его наследжникам,
   * и вызываются соотведствующие методы обработки.
   */
  JasperTableBuilderCustomizer  customizer;
  /**
   * Колонка в таблице начиная с которой будет строится отчет.
   * Может использоватся для разделения большой таблицы по нескольким отчетам,
   * Передачи дополнительных данны в одной из таблиц и тп.
   */
  int                beginColoumn;
 
  /**
   * Оконечная колонка в таблице до которой будет строится отчет.
   */
  int                endColoumn;
  /**
   * Стиль которым ресуется таблица. Обычный стиль + окантовка ечеек
   */
  JRDesignStyle          tableStyle;
  /**
   * Банд содержит заголовок таблицы высата как у элемента таблицы
   */
  JRDesignBand          colomnHeaderBand;
  /**
   * Банд с элементами таблицы
   */
  JRDesignBand          detalsBand;
  /**
   * Максимальная ширина всех строк в таблице (destingWidth минус лишний размер элементов)
   */
  double              stringsWidth;
 
  JasperBuilder          builder;
 

  public JasperTableBuilder(TableReportOptions options, TableModel table) {
    this.options = options;
    this.table = table;
    this.beginColoumn = 0;
    this.endColoumn = table == null? 0: table.getColumnCount();
  }
 
  /**
   * Колонка в таблице начиная с которой будет строится отчет.
   * @return - Номер колонки начиная с нуля
   */
 
  public int getBeginColoumn() {
    return beginColoumn;
  }

  /**
   * Устанавливает номер колонки таблице начиная с которой будет строится отчет.
   * Может использоватся для разделения большой таблицы по нескольким отчетам,
   * Передачи дополнительных данны в одной из таблиц и тп.
   * @param beginColoumn - номер колонки, начиная с нуля
   */
 
  public void setBeginColoumn(int beginColoumn) {
    this.beginColoumn = beginColoumn;
  }


  /**
   * Возврящает номер колонкт в таблице, идущей сразу после колонки,
   * до которой будет строится отчет.
   * @return номер колонки
   */
  public int getEndColoumn() {
    return endColoumn;
  }

  /**
   * Устанавливает номер колонкт в таблице, идущей сразу после колонки,
   * до которой будет строится отчет.
   * @param endColoumn
   */
 
  public void setEndColoumn(int endColoumn) {
    this.endColoumn = endColoumn;
  }
  /**
   * Возвращает минимальну высоту элемента в пикселях, в которую влазит одна строка текста.
   * @return высота элемента
   */
 
  int getElementHeight(){
    double      target = builder.getFieldHeigth();
    JRLineBox box = tableStyle.getLineBox();
    target += box.getTopPen().getLineWidth();
    return (int) Math.round(target);
  }
 
  /**
   * Возврашает минимальный размер элемента таблицы по горизонтали, который
   * вмещает в себя эту строку без переносов.
   * @param line - строка
   * @return - длинну
   */
 
  double getElementLenght(String line){
    double    target = getStringLength(line);
    JRLineBox  box = tableStyle.getLineBox();
    target += box.getLeftPadding();
    target += box.getRightPadding();
    target += box.getLeftPen().getLineWidth();
    target += 1;
    return target;
  }
 
  /**
   * Возвращает размер который элемен таблицы занимает дополнительно к размеру
   * содержащейсе внем строки (размер на отступы, бордюр, и тп)
   * @return
   */
 
  double getElementOverhead(){
    return getElementLenght("");
  }
 
  /**
   * Возвращает максимальную ширина всех строк в таблице
   * (destingWidth минус лишний размер элементов)
   */
 
  public double getStringsWidth() {
    return stringsWidth;
  }
   
  /**
   * Взвращает длинну строки, отпечатонной стилем Normal.
   * @param line
   * @return
   */
 
  double getStringLength(String str){
    return builder.getStringLength(str);
  }
 
  /**
   * Возвращает число колонок таблицы которое попадет в результирующий отчет.
   * @return
   */
 
  int getColoumCount(){
    return Math.max(0, endColoumn - beginColoumn);
  }

  @Override
  public void buildDetails(JasperBuilder inBuilder, JasperReportBuilderCustomizer inCustomizer) throws JRException{
    if (inBuilder == null) {
      throw new IllegalArgumentException("inBuilder can not be null");
    }

    this.builder = inBuilder;
    if (inCustomizer != null && inCustomizer instanceof JasperTableBuilderCustomizer){
      this.customizer = (JasperTableBuilderCustomizer)inCustomizer;
      this.customizer.customizeTableBuilder(this);
    }
    else{
      this.customizer = null;
    }
    initStyles();
    createTable();
  }
 
  private void initStyles() throws JRException{
    tableStyle = new JRDesignStyle();
    tableStyle.setName("Table");
    tableStyle.setDefault(false);
    tableStyle.setParentStyle(builder.getNormalStyle());
    JRLineBox box = tableStyle.getLineBox();
    box.getPen().setLineStyle(JRPen.LINE_STYLE_SOLID);
    box.getPen().setLineWidth(1);
    builder.getTargetDesting().addStyle(tableStyle);
   
    stringsWidth = builder.getDestingWidth() - (endColoumn - beginColoumn) * getElementOverhead();
   
    if (options.showTableHeader && table != null){
      colomnHeaderBand = builder.getColomnHeaderBand();
      colomnHeaderBand.setSplitAllowed(false);
      colomnHeaderBand.setHeight(getElementHeight());
    }
    if (table != null){
      detalsBand = builder.getDetalsBand();
      detalsBand.setSplitAllowed(false);
      detalsBand.setHeight(getElementHeight());
    }
  }
 
  /**
   * Служебная функция функции calcTableSizes
   * увеличивает значение ячейки массива длин ячеек, в соотведствии с длинной строки.
   * @param str - строка чья длинна измеряется
   * @param linear - метод увеличения
   * @param sizes - размеры.
   * @param col - колонка
   */
 
  void increaseTableSizes(String str, boolean linear, double[] sizes, int col){
    if (str!= null) {
      double    len = getStringLength(str);
      if (linear){
        if (sizes[col] < len) {
          sizes[col] = len;
        }
      }
      else{
        sizes[col] = (sizes[col] + len * len);
      }
    }
  }

  /**
   * Находит соотношение размеров колонок в таблице.
   * Или максимальнуюю длинну элемента в колонке.
   * @param linear - если истина возващает максимальный размер элемента в таблице.
   *          Если ложь - нелинейные коофиценты отношения размеров элементов.
   * @return - массив double каждый элемент которого соотведствует одной колонке,
   *      притом первый элемент соотведствует превой отображамой колонке.
   */
 
  double[] calcTableSizes(boolean linear){
    if (table == null) {
      return new double[0];
    }
    double[]      target = new double[getColoumCount()];
   
    for (int col = 0; col < getColoumCount(); col++){
      String      str;
      if (options.showTableHeader){
        str = table.getColumnName(col + beginColoumn);
        increaseTableSizes(str, linear, target, col);
      }
      for (int row = table.getRowCount() - 1; row >= 0; row--){
        str = ReporterFactory.convertDataToString(table.getValueAt(row, col + beginColoumn));
        increaseTableSizes(str, linear, target, col);
      }
    }
    if (!linear){
      double      rc = table.getRowCount();
      if (options.showTableHeader) {
        rc += 1;
      }
      if (rc > 0){
        for (int i = 0; i < target.length; i++) {
          target[i] = Math.sqrt(target[i] / rc);
        }
      }
    }
    return target;
  }
 
  JRDesignTextField createItem(FieldTypes type, int x, int y, int w, int h, JRExpression fieldExpression){
    JRDesignTextField      textField = builder.createItem(JasperBuilder.FieldTypes.other, x, y, w, h, fieldExpression);
    textField.setStyle(tableStyle);
    textField.setStretchType(JRDesignTextField.STRETCH_TYPE_RELATIVE_TO_BAND_HEIGHT);
    switch (type){
      case tableHeader:
        if (options.tableHeaderColor != null){
          textField.setBackcolor(options.tableHeaderColor);
          textField.setMode(JRElement.MODE_OPAQUE);
        }
        break;
      case table:
        break;
    }
    return textField;
  }
 
  /**
   * Создает, или находит, поле данных, ссылающиеся на одно из заначений таблици, по номеру колонки.
   * @param coloumn номер колонки в таблице
   * @return - поле данных
   * @throws net.sf.jasperreports.engine.JRException
   */
 
  public JRField createTableField(int coloumn) throws JRException{
    String        name = "COLUMN_" + coloumn;
    JRDesignField    dsfield = (JRDesignField) builder.getTargetDesting().getFieldsMap().get(name);
    if (dsfield == null){
      dsfield = new JRDesignField();
      dsfield.setValueClass(String.class);
      dsfield.setName(name);
      builder.getTargetDesting().addField(dsfield);
    }
    return dsfield;
  }
 
  /**
   * Созадает поле, элемент таблицы, оторое содержит либо статичный заголовок таблицы.
   * Либо одну ячейку таблицы.
   * @param pos - позиция элемента по горизонтали (по вертикали всегда ноль)
   * @param size - размер элемента по горизонтали (по вертикали всегда в одну строку)
   * @param coloumn - номер колонки для которой сооздается элемент
   * @param toHeader - если истина, то это будет ячейка заголовка, если ложь то ячейка таблицы.
   * @throws net.sf.jasperreports.engine.JRException
   */
 
  public void createTableItem(int pos, int size, int coloumn, boolean toHeader) throws JRException{
    JRField          dataField = null;
    JRExpression      ex;
    if (toHeader){
      ex = builder.createStringExpression(table.getColumnName(coloumn));
    }
    else{
      dataField = createTableField(coloumn);
      ex = builder.createExpression("$F{"+ dataField.getName() + "}");
    }
    JRDesignTextField      field = createItem(
        toHeader? FieldTypes.tableHeader: FieldTypes.table, pos, 0,
        size, getElementHeight(), ex);
   
    boolean      needIsert = true;
    if (customizer != null && customizer instanceof JasperrCustomizerTableItem) {
      needIsert = ((JasperrCustomizerTableItem) customizer).onNewTableElement(pos, size,
          coloumn, toHeader, dataField, field);
    }
   
    if (needIsert){
      if (toHeader) {
        colomnHeaderBand.addElement(field);
      }
      else {
        detalsBand.addElement(field);
      }
    }
  }
 
  /**
   * Создает элементы таблицы
   * @throws net.sf.jasperreports.engine.JRException
   */

  void createTable() throws JRException{
    double[]      itemSizes = calcTableSizes(true);
    ColoumnAligner    aligner = new ColoumnAligner(itemSizes, itemSizes, beginColoumn);
    double        totalLen = aligner.calcTotalSize();
   
    if (totalLen > stringsWidth){
      for (int i = 0; i < itemSizes.length; i++) {
        itemSizes[i] *= 1.125;
        if (itemSizes[i] < MINIMUM_COLOUMN_SIZE) {
          itemSizes[i] = MINIMUM_COLOUMN_SIZE;
        }
      }
      itemSizes = calcTableSizes(false);
      aligner.setSizes(itemSizes);
    }
    aligner.normalize(stringsWidth);
    aligner.allignColouns();
   
    double      pos = 0;// = targetDesting.getLeftMargin();
    for (int i = 0; i < itemSizes.length; i++){
     
      int      x = (int)Math.round(pos);
      pos += itemSizes[i] + getElementOverhead();
      int      len = (int)Math.round(pos) - x;
      if (options.showTableHeader) {
        createTableItem(x, len, i + beginColoumn, true);
      }
      createTableItem(x, len, i + beginColoumn, false);
    }
   
    if (customizer != null && customizer instanceof JasperrCustomizerTable) {
      ((JasperrCustomizerTable) customizer).onTableCreated(colomnHeaderBand, detalsBand, itemSizes);
    }
  }

}
TOP

Related Classes of cli_fmw.report.implemenatation.JasperTableBuilder

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.