* Implement option to keep current editor in sync with filetree

This commit is contained in:
Michaël Van Canneyt 2024-08-03 15:06:44 +02:00
parent df8ab730bb
commit 1cae4b5382
5 changed files with 115 additions and 8 deletions

View File

@ -5,7 +5,7 @@ unit ctrlfilebrowser;
interface interface
uses uses
Classes, SysUtils, frmFileBrowser, forms, filebrowsertypes, Classes, SysUtils, frmFileBrowser, forms, filebrowsertypes, SrcEditorIntf,
LazIDEIntf, MenuIntf, IDECommands, ProjectIntf, IDEOptEditorIntf, IDEWindowIntf, BaseIDEIntf; LazIDEIntf, MenuIntf, IDECommands, ProjectIntf, IDEOptEditorIntf, IDEWindowIntf, BaseIDEIntf;
Type Type
@ -22,7 +22,9 @@ Type
FCustomRootDir : string; FCustomRootDir : string;
FNeedSave: Boolean; FNeedSave: Boolean;
FSplitterPos: integer; FSplitterPos: integer;
FCurrentEditorFile : String;
FSyncCurrentEditor: Boolean;
procedure ActiveEditorChanged(Sender: TObject);
function DoProjectChanged(Sender: TObject; AProject: TLazProject): TModalResult; function DoProjectChanged(Sender: TObject; AProject: TLazProject): TModalResult;
procedure DoSelectDir(Sender: TObject); procedure DoSelectDir(Sender: TObject);
function GetProjectDir: String; function GetProjectDir: String;
@ -36,6 +38,7 @@ Type
procedure SetRoootDir(AValue: TRootDir); procedure SetRoootDir(AValue: TRootDir);
procedure SetSplitterPos(AValue: integer); procedure SetSplitterPos(AValue: integer);
procedure SetStartDir(AValue: TStartDir); procedure SetStartDir(AValue: TStartDir);
procedure SetSyncCurrentEditor(AValue: Boolean);
procedure WriteConfig; virtual; procedure WriteConfig; virtual;
procedure OnFormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction); procedure OnFormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
protected protected
@ -43,6 +46,7 @@ Type
procedure DoOpenFile(Sender: TObject; const AFileName: string); virtual; procedure DoOpenFile(Sender: TObject; const AFileName: string); virtual;
{ Called by file browser window } { Called by file browser window }
procedure DoConfig(Sender: TObject); procedure DoConfig(Sender: TObject);
procedure SyncCurrentFile;
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
destructor Destroy; override; destructor Destroy; override;
@ -55,7 +59,7 @@ Type
property CustomStartDir: string read FCustomStartDir write SetCustomStartDir; property CustomStartDir: string read FCustomStartDir write SetCustomStartDir;
property CustomRootDir: string read FCustomRootDir write SetCustomRootDir; property CustomRootDir: string read FCustomRootDir write SetCustomRootDir;
property LastOpenedDir: string read FLastOpenedDir write SetLastOpenedDir; property LastOpenedDir: string read FLastOpenedDir write SetLastOpenedDir;
property SyncCurrentEditor : Boolean Read FSyncCurrentEditor Write SetSyncCurrentEditor;
property SplitterPos: integer read FSplitterPos write SetSplitterPos; property SplitterPos: integer read FSplitterPos write SetSplitterPos;
Property FilesInTree : Boolean Read FFilesInTree Write SetFilesInTree; Property FilesInTree : Boolean Read FFilesInTree Write SetFilesInTree;
Property DirectoriesBeforeFiles : Boolean Read FDirectoriesBeforeFiles Write SetDirectoriesBeforeFiles; Property DirectoriesBeforeFiles : Boolean Read FDirectoriesBeforeFiles Write SetDirectoriesBeforeFiles;
@ -83,6 +87,7 @@ begin
FSplitterPos:=GetValue(KeySplitterPos, DefaultSplitterPos); FSplitterPos:=GetValue(KeySplitterPos, DefaultSplitterPos);
FFilesInTree:=GetValue(KeyFilesInTree, DefaultFilesInTree); FFilesInTree:=GetValue(KeyFilesInTree, DefaultFilesInTree);
FDirectoriesBeforeFiles:=GetValue(KeyDirectoriesBeforeFiles,DefaultDirectoriesBeforeFiles); FDirectoriesBeforeFiles:=GetValue(KeyDirectoriesBeforeFiles,DefaultDirectoriesBeforeFiles);
FSyncCurrentEditor:=GetValue(KeySyncCurrentEditor,DefaultSyncCurrentEditor);
finally finally
Free; Free;
end; end;
@ -145,6 +150,15 @@ begin
FNeedSave:=True; FNeedSave:=True;
end; end;
procedure TFileBrowserController.SetSyncCurrentEditor(AValue: Boolean);
begin
if FSyncCurrentEditor=AValue then Exit;
FSyncCurrentEditor:=AValue;
FNeedSave:=True;
if aValue and (FCurrentEditorFile<>'') then
SyncCurrentFile;
end;
procedure TFileBrowserController.WriteConfig; procedure TFileBrowserController.WriteConfig;
var var
Storage : TConfigStorage; Storage : TConfigStorage;
@ -159,6 +173,7 @@ begin
SetDeleteValue(KeySplitterPos, FSplitterPos, DefaultSplitterPos); SetDeleteValue(KeySplitterPos, FSplitterPos, DefaultSplitterPos);
SetDeleteValue(KeyFilesInTree, FFilesInTree, DefaultFilesInTree); SetDeleteValue(KeyFilesInTree, FFilesInTree, DefaultFilesInTree);
SetDeleteValue(KeyDirectoriesBeforeFiles, FDirectoriesBeforeFiles, DefaultDirectoriesBeforeFiles); SetDeleteValue(KeyDirectoriesBeforeFiles, FDirectoriesBeforeFiles, DefaultDirectoriesBeforeFiles);
SetDeleteValue(KeySyncCurrentEditor,FSyncCurrentEditor, DefaultSyncCurrentEditor);
FNeedSave := False; FNeedSave := False;
finally finally
Free; Free;
@ -180,6 +195,8 @@ begin
aForm.CurrentDirectory := GetResolvedStartDir; aForm.CurrentDirectory := GetResolvedStartDir;
aForm.FilesInTree:=FilesInTree; aForm.FilesInTree:=FilesInTree;
aForm.DirectoriesBeforeFiles:=DirectoriesBeforeFiles; aForm.DirectoriesBeforeFiles:=DirectoriesBeforeFiles;
if FCurrentEditorFile<>'' then
SyncCurrentFile;
end; end;
function TFileBrowserController.GetProjectDir : String; function TFileBrowserController.GetProjectDir : String;
@ -249,6 +266,24 @@ begin
end; end;
procedure TFileBrowserController.ActiveEditorChanged(Sender: TObject);
begin
if not Assigned(SourceEditorManagerIntf.ActiveEditor) then
exit;
FCurrentEditorFile:=SourceEditorManagerIntf.ActiveEditor.FileName;
SyncCurrentFile;
end;
procedure TFileBrowserController.SyncCurrentFile;
begin
if Not (Assigned(FileBrowserForm) and SyncCurrentEditor) then
exit;
FileBrowserForm.CurrentFile:=FCurrentEditorFile
end;
procedure TFileBrowserController.DoConfig(Sender: TObject); procedure TFileBrowserController.DoConfig(Sender: TObject);
begin begin
// Maybe later some reconfiguration of FWindow is needed after ShowConfig ? // Maybe later some reconfiguration of FWindow is needed after ShowConfig ?
@ -260,6 +295,7 @@ constructor TFileBrowserController.Create(AOwner: TComponent);
begin begin
inherited Create(AOwner); inherited Create(AOwner);
LazarusIDE.AddHandlerOnProjectOpened(@DoProjectChanged); LazarusIDE.AddHandlerOnProjectOpened(@DoProjectChanged);
SourceEditorManagerIntf.RegisterChangeEvent(semEditorActivate,@ActiveEditorChanged);
FDirectoriesBeforeFiles:=DefaultDirectoriesBeforeFiles; FDirectoriesBeforeFiles:=DefaultDirectoriesBeforeFiles;
FFilesInTree:=DefaultFilesInTree; FFilesInTree:=DefaultFilesInTree;
ReadConfig; ReadConfig;
@ -267,6 +303,7 @@ end;
destructor TFileBrowserController.Destroy; destructor TFileBrowserController.Destroy;
begin begin
LazarusIDE.RemoveAllHandlersOfObject(Self);
if FNeedSave then if FNeedSave then
WriteConfig; WriteConfig;
inherited; inherited;

