unit foBafGridFilter;

// this code is under the BAF fair use license (BFUL) - https://bafbal.de/index.php?title=Bful
// for filtering the grid

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
  FMX.Controls.Presentation, uBafPage, uBafTypes, uBafComboHelper,
  uStringIniFile;

type
  TFrmBafFilter = class(TForm)
    pnlDesk: TPanel;
    btnAbort: TButton;
    PanelGrid: TPanel;
    btnOk: TButton;
    btnClearAll: TButton;
    procedure btnClearAllClick(Sender: TObject);
  private
    FPage: TBafPage;
    FFilterGrid: TBafSimpleGrid;
    FFgSegment: TBafPageSegment;
    FSegment: TBafPageSegment;
    FFilterHelper: TBafComboHelper;
    procedure CreateGrid;
    procedure InitLookup;
    procedure InitLanguage;
    procedure InitFilter;
    procedure DoFilter;
  public
    class procedure ShowSegment(ASegment: TBafPageSegment);
  end;


implementation

{$R *.fmx}

uses foMain, uBafTranslationModule;

{ TFrmBafFilter }

procedure TFrmBafFilter.btnClearAllClick(Sender: TObject);
var
  i: integer;
begin
  for i := 0 to FFilterGrid.RowCount - 1 do begin
    FFilterGrid.Cells[rtData, 2, i].Text := '';
    FFilterGrid.Cells[rtData, 3, i].Text := '';
    FFilterGrid.Cells[rtData, 4, i].Text := '';
  end;
  FFilterGrid.Repaint;
end;

procedure TFrmBafFilter.CreateGrid;
var
  LPrim: TBafPagePrimaryDiv;
  LCat: TBafPageCategory;
  LColumn: TBafSgColumn;
begin
  FPage := TBafPage.Create(frmMain);
  FPage.Parent := PanelGrid;
  FPage.Align := TAlignLayout.Client;
  LPrim := FPage.PrimaryDivs.Add;
  LPrim.AutoSize := true;
  LCat := LPrim.Categories.Add;
  LCat.Caption := 'Filter';
  LCat.AutoSize := true;
  LCat.Size := 120;
  FFgSegment := LCat.Segments.Add;
  FFgSegment.SegmentType := stGrid;
  FFgSegment.Header := '';
  FFgSegment.SegRight := brWrite;
  FFilterGrid := FFgSegment.Grid;
  FFilterGrid.Columns.LineType := ltSingleStretch;
  FFilterGrid.Columns.AddColumn('', 'No', '', true, true, 30, 0);
  FFilterGrid.Columns.AddColumn('', 'Field', '', true, true, 100, 0);
  LColumn := FFilterGrid.Columns.AddColumn('op', 'Operator', '', false, true, 80, 200);
  LColumn.CellType := ctLookup;
  LColumn.CellLookupHelper := FFilterHelper;
  LColumn.CellVisible := true;
  LColumn := FFilterGrid.Columns.AddColumn('', 'Wert 1', '', false, true, 80, 200);
  LColumn.CellVisible := true;
  LColumn := FFilterGrid.Columns.AddColumn('', 'Wert 2', '', false, true, 80, 200);
  LColumn.CellVisible := true;
  FFilterGrid.Columns.GridHeaderLineBreak;
end;

procedure TFrmBafFilter.DoFilter;
var
  LRow: integer;
  LIni: TStringIniFile;
  LFilter, LWert1, LWert2, LCat: string;
begin
  FFgSegment.Grid.HideEdit(true);
  LIni := TStringIniFile.Create('');
  try
    for LRow := 0 to FFgSegment.Grid.RowCount(rtData) - 1 do begin
      LFilter := FFgSegment.Grid.DataCells[2, LRow].Text;
      LWert1 := FFgSegment.Grid.DataCells[3, LRow].Text;
      LWert2 := FFgSegment.Grid.DataCells[4, LRow].Text;
      if (LFilter <> '') and ((LWert1 <> '')
          or (LFilter = 'empty') or (LFilter = 'notempty')) then begin
        LCat := FFgSegment.Grid.DataCells[1, LRow].Text;
        LIni.WriteString(LCat, 'filter', LFilter);
        LIni.WriteString(LCat, 'wert_1', LWert1);
        LIni.WriteString(LCat, 'wert_2', LWert2);
      end;
    end;
    FSegment.Grid.FilterStatement := LIni.AsString;
  finally
    LIni.Free;
  end;

