using System;
using System.Diagnostics;
using System.Drawing;

// Creation date: 05.11.2002
// Checked: 30.05.2003
// Author: Otto Mayer (mot@root.ch)
// Version: 1.01

// Report.NET copyright 2002-2004 root-software ag, Bürglen Switzerland - O. Mayer, S. Spirig, R. Gartenmann, all rights reserved
// 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, version 2.1 of the License.
// 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 www.opensource.org/licenses/lgpl-license.html

namespace Root.Reports {
  /// <summary>Table Layout Manager</summary>
  public class TableLayoutManager : TlmBase {
    //====================================================================================================x
    /// <summary>Header cell definition</summary>
    public class HeaderCellDef : TlmCellDef {
      //----------------------------------------------------------------------------------------------------x
      /// <summary>Creates a definition structure for the default values of a header cell.</summary>
      internal HeaderCellDef() {
      }
    }

    //====================================================================================================x
    /// <summary>Header row definition</summary>
    public class HeaderRowDef : TlmRowDef {
      //----------------------------------------------------------------------------------------------------x
      /// <summary>Creates a definition structure for the default values of a header row.</summary>
      internal HeaderRowDef() {
      }
    }

    //====================================================================================================x
    /// <summary>Column definition.</summary>
    public class Column : TlmColumn {
      /// <summary>Definition of the default values of a cell of this column</summary>
      public readonly HeaderCellDef headerCellDef;

      /// <summary>Header of the column</summary>
      public String sHeader;

      /// <summary>Header font properties</summary>
      public FontProp fp_Header;

      /// <summary>Horizontal alignment</summary>
      [Obsolete("use 'cellDef.rAlignH = ...'")]
      public Double rAlignH {
        set { cellDef.rAlignH = value; }
      }

      /// <summary>Vertical alignment</summary>
      [Obsolete("use 'cellDef.rAlignV = ...'")]
      public Double rAlignV {
        set { cellDef.rAlignV = value; }
      }

      /// <summary>Left margin within the column</summary>
      [Obsolete("use 'cellDef.rMarginLeft = ...'")]
      public Double rMarginLeft {
        set { cellDef.rMarginLeft = value; }
      }

      /// <summary>Right margin within the column</summary>
      [Obsolete("use 'cellDef.rMarginRight = ...'")]
      public Double rMarginRight {
        set { cellDef.rMarginRight = value; }
      }

      /// <summary>Multiline mode: true if the column supports automatic multiline text mode; otherwise, false.</summary>
      [Obsolete("use 'col.cellDef.textMode = TableLayoutManager.TextMode.MultiLine'")]
      public Boolean bMultiline {
        set { cellDef.textMode = (value ? TlmBase.TextMode.MultiLine : TlmBase.TextMode.EllipsisCharacter); }
      }

      //----------------------------------------------------------------------------------------------------x
      /// <summary>Creates a column definition object.</summary>
      /// <param name="tlm">Table layout manager of this column</param>
      /// <param name="sHeader">Header of the column</param>
      /// <param name="rWidth">Width of the column</param>
      public Column(TableLayoutManager tlm, String sHeader, Double rWidth) : base(tlm, rWidth) {
        headerCellDef = new HeaderCellDef();
        this.sHeader = sHeader;
        fp_Header = tlm.fp_Header;
      }

    }

    //====================================================================================================x
    /// <summary>Column definition with metric values.</summary>
    public class ColumnMM : Column {
      /// <summary>Creates a column definition object with metric values.</summary>
      /// <param name="tlm">Table layout manager of this column</param>
      /// <param name="sHeader">Header of the column</param>
      /// <param name="rWidthMM">Width of the column</param>
      public ColumnMM(TableLayoutManager tlm, String sHeader, Double rWidthMM) : base(tlm, sHeader, RT.rPointFromMM(rWidthMM)) {
      }
    }

    //====================================================================================================x
    /// <summary>Definition of the default properties of a cell of this table</summary>
    public readonly HeaderCellDef headerCellDef;
    /// <summary>Definition of the default properties of a cell of this table (VB version)</summary>
    public HeaderCellDef _headerCellDef {
      get { return headerCellDef; }
    }

    /// <summary>Definition of the default properties of a row of this table</summary>
    public readonly HeaderRowDef headerRowDef;
    /// <summary>Definition of the default properties of a row of this table (VB version)</summary>
    public HeaderRowDef _headerRowDef {
      get { return headerRowDef; }
    }

    /// <summary>Header font properties</summary>
    public FontProp fp_Header;

    /// <summary>Adjusts the width of the columns to the width of the container</summary>
    [Obsolete("use 'ScaleWidth(rWidth)'")]
    public Boolean bAutoColWidth {
      set {
        if (value) {
          ScaleWidth(rWidth);
        }
      }
    }

    /// <summary>Pen properties of the header grid lines</summary>
    [Obsolete("use 'headerCellDef.pp_Line = ...'")]
    public PenProp pp_HeaderGrid {
      set { headerCellDef.pp_Line = value; }
    }