View File

@ -89,6 +89,7 @@ const
DefaultRootDir = sdProjectDir; DefaultRootDir = sdProjectDir;
DefaultFilesInTree = False; DefaultFilesInTree = False;
DefaultDirectoriesBeforeFiles = True; DefaultDirectoriesBeforeFiles = True;
DefaultSyncCurrentEditor = False;
DefaultSplitterPos = 150; DefaultSplitterPos = 150;
SConfigFile = 'idebrowserwin.xml'; SConfigFile = 'idebrowserwin.xml';
@ -99,6 +100,7 @@ const
KeySplitterPos = 'SplitterPos'; KeySplitterPos = 'SplitterPos';
KeyFilesInTree = 'FilesInTree'; KeyFilesInTree = 'FilesInTree';
KeyDirectoriesBeforeFiles = 'DirectoriesBeforeFiles'; KeyDirectoriesBeforeFiles = 'DirectoriesBeforeFiles';
KeySyncCurrentEditor = 'SyncCurrentEditor';
resourcestring resourcestring
SFileBrowserIDEMenuCaption = 'File Browser'; SFileBrowserIDEMenuCaption = 'File Browser';

View File

@ -1,13 +1,13 @@
object FileBrowserOptionsFrame: TFileBrowserOptionsFrame object FileBrowserOptionsFrame: TFileBrowserOptionsFrame
Left = 0 Left = 0
Height = 430 Height = 456
Top = 0 Top = 0
Width = 803 Width = 803
ClientHeight = 430 ClientHeight = 456
ClientWidth = 803 ClientWidth = 803
TabOrder = 0 TabOrder = 0
DesignLeft = 413 DesignLeft = 828
DesignTop = 362 DesignTop = 271
object GBStartDir1: TGroupBox object GBStartDir1: TGroupBox
Left = 0 Left = 0
Height = 191 Height = 191
@ -124,11 +124,26 @@ object FileBrowserOptionsFrame: TFileBrowserOptionsFrame
OnChange = CBShowFilesInlineChange OnChange = CBShowFilesInlineChange
end end
object CBShowDirectoriesBeforeFiles: TCheckBox object CBShowDirectoriesBeforeFiles: TCheckBox
AnchorSideTop.Control = CBShowFilesInline
AnchorSideTop.Side = asrBottom
Left = 52 Left = 52
Height = 23 Height = 23
Top = 376 Top = 386
Width = 191 Width = 191
BorderSpacing.Top = 8
Caption = 'Show files in main tree view' Caption = 'Show files in main tree view'
TabOrder = 3 TabOrder = 3
end end
object CBSyncCurrentEditor: TCheckBox
AnchorSideLeft.Control = CBShowFilesInline
AnchorSideTop.Control = CBShowDirectoriesBeforeFiles
AnchorSideTop.Side = asrBottom
Left = 24
Height = 23
Top = 417
Width = 277
BorderSpacing.Top = 8
Caption = 'Keep synchronized with current editor file'
TabOrder = 4
end
end end

