home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 December / Chip_2001-12_cd1.bin / zkuste / delphi / kolekce / d3456 / ALEXSOFT.ZIP / DBxNav.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2001-09-29  |  27.4 KB  |  883 lines

  1. (*////////////////////////////////////////////////////////////////////////////
  2. //   Part of AlexSoft VCL/DLL Library.                                      //
  3. //   All rights reserved. (c) Copyright 1998.                               //
  4. //   Created by: Alex Rabichooc                                             //
  5. //**************************************************************************//
  6. //  Users of this unit must accept this disclaimer of warranty:             //
  7. //    "This unit is supplied as is. The author disclaims all warranties,    //
  8. //    expressed or implied, including, without limitation, the warranties   //
  9. //    of merchantability and of fitness for any purpose.                    //
  10. //    The author assumes no liability for damages, direct or                //
  11. //    consequential, which may result from the use of this unit."           //
  12. //                                                                          //
  13. //  This Unit is donated to the public as public domain.                    //
  14. //                                                                          //
  15. //  This Unit can be freely used and distributed in commercial and          //
  16. //  private environments provided this notice is not modified in any way.   //
  17. //                                                                          //
  18. //  If you do find this Unit handy and you feel guilty for using such a     //
  19. //  great product without paying someone - sorry :-)                        //
  20. //                                                                          //
  21. //  Please forward any comments or suggestions to Alex Rabichooc at:        //
  22. //                                                                          //
  23. //  a_rabichooc@yahoo.com or alex@carmez.mldnet.com                         //
  24. /////////////////////////////////////////////////////////////////////////////*)
  25.  
  26. {---------------------------------------------------------------------------
  27.   TRaDBNavigator - Extended TDBNavigator component
  28.      properties
  29.        DataSourceAuto: boolean;
  30.          Determines whether Component will changes DataSource property to
  31.          the Active data-aware Control DataSource property
  32.        DefaultAction: boolean;
  33.          If you set the OnClick property, DefaultAction determines,
  34.          whether Components will execute an action by default for this event.
  35.          You also can call an action by default manually: DoDefaultClick.
  36.        SearchComponent: TRaDBSearch;
  37.          If you set SearchComponent then for pressing to a search button
  38.          Execute method of the SearchComponent will be called.
  39. ----------------------------------------------------------------------------}
  40. unit DBxNav;
  41.  
  42. interface
  43.  
  44. uses
  45.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  46.   ExtCtrls, dbCtrls, db, Buttons, DbSearch;
  47.  
  48. type
  49.   TxNavButton = class;
  50.   TxNavDataLink = class;
  51.  
  52.   TxNavGlyph = (ngEnabled, ngDisabled);
  53.   TxNavigateBtn = (nbFirst, nbPrior, nbNext, nbLast,
  54.                   nbInsert, nbDelete, nbEdit, nbPost,
  55.                   nbCancel, nbRefresh, nbSearch);
  56.   TButtonSet = set of TxNavigateBtn;
  57.   TxNavButtonStyle = set of (nsAllowTimer, nsFocusRect);
  58.  
  59.   ENavClick = procedure (Sender: TObject; Button: TxNavigateBtn) of object;
  60.  
  61.   TRaDBNavigator = class (TCustomPanel)
  62.   private
  63.     FSearchComponent: TRaDBSearch;
  64.     FDataSource: TDataSource;
  65.     FDataSourceAuto: Boolean;
  66.     FDataLink: TxNavDataLink;
  67.     FVisibleButtons: TButtonSet;
  68.     FHints: TStrings;
  69.     ButtonWidth: Integer;
  70.     MinBtnSize: TPoint;
  71.     FOnNavClick: ENavClick;
  72.     FBeforeAction: ENavClick;
  73.     FocusedButton: TxNavigateBtn;
  74.     FConfirmDelete: Boolean;
  75.     FFlat: Boolean;
  76.     FDefaultAction: Boolean;
  77.     procedure ClickHandler(Sender: TObject);
  78.     function CurrentField: TField;
  79.     function GetDataSource: TDataSource;
  80.     procedure SetDataSource(Value: TDataSource);
  81.     procedure InitButtons;
  82.     procedure InitHints;
  83.     procedure BtnMouseDown (Sender: TObject; Button: TMouseButton;
  84.       Shift: TShiftState; X, Y: Integer);
  85.     procedure SetVisible(Value: TButtonSet);
  86.     procedure AdjustSize (var W: Integer; var H: Integer);
  87.     procedure HintsChanged(Sender: TObject);
  88.     procedure SetHints(Value: TStrings);
  89.     procedure SetFlat(Value: Boolean);
  90.     procedure WMSize(var Message: TWMSize);  message WM_SIZE;
  91.     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  92.     procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  93.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  94.     procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  95.     procedure CMFocusChanged(var Message: TCMFocusChanged); message CM_FOCUSCHANGED;
  96.     procedure SetDataSourceAuto(Value: Boolean);
  97.     procedure ChangeDataSource;
  98.   protected
  99.     Buttons: array[TxNavigateBtn] of TxNavButton;
  100.     procedure DataChanged;
  101.     procedure EditingChanged;
  102.     procedure ActiveChanged;
  103.     procedure Loaded; override;
  104.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  105.     procedure Notification(AComponent: TComponent;
  106.       Operation: TOperation); override;
  107.     procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  108.   public
  109.     constructor Create(AOwner: TComponent); override;
  110.     destructor Destroy; override;
  111.     procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  112.     procedure DoDefaultClick(Index: TxNavigateBtn);
  113.     procedure BtnClick(Index: TxNavigateBtn);
  114.   published
  115.     property DataSource: TDataSource read GetDataSource write SetDataSource;
  116.     property DataSourceAuto: boolean read FDataSourceAuto write SetDataSourceAuto;
  117.     property DefaultAction: boolean read FDefaultAction write FDefaultAction
  118.                                                            default True;
  119.     property VisibleButtons: TButtonSet read FVisibleButtons write SetVisible
  120.       default [nbFirst, nbPrior, nbNext, nbLast, nbInsert, nbDelete,
  121.         nbEdit, nbPost, nbCancel, nbRefresh, nbSearch];
  122.     property SearchComponent: TRaDBSearch read FSearchComponent
  123.                                           write FSearchComponent;
  124.     property Align;
  125.     property DragCursor;
  126.     property DragMode;
  127.     property Enabled;
  128.     property Flat: Boolean read FFlat write SetFlat default False;
  129.     property Ctl3D;
  130.     property Hints: TStrings read FHints write SetHints;
  131.     property ParentCtl3D;
  132.     property ParentShowHint;
  133.     property PopupMenu;
  134.     property ConfirmDelete: Boolean read FConfirmDelete write FConfirmDelete default True;
  135.     property ShowHint;
  136.     property TabOrder;
  137.     property TabStop;
  138.     property Visible;
  139.     property BeforeAction: ENavClick read FBeforeAction write FBeforeAction;
  140.     property OnClick: ENavClick read FOnNavClick write FOnNavClick;
  141.     property OnDblClick;
  142.     property OnDragDrop;
  143.     property OnDragOver;
  144.     property OnEndDrag;
  145.     property OnEnter;
  146.     property OnExit;
  147.     property OnResize;
  148.     property OnStartDrag;
  149.   end;
  150.  
  151.   TxNavButton = class(TSpeedButton)
  152.   private
  153.     FIndex: TxNavigateBtn;
  154.     FNavStyle: TxNavButtonStyle;
  155.     FRepeatTimer: TTimer;
  156.     procedure TimerExpired(Sender: TObject);
  157.   protected
  158.     procedure Paint; override;
  159.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  160.       X, Y: Integer); override;
  161.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  162.       X, Y: Integer); override;
  163.   public
  164.     destructor Destroy; override;
  165.     property NavStyle: TxNavButtonStyle read FNavStyle write FNavStyle;
  166.     property Index : TxNavigateBtn read FIndex write FIndex;
  167.   end;
  168.  
  169.   TxNavDataLink = class(TDataLink)
  170.   private
  171.     FNavigator: TRaDBNavigator;
  172.   protected
  173.     procedure EditingChanged; override;
  174.     procedure DataSetChanged; override;
  175.     procedure ActiveChanged; override;
  176.   public
  177.     constructor Create(ANav: TRaDBNavigator);
  178.     destructor Destroy; override;
  179.   end;
  180.  
  181. implementation
  182.  
  183. {$R DBXNAV}
  184.  
  185. uses dbConsts, dbXCnsts, dbGrids, dbCgrids, dbEdFld, dbXgrid, dbTools, dbBoxGrd,
  186.      dbClient
  187.      {$IFDEF VER140},VDBConsts
  188.      {$ENDIF};
  189.  
  190. {TRaDBNavigator}
  191. var
  192.   BtnTypeName: array[TxNavigateBtn] of PChar = ('FIRST', 'PRIOR', 'NEXT',
  193.     'LAST', 'INSERT', 'DELETE', 'EDIT', 'POST', 'CANCEL', 'REFRESH', 'SEARCH');
  194.   BtnHintId: array[TxNavigateBtn] of String = (SFirstRecord, SPriorRecord,
  195.     SNextRecord, SLastRecord, SInsertRecord, SDeleteRecord, SEditRecord,
  196.     SPostEdit, SCancelEdit, SRefreshRecord, SSearchRecord);
  197.  
  198. constructor TRaDBNavigator.Create(AOwner: TComponent);
  199. begin
  200.   inherited Create(AOwner);
  201.   ControlStyle := ControlStyle - [csAcceptsControls, csSetCaption] + [csOpaque];
  202.   if not NewStyleControls then ControlStyle := ControlStyle + [csFramed];
  203.   FDataLink := TxNavDataLink.Create(Self);
  204.   FVisibleButtons := [nbFirst, nbPrior, nbNext, nbLast, nbInsert,
  205.     nbDelete, nbEdit, nbPost, nbCancel, nbRefresh, nbSearch];
  206.   FHints := TStringList.Create;
  207.   TStringList(FHints).OnChange := HintsChanged;
  208.   InitButtons;
  209.   BevelOuter := bvNone;
  210.   BevelInner := bvNone;
  211.   Width := 241;
  212.   Height := 25;
  213.   ButtonWidth := 0;
  214.   FocusedButton := nbFirst;
  215.   FConfirmDelete := True;
  216.   FullRepaint := False;
  217.   FDefaultAction := True;
  218. end;
  219.  
  220. destructor TRaDBNavigator.Destroy;
  221. begin
  222.   FDataLink.Free;
  223.   FHints.Free;
  224.   FDataLink := nil;
  225.   inherited Destroy;
  226. end;
  227.  
  228. procedure TRaDBNavigator.InitButtons;
  229. var
  230.   I: TxNavigateBtn;
  231.   Btn: TxNavButton;
  232.   X: Integer;
  233.   ResName: string;
  234. begin
  235.   MinBtnSize := Point(20, 18);
  236.   X := 0;
  237.   for I := Low(Buttons) to High(Buttons) do
  238.   begin
  239.     Btn := TxNavButton.Create (Self);
  240.     Btn.Flat := Flat;
  241.     Btn.Index := I;
  242.     Btn.Visible := I in FVisibleButtons;
  243.     Btn.Enabled := True;
  244.     Btn.SetBounds (X, 0, MinBtnSize.X, MinBtnSize.Y);
  245.     FmtStr(ResName, 'dbxn_%s', [BtnTypeName[I]]);
  246.     Btn.Glyph.LoadFromResourceName(HInstance, ResName);
  247.     Btn.NumGlyphs := 2;
  248.     Btn.Enabled := False;
  249.     Btn.Enabled := True;
  250.     Btn.OnClick := ClickHandler;
  251.     Btn.OnMouseDown := BtnMouseDown;
  252.     Btn.Parent := Self;
  253.     Buttons[I] := Btn;
  254.     X := X + MinBtnSize.X;
  255.   end;
  256.   InitHints;
  257.   Buttons[nbPrior].NavStyle := Buttons[nbPrior].NavStyle + [nsAllowTimer];
  258.   Buttons[nbNext].NavStyle  := Buttons[nbNext].NavStyle + [nsAllowTimer];
  259. end;
  260.  
  261. procedure TRaDBNavigator.InitHints;
  262. var
  263.   I: Integer;
  264.   J: TxNavigateBtn;
  265. begin
  266.   for J := Low(Buttons) to High(Buttons) do
  267.     Buttons[J].Hint := BtnHintId[J];
  268.   J := Low(Buttons);
  269.   for I := 0 to (FHints.Count - 1) do
  270.   begin
  271.     if FHints.Strings[I] <> '' then Buttons[J].Hint := FHints.Strings[I];
  272.     if J = High(Buttons) then Exit;
  273.     Inc(J);
  274.   end;
  275. end;
  276.  
  277. procedure TRaDBNavigator.HintsChanged(Sender: TObject);
  278. begin
  279.   InitHints;
  280. end;
  281.  
  282. procedure TRaDBNavigator.SetFlat(Value: Boolean);
  283. var
  284.   I: TxNavigateBtn;
  285. begin
  286.   if FFlat <> Value then
  287.   begin
  288.     FFlat := Value;
  289.     for I := Low(Buttons) to High(Buttons) do
  290.       Buttons[I].Flat := Value;
  291.   end;
  292. end;
  293.  
  294. procedure TRaDBNavigator.SetHints(Value: TStrings);
  295. begin
  296.   FHints.Assign(Value);
  297. end;
  298.  
  299. procedure TRaDBNavigator.GetChildren(Proc: TGetChildProc; Root: TComponent);
  300. begin
  301. end;
  302.  
  303. procedure TRaDBNavigator.Notification(AComponent: TComponent;
  304.   Operation: TOperation);
  305. begin
  306.   inherited Notification(AComponent, Operation);
  307.   if (Operation = opRemove) and (FDataLink <> nil) and
  308.     (AComponent = DataSource) then DataSource := nil;
  309.   if (Operation = opRemove) and (FDataSource <> nil) and
  310.     (AComponent = FDataSource) then FDataSource := nil;
  311.   if (Operation = opRemove) and (FSearchComponent <> nil) and
  312.      (AComponent = FSearchComponent) then FSearchComponent := nil;
  313. end;
  314.  
  315. procedure TRaDBNavigator.SetVisible(Value: TButtonSet);
  316. var
  317.   I: TxNavigateBtn;
  318.   W, H: Integer;
  319. begin
  320.   W := Width;
  321.   H := Height;
  322.   FVisibleButtons := Value;
  323.   for I := Low(Buttons) to High(Buttons) do
  324.     Buttons[I].Visible := I in FVisibleButtons;
  325.   AdjustSize (W, H);
  326.   if (W <> Width) or (H <> Height) then
  327.     inherited SetBounds (Left, Top, W, H);
  328.   Invalidate;
  329. end;
  330.  
  331. procedure TRaDBNavigator.AdjustSize (var W: Integer; var H: Integer);
  332. var
  333.   Count: Integer;
  334.   MinW: Integer;
  335.   I: TxNavigateBtn;
  336.   Space, Temp, Remain: Integer;
  337.   X: Integer;
  338. begin
  339.   if (csLoading in ComponentState) then Exit;
  340.   if Buttons[nbFirst] = nil then Exit;
  341.  
  342.   Count := 0;
  343.   for I := Low(Buttons) to High(Buttons) do
  344.   begin
  345.     if Buttons[I].Visible then
  346.     begin
  347.       Inc(Count);
  348.     end;
  349.   end;
  350.   if Count = 0 then Inc(Count);
  351.  
  352.   MinW := Count * MinBtnSize.X;
  353.   if W < MinW then W := MinW;
  354.   if H < MinBtnSize.Y then H := MinBtnSize.Y;
  355.  
  356.   ButtonWidth := W div Count;
  357.   Temp := Count * ButtonWidth;
  358.   if Align = alNone then W := Temp;
  359.  
  360.   X := 0;
  361.   Remain := W - Temp;
  362.   Temp := Count div 2;
  363.   for I := Low(Buttons) to High(Buttons) do
  364.   begin
  365.     if Buttons[I].Visible then
  366.     begin
  367.       Space := 0;
  368.       if Remain <> 0 then
  369.       begin
  370.         Dec(Temp, Remain);
  371.         if Temp < 0 then
  372.         begin
  373.           Inc(Temp, Count);
  374.           Space := 1;
  375.         end;
  376.       end;
  377.       Buttons[I].SetBounds(X, 0, ButtonWidth + Space, Height);
  378.       Inc(X, ButtonWidth + Space);
  379.     end
  380.     else
  381.       Buttons[I].SetBounds (Width + 1, 0, ButtonWidth, Height);
  382.   end;
  383. end;
  384.  
  385. procedure TRaDBNavigator.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  386. var
  387.   W, H: Integer;
  388. begin
  389.   W := AWidth;
  390.   H := AHeight;
  391.   if not HandleAllocated then AdjustSize (W, H);
  392.   inherited SetBounds (ALeft, ATop, W, H);
  393. end;
  394.  
  395. procedure TRaDBNavigator.WMSize(var Message: TWMSize);
  396. var
  397.   W, H: Integer;
  398. begin
  399.   inherited;
  400.   { check for minimum size }
  401.   W := Width;
  402.   H := Height;
  403.   AdjustSize (W, H);
  404.   if (W <> Width) or (H <> Height) then
  405.     inherited SetBounds(Left, Top, W, H);
  406.   Message.Result := 0;
  407. end;
  408.  
  409. procedure TRaDBNavigator.ClickHandler(Sender: TObject);
  410. begin
  411.   BtnClick (TxNavButton (Sender).Index);
  412. end;
  413.  
  414. procedure TRaDBNavigator.BtnMouseDown(Sender: TObject; Button: TMouseButton;
  415.   Shift: TShiftState; X, Y: Integer);
  416. var
  417.   OldFocus: TxNavigateBtn;
  418. begin
  419.   OldFocus := FocusedButton;
  420.   FocusedButton := TxNavButton (Sender).Index;
  421.   if TabStop and (GetFocus <> Handle) and CanFocus then
  422.   begin
  423.     SetFocus;
  424.     if (GetFocus <> Handle) then
  425.       Exit;
  426.   end
  427.   else if TabStop and (GetFocus = Handle) and (OldFocus <> FocusedButton) then
  428.   begin
  429.     Buttons[OldFocus].Invalidate;
  430.     Buttons[FocusedButton].Invalidate;
  431.   end;
  432. end;
  433.  
  434. procedure TRaDBNavigator.BtnClick(Index: TxNavigateBtn);
  435. begin
  436.   if (DataSource <> nil) and (DataSource.State <> dsInactive) then
  437.   begin
  438.     if not (csDesigning in ComponentState) and Assigned(FOnNavClick) then
  439.     begin
  440.        if FDefaultAction then
  441.          DoDefaultClick(Index);
  442.        FOnNavClick(Self, Index);
  443.     end
  444.       else
  445.        DoDefaultClick(Index);
  446.   end;
  447. end;
  448.  
  449. procedure TRaDBNavigator.DoDefaultClick(Index: TxNavigateBtn);
  450. var ABookMark: TBookmark;
  451. begin
  452.   if (DataSource <> nil) and (DataSource.State <> dsInactive) then
  453.   begin
  454.     if not (csDesigning in ComponentState) and Assigned(FBeforeAction) then
  455.       FBeforeAction(Self, Index);
  456.     with DataSource.DataSet do
  457.     begin
  458.       case Index of
  459.         nbPrior: Prior;
  460.         nbNext: Next;
  461.         nbFirst: First;
  462.         nbLast: Last;
  463.         nbInsert: Insert;
  464.         nbEdit: Edit;
  465.         nbCancel: Cancel;
  466.         nbPost: Post;
  467.         nbRefresh: begin
  468.                       if (not (FDataLink.DataSet is TClientDataSet) or
  469.                                 ((FDataLink.DataSet as TClientDataSet).RemoteServer <> nil)) then
  470.                           Refresh
  471.                         else
  472.                         begin
  473.                           DisableControls;
  474.                           try
  475.                             ABookmark := GetBookMark;
  476.                             try
  477.                               Close;
  478.                               Open;
  479.                               if (ABookmark <> nil) and BookmarkValid(ABookmark) then
  480.                                  GotoBookmark(ABookmark);
  481.                             finally
  482.                               if ABookmark <> nil then
  483.                                 FreeBookmark(ABookmark);
  484.                             end;
  485.                           finally
  486.                             EnableControls;
  487.                           end;
  488.                         end;
  489.                    end;
  490.         nbDelete:
  491.           if not FConfirmDelete or
  492.             (MessageDlg(SDeleteRecordQuestion, mtConfirmation,
  493.             mbOKCancel, 0) <> idCancel) then Delete;
  494.         nbSearch: begin
  495.                      if FDataLink.DataSet.Modified then
  496.                         FDataLink.DataSet.CheckBrowseMode;
  497.                      if FSearchComponent <> nil then
  498.                         FSearchComponent.Execute(CurrentField)
  499.                        else
  500.                         DBTools.DBSearch(FDataLink.DataSet, nil,
  501.                                          CurrentField, Owner);
  502.                   end;
  503.       end;
  504.     end;
  505.   end;
  506. end;
  507.  
  508. procedure TRaDBNavigator.WMSetFocus(var Message: TWMSetFocus);
  509. begin
  510.   Buttons[FocusedButton].Invalidate;
  511. end;
  512.  
  513. procedure TRaDBNavigator.WMKillFocus(var Message: TWMKillFocus);
  514. begin
  515.   Buttons[FocusedButton].Invalidate;
  516. end;
  517.  
  518. procedure TRaDBNavigator.KeyDown(var Key: Word; Shift: TShiftState);
  519. var
  520.   NewFocus: TxNavigateBtn;
  521.   OldFocus: TxNavigateBtn;
  522. begin
  523.   OldFocus := FocusedButton;
  524.   case Key of
  525.     VK_RIGHT:
  526.       begin
  527.         NewFocus := FocusedButton;
  528.         repeat
  529.           if NewFocus < High(Buttons) then
  530.             NewFocus := Succ(NewFocus);
  531.         until (NewFocus = High(Buttons)) or (Buttons[NewFocus].Visible);
  532.         if NewFocus <> FocusedButton then
  533.         begin
  534.           FocusedButton := NewFocus;
  535.           Buttons[OldFocus].Invalidate;
  536.           Buttons[FocusedButton].Invalidate;
  537.         end;
  538.       end;
  539.     VK_LEFT:
  540.       begin
  541.         NewFocus := FocusedButton;
  542.         repeat
  543.           if NewFocus > Low(Buttons) then
  544.             NewFocus := Pred(NewFocus);
  545.         until (NewFocus = Low(Buttons)) or (Buttons[NewFocus].Visible);
  546.         if NewFocus <> FocusedButton then
  547.         begin
  548.           FocusedButton := NewFocus;
  549.           Buttons[OldFocus].Invalidate;
  550.           Buttons[FocusedButton].Invalidate;
  551.         end;
  552.       end;
  553.     VK_SPACE:
  554.       begin
  555.         if Buttons[FocusedButton].Enabled then
  556.           Buttons[FocusedButton].Click;
  557.       end;
  558.   end;
  559. end;
  560.  
  561. procedure TRaDBNavigator.WMGetDlgCode(var Message: TWMGetDlgCode);
  562. begin
  563.   Message.Result := DLGC_WANTARROWS;
  564. end;
  565.  
  566. procedure TRaDBNavigator.DataChanged;
  567. var
  568.   UpEnable, DnEnable: Boolean;
  569. begin
  570.   UpEnable := Enabled and FDataLink.Active and not FDataLink.DataSet.BOF;
  571.   DnEnable := Enabled and FDataLink.Active and not FDataLink.DataSet.EOF;
  572.   Buttons[nbFirst].Enabled := UpEnable;
  573.   Buttons[nbPrior].Enabled := UpEnable;
  574.   Buttons[nbNext].Enabled := DnEnable;
  575.   Buttons[nbLast].Enabled := DnEnable;
  576.   Buttons[nbDelete].Enabled := Enabled and FDataLink.Active and
  577.     FDataLink.DataSet.CanModify and
  578.     not (FDataLink.DataSet.BOF and FDataLink.DataSet.EOF);
  579.   Buttons[nbSearch].Enabled := Enabled and FDataLink.Active and
  580.                                not FDataLink.DataSet.IsEmpty;
  581. end;
  582.  
  583. procedure TRaDBNavigator.EditingChanged;
  584. var
  585.   CanModify: Boolean;
  586. begin
  587.   CanModify := Enabled and FDataLink.Active and FDataLink.DataSet.CanModify;
  588.   Buttons[nbInsert].Enabled := CanModify;
  589.   Buttons[nbEdit].Enabled := CanModify and not FDataLink.Editing;
  590.   Buttons[nbPost].Enabled := CanModify and FDataLink.Editing;
  591.   Buttons[nbCancel].Enabled := CanModify and FDataLink.Editing;
  592.   Buttons[nbRefresh].Enabled := Enabled and FDataLink.Active;
  593.   Buttons[nbSearch].Enabled := Enabled and FDataLink.Active and
  594.                                not FDataLink.DataSet.IsEmpty;
  595. end;
  596.  
  597. procedure TRaDBNavigator.ActiveChanged;
  598. var
  599.   I: TxNavigateBtn;
  600. begin
  601.   if not (Enabled and FDataLink.Active) then
  602.     for I := Low(Buttons) to High(Buttons) do
  603.       Buttons[I].Enabled := False
  604.   else
  605.   begin
  606.     DataChanged;
  607.     EditingChanged;
  608.   end;
  609. end;
  610.  
  611. procedure TRaDBNavigator.CMEnabledChanged(var Message: TMessage);
  612. begin
  613.   inherited;
  614.   if not (csLoading in ComponentState) then
  615.     ActiveChanged;
  616. end;
  617.  
  618. function TRaDBNavigator.CurrentField: TField;
  619. var ParentForm: TCustomForm;
  620.     AControl: TControl;
  621. begin
  622.    Result := nil;
  623.    ParentForm := GetParentForm(Self);
  624.    if (ParentForm <> nil) then
  625.       AControl := ParentForm.ActiveControl
  626.      else
  627.       AControl := nil;
  628.  
  629.    if (AControl <> nil) then
  630.    begin
  631.       if (AControl.Parent is TRaDBEdit) then
  632.          Result := (AControl.Parent as TRaDBEdit).Field
  633.         else
  634.       if (AControl is TDBGrid) then
  635.          Result := (AControl as TDBGrid).SelectedField
  636.         else
  637.       if (AControl is TRaDBBox) then
  638.       begin
  639.          if (AControl as TRaDBBox).ControlCount > 1 then
  640.             Result := ((AControl as TRaDBBox).Controls[0] as TRaDBEdit).Field;
  641.       end
  642.         else
  643.       if (AControl is TDBEdit) then
  644.          Result := (AControl as TDBEdit).Field
  645.         else
  646.       if (AControl is TDBMemo) then
  647.          Result := (AControl as TDBMemo).Field
  648.         else
  649.       if (AControl is TDBImage) then
  650.          Result := (AControl as TDBImage).Field
  651.         else
  652.       if (AControl is TDBListBox) then
  653.          Result := (AControl as TDBListBox).Field
  654.         else
  655.       if (AControl is TDBComboBox) then
  656.          Result := (AControl as TDBComboBox).Field
  657.         else
  658.       if (AControl is TDBCheckBox) then
  659.          Result := (AControl as TDBCheckBox).Field
  660.         else
  661.       if (AControl is TDBComboBox) then
  662.          Result := (AControl as TDBComboBox).Field
  663.         else
  664.       if (AControl is TDBRadioGroup) then
  665.          Result := (AControl as TDBRadioGroup).Field
  666.         else
  667.       if (AControl is TDBLookupListBox) then
  668.          Result := (AControl as TDBLookupListBox).Field
  669.         else
  670.       if (AControl is TDBLookupComboBox) then
  671.          Result := (AControl as TDBLookupComboBox).Field
  672.         else
  673.       if (AControl is TxDBLookupComboBox) then
  674.          Result := (AControl as TxDBLookupComboBox).Field
  675.         else
  676.       if (AControl is TDBRichEdit) then
  677.          Result := (AControl as TDBRichEdit).Field
  678.    end;
  679. end;
  680.  
  681. procedure TRaDBNavigator.ChangeDataSource;
  682. var ParentForm: TCustomForm;
  683.     AControl: TControl;
  684.     ADataSource: TDataSource;
  685. begin
  686.    ADataSource := FDataSource;
  687.    ParentForm := GetParentForm(Self);
  688.    if (ParentForm <> nil) then
  689.       AControl := ParentForm.ActiveControl
  690.      else
  691.       AControl := nil;
  692.  
  693.    if (AControl <> nil) and FDataSourceAuto then
  694.    begin
  695.       if (AControl.Parent is TRaDBEdit) then
  696.          ADataSource := (AControl.Parent as TRaDBEdit).DataSource
  697.         else
  698.       if (AControl is TDBGrid) then
  699.          ADataSource := (AControl as TDBGrid).DataSource
  700.         else
  701.       if (AControl is TRaDBBox) then
  702.          ADataSource := (AControl as TRaDBBox).DataSource
  703.         else
  704.       if (AControl is TDBEdit) then
  705.          ADataSource := (AControl as TDBEdit).DataSource
  706.         else
  707.       if (AControl is TDBMemo) then
  708.          ADataSource := (AControl as TDBMemo).DataSource
  709.         else
  710.       if (AControl is TDBImage) then
  711.          ADataSource := (AControl as TDBImage).DataSource
  712.         else
  713.       if (AControl is TDBListBox) then
  714.          ADataSource := (AControl as TDBListBox).DataSource
  715.         else
  716.       if (AControl is TDBComboBox) then
  717.          ADataSource := (AControl as TDBComboBox).DataSource
  718.         else
  719.       if (AControl is TDBCheckBox) then
  720.          ADataSource := (AControl as TDBCheckBox).DataSource
  721.         else
  722.       if (AControl is TDBComboBox) then
  723.          ADataSource := (AControl as TDBComboBox).DataSource
  724.         else
  725.       if (AControl is TDBRadioGroup) then
  726.          ADataSource := (AControl as TDBRadioGroup).DataSource
  727.         else
  728.       if (AControl is TDBLookupListBox) then
  729.          ADataSource := (AControl as TDBLookupListBox).DataSource
  730.         else
  731.       if (AControl is TDBLookupComboBox) then
  732.          ADataSource := (AControl as TDBLookupComboBox).DataSource
  733.         else
  734.       if (AControl is TxDBLookupComboBox) then
  735.          ADataSource := (AControl as TxDBLookupComboBox).DataSource
  736.         else
  737.       if (AControl is TDBRichEdit) then
  738.          ADataSource := (AControl as TDBRichEdit).DataSource
  739.         else
  740.       if (AControl is TDBCtrlGrid) then
  741.          ADataSource := (AControl as TDBCtrlGrid).DataSource;
  742.    end;
  743.  
  744.    if (ADataSource <> FDataLink.DataSource) then
  745.    begin
  746.       FDataLink.DataSource := ADataSource;
  747.       if not (csLoading in ComponentState) then
  748.         ActiveChanged;
  749.       if ADataSource <> nil then ADataSource.FreeNotification(Self);
  750.    end;
  751. end;
  752.  
  753. procedure TRaDBNavigator.CMFocusChanged(var Message: TCMFocusChanged);
  754. begin
  755.    Inherited;
  756.    ChangeDataSource;
  757. end;
  758.  
  759. procedure TRaDBNavigator.SetDataSource(Value: TDataSource);
  760. begin
  761.   FDataLink.DataSource := Value;
  762.   FDataSource := Value;
  763.   if not (csLoading in ComponentState) then
  764.     ActiveChanged;
  765.   if Value <> nil then Value.FreeNotification(Self);
  766. end;
  767.  
  768. function TRaDBNavigator.GetDataSource: TDataSource;
  769. begin
  770.   Result := FDataLink.DataSource;
  771. end;
  772.  
  773. procedure TRaDBNavigator.Loaded;
  774. var
  775.   W, H: Integer;
  776. begin
  777.   inherited Loaded;
  778.   W := Width;
  779.   H := Height;
  780.   AdjustSize (W, H);
  781.   if (W <> Width) or (H <> Height) then
  782.     inherited SetBounds (Left, Top, W, H);
  783.   InitHints;
  784.   ActiveChanged;
  785. end;
  786.  
  787. procedure TRaDBNavigator.SetDataSourceAuto(Value: Boolean);
  788. begin
  789.    FDataSourceAuto := Value;
  790.    ChangeDataSource;
  791. end;
  792. {TxNavButton}
  793.  
  794. destructor TxNavButton.Destroy;
  795. begin
  796.   if FRepeatTimer <> nil then
  797.     FRepeatTimer.Free;
  798.   inherited Destroy;
  799. end;
  800.  
  801. procedure TxNavButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
  802.   X, Y: Integer);
  803. begin
  804.   inherited MouseDown (Button, Shift, X, Y);
  805.   if nsAllowTimer in FNavStyle then
  806.   begin
  807.     if FRepeatTimer = nil then
  808.       FRepeatTimer := TTimer.Create(Self);
  809.  
  810.     FRepeatTimer.OnTimer := TimerExpired;
  811.     FRepeatTimer.Interval := InitRepeatPause;
  812.     FRepeatTimer.Enabled  := True;
  813.   end;
  814. end;
  815.  
  816. procedure TxNavButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
  817.                                   X, Y: Integer);
  818. begin
  819.   inherited MouseUp (Button, Shift, X, Y);
  820.   if FRepeatTimer <> nil then
  821.     FRepeatTimer.Enabled  := False;
  822. end;
  823.  
  824. procedure TxNavButton.TimerExpired(Sender: TObject);
  825. begin
  826.   FRepeatTimer.Interval := RepeatPause;
  827.   if (FState = bsDown) and MouseCapture then
  828.   begin
  829.     try
  830.       Click;
  831.     except
  832.       FRepeatTimer.Enabled := False;
  833.       raise;
  834.     end;
  835.   end;
  836. end;
  837.  
  838. procedure TxNavButton.Paint;
  839. var
  840.   R: TRect;
  841. begin
  842.   inherited Paint;
  843.   if (GetFocus = Parent.Handle) and
  844.      (FIndex = TRaDBNavigator (Parent).FocusedButton) then
  845.   begin
  846.     R := Bounds(0, 0, Width, Height);
  847.     InflateRect(R, -3, -3);
  848.     if FState = bsDown then
  849.       OffsetRect(R, 1, 1);
  850.     DrawFocusRect(Canvas.Handle, R);
  851.   end;
  852. end;
  853.  
  854. { TxNavDataLink }
  855. constructor TxNavDataLink.Create(ANav: TRaDBNavigator);
  856. begin
  857.   inherited Create;
  858.   FNavigator := ANav;
  859. end;
  860.  
  861. destructor TxNavDataLink.Destroy;
  862. begin
  863.   FNavigator := nil;
  864.   inherited Destroy;
  865. end;
  866.  
  867. procedure TxNavDataLink.EditingChanged;
  868. begin
  869.   if FNavigator <> nil then FNavigator.EditingChanged;
  870. end;
  871.  
  872. procedure TxNavDataLink.DataSetChanged;
  873. begin
  874.   if FNavigator <> nil then FNavigator.DataChanged;
  875. end;
  876.  
  877. procedure TxNavDataLink.ActiveChanged;
  878. begin
  879.   if FNavigator <> nil then FNavigator.ActiveChanged;
  880. end;
  881.  
  882. end.
  883.