(************************************************************************
*    This File is Part of the AHM Triton Tools                          *
*    for Borland Delphi and C++ Builder.                                *
*************************************************************************
* Copyright © 1995-1999 Alexander H. Mehlhorn (AHM) and Tritontools.com *
* All Rights reserved.                                                  *
*                                                                       *
*    For more Information contact us at                                 *
*    E-Mail : support@tritontools.com                                   *
*    URL : http://www.tritontools.com                                   *
*                                                                       *
*    AHM is copyright by Alexander H. Mehlhorn                          *
*    All Parts of this Collection were developed,                       *
*    designed and implemented by AHM                                    *
*                                                                       *
*    Under no Circumstances may you distribute this file                *
*    in this or any other format. This File is supplied                 *
*    as Evaluation of Source only. No Delphi Components may be developed*
*    using extracts or subsets of this code without expressed permission*
*    by AHM.                                                            *
*                                                                       *
*************************************************************************)
unit AHMTDBNavigator;
{$I AHM.INC}
interface
uses Windows, SysUtils, Messages, Classes, Controls, Forms,
     Graphics, Menus, StdCtrls, ExtCtrls, Mask, Buttons, ComCtrls, Db,
     AHMTBackground,AHMEnhancedClass,AHMEnhancedConst;
const
  InitRepeatPause = 400;
  RepeatPause     = 100;
  SpaceSize       =  5;
type
  TAHMNavButton = class;
  TAHMNavDataLink = class;
  TAHMNavGlyph = (ngEnabled, ngDisabled);
  TAHMNavigateBtn=(nbFirst,nbPrior,nbNext,nbLast,nbInsert,nbDelete,nbEdit,nbPost,nbCancel,nbRefresh);
  TAHMButtonSet = set of TAHMNavigateBtn;
  TAHMNavButtonStyle = set of (nsAllowTimer, nsFocusRect);
  TAHMNavigationClick = procedure (Sender: TObject; Button: TAHMNavigateBtn) of object;
  TAHMDBNavigator = class (TCustomPanel)
  private
    fchangedir : Boolean;
    FAHMAboutStr : TAHMAboutEnhancedStr;
    fback : TAHMBackground;
    FDataLink: TAHMNavDataLink;
    FVisibleButtons: TAHMButtonSet;
    FHints: TStrings;
    fDir : TAHMKind;
    ButtonWidth: Integer;
    Buttonheight : Integer;
    MinBtnSize: TPoint;
    FOnNavClick: TAHMNavigationClick;
    FBeforeAction: TAHMNavigationClick;
    FocusedButton: TAHMNavigateBtn;
    FConfirmDelete: Boolean;
    FFlat: Boolean;
    procedure ClickHandler(Sender: TObject);
    function GetDataSource: TDataSource;
    procedure SetDataSource(Value: TDataSource);
    procedure SetDir(Value : TAHMKind);
    procedure InitButtons;
    procedure InitHints;
    procedure BtnMouseDown (Sender: TObject; Button: TMouseButton;Shift:TShiftState;X,Y:Integer);
    procedure SetVisible(Value: TAHMButtonSet);
    procedure AdjustHSize (var W: Integer; var H: Integer);
    procedure AdjustVSize (var W: Integer; var H: Integer);
    procedure Setback(value : TAHMBackground);
    procedure HintsChanged(Sender: TObject);
    procedure SetHints(Value: TStrings);
    {$IFDEF AHMINPRISE3}
    procedure SetFlat(Value: Boolean);
    {$ENDIF}
    procedure WMSize(var Message: TWMSize);  message WM_SIZE;
    procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
    procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
    procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
    procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  protected
    Buttons: array[TAHMNavigateBtn] of TAHMNavButton;
    procedure DataChanged;
    procedure EditingChanged;
    procedure ActiveChanged;
    procedure Loaded; override;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure Notification(AComponent: TComponent;
      Operation: TOperation); override;
    procedure GetChildren(Proc: TGetChildProc
     {$IFDEF AHMINPRISE3} ;Root: TComponent {$ENDIF}); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
    procedure BtnClick(Index: TAHMNavigateBtn);
    procedure Paint; override;
  published
    property About : TAHMAboutEnhancedStr read FAHMAboutStr write FAHMAboutStr stored False;
    {$IFDEF AHMONLY4}
    property Anchors;
    property BiDiMode;
    property Constraints;
    property DragKind;
    property ParentBiDiMode;
    {$ENDIF}
    property Direction : TAHMKind read fdir write SetDir default kHorizontal;
    property Background : TAHMBackground read fback write Setback;
    property DataSource: TDataSource read GetDataSource write SetDataSource;
    property VisibleButtons: TAHMButtonSet read FVisibleButtons write SetVisible
      default [nbFirst,nbPrior,nbNext,nbLast,nbInsert,nbDelete,nbEdit,nbPost,nbCancel,nbRefresh];
    property Align;
    property DragCursor;
    property DragMode;
    property Enabled;
    {$IFDEF AHMINPRISE3}
    property Flat: Boolean read FFlat write SetFlat default False;
    {$ENDIF}
    property Ctl3D;
    property Hints: TStrings read FHints write SetHints;
    property ParentCtl3D;
    property ParentShowHint;
    property PopupMenu;
    property ConfirmDelete: Boolean read FConfirmDelete write FConfirmDelete default True;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property Visible;
    property BeforeAction: TAHMNavigationClick read FBeforeAction write FBeforeAction;
    property OnClick: TAHMNavigationClick read FOnNavClick write FOnNavClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnResize;
    property OnStartDrag;
  end;
  TAHMNavButton = class(TSpeedButton)
  private
    FIndex: TAHMNavigateBtn;
    FNavStyle: TAHMNavButtonStyle;
    FRepeatTimer: TTimer;
    procedure TimerExpired(Sender: TObject);
  protected
    procedure Paint; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;X, Y: Integer); override;
  public
    destructor Destroy; override;
    property NavStyle: TAHMNavButtonStyle read FNavStyle write FNavStyle;
    property Index : TAHMNavigateBtn read FIndex write FIndex;
  end;
  TAHMNavDataLink = class(TDataLink)
  private
    FNavigator: TAHMDBNavigator;
  protected
    procedure EditingChanged; override;
    procedure DataSetChanged; override;
    procedure ActiveChanged; override;
  public
    constructor Create(ANav: TAHMDBNavigator);
    destructor Destroy; override;
  end;

