IDE: project inspector: filter, directory hierarchy, show sorted alphabetically

git-svn-id: trunk@30055 -
This commit is contained in:
mattias 2011-03-28 21:12:14 +00:00
parent 81c93dc90f
commit c0594332b5
12 changed files with 538 additions and 271 deletions

View File

@ -2328,7 +2328,7 @@ begin
FBreakPointGroups.LoadFromXMLConfig(XMLConfig,
'Debugging/'+XMLBreakPointGroupsNode+'/');
FBreakPoints.LoadFromXMLConfig(XMLConfig,'Debugging/'+XMLBreakPointsNode+'/',
@Project1.LongenFilename,
@Project1.ConvertFromLPIFilename,
@FBreakPointGroups.GetGroupByName);
FWatches.LoadFromXMLConfig(XMLConfig,'Debugging/'+XMLWatchesNode+'/');
end;
@ -2347,7 +2347,7 @@ begin
FBreakPointGroups.SaveToXMLConfig(XMLConfig,
'Debugging/'+XMLBreakPointGroupsNode+'/');
FBreakPoints.SaveToXMLConfig(XMLConfig,'Debugging/'+XMLBreakPointsNode+'/',
@Project1.ShortenFilename);
@Project1.ConvertToLPIFilename);
FWatches.SaveToXMLConfig(XMLConfig,'Debugging/'+XMLWatchesNode+'/');
end;
if not (pwfDoNotSaveProjectInfo in Flags) then

View File

@ -692,7 +692,7 @@ begin
if DocFile<>nil then begin
Filename:=DocFile.Filename;
if (LazarusIDE.ActiveProject<>nil) then
LazarusIDE.ActiveProject.ShortenFilename(Filename);
Filename:=LazarusIDE.ActiveProject.GetShortFilename(Filename,true);
Caption := strCaption + Filename;
end else
Caption := strCaption + lisCodeHelpNoTagCaption;

View File

@ -32,7 +32,7 @@ interface
uses
Classes, SysUtils, Laz_XMLCfg, FileUtil, LCLProc, AvgLvlTree, SourceLog,
FileProcs, CodeToolManager, CodeToolsConfig, CodeCache, LazConf,
StdCtrls, ExtCtrls;
StdCtrls, ExtCtrls, ComCtrls;
type
// comments
@ -265,6 +265,14 @@ procedure SetComboBoxText(AComboBox:TComboBox; const AText: String;
Cmp: TCmpStrType; MaxCount: integer);
function CheckGroupItemChecked(CheckGroup: TCheckGroup; const Caption: string): Boolean;
// treeview
procedure TVDeleteUnneededNodes(TVNodeStack: TFPList; p: integer);
procedure TVClearUnneededAndCreateHierachy(TV: TTreeView; FilesNode: TTreeNode;
Filename: string; TVNodeStack: TFPList;
ShowDirectoryHierarchy: boolean; ImageIndexDirectory: integer);
implementation
@ -2729,6 +2737,84 @@ begin
Result := CheckGroup.Checked[CheckGroup.Items.IndexOf(Caption)];
end;
procedure TVDeleteUnneededNodes(TVNodeStack: TFPList; p: integer);
// delete all nodes behind the nodes in the stack, and depth>=p
var
i: Integer;
Node: TTreeNode;
begin
for i:=TVNodeStack.Count-1 downto p do begin
Node:=TTreeNode(TVNodeStack[i]);
while Node.GetNextSibling<>nil do
Node.GetNextSibling.Free;
end;
TVNodeStack.Count:=p;
end;
procedure TVClearUnneededAndCreateHierachy(TV: TTreeView; FilesNode: TTreeNode;
Filename: string; TVNodeStack: TFPList;
ShowDirectoryHierarchy: boolean; ImageIndexDirectory: integer);
// TVNodeStack contains a path of TTreeNode for the last filename
var
DelimPos: Integer;
FilePart: String;
Node: TTreeNode;
p: Integer;
begin
p:=0;
while Filename<>'' do begin
// get the next file name part
if ShowDirectoryHierarchy then
DelimPos:=System.Pos(PathDelim,Filename)
else
DelimPos:=0;
if DelimPos>0 then begin
FilePart:=copy(Filename,1,DelimPos-1);
Filename:=copy(Filename,DelimPos+1,length(Filename));
end else begin
FilePart:=Filename;
Filename:='';
end;
//debugln(['ClearUnneededAndCreateHierachy FilePart=',FilePart,' Filename=',Filename,' p=',p]);
if p<TVNodeStack.Count then begin
Node:=TTreeNode(TVNodeStack[p]);
if (FilePart=Node.Text) and (Node.Data=nil) then begin
// same sub directory
end
else begin
// change directory => last directory is complete
// => delete unneeded nodes after last path
TVDeleteUnneededNodes(TVNodeStack,p+1);
if Node.GetNextSibling<>nil then begin
Node:=Node.GetNextSibling;
Node.Text:=FilePart;
end
else
Node:=TV.Items.Add(Node,FilePart);
TVNodeStack[p]:=Node;
end;
end else begin
// new sub node
if p>0 then
Node:=TTreeNode(TVNodeStack[p-1])
else
Node:=FilesNode;
if Node.GetFirstChild<>nil then begin
Node:=Node.GetFirstChild;
Node.Text:=FilePart;
end
else
Node:=TV.Items.AddChild(Node,FilePart);
TVNodeStack.Add(Node);
end;
if (Filename<>'') then begin
Node.ImageIndex:=ImageIndexDirectory;
Node.SelectedIndex:=Node.ImageIndex;
end;
inc(p);
end;
end;
procedure CTDbgOut(const s: string);
begin
LCLProc.DbgOut(s);

View File

@ -135,7 +135,7 @@ begin
SrcLine:=CodeBuf.GetLine(jh_item.CaretXY.Y-1);
Filename:=jh_item.Filename;
if Project1<>nil then
Project1.ShortenFilename(Filename);
Filename:=Project1.GetShortFilename(Filename,true);
listHistory.Items.Append
(BeautifyLine(Filename,
jh_item.CaretXY.X,
@ -144,7 +144,7 @@ begin
)
);
end;
DebugLn(['TJumpHistoryViewWin.InitDisplay Project1.JumpHistory.HistoryIndex=',Project1.JumpHistory.HistoryIndex]);
//DebugLn(['TJumpHistoryViewWin.InitDisplay Project1.JumpHistory.HistoryIndex=',Project1.JumpHistory.HistoryIndex]);
listHistory.ItemIndex := Project1.JumpHistory.HistoryIndex;
end;
listHistory.Items.EndUpdate;