end;

procedure TFrmBafFilter.InitFilter;
var
  LCol, LRow: integer;
  LCell: TBafSgCell;
  LColumn: TBafSgColumn;
  s: string;
  LIni: TStringIniFile;
begin
  LIni := TStringIniFile.Create('');
  try
    LIni.AsString := FSegment.Grid.FilterStatement;
    LRow := 0;
    for LCol := 0 to FSegment.Grid.Columns.Count - 1 do begin
      LColumn := FSegment.Grid.Columns.Items[LCol];
      s := LColumn.Caption;
      if s = '' then
        s := FSegment.Grid.Cells[rtHeader, LCol, 0].Text;
//        s := FSegment.Grid.Cells[rtHeader, LCol, FSegment.FilterColumnsRow].Text;
      if (LColumn.Width > 1) and (s <> '') then begin
        FFilterGrid.Cells[rtData, 0, LRow].Text := IntToStr(LCol);
        LCell := FFilterGrid.Cells[rtData, 1, LRow];
        LCell.Text := s;
        LCell.ReadOnly := true;

        FFilterGrid.Cells[rtData, 2, LRow].Text := LIni.ReadString(s, 'filter', '');
        FFilterGrid.Cells[rtData, 3, LRow].Text := LIni.ReadString(s, 'wert_1', '');
        FFilterGrid.Cells[rtData, 4, LRow].Text := LIni.ReadString(s, 'wert_2', '');
        inc(LRow);
      end;
    end;
    FFgSegment.GridCalcHeight;
  finally
    LIni.Free;
  end;
  FPage.SetAutoSize;
  FPage.RecalcCells;
end;

procedure TFrmBafFilter.InitLanguage;
var
  s: string;
begin
  s := TBafTranslationModule.BafTranslate('$T(Abort)');
  if s <> '' then
    btnAbort.Text := s;
  s := TBafTranslationModule.BafTranslate('$T(clear_all)');
  if s <> '' then
    btnClearAll.Text := s;
end;

procedure TFrmBafFilter.InitLookup;
begin
  FFilterHelper := TBafComboHelper.Create(false);
  FFilterHelper.AddGuidItem('', '');
  FFilterHelper.AddGuidItem('=', 'Equal');
  FFilterHelper.AddGuidItem('= CI (CaseInsensitive)', 'EqualCi');
  FFilterHelper.AddGuidItem('in Liste', 'List');
  FFilterHelper.AddGuidItem('in Liste CI', 'ListCi');
  FFilterHelper.AddGuidItem('Start', 'Start');
  FFilterHelper.AddGuidItem('Start CI', 'StartCi');
  FFilterHelper.AddGuidItem('Teilstring', 'Part');
  FFilterHelper.AddGuidItem('Teilstring CI', 'PartCi');
  FFilterHelper.AddGuidItem('leer', 'empty');
  FFilterHelper.AddGuidItem('nicht leer', 'notempty');
  FFilterHelper.AddGuidItem('>', '>');
  FFilterHelper.AddGuidItem('>=', '>=');
  FFilterHelper.AddGuidItem('<', '<');
  FFilterHelper.AddGuidItem('<=', '<=');
  FFilterHelper.AddGuidItem('zwischen', 'Between');
  FFilterHelper.AddGuidItem('Wert 1 oder Wert 2', 'v1orv2');
end;

class procedure TFrmBafFilter.ShowSegment(ASegment: TBafPageSegment);
var
  FrmBafFilter: TFrmBafFilter;
begin
  FrmBafFilter := TFrmBafFilter.Create(nil);
  try
    FrmBafFilter.FSegment := ASegment;
    if ASegment.SegmentType in [stGrid, stXGrid, stXXGrid] then begin
      if frmMain.Scale > 0.45 then begin
        FrmBafFilter.pnlDesk.Scale.X := frmMain.Scale;
        FrmBafFilter.pnlDesk.Scale.Y := frmMain.Scale;
      end;
      FrmBafFilter.InitLanguage;
      FrmBafFilter.InitLookup;
      FrmBafFilter.CreateGrid;
      FrmBafFilter.InitFilter;
      if FrmBafFilter.ShowModal = mrOk then
        FrmBafFilter.DoFilter;
    end;
  finally
    FrmBafFilter.Free;
  end;
end;

end.
