unit uEditorDBBase;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, uEditorItem, ImgList, PngImageList, StdActns, ActnList, TBX,
  TB2Item, TB2Dock, TB2Toolbar, ComCtrls, JvExControls, JvComponent,
  JvNavigationPane, DB, uDADataTable, uEditorBase, JvFormAutoSize,
  uDAScriptingProvider, uDACDSDataTable, AppEvnts, uCustomView, uViewBase,
  JvAppStorage, JvAppRegistryStorage, JvFormPlacement,
  pngimage, ExtCtrls, dxLayoutLookAndFeels, JvComponentBase, TBXStatusBars,
  JvExComCtrls, JvStatusBar;

type
  IEditorDBBase = interface(IEditorBase)
  ['{1F5B318F-F700-4C78-ABCE-E2329AD876B8}']
  end;

  TfEditorDBBase = class(TfEditorBase, IEditorDBBase)
    dsDataTable: TDADataSource;
    procedure actAnteriorExecute(Sender: TObject);
    procedure actSiguienteExecute(Sender: TObject);
    procedure actAnteriorUpdate(Sender: TObject);
    procedure actSiguienteUpdate(Sender: TObject);
    procedure actRefrescarUpdate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); virtual;
    procedure actEliminarUpdate(Sender: TObject);
    procedure actModificarUpdate(Sender: TObject);
    procedure actPrevisualizarUpdate(Sender: TObject);
    procedure actImprimirUpdate(Sender: TObject);
    procedure actGuardarUpdate(Sender: TObject);
    procedure actGuardarCerrarUpdate(Sender: TObject);
    procedure dsDataTableDataChange(Sender: TObject; Field: TField);
  protected
    function HayDatos: Boolean;
    function GetModified: Boolean; override;
    procedure RefrescarInterno; override;
    procedure CancelarCambiosInterno; override;
  end;

implementation

uses
  uDataTableUtils, uBizInformesBase,
  uDAInterfaces, cxControls, uCustomEditor;

{$R *.dfm}

procedure TfEditorDBBase.actAnteriorExecute(Sender: TObject);
begin
  inherited;
  if Assigned(dsDataTable.DataTable) then
  begin
    if (not ModifiedQuery) then
      Exit;

    dsDataTable.DataTable.Prior;
  end;
end;

procedure TfEditorDBBase.actSiguienteExecute(Sender: TObject);
begin
  inherited;
  if Assigned(dsDataTable.DataTable) then
  begin
    if (not ModifiedQuery) then
      Exit;

    dsDataTable.DataTable.Next;
  end;
end;

procedure TfEditorDBBase.actAnteriorUpdate(Sender: TObject);
begin
  inherited;
  if HayDatos then
    (Sender as TAction).Enabled := not dsDataTable.DataTable.BOF
  else
    (Sender as TAction).Enabled := False;
end;

procedure TfEditorDBBase.actSiguienteUpdate(Sender: TObject);
begin
  inherited;
  if HayDatos then
    (Sender as TAction).Enabled := not dsDataTable.DataTable.EOF
  else
    (Sender as TAction).Enabled := False;
end;

procedure TfEditorDBBase.CancelarCambiosInterno;
var
  dtDetails : TList;
  i : integer;
  ABookmark : TBookmark;
begin
  inherited;

  if Assigned(dsDataTable.DataTable) then
  begin
    ABookmark := dsDataTable.DataTable.GetBookMark;
    dsDataTable.DataTable.DisableControls;
//    dsDataTable.DataTable.DisableEventHandlers;  <- No descomentar

    ShowHourglassCursor;
    { No lo pongo en try..finally para ver posibles errores }
    //try
      dsDataTable.DataTable.Cancel;

      dtDetails := dsDataTable.DataTable.GetDetailDataTables;
      for i := 0 to dtDetails.Count - 1 do
      begin
        (TDADataTable(dtDetails.Items[i])).Cancel;
      end;

      dsDataTable.DataTable.CancelUpdates;

      { Comprobar si el bookmark no es válido cuando estamos cancelando la
        inserción de una fila nueva.
        CUIDADO!! Si no es válido salta una excepción. NO devuelve false!!!}
      try
        if (Assigned(ABookmark)) and
           (dsDataTable.DataTable.Dataset.BookmarkValid(ABookmark)) then
            dsDataTable.DataTable.GotoBookmark(ABookmark);
      except
      end;

    //finally
      dsDataTable.DataTable.EnableControls;
      dsDataTable.DataTable.FreeBookmark(ABookmark);
