unit uViewGrid;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, uViewBase, cxStyles, cxCustomData, cxGraphics, cxFilter, cxData,
  cxDataStorage, cxEdit, DB, cxDBData, uDADataTable, cxGridLevel,
  cxClasses, cxControls, cxGridCustomView, cxGridCustomTableView,
  cxGridTableView, cxGridDBTableView, cxGrid, Menus, ActnList, Grids,
  DBGrids, JvComponent, JvFormAutoSize, dxPSGlbl, dxPSUtl, dxPSEngn,
  dxPrnPg, dxBkgnd, dxWrap, dxPrnDev, dxPSCompsProvider, dxPSFillPatterns,
  dxPSEdgePatterns, dxPSCore, dxPScxCommon, dxPScxGridLnk, dxPrnDlg,
  cxIntlPrintSys3, dxPSPrvwAdv;

type
  IViewGrid = interface(IViewBase)
    ['{07468FAD-4891-42E6-B646-51F17F0033F5}']
    function GetDblClick: TNotifyEvent;
    function GetFilter: string;
    function GetPopupMenu: TPopupMenu;
    function GetGrid : TcxGrid;
    procedure Preview;
    procedure Print;
    procedure PrintSetup;
    procedure GotoFirst;
    procedure GotoLast;
    procedure SetDblClick(const Value: TNotifyEvent);
    procedure SetFilter(const Value: string);
    procedure SetPopupMenu(const Value: TPopupMenu);
    procedure RefreshGrid;
    function GetMultiSelection: Boolean;
    procedure SetMultiSelection(const Value: Boolean);
    property Filter: string read GetFilter write SetFilter;
    property OnDblClick: TNotifyEvent read GetDblClick write SetDblClick;
    property PopupMenu: TPopupMenu read GetPopupMenu write SetPopupMenu;
    property MultiSelection : Boolean read GetMultiSelection write SetMultiSelection;
    property Grid : TcxGrid read GetGrid;
    procedure SyncFocusedRecordsFromGrid;
    procedure SyncFocusedRecordsFromDataSet;
    procedure StoreToRegistry;
    procedure RestoreFromRegistry;
  end;

  TfrViewGrid = class(TfrViewBase, IViewGrid)
    ActionList1: TActionList;
    cxGrid: TcxGrid;
    cxGridLevel: TcxGridLevel;
    cxGridView: TcxGridDBTableView;
    DADataSource: TDADataSource;
    dxComponentPrinter: TdxComponentPrinter;
    dxComponentPrinterLink: TdxGridReportLink;
    dxPSEngineController1: TdxPSEngineController;
    cxStyleRepository1: TcxStyleRepository;
    cxStyleEven: TcxStyle;
    cxStyleOdd: TcxStyle;
    cxStyleSelection: TcxStyle;
    procedure cxGridViewDblClick(Sender: TObject);
    procedure cxGridViewDataControllerSortingChanged(Sender: TObject);
//    procedure SelectionChanged(Sender: TcxCustomGridTableView); virtual; abstract;
  private
    FFilter: string;
    FOnFilterChanged : TNotifyEvent;    
    FOnDblClick: TNotifyEvent;
    FPopupMenu: TPopupMenu;
    procedure FiltrarGrid(TextoFiltro : String);
  protected
    function GetGrid : TcxGrid;
    function GetDblClick: TNotifyEvent; virtual;
    function GetFilter: string; virtual;
    function GetPopupMenu: TPopupMenu; virtual;
    function GetMultiSelection: Boolean; virtual;
    procedure SetDblClick(const Value: TNotifyEvent); virtual;
    procedure SetFilter(const Value: string); virtual;
    procedure SetPopupMenu(const Value: TPopupMenu); virtual;
    procedure SetMultiSelection(const Value: Boolean); virtual;
    procedure FilterChanged(Sender : TObject); virtual;
        
  public
    procedure ShowEmbedded(const AParent : TWinControl); override;
    constructor Create(AOwner: TComponent); override;
    procedure Preview; virtual;
    procedure Print; virtual;
    procedure PrintSetup;
    procedure GotoFirst;
    procedure GotoLast;
    procedure StoreToRegistry; virtual;
    procedure RestoreFromRegistry; virtual;
    property Filter: string read GetFilter write SetFilter;
    property OnDblClick: TNotifyEvent read GetDblClick write SetDblClick;
    property PopupMenu: TPopupMenu read GetPopupMenu write SetPopupMenu;
    property Grid : TcxGrid read GetGrid;
    procedure SyncFocusedRecordsFromGrid; virtual;
    procedure SyncFocusedRecordsFromDataSet; virtual;
    property MultiSelection : Boolean read GetMultiSelection write SetMultiSelection;
    procedure RefreshGrid; virtual;
  end;

