mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-06 10:18:05 +02:00

IDE: Support ENTER also in FilterEdits of ProjectInspector and PackageEditor. Issue #30523, patch from Markus. ........ git-svn-id: branches/fixes_1_6@52929 -
1525 lines
48 KiB
ObjectPascal
1525 lines
48 KiB
ObjectPascal
{
|
|
/***************************************************************************
|
|
projectinspector.pas
|
|
--------------------
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
***************************************************************************
|
|
* *
|
|
* This source is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This code 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 *
|
|
* General Public License for more details. *
|
|
* *
|
|
* A copy of the GNU General Public License is available on the World *
|
|
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
|
* obtain it by writing to the Free Software Foundation, *
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
* *
|
|
***************************************************************************
|
|
|
|
Author: Mattias Gaertner
|
|
|
|
Abstract:
|
|
TProjectInspectorForm is the form of the project inspector.
|
|
|
|
ToDo:
|
|
- project groups:
|
|
- activate
|
|
popup menu:
|
|
- copy file name
|
|
- save
|
|
- options
|
|
- activate
|
|
- compile
|
|
- build
|
|
- view source
|
|
- close
|
|
- remove project
|
|
- build sooner Ctrl+Up
|
|
- build later Ctrl+Down
|
|
- compile all from here
|
|
- build all from here
|
|
}
|
|
unit ProjectInspector;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, LCLProc, LCLType, Forms, Controls, Buttons, ComCtrls,
|
|
Menus, Dialogs, FileUtil, LazFileUtils, LazFileCache, ExtCtrls, Graphics,
|
|
TreeFilterEdit,
|
|
// IDEIntf
|
|
IDEHelpIntf, IDECommands, IDEDialogs, IDEImagesIntf, LazIDEIntf, ProjectIntf,
|
|
PackageIntf,
|
|
// IDE
|
|
LazarusIDEStrConsts, IDEProcs, DialogProcs, IDEOptionDefs, EnvironmentOpts,
|
|
PackageDefs, Project, MainIntf, PackageEditor, AddToProjectDlg, InputHistory;
|
|
|
|
type
|
|
TOnAddUnitToProject =
|
|
function(Sender: TObject; AnUnitInfo: TUnitInfo): TModalresult of object;
|
|
TRemoveProjInspFileEvent =
|
|
function(Sender: TObject; AnUnitInfo: TUnitInfo): TModalResult of object;
|
|
TRemoveProjInspDepEvent = function(Sender: TObject;
|
|
ADependency: TPkgDependency): TModalResult of object;
|
|
TAddProjInspDepEvent = function(Sender: TObject;
|
|
ADependency: TPkgDependency): TModalResult of object;
|
|
|
|
TProjectInspectorFlag = (
|
|
pifNeedUpdateFiles,
|
|
pifNeedUpdateDependencies,
|
|
pifNeedUpdateButtons,
|
|
pifNeedUpdateTitle
|
|
);
|
|
TProjectInspectorFlags = set of TProjectInspectorFlag;
|
|
|
|
{ TProjectInspectorForm }
|
|
|
|
TProjectInspectorForm = class(TForm,IFilesEditorInterface)
|
|
AddPopupMenu: TPopupMenu;
|
|
BtnPanel: TPanel;
|
|
DirectoryHierarchyButton: TSpeedButton;
|
|
FilterEdit: TTreeFilterEdit;
|
|
MenuItem1: TMenuItem;
|
|
MenuItem2: TMenuItem;
|
|
mnuAddEditorFiles: TMenuItem;
|
|
mnuAddDiskFile: TMenuItem;
|
|
mnuAddDiskFiles: TMenuItem;
|
|
mnuAddReq: TMenuItem;
|
|
OpenButton: TSpeedButton;
|
|
ItemsTreeView: TTreeView;
|
|
ItemsPopupMenu: TPopupMenu;
|
|
SortAlphabeticallyButton: TSpeedButton;
|
|
// toolbar
|
|
ToolBar: TToolBar;
|
|
// toolbuttons
|
|
AddBitBtn: TToolButton;
|
|
RemoveBitBtn: TToolButton;
|
|
OptionsBitBtn: TToolButton;
|
|
HelpBitBtn: TToolButton;
|
|
procedure CopyMoveToDirMenuItemClick(Sender: TObject);
|
|
procedure DirectoryHierarchyButtonClick(Sender: TObject);
|
|
procedure FilterEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
|
procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
|
|
procedure ItemsPopupMenuPopup(Sender: TObject);
|
|
procedure ItemsTreeViewAdvancedCustomDrawItem(Sender: TCustomTreeView;
|
|
Node: TTreeNode; {%H-}State: TCustomDrawState; Stage: TCustomDrawStage;
|
|
var {%H-}PaintImages, {%H-}DefaultDraw: Boolean);
|
|
procedure ItemsTreeViewDblClick(Sender: TObject);
|
|
procedure ItemsTreeViewDragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
procedure ItemsTreeViewDragOver(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
procedure ItemsTreeViewKeyDown(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState);
|
|
procedure ItemsTreeViewSelectionChanged(Sender: TObject);
|
|
procedure mnuAddBitBtnClick(Sender: TObject);
|
|
procedure mnuAddDiskFilesClick(Sender: TObject);
|
|
procedure mnuAddEditorFilesClick(Sender: TObject);
|
|
procedure mnuAddReqClick(Sender: TObject);
|
|
procedure MoveDependencyUpClick(Sender: TObject);
|
|
procedure MoveDependencyDownClick(Sender: TObject);
|
|
procedure SetDependencyDefaultFilenameMenuItemClick(Sender: TObject);
|
|
procedure SetDependencyPreferredFilenameMenuItemClick(Sender: TObject);
|
|
procedure ClearDependencyFilenameMenuItemClick(Sender: TObject);
|
|
procedure OpenButtonClick(Sender: TObject);
|
|
procedure OptionsBitBtnClick(Sender: TObject);
|
|
procedure HelpBitBtnClick(Sender: TObject);
|
|
procedure ReAddMenuItemClick(Sender: TObject);
|
|
procedure RemoveBitBtnClick(Sender: TObject);
|
|
procedure RemoveNonExistingFilesMenuItemClick(Sender: TObject);
|
|
procedure SortAlphabeticallyButtonClick(Sender: TObject);
|
|
procedure EnableI18NForLFMMenuItemClick(Sender: TObject);
|
|
procedure DisableI18NForLFMMenuItemClick(Sender: TObject);
|
|
private
|
|
FIdleConnected: boolean;
|
|
FOnAddDependency: TAddProjInspDepEvent;
|
|
FOnAddUnitToProject: TOnAddUnitToProject;
|
|
FOnCopyMoveFiles: TNotifyEvent;
|
|
FOnDragDropTreeView: TDragDropEvent;
|
|
FOnDragOverTreeView: TOnDragOverTreeView;
|
|
FOnReAddDependency: TAddProjInspDepEvent;
|
|
FOnRemoveDependency: TRemoveProjInspDepEvent;
|
|
FOnRemoveFile: TRemoveProjInspFileEvent;
|
|
FOnShowOptions: TNotifyEvent;
|
|
FShowDirectoryHierarchy: boolean;
|
|
FSortAlphabetically: boolean;
|
|
FUpdateLock: integer;
|
|
FLazProject: TProject;
|
|
FFilesNode: TTreeNode;
|
|
FNextSelectedPart: TObject;// select this file/dependency on next update
|
|
FDependenciesNode: TTreeNode;
|
|
FRemovedDependenciesNode: TTreeNode;
|
|
ImageIndexFiles: integer;
|
|
ImageIndexRequired: integer;
|
|
ImageIndexConflict: integer;
|
|
ImageIndexRemovedRequired: integer;
|
|
ImageIndexProject: integer;
|
|
ImageIndexUnit: integer;
|
|
ImageIndexRegisterUnit: integer;
|
|
ImageIndexText: integer;
|
|
ImageIndexBinary: integer;
|
|
ImageIndexDirectory: integer;
|
|
FFlags: TProjectInspectorFlags;
|
|
FProjectNodeDataList : array [TPENodeType] of TPENodeData;
|
|
procedure AddMenuItemClick(Sender: TObject);
|
|
function AddOneFile(aFilename: string): TModalResult;
|
|
procedure DoAddMoreDialog(AInitTab: TAddToProjectType);
|
|
procedure FreeNodeData(Typ: TPENodeType);
|
|
function CreateNodeData(Typ: TPENodeType; aName: string; aRemoved: boolean): TPENodeData;
|
|
procedure SetDependencyDefaultFilename(AsPreferred: boolean);
|
|
procedure SetIdleConnected(AValue: boolean);
|
|
procedure SetLazProject(const AValue: TProject);
|
|
procedure SetShowDirectoryHierarchy(const AValue: boolean);
|
|
procedure SetSortAlphabetically(const AValue: boolean);
|
|
procedure SetupComponents;
|
|
function OnTreeViewGetImageIndex({%H-}Str: String; Data: TObject; var {%H-}AIsEnabled: Boolean): Integer;
|
|
procedure OnProjectBeginUpdate(Sender: TObject);
|
|
procedure OnProjectEndUpdate(Sender: TObject; ProjectChanged: boolean);
|
|
procedure EnableI18NForSelectedLFM(TheEnable: boolean);
|
|
protected
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure IdleHandler(Sender: TObject; var {%H-}Done: Boolean);
|
|
public
|
|
constructor Create(TheOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
function IsUpdateLocked: boolean; inline;
|
|
procedure UpdateTitle;
|
|
procedure UpdateProjectFiles;
|
|
procedure UpdateRequiredPackages;
|
|
procedure UpdateButtons;
|
|
procedure UpdatePending;
|
|
function CanUpdate(Flag: TProjectInspectorFlag): boolean;
|
|
function GetSingleSelectedDependency: TPkgDependency;
|
|
function TreeViewToInspector(TV: TTreeView): TProjectInspectorForm;
|
|
public
|
|
// IFilesEditorInterface
|
|
procedure BeginUpdate;
|
|
procedure EndUpdate;
|
|
procedure UpdateAll(Immediately: boolean = false);
|
|
function GetNodeData(TVNode: TTreeNode): TPENodeData;
|
|
function GetNodeItem(NodeData: TPENodeData): TObject;
|
|
function GetNodeDataItem(TVNode: TTreeNode; out NodeData: TPENodeData;
|
|
out Item: TObject): boolean;
|
|
function ExtendIncSearchPath(NewIncPaths: string): boolean;
|
|
function ExtendUnitSearchPath(NewUnitPaths: string): boolean;
|
|
function FilesBaseDirectory: string;
|
|
function FilesEditForm: TCustomForm;
|
|
function FilesEditTreeView: TTreeView;
|
|
function FilesOwner: TObject;
|
|
function FilesOwnerName: string;
|
|
function FilesOwnerReadOnly: boolean;
|
|
function FirstRequiredDependency: TPkgDependency;
|
|
function GetNodeFilename(Node: TTreeNode): string;
|
|
function IsDirectoryNode(Node: TTreeNode): boolean;
|
|
function TVNodeFiles: TTreeNode;
|
|
function TVNodeRequiredPackages: TTreeNode;
|
|
public
|
|
property LazProject: TProject read FLazProject write SetLazProject;
|
|
property OnShowOptions: TNotifyEvent read FOnShowOptions write FOnShowOptions;
|
|
property OnAddUnitToProject: TOnAddUnitToProject read FOnAddUnitToProject
|
|
write FOnAddUnitToProject;
|
|
property OnAddDependency: TAddProjInspDepEvent
|
|
read FOnAddDependency write FOnAddDependency;
|
|
property OnRemoveFile: TRemoveProjInspFileEvent read FOnRemoveFile
|
|
write FOnRemoveFile;
|
|
property OnRemoveDependency: TRemoveProjInspDepEvent
|
|
read FOnRemoveDependency write FOnRemoveDependency;
|
|
property OnReAddDependency: TAddProjInspDepEvent
|
|
read FOnReAddDependency write FOnReAddDependency;
|
|
property OnDragDropTreeView: TDragDropEvent read FOnDragDropTreeView
|
|
write FOnDragDropTreeView;
|
|
property OnDragOverTreeView: TOnDragOverTreeView read FOnDragOverTreeView
|
|
write FOnDragOverTreeView;
|
|
property OnCopyMoveFiles: TNotifyEvent read FOnCopyMoveFiles
|
|
write FOnCopyMoveFiles;
|
|
property SortAlphabetically: boolean read FSortAlphabetically write SetSortAlphabetically;
|
|
property ShowDirectoryHierarchy: boolean read FShowDirectoryHierarchy write SetShowDirectoryHierarchy;
|
|
property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
|
|
end;
|
|
|
|
var
|
|
ProjInspector: TProjectInspectorForm = nil;
|
|
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
{ TProjectInspectorForm }
|
|
|
|
// inline
|
|
function TProjectInspectorForm.IsUpdateLocked: boolean;
|
|
begin
|
|
Result:=FUpdateLock>0;
|
|
end;
|
|
|
|
function TProjectInspectorForm.TVNodeFiles: TTreeNode;
|
|
begin
|
|
Result:=FFilesNode;
|
|
end;
|
|
|
|
function TProjectInspectorForm.TVNodeRequiredPackages: TTreeNode;
|
|
begin
|
|
Result:=FDependenciesNode;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ItemsTreeViewDblClick(Sender: TObject);
|
|
begin
|
|
OpenButtonClick(Self);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ItemsTreeViewDragDrop(Sender, Source: TObject;
|
|
X, Y: Integer);
|
|
begin
|
|
OnDragDropTreeView(Sender,Source,X,Y);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ItemsTreeViewDragOver(Sender, Source: TObject;
|
|
X, Y: Integer; State: TDragState; var Accept: Boolean);
|
|
var
|
|
TargetTVNode: TTreeNode;
|
|
TargetTVType: TTreeViewInsertMarkType;
|
|
begin
|
|
if not OnDragOverTreeView(Sender,Source,X,Y, TargetTVNode, TargetTVType) then
|
|
begin
|
|
ItemsTreeView.SetInsertMark(nil,tvimNone);
|
|
Accept:=false;
|
|
exit;
|
|
end;
|
|
|
|
if State=dsDragLeave then
|
|
ItemsTreeView.SetInsertMark(nil,tvimNone)
|
|
else
|
|
ItemsTreeView.SetInsertMark(TargetTVNode,TargetTVType);
|
|
Accept:=true;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ItemsTreeViewKeyDown(Sender: TObject;
|
|
var Key: Word; Shift: TShiftState);
|
|
var
|
|
Handled: Boolean;
|
|
begin
|
|
Handled := True;
|
|
try
|
|
if Key = VK_ESCAPE then
|
|
Close
|
|
else if Key = VK_RETURN then
|
|
OpenButtonClick(Nil)
|
|
else if Key = VK_DELETE then
|
|
RemoveBitBtnClick(Nil)
|
|
else if Key = VK_INSERT then
|
|
AddMenuItemClick(Nil)
|
|
else
|
|
Handled := False;
|
|
finally
|
|
if Handled then
|
|
Key := VK_UNKNOWN;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ItemsTreeViewSelectionChanged(Sender: TObject);
|
|
begin
|
|
UpdateButtons;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.mnuAddBitBtnClick(Sender: TObject);
|
|
var
|
|
OpenDialog: TOpenDialog;
|
|
i: Integer;
|
|
ADirectory: String;
|
|
begin
|
|
OpenDialog:=TOpenDialog.Create(nil);
|
|
try
|
|
InputHistories.ApplyFileDialogSettings(OpenDialog);
|
|
ADirectory:=LazProject.ProjectDirectory;
|
|
if not FilenameIsAbsolute(ADirectory) then ADirectory:='';
|
|
if ADirectory<>'' then
|
|
OpenDialog.InitialDir:=ADirectory;
|
|
OpenDialog.Title:=lisOpenFile;
|
|
OpenDialog.Options:=OpenDialog.Options
|
|
+[ofFileMustExist,ofPathMustExist,ofAllowMultiSelect];
|
|
OpenDialog.Filter:=dlgFilterAll+' ('+GetAllFilesMask+')|'+GetAllFilesMask
|
|
+'|'+dlgFilterLazarusUnit+' (*.pas;*.pp)|*.pas;*.pp'
|
|
+'|'+dlgFilterLazarusInclude+' (*.inc)|*.inc'
|
|
+'|'+dlgFilterLazarusForm+' (*.lfm;*.dfm)|*.lfm;*.dfm';
|
|
if OpenDialog.Execute then begin
|
|
for i:=0 to OpenDialog.Files.Count-1 do
|
|
if not (AddOneFile(OpenDialog.Files[i]) in [mrOk, mrIgnore]) then break;
|
|
end;
|
|
InputHistories.StoreFileDialogSettings(OpenDialog);
|
|
finally
|
|
OpenDialog.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.mnuAddDiskFilesClick(Sender: TObject);
|
|
begin
|
|
DoAddMoreDialog(a2pFiles);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.mnuAddEditorFilesClick(Sender: TObject);
|
|
begin
|
|
DoAddMoreDialog(a2pEditorFiles);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.mnuAddReqClick(Sender: TObject);
|
|
begin
|
|
DoAddMoreDialog(a2pRequiredPkg);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.MoveDependencyUpClick(Sender: TObject);
|
|
var
|
|
Dependency: TPkgDependency;
|
|
begin
|
|
Dependency:=GetSingleSelectedDependency;
|
|
if SortAlphabetically or (Dependency=nil) or Dependency.Removed
|
|
or (Dependency.PrevRequiresDependency=nil) then exit;
|
|
LazProject.MoveRequiredDependencyUp(Dependency);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.MoveDependencyDownClick(Sender: TObject);
|
|
var
|
|
Dependency: TPkgDependency;
|
|
begin
|
|
Dependency:=GetSingleSelectedDependency;
|
|
if SortAlphabetically or (Dependency=nil) or Dependency.Removed
|
|
or (Dependency.NextRequiresDependency=nil) then exit;
|
|
LazProject.MoveRequiredDependencyDown(Dependency);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SetDependencyDefaultFilenameMenuItemClick(Sender: TObject);
|
|
begin
|
|
SetDependencyDefaultFilename(false);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SetDependencyPreferredFilenameMenuItemClick(Sender: TObject);
|
|
begin
|
|
SetDependencyDefaultFilename(true);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ClearDependencyFilenameMenuItemClick(Sender: TObject);
|
|
var
|
|
CurDependency: TPkgDependency;
|
|
i: Integer;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
|
|
if not (Item is TPkgDependency) then continue;
|
|
CurDependency:=TPkgDependency(Item);
|
|
if CurDependency.DefaultFilename='' then exit;
|
|
CurDependency.DefaultFilename:='';
|
|
CurDependency.PreferDefaultFilename:=false;
|
|
LazProject.Modified:=true;
|
|
UpdateRequiredPackages;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TProjectInspectorForm.AddOneFile(aFilename: string): TModalResult;
|
|
var
|
|
NewFile: TUnitInfo;
|
|
begin
|
|
Result := mrOK;
|
|
aFilename:=CleanAndExpandFilename(aFilename);
|
|
NewFile:=LazProject.UnitInfoWithFilename(aFilename);
|
|
if NewFile<>nil then begin
|
|
if NewFile.IsPartOfProject then Exit(mrIgnore);
|
|
end else begin
|
|
NewFile:=TUnitInfo.Create(nil);
|
|
NewFile.Filename:=aFilename;
|
|
LazProject.AddFile(NewFile,false);
|
|
end;
|
|
NewFile.IsPartOfProject:=true;
|
|
if Assigned(OnAddUnitToProject) then begin
|
|
Result:=OnAddUnitToProject(Self,NewFile);
|
|
if Result<>mrOK then Exit;
|
|
end;
|
|
FNextSelectedPart:=NewFile;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.AddMenuItemClick(Sender: TObject);
|
|
|
|
function _NodeTreeIsIn(xIterNode, xParentNode: TTreeNode): Boolean;
|
|
begin
|
|
Result := (xIterNode = xParentNode);
|
|
if not Result and Assigned(xIterNode) then
|
|
Result := _NodeTreeIsIn(xIterNode.Parent, xParentNode);
|
|
end;
|
|
|
|
begin
|
|
//check the selected item in ItemsTreeView
|
|
// -> if it's "Required Packages", call "New Requirement" (mnuAddReqClick)
|
|
// -> otherwise (selected = "Files") call "Add files from file system" (AddBitBtnClick)
|
|
if _NodeTreeIsIn(ItemsTreeView.Selected, FDependenciesNode) then
|
|
mnuAddReqClick(Sender)
|
|
else
|
|
mnuAddBitBtnClick(Sender);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.DoAddMoreDialog(AInitTab: TAddToProjectType);
|
|
var
|
|
AddResult: TAddToProjectResult;
|
|
i: Integer;
|
|
begin
|
|
AddResult:=nil;
|
|
if ShowAddToProjectDlg(LazProject,AddResult,AInitTab)<>mrOk then exit;
|
|
|
|
case AddResult.AddType of
|
|
a2pFiles:
|
|
begin
|
|
BeginUpdate;
|
|
for i:=0 to AddResult.FileNames.Count-1 do
|
|
if not (AddOneFile(AddResult.FileNames[i]) in [mrOk, mrIgnore]) then break;
|
|
UpdateAll;
|
|
EndUpdate;
|
|
end;
|
|
|
|
a2pRequiredPkg:
|
|
begin
|
|
BeginUpdate;
|
|
if Assigned(OnAddDependency) then
|
|
OnAddDependency(Self,AddResult.Dependency);
|
|
FNextSelectedPart:=AddResult.Dependency;
|
|
UpdateRequiredPackages;
|
|
EndUpdate;
|
|
end;
|
|
|
|
else
|
|
Showmessage('Not implemented');
|
|
end;
|
|
|
|
AddResult.Free;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.CopyMoveToDirMenuItemClick(Sender: TObject);
|
|
begin
|
|
OnCopyMoveFiles(Self);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.DirectoryHierarchyButtonClick(Sender: TObject);
|
|
begin
|
|
ShowDirectoryHierarchy:=DirectoryHierarchyButton.Down;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.FilterEditKeyDown(Sender: TObject;
|
|
var Key: Word; Shift: TShiftState);
|
|
begin
|
|
if Key = VK_RETURN then
|
|
begin
|
|
OpenButtonClick(Nil);
|
|
Key := VK_UNKNOWN;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.FormDropFiles(Sender: TObject;
|
|
const FileNames: array of String);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
{$IFDEF VerboseProjInspDrag}
|
|
debugln(['TProjectInspectorForm.FormDropFiles ',length(FileNames)]);
|
|
{$ENDIF}
|
|
if length(FileNames)=0 then exit;
|
|
BeginUpdate;
|
|
try
|
|
for i:=0 to high(Filenames) do
|
|
if not (AddOneFile(FileNames[i]) in [mrOk, mrIgnore]) then break;
|
|
UpdateAll;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ItemsPopupMenuPopup(Sender: TObject);
|
|
var
|
|
ItemCnt: integer;
|
|
|
|
function AddPopupMenuItem(const ACaption: string; AnEvent: TNotifyEvent;
|
|
EnabledFlag: boolean = True): TMenuItem;
|
|
begin
|
|
if ItemsPopupMenu.Items.Count<=ItemCnt then begin
|
|
Result:=TMenuItem.Create(Self);
|
|
ItemsPopupMenu.Items.Add(Result);
|
|
end else
|
|
Result:=ItemsPopupMenu.Items[ItemCnt];
|
|
Result.Caption:=ACaption;
|
|
Result.OnClick:=AnEvent;
|
|
Result.Enabled:=EnabledFlag;
|
|
Result.Checked:=false;
|
|
Result.ShowAlwaysCheckable:=false;
|
|
Result.Visible:=true;
|
|
Result.RadioItem:=false;
|
|
Result.ImageIndex:=-1;
|
|
inc(ItemCnt);
|
|
end;
|
|
|
|
var
|
|
i: Integer;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
CanRemoveCount: Integer;
|
|
CanOpenCount: Integer;
|
|
HasLFMCount: Integer;
|
|
CurUnitInfo: TUnitInfo;
|
|
DisabledI18NForLFMCount: Integer;
|
|
CanReAddCount: Integer;
|
|
SingleSelectedDep: TPkgDependency;
|
|
DepCount: Integer;
|
|
Dependency: TPkgDependency;
|
|
HasValidDep: Integer;
|
|
CanClearDep: Integer;
|
|
CanMoveFileCount: Integer;
|
|
begin
|
|
ItemCnt:=0;
|
|
|
|
CanRemoveCount:=0;
|
|
CanOpenCount:=0;
|
|
CanMoveFileCount:=0;
|
|
HasLFMCount:=0;
|
|
DisabledI18NForLFMCount:=0;
|
|
CanReAddCount:=0;
|
|
SingleSelectedDep:=nil;
|
|
DepCount:=0;
|
|
HasValidDep:=0;
|
|
CanClearDep:=0;
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
|
|
if Item is TUnitInfo then begin
|
|
CurUnitInfo:=TUnitInfo(Item);
|
|
inc(CanOpenCount);
|
|
if (CurUnitInfo<>LazProject.MainUnitInfo) and (not NodeData.Removed) then begin
|
|
inc(CanRemoveCount);
|
|
inc(CanMoveFileCount);
|
|
end;
|
|
if FilenameIsPascalSource(CurUnitInfo.Filename)
|
|
and FileExistsCached(ChangeFileExt(CurUnitInfo.Filename,'.lfm')) then begin
|
|
inc(HasLFMCount);
|
|
if CurUnitInfo.DisableI18NForLFM then
|
|
inc(DisabledI18NForLFMCount);
|
|
end;
|
|
end else if Item is TPkgDependency then begin
|
|
Dependency:=TPkgDependency(Item);
|
|
if NodeData.Removed then begin
|
|
inc(CanReAddCount);
|
|
end else begin
|
|
inc(DepCount);
|
|
if DepCount=1 then
|
|
SingleSelectedDep:=Dependency
|
|
else
|
|
SingleSelectedDep:=nil;
|
|
inc(CanRemoveCount);
|
|
inc(CanOpenCount);
|
|
if Dependency.RequiredPackage<>nil then
|
|
inc(HasValidDep);
|
|
if (Dependency.DefaultFilename<>'') then
|
|
inc(CanClearDep);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if ItemsTreeView.Selected = FFilesNode then
|
|
begin
|
|
// Only the Files node is selected.
|
|
Assert(AddBitBtn.Enabled, 'AddBitBtn not Enabled');
|
|
AddPopupMenuItem(lisBtnDlgAdd, @mnuAddBitBtnClick);
|
|
if not LazProject.IsVirtual then
|
|
AddPopupMenuItem(lisRemoveNonExistingFiles,@RemoveNonExistingFilesMenuItemClick);
|
|
end
|
|
else if ItemsTreeView.Selected = FDependenciesNode then
|
|
begin
|
|
// Only the Required Packages node is selected.
|
|
AddPopupMenuItem(lisBtnDlgAdd, @mnuAddReqClick);
|
|
end
|
|
else begin
|
|
// Files, dependencies or everything mixed is selected.
|
|
if CanOpenCount>0 then
|
|
AddPopupMenuItem(lisOpen, @OpenButtonClick);
|
|
if CanRemoveCount>0 then
|
|
AddPopupMenuItem(lisRemove, @RemoveBitBtnClick);
|
|
// files section
|
|
if CanMoveFileCount>0 then
|
|
AddPopupMenuItem(lisCopyMoveFileToDirectory,@CopyMoveToDirMenuItemClick);
|
|
end;
|
|
|
|
if LazProject.EnableI18N and LazProject.EnableI18NForLFM
|
|
and (HasLFMCount>0) then begin
|
|
AddPopupMenuItem(lisEnableI18NForLFM,
|
|
@EnableI18NForLFMMenuItemClick, DisabledI18NForLFMCount>0);
|
|
AddPopupMenuItem(lisDisableI18NForLFM,
|
|
@DisableI18NForLFMMenuItemClick, DisabledI18NForLFMCount<HasLFMCount);
|
|
end;
|
|
|
|
// Required packages section
|
|
if CanReAddCount>0 then
|
|
AddPopupMenuItem(lisPckEditReAddDependency, @ReAddMenuItemClick, true);
|
|
if SingleSelectedDep<>nil then begin
|
|
AddPopupMenuItem(lisPckEditMoveDependencyUp, @MoveDependencyUpClick,
|
|
(SingleSelectedDep.PrevRequiresDependency<>nil));
|
|
AddPopupMenuItem(lisPckEditMoveDependencyDown, @MoveDependencyDownClick,
|
|
(SingleSelectedDep.NextRequiresDependency<>nil));
|
|
end;
|
|
if HasValidDep>0 then begin
|
|
AddPopupMenuItem(lisPckEditStoreFileNameAsDefaultForThisDependency,
|
|
@SetDependencyDefaultFilenameMenuItemClick, true);
|
|
AddPopupMenuItem(lisPckEditStoreFileNameAsPreferredForThisDependency,
|
|
@SetDependencyPreferredFilenameMenuItemClick, true);
|
|
end;
|
|
if CanClearDep>0 then begin
|
|
AddPopupMenuItem(lisPckEditClearDefaultPreferredFilenameOfDependency,
|
|
@ClearDependencyFilenameMenuItemClick, true);
|
|
end;
|
|
|
|
while ItemsPopupMenu.Items.Count>ItemCnt do
|
|
ItemsPopupMenu.Items.Delete(ItemsPopupMenu.Items.Count-1);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ItemsTreeViewAdvancedCustomDrawItem(
|
|
Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState;
|
|
Stage: TCustomDrawStage; var PaintImages, DefaultDraw: Boolean);
|
|
var
|
|
NodeData: TPENodeData;
|
|
r: TRect;
|
|
y: Integer;
|
|
begin
|
|
if Stage=cdPostPaint then begin
|
|
NodeData:=GetNodeData(Node);
|
|
if (NodeData<>nil) then begin
|
|
if (NodeData.Typ=penFile) and (not NodeData.Removed)
|
|
and FilenameIsAbsolute(NodeData.Name)
|
|
and (not FileExistsCached(NodeData.Name))
|
|
then begin
|
|
r:=Node.DisplayRect(true);
|
|
ItemsTreeView.Canvas.Pen.Color:=clRed;
|
|
y:=(r.Top+r.Bottom) div 2;
|
|
ItemsTreeView.Canvas.Line(r.Left,y,r.Right,y);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.OpenButtonClick(Sender: TObject);
|
|
var
|
|
i: Integer;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
CurFile: TUnitInfo;
|
|
CurDependency: TPkgDependency;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
|
|
if Item is TUnitInfo then begin
|
|
CurFile:=TUnitInfo(Item);
|
|
if LazarusIDE.DoOpenEditorFile(CurFile.Filename,-1,-1,[ofAddToRecent])<>mrOk
|
|
then exit;
|
|
end else if Item is TPkgDependency then begin
|
|
CurDependency:=TPkgDependency(Item);
|
|
if PackageEditingInterface.DoOpenPackageWithName(
|
|
CurDependency.PackageName,[],false)<>mrOk
|
|
then
|
|
exit;
|
|
end;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.OptionsBitBtnClick(Sender: TObject);
|
|
begin
|
|
if Assigned(OnShowOptions) then OnShowOptions(Self);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.HelpBitBtnClick(Sender: TObject);
|
|
begin
|
|
LazarusHelp.ShowHelpForIDEControl(Self);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ReAddMenuItemClick(Sender: TObject);
|
|
var
|
|
Dependency: TPkgDependency;
|
|
i: Integer;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
|
|
if not NodeData.Removed then continue;
|
|
if not (Item is TPkgDependency) then continue;
|
|
Dependency:=TPkgDependency(Item);
|
|
if not CheckAddingDependency(LazProject,Dependency) then exit;
|
|
if Assigned(OnReAddDependency) then
|
|
OnReAddDependency(Self,Dependency);
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.RemoveBitBtnClick(Sender: TObject);
|
|
var
|
|
CurDependency: TPkgDependency;
|
|
i: Integer;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
Msg: String;
|
|
DeleteCount: Integer;
|
|
CurFile: TUnitInfo;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
// check selection
|
|
Msg:='';
|
|
DeleteCount:=0;
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
|
|
if Item is TUnitInfo then begin
|
|
CurFile:=TUnitInfo(Item);
|
|
if CurFile=LazProject.MainUnitInfo then continue;
|
|
// remove file
|
|
inc(DeleteCount);
|
|
Msg:=Format(lisProjInspRemoveFileFromProject, [CurFile.Filename]);
|
|
end else if Item is TPkgDependency then begin
|
|
CurDependency:=TPkgDependency(item);
|
|
if NodeData.Removed then continue;
|
|
// remove dependency
|
|
inc(DeleteCount);
|
|
Msg:=Format(lisProjInspDeleteDependencyFor, [CurDependency.AsString]);
|
|
end;
|
|
end;
|
|
|
|
// ask for confirmation
|
|
if DeleteCount=0 then exit;
|
|
if DeleteCount>1 then
|
|
Msg:=Format(lisProjInspRemoveItemsF, [IntToStr(DeleteCount)]);
|
|
if IDEMessageDialog(lisProjInspConfirmDeletingDependency,
|
|
Msg, mtConfirmation,[mbYes,mbNo])<>mrYes then exit;
|
|
|
|
// delete
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
|
|
if Item is TUnitInfo then begin
|
|
CurFile:=TUnitInfo(Item);
|
|
if CurFile=LazProject.MainUnitInfo then continue;
|
|
// remove file
|
|
if Assigned(OnRemoveFile) then OnRemoveFile(Self,CurFile);
|
|
end else if Item is TPkgDependency then begin
|
|
CurDependency:=TPkgDependency(item);
|
|
if NodeData.Removed then continue;
|
|
// remove dependency
|
|
if Assigned(OnRemoveDependency) then
|
|
OnRemoveDependency(Self,CurDependency);
|
|
end;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.RemoveNonExistingFilesMenuItemClick(Sender: TObject);
|
|
var
|
|
AnUnitInfo: TUnitInfo;
|
|
NextUnitInfo: TUnitInfo;
|
|
HasChanged: Boolean;
|
|
begin
|
|
if LazProject.IsVirtual then exit;
|
|
BeginUpdate;
|
|
try
|
|
HasChanged:=false;
|
|
AnUnitInfo:=LazProject.FirstPartOfProject;
|
|
while AnUnitInfo<>nil do begin
|
|
NextUnitInfo:=AnUnitInfo.NextPartOfProject;
|
|
if not (AnUnitInfo.IsVirtual or FileExistsUTF8(AnUnitInfo.Filename)) then begin
|
|
AnUnitInfo.IsPartOfProject:=false;
|
|
HasChanged:=true;
|
|
end;
|
|
AnUnitInfo:=NextUnitInfo;
|
|
end;
|
|
if HasChanged then begin
|
|
LazProject.Modified:=true;
|
|
UpdateProjectFiles;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SortAlphabeticallyButtonClick(Sender: TObject);
|
|
begin
|
|
SortAlphabetically:=SortAlphabeticallyButton.Down;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.EnableI18NForLFMMenuItemClick(Sender: TObject);
|
|
begin
|
|
EnableI18NForSelectedLFM(true);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.DisableI18NForLFMMenuItemClick(Sender: TObject);
|
|
begin
|
|
EnableI18NForSelectedLFM(false);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SetLazProject(const AValue: TProject);
|
|
begin
|
|
if FLazProject=AValue then exit;
|
|
if FLazProject<>nil then begin
|
|
dec(FUpdateLock,LazProject.UpdateLock);
|
|
FLazProject.OnBeginUpdate:=nil;
|
|
FLazProject.OnEndUpdate:=nil;
|
|
end;
|
|
FLazProject:=AValue;
|
|
if FLazProject<>nil then begin
|
|
inc(FUpdateLock,LazProject.UpdateLock);
|
|
FLazProject.OnBeginUpdate:=@OnProjectBeginUpdate;
|
|
FLazProject.OnEndUpdate:=@OnProjectEndUpdate;
|
|
end;
|
|
UpdateAll;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SetShowDirectoryHierarchy(const AValue: boolean);
|
|
begin
|
|
if FShowDirectoryHierarchy=AValue then exit;
|
|
FShowDirectoryHierarchy:=AValue;
|
|
DirectoryHierarchyButton.Down:=FShowDirectoryHierarchy;
|
|
FilterEdit.ShowDirHierarchy:=FShowDirectoryHierarchy;
|
|
FilterEdit.InvalidateFilter;
|
|
EnvironmentOptions.ProjInspShowDirHierarchy := ShowDirectoryHierarchy;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SetSortAlphabetically(const AValue: boolean);
|
|
begin
|
|
if FSortAlphabetically=AValue then exit;
|
|
FSortAlphabetically:=AValue;
|
|
SortAlphabeticallyButton.Down:=FSortAlphabetically;
|
|
FilterEdit.SortData:=FSortAlphabetically;
|
|
FilterEdit.InvalidateFilter;
|
|
EnvironmentOptions.ProjInspSortAlphabetically := SortAlphabetically;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SetDependencyDefaultFilename(AsPreferred: boolean);
|
|
var
|
|
NewFilename: String;
|
|
CurDependency: TPkgDependency;
|
|
i: Integer;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
|
|
if NodeData.Removed then continue;
|
|
if not (Item is TPkgDependency) then continue;
|
|
CurDependency:=TPkgDependency(Item);
|
|
if CurDependency.RequiredPackage=nil then continue;
|
|
NewFilename:=CurDependency.RequiredPackage.Filename;
|
|
if (NewFilename=CurDependency.DefaultFilename) // do not use CompareFilenames
|
|
and (CurDependency.PreferDefaultFilename=AsPreferred) then continue;
|
|
CurDependency.DefaultFilename:=NewFilename;
|
|
CurDependency.PreferDefaultFilename:=AsPreferred;
|
|
LazProject.Modified:=true;
|
|
UpdateRequiredPackages;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SetIdleConnected(AValue: boolean);
|
|
begin
|
|
if csDestroying in ComponentState then
|
|
AValue:=false;
|
|
if FIdleConnected=AValue then exit;
|
|
FIdleConnected:=AValue;
|
|
if FIdleConnected then
|
|
Application.AddOnIdleHandler(@IdleHandler)
|
|
else
|
|
Application.RemoveOnIdleHandler(@IdleHandler);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SetupComponents;
|
|
|
|
function CreateToolButton(AName, ACaption, AHint, AImageName: String; AOnClick: TNotifyEvent): TToolButton;
|
|
begin
|
|
Result := TToolButton.Create(Self);
|
|
Result.Name := AName;
|
|
Result.Caption := ACaption;
|
|
Result.Hint := AHint;
|
|
if AImageName <> '' then
|
|
Result.ImageIndex := IDEImages.LoadImage(16, AImageName);
|
|
Result.ShowHint := True;
|
|
Result.OnClick := AOnClick;
|
|
Result.AutoSize := True;
|
|
Result.Parent := ToolBar;
|
|
end;
|
|
|
|
function CreateDivider: TToolButton;
|
|
begin
|
|
Result := TToolButton.Create(Self);
|
|
Result.Style := tbsDivider;
|
|
Result.AutoSize := True;
|
|
Result.Parent := ToolBar;
|
|
end;
|
|
|
|
begin
|
|
ImageIndexFiles := IDEImages.LoadImage(16, 'pkg_files');
|
|
ImageIndexRequired := IDEImages.LoadImage(16, 'pkg_required');
|
|
ImageIndexConflict := IDEImages.LoadImage(16, 'pkg_conflict');
|
|
ImageIndexRemovedRequired := IDEImages.LoadImage(16, 'pkg_removedrequired');
|
|
ImageIndexProject := IDEImages.LoadImage(16, 'item_project');
|
|
ImageIndexUnit := IDEImages.LoadImage(16, 'item_unit');
|
|
ImageIndexRegisterUnit := IDEImages.LoadImage(16, 'pkg_registerunit');
|
|
ImageIndexText := IDEImages.LoadImage(16, 'pkg_text');
|
|
ImageIndexBinary := IDEImages.LoadImage(16, 'pkg_binary');
|
|
ImageIndexDirectory := IDEImages.LoadImage(16, 'pkg_files');
|
|
|
|
ItemsTreeView.Images := IDEImages.Images_16;
|
|
ToolBar.Images := IDEImages.Images_16;
|
|
FilterEdit.OnGetImageIndex:=@OnTreeViewGetImageIndex;
|
|
|
|
AddBitBtn := CreateToolButton('AddBitBtn', lisAddSub, lisClickToSeeTheChoices, 'laz_add', nil);
|
|
RemoveBitBtn := CreateToolButton('RemoveBitBtn', lisRemove, lisPckEditRemoveSelectedItem, 'laz_delete', @RemoveBitBtnClick);
|
|
CreateDivider;
|
|
OptionsBitBtn := CreateToolButton('OptionsBitBtn', lisOptions, lisPckEditEditGeneralOptions, 'menu_environment_options', @OptionsBitBtnClick);
|
|
HelpBitBtn := CreateToolButton('HelpBitBtn', GetButtonCaption(idButtonHelp), lisMenuOnlineHelp, 'menu_help', @HelpBitBtnClick);
|
|
|
|
AddBitBtn.DropdownMenu:=AddPopupMenu;
|
|
mnuAddDiskFile.Caption:=lisPckEditAddFilesFromFileSystem;
|
|
mnuAddDiskFiles.Caption:=lisAddFilesInDirectory;
|
|
mnuAddEditorFiles.Caption:=lisProjAddEditorFile;
|
|
mnuAddReq.Caption:=lisProjAddNewRequirement;
|
|
|
|
OpenButton.LoadGlyphFromResourceName(HInstance, 'laz_open');
|
|
OpenButton.Caption:='';
|
|
OpenButton.Hint:=lisOpenFile2;
|
|
SortAlphabeticallyButton.Hint:=lisPESortFilesAlphabetically;
|
|
SortAlphabeticallyButton.LoadGlyphFromResourceName(HInstance, 'pkg_sortalphabetically');
|
|
DirectoryHierarchyButton.Hint:=lisPEShowDirectoryHierarchy;
|
|
DirectoryHierarchyButton.LoadGlyphFromResourceName(HInstance, 'pkg_hierarchical');
|
|
|
|
with ItemsTreeView do begin
|
|
FFilesNode:=Items.Add(nil, dlgEnvFiles);
|
|
FFilesNode.ImageIndex:=ImageIndexFiles;
|
|
FFilesNode.SelectedIndex:=FFilesNode.ImageIndex;
|
|
FDependenciesNode:=Items.Add(nil, lisPckEditRequiredPackages);
|
|
FDependenciesNode.ImageIndex:=ImageIndexRequired;
|
|
FDependenciesNode.SelectedIndex:=FDependenciesNode.ImageIndex;
|
|
end;
|
|
end;
|
|
|
|
function TProjectInspectorForm.OnTreeViewGetImageIndex(Str: String; Data: TObject;
|
|
var AIsEnabled: Boolean): Integer;
|
|
var
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
begin
|
|
Result := -1;
|
|
if not (Data is TPENodeData) then exit;
|
|
NodeData:=TPENodeData(Data);
|
|
Item:=GetNodeItem(NodeData);
|
|
if Item=nil then exit;
|
|
|
|
if Item is TUnitInfo then begin
|
|
if FilenameIsPascalUnit(TUnitInfo(Item).Filename) then
|
|
Result:=ImageIndexUnit
|
|
else if (LazProject<>nil) and (LazProject.MainUnitinfo=Item) then
|
|
Result:=ImageIndexProject
|
|
else
|
|
Result:=ImageIndexText;
|
|
end
|
|
else if Item is TPkgDependency then begin
|
|
if TPkgDependency(Item).Removed then
|
|
Result:=ImageIndexRemovedRequired
|
|
else if TPkgDependency(Item).LoadPackageResult=lprSuccess then
|
|
Result:=ImageIndexRequired
|
|
else
|
|
Result:=ImageIndexConflict;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdateProjectFiles;
|
|
var
|
|
CurFile: TUnitInfo;
|
|
FilesBranch: TTreeFilterBranch;
|
|
Filename: String;
|
|
ANodeData : TPENodeData;
|
|
begin
|
|
if not CanUpdate(pifNeedUpdateFiles) then exit;
|
|
ItemsTreeView.BeginUpdate;
|
|
try
|
|
FilesBranch:=FilterEdit.GetCleanBranch(FFilesNode);
|
|
FilesBranch.ClearNodeData;
|
|
FreeNodeData(penFile);
|
|
if LazProject<>nil then begin
|
|
FilterEdit.SelectedPart:=FNextSelectedPart;
|
|
FilterEdit.ShowDirHierarchy:=ShowDirectoryHierarchy;
|
|
FilterEdit.SortData:=SortAlphabetically;
|
|
FilterEdit.ImageIndexDirectory:=ImageIndexDirectory;
|
|
// collect and sort files
|
|
CurFile:=LazProject.FirstPartOfProject;
|
|
while CurFile<>nil do begin
|
|
Filename:=CurFile.GetShortFilename(true);
|
|
if Filename<>'' then Begin
|
|
ANodeData := CreateNodeData(penFile, CurFile.Filename, False);
|
|
FilesBranch.AddNodeData(Filename, ANodeData, CurFile.Filename);
|
|
end;
|
|
CurFile:=CurFile.NextPartOfProject;
|
|
end;
|
|
end;
|
|
FilterEdit.InvalidateFilter; // Data is shown by FilterEdit.
|
|
finally
|
|
ItemsTreeView.EndUpdate;
|
|
end;
|
|
UpdateButtons;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdateRequiredPackages;
|
|
var
|
|
Dependency: TPkgDependency;
|
|
RequiredBranch, RemovedBranch: TTreeFilterBranch;
|
|
NodeText, AFilename: String;
|
|
ANodeData : TPENodeData;
|
|
begin
|
|
if not CanUpdate(pifNeedUpdateDependencies) then exit;
|
|
ItemsTreeView.BeginUpdate;
|
|
try
|
|
RequiredBranch:=FilterEdit.GetCleanBranch(FDependenciesNode);
|
|
RequiredBranch.ClearNodeData;
|
|
FreeNodeData(penDependency);
|
|
Dependency:=Nil;
|
|
if LazProject<>nil then begin
|
|
// required packages
|
|
Dependency:=LazProject.FirstRequiredDependency;
|
|
while Dependency<>nil do begin
|
|
// Figure out the item's caption
|
|
NodeText:=Dependency.AsString;
|
|
if Dependency.DefaultFilename<>'' then begin
|
|
AFilename:=Dependency.MakeFilenameRelativeToOwner(Dependency.DefaultFilename);
|
|
if Dependency.PreferDefaultFilename then
|
|
NodeText:=Format(lisCEIn, [NodeText,AFilename]) // like the 'in' keyword in the uses section
|
|
else
|
|
NodeText:=Format(lisPckEditDefault, [NodeText, AFilename]);
|
|
end;
|
|
// Add the required package under the branch
|
|
ANodeData := CreateNodeData(penDependency, Dependency.PackageName, False);
|
|
RequiredBranch.AddNodeData(NodeText, ANodeData);
|
|
Dependency:=Dependency.NextRequiresDependency;
|
|
end;
|
|
|
|
// removed required packages
|
|
Dependency:=LazProject.FirstRemovedDependency;
|
|
if Dependency<>nil then begin
|
|
// Create root node for removed dependencies if not done yet.
|
|
if FRemovedDependenciesNode=nil then begin
|
|
FRemovedDependenciesNode:=ItemsTreeView.Items.Add(FDependenciesNode,
|
|
lisProjInspRemovedRequiredPackages);
|
|
FRemovedDependenciesNode.ImageIndex:=ImageIndexRemovedRequired;
|
|
FRemovedDependenciesNode.SelectedIndex:=FRemovedDependenciesNode.ImageIndex;
|
|
end;
|
|
RemovedBranch:=FilterEdit.GetCleanBranch(FRemovedDependenciesNode);
|
|
// Add all removed dependencies under the branch
|
|
while Dependency<>nil do begin
|
|
ANodeData := CreateNodeData(penDependency, Dependency.PackageName, True);
|
|
RemovedBranch.AddNodeData(Dependency.AsString, ANodeData);
|
|
Dependency:=Dependency.NextRequiresDependency;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// Dependency is set to removed required packages if there is active project
|
|
if (Dependency=nil) and (FRemovedDependenciesNode<>nil) then begin
|
|
// No removed dependencies -> delete the root node
|
|
FilterEdit.DeleteBranch(FRemovedDependenciesNode);
|
|
FreeThenNil(FRemovedDependenciesNode);
|
|
end;
|
|
FilterEdit.InvalidateFilter;
|
|
finally
|
|
ItemsTreeView.EndUpdate;
|
|
end;
|
|
UpdateButtons;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.OnProjectBeginUpdate(Sender: TObject);
|
|
begin
|
|
BeginUpdate;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.OnProjectEndUpdate(Sender: TObject;
|
|
ProjectChanged: boolean);
|
|
begin
|
|
if ProjectChanged then
|
|
UpdateAll;
|
|
EndUpdate;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.EnableI18NForSelectedLFM(TheEnable: boolean);
|
|
var
|
|
i: Integer;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
CurUnitInfo: TUnitInfo;
|
|
begin
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
|
|
if not (Item is TUnitInfo) then continue;
|
|
CurUnitInfo:=TUnitInfo(Item);
|
|
if not FilenameIsPascalSource(CurUnitInfo.Filename) then continue;
|
|
CurUnitInfo.DisableI18NForLFM:=not TheEnable;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
inherited KeyDown(Key, Shift);
|
|
ExecuteIDEShortCut(Self,Key,Shift,nil);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.IdleHandler(Sender: TObject; var Done: Boolean);
|
|
begin
|
|
if IsUpdateLocked then begin
|
|
IdleConnected:=false;
|
|
exit;
|
|
end;
|
|
UpdatePending;
|
|
end;
|
|
|
|
function TProjectInspectorForm.GetSingleSelectedDependency: TPkgDependency;
|
|
var
|
|
Item: TObject;
|
|
NodeData: TPENodeData;
|
|
begin
|
|
Result:=nil;
|
|
if not GetNodeDataItem(ItemsTreeView.Selected,NodeData,Item) then exit;
|
|
if Item is TPkgDependency then
|
|
Result:=TPkgDependency(Item);
|
|
end;
|
|
|
|
function TProjectInspectorForm.TreeViewToInspector(TV: TTreeView): TProjectInspectorForm;
|
|
begin
|
|
if TV=ItemsTreeView then
|
|
Result:=Self
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
|
|
constructor TProjectInspectorForm.Create(TheOwner: TComponent);
|
|
begin
|
|
inherited Create(TheOwner);
|
|
Name:=NonModalIDEWindowNames[nmiwProjectInspector];
|
|
Caption:=lisMenuProjectInspector;
|
|
KeyPreview:=true;
|
|
SetupComponents;
|
|
KeyPreview:=true;
|
|
SortAlphabetically := EnvironmentOptions.ProjInspSortAlphabetically;
|
|
ShowDirectoryHierarchy := EnvironmentOptions.ProjInspShowDirHierarchy;
|
|
end;
|
|
|
|
destructor TProjectInspectorForm.Destroy;
|
|
var
|
|
nt: TPENodeType;
|
|
begin
|
|
IdleConnected:=false;
|
|
LazProject:=nil;
|
|
inherited Destroy;
|
|
for nt:=Low(TPENodeType) to High(TPENodeType) do
|
|
FreeNodeData(nt);
|
|
if ProjInspector=Self then
|
|
ProjInspector:=nil;
|
|
end;
|
|
|
|
function TProjectInspectorForm.ExtendIncSearchPath(NewIncPaths: string): boolean;
|
|
begin
|
|
Result:=MainIDEInterface.ExtendProjectIncSearchPath(LazProject,NewIncPaths);
|
|
end;
|
|
|
|
function TProjectInspectorForm.ExtendUnitSearchPath(NewUnitPaths: string): boolean;
|
|
begin
|
|
Result:=MainIDEInterface.ExtendProjectUnitSearchPath(LazProject,NewUnitPaths);
|
|
end;
|
|
|
|
function TProjectInspectorForm.FilesBaseDirectory: string;
|
|
begin
|
|
if LazProject<>nil then
|
|
Result:=LazProject.ProjectDirectory
|
|
else
|
|
Result:='';
|
|
end;
|
|
|
|
function TProjectInspectorForm.FilesEditForm: TCustomForm;
|
|
begin
|
|
Result:=Self;
|
|
end;
|
|
|
|
function TProjectInspectorForm.FilesEditTreeView: TTreeView;
|
|
begin
|
|
Result:=ItemsTreeView;
|
|
end;
|
|
|
|
function TProjectInspectorForm.FilesOwner: TObject;
|
|
begin
|
|
Result:=LazProject;
|
|
end;
|
|
|
|
function TProjectInspectorForm.FilesOwnerName: string;
|
|
begin
|
|
Result:=lisProject3;
|
|
end;
|
|
|
|
function TProjectInspectorForm.FilesOwnerReadOnly: boolean;
|
|
begin
|
|
Result:=false;
|
|
end;
|
|
|
|
function TProjectInspectorForm.FirstRequiredDependency: TPkgDependency;
|
|
begin
|
|
if LazProject<>nil then
|
|
Result:=LazProject.FirstRequiredDependency
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
|
|
function TProjectInspectorForm.GetNodeFilename(Node: TTreeNode): string;
|
|
var
|
|
Item: TFileNameItem;
|
|
begin
|
|
Result:='';
|
|
if Node=nil then exit;
|
|
if Node=FFilesNode then
|
|
exit(FilesBaseDirectory);
|
|
Item:=TFileNameItem(Node.Data);
|
|
if (Item is TFileNameItem) then begin
|
|
Result:=Item.Filename;
|
|
end else if Node.HasAsParent(FFilesNode) then begin
|
|
// directory node
|
|
Result:=Node.Text;
|
|
end else
|
|
exit;
|
|
if not FilenameIsAbsolute(Result) then
|
|
Result:=AppendPathDelim(FilesBaseDirectory)+Result;
|
|
end;
|
|
|
|
function TProjectInspectorForm.IsDirectoryNode(Node: TTreeNode): boolean;
|
|
begin
|
|
Result:=(Node<>nil) and (Node.Data=nil) and Node.HasAsParent(FFilesNode);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.BeginUpdate;
|
|
begin
|
|
inc(FUpdateLock);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.EndUpdate;
|
|
begin
|
|
if FUpdateLock=0 then RaiseException('TProjectInspectorForm.EndUpdate');
|
|
dec(FUpdateLock);
|
|
if FUpdateLock=0 then
|
|
IdleConnected:=true;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdateAll(Immediately: boolean);
|
|
begin
|
|
ItemsTreeView.BeginUpdate;
|
|
try
|
|
UpdateTitle;
|
|
UpdateProjectFiles;
|
|
UpdateRequiredPackages;
|
|
UpdateButtons;
|
|
if Immediately then
|
|
UpdatePending;
|
|
finally
|
|
ItemsTreeView.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdateTitle;
|
|
var
|
|
NewCaption: String;
|
|
begin
|
|
if not CanUpdate(pifNeedUpdateTitle) then exit;
|
|
|
|
if LazProject=nil then
|
|
Caption:=lisMenuProjectInspector
|
|
else begin
|
|
NewCaption:=LazProject.GetTitle;
|
|
if NewCaption='' then
|
|
NewCaption:=ExtractFilenameOnly(LazProject.ProjectInfoFile);
|
|
Caption:=Format(lisProjInspProjectInspector, [NewCaption]);
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdateButtons;
|
|
var
|
|
i: Integer;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
CanRemoveCount: Integer;
|
|
CurUnitInfo: TUnitInfo;
|
|
CanOpenCount: Integer;
|
|
begin
|
|
if not CanUpdate(pifNeedUpdateButtons) then exit;
|
|
|
|
if LazProject<>nil then begin
|
|
AddBitBtn.Enabled:=true;
|
|
|
|
CanRemoveCount:=0;
|
|
CanOpenCount:=0;
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
|
|
if Item is TUnitInfo then begin
|
|
CurUnitInfo:=TUnitInfo(Item);
|
|
inc(CanOpenCount);
|
|
if CurUnitInfo<>LazProject.MainUnitInfo then
|
|
inc(CanRemoveCount);
|
|
end else if Item is TPkgDependency then begin
|
|
if not NodeData.Removed then begin
|
|
inc(CanRemoveCount);
|
|
inc(CanOpenCount);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
RemoveBitBtn.Enabled:=(CanRemoveCount>0);
|
|
OpenButton.Enabled:=(CanOpenCount>0);
|
|
OptionsBitBtn.Enabled:=true;
|
|
end else begin
|
|
AddBitBtn.Enabled:=false;
|
|
RemoveBitBtn.Enabled:=false;
|
|
OpenButton.Enabled:=false;
|
|
OptionsBitBtn.Enabled:=false;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdatePending;
|
|
begin
|
|
ItemsTreeView.BeginUpdate;
|
|
try
|
|
if pifNeedUpdateFiles in FFlags then
|
|
UpdateProjectFiles;
|
|
if pifNeedUpdateDependencies in FFlags then
|
|
UpdateRequiredPackages;
|
|
if pifNeedUpdateTitle in FFlags then
|
|
UpdateTitle;
|
|
if pifNeedUpdateButtons in FFlags then
|
|
UpdateButtons;
|
|
IdleConnected:=false;
|
|
finally
|
|
ItemsTreeView.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TProjectInspectorForm.CanUpdate(Flag: TProjectInspectorFlag): boolean;
|
|
begin
|
|
Result:=false;
|
|
if csDestroying in ComponentState then exit;
|
|
if LazProject=nil then exit;
|
|
if IsUpdateLocked then begin
|
|
Include(fFlags,Flag);
|
|
IdleConnected:=true;
|
|
Result:=false;
|
|
end else begin
|
|
Exclude(fFlags,Flag);
|
|
Result:=true;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.FreeNodeData(Typ: TPENodeType);
|
|
var
|
|
NodeData,
|
|
n: TPENodeData;
|
|
begin
|
|
NodeData:=FProjectNodeDataList[Typ];
|
|
while NodeData<>nil do begin
|
|
n:=NodeData;
|
|
NodeData:=NodeData.Next;
|
|
n.Free;
|
|
end;
|
|
FProjectNodeDataList[Typ]:=nil;
|
|
End;
|
|
|
|
function TProjectInspectorForm.CreateNodeData(Typ: TPENodeType;
|
|
aName: string; aRemoved: boolean): TPENodeData;
|
|
Begin
|
|
Result := TPENodeData.Create(Typ,aName,aRemoved);
|
|
Result.Next := FProjectNodeDataList[Typ];
|
|
FProjectNodeDataList[Typ] := Result;
|
|
end;
|
|
|
|
function TProjectInspectorForm.GetNodeData(TVNode: TTreeNode): TPENodeData;
|
|
var
|
|
o: TObject;
|
|
begin
|
|
Result:=nil;
|
|
if (TVNode=nil) then exit;
|
|
o:=TObject(TVNode.Data);
|
|
if o is TFileNameItem then
|
|
o:=TObject(TFileNameItem(o).Data);
|
|
if o is TPENodeData then
|
|
Result:=TPENodeData(o);
|
|
end;
|
|
|
|
function TProjectInspectorForm.GetNodeItem(NodeData: TPENodeData): TObject;
|
|
begin
|
|
Result:=nil;
|
|
if (LazProject=nil) or (NodeData=nil) then exit;
|
|
case NodeData.Typ of
|
|
penFile:
|
|
if NodeData.Removed then
|
|
Result:=nil
|
|
else
|
|
Result:=LazProject.UnitInfoWithFilename(NodeData.Name,[pfsfOnlyProjectFiles]);
|
|
penDependency:
|
|
if NodeData.Removed then
|
|
Result:=LazProject.FindRemovedDependencyByName(NodeData.Name)
|
|
else
|
|
Result:=LazProject.FindDependencyByName(NodeData.Name);
|
|
end;
|
|
end;
|
|
|
|
function TProjectInspectorForm.GetNodeDataItem(TVNode: TTreeNode; out
|
|
NodeData: TPENodeData; out Item: TObject): boolean;
|
|
begin
|
|
Result:=false;
|
|
Item:=nil;
|
|
NodeData:=GetNodeData(TVNode);
|
|
Item:=GetNodeItem(NodeData);
|
|
Result:=Item<>nil;
|
|
end;
|
|
|
|
end.
|
|
|