mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-05 15:37:50 +02:00
2113 lines
69 KiB
ObjectPascal
2113 lines
69 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, 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,
|
|
// LCL
|
|
LCLType, LCLIntf, LResources, Forms, Controls, Buttons, ComCtrls, Menus, Dialogs,
|
|
ExtCtrls, StdCtrls, Graphics,
|
|
// LazControls
|
|
TreeFilterEdit,
|
|
// LazUtils
|
|
FileUtil, LazFileUtils, LazUtilities, LazLoggerBase, LazTracer, LazFileCache,
|
|
// Codetools
|
|
CodeToolsStructs, CodeToolManager, FileProcs, CodeCache, CodeTree, FindDeclarationTool,
|
|
// BuildIntf
|
|
ProjectIntf, PackageIntf, PackageLinkIntf, PackageDependencyIntf,
|
|
// IDEIntf
|
|
IDEHelpIntf, IDECommands, IDEDialogs, IDEImagesIntf, LazIDEIntf, ToolBarIntf,
|
|
IdeIntfStrConsts, MenuIntf, FormEditingIntf, SrcEditorIntf, InputHistory,
|
|
// IdeConfig
|
|
EnvironmentOpts, IDEOptionDefs, TransferMacros, IDEProcs,
|
|
// IDE
|
|
LazarusIDEStrConsts, MainBase, MainBar, DialogProcs, Project,
|
|
BuildManager, AddToProjectDlg, EnvGuiOptions,
|
|
BasePkgManager, ProjPackChecks, ProjPackEditing, ProjPackFilePropGui, PackageDefs,
|
|
AddPkgDependencyDlg, AddFPMakeDependencyDlg;
|
|
|
|
const
|
|
ProjectInspectorMenuItemsRootName = 'ProjectInspectorItems';
|
|
ProjectInspectorMenuAddRootName = 'ProjectInspectorAdd';
|
|
var
|
|
// items popupmenu: files
|
|
ProjInspMenuAddDiskFile: TIDEMenuCommand;
|
|
ProjInspMenuRemoveNonExistingFiles: TIDEMenuCommand;
|
|
ProjInspMenuOpenFolder: TIDEMenuCommand;
|
|
ProjInspMenuOpen: TIDEMenuCommand; // open file or dependency
|
|
ProjInspMenuRemove: TIDEMenuCommand;
|
|
ProjInspMenuCopyMoveFileToDir: TIDEMenuCommand;
|
|
ProjInspMenuEnableI18NForLFM: TIDEMenuCommand;
|
|
ProjInspMenuDisableI18NForLFM: TIDEMenuCommand;
|
|
|
|
// items popupmenu: dependencies
|
|
ProjInspMenuAddDependency: TIDEMenuCommand;
|
|
ProjInspMenuReAddDependency: TIDEMenuCommand;
|
|
ProjInspMenuMoveDependencyUp: TIDEMenuCommand;
|
|
ProjInspMenuMoveDependencyDown: TIDEMenuCommand;
|
|
ProjInspMenuStoreFilenameAsDefaultOfDependencyDown: TIDEMenuCommand;
|
|
ProjInspMenuStoreFilenameAsPreferredOfDependencyDown: TIDEMenuCommand;
|
|
ProjInspMenuClearPreferredFilenameOfDependencyDown: TIDEMenuCommand;
|
|
|
|
// add popupmenu
|
|
ProjInspAddMenuDiskFile: TIDEMenuCommand;
|
|
ProjInspAddMenuEditorFiles: TIDEMenuCommand;
|
|
ProjInspAddMenuDependency: TIDEMenuCommand;
|
|
ProjInspAddMenuFPMakeDependency: TIDEMenuCommand;
|
|
|
|
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;
|
|
|
|
{ TProjectInspectorForm }
|
|
|
|
TProjectInspectorForm = class(TForm,IFilesEditorInterface)
|
|
AddPopupMenu: TPopupMenu;
|
|
FilterPanel: TPanel;
|
|
DirectoryHierarchyButton: TSpeedButton;
|
|
FilterEdit: TTreeFilterEdit;
|
|
PropsGroupBox: TGroupBox;
|
|
OpenButton: TSpeedButton;
|
|
ItemsTreeView: TTreeView;
|
|
ItemsPopupMenu: TPopupMenu;
|
|
SortAlphabeticallyButton: TSpeedButton;
|
|
ShowPropsPanelButton: TSpeedButton;
|
|
Splitter1: TSplitter;
|
|
// toolbar
|
|
ToolBar: TToolBar;
|
|
// toolbuttons
|
|
AddBitBtn: TToolButton;
|
|
RemoveBitBtn: TToolButton;
|
|
OptionsBitBtn: TToolButton;
|
|
HelpBitBtn: TToolButton;
|
|
procedure AddPopupMenuPopup(Sender: TObject);
|
|
procedure CopyMoveToDirMenuItemClick(Sender: TObject);
|
|
procedure DirectoryHierarchyButtonClick(Sender: TObject);
|
|
procedure FilterEditAfterFilter(Sender: TObject);
|
|
procedure FilterEditKeyDown(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState);
|
|
procedure FormActivate(Sender: TObject);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormDeactivate(Sender: TObject);
|
|
procedure FormDestroy(Sender: TObject);
|
|
procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
|
|
procedure FormResize(Sender: TObject);
|
|
procedure FormShow(Sender: TObject);
|
|
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 mnuAddDiskFileClick(Sender: TObject);
|
|
procedure mnuAddEditorFilesClick(Sender: TObject);
|
|
procedure mnuAddFPMakeReqClick(Sender: TObject);
|
|
procedure mnuAddReqClick(Sender: TObject);
|
|
procedure mnuOpenFolderClick(Sender: TObject);
|
|
procedure MoveDependencyUpClick(Sender: TObject);
|
|
procedure MoveDependencyDownClick(Sender: TObject);
|
|
procedure PropsGroupBoxResize(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 ShowPropsPanelButtonClick(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;
|
|
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;
|
|
ImageIndexProject: integer;
|
|
ImageIndexUnit: integer;
|
|
ImageIndexRegisterUnit: integer;
|
|
ImageIndexText: integer;
|
|
ImageIndexBinary: integer;
|
|
ImageIndexDirectory: integer;
|
|
FFlags: TPEFlags;
|
|
FPropGui: TProjPackFilePropGui;
|
|
procedure ActiveEditorChanged(Sender: TObject);
|
|
procedure AddMenuItemClick(Sender: TObject);
|
|
function AddOneFile(aFilename: string): TModalResult;
|
|
procedure DoAddMoreDialog;
|
|
procedure DoAddDepDialog;
|
|
procedure DoAddFPMakeDepDialog;
|
|
function CreateToolButton(AName, ACaption, AHint, AImageName: String;
|
|
AOnClick: TNotifyEvent): TToolButton;
|
|
function CreateDivider: TToolButton;
|
|
procedure OptionsChanged(Sender: TObject; {%H-}Restore: boolean);
|
|
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 GetDependencyToUpdate(Immediately: boolean): TPkgDependencyID;
|
|
function GetSingleSelectedDependency: TPkgDependency;
|
|
procedure ApplyDependencyButtonClick(Sender: TObject);
|
|
function TreeViewGetImageIndex({%H-}Str: String; Data: TObject; var {%H-}AIsEnabled: Boolean): Integer;
|
|
procedure ProjectBeginUpdate(Sender: TObject);
|
|
procedure ProjectEndUpdate(Sender: TObject; ProjectChanged: boolean);
|
|
procedure EnableI18NForSelectedLFM(TheEnable: boolean);
|
|
procedure PackageListAvailable(Sender: TObject);
|
|
function CanUpdate(Flag: TPEFlag; Immediately: boolean): boolean;
|
|
procedure UpdateFiles(Immediately: boolean = false);
|
|
procedure UpdateProperties(Immediately: boolean = false);
|
|
procedure UpdateButtons(Immediately: boolean = false);
|
|
procedure UpdatePending;
|
|
procedure SelectFileNode(const AFileName: string);
|
|
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(Immediately: boolean = false);
|
|
procedure UpdateRequiredPackages(Immediately: boolean = false);
|
|
function TreeViewToInspector(TV: TTreeView): TProjectInspectorForm;
|
|
function GetSelectedItems: TFPList;
|
|
public
|
|
// IFilesEditorInterface
|
|
procedure BeginUpdate;
|
|
procedure EndUpdate;
|
|
procedure UpdateAll(Immediately: boolean = false);
|
|
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 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;
|
|
|
|
{ TSetBuildModeToolButton }
|
|
|
|
TSetBuildModeToolButton = class(TIDEToolButton)
|
|
public type
|
|
TBuildModeMenuItem = class(TMenuItem)
|
|
public
|
|
BuildModeIndex: Integer;
|
|
procedure Click; override;
|
|
end;
|
|
|
|
TBuildModeMenu = class(TPopupMenu)
|
|
protected
|
|
procedure DoPopup(Sender: TObject); override;
|
|
end;
|
|
public
|
|
procedure DoOnAdded; override;
|
|
end;
|
|
|
|
var
|
|
ProjInspector: TProjectInspectorForm = nil;
|
|
|
|
|
|
function UpdateUnitInfoResourceBaseClass(AnUnitInfo: TUnitInfo; Quiet: boolean): boolean;
|
|
procedure RegisterStandardProjectInspectorMenuItems;
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
function UpdateUnitInfoResourceBaseClass(AnUnitInfo: TUnitInfo; Quiet: boolean): boolean;
|
|
|
|
procedure ClearUnitResInfo;
|
|
begin
|
|
AnUnitInfo.ResourceBaseClass:=pfcbcNone;
|
|
AnUnitInfo.ResourceBaseClassname:='';
|
|
AnUnitInfo.ComponentName:='';
|
|
AnUnitInfo.ComponentResourceName:='';
|
|
end;
|
|
|
|
var
|
|
LFMFilename, LFMType, Ancestor, LFMClassName, LFMComponentName: String;
|
|
LFMCode, Code: TCodeBuffer;
|
|
LoadFileFlags: TLoadBufferFlags;
|
|
ClearOldInfo: Boolean;
|
|
Tool: TCodeTool;
|
|
Node: TCodeTreeNode;
|
|
ListOfPFindContext: TFPList;
|
|
i: Integer;
|
|
Context: PFindContext;
|
|
CompClass, aDesignerBaseClass: TComponentClass;
|
|
begin
|
|
Result:=false;
|
|
if AnUnitInfo.Component<>nil then
|
|
exit(true); // a loaded resource is always uptodate
|
|
if AnUnitInfo.IsVirtual then
|
|
exit(true); // a new unit is always uptodate
|
|
ListOfPFindContext:=nil;
|
|
ClearOldInfo:=true;
|
|
try
|
|
// find lfm file
|
|
if not FilenameIsPascalUnit(AnUnitInfo.Filename) then
|
|
exit(true); // not a unit -> clear info
|
|
LFMFilename:=AnUnitInfo.UnitResourceFileformat.GetUnitResourceFilename(
|
|
AnUnitInfo.Filename,true);
|
|
if (LFMFilename='') or not FileExistsCached(LFMFilename) then
|
|
exit(true); // no lfm -> clear info
|
|
finally
|
|
if ClearOldInfo then begin
|
|
ClearUnitResInfo;
|
|
end;
|
|
end;
|
|
try
|
|
if not FilenameExtIs(LFMFilename,'lfm',true) then
|
|
exit(true); // no lfm format -> keep old info
|
|
// clear old info
|
|
ClearUnitResInfo;
|
|
// load lfm
|
|
LoadFileFlags:=[lbfUpdateFromDisk,lbfCheckIfText];
|
|
if Quiet then
|
|
Include(LoadFileFlags,lbfQuiet);
|
|
if LoadCodeBuffer(LFMCode,LFMFilename,LoadFileFlags,false)<>mrOk then
|
|
exit; // lfm read error
|
|
// read lfm header
|
|
ReadLFMHeader(LFMCode.Source,LFMType,LFMComponentName,LFMClassName);
|
|
if LFMClassName='' then
|
|
exit; // lfm syntax error
|
|
|
|
// LFM component name
|
|
AnUnitInfo.ComponentName:=LFMComponentName;
|
|
AnUnitInfo.ComponentResourceName:=LFMComponentName;
|
|
|
|
// check ancestors
|
|
if LoadCodeBuffer(Code,AnUnitInfo.Filename,LoadFileFlags,false)<>mrOk then
|
|
exit; // pas read error
|
|
CodeToolBoss.Explore(Code,Tool,false,true);
|
|
if Tool=nil then
|
|
exit; // pas load error
|
|
aDesignerBaseClass:=nil;
|
|
try
|
|
Node:=Tool.FindDeclarationNodeInInterface(LFMClassName,true);
|
|
if Node=nil then
|
|
exit(Tool.FindImplementationNode<>nil); // class not found, reliable if whole interface was read
|
|
|
|
if (Node.Desc<>ctnTypeDefinition)
|
|
or (Node.FirstChild=nil) or (Node.FirstChild.Desc<>ctnClass) then
|
|
exit(true); // this is not a class
|
|
Tool.FindClassAndAncestors(Node.FirstChild,ListOfPFindContext,false);
|
|
if ListOfPFindContext=nil then
|
|
exit; // ancestor not found -> probably syntax error
|
|
|
|
for i:=0 to ListOfPFindContext.Count-1 do begin
|
|
Context:=PFindContext(ListOfPFindContext[i]);
|
|
Ancestor:=UpperCase(Context^.Tool.ExtractClassName(Context^.Node,false));
|
|
case Ancestor of
|
|
'TFORM':
|
|
begin
|
|
AnUnitInfo.ResourceBaseClass:=pfcbcForm;
|
|
aDesignerBaseClass:=TForm;
|
|
end;
|
|
'TCUSTOMFORM':
|
|
begin
|
|
AnUnitInfo.ResourceBaseClass:=pfcbcCustomForm;
|
|
aDesignerBaseClass:=TCustomForm;
|
|
end;
|
|
'TDATAMODULE':
|
|
begin
|
|
AnUnitInfo.ResourceBaseClass:=pfcbcDataModule;
|
|
aDesignerBaseClass:=TDataModule;
|
|
end;
|
|
'TFRAME':
|
|
begin
|
|
AnUnitInfo.ResourceBaseClass:=pfcbcFrame;
|
|
aDesignerBaseClass:=TFrame;
|
|
end;
|
|
'TCUSTOMFRAME':
|
|
begin
|
|
AnUnitInfo.ResourceBaseClass:=pfcbcFrame;
|
|
aDesignerBaseClass:=TCustomFrame;
|
|
end;
|
|
'TCOMPONENT':
|
|
begin
|
|
CompClass:=FormEditingHook.FindDesignerBaseClassByName(Ancestor,false);
|
|
if CompClass<>nil then
|
|
begin
|
|
AnUnitInfo.ResourceBaseClass:=pfcbcOther;
|
|
aDesignerBaseClass:=CompClass;
|
|
end;
|
|
end;
|
|
end;
|
|
if aDesignerBaseClass<>nil then
|
|
begin
|
|
AnUnitInfo.ResourceBaseClassname:=aDesignerBaseClass.ClassName;
|
|
Result:=true;
|
|
break;
|
|
end;
|
|
end;
|
|
if aDesignerBaseClass=nil then exit;
|
|
except
|
|
exit; // syntax error or unit not found
|
|
end;
|
|
|
|
// Maybe auto-create it
|
|
if (LFMComponentName<>'')
|
|
and (pfMainUnitHasCreateFormStatements in Project1.Flags)
|
|
and Project1.AutoCreateForms
|
|
and FormEditingHook.DesignerClassCanAppCreateForm(aDesignerBaseClass)
|
|
and (IDEMessageDialog(lisAddToStartupComponents,
|
|
Format(lisShouldTheComponentBeAutoCreatedWhenTheApplicationS,
|
|
[LFMComponentName]),
|
|
mtInformation,[mbYes,mbNo])=mrYes)
|
|
then
|
|
Project1.AddCreateFormToProjectFile(LFMClassName,LFMComponentName);
|
|
finally
|
|
FreeListOfPFindContext(ListOfPFindContext);
|
|
end;
|
|
end;
|
|
|
|
procedure RegisterStandardProjectInspectorMenuItems;
|
|
var
|
|
AParent: TIDEMenuSection;
|
|
begin
|
|
// items popupmenu
|
|
ProjectInspectorItemsMenuRoot:=RegisterIDEMenuRoot(ProjectInspectorMenuItemsRootName);
|
|
|
|
// register the section for operations on selected files
|
|
ProjInspMenuSectionFiles:=RegisterIDEMenuSection(ProjectInspectorMenuItemsRootName,'Files');
|
|
AParent:=ProjInspMenuSectionFiles;
|
|
ProjInspMenuAddDiskFile:=RegisterIDEMenuCommand(AParent,'Add disk file',lisBtnDlgAdd);
|
|
ProjInspMenuRemoveNonExistingFiles:=RegisterIDEMenuCommand(AParent,'Remove non existing files',lisRemoveNonExistingFiles);
|
|
ProjInspMenuOpenFolder:=RegisterIDEMenuCommand(AParent,'Open folder',lisMenuOpenFolder);
|
|
ProjInspMenuAddDependency:=RegisterIDEMenuCommand(AParent,'Add dependency',lisBtnDlgAdd);
|
|
ProjInspMenuOpen:=RegisterIDEMenuCommand(AParent,'Open',lisBtnDlgAdd);
|
|
ProjInspMenuRemove:=RegisterIDEMenuCommand(AParent,'Remove',lisRemove);
|
|
ProjInspMenuCopyMoveFileToDir:=RegisterIDEMenuCommand(AParent,'Copy/Move File to Directory',lisCopyMoveFileToDirectory);
|
|
ProjInspMenuEnableI18NForLFM:=RegisterIDEMenuCommand(AParent,'Enable I18N for LFM',lisEnableI18NForLFM);
|
|
ProjInspMenuDisableI18NForLFM:=RegisterIDEMenuCommand(AParent,'Disable I18N for LFM',lisDisableI18NForLFM);
|
|
|
|
// register the section for operations on dependencies
|
|
ProjInspMenuSectionDependencies:=RegisterIDEMenuSection(ProjectInspectorMenuItemsRootName,'Dependencies');
|
|
AParent:=ProjInspMenuSectionDependencies;
|
|
ProjInspMenuReAddDependency:=RegisterIDEMenuCommand(AParent,'ReAdd dependency',lisPckEditReAddDependency);
|
|
ProjInspMenuMoveDependencyUp:=RegisterIDEMenuCommand(AParent,'Move dependency up',lisPckEditMoveDependencyUp);
|
|
ProjInspMenuMoveDependencyDown:=RegisterIDEMenuCommand(AParent,'Move dependency down',lisPckEditMoveDependencyDown);
|
|
ProjInspMenuStoreFilenameAsDefaultOfDependencyDown:=RegisterIDEMenuCommand(AParent,'Store filename as default of dependency',lisPckEditStoreFileNameAsDefaultForThisDependency);
|
|
ProjInspMenuStoreFilenameAsPreferredOfDependencyDown:=RegisterIDEMenuCommand(AParent,'Store filename as preferred of dependency',lisPckEditStoreFileNameAsPreferredForThisDependency);
|
|
ProjInspMenuClearPreferredFilenameOfDependencyDown:=RegisterIDEMenuCommand(AParent,'Clear preferred filename of dependency',lisPckEditClearDefaultPreferredFilenameOfDependency);
|
|
|
|
// add popupmenu
|
|
ProjectInspectorAddMenuRoot:=RegisterIDEMenuRoot(ProjectInspectorMenuAddRootName);
|
|
|
|
// register the section for adding files
|
|
ProjInspAddMenuSectionFiles:=RegisterIDEMenuSection(ProjectInspectorMenuAddRootName,'Files');
|
|
AParent:=ProjInspAddMenuSectionFiles;
|
|
ProjInspAddMenuDiskFile:=RegisterIDEMenuCommand(AParent,'Add disk file',lisBtnDlgAdd);
|
|
ProjInspAddMenuEditorFiles:=RegisterIDEMenuCommand(AParent,'Add editor files',lisProjAddEditorFile);
|
|
|
|
// register the section for adding dependency
|
|
ProjInspAddMenuSectionDependencies:=RegisterIDEMenuSection(ProjectInspectorMenuAddRootName,'Dependencies');
|
|
AParent:=ProjInspAddMenuSectionFiles;
|
|
ProjInspAddMenuDependency:=RegisterIDEMenuCommand(AParent,'Add dependency',lisProjAddNewRequirement);
|
|
ProjInspAddMenuFPMakeDependency:=RegisterIDEMenuCommand(AParent,'Add fpmake dependency',lisProjAddNewFPMakeRequirement);
|
|
end;
|
|
|
|
|
|
{ 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
|
|
begin if NOT self.Docked then Close end
|
|
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
|
|
UpdateProperties;
|
|
UpdateButtons;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.mnuAddDiskFileClick(Sender: TObject);
|
|
var
|
|
OpenDialog: TOpenDialog;
|
|
ADirectory, NewFilename: String;
|
|
i: Integer;
|
|
begin
|
|
OpenDialog:=IDEOpenDialogClass.Create(nil);
|
|
try
|
|
InputHistories.ApplyFileDialogSettings(OpenDialog);
|
|
ADirectory:=LazProject.Directory;
|
|
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;*.fmx)|*.lfm;*.dfm;*.fmx';
|
|
if OpenDialog.Execute then
|
|
begin
|
|
InputHistories.StoreFileDialogSettings(OpenDialog);
|
|
for i:=0 to OpenDialog.Files.Count-1 do
|
|
begin
|
|
NewFilename := OpenDialog.Files[i];
|
|
case TPrjFileCheck.AddingFile(LazProject, NewFilename) of
|
|
mrOk: if not (AddOneFile(NewFilename) in [mrOk, mrIgnore]) then
|
|
break;
|
|
mrIgnore: continue;
|
|
mrCancel: exit;
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
OpenDialog.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.mnuAddEditorFilesClick(Sender: TObject);
|
|
begin
|
|
DoAddMoreDialog;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.mnuAddFPMakeReqClick(Sender: TObject);
|
|
begin
|
|
DoAddFPMakeDepDialog;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.mnuAddReqClick(Sender: TObject);
|
|
begin
|
|
DoAddDepDialog;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.mnuOpenFolderClick(Sender: TObject);
|
|
begin
|
|
OpenDocument(LazProject.Directory);
|
|
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.PropsGroupBoxResize(Sender: TObject);
|
|
begin
|
|
if PropsGroupBox.Visible then
|
|
EnvironmentGuiOpts.Desktop.ProjectInspectorPropsPanelHeight := ScaleFormTo96(PropsGroupBox.Height);
|
|
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
|
|
NewUnit: TUnitInfo;
|
|
begin
|
|
Result := mrOK;
|
|
NewUnit:=LazProject.UnitInfoWithFilename(aFilename);
|
|
if NewUnit<>nil then begin
|
|
if NewUnit.IsPartOfProject then Exit(mrIgnore);
|
|
end else begin
|
|
NewUnit:=TUnitInfo.Create(nil);
|
|
NewUnit.Filename:=aFilename;
|
|
if LazProject.AutoCreateForms and FilenameIsPascalUnit(NewUnit.Filename)
|
|
and (pfMainUnitHasCreateFormStatements in LazProject.Flags) then
|
|
UpdateUnitInfoResourceBaseClass(NewUnit, true);
|
|
LazProject.AddFile(NewUnit,false);
|
|
end;
|
|
if Assigned(OnAddUnitToProject) then begin
|
|
Result:=OnAddUnitToProject(Self,NewUnit);
|
|
if Result<>mrOK then Exit;
|
|
end;
|
|
FNextSelectedPart:=NewUnit;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.AddMenuItemClick(Sender: TObject);
|
|
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
|
|
mnuAddDiskFileClick(Sender);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.DoAddMoreDialog;
|
|
var
|
|
Files: TStringList;
|
|
i: Integer;
|
|
begin
|
|
Files:=TStringList.Create;
|
|
try
|
|
if ShowAddToProjectDlg(LazProject,Files)<>mrOk then
|
|
exit;
|
|
BeginUpdate;
|
|
for i:=0 to Files.Count-1 do
|
|
if not (AddOneFile(Files[i]) in [mrOk, mrIgnore]) then break;
|
|
UpdateAll;
|
|
EndUpdate;
|
|
finally
|
|
Files.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.DoAddDepDialog;
|
|
var
|
|
Deps: TPkgDependencyList;
|
|
i: Integer;
|
|
Resu: TModalResult;
|
|
begin
|
|
Resu:=ShowAddPkgDependencyDlg(LazProject, Deps);
|
|
try
|
|
if (Resu<>mrOK) or (Deps.Count=0) or (OnAddDependency=nil) then exit;
|
|
try
|
|
BeginUpdate;
|
|
for i := 0 to Deps.Count-1 do
|
|
OnAddDependency(Self, Deps[i]);
|
|
FNextSelectedPart:=Deps[Deps.Count-1];
|
|
UpdateRequiredPackages;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
finally
|
|
Deps.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.DoAddFPMakeDepDialog;
|
|
var
|
|
Deps: TPkgDependencyList;
|
|
i: Integer;
|
|
Resu: TModalResult;
|
|
begin
|
|
Resu:=ShowAddFPMakeDependencyDlg(LazProject, Deps);
|
|
try
|
|
if (Resu<>mrOK) or (Deps.Count=0) then exit;
|
|
try
|
|
BeginUpdate;
|
|
for i := 0 to Deps.Count-1 do
|
|
OnAddDependency(Self, Deps[i]);
|
|
FNextSelectedPart:=Deps[Deps.Count-1];
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
finally
|
|
Deps.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.CopyMoveToDirMenuItemClick(Sender: TObject);
|
|
begin
|
|
OnCopyMoveFiles(Self);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.AddPopupMenuPopup(Sender: TObject);
|
|
|
|
procedure SetItem(Item: TIDEMenuCommand; AnOnClick: TNotifyEvent;
|
|
aShow: boolean = true; AEnable: boolean = true);
|
|
begin
|
|
Item.OnClick:=AnOnClick;
|
|
Item.Visible:=aShow;
|
|
Item.Enabled:=AEnable;
|
|
end;
|
|
|
|
begin
|
|
ProjectInspectorAddMenuRoot.MenuItem:=AddPopupMenu.Items;
|
|
SetItem(ProjInspAddMenuDiskFile,@mnuAddDiskFileClick);
|
|
SetItem(ProjInspAddMenuEditorFiles,@mnuAddEditorFilesClick);
|
|
SetItem(ProjInspAddMenuDependency,@mnuAddReqClick);
|
|
SetItem(ProjInspAddMenuFPMakeDependency,@mnuAddFPMakeReqClick);
|
|
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.FormCreate(Sender: TObject);
|
|
begin
|
|
if LazarusIDE.IDEStarted and (LazProject=nil) then
|
|
begin // User opens this window for the very first time. Set active project.
|
|
LazProject := Project1;
|
|
UpdateAll;
|
|
end;
|
|
if OPMInterface <> nil then
|
|
OPMInterface.AddPackageListNotification(@PackageListAvailable);
|
|
if SourceEditorManagerIntf <> nil then
|
|
SourceEditorManagerIntf.RegisterChangeEvent(semEditorActivate,@ActiveEditorChanged);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.FormDestroy(Sender: TObject);
|
|
begin
|
|
if OPMInterface <> nil then
|
|
OPMInterface.RemovePackageListNotification(@PackageListAvailable);
|
|
if SourceEditorManagerIntf <> nil then
|
|
SourceEditorManagerIntf.UnRegisterChangeEvent(semEditorActivate,@ActiveEditorChanged);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.FormActivate(Sender: TObject);
|
|
begin
|
|
//DebugLn('* TProjectInspectorForm.FormActivate *');
|
|
ItemsTreeView.OnSelectionChanged := @ItemsTreeViewSelectionChanged;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.FormDeactivate(Sender: TObject);
|
|
begin
|
|
// Prevent calling handler when the tree gets updated with a project.
|
|
ItemsTreeView.OnSelectionChanged := Nil;
|
|
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;
|
|
|
|
// the Drop event comes before the Application activate event or not at all
|
|
// => invalidate file state
|
|
InvalidateFileStateCache;
|
|
|
|
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.FormResize(Sender: TObject);
|
|
begin
|
|
PropsGroupBox.Constraints.MaxHeight := self.Height - FilterPanel.Height - ToolBar.Height - 20;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.FormShow(Sender: TObject);
|
|
begin
|
|
UpdateTitle; // update title on dock/undock
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ItemsPopupMenuPopup(Sender: TObject);
|
|
|
|
procedure SetItem(Item: TIDEMenuCommand; AnOnClick: TNotifyEvent;
|
|
aShow: boolean = true; AEnable: boolean = true);
|
|
begin
|
|
Item.OnClick:=AnOnClick;
|
|
Item.Visible:=aShow;
|
|
Item.Enabled:=AEnable;
|
|
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;
|
|
OpenItemCapt: String;
|
|
OnlyFilesNodeSelected, OnlyDependenciesNodeSelected, CanI18NforLFM: Boolean;
|
|
begin
|
|
ProjectInspectorItemsMenuRoot.MenuItem:=ItemsPopupMenu.Items;
|
|
|
|
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);
|
|
if Dependency.DependencyType=pdtLazarus then
|
|
inc(CanOpenCount);
|
|
if Dependency.RequiredPackage<>nil then
|
|
inc(HasValidDep);
|
|
if (Dependency.DefaultFilename<>'') then
|
|
inc(CanClearDep);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
OnlyFilesNodeSelected:=ItemsTreeView.Selected = FFilesNode;
|
|
SetItem(ProjInspMenuAddDiskFile,@mnuAddDiskFileClick,OnlyFilesNodeSelected);
|
|
SetItem(ProjInspMenuRemoveNonExistingFiles,@RemoveNonExistingFilesMenuItemClick,
|
|
OnlyFilesNodeSelected and not LazProject.IsVirtual);
|
|
SetItem(ProjInspMenuOpenFolder,@mnuOpenFolderClick,
|
|
OnlyFilesNodeSelected and not LazProject.IsVirtual);
|
|
|
|
OnlyDependenciesNodeSelected:=ItemsTreeView.Selected = FDependenciesNode;
|
|
SetItem(ProjInspMenuAddDependency,@mnuAddReqClick,OnlyDependenciesNodeSelected);
|
|
|
|
// open, remove
|
|
if CanOpenCount>0 then begin
|
|
OpenItemCapt := lisOpen;
|
|
if Assigned(SingleSelectedDep) then
|
|
case SingleSelectedDep.LoadPackageResult of
|
|
lprAvailableOnline:
|
|
OpenItemCapt:=lisPckEditInstall;
|
|
lprNotFound:
|
|
if Assigned(OPMInterface) and not OPMInterface.IsPackageListLoaded then
|
|
OpenItemCapt:=lisPckEditCheckAvailabilityOnline;
|
|
end;
|
|
SetItem(ProjInspMenuOpen,@OpenButtonClick,true);
|
|
ProjInspMenuOpen.Caption:=OpenItemCapt;
|
|
end else begin
|
|
SetItem(ProjInspMenuOpen,@OpenButtonClick,false);
|
|
end;
|
|
SetItem(ProjInspMenuRemove,@RemoveBitBtnClick,CanRemoveCount>0);
|
|
|
|
// move
|
|
SetItem(ProjInspMenuCopyMoveFileToDir,@CopyMoveToDirMenuItemClick,CanMoveFileCount>0);
|
|
|
|
// i18n for lfm
|
|
CanI18NforLFM:=LazProject.EnableI18N and LazProject.EnableI18NForLFM and (HasLFMCount>0);
|
|
SetItem(ProjInspMenuEnableI18NForLFM,@EnableI18NForLFMMenuItemClick,
|
|
CanI18NforLFM,DisabledI18NForLFMCount>0);
|
|
SetItem(ProjInspMenuDisableI18NForLFM,@DisableI18NForLFMMenuItemClick,
|
|
CanI18NforLFM,DisabledI18NForLFMCount<HasLFMCount);
|
|
|
|
// Required packages section
|
|
// undo delete
|
|
SetItem(ProjInspMenuReAddDependency,@ReAddMenuItemClick,CanReAddCount>0);
|
|
// move up/down
|
|
SetItem(ProjInspMenuMoveDependencyUp,@MoveDependencyUpClick,
|
|
(SingleSelectedDep<>nil) and (SingleSelectedDep.PrevRequiresDependency<>nil), not SortAlphabetically);
|
|
SetItem(ProjInspMenuMoveDependencyDown,@MoveDependencyDownClick,
|
|
(SingleSelectedDep<>nil) and (SingleSelectedDep.NextRequiresDependency<>nil), not SortAlphabetically);
|
|
// default and preferred filename
|
|
SetItem(ProjInspMenuStoreFilenameAsDefaultOfDependencyDown,@SetDependencyDefaultFilenameMenuItemClick,
|
|
HasValidDep>0);
|
|
SetItem(ProjInspMenuStoreFilenameAsPreferredOfDependencyDown,@SetDependencyPreferredFilenameMenuItemClick,
|
|
HasValidDep>0);
|
|
SetItem(ProjInspMenuClearPreferredFilenameOfDependencyDown,@ClearDependencyFilenameMenuItemClick,
|
|
CanClearDep>0);
|
|
ProjectInspectorItemsMenuRoot.NotifySubSectionOnShow(Self);
|
|
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;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
begin
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do
|
|
begin
|
|
if GetNodeDataItem(ItemsTreeView.Selections[i], NodeData, Item) then
|
|
begin
|
|
if Item is TUnitInfo then
|
|
begin
|
|
if LazarusIDE.DoOpenEditorFile(TUnitInfo(Item).Filename,
|
|
-1,-1,[ofAddToRecent]) <> mrOk then
|
|
Exit;
|
|
end
|
|
else if Item is TPkgDependency then
|
|
if not OpmAddOrOpenDependency(TPkgDependency(Item)) then
|
|
Exit;
|
|
end;
|
|
end;
|
|
OpmInstallPendingDependencies;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.OptionsBitBtnClick(Sender: TObject);
|
|
begin
|
|
MainIDEBar.itmProjectOptions.DoOnClick;
|
|
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 TPrjFileCheck.AddingDependency(LazProject,Dependency)<>mrOK 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, Cap: 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 CurFile<>nil then
|
|
Cap:=lisProjInspConfirmRemovingFile
|
|
else
|
|
Cap:=lisProjInspConfirmDeletingDependency;
|
|
if IDEMessageDialog(Cap,
|
|
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;
|
|
HasChanged: Boolean;
|
|
begin
|
|
if LazProject.IsVirtual then exit;
|
|
BeginUpdate;
|
|
try
|
|
HasChanged:=false;
|
|
for TLazProjectFile(AnUnitInfo) in LazProject.UnitsBelongingToProject do begin
|
|
if not (AnUnitInfo.IsVirtual or FileExistsUTF8(AnUnitInfo.Filename)) then begin
|
|
AnUnitInfo.IsPartOfProject:=false;
|
|
HasChanged:=true;
|
|
end;
|
|
end;
|
|
if HasChanged then begin
|
|
LazProject.Modified:=true;
|
|
UpdateFiles;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ShowPropsPanelButtonClick(Sender: TObject);
|
|
begin
|
|
with EnvironmentGuiOpts.Desktop do
|
|
ProjectInspectorShowProps := not ProjectInspectorShowProps;
|
|
OptionsChanged(Sender, false);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SelectFileNode(const AFileName: string);
|
|
function _FindInChildren(_Parent: TTreeNode): TTreeNode;
|
|
var
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
UInfo: TUnitInfo;
|
|
begin
|
|
Result := nil;
|
|
|
|
TVNode:=_Parent.GetFirstChild;
|
|
while Assigned(TVNode) do
|
|
begin
|
|
if GetNodeDataItem(TVNode,NodeData,Item) and (Item is TUnitInfo) then
|
|
begin
|
|
UInfo := TUnitInfo(Item);
|
|
if SameFileName(UInfo.GetFullFilename, AFileName) then
|
|
Exit(TVNode);
|
|
end;
|
|
if TVNode.HasChildren then
|
|
begin
|
|
Result := _FindInChildren(TVNode);
|
|
if Assigned(Result) then
|
|
Exit;
|
|
end;
|
|
TVNode := TVNode.GetNextSibling;
|
|
end;
|
|
end;
|
|
var
|
|
FileNode: TTreeNode;
|
|
begin
|
|
if not Assigned(FFilesNode) then
|
|
Exit;
|
|
FileNode := _FindInChildren(FFilesNode);
|
|
if Assigned(FileNode) then
|
|
begin
|
|
ItemsTreeView.BeginUpdate;
|
|
try
|
|
ItemsTreeView.ClearSelection;
|
|
ItemsTreeView.Selected := FileNode;
|
|
finally
|
|
ItemsTreeView.EndUpdate;
|
|
end;
|
|
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 // Old Project
|
|
dec(FUpdateLock,LazProject.UpdateLock);
|
|
FLazProject.OnBeginUpdate:=nil;
|
|
FLazProject.OnEndUpdate:=nil;
|
|
end;
|
|
FLazProject:=AValue;
|
|
if FLazProject<>nil then begin // New Project
|
|
inc(FUpdateLock,LazProject.UpdateLock);
|
|
FLazProject.OnBeginUpdate:=@ProjectBeginUpdate;
|
|
FLazProject.OnEndUpdate:=@ProjectEndUpdate;
|
|
end
|
|
else // Only update when no project. ProjectEndUpdate will update a project.
|
|
UpdateAll;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SetShowDirectoryHierarchy(const AValue: boolean);
|
|
begin
|
|
if FShowDirectoryHierarchy=AValue then exit;
|
|
FShowDirectoryHierarchy:=AValue;
|
|
DirectoryHierarchyButton.Down:=FShowDirectoryHierarchy;
|
|
FilterEdit.ShowDirHierarchy:=FShowDirectoryHierarchy;
|
|
EnvironmentOptions.ProjInspShowDirHierarchy := ShowDirectoryHierarchy;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SetSortAlphabetically(const AValue: boolean);
|
|
begin
|
|
if FSortAlphabetically=AValue then exit;
|
|
FSortAlphabetically:=AValue;
|
|
SortAlphabeticallyButton.Down:=FSortAlphabetically;
|
|
FilterEdit.SortData:=FSortAlphabetically;
|
|
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;
|
|
|
|
function TProjectInspectorForm.GetDependencyToUpdate(Immediately: boolean): TPkgDependencyID;
|
|
begin
|
|
if CanUpdate(pefNeedUpdateApplyDependencyButton,Immediately) then
|
|
Result:=GetSingleSelectedDependency
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ApplyDependencyButtonClick(Sender: TObject);
|
|
var
|
|
CurDependency: TPkgDependency;
|
|
begin
|
|
CurDependency:=GetSingleSelectedDependency;
|
|
if (LazProject=nil) or (CurDependency=nil)
|
|
or not FPropGui.CheckApplyDependency(CurDependency) then exit;
|
|
LazProject.Modified:=True;
|
|
PkgBoss.ApplyDependency(CurDependency);
|
|
end;
|
|
|
|
function TProjectInspectorForm.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(AImageName);
|
|
Result.ShowHint := True;
|
|
Result.OnClick := AOnClick;
|
|
Result.AutoSize := True;
|
|
Result.Parent := ToolBar;
|
|
end;
|
|
|
|
function TProjectInspectorForm.CreateDivider: TToolButton;
|
|
begin
|
|
Result := TToolButton.Create(Self);
|
|
Result.Style := tbsDivider;
|
|
Result.AutoSize := True;
|
|
Result.Parent := ToolBar;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.OptionsChanged(Sender: TObject; Restore: boolean);
|
|
begin
|
|
PropsGroupBox.Visible := EnvironmentGuiOpts.Desktop.ProjectInspectorShowProps;
|
|
ShowPropsPanelButton.Down := PropsGroupBox.Visible;
|
|
PropsGroupBox.Height := Scale96ToForm(EnvironmentGuiOpts.Desktop.ProjectInspectorPropsPanelHeight);
|
|
Splitter1.Visible := PropsGroupBox.Visible;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.SetupComponents;
|
|
begin
|
|
ImageIndexFiles := IDEImages.LoadImage('pkg_files');
|
|
ImageIndexProject := IDEImages.LoadImage('item_project_source');
|
|
ImageIndexUnit := IDEImages.LoadImage('item_unit');
|
|
ImageIndexRegisterUnit := IDEImages.LoadImage('pkg_registerunit');
|
|
ImageIndexText := IDEImages.LoadImage('pkg_text');
|
|
ImageIndexBinary := IDEImages.LoadImage('pkg_binary');
|
|
ImageIndexDirectory := IDEImages.LoadImage('pkg_files');
|
|
|
|
ItemsTreeView.Images := IDEImages.Images_16;
|
|
ToolBar.Images := IDEImages.Images_16;
|
|
FilterEdit.OnGetImageIndex:=@TreeViewGetImageIndex;
|
|
|
|
AddBitBtn := CreateToolButton('AddBitBtn', lisAdd, lisClickToSeeTheChoices, 'laz_add', nil);
|
|
AddBitBtn.Style:=tbsButtonDrop;
|
|
RemoveBitBtn := CreateToolButton('RemoveBitBtn', lisRemove, lisPckEditRemoveSelectedItem, 'laz_delete', @RemoveBitBtnClick);
|
|
CreateDivider;
|
|
OptionsBitBtn := CreateToolButton('OptionsBitBtn', lisOptions, lisPckEditEditGeneralOptions, 'menu_environment_options', @OptionsBitBtnClick);
|
|
OptionsBitBtn.DropdownMenu := TSetBuildModeToolButton.TBuildModeMenu.Create(Self);
|
|
OptionsBitBtn.Style := tbsDropDown;
|
|
HelpBitBtn := CreateToolButton('HelpBitBtn', GetButtonCaption(idButtonHelp), lisMenuOnlineHelp, 'btn_help', @HelpBitBtnClick);
|
|
|
|
AddBitBtn.DropdownMenu:=AddPopupMenu;
|
|
|
|
IDEImages.AssignImage(OpenButton, 'laz_open');
|
|
OpenButton.Caption:='';
|
|
OpenButton.Hint:=lisOpenFile2;
|
|
SortAlphabeticallyButton.Hint:=lisPESortFilesAlphabetically;
|
|
IDEImages.AssignImage(SortAlphabeticallyButton, 'pkg_sortalphabetically');
|
|
DirectoryHierarchyButton.Hint:=lisPEShowDirectoryHierarchy;
|
|
IDEImages.AssignImage(DirectoryHierarchyButton, 'pkg_hierarchical');
|
|
ShowPropsPanelButton.Hint:=lisPEShowPropsPanel;
|
|
IDEImages.AssignImage(ShowPropsPanelButton, 'item_todo');
|
|
|
|
FPropGui.OnGetPkgDep := @GetDependencyToUpdate;
|
|
FPropGui.ApplyDependencyButton.OnClick := @ApplyDependencyButtonClick;
|
|
|
|
with ItemsTreeView do begin
|
|
FFilesNode:=Items.Add(nil, dlgEnvFiles);
|
|
FFilesNode.ImageIndex:=ImageIndexFiles;
|
|
FFilesNode.SelectedIndex:=FFilesNode.ImageIndex;
|
|
FDependenciesNode:=Items.Add(nil, lisPckEditRequiredPackages);
|
|
FDependenciesNode.ImageIndex:=FPropGui.ImageIndexRequired;
|
|
FDependenciesNode.SelectedIndex:=FDependenciesNode.ImageIndex;
|
|
end;
|
|
|
|
EnvironmentOptions.AddHandlerAfterWrite(@OptionsChanged);
|
|
OptionsChanged(Nil, False);
|
|
end;
|
|
|
|
function TProjectInspectorForm.TreeViewGetImageIndex(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 FilenameHasPascalExt(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
|
|
Result:=FPropGui.GetDependencyImageIndex(TPkgDependency(Item));
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdateFiles(Immediately: boolean);
|
|
var
|
|
CurFile: TUnitInfo;
|
|
FilesBranch: TTreeFilterBranch;
|
|
Filename: String;
|
|
ANodeData : TPENodeData;
|
|
begin
|
|
if not CanUpdate(pefNeedUpdateFiles,Immediately) then exit;
|
|
FilesBranch:=FilterEdit.GetCleanBranch(FFilesNode);
|
|
FilesBranch.ClearNodeData;
|
|
FPropGui.FreeNodeData(penFile);
|
|
if LazProject<>nil then begin
|
|
FilterEdit.SelectedPart:=FNextSelectedPart;
|
|
FilterEdit.ShowDirHierarchy:=ShowDirectoryHierarchy;
|
|
FilterEdit.SortData:=SortAlphabetically;
|
|
FilterEdit.ImageIndexDirectory:=ImageIndexDirectory;
|
|
// collect and sort files
|
|
for TLazProjectFile(CurFile) in LazProject.UnitsBelongingToProject do begin
|
|
Filename:=CurFile.GetShortFilename(true);
|
|
if Filename<>'' then Begin
|
|
ANodeData:=FPropGui.CreateNodeData(penFile, CurFile.Filename, False);
|
|
FilesBranch.AddNodeData(Filename, ANodeData, CurFile.Filename);
|
|
end;
|
|
end;
|
|
end;
|
|
FilterEdit.InvalidateFilter; // Data is shown by FilterEdit.
|
|
UpdateProperties;
|
|
UpdateButtons;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdateRequiredPackages(Immediately: boolean);
|
|
var
|
|
Dependency: TPkgDependency;
|
|
RequiredBranch, RemovedBranch: TTreeFilterBranch;
|
|
ANodeData : TPENodeData;
|
|
begin
|
|
if not CanUpdate(pefNeedUpdateRequiredPkgs,Immediately) then exit;
|
|
RequiredBranch:=FilterEdit.GetCleanBranch(FDependenciesNode);
|
|
RequiredBranch.ClearNodeData;
|
|
FPropGui.FreeNodeData(penDependency);
|
|
Dependency:=Nil;
|
|
if LazProject<>nil then begin
|
|
// required packages
|
|
Dependency:=LazProject.FirstRequiredDependency;
|
|
while Dependency<>nil do begin
|
|
// Add the required package under the branch
|
|
ANodeData:=FPropGui.CreateNodeData(penDependency, Dependency.PackageName, False);
|
|
RequiredBranch.AddNodeData(Dependency.AsString(False,True)+OPNote(Dependency), 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:=FPropGui.ImageIndexRemovedRequired;
|
|
FRemovedDependenciesNode.SelectedIndex:=FRemovedDependenciesNode.ImageIndex;
|
|
end;
|
|
RemovedBranch:=FilterEdit.GetCleanBranch(FRemovedDependenciesNode);
|
|
// Add all removed dependencies under the branch
|
|
while Dependency<>nil do begin
|
|
ANodeData := FPropGui.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;
|
|
UpdateProperties;
|
|
UpdateButtons;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ProjectBeginUpdate(Sender: TObject);
|
|
begin
|
|
BeginUpdate;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ProjectEndUpdate(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.PackageListAvailable(Sender: TObject);
|
|
begin
|
|
//DebugLn(['TProjectInspectorForm.PackageListAvailable: ', LazProject.Title]);
|
|
UpdateRequiredPackages;
|
|
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 fUpdateLock>0 then exit;
|
|
IdleConnected:=false;
|
|
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;
|
|
|
|
function TProjectInspectorForm.GetSelectedItems: TFPList;
|
|
var
|
|
i: Integer;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
begin
|
|
Result:=nil;
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
|
|
if (Item is TLazProjectFile)
|
|
or (Item is TPkgDependency) then begin
|
|
if Result=nil then Result:=TFPList.Create;
|
|
Result.Add(Item);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
constructor TProjectInspectorForm.Create(TheOwner: TComponent);
|
|
begin
|
|
inherited Create(TheOwner);
|
|
Name:=NonModalIDEWindowNames[nmiwProjectInspector];
|
|
Caption:=lisMenuProjectInspector;
|
|
KeyPreview:=true;
|
|
FPropGui:=TProjPackFilePropGui.Create(PropsGroupBox, False);
|
|
SetupComponents;
|
|
KeyPreview:=true;
|
|
SortAlphabetically := EnvironmentOptions.ProjInspSortAlphabetically;
|
|
ShowDirectoryHierarchy := EnvironmentOptions.ProjInspShowDirHierarchy;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.ActiveEditorChanged(Sender: TObject);
|
|
begin
|
|
if Assigned(SourceEditorManagerIntf.ActiveEditor) then
|
|
SelectFileNode(SourceEditorManagerIntf.ActiveEditor.FileName);
|
|
end;
|
|
|
|
destructor TProjectInspectorForm.Destroy;
|
|
begin
|
|
IdleConnected:=false;
|
|
LazProject:=nil;
|
|
inherited Destroy;
|
|
FreeAndNil(FPropGui);
|
|
if ProjInspector=Self then
|
|
ProjInspector:=nil;
|
|
end;
|
|
|
|
function TProjectInspectorForm.ExtendIncSearchPath(NewIncPaths: string): boolean;
|
|
begin
|
|
Result:=LazProject.ExtendIncSearchPath(NewIncPaths);
|
|
end;
|
|
|
|
function TProjectInspectorForm.ExtendUnitSearchPath(NewUnitPaths: string): boolean;
|
|
begin
|
|
Result:=LazProject.ExtendUnitSearchPath(NewUnitPaths);
|
|
end;
|
|
|
|
function TProjectInspectorForm.FilesBaseDirectory: string;
|
|
begin
|
|
if LazProject<>nil then
|
|
Result:=LazProject.Directory
|
|
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;
|
|
|
|
procedure TProjectInspectorForm.FilterEditAfterFilter(Sender: TObject);
|
|
begin
|
|
ActiveEditorChanged(Sender);
|
|
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 RaiseGDBException('TProjectInspectorForm.EndUpdate');
|
|
dec(FUpdateLock);
|
|
if FUpdateLock=0 then
|
|
IdleConnected:=true;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdateAll(Immediately: boolean);
|
|
begin
|
|
if csDestroying in ComponentState then exit;
|
|
fFlags:=fFlags+[
|
|
pefNeedUpdateTitle,
|
|
pefNeedUpdateFiles,
|
|
pefNeedUpdateRequiredPkgs,
|
|
pefNeedUpdateProperties,
|
|
pefNeedUpdateButtons,
|
|
pefNeedUpdateApplyDependencyButton,
|
|
pefNeedUpdateStatusBar];
|
|
//UpdateTitle;
|
|
//UpdateFiles;
|
|
//UpdateRequiredPackages;
|
|
//UpdateButtons;
|
|
if Immediately then
|
|
UpdatePending
|
|
else
|
|
IdleConnected:=true;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdateTitle(Immediately: boolean);
|
|
var
|
|
NewCaption: String;
|
|
IconStream: TStream;
|
|
begin
|
|
if not CanUpdate(pefNeedUpdateTitle,Immediately) then exit;
|
|
Icon.Clear;
|
|
if (LazProject = nil) or
|
|
(assigned(HostDockSite) and assigned(HostDockSite.Parent)) // is docked
|
|
then
|
|
Caption:=lisMenuProjectInspector
|
|
else begin
|
|
NewCaption:=LazProject.GetTitle;
|
|
if NewCaption='' then
|
|
NewCaption:=ExtractFilenameOnly(LazProject.ProjectInfoFile);
|
|
NewCaption:=Format(lisProjInspProjectInspector, [NewCaption]);
|
|
if (LazProject.ActiveBuildMode.GetCaption<>'') then
|
|
NewCaption := NewCaption + ' ['+LazProject.ActiveBuildMode.GetCaption+']';
|
|
Caption := NewCaption;
|
|
|
|
if not LazProject.ProjResources.ProjectIcon.IsEmpty then
|
|
begin
|
|
IconStream := LazProject.ProjResources.ProjectIcon.GetStream;
|
|
if IconStream<>nil then
|
|
begin
|
|
try
|
|
Icon.LoadFromStream(IconStream);
|
|
except
|
|
Icon.Clear; // ignore exceptions for invalid icons
|
|
end;
|
|
IconStream.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdateProperties(Immediately: boolean);
|
|
var
|
|
CurDependency, SingleSelectedDep: TPkgDependency;
|
|
TVNode, DepHeaderNode, SingleSelectedDirectory: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
i, SelFileCount, SelDepCount, SelUnitCount, SelDirCount: Integer;
|
|
SingleSelectedRemoved: Boolean;
|
|
begin
|
|
if not CanUpdate(pefNeedUpdateProperties,Immediately) then exit;
|
|
|
|
// check selection
|
|
DepHeaderNode:=nil;
|
|
SingleSelectedDep:=nil;
|
|
SingleSelectedDirectory:=nil;
|
|
SingleSelectedRemoved:=false;
|
|
SelFileCount:=0;
|
|
SelDepCount:=0;
|
|
SelUnitCount:=0;
|
|
SelDirCount:=0;
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if GetNodeDataItem(TVNode,NodeData,Item) then begin
|
|
if Item is TUnitInfo then begin
|
|
inc(SelFileCount);
|
|
SingleSelectedRemoved:=NodeData.Removed;
|
|
inc(SelUnitCount);
|
|
end
|
|
else if Item is TPkgDependency then begin
|
|
inc(SelDepCount);
|
|
CurDependency:=TPkgDependency(Item);
|
|
SingleSelectedDep:=CurDependency;
|
|
SingleSelectedRemoved:=NodeData.Removed;
|
|
end;
|
|
end else if IsDirectoryNode(TVNode) then begin
|
|
inc(SelDirCount);
|
|
SingleSelectedDirectory:=TVNode;
|
|
end else if TVNode=FDependenciesNode then
|
|
DepHeaderNode:=TVNode;
|
|
end;
|
|
|
|
if (SelFileCount+SelDepCount+SelDirCount>1) then begin
|
|
// it is a multi selection
|
|
SingleSelectedDep:=nil;
|
|
SingleSelectedDirectory:=nil;
|
|
end;
|
|
|
|
//OnlyFilesWithUnitsSelected:=
|
|
// (SelFileCount>0) and (SelDepCount=0) and (SelDirCount=0) and (SelUnitCount>0);
|
|
//FPropGui.ControlVisible := OnlyFilesWithUnitsSelected;
|
|
FPropGui.ControlEnabled := True; //not LazProject.ReadOnly;
|
|
DisableAlign;
|
|
try
|
|
// Min/Max version of dependency (only single selection)
|
|
FPropGui.ControlVisible := SingleSelectedDep<>nil;
|
|
FPropGui.SetMinMaxVisibility;
|
|
if SelFileCount>0 then begin
|
|
PropsGroupBox.Enabled:=true;
|
|
PropsGroupBox.Caption:=lisPckEditFileProperties;
|
|
end
|
|
else if SingleSelectedDep<>nil then begin
|
|
PropsGroupBox.Enabled:=not SingleSelectedRemoved;
|
|
PropsGroupBox.Caption:=lisPckEditDependencyProperties;
|
|
FPropGui.SetMinMaxValues(SingleSelectedDep);
|
|
FPropGui.UpdateApplyDependencyButton;
|
|
end
|
|
else if SingleSelectedDirectory<>nil then begin
|
|
PropsGroupBox.Enabled:=true;
|
|
PropsGroupBox.Caption:=lisPckEditFileProperties;
|
|
end
|
|
else begin
|
|
PropsGroupBox.Enabled:=false;
|
|
if Assigned(DepHeaderNode) then
|
|
PropsGroupBox.Caption:=lisPckEditDependencyProperties
|
|
else
|
|
PropsGroupBox.Caption:=lisPckEditFileProperties;
|
|
end;
|
|
finally
|
|
EnableAlign;
|
|
end;
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdateButtons(Immediately: boolean);
|
|
var
|
|
i: Integer;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
CanRemoveCount: Integer;
|
|
CurUnitInfo: TUnitInfo;
|
|
CanOpenCount: Integer;
|
|
begin
|
|
if not CanUpdate(pefNeedUpdateButtons,Immediately) then exit;
|
|
CanRemoveCount:=0;
|
|
CanOpenCount:=0;
|
|
if Assigned(LazProject) then
|
|
begin
|
|
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 and (TPkgDependency(Item).DependencyType=pdtLazarus) then begin
|
|
inc(CanRemoveCount);
|
|
inc(CanOpenCount);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
AddBitBtn.Enabled:=Assigned(LazProject);
|
|
RemoveBitBtn.Enabled:=(CanRemoveCount>0);
|
|
OpenButton.Enabled:=(CanOpenCount>0);
|
|
OptionsBitBtn.Enabled:=Assigned(LazProject);
|
|
end;
|
|
|
|
procedure TProjectInspectorForm.UpdatePending;
|
|
begin
|
|
ItemsTreeView.BeginUpdate;
|
|
try
|
|
if pefNeedUpdateTitle in FFlags then
|
|
UpdateTitle(True);
|
|
if pefNeedUpdateFiles in FFlags then
|
|
UpdateFiles(True);
|
|
if pefNeedUpdateRequiredPkgs in FFlags then
|
|
UpdateRequiredPackages(True);
|
|
if pefNeedUpdateProperties in FFlags then
|
|
UpdateProperties(True);
|
|
if pefNeedUpdateButtons in FFlags then
|
|
UpdateButtons(True);
|
|
//if pefNeedUpdateApplyDependencyButton in fFlags then
|
|
// FPropGui.UpdateApplyDependencyButton(true);
|
|
IdleConnected:=false;
|
|
finally
|
|
ItemsTreeView.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TProjectInspectorForm.CanUpdate(Flag: TPEFlag; Immediately: boolean): boolean;
|
|
begin
|
|
Result:=false;
|
|
if csDestroying in ComponentState then exit;
|
|
if (FUpdateLock>0) and not Immediately then begin
|
|
Include(fFlags,Flag);
|
|
IdleConnected:=true;
|
|
end else begin
|
|
Exclude(fFlags,Flag);
|
|
Result:=true;
|
|
end;
|
|
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;
|
|
|
|
{ TSetBuildModeToolButton.TBuildModeMenu }
|
|
|
|
procedure TSetBuildModeToolButton.TBuildModeMenu.DoPopup(Sender: TObject);
|
|
var
|
|
CurIndex: Integer;
|
|
i: Integer;
|
|
|
|
procedure AddMode(BuildModeIndex: Integer; CurMode: TProjectBuildMode);
|
|
var
|
|
AMenuItem: TBuildModeMenuItem;
|
|
begin
|
|
if Items.Count > CurIndex then
|
|
AMenuItem := Items[CurIndex] as TBuildModeMenuItem
|
|
else
|
|
begin
|
|
AMenuItem := TBuildModeMenuItem.Create(Self);
|
|
AMenuItem.Name := Name + 'Mode' + IntToStr(CurIndex);
|
|
Items.Add(AMenuItem);
|
|
end;
|
|
AMenuItem.BuildModeIndex := BuildModeIndex;
|
|
AMenuItem.Caption := CurMode.GetCaption;
|
|
AMenuItem.Checked := (Project1<>nil) and (Project1.ActiveBuildMode=CurMode);
|
|
AMenuItem.RadioItem := true;
|
|
AMenuItem.ShowAlwaysCheckable:=true;
|
|
inc(CurIndex);
|
|
end;
|
|
|
|
begin
|
|
// fill the PopupMenu
|
|
CurIndex := 0;
|
|
if Project1<>nil then
|
|
for i:=0 to Project1.BuildModes.Count-1 do
|
|
AddMode(i, Project1.BuildModes[i]);
|
|
// remove unused menuitems
|
|
while Items.Count > CurIndex do
|
|
Items[Items.Count - 1].Free;
|
|
|
|
inherited DoPopup(Sender);
|
|
end;
|
|
|
|
{ TSetBuildModeToolButton.TBuildModeMenuItem }
|
|
|
|
procedure TSetBuildModeToolButton.TBuildModeMenuItem.Click;
|
|
var
|
|
NewMode: TProjectBuildMode;
|
|
begin
|
|
inherited Click;
|
|
|
|
NewMode := Project1.BuildModes[BuildModeIndex];
|
|
if NewMode = Project1.ActiveBuildMode then exit;
|
|
if not (MainIDE.ToolStatus in [itNone,itDebugger]) then begin
|
|
IDEMessageDialog(dlgMsgWinColorUrgentError,
|
|
lisYouCanNotChangeTheBuildModeWhileCompiling,
|
|
mtError,[mbOk]);
|
|
exit;
|
|
end;
|
|
|
|
Project1.ActiveBuildMode := NewMode;
|
|
Project1.DefineTemplates.AllChanged(false);
|
|
IncreaseCompilerParseStamp;
|
|
MainBuildBoss.SetBuildTargetProject1(false);
|
|
MainIDE.UpdateCaption;
|
|
MainIDE.UpdateDefineTemplates;
|
|
if Assigned(ProjInspector) then
|
|
ProjInspector.UpdateTitle;
|
|
end;
|
|
|
|
{ TSetBuildModeToolButton }
|
|
|
|
procedure TSetBuildModeToolButton.DoOnAdded;
|
|
begin
|
|
inherited DoOnAdded;
|
|
|
|
DropdownMenu := TBuildModeMenu.Create(Self);
|
|
Style := tbsDropDown;
|
|
end;
|
|
|
|
end.
|
|
|