procedure Register;

var
  frViewGrid: TfrViewGrid;

implementation

uses
  CCReg, uDataModuleBase, uDBSelectionList;

{$R *.dfm}

{ TfrViewGrid }

procedure Register;
begin
  RegisterCustomContainer(TfrViewGrid);
end;


{
********************************* TfrViewGrid **********************************
}
constructor TfrViewGrid.Create(AOwner: TComponent);
begin
  inherited;
  FFilter := '';
  FOnFilterChanged := FilterChanged;  
  GotoFirst;
end;

procedure TfrViewGrid.cxGridViewDblClick(Sender: TObject);
begin
  if Assigned(FOnDblClick) then
    FOnDblClick(Sender);
end;

procedure TfrViewGrid.FiltrarGrid(TextoFiltro : String);
var
  Columna: TcxGridDBColumn;
  i: Integer;
  AItemList: TcxFilterCriteriaItemList;
begin
  with cxGrid.ActiveView.DataController.Filter do
  begin
    BeginUpdate;
    try
      Options := [fcoCaseInsensitive, fcoSoftCompare];
      Root.Clear;
      if Length(TextoFiltro) > 0 then
      begin
        AItemList := Root.AddItemList(fboAnd);
        AItemList.BoolOperatorKind := fboOr;
        for i:=0 to (cxGrid.ActiveView as TcxGridDBTableView).ColumnCount - 1 do
        begin
          Columna := (cxGrid.ActiveView as TcxGridDBTableView).Columns[i];
          if (Length(Columna.Caption) > 0) and (Columna.Caption <> 'RecID') then
             AItemList.AddItem(Columna, foLike, '%'+TextoFiltro+'%', IntToStr(i));
        end;
        Active := True;
      end
      else
        Active := False;
    finally
      EndUpdate;
    end;
  end;
end;

function TfrViewGrid.GetDblClick: TNotifyEvent;
begin
  Result := FOnDblClick;
end;

function TfrViewGrid.GetFilter: string;
begin
  Result := FFilter;
end;

function TfrViewGrid.GetPopupMenu: TPopupMenu;
begin
  Result := FPopupMenu;
end;

procedure TfrViewGrid.GotoFirst;
begin
  cxGridView.DataController.GotoFirst;
end;

procedure TfrViewGrid.GotoLast;
begin
  cxGridView.DataController.GotoLast;
end;

procedure TfrViewGrid.SetDblClick(const Value: TNotifyEvent);
begin
  FOnDblClick := Value;
end;

procedure TfrViewGrid.SetFilter(const Value: string);
begin
  if FFilter <> Value then
  begin
    FFilter := Value;
    FiltrarGrid(FFilter);
    if Assigned(FOnFilterChanged) then
      FOnFilterChanged(Self);
  end;
end;

procedure TfrViewGrid.SetPopupMenu(const Value: TPopupMenu);
begin
  FPopupMenu := Value;
  cxGridView.PopupMenu := FPopupMenu;
end;

procedure TfrViewGrid.cxGridViewDataControllerSortingChanged(
  Sender: TObject);
var
  i: Integer;
  AFields: array of String;
  ADirections: array of TDASortDirection;
  ABookmark : Pointer;
begin
  inherited;

  with cxGridView do
  begin
    for i := 0 to SortedItemCount - 1 do
    begin
      SetLength(AFields, i+1);
      AFields[i] := (SortedItems[i] as TcxGridDBColumn).DataBinding.FieldName;
      SetLength(ADirections, i+1);
      case (SortedItems[i] as TcxGridDBColumn).SortOrder of
        soAscending   : ADirections[i] := sdAscending;
        soDescending  : ADirections[i] := sdDescending;
      end;
    end;
  end;

  if Assigned(DADataSource.DataTable) then
    with DADataSource.DataTable do
    begin
      DisableControls;
      ABookmark := GetBookMark;      
      try
        Sort(AFields, ADirections);
        GotoBookmark(ABookmark);
      finally
        FreeBookmark(ABookmark);
        EnableControls;
      end;
    end;
end;

function TfrViewGrid.GetGrid: TcxGrid;
begin
  Result := cxGrid;
end;

procedure TfrViewGrid.ShowEmbedded(const AParent : TWinControl);
begin
  inherited;

  if not DADataSource.DataTable.Active then
    DADataSource.DataTable.Active := True;

  with Grid do
  begin
    ActiveView.DataController.GotoFirst;
    ActiveView.Focused := True;
    if (ActiveView.ViewData as TcxCustomGridTableViewData).RecordCount > 0 then
    begin
      (ActiveView.ViewData as TcxCustomGridTableViewData).Records[0].Selected := True;
      (ActiveView.ViewData as TcxCustomGridTableViewData).Records[0].Focused := True;
    end;
{    if (ActiveView is TcxCustomGridTableView) then
      (ActiveView as TcxCustomGridTableView).ApplyBestFit;}
  end;
