{*************************************************************************}
{ TMS PDF Engine                                                          }
{ for Delphi & C++Builder                                                 }
{                                                                         }
{ written by TMS Software                                                 }
{           copyright © 2015                                              }
{           Email : info@tmssoftware.com                                  }
{           Web : http://www.tmssoftware.com                              }
{                                                                         }
{ The source code is given as is. The author is not responsible           }
{ for any possible damage done due to the use of this code.               }
{ The component can be freely used in any application. The complete       }
{ source code remains property of the author and may not be distributed,  }
{ published, given or sold in any form as such. No parts of the source    }
{ code can be included in any other component or application without      }
{ written authorization of the author.                                    }
{*************************************************************************}
unit iwadvwebgridpdfio;

{$I TMSDEFS.INC}

interface

uses
  Classes, IWWebGrid, IWAdvWebGrid, IwAdvPDFLib, IwAdvPDFIO, Math, IWApplication;

type
  TAGrid = class(TTIWCustomWebGrid)
  end;

  TTIWAdvWebGridPDFIO = class(TIwAdvPDFIOComponent)
  private
    FAdvWebGrid: TTIWCustomWebGrid;
    function CurrentGrid: TAGrid;
  protected
    procedure Notification(AComponent: TComponent; AOperation: TOperation); override;
  public
    procedure PDFExport(AFileName: string; WebApplication: TIWApplication);
  published
    property AdvWebGrid: TTIWCustomWebGrid read FAdvWebGrid write FAdvWebGrid;
  end;


implementation

uses
  Graphics, SysUtils
  {$IFDEF DELPHIXE3_LVL}
  , System.UITypes
  {$ENDIF}
  ;


{ TTIWAdvWebGridPDFIO }

function TTIWAdvWebGridPDFIO.CurrentGrid: TAGrid;
begin
  Result := TAGrid(FAdvWebGrid);
end;

procedure TTIWAdvWebGridPDFIO.Notification(AComponent: TComponent;
  AOperation: TOperation);
begin
  inherited;
  if (AComponent = FAdvWebGrid) and (AOperation = opRemove) then
    FAdvWebGrid := nil;
end;

procedure TTIWAdvWebGridPDFIO.PDFExport(AFileName: string; WebApplication: TIWApplication);
var
  c,r: integer;
  W,MW,WI,H: Integer;
  pdf: TPDFDocument;
  table: TPDFTableItem;
  tri: TPDFTableRowItem;
  tci: TPDFTableColumnItem;
  trci: TPDFTableRowCellItem;
  font: TFont;

  AFont: TFont;
  membmp: TBitmap;
  memico: TIcon;
  tt: TTextType;
  m: TPdfMarges;
  NumRows, RowOffset, PageOffset: integer;
begin
  if not Assigned(AdvWebGrid) then
    raise Exception.Create('No TIWAdvWebGrid assigned');

  pdf := TPDFDocument.Create(Self);
  if PageLayout = plLandscape then
  begin
    pdf.Width := 762;
    pdf.Height := 559;
  end
  else
  begin
    pdf.Width := 612;
    pdf.Height := 775;
  end;
  pdf.ImagesList := CurrentGrid.Images;

  // Set Marges
  m.Top := 15;
  m.Bottom:= 15;
  m.Left:= 15;
  m.Right:= 15;

  pdf.CurrentPage.Marges := m;

  pdf.RootPath := WebApplication.ApplicationPath;

  pdf.Header := (Header);
  pdf.Footer := (Footer);

  pdf.MetaData := MetaData;

  font := pdf.DefaultFont;
  font.Name := 'Arial';


  table := pdf.CurrentPage.Tables.Add;
  table.X := 10;
  table.Y := pdf.Height - pdf.LineYPosition;
  table.Width := CurrentGrid.Width;

  {$REGION 'Header'}
  // First add the header
  if CurrentGrid.ShowColumnHeader then
  begin
    tri := table.Rows.Add;
    tri.Height := CurrentGrid.DefaultRowHeight;
    for c := 0 to CurrentGrid.Columns.Count - 1 do
    begin
      tci := table.Columns.Add;
      tci.Width := CurrentGrid.Columns[c].Width;

      trci := tri.Cells.Add;
      trci.Text := CurrentGrid.Columns[c].Title;


      AFont := TFont.Create;
      try
        AFont.Assign(CurrentGrid.Font);
        if CurrentGrid.Columns[c].Font.Enabled then
        begin
          if (CurrentGrid.Columns[c].ColumnHeaderFont.Color <> clNone) then
            AFont.Color := CurrentGrid.Columns[c].ColumnHeaderFont.Color;
          if CurrentGrid.Columns[c].ColumnHeaderFont.Style <> CurrentGrid.Font.Style then
            AFont.Style := CurrentGrid.Columns[c].ColumnHeaderFont.Style;
          if CurrentGrid.Columns[c].ColumnHeaderFont.FontFamily <> CurrentGrid.Font.FontFamily then
            AFont.Name := CurrentGrid.Columns[c].ColumnHeaderFont.FontFamily;
          if CurrentGrid.Columns[c].ColumnHeaderFont.Size <> CurrentGrid.Font.Size then
            AFont.Size := CurrentGrid.Columns[c].ColumnHeaderFont.Size;
        end;

        trci.TextFont.Assign(AFont);
      finally
        AFont.Free;
      end;

      trci.HAlign := CurrentGrid.Columns[c].ColumnHeaderAlignment;
      trci.VAlign := TPdfVerticalAlignment(vaTop);

      trci.BorderColor := CurrentGrid.Borders.Color;
      trci.UrlColor := clBlue;
      trci.BackgroundColor := CurrentGrid.ColumnHeaderColor;
      trci.BackgroundColorFrom := clNone;
      trci.BackgroundColorTo := clNone;
      trci.BackgroundMirrorColorTo := clNone;
      trci.BackgroundMirrorColorFrom := clNone;
      trci.BackgroundOrientation := False;


      trci.IsMerged := False;
    end;
  end;
  {$ENDREGION}

  {$REGION 'SubHeader'}
  // First add the header
  if CurrentGrid.ShowColumnHeader then
  begin
    tri := table.Rows.Add;
    tri.Height := CurrentGrid.DefaultRowHeight;
    for c := 0 to CurrentGrid.Columns.Count - 1 do
    begin
      trci := tri.Cells.Add;
      trci.Text := CurrentGrid.Columns[c].SubTitle;

      trci.TextFont.Assign(CurrentGrid.Font);

      trci.HAlign := CurrentGrid.Columns[c].ColumnHeaderAlignment;
      trci.VAlign := TPdfVerticalAlignment(vaTop);

      trci.BorderColor := CurrentGrid.Borders.Color;
      trci.UrlColor := clBlue;
      trci.BackgroundColor := CurrentGrid.ColumnHeaderColor;
      trci.BackgroundColorFrom := clNone;
      trci.BackgroundColorTo := clNone;
      trci.BackgroundMirrorColorTo := clNone;
      trci.BackgroundMirrorColorFrom := clNone;
      trci.BackgroundOrientation := False;

      trci.IsMerged := False;
    end;
  end;
  {$ENDREGION}

  // The grid
  CurrentGrid.GetRowInfo(NumRows, RowOffset, PageOffset);
  for r := 0 to NumRows - 1 do
  begin
    tri := table.Rows.Add;
    tri.Height := CurrentGrid.DefaultRowHeight;

    {$REGION 'Adaptive Row Heights'}
    //first check for adaptive row height
    MW := 0;
    WI := 0;
    for c := 0 to CurrentGrid.Columns.Count - 1 do
    begin
      AFont := TFont.Create;
      try
        AFont.Assign(CurrentGrid.Font);
        if CurrentGrid.Columns[c].Font.Enabled then
        begin
          if (CurrentGrid.Columns[c].Font.Color <> clNone) then
            AFont.Color := CurrentGrid.Columns[c].Font.Color;
          if CurrentGrid.Columns[c].Font.Style <> CurrentGrid.Font.Style then
            AFont.Style := CurrentGrid.Columns[c].Font.Style;
          if CurrentGrid.Columns[c].Font.FontFamily <> CurrentGrid.Font.FontFamily then
            AFont.Name := CurrentGrid.Columns[c].Font.FontFamily;
          if CurrentGrid.Columns[c].Font.Size <> CurrentGrid.Font.Size then
            AFont.Size := CurrentGrid.Columns[c].Font.Size;

          W := pdf.CurrentPage.GetWidthText(CurrentGrid.GetCellData(c,r), AFont);
          if (CurrentGrid.Columns[c].Width < W) and (W > MW) then
          begin
            MW := W;
            WI := c;
          end;
        end;
      finally
        AFont.Free;
      end;
    end;

    if MW > 0 then
    begin
      AFont := TFont.Create;
      try
        AFont.Assign(CurrentGrid.Font);
        if CurrentGrid.Columns[WI].Font.Enabled then
        begin
          if (CurrentGrid.Columns[WI].Font.Color <> clNone) then
            AFont.Color := CurrentGrid.Columns[WI].Font.Color;
          if CurrentGrid.Columns[WI].Font.Style <> CurrentGrid.Font.Style then
            AFont.Style := CurrentGrid.Columns[WI].Font.Style;
          if CurrentGrid.Columns[WI].Font.FontFamily <> CurrentGrid.Font.FontFamily then
            AFont.Name := CurrentGrid.Columns[WI].Font.FontFamily;
          if CurrentGrid.Columns[WI].Font.Size <> CurrentGrid.Font.Size then
            AFont.Size := CurrentGrid.Columns[WI].Font.Size;

          H := Ceil(MW/CurrentGrid.Columns[WI].Width);
          H := H * AFont.Size;
          if H > CurrentGrid.DefaultRowHeight then
          begin
            CurrentGrid.SetCellData(WI,r,WrapText(CurrentGrid.GetCellData(WI,r), CurrentGrid.Columns[WI].Width-5));
            tri.Height := H;
          end;
        end;
      finally
        AFont.Free;
      end;
    end;
    {$ENDREGION}

    for c := 0 to CurrentGrid.Columns.Count - 1 do
    begin

      if (not CurrentGrid.ShowColumnHeader) and (r = 0) then
      begin
        tci := table.Columns.Add;
        tci.Width := CurrentGrid.Columns[c].Width;
      end;

      trci := tri.Cells.Add;
      trci.BorderColor := CurrentGrid.Borders.Color;
      trci.UrlColor := clBlue;

      trci.IsMerged := False;

      {$REGION 'Background Color & alignment'}
      trci.HAlign := CurrentGrid.Columns[c].Alignment;
      trci.VAlign := TpdfVerticalAlignment.vtaTop;

      trci.BackgroundColor := CurrentGrid.Color;
      trci.BackgroundColorFrom := clNone;
      trci.BackgroundColorTo := clNone;
      trci.BackgroundMirrorColorTo := clNone;
      trci.BackgroundMirrorColorFrom := clNone;
      trci.BackgroundOrientation := False;

      {$ENDREGION}

      {$REGION 'Text Types'}
      if CurrentGrid.Columns[c].ColumnType = ctNormal then
      begin
        trci.Text := CurrentGrid.GetCellData(c,r);

        AFont := TFont.Create;
        try
          AFont.Assign(CurrentGrid.Font);
          if CurrentGrid.Columns[c].Font.Enabled then
          begin
            if (CurrentGrid.Columns[c].Font.Color <> clNone) then
              AFont.Color := CurrentGrid.Columns[c].Font.Color;
            if CurrentGrid.Columns[c].Font.Style <> CurrentGrid.Font.Style then
              AFont.Style := CurrentGrid.Columns[c].Font.Style;
            if CurrentGrid.Columns[c].Font.FontFamily <> CurrentGrid.Font.FontFamily then
              AFont.Name := CurrentGrid.Columns[c].Font.FontFamily;
            if CurrentGrid.Columns[c].Font.Size <> CurrentGrid.Font.Size then
              AFont.Size := CurrentGrid.Columns[c].Font.Size;
          end;

          trci.TextFont.Assign(AFont);
        finally
          AFont.Free;
        end;
      end;

      tt := pdf.TextType(trci.Text);
      case tt of
        ttText:
        begin
          //
        end;
        ttHTML:
        begin
          trci.HTMLText := trci.Text;
          trci.HAlign := taLeftJustify;
          trci.VAlign := TPdfVerticalAlignment.vtaBottom;
        end;
        ttURL:
        begin
          trci.Url := trci.Text;
        end;
      end;
      {$ENDREGION}

      {$REGION 'IMAGES'}
      if (CurrentGrid.Columns[c].ColumnType = ctDataImage) then
        begin
           memico := TIcon.Create;
           try
//            if CurrentGrid.Images.GetBitmap(StrToInt(CurrentGrid.Cells[c,r]), membmp) then
            CurrentGrid.Images.GetIcon(StrToInt(CurrentGrid.GetCellData(c,r)), memico);
            if Assigned(memico) and not memico.Empty then
            begin
              membmp := TBitmap.Create;
              membmp.Width := memico.Width;
              membmp.Height := memico.Height;
              membmp.Canvas.Draw(0,0, memico);
              membmp.Transparent := true;
              trci.ImageType := citImageList;
              trci.Bitmaps.Add(membmp);

              trci.ImageHAlign := TPdfCellHAlign(taLeftJustify);
              trci.ImageVAlign := TPdfCellVAlign(vatop);
            end;
          finally
          begin
            memico.Free;
          end;
        end;
      end;
      {$ENDREGION}
    end;
  end;

  {$REGION 'Footer'}
  // Now add the Footer
  if CurrentGrid.ShowFooter then
  begin
    tri := table.Rows.Add;
    tri.Height := CurrentGrid.DefaultRowHeight;
    for c := 0 to CurrentGrid.Columns.Count - 1 do
    begin

      trci := tri.Cells.Add;
      trci.Text := CurrentGrid.Columns[c].FooterText;

      trci.BackgroundColor := CurrentGrid.FooterColor;

      AFont := TFont.Create;
      try
        AFont.Assign(CurrentGrid.Font);
        if CurrentGrid.Columns[c].Font.Enabled then
        begin
          if (CurrentGrid.Columns[c].Font.Color <> clNone) then
            AFont.Color := CurrentGrid.Columns[c].Font.Color;
          if CurrentGrid.Columns[c].Font.Style <> CurrentGrid.Font.Style then
            AFont.Style := CurrentGrid.Columns[c].Font.Style;
          if CurrentGrid.Columns[c].Font.FontFamily <> CurrentGrid.Font.FontFamily then
            AFont.Name := CurrentGrid.Columns[c].Font.FontFamily;
          if CurrentGrid.Columns[c].Font.Size <> CurrentGrid.Font.Size then
            AFont.Size := CurrentGrid.Columns[c].Font.Size;
        end;

        trci.TextFont.Assign(AFont);
      finally
        AFont.Free;
      end;

      trci.HAlign := CurrentGrid.Columns[c].FooterAlignment;
      trci.VAlign := TPdfVerticalAlignment(vaCenter);

      trci.BorderColor := CurrentGrid.Borders.Color;
      trci.UrlColor := clBlue;
      trci.BackgroundColorFrom := clNone;
      trci.BackgroundColorTo := clNone;
      trci.BackgroundMirrorColorTo := clNone;
      trci.BackgroundMirrorColorFrom := clNone;
      trci.BackgroundOrientation := False;

      trci.IsMerged := False;
    end;
  end;
  {$ENDREGION}

  table.TableType := ttWysiwyg;

  if table.TableType = ttWysiwyg then
    TPDFTableItem(table).DrawFixedTable
  else
    TPDFTableItem(table).DrawTable;

  pdf.GeneratePDF(AFileName);

  pdf.Free;

  if WebApplication <> nil then
    WebApplication.SendFile(AFileName);
end;

end.