    /// <summary>Brush properties of the grid header</summary>
    [Obsolete("use 'headerCellDef.bp_Back = ...'")]
    public BrushProp bp_HeaderBack {
      set { headerCellDef.bp_Back = value; }
    }

    /// <summary>Pen properties of the vertical grid lines</summary>
    [Obsolete("use 'headerCellDef.pp_LineV = ...' and 'cellDef.pp_LineV = ...'")]
    public PenProp pp_LineV {
      set { headerCellDef.pp_LineV = value;  cellDef.pp_LineV = value; }
    }

    /// <summary>Pen properties of the horizontal grid lines</summary>
    [Obsolete("use 'headerCellDef.pp_LineH = ...' and 'columnDef.pp_BorderH = ...'")]
    public PenProp pp_LineH {
      set { headerCellDef.pp_LineH = value;  columnDef.pp_BorderH = value; }
    }

    /// <summary>Bottom margin of the row</summary>
    [Obsolete("use 'cellDef.rMarginBottom = ...'")]
    public Double rRowBottomMargin {
      set { cellDef.rMarginBottom = value; }
    }

    //----------------------------------------------------------------------------------------------------x
    /// <summary>Creates a new table layout manager.</summary>
    /// <param name="report">Report of this table layout manager</param>
    public TableLayoutManager(Report report) : base(report) {
      tableHeight = TableHeight.Static;

      // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -x
      PenProp pp_Solid = new PenProp(report, 0.5, Color.Black);
      cellDef.pp_LineV = pp_Solid;

      // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -x
      columnDef.pp_BorderH = pp_Solid;

      // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -x
      headerCellDef = new HeaderCellDef();
      headerRowDef = new HeaderRowDef();

      headerCellDef.rAlignH = RepObj.rAlignLeft;
      headerCellDef.rAlignV = RepObj.rAlignTop;
      headerCellDef.rAngle = 0;
      headerCellDef.textMode = TlmBase.TextMode.MultiLine;
      headerCellDef.rLineFeed = 72.0 / 6;

      headerCellDef.rMargin = 0;
      headerCellDef.rIndentH_MM = 1;
      headerCellDef.rIndentV_MM = 2;

      headerCellDef.bp_Back = new BrushProp(report, Color.FromArgb(220, 220, 220));
      headerCellDef.pp_Line = pp_Solid;
    }

    //----------------------------------------------------------------------------------------------------x
    /// <summary>Creates a new table layout manager.</summary>
    /// <param name="fp_Header">Font property of the header</param>
    public TableLayoutManager(FontProp fp_Header) : this(fp_Header.fontDef.report) {
      this.fp_Header = fp_Header;
    }

    //----------------------------------------------------------------------------------------------------x
    /// <summary>Adds a column definition to the table layout manager</summary>
    [Obsolete("set 'tableHeight = TableHeight...' instead of calling 'AdjustHeight()'")]
    public void AdjustHeight() {
      tableHeight = TableHeight.AdjustLast;
    }

    //----------------------------------------------------------------------------------------------------x
    /// <summary></summary>
    public CellCreateType[] aCellCreateType = null;
    