View File

@ -17,6 +17,7 @@ type
TFileBrowserOptionsFrame = class(TAbstractIDEOptionsEditor) TFileBrowserOptionsFrame = class(TAbstractIDEOptionsEditor)
CBShowFilesInline: TCheckBox; CBShowFilesInline: TCheckBox;
CBShowDirectoriesBeforeFiles: TCheckBox; CBShowDirectoriesBeforeFiles: TCheckBox;
CBSyncCurrentEditor: TCheckBox;
DEStartDir: TDirectoryEdit; DEStartDir: TDirectoryEdit;
DERootDir: TDirectoryEdit; DERootDir: TDirectoryEdit;
GBStartDir: TGroupBox; GBStartDir: TGroupBox;
@ -98,6 +99,7 @@ begin
RB.Checked := True; RB.Checked := True;
CBShowFilesInline.Checked:=C.FilesInTree; CBShowFilesInline.Checked:=C.FilesInTree;
CBShowDirectoriesBeforeFiles.Checked:=C.DirectoriesBeforeFiles; CBShowDirectoriesBeforeFiles.Checked:=C.DirectoriesBeforeFiles;
CBSyncCurrentEditor.Checked:=C.SyncCurrentEditor;
CheckDirsBeforeFiles; CheckDirsBeforeFiles;
end; end;
@ -137,6 +139,7 @@ begin
else else
C.CustomStartDir:=''; C.CustomStartDir:='';
C.FilesInTree:=CBShowFilesInline.Checked; C.FilesInTree:=CBShowFilesInline.Checked;
C.SyncCurrentEditor:=CBSyncCurrentEditor.Checked;
end; end;
class function TFileBrowserOptionsFrame.SupportedOptionsClass: TAbstractIDEOptionsClass; class function TFileBrowserOptionsFrame.SupportedOptionsClass: TAbstractIDEOptionsClass;

