lazarus/components/externhelp/externhelpfrm.pas
mattias 84ee7a6b32 externhelp: add, delete item
git-svn-id: trunk@23754 -
2010-02-21 18:32:07 +00:00

730 lines
18 KiB
ObjectPascal

unit ExternHelpFrm;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LCLProc, FileUtil, LResources, Forms, Controls, Graphics,
Dialogs, LazConfigStorage, ComCtrls, Buttons, StdCtrls, ExtCtrls,
PackageIntf, MacroIntf, IDEOptionsIntf, LazIDEIntf, BaseIDEIntf;
var
ExternHelpOptionID: integer = 2000;
ExternHelpOptionGeneralID: integer = 100;
resourcestring
EHGroupTitle = 'Extern help';
ehrsName = 'Name';
ehrsUnitFileOrUnitDirectory = 'Unit file or unit directory';
ehrsURL = 'URL';
ehrsHelp = 'Help';
ehrsAddNewItem = 'Add new item';
ehrsDeleteItem = 'Delete item';
ehrsBrowseForPath = 'Browse for path';
ehrsGeneral = 'General';
type
{ TExternHelpItem }
TExternHelpItem = class
private
FChangeStep: integer;
fChilds: TFPList;
FFilename: string;
FName: string;
FStoreIn: string;
FURL: string;
function GetChildCount: integer;
function GetChilds(Index: integer): TExternHelpItem;
procedure SetFilename(const AValue: string);
procedure SetName(const AValue: string);
procedure SetStoreIn(const AValue: string);
procedure SetURL(const AValue: string);
public
Parent: TExternHelpItem;
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure AddChild(Item: TExternHelpItem);
procedure MoveChild(FromPos, ToPos: integer);
procedure RemoveChild(Index: integer);
procedure DeleteChild(Index: integer);
procedure DeleteChild(Child: TExternHelpItem);
function IndexOf(Child: TExternHelpItem): integer;
function IsEqual(Item: TExternHelpItem; WithName: boolean): boolean;
procedure Assign(Src: TExternHelpItem; WithName: boolean);
procedure IncreaseChangeStep; virtual;
property Name: string read FName write SetName;
property Filename: string read FFilename write SetFilename;
property URL: string read FURL write SetURL;
property StoreIn: string read FStoreIn write SetStoreIn;
property ChildCount: integer read GetChildCount;
property Childs[Index: integer]: TExternHelpItem read GetChilds;
property ChangeStep: integer read FChangeStep;
end;
TExternHelpOptions = class;
{ TExternHelpRootItem }
TExternHelpRootItem = class(TExternHelpItem)
public
Owner: TExternHelpOptions;
procedure IncreaseChangeStep; override;
end;
{ TExternHelpOptions }
TExternHelpOptions = class(TAbstractIDEEnvironmentOptions)
private
FChangeStep: integer;
FFilename: string;
FLastSavedChangeStep: integer;
procedure SetFilename(const AValue: string);
public
RootItem: TExternHelpRootItem;
constructor Create;
destructor Destroy; override;
class function GetGroupCaption: string; override;
class function GetInstance: TAbstractIDEOptions; override;
function Load(Config: TConfigStorage): TModalResult; virtual;
function Save(Config: TConfigStorage): TModalResult; virtual;
function LoadFromFile(Filename: string): TModalResult; virtual;
function SaveToFile(Filename: string): TModalResult; virtual;
function Load: TModalResult; virtual;
function Save: TModalResult; virtual;
function GetFullFilename: string;
function IsEqual(Src: TExternHelpOptions): boolean;
procedure Assign(Src: TExternHelpOptions);
procedure IncreaseChangeStep;
property Filename: string read FFilename write SetFilename;
property ChangeStep: integer read FChangeStep;
property LastSavedChangeStep: integer read FLastSavedChangeStep;
end;
type
{ TExternHelpGeneralOptsFrame }
TExternHelpGeneralOptsFrame = class(TAbstractIDEOptionsEditor)
AddSpeedButton: TSpeedButton;
DeleteSpeedButton: TSpeedButton;
FileBrowseSpeedButton: TSpeedButton;
FilenameEdit: TEdit;
FilenameLabel: TLabel;
HelpBitBtn: TBitBtn;
ItemsTreeView: TTreeView;
NameEdit: TEdit;
NameLabel: TLabel;
Splitter1: TSplitter;
StoreComboBox: TComboBox;
StoreLabel: TLabel;
URLEdit: TEdit;
URLLabel: TLabel;
procedure AddSpeedButtonClick(Sender: TObject);
procedure DeleteSpeedButtonClick(Sender: TObject);
procedure FilenameEditEditingDone(Sender: TObject);
procedure ItemsTreeViewEdited(Sender: TObject; Node: TTreeNode;
var S: string);
procedure ItemsTreeViewEditing(Sender: TObject; Node: TTreeNode;
var AllowEdit: Boolean);
procedure ItemsTreeViewSelectionChanged(Sender: TObject);
procedure NameEditChange(Sender: TObject);
procedure NameEditEditingDone(Sender: TObject);
procedure URLEditEditingDone(Sender: TObject);
private
FOptions: TExternHelpOptions;
procedure FillItemsTreeView;
procedure NameChanged(TVNode: TTreeNode; var NewName: string;
UpdateTree, UpdateEdit: boolean);
procedure SelectionChanged;
function FindTVNode(NodeText: string): TTreeNode;
function CreateUniqueName(Prefix: string): string;
procedure FillStoreInCombobox;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
function GetTitle: String; override;
procedure ReadSettings(AOptions: TAbstractIDEOptions); override;
procedure Setup(ADialog: TAbstractOptionsEditorDialog); override;
class function SupportedOptionsClass: TAbstractIDEOptionsClass; override;
procedure WriteSettings(AOptions: TAbstractIDEOptions); override;
property Options: TExternHelpOptions read FOptions;
end;
var
ExternHelpOptions: TExternHelpOptions = nil;
procedure Register;
implementation
{$R *.lfm}
procedure Register;
begin
ExternHelpOptions:=TExternHelpOptions.Create;
ExternHelpOptionID:=RegisterIDEOptionsGroup(ExternHelpOptionID,TExternHelpOptions)^.Index;
ExternHelpOptionGeneralID:=RegisterIDEOptionsEditor(ExternHelpOptionID,
TExternHelpGeneralOptsFrame,ExternHelpOptionGeneralID)^.Index;
end;
{ TExternHelpOptions }
procedure TExternHelpOptions.SetFilename(const AValue: string);
begin
if FFilename=AValue then exit;
FFilename:=AValue;
end;
constructor TExternHelpOptions.Create;
begin
RootItem:=TExternHelpRootItem.Create;
RootItem.Owner:=Self;
Filename:='externhelp.xml';
end;
destructor TExternHelpOptions.Destroy;
begin
FreeAndNil(RootItem);
inherited Destroy;
end;
class function TExternHelpOptions.GetGroupCaption: string;
begin
Result:=EHGroupTitle;
end;
class function TExternHelpOptions.GetInstance: TAbstractIDEOptions;
begin
Result:=ExternHelpOptions;
end;
function TExternHelpOptions.Load(Config: TConfigStorage): TModalResult;
begin
Result:=mrOk;
end;
function TExternHelpOptions.Save(Config: TConfigStorage): TModalResult;
begin
Result:=mrOk;
end;
function TExternHelpOptions.LoadFromFile(Filename: string): TModalResult;
var
Config: TConfigStorage;
begin
Config:=GetIDEConfigStorage(Filename,true);
try
Result:=Load(Config);
finally
Config.Free;
end;
end;
function TExternHelpOptions.SaveToFile(Filename: string): TModalResult;
var
Config: TConfigStorage;
begin
Config:=GetIDEConfigStorage(Filename,false);
try
Result:=Save(Config);
finally
Config.Free;
end;
end;
function TExternHelpOptions.Load: TModalResult;
begin
Result:=LoadFromFile(Filename);
FLastSavedChangeStep:=ChangeStep;
end;
function TExternHelpOptions.Save: TModalResult;
var
FullFilename: String;
begin
FullFilename:=GetFullFilename;
if FileExistsUTF8(FullFilename)
and (FLastSavedChangeStep=ChangeStep) then
Result:=mrOK;
Result:=SaveToFile(Filename);
FLastSavedChangeStep:=ChangeStep;
end;
function TExternHelpOptions.GetFullFilename: string;
begin
Result:=Filename;
if FilenameIsAbsolute(Result) then exit;
Result:=AppendPathDelim(LazarusIDE.GetPrimaryConfigPath)+Result;
end;
function TExternHelpOptions.IsEqual(Src: TExternHelpOptions): boolean;
begin
Result:=RootItem.IsEqual(Src.RootItem,false);
end;
procedure TExternHelpOptions.Assign(Src: TExternHelpOptions);
begin
RootItem.Assign(Src.RootItem,false);
end;
procedure TExternHelpOptions.IncreaseChangeStep;
begin
if FChangeStep=high(FChangeStep) then
FChangeStep:=low(FChangeStep)
else
inc(FChangeStep);
end;
{ TExternHelpGeneralOptsFrame }
procedure TExternHelpGeneralOptsFrame.ItemsTreeViewEdited(Sender: TObject;
Node: TTreeNode; var S: string);
begin
NameChanged(Node,S,false,true);
end;
procedure TExternHelpGeneralOptsFrame.FilenameEditEditingDone(Sender: TObject);
var
s: String;
TVNode: TTreeNode;
Item: TExternHelpItem;
Msg: String;
Filename: String;
begin
s:=FilenameEdit.Text;
TVNode:=ItemsTreeView.Selected;
if (TVNode=nil) or (not (TObject(TVNode.Data) is TExternHelpItem)) then exit;
Item:=TExternHelpItem(TVNode.Data);
s:=Trim(s);
if s<>Item.Filename then begin
Filename:=s;
DoDirSeparators(Filename);
IDEMacros.SubstituteMacros(Filename);
Msg:='';
if (Filename<>'') and (Filename[length(Filename)]=PathDelim) then begin
if not DirPathExists(Filename) then
Msg:='Directory not found: '+Filename;
end else begin
if not FileExistsUTF8(Filename) then
Msg:='File not found: '+Filename;
end;
if Msg<>'' then begin
MessageDlg('Warning',Msg,mtWarning,[mbIgnore],0);
end;
Item.Filename:=s;
end;
end;
procedure TExternHelpGeneralOptsFrame.AddSpeedButtonClick(Sender: TObject);
var
SelTVNode: TTreeNode;
Item: TExternHelpItem;
TVNode: TTreeNode;
SelItem: TExternHelpItem;
begin
SelTVNode:=ItemsTreeView.Selected;
Item:=TExternHelpItem.Create;
Item.Name:=CreateUniqueName('Item');
if TObject(SelTVNode.Data) is TExternHelpItem then begin
// init with values of selected node
SelItem:=TExternHelpItem(SelTVNode.Data);
Item.Filename:=SelItem.Filename;
Item.URL:=SelItem.URL;
Item.StoreIn:=SelItem.StoreIn;
end;
TVNode:=ItemsTreeView.Items.AddObject(SelTVNode,Item.Name,Item);
ItemsTreeView.Selected:=TVNode;
end;
procedure TExternHelpGeneralOptsFrame.DeleteSpeedButtonClick(Sender: TObject);
var
SelTVNode: TTreeNode;
Item: TExternHelpItem;
begin
SelTVNode:=ItemsTreeView.Selected;
if (SelTVNode=nil) or (not (TObject(SelTVNode.Data) is TExternHelpItem)) then exit;
Item:=TExternHelpItem(SelTVNode.Data);
// select next
if SelTVNode.GetNext<>nil then
ItemsTreeView.Selected:=SelTVNode.GetNext
else
ItemsTreeView.Selected:=SelTVNode.GetPrev;
// delete in treeview
SelTVNode.Free;
// delete in Options
Item.Free;
end;
procedure TExternHelpGeneralOptsFrame.ItemsTreeViewEditing(Sender: TObject;
Node: TTreeNode; var AllowEdit: Boolean);
begin
end;
procedure TExternHelpGeneralOptsFrame.ItemsTreeViewSelectionChanged(
Sender: TObject);
begin
SelectionChanged;
end;
procedure TExternHelpGeneralOptsFrame.NameEditChange(Sender: TObject);
var
S: String;
begin
S:=NameEdit.Text;
NameChanged(ItemsTreeView.Selected,S,true,false);
end;
procedure TExternHelpGeneralOptsFrame.NameEditEditingDone(Sender: TObject);
var
S: String;
begin
S:=NameEdit.Text;
NameChanged(ItemsTreeView.Selected,S,true,true);
end;
procedure TExternHelpGeneralOptsFrame.URLEditEditingDone(Sender: TObject);
var
s: String;
TVNode: TTreeNode;
Item: TExternHelpItem;
begin
s:=URLEdit.Text;
TVNode:=ItemsTreeView.Selected;
if (TVNode=nil) or (not (TObject(TVNode.Data) is TExternHelpItem)) then exit;
Item:=TExternHelpItem(TVNode.Data);
s:=Trim(s);
if s<>Item.URL then begin
Item.URL:=s;
end;
end;
procedure TExternHelpGeneralOptsFrame.FillItemsTreeView;
procedure Add(ParentItem: TExternHelpItem; ParentTVNode: TTreeNode);
var
i: Integer;
Item: TExternHelpItem;
TVNode: TTreeNode;
begin
for i:=0 to ParentItem.ChildCount-1 do begin
Item:=ParentItem.Childs[i];
TVNode:=ItemsTreeView.Items.AddChildObject(ParentTVNode,Item.Name,Item);
Add(Item,TVNode);
TVNode.Expanded:=true;
end;
end;
begin
ItemsTreeView.BeginUpdate;
ItemsTreeView.Items.Clear;
Add(Options.RootItem,nil);
ItemsTreeView.EndUpdate;
end;
procedure TExternHelpGeneralOptsFrame.NameChanged(TVNode: TTreeNode;
var NewName: string; UpdateTree, UpdateEdit: boolean);
var
Item: TExternHelpItem;
begin
NewName:=Trim(NewName);
if TObject(TVNode.Data) is TExternHelpItem then begin
Item:=TExternHelpItem(TVNode.Data);
Item.Name:=NewName;
if UpdateTree then
TVNode.Text:=NewName;
if UpdateEdit then
NameEdit.Text:=NewName;
end;
end;
procedure TExternHelpGeneralOptsFrame.SelectionChanged;
var
TVNode: TTreeNode;
Item: TExternHelpItem;
begin
TVNode:=ItemsTreeView.Selected;
Item:=nil;
if (TVNode<>nil) and (TObject(TVNode.Data) is TExternHelpItem) then
Item:=TExternHelpItem(TVNode.Data);
DisableAlign;
if Item<>nil then begin
NameEdit.Enabled:=true;
NameEdit.Text:=Item.Name;
FilenameEdit.Enabled:=true;
FilenameEdit.Text:=Item.Filename;
URLEdit.Enabled:=true;
URLEdit.Text:=Item.URL;
StoreComboBox.Enabled:=Item.Parent=Options.RootItem;
StoreComboBox.Text:=Item.StoreIn;
end else begin
NameEdit.Enabled:=false;
NameEdit.Text:='';
FilenameEdit.Enabled:=false;
FilenameEdit.Text:='';
URLEdit.Enabled:=false;
URLEdit.Text:='';
StoreComboBox.Enabled:=false;
StoreComboBox.Text:='';
end;
end;
function TExternHelpGeneralOptsFrame.FindTVNode(NodeText: string): TTreeNode;
begin
Result:=ItemsTreeView.Items.GetFirstNode;
while (Result<>nil) and (SysUtils.CompareText(Result.Text,NodeText)<>0) do
Result:=Result.GetNext;
end;
function TExternHelpGeneralOptsFrame.CreateUniqueName(Prefix: string): string;
var
i: Integer;
begin
i:=0;
repeat
inc(i);
Result:=Prefix+IntToStr(i);
until FindTVNode(Result)=nil;
end;
procedure TExternHelpGeneralOptsFrame.FillStoreInCombobox;
var
sl: TStringList;
begin
sl:=TStringList.Create;
try
sl.Sort;
sl.Insert(0,'My settings');
StoreComboBox.Items.Assign(sl);
finally
sl.Free;
end;
end;
constructor TExternHelpGeneralOptsFrame.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
FOptions:=TExternHelpOptions.Create;
end;
destructor TExternHelpGeneralOptsFrame.Destroy;
begin
FreeAndNil(FOptions);
inherited Destroy;
end;
function TExternHelpGeneralOptsFrame.GetTitle: String;
begin
Result:=ehrsGeneral;
end;
procedure TExternHelpGeneralOptsFrame.ReadSettings(AOptions: TAbstractIDEOptions);
var
Opts: TExternHelpOptions;
begin
if AOptions is TExternHelpOptions then begin
Opts:=TExternHelpOptions(AOptions);
Options.Assign(Opts);
FillItemsTreeView;
ItemsTreeView.Selected:=ItemsTreeView.Items.GetFirstNode;
end;
end;
procedure TExternHelpGeneralOptsFrame.Setup(ADialog: TAbstractOptionsEditorDialog);
begin
NameLabel.Caption:=ehrsName;
FilenameLabel.Caption:=ehrsUnitFileOrUnitDirectory;
URLLabel.Caption:=ehrsURL;
HelpBitBtn.Caption:=ehrsHelp;
AddSpeedButton.Hint:=ehrsAddNewItem;
DeleteSpeedButton.Hint:=ehrsDeleteItem;
FileBrowseSpeedButton.Hint:=ehrsBrowseForPath;
end;
class function TExternHelpGeneralOptsFrame.SupportedOptionsClass: TAbstractIDEOptionsClass;
begin
Result:=TExternHelpOptions;
end;
procedure TExternHelpGeneralOptsFrame.WriteSettings(AOptions: TAbstractIDEOptions);
var
Opts: TExternHelpOptions;
begin
if AOptions is TExternHelpOptions then begin
Opts:=TExternHelpOptions(AOptions);
Opts.Assign(Options);
end;
end;
{ TExternHelpItem }
function TExternHelpItem.GetChildCount: integer;
begin
Result:=fChilds.Count;
end;
function TExternHelpItem.GetChilds(Index: integer): TExternHelpItem;
begin
Result:=TExternHelpItem(fChilds[Index]);
end;
procedure TExternHelpItem.SetFilename(const AValue: string);
begin
if FFilename=AValue then exit;
FFilename:=AValue;
IncreaseChangeStep;
end;
procedure TExternHelpItem.SetName(const AValue: string);
begin
if FName=AValue then exit;
FName:=AValue;
IncreaseChangeStep;
end;
procedure TExternHelpItem.SetStoreIn(const AValue: string);
begin
if FStoreIn=AValue then exit;
FStoreIn:=AValue;
IncreaseChangeStep;
end;
procedure TExternHelpItem.SetURL(const AValue: string);
begin
if FURL=AValue then exit;
FURL:=AValue;
IncreaseChangeStep;
end;
constructor TExternHelpItem.Create;
begin
fChilds:=TFPList.Create;
end;
destructor TExternHelpItem.Destroy;
begin
if Parent<>nil then
Parent.RemoveChild(Parent.IndexOf(Self));
Clear;
FreeAndNil(fChilds);
inherited Destroy;
end;
procedure TExternHelpItem.Clear;
var
i: Integer;
Child: TExternHelpItem;
begin
if (ChildCount=0) and (URL='') and (Filename='') and (StoreIn='') then exit;
for i:=fChilds.Count-1 downto 0 do begin
Child:=Childs[i];
Child.Parent:=nil;
Child.Free;
end;
fChilds.Clear;
fURL:='';
FFilename:='';
FStoreIn:='';
IncreaseChangeStep;
end;
procedure TExternHelpItem.AddChild(Item: TExternHelpItem);
begin
Item.Parent:=Self;
fChilds.Add(Item);
IncreaseChangeStep;
end;
procedure TExternHelpItem.MoveChild(FromPos, ToPos: integer);
begin
if FromPos=ToPos then exit;
fChilds.Move(FromPos,ToPos);
IncreaseChangeStep;
end;
procedure TExternHelpItem.RemoveChild(Index: integer);
begin
Childs[Index].Parent:=nil;
fChilds.Delete(Index);
IncreaseChangeStep;
end;
procedure TExternHelpItem.DeleteChild(Index: integer);
begin
Childs[Index].Free;
end;
procedure TExternHelpItem.DeleteChild(Child: TExternHelpItem);
begin
Child.Free;
end;
function TExternHelpItem.IndexOf(Child: TExternHelpItem): integer;
begin
Result:=fChilds.IndexOf(Child);
end;
function TExternHelpItem.IsEqual(Item: TExternHelpItem; WithName: boolean
): boolean;
var
i: Integer;
begin
Result:=((not WithName) or (Name=Item.Name))
and (Filename=Item.Filename)
and (URL=Item.URL)
and (StoreIn=Item.StoreIn)
and (ChildCount=Item.ChildCount);
if Result then begin
for i:=0 to ChildCount-1 do
if not (Childs[i].IsEqual(Item.Childs[i],true)) then exit(false);
end;
end;
procedure TExternHelpItem.Assign(Src: TExternHelpItem; WithName: boolean);
var
i: Integer;
Item: TExternHelpItem;
begin
if WithName then Name:=Src.Name;
Filename:=Src.Filename;
URL:=Src.URL;
StoreIn:=Src.StoreIn;
for i:=0 to Src.ChildCount-1 do begin
if ChildCount<=i then begin
Item:=TExternHelpItem.Create;
AddChild(Item);
end else begin
Item:=Childs[i];
end;
Item.Assign(Src.Childs[i],true);
end;
while ChildCount>Src.ChildCount do DeleteChild(ChildCount-1);
end;
procedure TExternHelpItem.IncreaseChangeStep;
begin
if Parent<>nil then Parent.IncreaseChangeStep;
if FChangeStep=High(FChangeStep) then
FChangeStep:=low(FChangeStep)
else
inc(FChangeStep);
end;
{ TExternHelpRootItem }
procedure TExternHelpRootItem.IncreaseChangeStep;
begin
inherited IncreaseChangeStep;
Owner.IncreaseChangeStep;
end;
finalization
FreeAndNil(ExternHelpOptions);
end.