View File

@ -7098,9 +7098,9 @@ var
LFMFilename:=ChangeFileExt(UnitCode.Filename,'.lfm');
if FileExistsUTF8(LFMFilename) then begin
UsingFilename:=AnUnitInfo.Filename;
Project1.ShortenFilename(UsingFilename);
Project1.ConvertToLPIFilename(UsingFilename);
UsedFilename:=UnitCode.Filename;
Project1.ShortenFilename(UsedFilename);
Project1.ConvertToLPIFilename(UsedFilename);
TheModalResult:=QuestionDlg(lisCodeTemplError,
Format(lisClassConflictsWithLfmFileTheUnitUsesTheUnitWhic, [#13,
UsingFilename, #13, UsedFilename, #13, AComponentClassName, #13, #13,

View File

@ -342,6 +342,7 @@ type
function IsMainUnit: boolean;
function IsVirtual: boolean;
function GetDirectory: string;
function GetShortFilename(UseUp: boolean): string;
function NeedsSaveToDisk: boolean;
function ReadOnly: boolean;
function ReadUnitSource(ReadUnitName,Revert:boolean): TModalResult;
@ -958,8 +959,9 @@ type
function FileIsInProjectDir(const AFilename: string): boolean;
procedure GetVirtualDefines(DefTree: TDefineTree; DirDef: TDirectoryDefines);
function SearchFile(const Filename,SearchPaths,InitialDir:string):string;
procedure ShortenFilename(var AFilename: string); override; // for lpi file
procedure LongenFilename(var AFilename: string); override; // for lpi file
function GetShortFilename(const Filename: string; UseUp: boolean): string; override;
procedure ConvertToLPIFilename(var AFilename: string); override;
procedure ConvertFromLPIFilename(var AFilename: string); override;
// package dependencies
function FindDependencyByName(const PackageName: string): TPkgDependency;
@ -1967,6 +1969,14 @@ begin
end;
end;
function TUnitInfo.GetShortFilename(UseUp: boolean): string;
begin
if Project<>nil then
Result:=Project.GetShortFilename(Filename,UseUp)
else
Result:=Filename;
end;
function TUnitInfo.IsMainUnit: boolean;
begin
Result:=(Project<>nil) and (Project.MainUnitInfo=Self);
@ -4068,12 +4078,29 @@ begin
Result:='';
end;
procedure TProject.ShortenFilename(var AFilename: string);
function TProject.GetShortFilename(const Filename: string; UseUp: boolean
): string;
var
BaseDir: String;
CurPath: String;
begin
Result:=Filename;
BaseDir:=AppendPathDelim(ProjectDirectory);
if (BaseDir<>'') and FilenameIsAbsolute(BaseDir) and UseUp then
Result:=CreateRelativePath(Result,BaseDir)
else begin
CurPath:=copy(ExtractFilePath(Result),1,length(BaseDir));
if CompareFilenames(BaseDir,CurPath)=0 then
Result:=copy(Result,length(CurPath)+1,length(Result));
end;
end;
procedure TProject.ConvertToLPIFilename(var AFilename: string);
begin
OnLoadSaveFilename(AFilename,false);
end;
procedure TProject.LongenFilename(var AFilename: string);
procedure TProject.ConvertFromLPIFilename(var AFilename: string);
begin
OnLoadSaveFilename(AFilename,true);
end;
@ -5017,7 +5044,7 @@ begin
Result:=POOutputDirectory;
IDEMacros.SubstituteMacros(Result);
Result:=TrimFilename(Result);
LongenFilename(Result);
ConvertFromLPIFilename(Result);
end;
function TProject.GetAutoCreatedFormsList: TStrings;

View File

@ -1,20 +1,19 @@
object ProjectInspectorForm: TProjectInspectorForm
Left = 457
Height = 309
Height = 335
Top = 399
Width = 223
Width = 279
ActiveControl = ItemsTreeView
Caption = 'ProjectInspectorForm'
ClientHeight = 309
ClientWidth = 223
ClientHeight = 335
ClientWidth = 279
OnShow = ProjectInspectorFormShow
LCLVersion = '0.9.29'
LCLVersion = '0.9.31'
object ItemsTreeView: TTreeView
AnchorSideTop.Side = asrBottom
Left = 0
Height = 283
Top = 26
Width = 223
Height = 304
Top = 31
Width = 279
Align = alClient
BorderSpacing.Top = 2
DefaultItemHeight = 19
@ -29,72 +28,110 @@ object ProjectInspectorForm: TProjectInspectorForm
end
object BtnPanel: TPanel
Left = 0
Height = 24
Height = 29
Top = 0
Width = 223
Width = 279
Align = alTop
AutoSize = True
ChildSizing.EnlargeHorizontal = crsScaleChilds
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 10
ClientHeight = 24
ClientWidth = 223
ClientHeight = 29
ClientWidth = 279
TabOrder = 1
object OpenBitBtn: TSpeedButton
Left = 0
Height = 23
Top = 0
Width = 53
Left = 1
Height = 27
Top = 1
Width = 40
Align = alLeft
AutoSize = True
Constraints.MinWidth = 25
Color = clBtnFace
NumGlyphs = 0
OnClick = OpenBitBtnClick
ShowHint = True
ParentShowHint = False
end
object AddBitBtn: TSpeedButton
AnchorSideLeft.Side = asrBottom
Left = 53
Height = 23
Top = 0
Width = 53
Left = 41
Height = 27
Top = 1
Width = 40
Align = alLeft
AutoSize = True
Constraints.MinWidth = 25
Color = clBtnFace
NumGlyphs = 0
OnClick = AddBitBtnClick
ShowHint = True
ParentShowHint = False
end
object RemoveBitBtn: TSpeedButton
AnchorSideLeft.Side = asrBottom
Left = 106
Height = 23
Top = 0
Width = 53
Left = 81
Height = 27
Top = 1
Width = 40
Align = alLeft
AutoSize = True
Constraints.MinWidth = 25
Color = clBtnFace
NumGlyphs = 0
OnClick = RemoveBitBtnClick
ShowHint = True
ParentShowHint = False
end
object OptionsBitBtn: TSpeedButton
AnchorSideLeft.Side = asrBottom
Left = 159
Height = 23
Top = 0
Width = 53
Left = 121
Height = 27
Top = 1
Width = 40
Align = alLeft
AutoSize = True
Constraints.MinWidth = 25
Color = clBtnFace
NumGlyphs = 0
OnClick = OptionsBitBtnClick
ShowHint = True
ParentShowHint = False
end
object DirectoryHierarchySpeedButton: TSpeedButton
Left = 232
Height = 27
Top = 1
Width = 23
Align = alRight
AllowAllUp = True
AutoSize = True
GroupIndex = 1
NumGlyphs = 0
OnClick = DirectoryHierarchySpeedButtonClick
ShowHint = True
ParentShowHint = False
end
object SortAlphabeticallySpeedButton: TSpeedButton
Left = 255
Height = 27
Top = 1
Width = 23
Align = alRight
AllowAllUp = True
AutoSize = True
GroupIndex = 2
NumGlyphs = 0
OnClick = SortAlphabeticallySpeedButtonClick
ShowHint = True
ParentShowHint = False
end
object FilterEdit: TEdit
Left = 161
Height = 27
Top = 1
Width = 71
Align = alClient
OnChange = FilterEditChange
OnEnter = FilterEditEnter
OnExit = FilterEditExit
TabOrder = 0
Text = 'FilterEdit'
end
end
object ItemsPopupMenu: TPopupMenu
OnPopup = ItemsPopupMenuPopup
left = 40
left = 65
top = 59
end
end

View File

@ -32,9 +32,6 @@
TProjectInspectorForm is the form of the project inspector.
ToDo:
- hierachical view
- alpha sort
- filter
- show lfm/lrs files as sub items
- dnd move
- project groups:
@ -80,23 +77,40 @@ type
ADependency: TPkgDependency): TModalResult of object;
TProjectInspectorFlag = (
pifAllChanged,
pifItemsChanged,
pifFilesChanged,
pifButtonsChanged,
pifTitleChanged
);
TProjectInspectorFlags = set of TProjectInspectorFlag;
{ TProjInspFileItem }
TProjInspFileItem = class
public
Filename: string;
constructor Create(AFilename: string);
end;
{ TProjectInspectorForm }
TProjectInspectorForm = class(TForm)
AddBitBtn: TSpeedButton;
BtnPanel: TPanel;
DirectoryHierarchySpeedButton: TSpeedButton;
FilterEdit: TEdit;
OpenBitBtn: TSpeedButton;
ItemsTreeView: TTreeView;
ItemsPopupMenu: TPopupMenu;
OptionsBitBtn: TSpeedButton;
RemoveBitBtn: TSpeedButton;
SortAlphabeticallySpeedButton: TSpeedButton;
procedure AddBitBtnClick(Sender: TObject);
procedure DirectoryHierarchySpeedButtonClick(Sender: TObject);
procedure FilterEditChange(Sender: TObject);
procedure FilterEditEnter(Sender: TObject);
procedure FilterEditExit(Sender: TObject);
procedure ItemsPopupMenuPopup(Sender: TObject);
procedure ItemsTreeViewDblClick(Sender: TObject);
procedure ItemsTreeViewKeyDown(Sender: TObject; var Key: Word;
@ -113,8 +127,11 @@ type
procedure ReAddMenuItemClick(Sender: TObject);
procedure RemoveBitBtnClick(Sender: TObject);
procedure RemoveNonExistingFilesMenuItemClick(Sender: TObject);
procedure SortAlphabeticallySpeedButtonClick(Sender: TObject);
procedure ToggleI18NForLFMMenuItemClick(Sender: TObject);
private
FFilter: string;
FIdleConnected: boolean;
FOnAddDependency: TAddProjInspDepEvent;
FOnAddUnitToProject: TOnAddUnitToProject;
FOnOpen: TNotifyEvent;
@ -122,9 +139,12 @@ type
FOnRemoveDependency: TRemoveProjInspDepEvent;
FOnRemoveFile: TRemoveProjInspFileEvent;
FOnShowOptions: TNotifyEvent;
FShowDirectoryHierarchy: boolean;
FSortAlphabetically: boolean;
FUpdateLock: integer;
FLazProject: TProject;
FilesNode: TTreeNode;
FFilesNode: TTreeNode;
FNextSelectedPart: TObject;// select this file/dependency on next update
DependenciesNode: TTreeNode;
RemovedDependenciesNode: TTreeNode;
ImageIndexFiles: integer;
@ -136,30 +156,37 @@ type
ImageIndexRegisterUnit: integer;
ImageIndexText: integer;
ImageIndexBinary: integer;
ImageIndexDirectory: integer;
FFlags: TProjectInspectorFlags;
procedure SetDependencyDefaultFilename(AsPreferred: boolean);
procedure SetFilter(const AValue: string);
procedure SetIdleConnected(const AValue: boolean);
procedure SetLazProject(const AValue: TProject);
procedure SetShowDirectoryHierarchy(const AValue: boolean);
procedure SetSortAlphabetically(const AValue: boolean);
procedure SetupComponents;
procedure UpdateProjectItems;
procedure UpdateProjectFiles(Immediately: boolean);
procedure UpdateRequiredPackages;
procedure UpdateRemovedRequiredPackages;
function GetImageIndexOfFile(AFile: TUnitInfo): integer;
procedure OnProjectBeginUpdate(Sender: TObject);
procedure OnProjectEndUpdate(Sender: TObject; ProjectChanged: boolean);
function FitsFilter(aFilename: string): boolean;
function CompareProjFilenames(AFilename1, AFilename2: string): integer;
procedure FreeTVNodeData(Node: TTreeNode);
protected
procedure KeyUp(var Key: Word; Shift: TShiftState); override;
function ProjectFileToNodeText(AFile: TUnitInfo): string;
function CompareUnitInfos(Tree: TAvgLvlTree; UnitInfo1, UnitInfo2: Pointer): integer;
procedure IdleHandler(Sender: TObject; var Done: Boolean);
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure BeginUpdate;
procedure EndUpdate;
function IsUpdateLocked: boolean;
procedure UpdateAll;
procedure UpdateAll(Immediately: boolean);
procedure UpdateTitle;
procedure UpdateButtons;
procedure UpdateItems;
procedure UpdateItems(Immediately: boolean);
function GetSelectedFile: TUnitInfo;
function GetSelectedDependency: TPkgDependency;
function StoreCurrentTreeSelection: TStringList;
@ -178,6 +205,10 @@ type
read FOnRemoveDependency write FOnRemoveDependency;
property OnReAddDependency: TAddProjInspDepEvent
read FOnReAddDependency write FOnReAddDependency;
property Filter: string read FFilter write SetFilter;
property SortAlphabetically: boolean read FSortAlphabetically write SetSortAlphabetically;
property ShowDirectoryHierarchy: boolean read FShowDirectoryHierarchy write SetShowDirectoryHierarchy;
property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
end;
var
@ -191,6 +222,13 @@ implementation
uses
IDEImagesIntf;
{ TProjInspFileItem }
constructor TProjInspFileItem.Create(AFilename: string);
begin
Filename:=AFilename;
end;
{ TProjectInspectorForm }
procedure TProjectInspectorForm.ItemsTreeViewDblClick(Sender: TObject);
@ -216,31 +254,21 @@ end;
procedure TProjectInspectorForm.MoveDependencyUpClick(Sender: TObject);
var
Dependency: TPkgDependency;
OldSelection: TStringList;
begin
Dependency:=GetSelectedDependency;
if (Dependency=nil) or (Dependency.Removed)
or (Dependency.PrevRequiresDependency=nil) then exit;
ItemsTreeView.BeginUpdate;
OldSelection:=StoreCurrentTreeSelection;
LazProject.MoveRequiredDependencyUp(Dependency);
ApplyTreeSelection(OldSelection,true);
ItemsTreeView.EndUpdate;
end;
procedure TProjectInspectorForm.MoveDependencyDownClick(Sender: TObject);
var
Dependency: TPkgDependency;
OldSelection: TStringList;
begin
Dependency:=GetSelectedDependency;
if (Dependency=nil) or (Dependency.Removed)
or (Dependency.NextRequiresDependency=nil) then exit;
ItemsTreeView.BeginUpdate;
OldSelection:=StoreCurrentTreeSelection;
LazProject.MoveRequiredDependencyDown(Dependency);
ApplyTreeSelection(OldSelection,true);
ItemsTreeView.EndUpdate;
end;
procedure TProjectInspectorForm.SetDependencyDefaultFilenameMenuItemClick(
@ -298,8 +326,9 @@ begin
if Assigned(OnAddUnitToProject) then begin
if OnAddUnitToProject(Self,NewFile)<>mrOk then break;
end;
FNextSelectedPart:=NewFile;
end;
UpdateAll;
UpdateAll(false);
EndUpdate;
end;
@ -308,7 +337,8 @@ begin
BeginUpdate;
if Assigned(OnAddDependency) then
OnAddDependency(Self,AddResult.Dependency);
UpdateItems;
FNextSelectedPart:=AddResult.Dependency;
UpdateItems(false);
EndUpdate;
end;
@ -317,6 +347,29 @@ begin
AddResult.Free;
end;
procedure TProjectInspectorForm.DirectoryHierarchySpeedButtonClick(
Sender: TObject);
begin
ShowDirectoryHierarchy:=DirectoryHierarchySpeedButton.Down;
end;
procedure TProjectInspectorForm.FilterEditChange(Sender: TObject);
begin
Filter:=FilterEdit.Text;
end;
procedure TProjectInspectorForm.FilterEditEnter(Sender: TObject);
begin
if FilterEdit.Text=lisCEFilter then
FilterEdit.Text:='';
end;
procedure TProjectInspectorForm.FilterEditExit(Sender: TObject);
begin
if FilterEdit.Text=lisCEFilter then
FilterEdit.Text:='';
end;
procedure TProjectInspectorForm.ItemsPopupMenuPopup(Sender: TObject);
var
ItemCnt: integer;
@ -403,7 +456,7 @@ end;
procedure TProjectInspectorForm.ProjectInspectorFormShow(Sender: TObject);
begin
UpdateAll;
UpdateAll(false);
end;
procedure TProjectInspectorForm.ReAddMenuItemClick(Sender: TObject);
@ -466,10 +519,16 @@ begin
end;
if HasChanged then begin
LazProject.Modified:=true;
UpdateAll;
UpdateProjectFiles(false);
end;
end;
procedure TProjectInspectorForm.SortAlphabeticallySpeedButtonClick(
Sender: TObject);
begin
SortAlphabetically:=SortAlphabeticallySpeedButton.Down;
end;
procedure TProjectInspectorForm.ToggleI18NForLFMMenuItemClick(Sender: TObject);
var
CurFile: TUnitInfo;
@ -493,7 +552,24 @@ begin
FLazProject.OnBeginUpdate:=@OnProjectBeginUpdate;
FLazProject.OnEndUpdate:=@OnProjectEndUpdate;
end;
UpdateAll;
UpdateAll(false);
end;
procedure TProjectInspectorForm.SetShowDirectoryHierarchy(const AValue: boolean
);
begin
if FShowDirectoryHierarchy=AValue then exit;
FShowDirectoryHierarchy:=AValue;
DirectoryHierarchySpeedButton.Down:=ShowDirectoryHierarchy;
UpdateProjectFiles(false);
end;
procedure TProjectInspectorForm.SetSortAlphabetically(const AValue: boolean);
begin
if FSortAlphabetically=AValue then exit;
FSortAlphabetically:=AValue;
SortAlphabeticallySpeedButton.Down:=SortAlphabetically;
UpdateProjectFiles(false);
end;
procedure TProjectInspectorForm.SetDependencyDefaultFilename(
@ -515,6 +591,34 @@ begin
UpdateButtons;
end;
procedure TProjectInspectorForm.SetFilter(const AValue: string);
var
NewValue: String;
begin
NewValue:=AValue;
if NewValue=lisCEFilter then NewValue:='';
NewValue:=LowerCase(NewValue);
//debugln(['TProjectInspectorForm.SetFilter Old="',Filter,'" New="',NewValue,'"']);
if FFilter=NewValue then exit;
FFilter:=NewValue;
if not FilterEdit.Focused then
if Filter='' then
FilterEdit.Text:=lisCEFilter
else
FilterEdit.Text:=Filter;
UpdateProjectFiles(false);
end;
procedure TProjectInspectorForm.SetIdleConnected(const AValue: boolean);
begin
if FIdleConnected=AValue then exit;
FIdleConnected:=AValue;
if FIdleConnected then
Application.AddOnIdleHandler(@IdleHandler)
else
Application.RemoveOnIdleHandler(@IdleHandler);
end;
procedure TProjectInspectorForm.SetupComponents;
begin
ItemsTreeView.Images := IDEImages.Images_16;
@ -527,6 +631,7 @@ begin
ImageIndexRegisterUnit := IDEImages.LoadImage(16, 'pkg_registerunit');
ImageIndexText := IDEImages.LoadImage(16, 'pkg_text');
ImageIndexBinary := IDEImages.LoadImage(16, 'pkg_binary');
ImageIndexDirectory := IDEImages.LoadImage(16, 'pkg_files');
OpenBitBtn.LoadGlyphFromLazarusResource('laz_open');
AddBitBtn.LoadGlyphFromLazarusResource('laz_add');
@ -541,59 +646,104 @@ begin
AddBitBtn.Hint:=lisCodeTemplAdd;
RemoveBitBtn.Hint:=lisExtToolRemove;
OptionsBitBtn.Hint:=dlgFROpts;
FilterEdit.Text:=lisCEFilter;
SortAlphabeticallySpeedButton.Hint:=lisPESortFilesAlphabetically;
SortAlphabeticallySpeedButton.LoadGlyphFromLazarusResource('pkg_sortalphabetically');
DirectoryHierarchySpeedButton.Hint:=lisPEShowDirectoryHierarchy;
DirectoryHierarchySpeedButton.LoadGlyphFromLazarusResource('pkg_hierarchical');
with ItemsTreeView do begin
FilesNode:=Items.Add(nil, dlgEnvFiles);
FilesNode.ImageIndex:=ImageIndexFiles;
FilesNode.SelectedIndex:=FilesNode.ImageIndex;
FFilesNode:=Items.Add(nil, dlgEnvFiles);
FFilesNode.ImageIndex:=ImageIndexFiles;
FFilesNode.SelectedIndex:=FFilesNode.ImageIndex;
DependenciesNode:=Items.Add(nil, lisPckEditRequiredPackages);
DependenciesNode.ImageIndex:=ImageIndexRequired;
DependenciesNode.SelectedIndex:=DependenciesNode.ImageIndex;
end;
end;
procedure TProjectInspectorForm.UpdateProjectItems;
procedure TProjectInspectorForm.UpdateProjectFiles(Immediately: boolean);
var
CurFile: TUnitInfo;
CurNode: TTreeNode;
NodeText: String;
NextNode: TTreeNode;
Tree: TAvgLvlTree;
AVLNode: TAvgLvlTreeNode;
OldSelection: TStringList;
Files: TStringList;
TVNodeStack: TFPList;
ExpandedState: TTreeNodeExpandedState;
Filename: String;
i: Integer;
begin
ItemsTreeView.BeginUpdate;
if LazProject<>nil then begin
Tree:=TAvgLvlTree.CreateObjectCompare(@CompareUnitInfos);
CurFile:=LazProject.FirstPartOfProject;
while CurFile<>nil do begin
Tree.Add(CurFile);
CurFile:=CurFile.NextPartOfProject;
end;
AVLNode:=Tree.FindLowest;
CurNode:=FilesNode.GetFirstChild;
while AVLNode<>nil do begin
CurFile:=TUnitInfo(AVLNode.Data);
NodeText:=ProjectFileToNodeText(CurFile);
if CurNode=nil then
CurNode:=ItemsTreeView.Items.AddChild(FilesNode,NodeText)
else
CurNode.Text:=NodeText;
CurNode.ImageIndex:=GetImageIndexOfFile(CurFile);
CurNode.SelectedIndex:=CurNode.ImageIndex;
CurNode:=CurNode.GetNextSibling;
AVLNode:=Tree.FindSuccessor(AVLNode);
end;
while CurNode<>nil do begin
NextNode:=CurNode.GetNextSibling;
CurNode.Free;
CurNode:=NextNode;
end;
FilesNode.Expanded:=true;
Tree.Free;
end else begin
// delete file nodes
FilesNode.HasChildren:=false;
if (not Immediately) or (FUpdateLock>0) or (not Visible) then begin
Include(FFlags,pifFilesChanged);
IdleConnected:=true;
exit;
end;
Exclude(FFlags,pifFilesChanged);
ItemsTreeView.BeginUpdate;
if FNextSelectedPart=nil then
OldSelection:=StoreCurrentTreeSelection
else
OldSelection:=nil;
Files:=TStringList.Create;
TVNodeStack:=TFPList.Create;
ExpandedState:=TTreeNodeExpandedState.Create(ItemsTreeView);
try
if LazProject<>nil then begin
// collect and sort files
CurFile:=LazProject.FirstPartOfProject;
while CurFile<>nil do begin
Filename:=CurFile.GetShortFilename(true);
if (Filename<>'') and FitsFilter(Filename) then begin
i:=Files.Count-1;
while i>=0 do begin
if CompareProjFilenames(Filename,Files[i])>=0 then break;
dec(i);
end;
Files.Insert(i+1,Filename);
Files.Objects[i+1]:=CurFile;
end;
CurFile:=CurFile.NextPartOfProject;
end;
//debugln(['TProjectInspectorForm.UpdateFiles filtered=',Files.Count,' of ',LazProject.FileCount,' Filter="',Filter,'" Hierachy=',ShowDirectoryHierarchy,' SortAlpha=',SortAlphabetically]);
// update treeview nodes
FreeTVNodeData(FFilesNode);
if Files.Count=0 then
FFilesNode.DeleteChildren
else begin
CurNode:=FFilesNode.GetFirstChild;
for i:=0 to Files.Count-1 do begin
Filename:=Files[i];
CurFile:=TUnitInfo(Files.Objects[i]);
TVClearUnneededAndCreateHierachy(ItemsTreeView,FFilesNode,Filename,
TVNodeStack,ShowDirectoryHierarchy,ImageIndexDirectory);
CurNode:=TTreeNode(TVNodeStack[TVNodeStack.Count-1]);
if FNextSelectedPart<>nil then begin
CurNode.Selected:=FNextSelectedPart=CurFile;
FNextSelectedPart:=nil;
end;
CurNode.Data:=TProjInspFileItem.Create(CurFile.Filename);
CurNode.ImageIndex:=GetImageIndexOfFile(CurFile);
CurNode.SelectedIndex:=CurNode.ImageIndex;
CurNode.DeleteChildren;
end;
TVDeleteUnneededNodes(TVNodeStack,0);
end;
end else begin
// delete file nodes
FFilesNode.DeleteChildren;
end;
ExpandedState.Apply(ItemsTreeView);
FFilesNode.Expanded:=true;
finally
ExpandedState.Free;
TVNodeStack.Free;
Files.Free;
end;
if OldSelection<>nil then
ApplyTreeSelection(OldSelection,true);
ItemsTreeView.EndUpdate;
end;
@ -704,48 +854,85 @@ end;
procedure TProjectInspectorForm.OnProjectEndUpdate(Sender: TObject;
ProjectChanged: boolean);
begin
UpdateAll;
UpdateAll(false);
EndUpdate;
end;
function TProjectInspectorForm.FitsFilter(aFilename: string): boolean;
begin
Result:=(Filter='') or (System.Pos(Filter,lowercase(aFilename))>0);
end;
function TProjectInspectorForm.CompareProjFilenames(AFilename1,
AFilename2: string): integer;
begin
if SortAlphabetically then
Result:=CompareFilenames(AFilename1, AFilename2)
else if ShowDirectoryHierarchy then
Result:=CompareFilenames(ExtractFilePath(AFilename1), ExtractFilePath(AFilename2))
else
Result:=0;
end;
procedure TProjectInspectorForm.FreeTVNodeData(Node: TTreeNode);
var
Child: TTreeNode;
begin
if Node=nil then exit;
if (Node.Data<>nil) then begin
TObject(Node.Data).Free;
Node.Data:=nil;
end;
Child:=Node.GetFirstChild;
while Child<>nil do
begin
FreeTVNodeData(Child);
Child:=Child.GetNextSibling;
end;
end;
procedure TProjectInspectorForm.KeyUp(var Key: Word; Shift: TShiftState);
begin
inherited KeyDown(Key, Shift);
ExecuteIDEShortCut(Self,Key,Shift,nil);
end;
function TProjectInspectorForm.ProjectFileToNodeText(AFile: TUnitInfo): string;
procedure TProjectInspectorForm.IdleHandler(Sender: TObject; var Done: Boolean
);
begin
Result:=CreateRelativePath(AFile.Filename,LazProject.ProjectDirectory);
end;
function TProjectInspectorForm.CompareUnitInfos(Tree: TAvgLvlTree;
UnitInfo1, UnitInfo2: Pointer): integer;
var
ShortFilename1: String;
ShortFilename2: String;
begin
ShortFilename1:=CreateRelativePath(TUnitInfo(UnitInfo1).Filename,
LazProject.ProjectDirectory);
ShortFilename2:=CreateRelativePath(TUnitInfo(UnitInfo2).Filename,
LazProject.ProjectDirectory);
Result:=CompareFilenames(ShortFilename1,ShortFilename2);
if (not Visible) or (FUpdateLock>0) then begin
IdleConnected:=false;
exit;
end;
if pifAllChanged in FFlags then
UpdateAll(true)
else if pifItemsChanged in FFlags then
UpdateItems(true)
else if pifFilesChanged in FFlags then
UpdateProjectFiles(true)
else if pifTitleChanged in FFlags then
UpdateTitle
else if pifButtonsChanged in FFlags then
UpdateButtons
else
IdleConnected:=false;
end;
function TProjectInspectorForm.GetSelectedFile: TUnitInfo;
var
CurNode: TTreeNode;
NodeText: String;
Item: TProjInspFileItem;
begin
Result:=nil;
if LazProject=nil then exit;
CurNode:=ItemsTreeView.Selected;
if (CurNode=nil) or (CurNode.Parent<>FilesNode) then exit;
Result:=LazProject.FirstPartOfProject;
while (Result<>nil) do begin
NodeText:=ProjectFileToNodeText(Result);
if NodeText=CurNode.Text then exit;
Result:=Result.NextPartOfProject;
if (CurNode=nil) or (CurNode.Parent<>FFilesNode) then exit;
//debugln(['TProjectInspectorForm.GetCurrentFile ',DbgSName(TObject(CurNode.Data)),' ',CurNode.Text]);
if TObject(CurNode.Data) is TProjInspFileItem then
begin
Item:=TProjInspFileItem(CurNode.Data);
//debugln(['TProjectInspectorForm.GetCurrentFile Item=',Item.Filename,' ',Item.IsDirectory]);
Result:=LazProject.UnitInfoWithFilename(Item.Filename);
end;
end;
@ -815,7 +1002,9 @@ end;
destructor TProjectInspectorForm.Destroy;
begin
IdleConnected:=false;
BeginUpdate;
FreeTVNodeData(FFilesNode);
LazProject:=nil;
inherited Destroy;
if ProjInspector=Self then ProjInspector:=nil;
@ -830,11 +1019,6 @@ procedure TProjectInspectorForm.EndUpdate;
begin
if FUpdateLock=0 then RaiseException('TProjectInspectorForm.EndUpdate');
dec(FUpdateLock);
if FUpdateLock=0 then begin
if pifTitleChanged in FFlags then UpdateTitle;
if pifItemsChanged in FFlags then UpdateItems;
if pifButtonsChanged in FFlags then UpdateButtons;
end;
end;
function TProjectInspectorForm.IsUpdateLocked: boolean;
@ -842,11 +1026,17 @@ begin
Result:=FUpdateLock>0;
end;
procedure TProjectInspectorForm.UpdateAll;
procedure TProjectInspectorForm.UpdateAll(Immediately: boolean);
begin
if (FUpdateLock>0) or (not Visible) then begin
Include(FFlags,pifAllChanged);
IdleConnected:=true;
exit;
end;
Exclude(FFlags,pifAllChanged);
UpdateTitle;
UpdateButtons;
UpdateItems;
UpdateItems(true);
end;
procedure TProjectInspectorForm.UpdateTitle;
@ -855,6 +1045,7 @@ var
begin
if (FUpdateLock>0) or (not Visible) then begin
Include(FFlags,pifTitleChanged);
IdleConnected:=true;
exit;
end;
Exclude(FFlags,pifTitleChanged);
@ -875,6 +1066,7 @@ var
begin
if (FUpdateLock>0) or (not Visible) then begin
Include(FFlags,pifButtonsChanged);
IdleConnected:=true;
exit;
end;
Exclude(FFlags,pifButtonsChanged);
@ -895,15 +1087,16 @@ begin
end;
end;
procedure TProjectInspectorForm.UpdateItems;
procedure TProjectInspectorForm.UpdateItems(Immediately: boolean);
begin
if (FUpdateLock>0) or (not Visible) then begin
Include(FFlags,pifItemsChanged);
IdleConnected:=true;
exit;
end;
Exclude(FFlags,pifItemsChanged);
ItemsTreeView.BeginUpdate;
UpdateProjectItems;
UpdateProjectFiles(true);
UpdateRequiredPackages;
UpdateRemovedRequiredPackages;
ItemsTreeView.EndUpdate;

View File

@ -372,8 +372,9 @@ type
function FindFile(const AFilename: string;
SearchFlags: TProjectFileSearchFlags): TLazProjectFile; virtual; abstract;
procedure UpdateExecutableType; virtual; abstract;
procedure ShortenFilename(var AFilename: string); virtual; abstract;
procedure LongenFilename(var AFilename: string); virtual; abstract;
function GetShortFilename(const Filename: string; UseUp: boolean): string; virtual; abstract;
procedure ConvertToLPIFilename(var AFilename: string); virtual; abstract;
procedure ConvertFromLPIFilename(var AFilename: string); virtual; abstract;
public
property MainFileID: Integer read GetMainFileID write SetMainFileID;
property Files[Index: integer]: TLazProjectFile read GetFiles;

View File

@ -25,18 +25,18 @@ inherited PackageEditorForm: TPackageEditorForm
object FilePropsGroupBox: TGroupBox[1]
Left = 0
Height = 118
Top = 309
Top = 310
Width = 577
Align = alBottom
Caption = 'FilePropsGroupBox'
ClientHeight = 100
ClientWidth = 573
ClientHeight = 97
ClientWidth = 569
TabOrder = 1
object CallRegisterProcCheckBox: TCheckBox
Left = 0
Height = 19
Height = 22
Top = 0
Width = 158
Width = 209
Caption = 'CallRegisterProcCheckBox'
OnChange = CallRegisterProcCheckBoxChange
ParentShowHint = False
@ -46,10 +46,10 @@ inherited PackageEditorForm: TPackageEditorForm
object AddToUsesPkgSectionCheckBox: TCheckBox
AnchorSideLeft.Control = CallRegisterProcCheckBox
AnchorSideLeft.Side = asrBottom
Left = 168
Height = 19
Left = 219
Height = 22
Top = 0
Width = 191
Width = 248
BorderSpacing.Left = 10
Caption = 'AddToUsesPkgSectionCheckBox'
OnChange = AddToUsesPkgSectionCheckBoxChange
@ -62,9 +62,9 @@ inherited PackageEditorForm: TPackageEditorForm
AnchorSideTop.Control = MinVersionEdit
AnchorSideTop.Side = asrCenter
Left = 0
Height = 19
Height = 22
Top = 2
Width = 151
Width = 197
Caption = 'UseMinVersionCheckBox'
OnChange = UseMinVersionCheckBoxChange
TabOrder = 2
@ -73,8 +73,8 @@ inherited PackageEditorForm: TPackageEditorForm
AnchorSideLeft.Control = UseMinVersionCheckBox
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = FilePropsGroupBox
Left = 161
Height = 23
Left = 207
Height = 27
Top = 0
Width = 100
BorderSpacing.Left = 10
@ -87,9 +87,9 @@ inherited PackageEditorForm: TPackageEditorForm
AnchorSideTop.Control = MaxVersionEdit
AnchorSideTop.Side = asrCenter
Left = 0
Height = 19
Top = 27
Width = 152
Height = 22
Top = 31
Width = 201
Caption = 'UseMaxVersionCheckBox'
OnChange = UseMaxVersionCheckBoxChange
TabOrder = 4
@ -99,9 +99,9 @@ inherited PackageEditorForm: TPackageEditorForm
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = MinVersionEdit
AnchorSideTop.Side = asrBottom
Left = 162
Height = 23
Top = 25
Left = 211
Height = 27
Top = 29
Width = 100
BorderSpacing.Left = 10
BorderSpacing.Top = 2
@ -114,9 +114,9 @@ inherited PackageEditorForm: TPackageEditorForm
AnchorSideTop.Control = MaxVersionEdit
AnchorSideTop.Side = asrBottom
Left = 0
Height = 25
Top = 54
Width = 159
Height = 27
Top = 62
Width = 188
AutoSize = True
BorderSpacing.Top = 6
Caption = 'ApplyDependencyButton'
@ -128,19 +128,19 @@ inherited PackageEditorForm: TPackageEditorForm
AnchorSideTop.Side = asrBottom
Left = 0
Height = 60
Top = 40
Width = 573
Top = 37
Width = 569
Align = alBottom
BorderSpacing.Top = 6
Caption = 'RegisteredPluginsGroupBox'
ClientHeight = 42
ClientWidth = 569
ClientHeight = 39
ClientWidth = 561
TabOrder = 7
object RegisteredListBox: TListBox
Left = 0
Height = 42
Height = 39
Top = 0
Width = 569
Width = 561
Align = alClient
ItemHeight = 0
OnDrawItem = RegisteredListBoxDrawItem
@ -151,8 +151,8 @@ inherited PackageEditorForm: TPackageEditorForm
end
object StatusBar: TStatusBar[2]
Left = 0
Height = 23
Top = 427
Height = 22
Top = 428
Width = 577
Panels = <>
end
@ -160,31 +160,31 @@ inherited PackageEditorForm: TPackageEditorForm
Cursor = crVSplit
Left = 0
Height = 5
Top = 304
Top = 305
Width = 577
Align = alBottom
ResizeAnchor = akBottom
end
object ItemsPanel: TPanel[4]
Left = 0
Height = 256
Height = 257
Top = 48
Width = 577
Align = alClient
BevelOuter = bvNone
ClientHeight = 256
ClientHeight = 257
ClientWidth = 577
TabOrder = 4
object FilesTreeView: TTreeView
AnchorSideTop.Control = FilterEdit
AnchorSideTop.Side = asrBottom
Left = 0
Height = 233
Top = 23
Height = 230
Top = 27
Width = 577
Align = alBottom
Anchors = [akTop, akLeft, akRight, akBottom]
DefaultItemHeight = 17
DefaultItemHeight = 19
PopupMenu = FilesPopupMenu
ReadOnly = True
TabOrder = 0
@ -200,7 +200,7 @@ inherited PackageEditorForm: TPackageEditorForm
AnchorSideRight.Control = ItemsPanel
AnchorSideRight.Side = asrBottom
Left = 46
Height = 23
Height = 27
Top = 0
Width = 531
Anchors = [akTop, akLeft, akRight]
@ -216,7 +216,7 @@ inherited PackageEditorForm: TPackageEditorForm
AnchorSideBottom.Control = FilterEdit
AnchorSideBottom.Side = asrBottom
Left = 0
Height = 23
Height = 27
Top = 0
Width = 23
AllowAllUp = True
@ -235,7 +235,7 @@ inherited PackageEditorForm: TPackageEditorForm
AnchorSideBottom.Control = FilterEdit
AnchorSideBottom.Side = asrBottom
Left = 23
Height = 23
Height = 27
Top = 0
Width = 23
AllowAllUp = True

View File

@ -282,8 +282,8 @@ type
function CanBeAddedToProject: boolean;
procedure IdleHandler(Sender: TObject; var Done: Boolean);
function FitsFilter(aFilename: string): boolean;
procedure FreeTVNodeData(Node: TTreeNode);
function ComparePkgFilenames(AFilename1, AFilename2: string): integer;
procedure FreeTVNodeData(Node: TTreeNode);
protected
procedure SetLazPackage(const AValue: TLazPackage); override;
public
@ -1510,10 +1510,8 @@ begin
ImageIndexDirectory := IDEImages.LoadImage(16, 'pkg_files');
FilterEdit.Text:=lisCEFilter;
//SortAlphabeticallySpeedButton.Caption:=dlgAlphabetically;
SortAlphabeticallySpeedButton.Hint:=lisPESortFilesAlphabetically;
SortAlphabeticallySpeedButton.LoadGlyphFromLazarusResource('pkg_sortalphabetically');
//DirectoryHierarchySpeedButton.Caption:=lisPEDirectories;
DirectoryHierarchySpeedButton.Hint:=lisPEShowDirectoryHierarchy;
DirectoryHierarchySpeedButton.LoadGlyphFromLazarusResource('pkg_hierarchical');
@ -1715,82 +1713,6 @@ procedure TPackageEditorForm.UpdateFiles(Immediately: boolean);
ANode.SelectedIndex:=ANode.ImageIndex;
end;
procedure DeleteUnneededNodes(TVNodeStack: TFPList; p: integer);
// delete all nodes behind the nodes in the stack, and depth>=p
var
i: Integer;
Node: TTreeNode;
begin
for i:=TVNodeStack.Count-1 downto p do begin
Node:=TTreeNode(TVNodeStack[i]);
while Node.GetNextSibling<>nil do
Node.GetNextSibling.Free;
end;
TVNodeStack.Count:=p;
end;
procedure ClearUnneededAndCreateHierachy(Filename: string; TVNodeStack: TFPList);
// TVNodeStack contains a path of TTreeNode for the last filename
var
DelimPos: Integer;
FilePart: String;
Node: TTreeNode;
p: Integer;
begin
p:=0;
while Filename<>'' do begin
// get the next file name part
if ShowDirectoryHierarchy then
DelimPos:=System.Pos(PathDelim,Filename)
else
DelimPos:=0;
if DelimPos>0 then begin
FilePart:=copy(Filename,1,DelimPos-1);
Filename:=copy(Filename,DelimPos+1,length(Filename));
end else begin
FilePart:=Filename;
Filename:='';
end;
//debugln(['ClearUnneededAndCreateHierachy FilePart=',FilePart,' Filename=',Filename,' p=',p]);
if p<TVNodeStack.Count then begin
Node:=TTreeNode(TVNodeStack[p]);
if (FilePart=Node.Text) and (Node.Data=nil) then begin
// same sub directory
end
else begin
// change directory => last directory is complete
// => delete unneeded nodes after last path
DeleteUnneededNodes(TVNodeStack,p+1);
if Node.GetNextSibling<>nil then begin
Node:=Node.GetNextSibling;
Node.Text:=FilePart;
end
else
Node:=FilesTreeView.Items.Add(Node,FilePart);
TVNodeStack[p]:=Node;
end;
end else begin
// new sub node
if p>0 then
Node:=TTreeNode(TVNodeStack[p-1])
else
Node:=FFilesNode;
if Node.GetFirstChild<>nil then begin
Node:=Node.GetFirstChild;
Node.Text:=FilePart;
end
else
Node:=FilesTreeView.Items.AddChild(Node,FilePart);
TVNodeStack.Add(Node);
end;
if (Filename<>'') then begin
Node.ImageIndex:=ImageIndexDirectory;
Node.SelectedIndex:=Node.ImageIndex;
end;
inc(p);
end;
end;
var
Cnt: Integer;
i: Integer;
@ -1850,7 +1772,8 @@ begin
for i:=0 to Files.Count-1 do begin
Filename:=Files[i];
CurFile:=TPkgFile(Files.Objects[i]);
ClearUnneededAndCreateHierachy(Filename,TVNodeStack);
TVClearUnneededAndCreateHierachy(FilesTreeView,FFilesNode,Filename,
TVNodeStack,ShowDirectoryHierarchy,ImageIndexDirectory);
CurNode:=TTreeNode(TVNodeStack[TVNodeStack.Count-1]);
if FNextSelectedPart<>nil then
CurNode.Selected:=FNextSelectedPart=CurFile;
@ -1858,7 +1781,7 @@ begin
SetImageIndex(CurNode,CurFile);
CurNode.DeleteChildren;
end;
DeleteUnneededNodes(TVNodeStack,0);
TVDeleteUnneededNodes(TVNodeStack,0);
end;
// removed files

View File

@ -895,7 +895,7 @@ begin
if PackageEditors<>nil then
PackageEditors.UpdateAllEditors(false);
if ProjInspector<>nil then
ProjInspector.UpdateItems;
ProjInspector.UpdateItems(false);
DoCallNotifyHandler(pihtGraphChanged,Self);
end;
end;