unit column_selection;

{$mode delphi}{$H+}

interface

uses
  Classes, Controls, Forms, StdCtrls, CheckLst, ExtCtrls, SysUtils,
  apphelpers, extra_controls, EditBtn;

type

  { TfrmColumnSelection }

  TfrmColumnSelection = class(TExtForm)
    btnCancel: TButton;
    btnOK: TButton;
    chkSelectAll: TCheckBox;
    chklistColumns: TCheckListBox;
    chkSort: TCheckBox;
    editFilter: TEditButton;
    chkShowRowId: TCheckBox;
    procedure btnCancelClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure chklistColumnsClickCheck(Sender: TObject);
    procedure chkSelectAllClick(Sender: TObject);
    procedure btnOKClick(Sender: TObject);
    procedure PopulateList(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormDeactivate(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure editFilterButtonClick(Sender: TObject);
  private
    { Private declarations }
    FCheckedColumns: TStringList;
    FLastFilter: String;
  public
    { Public declarations }
  end;


implementation

uses main;


{$R *.lfm}



procedure TfrmColumnSelection.FormCreate(Sender: TObject);
begin
  FCheckedColumns := TStringList.Create;
  Width := AppSettings.ReadInt(asColumnSelectorWidth);
  Height := AppSettings.ReadInt(asColumnSelectorHeight);
end;


{**
  FormShow
}
procedure TfrmColumnSelection.FormShow(Sender: TObject);
var
  i: Integer;
  Col: String;
begin
  FCheckedColumns.Clear;
  for i:=0 to Mainform.SelectedTableColumns.Count-1 do begin
    Col := Mainform.SelectedTableColumns[i].Name;
    chklistColumns.Items.Add(Col);
    if (Mainform.DataGridHiddenColumns.Count = 0) or
      (Mainform.DataGridHiddenColumns.IndexOf(chklistColumns.Items[i]) = -1)
      then begin
      FCheckedColumns.Add(Col);
      chklistColumns.Checked[i] := True;
    end;
  end;

  // Call check-event to update state of "Select / Deselect all" checkbox
  chklistColumnsClickCheck( Sender );

  // Restore last used sorting state from registry
  chkSort.Checked := AppSettings.ReadBool(asDisplayedColumnsSorted);
  chkShowRowId.Checked := AppSettings.ReadBool(asShowRowId);
end;


{**
  OK clicked
}
procedure TfrmColumnSelection.btnOKClick(Sender: TObject);
var
  i: Integer;
  Col: String;
begin
  AppSettings.WriteBool(asDisplayedColumnsSorted, chkSort.Checked);
  AppSettings.WriteBool(asShowRowId, chkShowRowId.Checked);
  // Prepare string for storing in registry.
  // Use quote-character as separator to ensure columnnames can
  // be extracted safely later
  Mainform.DataGridHiddenColumns.Clear;
  for i:=0 to Mainform.SelectedTableColumns.Count-1 do begin
    Col := Mainform.SelectedTableColumns[i].Name;
    if FCheckedColumns.IndexOf(Col) = -1 then
      Mainform.DataGridHiddenColumns.Add(Col);
  end;
  InvalidateVT(Mainform.DataGrid, VTREE_NOTLOADED_PURGECACHE, False);
  btnCancel.OnClick(Sender);
end;


{**
  Select / Deselect all
}
procedure TfrmColumnSelection.chkSelectAllClick(Sender: TObject);
var
  cb: TCheckBox;
  i: Integer;
begin
  // Avoid executing when Checked or State property was modified by code. Happens in OnClickCheck handler of TCheckListBox.
  cb := Sender as TCheckBox;
  if cb.Tag = SUSPEND_ONCLICK then
    Exit;
  chklistColumns.CheckAll(cb.State);
  for i:=0 to chklistColumns.Items.Count-1 do begin
    if (FCheckedColumns.IndexOf(chklistColumns.Items[i]) = -1) and (cb.State = cbChecked) then
      FCheckedColumns.Add(chklistColumns.Items[i]);
    if (FCheckedColumns.IndexOf(chklistColumns.Items[i]) > -1) and (cb.State = cbUnchecked) then
      FCheckedColumns.Delete(FCheckedColumns.IndexOf(chklistColumns.Items[i]));
  end;
end;


procedure TfrmColumnSelection.editFilterButtonClick(Sender: TObject);
begin
  if IsNotEmpty(editFilter.Text) then begin
    FLastFilter := editFilter.Text;
    editFilter.Text := '';
  end else if not FLastFilter.IsEmpty then begin
    editFilter.Text := FLastFilter;
    FLastFilter := '';
  end;
end;


{**
  Click within column list
  Updates state of "Select / deselect all" checkbox
}
procedure TfrmColumnSelection.chklistColumnsClickCheck(Sender: TObject);
var
  i : Integer;
  AllSelected, NoneSelected : Boolean;
  FocusedItem: String;
  FocusedItemIndex: Integer;
begin
  // Add or remove clicked item from list
  if chklistColumns.ItemIndex > -1 then begin
    FocusedItem := chklistColumns.Items[chklistColumns.ItemIndex];
    if chklistColumns.Checked[chklistColumns.ItemIndex] then begin
      FCheckedColumns.Add(FocusedItem)
    end else begin
      FocusedItemIndex := FCheckedColumns.IndexOf(FocusedItem);
      if FocusedItemIndex > -1 then
        FCheckedColumns.Delete(FocusedItemIndex);
    end;
  end;

  Allselected := True;
  NoneSelected := True;
  for i:=0 to chklistColumns.Items.Count-1 do begin
    if chklistColumns.Checked[i] then
      NoneSelected := False
    else
      AllSelected := False;
  end;
  chkSelectAll.Tag := SUSPEND_ONCLICK;
  if NoneSelected then
    chkSelectAll.State := cbUnchecked
  else if AllSelected then
    chkSelectAll.State := cbChecked
  else
    chkSelectAll.State := cbGrayed;
  chkSelectAll.Tag := 0;
end;


{**
  Sort / Unsort the list with fields
}
procedure TfrmColumnSelection.PopulateList(Sender: TObject);
var
  i: Integer;
  Col: String;
  TempList: TStringList;
begin
  // Setting Sorted to false doesn't resort anything in the list.
  // So we have to add all items again in original order
  TempList := TStringList.Create;
  TempList.Sorted := chkSort.Checked;
  for i:=0 to Mainform.SelectedTableColumns.Count-1 do begin
    Col := Mainform.SelectedTableColumns[i].Name;
    if IsEmpty(editFilter.Text) or (Pos(LowerCase(editFilter.Text), LowerCase(Col)) > 0) then
      TempList.Add(Col);
  end;
  chklistColumns.Clear;
  chklistColumns.Items.AddStrings(TempList);
  TempList.Free;

  // check those which remembered as checked
  for i:=0 to chklistColumns.Items.Count-1 do begin
    chklistColumns.Checked[i] := FCheckedColumns.IndexOf(chklistColumns.Items[i]) > -1;
  end;
end;


procedure TfrmColumnSelection.btnCancelClick(Sender: TObject);
begin
  Mainform.tbtnDataColumns.Down := False;
  Close;
end;

procedure TfrmColumnSelection.FormDestroy(Sender: TObject);
begin
  AppSettings.WriteInt(asColumnSelectorWidth, ScaleFormToDesign(Width));
  AppSettings.WriteInt(asColumnSelectorHeight, ScaleFormToDesign(Height));
end;


{**
  Cancel this dialog if the user clicks elsewhere on mainform
}
procedure TfrmColumnSelection.FormDeactivate(Sender: TObject);
begin
  btnCancel.OnClick(Sender);
end;


{**
  Be sure the form is destroyed after closing.
}
procedure TfrmColumnSelection.FormClose(Sender: TObject; var Action:
    TCloseAction);
begin
  Action := caFree;
  FCheckedColumns.Free;
end;


end.