//      dsDataTable.DataTable.EnableEventHandlers; <- No descomentar
      HideHourglassCursor
    //end;
  end;
end;

procedure TfEditorDBBase.dsDataTableDataChange(Sender: TObject; Field: TField);
begin
  inherited;
  ActualizarEstadoEditor;
end;

procedure TfEditorDBBase.actRefrescarUpdate(Sender: TObject);
begin
  inherited;
  if HayDatos then
    (Sender as TAction).Enabled := (not dsDataTable.DataTable.Fetching) or
      (not dsDataTable.DataTable.Opening) or
      (not dsDataTable.DataTable.Closing)
  else
    (Sender as TAction).Enabled := False;
end;

function TfEditorDBBase.GetModified: Boolean;
var
  dtDetails : TList;
  i : integer;
  bCambiado : Boolean;
begin
  bCambiado := False;
  if Assigned(dsDataTable.DataTable) then
  begin
    bCambiado := (dsDataTable.DataTable.State = dsEdit) or
                DeltaValuesAreDifferent(dsDataTable.DataTable.Delta);

    if (not bCambiado) then
    begin
      dtDetails := dsDataTable.DataTable.GetDetailDataTables;
      for i := 0 to dtDetails.Count - 1 do
      begin
        bCambiado := bCambiado or
                    ((TDADataTable(dtDetails.Items[i])).State in dsEditModes) or
                    DeltaValuesAreDifferent((TDADataTable(dtDetails.Items[i])).Delta);
        if bCambiado then
          Break;
      end;
    end;
  end;

  if (not bCambiado) then
    bCambiado := inherited GetModified;

  Result := bCambiado;
end;

function TfEditorDBBase.HayDatos: Boolean;
begin
  Result := Assigned(dsDataTable.DataTable) and (not dsDataTable.DataTable.IsEmpty);
end;

procedure TfEditorDBBase.RefrescarInterno;
var
  ABookmark : TBookmark;
begin
  inherited;
  if Assigned(dsDataTable.DataTable) then
  begin
    if (dsDataTable.DataTable.IsEmpty) or (not ModifiedQuery) then
      Exit; // No continuar con el refresco

    ABookmark := dsDataTable.DataTable.GetBookMark;
    dsDataTable.DataTable.DisableControls;  //<- No descomentar

    ShowHourglassCursor;
    try
      dsDataTable.DataTable.Refresh;

      if dsDataTable.DataTable.Dataset.BookmarkValid(ABookmark) then
        dsDataTable.DataTable.GotoBookmark(ABookmark);
    finally
      dsDataTable.DataTable.FreeBookmark(ABookmark);
      dsDataTable.DataTable.EnableControls;   //<- No descomentar
      HideHourglassCursor;
    end;
  end;
end;

procedure TfEditorDBBase.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
  { Para resetear el estado de la tabla en el caso de hacer un insert
    sin meter ningún dato. }
  if Assigned(dsDataTable.DataTable) and (not Modified) then
    dsDataTable.DataTable.Cancel;
  inherited;
end;

procedure TfEditorDBBase.actEliminarUpdate(Sender: TObject);
begin
  inherited;
  (Sender as TAction).Enabled := HayDatos;
end;

procedure TfEditorDBBase.actGuardarCerrarUpdate(Sender: TObject);
begin
  inherited;
  (Sender as TAction).Enabled := Self.Modified;
end;

procedure TfEditorDBBase.actGuardarUpdate(Sender: TObject);
begin
  inherited;
  (Sender as TAction).Enabled := Self.Modified;
end;

procedure TfEditorDBBase.actModificarUpdate(Sender: TObject);
begin
  inherited;
  (Sender as TAction).Enabled := HayDatos;
end;

procedure TfEditorDBBase.actPrevisualizarUpdate(Sender: TObject);
begin
  inherited;
  (Sender as TAction).Enabled := HayDatos;
end;

procedure TfEditorDBBase.actImprimirUpdate(Sender: TObject);
begin
  inherited;
  (Sender as TAction).Enabled := HayDatos;
end;

initialization
  RegisterClass(TfEditorDBBase);

finalization
  UnRegisterClass(TfEditorDBBase);

end.