implementation
uses Clipbrd, DBConsts, Dialogs;
{$R AHMNavigator.Res}
var
  BtnTypeName: array[TAHMNavigateBtn]
    of String=(ahmscdbnav1,ahmscdbnav2,ahmscdbnav3,ahmscdbnav4,ahmscdbnav5,ahmscdbnav6,ahmscdbnav7,ahmscdbnav8,ahmscdbnav9,ahmscdbnav10);
  BtnHintId: array[TAHMNavigateBtn] of String=(ahmscdbnavhint1,ahmscdbnavhint2,ahmscdbnavhint3,ahmscdbnavhint4,ahmscdbnavhint5,ahmscdbnavhint6,ahmscdbnavhint7,ahmscdbnavhint8,ahmscdbnavhint9,ahmscdbnavhint10);

constructor TAHMDBNavigator.Create(AOwner: TComponent);
begin
  fdir := kHorizontal;
  fchangedir:=false;
  inherited Create(AOwner);
  ControlStyle := ControlStyle - [csAcceptsControls, csSetCaption] + [csOpaque];
  if not NewStyleControls then ControlStyle := ControlStyle + [csFramed];
  FDataLink := TAHMNavDataLink.Create(Self);
  FVisibleButtons:=[nbFirst,nbPrior,nbNext,nbLast,nbInsert,nbDelete,nbEdit,nbPost,nbCancel,nbRefresh];
  FHints := TStringList.Create;
  TStringList(FHints).OnChange := HintsChanged;
  InitButtons;
  BevelOuter := bvNone;
  BevelInner := bvNone;
  Width := 241;
  Height := 25;
  ButtonWidth := 0;
  ButtonHeight := 0;
  FocusedButton := nbFirst;
  FConfirmDelete := True;
  FullRepaint := False;
end;

destructor TAHMDBNavigator.Destroy;
begin
  if fback<>nil then fback.olist.remove(self);
  FDataLink.Free;
  FHints.Free;
  FDataLink := nil;
  inherited Destroy;