View File

@ -63,8 +63,10 @@ type
procedure ConfigNode(aNode: TTreeNode; aEntry: TFileSystemEntry); procedure ConfigNode(aNode: TTreeNode; aEntry: TFileSystemEntry);
function FindNode(aNodePath: String): TTreeNode; function FindNode(aNodePath: String): TTreeNode;
function GetAbsolutePath(Node: TTreeNode): string; function GetAbsolutePath(Node: TTreeNode): string;
function GetCurrentFile: string;
function GetTreeFileMask: String; function GetTreeFileMask: String;
function NodeToEntry(aNode: TTreeNode): TFileSystemEntry; function NodeToEntry(aNode: TTreeNode): TFileSystemEntry;
procedure SetCurrentFile(AValue: string);
procedure SetDir(const Value: string); procedure SetDir(const Value: string);
procedure SetDirectoriesBeforeFiles(AValue: Boolean); procedure SetDirectoriesBeforeFiles(AValue: Boolean);
procedure SetFilesIntree(AValue: Boolean); procedure SetFilesIntree(AValue: Boolean);
@ -82,6 +84,8 @@ type
{ return the selected directory } { return the selected directory }
function SelectedDir: string; function SelectedDir: string;
{ The selected/opened directory } { The selected/opened directory }
property CurrentFile: string read GetCurrentFile write SetCurrentFile;
{ The selected/opened directory }
property CurrentDirectory: string read FCurrentDir write SetDir; property CurrentDirectory: string read FCurrentDir write SetDir;
{ Directory the treeview starts from } { Directory the treeview starts from }
property RootDirectory: string read FRootDir write SetRootDir; property RootDirectory: string read FRootDir write SetRootDir;
@ -316,6 +320,28 @@ begin
end; end;
end; end;
function TFileBrowserForm.GetCurrentFile: string;
var
N : TTreeNode;
E : TFileSystemEntry;
begin
Result:='';
if FilesInTree then
begin
N:=TV.Selected;
if Assigned(N) then
E:=NodeToEntry(N);
if Assigned(E) and (E.EntryType=etFile) then
Result:=E.AbsolutePath;
end
else
With FileListBox do
if FileName<>'' then
Result:=IncludeTrailingPathDelimiter(Directory)+FileName;
end;
function TFileBrowserForm.GetTreeFileMask: String; function TFileBrowserForm.GetTreeFileMask: String;
begin begin
if Assigned(FSelectedMask) then if Assigned(FSelectedMask) then
@ -346,6 +372,8 @@ begin
if SubDir[0] = #0 then if SubDir[0] = #0 then
SubDir := @SubDir[1]; SubDir := @SubDir[1];
Node := TV.Items.GetFirstNode; Node := TV.Items.GetFirstNode;
if Node=Nil then
exit;
while SubDir[0] <> #0 do while SubDir[0] <> #0 do
begin begin
Node := Node.GetFirstChild; Node := Node.GetFirstChild;
@ -534,6 +562,28 @@ begin
Result:=TFileSystemEntry(aNode.Data); Result:=TFileSystemEntry(aNode.Data);
end; end;
procedure TFileBrowserForm.SetCurrentFile(AValue: string);
var
Dir : String;
Node : TTreeNode;
begin
if FilesInTree then
begin
Node:=FindNode(aValue);
if Assigned(Node) then
TV.Selected:=Node;
end
else
begin
Dir:=ExtractFilePath(aValue);
CurrentDirectory:=Dir;
FileListBox.Directory:=Dir;
FileListBox.FileName:=ExtractFileName(aValue);
end
end;
function TFileBrowserForm.SelectedDir: string; function TFileBrowserForm.SelectedDir: string;
var var