lasarus_compotents/RXLib/rxcontrols/rxhistorynavigator.pas

464 lines
11 KiB
ObjectPascal

{ RxHistoryNavigator unit
Copyright (C) 2005-2017 Lagunov Aleksey alexs75@yandex.ru and Lazarus team
original conception from rx library for Delphi (c)
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version with the following modification:
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent modules,and
to copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the terms
and conditions of the license of that module. An independent module is a
module which is not derived from or based on this library. If you modify
this library, you may extend this exception to your version of the library,
but you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
for more details.
You should have received a copy of the GNU Library General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
}
unit RxHistoryNavigator;
{$I rx.inc}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, rxtoolbar,
Menus;
type
PNavigateRec = ^TNavigateRec;
TNavigateRec = record
Name:string;
Cond:string;
Next:PNavigateRec;
end;
type
TRxHistoryNavigator = class;
THistoryNavigateEvent = procedure(Sender:TRxHistoryNavigator; AInfo:string; AProcessed:boolean) of object;
{ TRxHistoryNavigator }
TRxHistoryNavigator = class(TComponent)
private
FForwardBtnItem:TToolbarItem;
FForwardBtn: string;
FBackBtnItem:TToolbarItem;
FBackBtn: string;
First:PNavigateRec;
Curr:PNavigateRec;
FMaxPopupItems: integer;
FOnHistoryNavigate: THistoryNavigateEvent;
FToolPanel: TToolPanel;
PMBack:TPopupMenu;
PMForw:TPopupMenu;
function GetBackBtn: string;
function GetForwardBtn: string;
procedure SetBackBtn(AValue: string);
procedure SetForwardBtn(AValue: string);
procedure SetToolPanel(AValue: TToolPanel);
procedure ClearFromCurrent(var C:PNavigateRec);
procedure CreateBackMenu;
procedure CreateRetrMenu;
function Last:PNavigateRec;
function Prior(R:PNavigateRec):PNavigateRec;
procedure CheckTop;
procedure CheckBottom;
procedure EnableAction(ActName:byte; Enable:boolean);
procedure BackProc(Sender: TObject);
procedure ForwardProc(Sender: TObject);
procedure DoSetItems;
protected
function Navigate(ToTop:boolean; Count:integer):boolean;
procedure Loaded; override;
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure ClearHistory;
procedure AddToHistory(AHistoryCaption, AInfo:string);
published
property ToolPanel: TToolPanel read FToolPanel write SetToolPanel;
property BackBtn:string read GetBackBtn write SetBackBtn;
property ForwardBtn:string read GetForwardBtn write SetForwardBtn;
property OnHistoryNavigate:THistoryNavigateEvent read FOnHistoryNavigate write FOnHistoryNavigate;
property MaxPopupItems:integer read FMaxPopupItems write FMaxPopupItems default 10;
end;
implementation
uses ActnList, rxconst;
{ TRxHistoryNavigator }
procedure TRxHistoryNavigator.SetToolPanel(AValue: TToolPanel);
begin
if FToolPanel=AValue then Exit;
FToolPanel:=AValue;
end;
procedure TRxHistoryNavigator.ClearFromCurrent(var C: PNavigateRec);
var
R:PNavigateRec;
begin
while C<>nil do
begin
R:=C;
C:=C^.Next;
Dispose(R);
end;
end;
procedure TRxHistoryNavigator.CreateRetrMenu;
var i:integer;
S:PNavigateRec;
Item:TMenuItem;
begin
if Curr=nil then exit;
PMForw.Items.Clear;
i:=0;
S:=Curr^.Next;
while (i<FMaxPopupItems) and (S<>nil) do
begin
Item := TMenuItem.Create(Self);
Item.Caption := S^.Name;
Item.OnClick := @ForwardProc;
Item.Hint:=Format(sHistoryDesc, [S^.Cond]);
Item.Tag:=i;
PMForw.Items.Add(Item);
inc(i);
S:=S^.Next;
end;
end;
function TRxHistoryNavigator.Last: PNavigateRec;
begin
if First=nil then Result:=nil
else
begin
Result:=First;
while Result^.Next<>nil do Result:=Result^.Next;
end;
end;
function TRxHistoryNavigator.Prior(R: PNavigateRec): PNavigateRec;
var
L:PNavigateRec;
begin
if First=nil then Result:=nil
else
begin
L:=First;
while (L^.Next<>nil) and (L^.Next<>R) do
begin
L:=L^.Next;
end;
if L^.Next=nil then Result:=nil else Result:=l;
end;
end;
procedure TRxHistoryNavigator.CheckTop;
begin
EnableAction(0, (Curr<>nil) and (Curr<>First));
end;
procedure TRxHistoryNavigator.CheckBottom;
begin
EnableAction(1, (Curr<>nil) and (Curr^.Next<>nil));
end;
procedure TRxHistoryNavigator.EnableAction(ActName: byte; Enable: boolean);
begin
if First=nil then Enable:=false;
if ActName = 0 then
begin
if Assigned(FBackBtnItem) then
(FBackBtnItem.Action as TAction).Enabled:=Enable
end
else
if Assigned(FForwardBtnItem) then
(FForwardBtnItem.Action as TAction).Enabled:=Enable
end;
procedure TRxHistoryNavigator.BackProc(Sender: TObject);
begin
Navigate(true, (Sender as TComponent).Tag);
end;
procedure TRxHistoryNavigator.ForwardProc(Sender: TObject);
begin
Navigate(false, (Sender as TComponent).Tag);
end;
procedure TRxHistoryNavigator.DoSetItems;
begin
if Assigned(FToolPanel) then
begin
FForwardBtnItem:=FToolPanel.Items.ByActionName[FForwardBtn];
if Assigned(FForwardBtnItem) then
begin
FForwardBtnItem.DropDownMenu:=PMForw;
FForwardBtnItem.Action.OnExecute:=@ForwardProc;
end;
FBackBtnItem:=FToolPanel.Items.ByActionName[FBackBtn];
if Assigned(FBackBtnItem) then
begin
FBackBtnItem.DropDownMenu:=PMBack;
FBackBtnItem.Action.OnExecute:=@BackProc;
end;
end;
end;
function TRxHistoryNavigator.Navigate(ToTop: boolean; Count: integer): boolean;
var
F:boolean;
Condit: string;
begin
Result:=false;
if First=nil then exit;
if ToTop then
begin
inc(Count);
repeat
Curr:=Prior(Curr);
if Curr=nil then Curr:=First;
Dec(Count);
until (Count=0) or (Curr=First);
Result:=true;
Condit:=Curr^.Cond;
CreateBackMenu;
CreateRetrMenu;
end
else
begin
inc(Count);
repeat
if Curr^.Next<>nil then Curr:=Curr^.Next;
Dec(Count);
until (Count=0) or (Curr^.Next=nil);
Result:=true;
Condit:=Curr^.Cond;
CreateRetrMenu;
CreateBackMenu;
end;
CheckTop;
CheckBottom;
F:=true;
if Assigned(FOnHistoryNavigate) and Assigned(Curr) then
FOnHistoryNavigate(Self, Condit, F);
end;
procedure TRxHistoryNavigator.Loaded;
begin
inherited Loaded;
DoSetItems;
CheckTop;
CheckBottom;
end;
procedure TRxHistoryNavigator.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if Operation = opRemove then
begin
if AComponent = FToolPanel then
begin
if Assigned(FForwardBtnItem) then
begin
FForwardBtnItem.Action.OnExecute:=nil;
FForwardBtnItem:=nil;
end;
if Assigned(FBackBtnItem) then
begin
FBackBtnItem.Action.OnExecute:=nil;
FBackBtnItem:=nil;
end;
end
else
if AComponent = Self then
begin
if Assigned(FForwardBtnItem) then
begin
FForwardBtnItem.Action.OnExecute:=nil;
FForwardBtnItem.DropDownMenu:=nil;
FForwardBtnItem:=nil;
end;
if Assigned(FBackBtnItem) then
begin
FBackBtnItem.Action.OnExecute:=nil;
FBackBtnItem.DropDownMenu:=nil;
FBackBtnItem:=nil;
end;
end;
end;
end;
procedure TRxHistoryNavigator.CreateBackMenu;
var i:integer;
S:PNavigateRec;
Item:TMenuItem;
begin
if Curr=nil then exit;
PMBack.Items.Clear;
i:=0;
S:=Curr;
while (i<FMaxPopupItems) and (S<>First) do
begin
Item := TMenuItem.Create(Self);
Item.Caption := S^.Name;
Item.OnClick := @BackProc;
Item.Hint:=Format(sHistoryDesc, [S^.Cond]);
Item.Tag:=i;
PMBack.Items.Add(Item);
inc(i);
S:=Prior(S);
end;
end;
constructor TRxHistoryNavigator.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
PMBack:=TPopupMenu.Create(Self);
PMBack.Parent:=Self;
PMForw:=TPopupMenu.Create(Self);
PMForw.Parent:=Self;
FMaxPopupItems:=10;
end;
destructor TRxHistoryNavigator.Destroy;
begin
Curr:=nil;
ClearFromCurrent(First);
inherited Destroy;
end;
procedure TRxHistoryNavigator.ClearHistory;
begin
end;
procedure TRxHistoryNavigator.AddToHistory(AHistoryCaption, AInfo: string);
var
R, L:PNavigateRec;
begin
New(R);
FillChar(R^, SizeOf(TNavigateRec), 0);
R^.Name:=AHistoryCaption;
R^.Cond:=AInfo;
if First<>nil then
begin
L:=Last;
if Curr<>L then ClearFromCurrent(Curr^.Next);
Curr^.Next:=R;
Curr:=R;
end
else
begin
First:=R;
Curr:=R;
end;
CreateBackMenu;
CreateRetrMenu;
CheckTop;
CheckBottom;
end;
procedure TRxHistoryNavigator.SetBackBtn(AValue: string);
begin
if FBackBtn=AValue then Exit;
if ForwardBtn = AValue then
ForwardBtn:='';
FBackBtn:=AValue;
if Assigned(FBackBtnItem) then
begin
FBackBtnItem.DropDownMenu:=nil;
FBackBtnItem.Action.OnExecute:=nil;
end;
if Assigned(FToolPanel) and (FBackBtn<>'') then
begin
FBackBtnItem:=FToolPanel.Items.ByActionName[FBackBtn];
if Assigned(FBackBtnItem) then
begin
FBackBtnItem.DropDownMenu:=PMBack;
FBackBtnItem.Action.OnExecute:=@BackProc;
end;
end
else
FBackBtnItem:=nil;
end;
function TRxHistoryNavigator.GetBackBtn: string;
begin
if Assigned(FBackBtnItem) then
Result:=FBackBtnItem.Action.Name
else
Result:=FBackBtn;
end;
function TRxHistoryNavigator.GetForwardBtn: string;
begin
if Assigned(FForwardBtnItem) then
Result:=FForwardBtnItem.Action.Name
else
Result:=FForwardBtn;
end;
procedure TRxHistoryNavigator.SetForwardBtn(AValue: string);
begin
if FForwardBtn=AValue then Exit;
if BackBtn = AValue then
BackBtn:='';
FForwardBtn:=AValue;
if Assigned(FForwardBtnItem) then
begin
FForwardBtnItem.DropDownMenu:=nil;
FForwardBtnItem.Action.OnExecute:=nil;
end;
if Assigned(FToolPanel) and (AValue <>'') then
begin
FForwardBtnItem:=FToolPanel.Items.ByActionName[FForwardBtn];
if Assigned(FForwardBtnItem) then
begin
FForwardBtnItem.DropDownMenu:=PMForw;
FForwardBtnItem.Action.OnExecute:=@ForwardProc;
end;
end
else
FForwardBtnItem:=nil;
end;
end.