end;

procedure TAHMDBNavigator.SetDir(value : TAHMKind);
var Rem : Integer;
    I : TAHMNavigateBtn;
    X:Integer;
begin
  if (fdir<>Value) and not(csLoading in Componentstate) then
  begin
    fchangedir:=true;
    try
      rem:=width;
      Width:=Height;
      Height:=Rem;
    finally
      fchangedir:=false;
    end;
  end;
  fdir:=value;
  if fdir=kHorizontal then MinBtnSize := Point(20, 18) else MinBtnSize := Point(18, 20);
  X:=0;
  for I := Low(Buttons) to High(Buttons) do
  begin
    if fdir=kHorizontal then X:=X+MinBtnSize.X else X:=X+MinBtnSize.Y;
    if fdir=kHorizontal then Buttons[I].SetBounds (X, 0, MinBtnSize.X, MinBtnSize.Y)
                        else Buttons[I].SetBounds (0, X, MinBtnSize.X, MinBtnSize.Y);
  end;
  recreatewnd;
end;

procedure TAHMDBNavigator.InitButtons;
var
  I : TAHMNavigateBtn;
  Btn : TAHMNavButton;
  ResName: string;
begin
  for I := Low(Buttons) to High(Buttons) do
  begin
    Btn := TAHMNavButton.Create (Self);
    {$IFDEF AHMINPRISE3}
    Btn.Flat := Flat;
    {$ENDIF}
    Btn.Index := I;
    Btn.Visible := I in FVisibleButtons;
    Btn.Enabled := True;
    FmtStr(ResName, 'dbmn_%s', [PChar(BtnTypeName[I])]);
    Btn.Glyph.LoadFromResourceName(HInstance, ResName);
    Btn.NumGlyphs := 2;
    Btn.Enabled := False;
    Btn.Enabled := True;
    Btn.OnClick := ClickHandler;
    Btn.OnMouseDown := BtnMouseDown;
    Btn.Parent := Self;
    Buttons[I] := Btn;
  end;
  InitHints;
  Buttons[nbPrior].NavStyle := Buttons[nbPrior].NavStyle + [nsAllowTimer];
  Buttons[nbNext].NavStyle  := Buttons[nbNext].NavStyle + [nsAllowTimer];
end;

procedure TAHMDBNavigator.InitHints;
var I: Integer;
    J: TAHMNavigateBtn;
begin
  for J := Low(Buttons) to High(Buttons) do Buttons[J].Hint := BtnHintId[J];
  J := Low(Buttons);
  for I := 0 to (FHints.Count - 1) do
  begin
    if FHints.Strings[I] <> '' then Buttons[J].Hint := FHints.Strings[I];
    if J = High(Buttons) then Exit;
    Inc(J);
  end;
end;

procedure TAHMDBNavigator.HintsChanged(Sender: TObject);
begin
  InitHints;
end;

{$IFDEF AHMINPRISE3}
procedure TAHMDBNavigator.SetFlat(Value: Boolean);
var
  I: TAHMNavigateBtn;
begin
  if FFlat <> Value then
  begin
    FFlat := Value;
    for I := Low(Buttons) to High(Buttons) do Buttons[I].Flat := Value;
  end;
end;
{$ENDIF}

procedure TAHMDBNavigator.SetHints(Value: TStrings);
begin
  FHints.Assign(Value);
end;

procedure TAHMDBNavigator.GetChildren(Proc: TGetChildProc{$IFDEF AHMINPRISE3}; Root: TComponent{$ENDIF});
begin
end;

procedure TAHMDBNavigator.Notification(AComponent: TComponent;Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation=opRemove) and (AComponent=Background) then Setback(nil);
  if (Operation=opRemove) and (FDataLink<>nil) and (AComponent=DataSource) then DataSource := nil;
end;

procedure TAHMDBNavigator.SetVisible(Value: TAHMButtonSet);
var I : TAHMNavigateBtn;
    W,H : Integer;
begin
  W:=Width; H:=Height;
  FVisibleButtons := Value;
  for I := Low(Buttons) to High(Buttons) do Buttons[I].Visible := I in FVisibleButtons;
  if Direction=kHorizontal then AdjustHSize (W, H) else AdjustVSize(W,H);
  inherited SetBounds (Left, Top, Width, Height);
  Invalidate;