end;

procedure TfrViewGrid.Preview;
begin
  dxComponentPrinter.Preview;
end;

procedure TfrViewGrid.Print;
begin
  dxComponentPrinter.Print(True, nil, nil);
end;

procedure TfrViewGrid.PrintSetup;
begin
  dxComponentPrinter.PageSetup(nil);
end;

procedure TfrViewGrid.RefreshGrid;
var
  FocusedRow, TopRow, TopRecord : Integer;
  ARecordID : Variant;
begin
  { Refrescar las filas del grid a partir del dataset y colocar la fila
    seleccionada donde estaba }

  if DADataSource.DataTable.State = dsBrowse then
  begin
    TopRow := cxGridView.Controller.TopRowIndex;
    TopRecord := cxGridView.Controller.TopRecordIndex;

    FocusedRow := cxGridView.DataController.FocusedRowIndex;
    ARecordID := cxGridView.DataController.GetRecordId(cxGridView.DataController.FocusedRecordIndex);
    try
      cxGridView.DataController.UpdateItems(False);  // <- Refresco
    finally
      cxGridView.Controller.TopRowIndex := TopRow;
      cxGridView.Controller.TopRecordIndex := TopRecord;
      cxGridView.DataController.FocusedRowIndex := FocusedRow;
    end;
  end;
end;

procedure TfrViewGrid.SyncFocusedRecordsFromDataSet;
//var
//  AIndex : Integer;
begin
{  for AIndex := 0 to cxGridView.DataController.RecordCount - 1 do
  begin
    if (MessageBox(0, PChar(cxGridView.DataController.GetDisplayText(AIndex, 1)), '',
      MB_ICONQUESTION or MB_YESNO or MB_DEFBUTTON1) = idYes) then
    begin
      cxGridView.DataController.SelectAll;


      cxGridView.DataController.SelectRows(AIndex, AIndex);
      cxGridView.DataController.FocusSelectedRow(0);
      Break;
    end;
  end;}
end;

procedure TfrViewGrid.SyncFocusedRecordsFromGrid;
var
  AValue : Variant;
  i: Integer;
  aObj : ISelectedRowList;
  Clave : String;
begin
  if not Supports(DADataSource.DataTable, ISelectedRowList, aObj) then
    raise Exception.Create('La tabla no soporta el interfaz ISelectedRowList (SyncFocusedRecords)');

  Clave := cxGridView.DataController.KeyFieldNames;
  if Length(Clave) = 0 then
    raise Exception.Create('Falta indicar los campos clave de la tabla en la vista del grid (SyncFocusedRecords)');

  DADataSource.DataTable.DisableControls;
//  DADataSource.DataTable.DisableEventHandlers;  <- No descomentar
  try
    for i := 0 to cxGridView.Controller.SelectedRecordCount - 1 do
    begin
      AValue := cxGridView.Controller.SelectedRows[i].Values[cxGridView.GetColumnByFieldName(Clave).Index];
      DADataSource.DataTable.First;
      if DADataSource.DataTable.Locate(Clave, AValue, []) then
        aObj.SelectedRows.CurrentRowSelected := True;
    end;
  finally
//    DADataSource.DataTable.EnableEventHandlers; <- No descomentar
    DADataSource.DataTable.EnableControls;
  end;
end;

function TfrViewGrid.GetMultiSelection: Boolean;
begin
  Result := (cxGrid.ActiveView as TcxGridDBTableView).OptionsSelection.MultiSelect;
end;

procedure TfrViewGrid.SetMultiSelection(const Value: Boolean);
begin
  (cxGrid.ActiveView as TcxGridDBTableView).OptionsSelection.MultiSelect := True;
//  (cxGrid.ActiveView as TcxGridDBTableView).OnSelectionChanged := SelectionChanged;
end;

procedure TfrViewGrid.RestoreFromRegistry;
begin
  cxGridView.RestoreFromRegistry('Software\\FactuGES\\GridSettings\\' + Self.Name, False, False, []);
end;

procedure TfrViewGrid.StoreToRegistry;
begin
  cxGridView.StoreToRegistry('Software\\FactuGES\\GridSettings\\' + Self.Name, True, []);
end;

procedure TfrViewGrid.FilterChanged(Sender: TObject);
begin
//
end;

end.
