home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d6 / RX275D6.ZIP / Units / PAGEMNGR.PAS < prev    next >
Pascal/Delphi Source File  |  1999-10-12  |  24KB  |  843 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 1996 AO ROSNO                   }
  6. {         Copyright (c) 1998 Master-Bank                }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit PageMngr;
  11.  
  12. {$I RX.INC}
  13.  
  14. interface
  15.  
  16. uses Classes, Controls, ExtCtrls;
  17.  
  18. type
  19.   TPageNotifyEvent = procedure(Next: Boolean) of object;
  20.   TPageRequestEvent = procedure(CurrentPage: Integer;
  21.     var NewPage: Integer) of object;
  22.  
  23.   TPageOwner = TNotebook;
  24.   TPageItem = TPage;
  25.   TPageProxy = class;
  26.   TPageHistory = class;
  27.   TPageHistoryItem = class;
  28.   TPageHistoryCommand = (hcNone, hcAdd, hcBack, hcForward, hcGoto);
  29.  
  30.   TPageManager = class(TComponent)
  31.   private
  32.     FPageOwner: TPageOwner;
  33.     FPageProxies: TList;
  34.     FSetStartPage: Boolean;
  35.     FDestroyHandles: Boolean;
  36.     FButtons: array [Boolean] of TControl;
  37.     FSaveBtnClick: array [Boolean] of TNotifyEvent;
  38.     FChangeHelpContext: Boolean;
  39.     FPageHistory: TPageHistory;
  40.     FUseHistory: Boolean;
  41.     FHistoryCommand: TPageHistoryCommand;
  42.     FOnGetPriorPage: TPageRequestEvent;
  43.     FOnGetNextPage: TPageRequestEvent;
  44.     FOnCheckButtons: TNotifyEvent;
  45.     FOnCheckProxy: TNotifyEvent;
  46.     FOnPageChanged: TNotifyEvent;
  47.     procedure SetPageOwner(Value: TPageOwner);
  48.     function GetProxyIndex(const PageName: string): Integer;
  49.     procedure AddProxy(Proxy: TPageProxy);
  50.     procedure RemoveProxy(Proxy: TPageProxy);
  51.     procedure DestroyProxies;
  52.     procedure PageEnter(Page: Integer; Next: Boolean);
  53.     procedure PageLeave(Page: Integer; Next: Boolean);
  54.     procedure PageShow(Page: Integer; Next: Boolean);
  55.     procedure PageHide(Page: Integer; Next: Boolean);
  56.     procedure PageChanged;
  57.     function GetNextEnabled: Boolean;
  58.     function GetPriorEnabled: Boolean;
  59.     function GetPageIndex: Integer;
  60.     procedure SetPageIndex(Value: Integer);
  61.     function GetPageCount: Integer;
  62.     function GetPageName(Index: Integer): string;
  63.     function FindFreePage: string;
  64.     procedure SetPageProxies(Value: TList);
  65.     function GetButton(Index: Integer): TControl;
  66.     procedure SetButton(Index: Integer; Value: TControl);
  67.     procedure SetDestroyHandles(Value: Boolean);
  68.     procedure SyncBtnClick(Index: Integer; Sync: Boolean);
  69.     procedure BtnClick(Sender: TObject);
  70.     procedure DormantPages;
  71.   protected
  72.     procedure Loaded; override;
  73.     procedure Notification(AComponent: TComponent;
  74.       AOperation: TOperation); override;
  75. {$IFDEF WIN32}
  76.     procedure GetChildren(Proc: TGetChildProc {$IFDEF RX_D3};
  77.       Root: TComponent {$ENDIF}); override;
  78. {$ELSE}
  79.     procedure WriteComponents(Writer: TWriter); override;
  80. {$ENDIF WIN32}
  81.     procedure ChangePage(Next: Boolean); virtual;
  82.   public
  83.     constructor Create(AOwner: TComponent); override;
  84.     destructor Destroy; override;
  85.     procedure CheckBtnEnabled;
  86.     procedure Resync;
  87.     function GetPriorPageIndex(Page: Integer): Integer; virtual;
  88.     function GetNextPageIndex(Page: Integer): Integer; virtual;
  89.     procedure NextPage;
  90.     procedure PriorPage;
  91.     procedure GotoHistoryPage(HistoryIndex: Integer);
  92.     procedure SetPage(NewPageIndex: Integer; Next: Boolean);
  93.     property PageNames[Index: Integer]: string read GetPageName;
  94.     property PageCount: Integer read GetPageCount;
  95.     property PageIndex: Integer read GetPageIndex;
  96.     property NextEnabled: Boolean read GetNextEnabled;
  97.     property PriorEnabled: Boolean read GetPriorEnabled;
  98.     property PageHistory: TPageHistory read FPageHistory;
  99.     property HistoryCommand: TPageHistoryCommand read FHistoryCommand
  100.       write FHistoryCommand;
  101.     property OnCheckProxy: TNotifyEvent read FOnCheckProxy write FOnCheckProxy; { for internal use only }
  102.   published
  103.     property PageOwner: TPageOwner read FPageOwner write SetPageOwner;
  104.     property PageProxies: TList read FPageProxies write SetPageProxies;
  105.     property NextBtn: TControl index 1 read GetButton write SetButton;
  106.     property PriorBtn: TControl index 0 read GetButton write SetButton;
  107.     property SetStartPage: Boolean read FSetStartPage write FSetStartPage default True;
  108.     property DestroyHandles: Boolean read FDestroyHandles write SetDestroyHandles default False;
  109.     property UseHistory: Boolean read FUseHistory write FUseHistory default False;
  110.     property OnGetPriorPage: TPageRequestEvent read FOnGetPriorPage
  111.       write FOnGetPriorPage;
  112.     property OnGetNextPage: TPageRequestEvent read FOnGetNextPage
  113.       write FOnGetNextPage;
  114.     property OnCheckButtons: TNotifyEvent read FOnCheckButtons
  115.       write FOnCheckButtons;
  116.     property OnPageChanged: TNotifyEvent read FOnPageChanged write FOnPageChanged;
  117.   end;
  118.  
  119.   TPageProxy = class(TComponent)
  120.   private
  121.     FPageManager: TPageManager;
  122.     FPageName: PString;
  123.     FOnEnter: TPageNotifyEvent;
  124.     FOnLeave: TPageNotifyEvent;
  125.     FOnShow: TPageNotifyEvent;
  126.     FOnHide: TPageNotifyEvent;
  127.     function GetPageName: string;
  128.     procedure SetPageName(const Value: string);
  129.     procedure SetPageManager(Value: TPageManager);
  130.     procedure PageEnter(Next: Boolean);
  131.     procedure PageLeave(Next: Boolean);
  132.     procedure PageShow(Next: Boolean);
  133.     procedure PageHide(Next: Boolean);
  134.   protected
  135. {$IFDEF WIN32}
  136.     procedure SetParentComponent(Value: TComponent); override;
  137. {$ELSE}
  138.     procedure ReadState(Reader: TReader); override;
  139. {$ENDIF}
  140.   public
  141.     constructor Create(AOwner: TComponent); override;
  142.     destructor Destroy; override;
  143.     function HasParent: Boolean; override;
  144. {$IFDEF WIN32}
  145.     function GetParentComponent: TComponent; override;
  146. {$ENDIF}
  147.     property PageManager: TPageManager read FPageManager write SetPageManager;
  148.   published
  149.     property PageName: string read GetPageName write SetPageName;
  150.     property OnEnter: TPageNotifyEvent read FOnEnter write FOnEnter;
  151.     property OnLeave: TPageNotifyEvent read FOnLeave write FOnLeave;
  152.     property OnShow: TPageNotifyEvent read FOnShow write FOnShow;
  153.     property OnHide: TPageNotifyEvent read FOnHide write FOnHide;
  154.   end;
  155.  
  156.   TPageHistoryItem = class(TObject)
  157.   public
  158.     Index: Integer;
  159.   end;
  160.  
  161.   TPageHistory = class(TList)
  162.   private
  163.     FCurrent: Integer;
  164.     FHistoryCapacity: Integer;
  165.     procedure SetCurrent(Value: Integer);
  166.     procedure SetHistoryCapacity(Value: Integer);
  167.     function GetPageIndex(Index: Integer): Integer;
  168.   public
  169.     constructor Create;
  170.     destructor Destroy; override;
  171.     procedure AddPageIndex(PageIndex: Integer);
  172.     procedure DeleteHistoryItem(Index: Integer);
  173.     procedure ResetHistory;
  174.     property Current: Integer read FCurrent write SetCurrent;
  175.     property HistoryCapacity: Integer read FHistoryCapacity
  176.       write SetHistoryCapacity;
  177.     property PageIndexes[Index: Integer]: Integer read GetPageIndex;
  178.   end;
  179.  
  180. const
  181.   pageNull = -1;
  182.  
  183. implementation
  184.  
  185. uses SysUtils, Forms, StdCtrls {$IFDEF RX_D4}, ActnList {$ENDIF};
  186.  
  187. const
  188.   Registered: Boolean = False;
  189.  
  190. { TPageProxy }
  191.  
  192. constructor TPageProxy.Create(AOwner: TComponent);
  193. begin
  194.   inherited Create(AOwner);
  195.   FPageName := NullStr;
  196. end;
  197.  
  198. destructor TPageProxy.Destroy;
  199. begin
  200.   if FPageManager <> nil then FPageManager.RemoveProxy(Self);
  201.   DisposeStr(FPageName);
  202.   inherited Destroy;
  203. end;
  204.  
  205. function TPageProxy.GetPageName: string;
  206. begin
  207.   Result := FPageName^;
  208. end;
  209.  
  210. procedure TPageProxy.SetPageName(const Value: string);
  211. begin
  212.   if (FPageManager <> nil) and (FPageManager.PageOwner <> nil) then
  213.   begin
  214.     if (FPageManager.PageOwner.Pages.IndexOf(Value) >= 0) then
  215.       AssignStr(FPageName, Value)
  216.     else AssignStr(FPageName, '');
  217.   end
  218.   else AssignStr(FPageName, Value);
  219. end;
  220.  
  221. procedure TPageProxy.SetPageManager(Value: TPageManager);
  222. begin
  223.   if FPageManager <> nil then FPageManager.RemoveProxy(Self);
  224.   if Value <> nil then Value.AddProxy(Self);
  225. end;
  226.  
  227. function TPageProxy.HasParent: Boolean;
  228. begin
  229.   Result := True;
  230. end;
  231.  
  232. {$IFDEF WIN32}
  233.  
  234. function TPageProxy.GetParentComponent: TComponent;
  235. begin
  236.   Result := FPageManager;
  237. end;
  238.  
  239. procedure TPageProxy.SetParentComponent(Value: TComponent);
  240. begin
  241.   if FPageManager <> nil then FPageManager.RemoveProxy(Self);
  242.   if (Value <> nil) and (Value is TPageManager) then
  243.     PageManager := TPageManager(Value);
  244. end;
  245.  
  246. {$ELSE}
  247.  
  248. procedure TPageProxy.ReadState(Reader: TReader);
  249. begin
  250.   inherited ReadState(Reader);
  251.   if Reader.Parent is TPageManager then begin
  252.     PageManager := TPageManager(Reader.Parent);
  253.   end;
  254. end;
  255.  
  256. {$ENDIF WIN32}
  257.  
  258. procedure TPageProxy.PageEnter(Next: Boolean);
  259. begin
  260.   if Assigned(FOnEnter) then FOnEnter(Next);
  261. end;
  262.  
  263. procedure TPageProxy.PageLeave(Next: Boolean);
  264. begin
  265.   if Assigned(FOnLeave) then FOnLeave(Next);
  266. end;
  267.  
  268. procedure TPageProxy.PageShow(Next: Boolean);
  269. begin
  270.   if Assigned(FOnShow) then FOnShow(Next);
  271. end;
  272.  
  273. procedure TPageProxy.PageHide(Next: Boolean);
  274. begin
  275.   if Assigned(FOnHide) then FOnHide(Next);
  276. end;
  277.  
  278. { TPageManager }
  279.  
  280. constructor TPageManager.Create(AOwner: TComponent);
  281. begin
  282.   inherited Create(AOwner);
  283.   FPageProxies := TList.Create;
  284.   FPageHistory := TPageHistory.Create;
  285.   FHistoryCommand := hcAdd;
  286.   FSetStartPage := True;
  287.   FChangeHelpContext := True;
  288.   FUseHistory := False;
  289.   if not Registered then begin
  290.     RegisterClasses([TPageProxy]);
  291.     Registered := True;
  292.   end;
  293. end;
  294.  
  295. destructor TPageManager.Destroy;
  296. begin
  297.   DestroyProxies;
  298.   FPageProxies.Free;
  299.   FPageHistory.Free;
  300.   inherited Destroy;
  301. end;
  302.  
  303. procedure TPageManager.Loaded;
  304. var
  305.   Loading: Boolean;
  306. begin
  307.   Loading := csLoading in ComponentState;
  308.   inherited Loaded;
  309.   if not (csDesigning in ComponentState) and Loading then begin
  310.     SyncBtnClick(0, True);
  311.     SyncBtnClick(1, True);
  312.   end;
  313.   if FSetStartPage and not (csDesigning in ComponentState) and
  314.     (FPageOwner <> nil) and (FPageProxies.Count > 0) then
  315.   begin
  316.     if (FPageProxies.Items[0] <> nil) and
  317.       (TPageProxy(FPageProxies.Items[0]).PageName <> '') then
  318.     begin
  319.       FPageOwner.ActivePage := TPageProxy(FPageProxies.Items[0]).PageName;
  320.     end;
  321.   end;
  322.   if DestroyHandles then DormantPages;
  323.   if (FPageOwner <> nil) and (FPageHistory.Count = 0) then begin
  324.     FPageHistory.AddPageIndex(FPageOwner.PageIndex);
  325.   end;
  326.   CheckBtnEnabled;
  327. end;
  328.  
  329. procedure TPageManager.Notification(AComponent: TComponent; AOperation: TOperation);
  330. begin
  331.   inherited Notification(AComponent, AOperation);
  332.   if AOperation = opRemove then begin
  333.     if AComponent = PageOwner then PageOwner := nil
  334.     else if AComponent = FButtons[False] then FButtons[False] := nil
  335.     else if AComponent = FButtons[True] then FButtons[True] := nil;
  336.   end;
  337. end;
  338.  
  339. function TPageManager.GetButton(Index: Integer): TControl;
  340. begin
  341.   Result := FButtons[Boolean(Index)];
  342. end;
  343.  
  344. procedure TPageManager.SetButton(Index: Integer; Value: TControl);
  345. begin
  346.   if GetButton(Index) <> Value then begin
  347.     if not (csLoading in ComponentState) then  SyncBtnClick(Index, False);
  348.     FButtons[Boolean(Index)] := Value;
  349. {$IFDEF WIN32}
  350.     if Value <> nil then Value.FreeNotification(Self);
  351. {$ENDIF}
  352.     if not (csLoading in ComponentState) then  SyncBtnClick(Index, True);
  353.   end;
  354. end;
  355.  
  356. procedure TPageManager.SyncBtnClick(Index: Integer; Sync: Boolean);
  357. begin
  358.   if (GetButton(Index) <> nil) and not (csDesigning in ComponentState) then
  359.     if Sync then begin
  360.       FSaveBtnClick[Boolean(Index)] := TButton(GetButton(Index)).OnClick;
  361.       TButton(GetButton(Index)).OnClick := BtnClick;
  362.     end
  363.     else begin
  364.       TButton(GetButton(Index)).OnClick := FSaveBtnClick[Boolean(Index)];
  365.       FSaveBtnClick[Boolean(Index)] := nil;
  366.     end;
  367. end;
  368.  
  369. procedure TPageManager.BtnClick(Sender: TObject);
  370. var
  371.   Next: Boolean;
  372. begin
  373.   for Next := False to True do
  374.     if Sender = FButtons[Next] then begin
  375.       ChangePage(Next);
  376.       if Assigned(FSaveBtnClick[Next]) then FSaveBtnClick[Next](Sender);
  377.     end;
  378. end;
  379.  
  380. procedure TPageManager.CheckBtnEnabled;
  381. begin
  382.   if not (csDesigning in ComponentState) then begin
  383. {$IFDEF RX_D4}
  384.     if GetButton(0) <> nil then begin
  385.       if GetButton(0).Action <> nil then
  386.         TAction(GetButton(0).Action).Enabled := PriorEnabled
  387.       else
  388.         GetButton(0).Enabled := PriorEnabled;
  389.     end;
  390.     if GetButton(1) <> nil then begin
  391.       if GetButton(1).Action <> nil then
  392.         TAction(GetButton(1).Action).Enabled := NextEnabled
  393.       else
  394.         GetButton(1).Enabled := NextEnabled;
  395.     end;
  396. {$ELSE}
  397.     if GetButton(0) <> nil then GetButton(0).Enabled := PriorEnabled;
  398.     if GetButton(1) <> nil then GetButton(1).Enabled := NextEnabled;
  399. {$ENDIF}
  400.     if Assigned(FOnCheckButtons) then FOnCheckButtons(Self);
  401.   end;
  402. end;
  403.  
  404. {$IFDEF WIN32}
  405. procedure TPageManager.GetChildren(Proc: TGetChildProc {$IFDEF RX_D3};
  406.   Root: TComponent {$ENDIF});
  407. var
  408.   I: Integer;
  409. begin
  410.   inherited GetChildren(Proc{$IFDEF RX_D3}, Root {$ENDIF});
  411.   for I := 0 to FPageProxies.Count - 1 do begin
  412.     Proc(TPageProxy(FPageProxies.Items[I]));
  413.   end;
  414. end;
  415. {$ELSE}
  416. procedure TPageManager.WriteComponents(Writer: TWriter);
  417. var
  418.   I: Integer;
  419.   Proxy: TPageProxy;
  420. begin
  421.   inherited WriteComponents(Writer);
  422.   for I := 0 to FPageProxies.Count - 1 do begin
  423.     Proxy := FPageProxies.Items[I];
  424.     if Proxy.Owner = Writer.Root then Writer.WriteComponent(Proxy);
  425.   end;
  426. end;
  427. {$ENDIF WIN32}
  428.  
  429. procedure TPageManager.SetDestroyHandles(Value: Boolean);
  430. begin
  431.   if Value <> FDestroyHandles then begin
  432.     FDestroyHandles := Value;
  433.     if not (csLoading in ComponentState) and FDestroyHandles then
  434.       DormantPages;
  435.   end;
  436. end;
  437.  
  438. procedure TPageManager.SetPageOwner(Value: TPageOwner);
  439. begin
  440.   if FPageOwner <> Value then begin
  441.     FPageOwner := Value;
  442. {$IFDEF WIN32}
  443.     if Value <> nil then Value.FreeNotification(Self);
  444. {$ENDIF}
  445.     if not (csLoading in ComponentState) then begin
  446.       Resync;
  447.       if FDestroyHandles then DormantPages;
  448.       if (FPageOwner <> nil) and (FPageHistory.Count = 0) then begin
  449.         FPageHistory.AddPageIndex(FPageOwner.PageIndex);
  450.       end;
  451.     end;
  452.   end;
  453. end;
  454.  
  455. procedure TPageManager.SetPageProxies(Value: TList);
  456. begin
  457. end;
  458.  
  459. function TPageManager.GetProxyIndex(const PageName: string): Integer;
  460. var
  461.   I: Integer;
  462. begin
  463.   Result := -1;
  464.   for I := 0 to FPageProxies.Count - 1 do begin
  465.     if TPageProxy(FPageProxies.Items[I]).PageName = PageName then begin
  466.       Result := I;
  467.       Exit;
  468.     end;
  469.   end;
  470. end;
  471.  
  472. procedure TPageManager.Resync;
  473. var
  474.   I: Integer;
  475.   Index: Integer;
  476.   NewCount: Integer;
  477.   NewProxy: TPageProxy;
  478. begin
  479.   if FPageOwner = nil then Exit;
  480.   if PageCount > FPageProxies.Count then begin
  481.     NewCount := PageCount - FPageProxies.Count;
  482.     for I := 1 to NewCount do begin
  483.       NewProxy := TPageProxy.Create(Owner);
  484.       AddProxy(NewProxy);
  485.       if Assigned(FOnCheckProxy) then FOnCheckProxy(NewProxy);
  486.       {NewProxy.Name := GetUniqueName(NewProxy);}
  487.       NewProxy.PageName := FindFreePage;
  488.     end;
  489.   end;
  490.   for I := FPageProxies.Count - 1 downto 0 do begin
  491.     if FPageProxies.Count > PageCount then begin
  492.       if (TPageProxy(FPageProxies.Items[I]).PageName <> '') and
  493.         (FPageOwner.Pages.IndexOf(TPageProxy(FPageProxies.Items[I]).PageName) = -1) then
  494.         TPageProxy(FPageProxies.Items[I]).Free;
  495.     end
  496.     else Break;
  497.   end;
  498.   for I := 0 to FPageProxies.Count - 1 do
  499.     if Assigned(FOnCheckProxy) then
  500.       FOnCheckProxy(TObject(FPageProxies.Items[I]));
  501.   for I := 0 to PageCount - 1 do begin
  502.     Index := GetProxyIndex(PageNames[I]);
  503.     if Index <> -1 then begin
  504.       FPageProxies.Move(Index, I);
  505.     end;
  506.   end;
  507. end;
  508.  
  509. procedure TPageManager.AddProxy(Proxy: TPageProxy);
  510. begin
  511.   FPageProxies.Add(Proxy);
  512.   Proxy.FPageManager := Self;
  513. end;
  514.  
  515. procedure TPageManager.RemoveProxy(Proxy: TPageProxy);
  516. begin
  517.   Proxy.FPageManager := nil;
  518.   FPageProxies.Remove(Proxy);
  519. end;
  520.  
  521. procedure TPageManager.DestroyProxies;
  522. var
  523.   Proxy: TPageProxy;
  524. begin
  525.   while FPageProxies.Count > 0 do begin
  526.     Proxy := FPageProxies.Last;
  527.     RemoveProxy(Proxy);
  528.     Proxy.Free;
  529.   end;
  530. end;
  531.  
  532. function TPageManager.GetPageCount: Integer;
  533. begin
  534.   Result := 0;
  535.   if FPageOwner <> nil then begin
  536.     Result := FPageOwner.Pages.Count;
  537.   end;
  538. end;
  539.  
  540. function TPageManager.GetPageName(Index: Integer): string;
  541. begin
  542.   Result := '';
  543.   if (FPageOwner <> nil) and (Index < PageCount) then begin
  544.     Result := FPageOwner.Pages[Index];
  545.   end;
  546. end;
  547.  
  548. function TPageManager.FindFreePage: string;
  549. var
  550.   I: Integer;
  551. begin
  552.   Result := '';
  553.   if PageOwner <> nil then
  554.     for I := 0 to PageOwner.Pages.Count - 1 do
  555.       if GetProxyIndex(PageOwner.Pages[I]) = -1 then begin
  556.         Result := PageOwner.Pages[I];
  557.         Exit;
  558.       end;
  559. end;
  560.  
  561. function TPageManager.GetPageIndex: Integer;
  562. begin
  563.   if PageOwner <> nil then Result := PageOwner.PageIndex
  564.   else Result := pageNull;
  565. end;
  566.  
  567. procedure TPageManager.SetPageIndex(Value: Integer);
  568. var
  569.   Page: TPageItem;
  570.   OldPageIndex: Integer;
  571. begin
  572.   if PageOwner <> nil then begin
  573.     OldPageIndex := PageOwner.PageIndex;
  574.     PageOwner.PageIndex := Value;
  575.     if DestroyHandles then DormantPages;
  576.     if OldPageIndex <> PageOwner.PageIndex then begin
  577.       if not FUseHistory then begin
  578.         PageHistory.AddPageIndex(PageOwner.PageIndex);
  579.       end
  580.       else begin
  581.         case HistoryCommand of
  582.           hcNone: ;
  583.           hcAdd: PageHistory.AddPageIndex(PageOwner.PageIndex);
  584.           hcBack: PageHistory.Current := PageHistory.Current - 1;
  585.           hcForward: PageHistory.Current := PageHistory.Current + 1;
  586.           hcGoto: ;
  587.         end;
  588.       end;
  589.     end;
  590.     HistoryCommand := hcAdd;
  591.     CheckBtnEnabled;
  592.     { update owner form help context }
  593.     if FChangeHelpContext and (Owner <> nil) and (Owner is TForm) and
  594.       ((Owner as TForm).HelpContext = 0) then
  595.     begin
  596.       Page := TPageItem(PageOwner.Pages.Objects[PageIndex]);
  597.       if Page <> nil then (Owner as TForm).HelpContext := Page.HelpContext;
  598.     end;
  599.   end;
  600. end;
  601.  
  602. function TPageManager.GetNextEnabled: Boolean;
  603. begin
  604.   Result := GetNextPageIndex(PageIndex) >= 0;
  605. end;
  606.  
  607. function TPageManager.GetPriorEnabled: Boolean;
  608. begin
  609.   Result := GetPriorPageIndex(PageIndex) >= 0;
  610. end;
  611.  
  612. procedure TPageManager.NextPage;
  613. begin
  614.   ChangePage(True);
  615. end;
  616.  
  617. procedure TPageManager.PriorPage;
  618. begin
  619.   ChangePage(False);
  620. end;
  621.  
  622. procedure TPageManager.GotoHistoryPage(HistoryIndex: Integer);
  623. var
  624.   SaveCurrent: Integer;
  625. begin
  626.   SaveCurrent := PageHistory.Current;
  627.   HistoryCommand := hcGoto;
  628.   PageHistory.Current := HistoryIndex;
  629.   try
  630.     SetPage(PageHistory.PageIndexes[HistoryIndex], False);
  631.   finally
  632.     if PageOwner.PageIndex <> PageHistory.PageIndexes[HistoryIndex] then
  633.       PageHistory.Current := SaveCurrent;
  634.   end;
  635. end;
  636.  
  637. procedure TPageManager.PageEnter(Page: Integer; Next: Boolean);
  638. var
  639.   ProxyIndex: Integer;
  640. begin
  641.   ProxyIndex := GetProxyIndex(PageOwner.Pages.Strings[Page]);
  642.   if ProxyIndex <> pageNull then begin
  643.     TPageProxy(FPageProxies.Items[ProxyIndex]).PageEnter(Next);
  644.   end;
  645. end;
  646.  
  647. procedure TPageManager.PageLeave(Page: Integer; Next: Boolean);
  648. var
  649.   ProxyIndex: Integer;
  650. begin
  651.   ProxyIndex := GetProxyIndex(PageOwner.Pages.Strings[Page]);
  652.   if ProxyIndex <> pageNull then begin
  653.     TPageProxy(FPageProxies.Items[ProxyIndex]).PageLeave(Next);
  654.   end;
  655. end;
  656.  
  657. procedure TPageManager.PageShow(Page: Integer; Next: Boolean);
  658. var
  659.   ProxyIndex: Integer;
  660. begin
  661.   ProxyIndex := GetProxyIndex(PageOwner.Pages.Strings[Page]);
  662.   if ProxyIndex <> pageNull then begin
  663.     TPageProxy(FPageProxies.Items[ProxyIndex]).PageShow(Next);
  664.   end;
  665. end;
  666.  
  667. procedure TPageManager.PageHide(Page: Integer; Next: Boolean);
  668. var
  669.   ProxyIndex: Integer;
  670. begin
  671.   ProxyIndex := GetProxyIndex(PageOwner.Pages.Strings[Page]);
  672.   if ProxyIndex <> pageNull then begin
  673.     TPageProxy(FPageProxies.Items[ProxyIndex]).PageHide(Next);
  674.   end;
  675. end;
  676.  
  677. procedure TPageManager.PageChanged;
  678. begin
  679.   if Assigned(FOnPageChanged) then FOnPageChanged(Self);
  680. end;
  681.  
  682. function TPageManager.GetPriorPageIndex(Page: Integer): Integer;
  683. begin
  684.   if not FUseHistory then begin
  685.     if Page < 1 then
  686.       Result := pageNull
  687.     else
  688.       Result := Page - 1;
  689.     end
  690.   else begin
  691.     if PageHistory.Current < 1 then
  692.       Result := pageNull
  693.     else
  694.       Result := PageHistory.PageIndexes[PageHistory.Current - 1];
  695.   end;
  696.   if Assigned(FOnGetPriorPage) then FOnGetPriorPage(Page, Result);
  697. end;
  698.  
  699. function TPageManager.GetNextPageIndex(Page: Integer): Integer;
  700. begin
  701.   if not FUseHistory then begin
  702.     if Page >= PageCount - 1 then
  703.       Result := pageNull
  704.     else
  705.       Result := Page + 1;
  706.     end
  707.   else begin
  708.     if PageHistory.Current >= PageHistory.Count - 1 then
  709.       Result := pageNull
  710.     else
  711.       Result := PageHistory.PageIndexes[PageHistory.Current + 1];
  712.   end;
  713.   if Assigned(FOnGetNextPage) then FOnGetNextPage(Page, Result);
  714. end;
  715.  
  716. procedure TPageManager.SetPage(NewPageIndex: Integer; Next: Boolean);
  717. var
  718.   OldPageIndex: Integer;
  719. begin
  720.   if (NewPageIndex >=0) and (NewPageIndex < PageCount) then begin
  721.     OldPageIndex := PageIndex;
  722.     PageLeave(OldPageIndex, Next);
  723.     PageEnter(NewPageIndex, Next);
  724.     SetPageIndex(NewPageIndex);
  725.     if NewPageIndex = PageIndex then begin
  726.       PageHide(OldPageIndex, Next);
  727.       PageShow(NewPageIndex, Next);
  728.       PageChanged;
  729.     end;
  730.   end;
  731. end;
  732.  
  733. procedure TPageManager.ChangePage(Next: Boolean);
  734. var
  735.   NewPageIndex: Integer;
  736. begin
  737.   if Next then begin
  738.     NewPageIndex := GetNextPageIndex(PageIndex);
  739.     HistoryCommand := hcForward;
  740.   end
  741.   else begin
  742.     NewPageIndex := GetPriorPageIndex(PageIndex);
  743.     HistoryCommand := hcBack;
  744.   end;
  745.   SetPage(NewPageIndex, Next);
  746. end;
  747.  
  748. type
  749.   THack = class(TWinControl);
  750.  
  751. procedure TPageManager.DormantPages;
  752. var
  753.   I: Integer;
  754. begin
  755.   if Assigned(FPageOwner) then
  756.     with PageOwner do begin
  757.       for I := 0 to Pages.Count - 1 do
  758.         if PageIndex <> I then
  759.           THack(Pages.Objects[I]).DestroyHandle;
  760.     end;
  761. end;
  762.  
  763. { TPageHistory }
  764.  
  765. constructor TPageHistory.Create;
  766. begin
  767.   inherited Create;
  768.   FCurrent := -1;
  769.   FHistoryCapacity := 10;
  770. end;
  771.  
  772. destructor TPageHistory.Destroy;
  773. begin
  774.   ResetHistory;
  775.   inherited Destroy;
  776. end;
  777.  
  778. procedure TPageHistory.SetCurrent(Value: Integer);
  779. begin
  780.   if Value < 0 then Value := -1;
  781.   if Value > Count - 1 then Value := Count - 1;
  782.   FCurrent := Value;
  783. end;
  784.  
  785. procedure TPageHistory.SetHistoryCapacity(Value: Integer);
  786. var
  787.   I: Integer;
  788. begin
  789.   if Value < FHistoryCapacity then begin
  790.     for I := 0 to Count - Value do begin
  791.       DeleteHistoryItem(0);
  792.     end;
  793.   end;
  794.   FHistoryCapacity := Value;
  795. end;
  796.  
  797. function TPageHistory.GetPageIndex(Index: Integer): Integer;
  798. begin
  799.   Result := TPageHistoryItem(Items[Index]).Index;
  800. end;
  801.  
  802. procedure TPageHistory.AddPageIndex(PageIndex: Integer);
  803. var
  804.   I: Integer;
  805.   Item: TPageHistoryItem;
  806. begin
  807.   for I := Count - 1 downto Current + 1 do begin
  808.     DeleteHistoryItem(I);
  809.   end;
  810.   for I := 0 to Count - HistoryCapacity do begin
  811.     DeleteHistoryItem(0);
  812.   end;
  813.   if Count < HistoryCapacity then begin
  814.     Item := TPageHistoryItem.Create;
  815.     Item.Index := PageIndex;
  816.     Add(Item);
  817.   end;
  818.   Current := Count - 1;
  819. end;
  820.  
  821. procedure TPageHistory.DeleteHistoryItem(Index: Integer);
  822. var
  823.   Item: TPageHistoryItem;
  824. begin
  825.   if (Index >= 0) and (Index < Count) then begin
  826.     Item := TPageHistoryItem(Items[Index]);
  827.     Delete(Index);
  828.     Item.Free;
  829.     if Current > Count - 1 then Current := Count - 1;
  830.   end;
  831. end;
  832.  
  833. procedure TPageHistory.ResetHistory;
  834. var
  835.   I: Integer;
  836. begin
  837.   for I := Count - 1 downto 0 do begin
  838.     DeleteHistoryItem(I);
  839.   end;
  840. end;
  841.  
  842. end.
  843.