end;

procedure TAHMDBNavigator.SetBack(Value: TAHMBackground);
Begin
  if fback<>nil then fback.OList.remove(self);
  if value<>nil then value.additem(self);
  fback:=(Value);
  Invalidate;
end;

procedure TAHMDBNavigator.Paint;
begin
  if assigned(fback) then fback.draw(Canvas.Handle,width,height,True)
  else inherited paint;
end;


procedure TAHMDBNavigator.AdjustVSize (var W: Integer; var H: Integer);
var Count: Integer;
    MinH: Integer;
    I: TAHMNavigateBtn;
    Space, Temp, Remain: Integer;
    Y: Integer;
begin
  if (csLoading in ComponentState) then Exit;
  if Buttons[nbFirst] = nil then Exit;
  Count := 0;
  for I := Low(Buttons) to High(Buttons) do if Buttons[I].Visible then Inc(Count);
  if Count = 0 then Inc(Count);
  MinH := Count * MinBtnSize.Y;
  if H < MinH then H := MinH;
  if W < MinBtnSize.X then W := MinBtnSize.X;
  ButtonHeight := H div Count;
  Temp := Count * ButtonHeight;
  if Align = alNone then H := Temp;
  Y := 0;
  Remain := H - Temp;
  Temp := Count div 2;
  for I := Low(Buttons) to High(Buttons) do
  begin
    if Buttons[I].Visible then
    begin
      Space := 0;
      if Remain <> 0 then
      begin
        Dec(Temp, Remain);
        if Temp < 0 then
        begin
          Inc(Temp, Count);
          Space := 1;
        end;
      end;
      Buttons[I].SetBounds(0, Y, Width, ButtonHeight+Space);
      Inc(Y, ButtonHeight + Space);
    end else Buttons[I].SetBounds (0, Height+1,Width, ButtonHeight);
  end;
end;


procedure TAHMDBNavigator.AdjustHSize (var W: Integer; var H: Integer);
var
  Count: Integer;
  MinW: Integer;
  I: TAHMNavigateBtn;
  Space, Temp, Remain: Integer;
  X: Integer;
begin
  if (csLoading in ComponentState) then Exit;
  if Buttons[nbFirst] = nil then Exit;
  Count := 0;
  for I := Low(Buttons) to High(Buttons) do if Buttons[I].Visible then Inc(Count);
  if Count = 0 then Inc(Count);
  MinW := Count * MinBtnSize.X;
  if W < MinW then W := MinW;
  if H < MinBtnSize.Y then H := MinBtnSize.Y;
  ButtonWidth := W div Count;
  Temp := Count * ButtonWidth;
  if Align = alNone then W := Temp;
  X := 0;
  Remain := W - Temp;
  Temp := Count div 2;
  for I := Low(Buttons) to High(Buttons) do
  begin
    if Buttons[I].Visible then
    begin
      Space := 0;
      if Remain <> 0 then
      begin
        Dec(Temp, Remain);
        if Temp < 0 then
        begin
          Inc(Temp, Count);
          Space := 1;
        end;
      end;
      Buttons[I].SetBounds(X, 0, ButtonWidth + Space, Height);
      Inc(X, ButtonWidth + Space);
    end else Buttons[I].SetBounds (Width + 1, 0, ButtonWidth, Height);
  end;
end;

procedure TAHMDBNavigator.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
var W, H: Integer;
begin
  W := AWidth; H := AHeight;
  if not(HandleAllocated) and not(csReading in ComponentState) then
  begin
   if fdir=kHorizontal then AdjustHSize (W, H) else AdjustVSize(W,H);
  end;
  inherited SetBounds (ALeft, ATop, W, H);
end;

procedure TAHMDBNavigator.WMSize(var Message: TWMSize);
var W, H: Integer;
begin
  inherited;
  W := Width;
  H := Height;
  if fdir=kHorizontal then AdjustHSize (W, H) else AdjustVSize(W,H);
  if not(fchangedir) then inherited SetBounds(Left, Top, W, H);
  Message.Result := 0;
end;

procedure TAHMDBNavigator.ClickHandler(Sender: TObject);
begin
  BtnClick(TAHMNavButton(Sender).Index);