    /// <summary>Creates the table header.</summary>
    private void CreateHeader(Container cont) {
      TlmRow row = tlmRow_New((TlmRow)null, aCellCreateType);
      row.bAutoCommit = false;
      row.rPreferredHeight = headerRowDef.rPreferredHeight;

      foreach (Column col in al_TlmColumn) {
        TlmCell cell = row.aTlmCell[col.iIndex];

        HeaderCellDef hd_Base = headerCellDef;
        HeaderCellDef hd_Col = col.headerCellDef;
        
        cell.rAlignH = (Double.IsNaN(hd_Col.rAlignH) ? hd_Base.rAlignH : hd_Col.rAlignH);
        cell.rAlignV = (Double.IsNaN(hd_Col.rAlignV) ? hd_Base.rAlignV : hd_Col.rAlignV);
        cell.rAngle = (Double.IsNaN(hd_Col.rAngle) ? hd_Base.rAngle : hd_Col.rAngle);
        cell.textMode = (hd_Col.textMode == TlmBase.TextMode.FallBack ? hd_Base.textMode : hd_Col.textMode);
        cell.rLineFeed = (Double.IsNaN(hd_Col.rLineFeed) ? hd_Base.rLineFeed : hd_Col.rLineFeed);

        cell.rMarginLeft = (Double.IsNaN(hd_Col.rMarginLeft) ? hd_Base.rMarginLeft : hd_Col.rMarginLeft);
        cell.rMarginRight = (Double.IsNaN(hd_Col.rMarginRight) ? hd_Base.rMarginRight : hd_Col.rMarginRight);
        cell.rMarginTop = (Double.IsNaN(hd_Col.rMarginTop) ? hd_Base.rMarginTop : hd_Col.rMarginTop);
        cell.rMarginBottom = (Double.IsNaN(hd_Col.rMarginBottom) ? hd_Base.rMarginBottom : hd_Col.rMarginBottom);

        cell.rIndentLeft = (Double.IsNaN(hd_Col.rIndentLeft) ? hd_Base.rIndentLeft : hd_Col.rIndentLeft);
        cell.rIndentRight = (Double.IsNaN(hd_Col.rIndentRight) ? hd_Base.rIndentRight : hd_Col.rIndentRight);
        cell.rIndentTop = (Double.IsNaN(hd_Col.rIndentTop) ? hd_Base.rIndentTop : hd_Col.rIndentTop);
        cell.rIndentBottom = (Double.IsNaN(hd_Col.rIndentBottom) ? hd_Base.rIndentBottom : hd_Col.rIndentBottom);

        cell.bp_Back = (Object.ReferenceEquals(hd_Col.bp_Back, BrushProp.bp_Null) ? hd_Base.bp_Back : hd_Col.bp_Back);

        cell.pp_LineLeft = (Object.ReferenceEquals(hd_Col.pp_LineLeft, PenProp.pp_Null) ? hd_Base.pp_LineLeft : hd_Col.pp_LineLeft);
        cell.pp_LineRight = (Object.ReferenceEquals(hd_Col.pp_LineRight, PenProp.pp_Null) ? hd_Base.pp_LineRight : hd_Col.pp_LineRight);
        cell.pp_LineTop = (Object.ReferenceEquals(hd_Col.pp_LineTop, PenProp.pp_Null) ? hd_Base.pp_LineTop : hd_Col.pp_LineTop);
        cell.pp_LineBottom = (Object.ReferenceEquals(hd_Col.pp_LineBottom, PenProp.pp_Null) ? hd_Base.pp_LineBottom : hd_Col.pp_LineBottom);

        cell.iOrderLineLeft = (hd_Col.iOrderLineLeft == Int32.MinValue ? hd_Base.iOrderLineLeft : hd_Col.iOrderLineLeft);
        cell.iOrderLineRight = (hd_Col.iOrderLineRight == Int32.MinValue ? hd_Base.iOrderLineRight : hd_Col.iOrderLineRight);
        cell.iOrderLineTop = (hd_Col.iOrderLineTop == Int32.MinValue ? hd_Base.iOrderLineTop : hd_Col.iOrderLineTop);
        cell.iOrderLineBottom = (hd_Col.iOrderLineBottom == Int32.MinValue ? hd_Base.iOrderLineBottom : hd_Col.iOrderLineBottom);

        if (col.sHeader != null) {
          cell.Add(new RepString(col.fp_Header, col.sHeader));
        }
      }
    }

    //----------------------------------------------------------------------------------------------------x
    /// <summary>The layout manager will be closed.</summary>
    [Obsolete("use 'Close()' or 'using (...)' instead of 'Done()'")]
    public void Done() {
      Close();
    }

    //----------------------------------------------------------------------------------------------------x
    /// <summary>Raises the NewContainer event.</summary>
    /// <param name="ea">Event argument</param>
    internal protected override void OnNewContainer(NewContainerEventArgs ea) {
      base.OnNewContainer(ea);
      CreateHeader(container_Cur);
    }

    //----------------------------------------------------------------------------------------------------x
    // Virtual Methods
    //----------------------------------------------------------------------------------------------------x

    //----------------------------------------------------------------------------------------------------x
    /// <summary>This method will be called before the row will be closed.</summary>
    /// <param name="row">Row that will be closed</param>
    internal protected override void OnClosingRow(TlmRow row) {
      if (row.iIndex != 1) {
        return;
      }
      for (Int32 iCol = 0;  iCol < al_TlmColumn.Count;  iCol++) {
        TlmCell cell = row.aTlmCell[iCol];
        if (cell.tlmColumn_Start.iIndex != iCol) {
          continue;
        }
        TlmColumn col = al_TlmColumn[iCol];
        if (!Double.IsNaN(col.rBorderTop)) {
          cell.rMarginTop = col.rBorderTop;
        }
        if (!Object.ReferenceEquals(col.pp_BorderTop, PenProp.pp_Null)) {
          cell.pp_LineTop = col.pp_BorderTop;
        }
      }
    }

    //----------------------------------------------------------------------------------------------------x
    /// <summary>This method will be called before the report objects will be written to the container.</summary>
    internal protected override void OnBeforeWrite() {
      for (Int32 iCol = 0;  iCol < al_TlmColumn.Count;  iCol++) {
        TlmCell cell = tlmRow_Committed.aTlmCell[iCol];
        if (cell.tlmColumn_Start.iIndex != iCol) {
          continue;
        }
        TlmColumn col = al_TlmColumn[iCol];
        if (!Double.IsNaN(col.rBorderBottom)) {
          cell.rMarginBottom = col.rBorderBottom;
        }
        if (!Object.ReferenceEquals(col.pp_BorderBottom, PenProp.pp_Null)) {
          cell.pp_LineBottom = col.pp_BorderBottom;
        }
      }
    }

  }
}