end;

procedure TAHMDBNavigator.BtnMouseDown(Sender: TObject; Button: TMouseButton;
                                       Shift: TShiftState; X, Y: Integer);
var OldFocus: TAHMNavigateBtn;
begin
  OldFocus := FocusedButton;
  FocusedButton := TAHMNavButton(Sender).Index;
  if TabStop and (GetFocus <> Handle) and CanFocus then
  begin
    SetFocus;
    if (GetFocus <> Handle) then Exit;
  end else if TabStop and (GetFocus = Handle) and (OldFocus <> FocusedButton) then
  begin
    Buttons[OldFocus].Invalidate;
    Buttons[FocusedButton].Invalidate;
  end;
end;

procedure TAHMDBNavigator.BtnClick(Index: TAHMNavigateBtn);
begin
  if (DataSource<>nil) and (DataSource.State<>dsInactive) then
  begin
    if not(csDesigning in ComponentState) and Assigned(FBeforeAction) then FBeforeAction(Self,Index);
    with DataSource.DataSet do
    begin
      case Index of
        nbPrior: Prior;
        nbNext: Next;
        nbFirst: First;
        nbLast: Last;
        nbInsert: Insert;
        nbEdit: Edit;
        nbCancel: Cancel;
        nbPost: Post;
        nbRefresh: Refresh;
        nbDelete:
        if not FConfirmDelete or
          (MessageDlg({$IFDEF AHMINPRISE3}SDeleteRecordQuestion{$ELSE}
                     LoadStr(SDeleteRecordQuestion){$ENDIF}, mtConfirmation,mbOKCancel, 0) <> idCancel) then Delete;
      end;
    end;
  end;
  if not(csDesigning in ComponentState) and Assigned(FOnNavClick) then FOnNavClick(Self, Index);
end;

procedure TAHMDBNavigator.WMSetFocus(var Message: TWMSetFocus);
begin
  Buttons[FocusedButton].Invalidate;
end;

procedure TAHMDBNavigator.WMKillFocus(var Message: TWMKillFocus);
begin
  Buttons[FocusedButton].Invalidate;
end;

procedure TAHMDBNavigator.KeyDown(var Key: Word; Shift: TShiftState);
var NewFocus: TAHMNavigateBtn;
    OldFocus: TAHMNavigateBtn;
begin
  OldFocus := FocusedButton;
  case Key of
    VK_RIGHT:
    begin
      NewFocus := FocusedButton;
      repeat
        if NewFocus < High(Buttons) then NewFocus := Succ(NewFocus);
      until (NewFocus = High(Buttons)) or (Buttons[NewFocus].Visible);
      if NewFocus <> FocusedButton then
      begin
        FocusedButton := NewFocus;
        Buttons[OldFocus].Invalidate;
        Buttons[FocusedButton].Invalidate;
      end;
    end;
    VK_LEFT:
    begin
      NewFocus := FocusedButton;
      repeat
        if NewFocus > Low(Buttons) then NewFocus := Pred(NewFocus);
      until (NewFocus = Low(Buttons)) or (Buttons[NewFocus].Visible);
      if NewFocus <> FocusedButton then
      begin
        FocusedButton := NewFocus;
        Buttons[OldFocus].Invalidate;
        Buttons[FocusedButton].Invalidate;
      end;
    end;
    VK_SPACE:
    begin
      if Buttons[FocusedButton].Enabled then Buttons[FocusedButton].Click;
    end;
  end;
end;

procedure TAHMDBNavigator.WMGetDlgCode(var Message: TWMGetDlgCode);
begin
  Message.Result := DLGC_WANTARROWS;
end;

procedure TAHMDBNavigator.DataChanged;
var UpEnable, DnEnable: Boolean;
begin
  UpEnable := Enabled and FDataLink.Active and not FDataLink.DataSet.BOF;
  DnEnable := Enabled and FDataLink.Active and not FDataLink.DataSet.EOF;
  Buttons[nbFirst].Enabled := UpEnable;
  Buttons[nbPrior].Enabled := UpEnable;
  Buttons[nbNext].Enabled := DnEnable;
  Buttons[nbLast].Enabled := DnEnable;
  Buttons[nbDelete].Enabled := Enabled and FDataLink.Active and FDataLink.DataSet.CanModify and
    not (FDataLink.DataSet.BOF and FDataLink.DataSet.EOF);
end;

procedure TAHMDBNavigator.EditingChanged;
var CanModify: Boolean;
begin
  CanModify := Enabled and FDataLink.Active and FDataLink.DataSet.CanModify;
  Buttons[nbInsert].Enabled := CanModify;
  Buttons[nbEdit].Enabled := CanModify and not FDataLink.Editing;
  Buttons[nbPost].Enabled := CanModify and FDataLink.Editing;
  Buttons[nbCancel].Enabled := CanModify and FDataLink.Editing;
  Buttons[nbRefresh].Enabled := CanModify;
end;

procedure TAHMDBNavigator.ActiveChanged;
var I: TAHMNavigateBtn;
begin
  if not (Enabled and FDataLink.Active) then for I := Low(Buttons) to High(Buttons) do
     Buttons[I].Enabled := False else
  begin
    DataChanged;
    EditingChanged;
  end;
end;

procedure TAHMDBNavigator.CMEnabledChanged(var Message: TMessage);
begin
  inherited;
  if not (csLoading in ComponentState) then ActiveChanged;
end;

procedure TAHMDBNavigator.SetDataSource(Value: TDataSource);
begin
  FDataLink.DataSource := Value;
  if not (csLoading in ComponentState) then ActiveChanged;
  if Value <> nil then Value.FreeNotification(Self);
end;

function TAHMDBNavigator.GetDataSource: TDataSource;
begin
  Result := FDataLink.DataSource;
end;

procedure TAHMDBNavigator.Loaded;
var W, H: Integer;
begin
  inherited Loaded;
  W := Width;
  H := Height;
  if Direction=kHorizontal then AdjustHSize (W, H) else AdjustVSize(W,H);
  inherited Setbounds(Left,Top,Width,Height);
  InitHints;
  ActiveChanged;
end;

destructor TAHMNavButton.Destroy;
begin
  if FRepeatTimer <> nil then FRepeatTimer.Free;
  inherited Destroy;
end;

procedure TAHMNavButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
begin
  inherited MouseDown (Button, Shift, X, Y);
  if nsAllowTimer in FNavStyle then
  begin
    if FRepeatTimer = nil then FRepeatTimer := TTimer.Create(Self);
    FRepeatTimer.OnTimer := TimerExpired;
    FRepeatTimer.Interval := InitRepeatPause;
    FRepeatTimer.Enabled  := True;
  end;
end;

procedure TAHMNavButton.MouseUp(Button: TMouseButton; Shift: TShiftState;X, Y: Integer);
begin
  inherited MouseUp (Button, Shift, X, Y);
  if FRepeatTimer <> nil then FRepeatTimer.Enabled  := False;
end;

procedure TAHMNavButton.TimerExpired(Sender: TObject);
begin
  FRepeatTimer.Interval := RepeatPause;
  if (FState = bsDown) and MouseCapture then
  try
    Click;
  except
    FRepeatTimer.Enabled := False;
    raise;
  end;
end;

procedure TAHMNavButton.Paint;
var R: TRect;
begin
  inherited Paint;
  if (GetFocus = Parent.Handle) and (FIndex=TAHMDBNavigator(Parent).FocusedButton) then
  begin
    R := Bounds(0, 0, Width, Height);
    InflateRect(R, -3, -3);
    if FState = bsDown then OffsetRect(R, 1, 1);
    DrawFocusRect(Canvas.Handle, R);
  end;
end;

constructor TAHMNavDataLink.Create(ANav: TAHMDBNavigator);
begin
  inherited Create;
  FNavigator := ANav;
end;

destructor TAHMNavDataLink.Destroy;
begin
  FNavigator := nil;
  inherited Destroy;
end;

procedure TAHMNavDataLink.EditingChanged;
begin
  if FNavigator <> nil then FNavigator.EditingChanged;
end;

procedure TAHMNavDataLink.DataSetChanged;
begin
  if FNavigator <> nil then FNavigator.DataChanged;
end;

procedure TAHMNavDataLink.ActiveChanged;
begin
  if FNavigator <> nil then FNavigator.ActiveChanged;
end;

end.
