implemented multiple source directories for project

git-svn-id: trunk@8153 -
This commit is contained in:
mattias 2005-11-14 21:53:06 +00:00
parent 9a450654ae
commit 5d59178cc3
9 changed files with 704 additions and 119 deletions

View File

@ -26,7 +26,7 @@
Author: Mattias Gaertner Author: Mattias Gaertner
Abstract: Abstract:
- procs to transfer the compiler options to the CodeTools - procedures to transfer the compiler options to the CodeTools
} }
unit EditDefineTree; unit EditDefineTree;
@ -42,10 +42,11 @@ uses
// global // global
procedure SetAdditionalGlobalSrcPathToCodeToolBoss(const SrcPath: string); procedure SetAdditionalGlobalSrcPathToCodeToolBoss(const SrcPath: string);
// current project // projects
function FindCurrentProjectTemplate: TDefineTemplate; function FindProjectsTemplate: TDefineTemplate;
function CreateProjectTemplate(var ProjectDirTemplate: TDefineTemplate function FindProjectTemplateWithID(const ProjectID: string): TDefineTemplate;
): TDefineTemplate; function CreateProjectsTemplate: TDefineTemplate;
function CreateProjectTemplateWithID(const ProjectID: string): TDefineTemplate;
// packages // packages
function FindPackagesTemplate: TDefineTemplate; function FindPackagesTemplate: TDefineTemplate;
@ -66,9 +67,11 @@ function RemoveAutoGeneratedDefine(ParentTemplate: TDefineTemplate;
const const
ProjectDefTemplName = 'Current Project'; ProjectDefTemplName = 'Current Project';
ProjectDirDefTemplName = 'Current Project Directory'; ProjectDirDefTemplName = 'Current Project Directory';
ProjectsDefTemplName = 'Projects';
ProjectDirSrcPathDefTemplName = 'Project SrcPath'; ProjectDirSrcPathDefTemplName = 'Project SrcPath';
ProjectDirUnitPathDefTemplName = 'Project UnitPath'; ProjectDirUnitPathDefTemplName = 'Project UnitPath';
ProjectDirIncPathDefTemplName = 'Project IncPath'; ProjectDirIncPathDefTemplName = 'Project IncPath';
ProjectOutputDirDefTemplName = 'Project Output Directory';
PackagesDefTemplName = 'Packages'; PackagesDefTemplName = 'Packages';
PkgOutputDirDefTemplName = 'Output Directory'; PkgOutputDirDefTemplName = 'Output Directory';
@ -104,75 +107,55 @@ begin
Result:=PkgTempl.FindChildByName(PkgID); Result:=PkgTempl.FindChildByName(PkgID);
end; end;
function FindCurrentProjectTemplate: TDefineTemplate; function FindProjectsTemplate: TDefineTemplate;
begin begin
if (CodeToolBoss<>nil) then if (CodeToolBoss<>nil) then
Result:=CodeToolBoss.DefineTree.FindDefineTemplateByName( Result:=CodeToolBoss.DefineTree.FindDefineTemplateByName(
ProjectDefTemplName,true) ProjectsDefTemplName,true)
else else
Result:=nil; Result:=nil;
end; end;
function CreateProjectTemplate(var ProjectDirTemplate: TDefineTemplate function FindProjectTemplateWithID(const ProjectID: string): TDefineTemplate;
): TDefineTemplate;
var var
ProjectDir, ProjectSrcPath, ProjectIncPath, ProjectTempl: TDefineTemplate;
ProjectUnitPath: TDefineTemplate;
begin begin
if (CodeToolBoss=nil) then begin ProjectTempl:=FindProjectsTemplate;
Result:=nil; if ProjectTempl=nil then
exit; Result:=nil
end; else
Result:=FindCurrentProjectTemplate; Result:=ProjectTempl.FindChildByName(ProjectID);
if (Result<>nil) then begin end;
ProjectDirTemplate:=Result.FindChildByName(ProjectDirDefTemplName);
exit;
end;
// create the main template for the project
Result:=TDefineTemplate.Create(ProjectDefTemplName, lisEdtDefCurrentProject,
'', '',
da_Block);
// create the template for the project directory function CreateProjectsTemplate: TDefineTemplate;
ProjectDir:=TDefineTemplate.Create(ProjectDirDefTemplName, begin
lisEdtDefCurrentProjectDirectory, '', '$(#ProjPath)', da_Directory); Result:=FindProjectsTemplate;
Result.AddChild(ProjectDir); if Result<>nil then exit;
ProjectDirTemplate:=ProjectDir; Result:=TDefineTemplate.Create(ProjectsDefTemplName, lisEdtDefsAllProjects,
'', '', da_Block);
// create the template for the SrcPath Result.Flags:=[dtfAutoGenerated];
ProjectSrcPath:=TDefineTemplate.Create(ProjectDirSrcPathDefTemplName,
lisEdtDefProjectSrcPath, ExternalMacroStart+'SrcPath',
'$Project(SrcPath);$('+ExternalMacroStart+'SrcPath)',
da_DefineRecurse);
ProjectDir.AddChild(ProjectSrcPath);
// create the template for the IncPath
ProjectIncPath:=TDefineTemplate.Create(ProjectDirIncPathDefTemplName,
lisEdtDefProjectIncPath, ExternalMacroStart+'IncPath',
'$Project(IncPath);$('+ExternalMacroStart+'IncPath)',
da_DefineRecurse);
ProjectDir.AddChild(ProjectIncPath);
// create the template for the UnitPath
ProjectUnitPath:=TDefineTemplate.Create(ProjectDirUnitPathDefTemplName,
lisEdtDefProjectUnitPath, ExternalMacroStart+'UnitPath',
'$Project(UnitPath);$('+ExternalMacroStart+'UnitPath)',
da_DefineRecurse);
ProjectDir.AddChild(ProjectUnitPath);
Result.SetFlags([dtfAutoGenerated],[],false);
// insert behind all // insert behind all
CodeToolBoss.DefineTree.ReplaceRootSameName(Result); CodeToolBoss.DefineTree.ReplaceRootSameName(Result);
end; end;
function CreateProjectTemplateWithID(const ProjectID: string): TDefineTemplate;
var
ProjTempl: TDefineTemplate;
begin
ProjTempl:=CreateProjectsTemplate;
Result:=ProjTempl.FindChildByName(ProjectID);
if Result<>nil then exit;
Result:=TDefineTemplate.Create(ProjectID,ProjectID,'','',da_Block);
Result.Flags:=[dtfAutoGenerated];
ProjTempl.AddChild(Result);
end;
function CreatePackagesTemplate: TDefineTemplate; function CreatePackagesTemplate: TDefineTemplate;
begin begin
Result:=FindPackagesTemplate; Result:=FindPackagesTemplate;
if Result<>nil then exit; if Result<>nil then exit;
Result:=TDefineTemplate.Create(PackagesDefTemplName, lisEdtDefAllPackages, Result:=TDefineTemplate.Create(PackagesDefTemplName, lisEdtDefAllPackages,
'', '', '', '', da_Block);
da_Block);
Result.Flags:=[dtfAutoGenerated]; Result.Flags:=[dtfAutoGenerated];
// insert behind all // insert behind all
CodeToolBoss.DefineTree.ReplaceRootSameName(Result); CodeToolBoss.DefineTree.ReplaceRootSameName(Result);

View File

@ -148,14 +148,18 @@ begin
CurFileLen:=length(CurFileName); CurFileLen:=length(CurFileName);
if CurFileLen>0 then begin if CurFileLen>0 then begin
// add semicolon // add semicolon
FSearchPath[StartPos]:=';'; if StartPos>1 then begin
inc(StartPos); FSearchPath[StartPos]:=';';
inc(StartPos);
end;
// add path // add path
Move(CurFileName[1],FSearchPath[StartPos],CurFileLen); Move(CurFileName[1],FSearchPath[StartPos],CurFileLen);
inc(StartPos,CurFileLen); inc(StartPos,CurFileLen);
end; end;
ANode:=FTree.FindSuccessor(ANode); ANode:=FTree.FindSuccessor(ANode);
end; end;
if StartPos<>length(FSearchPath)+1 then
RaiseException('TFileReferenceList.UpdateSearchPath');
end; end;
Include(FFlags,frfSearchPathValid); Include(FFlags,frfSearchPathValid);
end; end;
@ -170,7 +174,7 @@ end;
procedure TFileReferenceList.Invalidate; procedure TFileReferenceList.Invalidate;
begin begin
if frfSearchPathValid in FFlags then exit; if not (frfSearchPathValid in FFlags) then exit;
Exclude(FFlags,frfSearchPathValid); Exclude(FFlags,frfSearchPathValid);
IncreaseTimeStamp; IncreaseTimeStamp;
if FUpdateLock>0 then if FUpdateLock>0 then

View File

@ -98,6 +98,7 @@ resourcestring
lisProjectSrcPath = 'Project Src Path'; lisProjectSrcPath = 'Project Src Path';
lisMakeExe = 'Make Executable'; lisMakeExe = 'Make Executable';
lisProjectMakroProperties = 'Project makro properties'; lisProjectMakroProperties = 'Project makro properties';
lisProjectMakroUnitPath = 'makro ProjectUnitPath';
lisConfigDirectory = 'Lazarus config directory'; lisConfigDirectory = 'Lazarus config directory';
// main bar menu // main bar menu
@ -2085,6 +2086,7 @@ resourcestring
lisEdtDefProjectIncPath = 'Project IncPath'; lisEdtDefProjectIncPath = 'Project IncPath';
lisEdtDefProjectUnitPath = 'Project UnitPath'; lisEdtDefProjectUnitPath = 'Project UnitPath';
lisEdtDefAllPackages = 'All packages'; lisEdtDefAllPackages = 'All packages';
lisEdtDefsAllProjects = 'All projects';
lisEdtDefsetFPCModeToDELPHI = 'set FPC mode to DELPHI'; lisEdtDefsetFPCModeToDELPHI = 'set FPC mode to DELPHI';
lisEdtDefsetFPCModeToTP = 'set FPC mode to TP'; lisEdtDefsetFPCModeToTP = 'set FPC mode to TP';
lisEdtDefsetFPCModeToGPC = 'set FPC mode to GPC'; lisEdtDefsetFPCModeToGPC = 'set FPC mode to GPC';
@ -2359,17 +2361,18 @@ resourcestring
+'components are outdated.'; +'components are outdated.';
lisPkgSysRegisterProcedureIsNil = 'Register procedure is nil'; lisPkgSysRegisterProcedureIsNil = 'Register procedure is nil';
lisPkgSysThisPackageIsInstalledButTheLpkFileWasNotFound = 'This package is ' lisPkgSysThisPackageIsInstalledButTheLpkFileWasNotFound = 'This package is '
+'installed, but the lpk file was not found.All its components are ' +'installed, but the lpk file was not found. All its components are '
+'deactivated. Please fix this.'; +'deactivated. Please fix this.';
lisPkgSysPackageFileNotFound = 'Package file not found'; lisPkgSysPackageFileNotFound = 'Package file not found';
lisPkgSysThePackageIsInstalledButNoValidPackageFileWasFound = 'The package %' lisPkgSysThePackageIsInstalledButNoValidPackageFileWasFound = 'The package %'
+'s%s%s is installed, but no valid package file was found.%sA broken ' +'s%s%s is installed, but no valid package file (.lpk) was found.%sA broken '
+'dummy package was created.'; +'dummy package was created.';
// package defs // package defs
lisPkgDefsOutputDirectory = 'Output directory'; lisPkgDefsOutputDirectory = 'Output directory';
lisPkgDefsCompiledSrcPathAddition = 'CompiledSrcPath addition'; lisPkgDefsCompiledSrcPathAddition = 'CompiledSrcPath addition';
lisPkgDefsUnitPath = 'Unit Path'; lisPkgDefsUnitPath = 'Unit Path';
lisProjProjectSourceDirectoryMark = 'Project Source Directory Mark';
lisPkgDefsSrcDirMark = 'Package Source Directory Mark'; lisPkgDefsSrcDirMark = 'Package Source Directory Mark';
// add active file to package dialog // add active file to package dialog

View File

@ -785,6 +785,9 @@ type
function OnMacroPromptFunction(const s:string; var Abort: boolean): string; function OnMacroPromptFunction(const s:string; var Abort: boolean): string;
function OnMacroFuncMakeExe(const Filename:string; var Abort: boolean): string; function OnMacroFuncMakeExe(const Filename:string; var Abort: boolean): string;
function OnMacroFuncProject(const Param: string; var Abort: boolean): string; function OnMacroFuncProject(const Param: string; var Abort: boolean): string;
function OnMacroFuncProjectUnitPath(Data: Pointer): boolean;
function OnMacroFuncProjectIncPath(Data: Pointer): boolean;
function OnMacroFuncProjectSrcPath(Data: Pointer): boolean;
procedure OnCmdLineCreate(var CmdLine: string; var Abort: boolean); procedure OnCmdLineCreate(var CmdLine: string; var Abort: boolean);
procedure GetIDEFileState(Sender: TObject; const AFilename: string; procedure GetIDEFileState(Sender: TObject; const AFilename: string;
NeededFlags: TIDEFileStateFlags; var ResultFlags: TIDEFileStateFlags); override; NeededFlags: TIDEFileStateFlags; var ResultFlags: TIDEFileStateFlags); override;
@ -1553,6 +1556,14 @@ begin
MacroList.OnSubstitution:=@OnMacroSubstitution; MacroList.OnSubstitution:=@OnMacroSubstitution;
CompilerOptions.OnParseString:=@OnSubstituteCompilerOption; CompilerOptions.OnParseString:=@OnSubstituteCompilerOption;
// projects macro functions
CodeToolBoss.DefineTree.MacroFunctions.AddExtended(
'PROJECTUNITPATH',nil,@OnMacroFuncProjectUnitPath);
CodeToolBoss.DefineTree.MacroFunctions.AddExtended(
'PROJECTINCPATH',nil,@OnMacroFuncProjectIncPath);
CodeToolBoss.DefineTree.MacroFunctions.AddExtended(
'PROJECTSRCPATH',nil,@OnMacroFuncProjectSrcPath);
end; end;
procedure TMainIDE.SetupCodeMacros; procedure TMainIDE.SetupCodeMacros;
@ -4016,7 +4027,7 @@ function TMainIDE.DoRenameUnit(AnUnitInfo: TUnitInfo;
var ResourceCode: TCodeBuffer): TModalresult; var ResourceCode: TCodeBuffer): TModalresult;
var var
NewLFMFilename: String; NewLFMFilename: String;
OldSource: String; OldSourceCode: String;
NewSource: TCodeBuffer; NewSource: TCodeBuffer;
NewFilePath: String; NewFilePath: String;
NewResFilePath: String; NewResFilePath: String;
@ -4070,9 +4081,9 @@ begin
end; end;
// create new source with the new filename // create new source with the new filename
OldSource:=AnUnitInfo.Source.Source; OldSourceCode:=AnUnitInfo.Source.Source;
NewSource:=CodeToolBoss.CreateFile(NewFilename); NewSource:=CodeToolBoss.CreateFile(NewFilename);
NewSource.Source:=OldSource; NewSource.Source:=OldSourceCode;
if NewSource=nil then begin if NewSource=nil then begin
Result:=MessageDlg(lisUnableToCreateFile, Result:=MessageDlg(lisUnableToCreateFile,
Format(lisCanNotCreateFile, ['"', NewFilename, '"']), Format(lisCanNotCreateFile, ['"', NewFilename, '"']),
@ -4953,6 +4964,7 @@ begin
PkgBoss.OpenProjectDependencies(Project1,true); PkgBoss.OpenProjectDependencies(Project1,true);
Project1.DefineTemplates.AllChanged; Project1.DefineTemplates.AllChanged;
Project1.DefineTemplates.Active:=true;
Result:=mrOk; Result:=mrOk;
end; end;
@ -8852,6 +8864,42 @@ begin
end; end;
end; end;
function TMainIDE.OnMacroFuncProjectUnitPath(Data: Pointer): boolean;
var
FuncData: PReadFunctionData;
begin
FuncData:=PReadFunctionData(Data);
Result:=false;
if Project1<>nil then begin
FuncData^.Result:=Project1.CompilerOptions.GetUnitPath(false);
Result:=true;
end;
end;
function TMainIDE.OnMacroFuncProjectIncPath(Data: Pointer): boolean;
var
FuncData: PReadFunctionData;
begin
FuncData:=PReadFunctionData(Data);
Result:=false;
if Project1<>nil then begin
FuncData^.Result:=Project1.CompilerOptions.GetIncludePath(false);
Result:=true;
end;
end;
function TMainIDE.OnMacroFuncProjectSrcPath(Data: Pointer): boolean;
var
FuncData: PReadFunctionData;
begin
FuncData:=PReadFunctionData(Data);
Result:=false;
if Project1<>nil then begin
FuncData^.Result:=Project1.CompilerOptions.GetSrcPath(false);
Result:=true;
end;
end;
procedure TMainIDE.OnCmdLineCreate(var CmdLine: string; var Abort:boolean); procedure TMainIDE.OnCmdLineCreate(var CmdLine: string; var Abort:boolean);
// replace all transfer macros in command line // replace all transfer macros in command line
begin begin

View File

@ -122,6 +122,7 @@ type
fUserReadOnly: Boolean; fUserReadOnly: Boolean;
FSourceDirectoryReferenced: boolean; FSourceDirectoryReferenced: boolean;
FSourceDirNeedReference: boolean; FSourceDirNeedReference: boolean;
fLastDirectoryReferenced: string;
function GetHasResources:boolean; function GetHasResources:boolean;
function GetNextAutoRevertLockedUnit: TUnitInfo; function GetNextAutoRevertLockedUnit: TUnitInfo;
@ -150,6 +151,7 @@ type
procedure SetFilename(const AValue: string); override; procedure SetFilename(const AValue: string); override;
procedure SetIsPartOfProject(const AValue: boolean); override; procedure SetIsPartOfProject(const AValue: boolean); override;
procedure UpdateList(ListType: TUnitInfoList; Add: boolean); procedure UpdateList(ListType: TUnitInfoList; Add: boolean);
procedure SetInternalFilename(const NewFilename: string);
public public
constructor Create(ACodeBuffer: TCodeBuffer); constructor Create(ACodeBuffer: TCodeBuffer);
destructor Destroy; override; destructor Destroy; override;
@ -158,6 +160,7 @@ type
function IsAutoRevertLocked: boolean; function IsAutoRevertLocked: boolean;
function IsMainUnit: boolean; function IsMainUnit: boolean;
function IsVirtual: boolean; function IsVirtual: boolean;
function GetDirectory: string;
function NeedsSaveToDisk: boolean; function NeedsSaveToDisk: boolean;
function ReadOnly: boolean; function ReadOnly: boolean;
function ReadUnitSource(ReadUnitName,Revert:boolean): TModalResult; function ReadUnitSource(ReadUnitName,Revert:boolean): TModalResult;
@ -266,6 +269,14 @@ type
procedure SetTargetCPU(const AValue: string); override; procedure SetTargetCPU(const AValue: string); override;
procedure SetTargetOS(const AValue: string); override; procedure SetTargetOS(const AValue: string); override;
procedure SetCustomOptions(const AValue: string); override;
procedure SetIncludeFiles(const AValue: string); override;
procedure SetLibraries(const AValue: string); override;
procedure SetLinkerOptions(const AValue: string); override;
procedure SetObjectPath(const AValue: string); override;
procedure SetSrcPath(const AValue: string); override;
procedure SetOtherUnitFiles(const AValue: string); override;
procedure SetUnitOutputDir(const AValue: string); override;
procedure UpdateGlobals; virtual; procedure UpdateGlobals; virtual;
public public
constructor Create(const AOwner: TObject); override; constructor Create(const AOwner: TObject); override;
@ -275,8 +286,10 @@ type
procedure GetInheritedCompilerOptions(var OptionsList: TList); override; procedure GetInheritedCompilerOptions(var OptionsList: TList); override;
procedure Assign(Source: TPersistent); override; procedure Assign(Source: TPersistent); override;
function IsEqual(CompOpts: TBaseCompilerOptions): boolean; override; function IsEqual(CompOpts: TBaseCompilerOptions): boolean; override;
procedure InvalidateOptions;
public public
property OwnerProject: TProject read FOwnerProject; property OwnerProject: TProject read FOwnerProject;
property Project: TProject read FOwnerProject;
property Globals: TGlobalCompilerOptions read FGlobals; property Globals: TGlobalCompilerOptions read FGlobals;
property CompileReasons: TCompileReasons read FCompileReasons write FCompileReasons; property CompileReasons: TCompileReasons read FCompileReasons write FCompileReasons;
end; end;
@ -285,19 +298,35 @@ type
{ TProjectDefineTemplates } { TProjectDefineTemplates }
TProjectDefineTemplatesFlag = ( TProjectDefineTemplatesFlag = (
ptfFlagsChanged ptfFlagsChanged,
ptfIDChanged,
ptfSourceDirsChanged,
ptfOutputDirChanged,
ptfCustomDefinesChanged
); );
TProjectDefineTemplatesFlags = set of TProjectDefineTemplatesFlag; TProjectDefineTemplatesFlags = set of TProjectDefineTemplatesFlag;
TProjectDefineTemplates = class TProjectDefineTemplates = class
private private
FActive: boolean;
FCustomDefines: TDefineTemplate;
FFlags: TProjectDefineTemplatesFlags; FFlags: TProjectDefineTemplatesFlags;
FMain: TDefineTemplate; FMain: TDefineTemplate;
FOutputDir: TDefineTemplate;
FOutPutSrcPath: TDefineTemplate;
FProjectDir: TDefineTemplate; FProjectDir: TDefineTemplate;
FProject: TProject; FOwnerProject: TProject;
FUpdateLock: integer; FUpdateLock: integer;
fLastSourceDirectories: TStringList;
fLastOutputDirSrcPathIDAsString: string;
fLastSourceDirsIDAsString: string;
fLastSourceDirStamp: integer;
FLastCustomOptions: string;
procedure SetActive(const AValue: boolean);
procedure UpdateMain; procedure UpdateMain;
procedure UpdateDefinesForOutputDirectory;
procedure UpdateDefinesForSourceDirectories; procedure UpdateDefinesForSourceDirectories;
procedure UpdateDefinesForCustomDefines;
public public
constructor Create(OwnerProject: TProject); constructor Create(OwnerProject: TProject);
destructor Destroy; override; destructor Destroy; override;
@ -306,11 +335,19 @@ type
procedure EndUpdate; procedure EndUpdate;
procedure CompilerFlagsChanged; procedure CompilerFlagsChanged;
procedure AllChanged; procedure AllChanged;
procedure ProjectIDChanged;
procedure SourceDirectoriesChanged; procedure SourceDirectoriesChanged;
procedure OutputDirectoryChanged;
procedure CustomDefinesChanged;
procedure UpdateGlobalValues; procedure UpdateGlobalValues;
public public
property Owner: TProject read FProject; property Owner: TProject read FOwnerProject;
property Project: TProject read FOwnerProject;
property Main: TDefineTemplate read FMain; property Main: TDefineTemplate read FMain;
property OutputDir: TDefineTemplate read FOutputDir;
property OutPutSrcPath: TDefineTemplate read FOutPutSrcPath;
property CustomDefines: TDefineTemplate read FCustomDefines;
property Active: boolean read FActive write SetActive;
end; end;
@ -402,7 +439,6 @@ type
fPathDelimChanged: boolean; fPathDelimChanged: boolean;
fProjectDirectory: string; fProjectDirectory: string;
fProjectInfoFile: String; // the lpi filename fProjectInfoFile: String; // the lpi filename
//fProjectType: TProjectType;
FPublishOptions: TPublishProjectOptions; FPublishOptions: TPublishProjectOptions;
FRunParameterOptions: TRunParamsOptions; FRunParameterOptions: TRunParamsOptions;
FSourceDirectories: TFileReferenceList; FSourceDirectories: TFileReferenceList;
@ -460,6 +496,7 @@ type
procedure BeginUpdate(Change: boolean); procedure BeginUpdate(Change: boolean);
procedure EndUpdate; procedure EndUpdate;
procedure UnitModified(AnUnitInfo: TUnitInfo); procedure UnitModified(AnUnitInfo: TUnitInfo);
function NeedsDefineTemplates: boolean;
// load/save // load/save
function IsVirtual: boolean; function IsVirtual: boolean;
@ -473,6 +510,8 @@ type
// title // title
function GetDefaultTitle: string; function GetDefaultTitle: string;
function TitleIsDefault: boolean; function TitleIsDefault: boolean;
function IDAsString: string;
function IDAsWord: string;
// units // units
function UnitCount:integer; function UnitCount:integer;
@ -656,7 +695,7 @@ begin
exit; exit;
end; end;
if Assigned(fOnFileBackup) then begin if Assigned(fOnFileBackup) then begin
Result:=fOnFileBackup(fFilename,IsPartOfProject); Result:=fOnFileBackup(Filename,IsPartOfProject);
if Result=mrAbort then exit; if Result=mrAbort then exit;
end; end;
repeat repeat
@ -685,7 +724,7 @@ begin
exit; exit;
end; end;
if Assigned(fOnFileBackup) then begin if Assigned(fOnFileBackup) then begin
Result:=fOnFileBackup(fFilename,false); Result:=fOnFileBackup(Filename,false);
if Result=mrAbort then exit; if Result=mrAbort then exit;
end; end;
repeat repeat
@ -712,10 +751,10 @@ var
NewSource: TCodeBuffer; NewSource: TCodeBuffer;
begin begin
repeat repeat
NewSource:=CodeToolBoss.LoadFile(fFilename,true,Revert); NewSource:=CodeToolBoss.LoadFile(Filename,true,Revert);
if NewSource=nil then begin if NewSource=nil then begin
ACaption:=lisCodeToolsDefsReadError; ACaption:=lisCodeToolsDefsReadError;
AText:=Format(lisUnableToReadFile2, ['"', fFilename, '"']); AText:=Format(lisUnableToReadFile2, ['"', Filename, '"']);
Result:=Application.MessageBox(PChar(AText),PChar(ACaption) Result:=Application.MessageBox(PChar(AText),PChar(ACaption)
,MB_ABORTRETRYIGNORE); ,MB_ABORTRETRYIGNORE);
if Result in [mrAbort,mrIgnore] then if Result in [mrAbort,mrIgnore] then
@ -783,7 +822,8 @@ begin
fFilename := ''; fFilename := '';
fFileReadOnly := false; fFileReadOnly := false;
fHasResources := false; fHasResources := false;
FIgnoreFileDateOnDiskValid:=false; FIgnoreFileDateOnDiskValid := false;
fAutoReferenceSourceDir := true;
inherited SetIsPartOfProject(false); inherited SetIsPartOfProject(false);
fModified := false; fModified := false;
FSessionModified := false; FSessionModified := false;
@ -906,10 +946,29 @@ begin
end; end;
end; end;
procedure TUnitInfo.SetInternalFilename(const NewFilename: string);
begin
if fFileName=NewFilename then exit;
//DebugLn('TUnitInfo.SetInternalFilename Old=',fFileName,' New=',NewFilename);
// if directory changed then remove the old directory reference
if SourceDirectoryReferenced
and (Project<>nil)
and (fLastDirectoryReferenced<>GetDirectory) then begin
Project.SourceDirectories.RemoveFilename(fLastDirectoryReferenced);
FSourceDirectoryReferenced:=false;
end;
fFileName:=NewFilename;
UpdateSourceDirectoryReference;
end;
function TUnitInfo.GetFileName: string; function TUnitInfo.GetFileName: string;
begin begin
if fSource<>nil then Result:=fSource.Filename if fSource<>nil then
else Result:=fFileName; Result:=fSource.Filename
else
Result:=fFileName;
end; end;
procedure TUnitInfo.SetFilename(const AValue: string); procedure TUnitInfo.SetFilename(const AValue: string);
@ -917,7 +976,7 @@ begin
if fSource<>nil then if fSource<>nil then
RaiseException('TUnitInfo.SetFilename Source<>nil') RaiseException('TUnitInfo.SetFilename Source<>nil')
else else
fFileName:=AValue; SetInternalFilename(AValue);
end; end;
function TUnitInfo.IsVirtual: boolean; function TUnitInfo.IsVirtual: boolean;
@ -928,6 +987,18 @@ begin
Result:=(fFileName<>ExpandFileName(fFileName)); Result:=(fFileName<>ExpandFileName(fFileName));
end; end;
function TUnitInfo.GetDirectory: string;
begin
if IsVirtual then begin
if Project<>nil then
Result:=Project.ProjectDirectory
else
Result:='';
end else begin
Result:=ExtractFilePath(Filename);
end;
end;
function TUnitInfo.IsMainUnit: boolean; function TUnitInfo.IsMainUnit: boolean;
begin begin
Result:=(Project<>nil) and (Project.MainUnitInfo=Self); Result:=(Project<>nil) and (Project.MainUnitInfo=Self);
@ -1018,15 +1089,19 @@ end;
procedure TUnitInfo.UpdateSourceDirectoryReference; procedure TUnitInfo.UpdateSourceDirectoryReference;
begin begin
FSourceDirNeedReference:=IsPartOfProject and (FilenameIsPascalUnit(Filename));
if (not AutoReferenceSourceDir) or (FProject=nil) then exit; if (not AutoReferenceSourceDir) or (FProject=nil) then exit;
if FSourceDirNeedReference then begin if FSourceDirNeedReference then begin
if not SourceDirectoryReferenced then begin if not SourceDirectoryReferenced then begin
//Project.SourceDirectories.AddFilename(FDirectory); fLastDirectoryReferenced:=GetDirectory;
Project.SourceDirectories.AddFilename(fLastDirectoryReferenced);
//DebugLn('TUnitInfo.UpdateSourceDirectoryReference ADD File="',Filename,' Path="',Project.SourceDirectories.CreateSearchPathFromAllFiles,'"');
FSourceDirectoryReferenced:=true; FSourceDirectoryReferenced:=true;
end; end;
end else begin end else begin
if SourceDirectoryReferenced then begin if SourceDirectoryReferenced then begin
//Project.SourceDirectories.RemoveFilename(FDirectory); Project.SourceDirectories.RemoveFilename(fLastDirectoryReferenced);
//DebugLn('TUnitInfo.UpdateSourceDirectoryReference REMOVE File="',Filename,' Path="',Project.SourceDirectories.CreateSearchPathFromAllFiles,'"');
FSourceDirectoryReferenced:=false; FSourceDirectoryReferenced:=false;
end; end;
end; end;
@ -1057,7 +1132,7 @@ begin
if (fSource<>nil) then begin if (fSource<>nil) then begin
if IsAutoRevertLocked then if IsAutoRevertLocked then
fSource.LockAutoDiskRevert; fSource.LockAutoDiskRevert;
fFileName:=fSource.FileName; SetInternalFilename(fSource.FileName);
if (fProject<>nil) and (fProject.MainUnitInfo=Self) then if (fProject<>nil) and (fProject.MainUnitInfo=Self) then
fProject.MainSourceFilenameChanged; fProject.MainSourceFilenameChanged;
end; end;
@ -1148,8 +1223,7 @@ procedure TUnitInfo.SetAutoReferenceSourceDir(const AValue: boolean);
begin begin
if FAutoReferenceSourceDir=AValue then exit; if FAutoReferenceSourceDir=AValue then exit;
FAutoReferenceSourceDir:=AValue; FAutoReferenceSourceDir:=AValue;
if FSourceDirNeedReference then UpdateSourceDirectoryReference;
UpdateSourceDirectoryReference;
end; end;
procedure TUnitInfo.SetBuildFileIfActive(const AValue: boolean); procedure TUnitInfo.SetBuildFileIfActive(const AValue: boolean);
@ -1188,6 +1262,7 @@ begin
inherited SetIsPartOfProject(AValue); inherited SetIsPartOfProject(AValue);
UpdateList(uilPartOfProject,IsPartOfProject); UpdateList(uilPartOfProject,IsPartOfProject);
if IsPartOfProject then UpdateUsageCount(uuIsPartOfProject,0); if IsPartOfProject then UpdateUsageCount(uuIsPartOfProject,0);
UpdateSourceDirectoryReference;
if Project<>nil then Project.EndUpdate; if Project<>nil then Project.EndUpdate;
end; end;
@ -1227,6 +1302,7 @@ begin
if IsAutoRevertLocked then Project.AddToList(Self,uilAutoRevertLocked); if IsAutoRevertLocked then Project.AddToList(Self,uilAutoRevertLocked);
if IsPartOfProject then Project.AddToList(Self,uilPartOfProject); if IsPartOfProject then Project.AddToList(Self,uilPartOfProject);
end; end;
UpdateSourceDirectoryReference;
end; end;
procedure TUnitInfo.SetRunFileIfActive(const AValue: boolean); procedure TUnitInfo.SetRunFileIfActive(const AValue: boolean);
@ -1276,6 +1352,7 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
destructor TProject.Destroy; destructor TProject.Destroy;
begin begin
FDefineTemplates.Active:=false;
fDestroying:=true; fDestroying:=true;
Clear; Clear;
FreeThenNil(FBookmarks); FreeThenNil(FBookmarks);
@ -1472,6 +1549,16 @@ begin
Result:=(Title='') or (Title=GetDefaultTitle); Result:=(Title='') or (Title=GetDefaultTitle);
end; end;
function TProject.IDAsString: string;
begin
Result:='Project'; // TODO: see TLazPackage
end;
function TProject.IDAsWord: string;
begin
Result:='Project'; // TODO: see TLazPackage
end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
TProject ReadProject TProject ReadProject
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
@ -1490,7 +1577,6 @@ var
Path: String; Path: String;
OldProjectType: TOldProjectType; OldProjectType: TOldProjectType;
xmlconfig: TXMLConfig; xmlconfig: TXMLConfig;
SourceDirectoriesUpdated: Boolean;
SubPath: String; SubPath: String;
NewUnitFilename: String; NewUnitFilename: String;
@ -1578,7 +1664,6 @@ begin
exit; exit;
end; end;
SourceDirectoriesUpdated:=true;
try try
Path:='ProjectOptions/'; Path:='ProjectOptions/';
fPathDelimChanged:= fPathDelimChanged:=
@ -1602,7 +1687,6 @@ begin
OldSrcPath := xmlconfig.GetValue(Path+'General/SrcPath/Value',''); OldSrcPath := xmlconfig.GetValue(Path+'General/SrcPath/Value','');
{$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TProject.ReadProject D reading units');{$ENDIF} {$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TProject.ReadProject D reading units');{$ENDIF}
SourceDirectoriesUpdated:=false;
NewUnitCount:=xmlconfig.GetValue(Path+'Units/Count',0); NewUnitCount:=xmlconfig.GetValue(Path+'Units/Count',0);
for i := 0 to NewUnitCount - 1 do begin for i := 0 to NewUnitCount - 1 do begin
SubPath:=Path+'Units/Unit'+IntToStr(i)+'/'; SubPath:=Path+'Units/Unit'+IntToStr(i)+'/';
@ -1618,8 +1702,6 @@ begin
AddFile(NewUnitInfo,false); AddFile(NewUnitInfo,false);
NewUnitInfo.LoadFromXMLConfig(xmlconfig,SubPath); NewUnitInfo.LoadFromXMLConfig(xmlconfig,SubPath);
end; end;
UpdateSourceDirectories;
SourceDirectoriesUpdated:=true;
//lazdoc //lazdoc
LazDocPathList.Text := xmlconfig.GetValue(Path+'LazDoc/Paths', ''); LazDocPathList.Text := xmlconfig.GetValue(Path+'LazDoc/Paths', '');
@ -1652,8 +1734,6 @@ begin
if Assigned(OnLoadProjectInfo) then OnLoadProjectInfo(Self,XMLConfig); if Assigned(OnLoadProjectInfo) then OnLoadProjectInfo(Self,XMLConfig);
finally finally
if not SourceDirectoriesUpdated then
UpdateSourceDirectories;
{$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TProject.ReadProject freeing xml');{$ENDIF} {$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TProject.ReadProject freeing xml');{$ENDIF}
fPathDelimChanged:=false; fPathDelimChanged:=false;
try try
@ -1808,6 +1888,7 @@ procedure TProject.BeginUpdate(Change: boolean);
begin begin
inc(FUpdateLock); inc(FUpdateLock);
FDefineTemplates.BeginUpdate; FDefineTemplates.BeginUpdate;
FSourceDirectories.BeginUpdate;
if FUpdateLock=1 then begin if FUpdateLock=1 then begin
fChanged:=Change; fChanged:=Change;
if Assigned(OnBeginUpdate) then OnBeginUpdate(Self); if Assigned(OnBeginUpdate) then OnBeginUpdate(Self);
@ -1819,6 +1900,7 @@ procedure TProject.EndUpdate;
begin begin
if FUpdateLock<=0 then RaiseException('TProject.EndUpdate'); if FUpdateLock<=0 then RaiseException('TProject.EndUpdate');
dec(FUpdateLock); dec(FUpdateLock);
FSourceDirectories.EndUpdate;
FDefineTemplates.EndUpdate; FDefineTemplates.EndUpdate;
if FUpdateLock=0 then begin if FUpdateLock=0 then begin
if Assigned(OnEndUpdate) then OnEndUpdate(Self,fChanged); if Assigned(OnEndUpdate) then OnEndUpdate(Self,fChanged);
@ -1833,6 +1915,11 @@ begin
SessionModified:=true; SessionModified:=true;
end; end;
function TProject.NeedsDefineTemplates: boolean;
begin
Result:=not Destroying;
end;
function TProject.GetUnits(Index:integer):TUnitInfo; function TProject.GetUnits(Index:integer):TUnitInfo;
begin begin
Result:=TUnitInfo(FUnitList[Index]); Result:=TUnitInfo(FUnitList[Index]);
@ -2675,7 +2762,7 @@ begin
end; end;
function TProject.JumpHistoryCheckPosition( function TProject.JumpHistoryCheckPosition(
APosition:TProjectJumpHistoryPosition): boolean; APosition: TProjectJumpHistoryPosition): boolean;
var i: integer; var i: integer;
begin begin
i:=IndexOfFilename(APosition.Filename); i:=IndexOfFilename(APosition.Filename);
@ -3050,6 +3137,66 @@ begin
FGlobals.TargetOS:=TargetOS; FGlobals.TargetOS:=TargetOS;
end; end;
procedure TProjectCompilerOptions.SetCustomOptions(const AValue: string);
begin
if CustomOptions=AValue then exit;
InvalidateOptions;
inherited SetCustomOptions(AValue);
if Project<>nil then
Project.DefineTemplates.CustomDefinesChanged;
end;
procedure TProjectCompilerOptions.SetIncludeFiles(const AValue: string);
begin
if IncludeFiles=AValue then exit;
InvalidateOptions;
inherited SetIncludeFiles(AValue);
end;
procedure TProjectCompilerOptions.SetLibraries(const AValue: string);
begin
if Libraries=AValue then exit;
InvalidateOptions;
inherited SetLibraries(AValue);
end;
procedure TProjectCompilerOptions.SetLinkerOptions(const AValue: string);
begin
if LinkerOptions=AValue then exit;
InvalidateOptions;
inherited SetLinkerOptions(AValue);
end;
procedure TProjectCompilerOptions.SetObjectPath(const AValue: string);
begin
if ObjectPath=AValue then exit;
InvalidateOptions;
inherited SetObjectPath(AValue);
end;
procedure TProjectCompilerOptions.SetSrcPath(const AValue: string);
begin
if SrcPath=AValue then exit;
InvalidateOptions;
inherited SetSrcPath(AValue);
end;
procedure TProjectCompilerOptions.SetOtherUnitFiles(const AValue: string);
begin
if OtherUnitFiles=AValue then exit;
InvalidateOptions;
inherited SetOtherUnitFiles(AValue);
end;
procedure TProjectCompilerOptions.SetUnitOutputDir(const AValue: string);
begin
if UnitOutputDirectory=AValue then exit;
InvalidateOptions;
inherited SetUnitOutputDir(AValue);
if Project<>nil then
Project.DefineTemplates.OutputDirectoryChanged;
end;
procedure TProjectCompilerOptions.Assign(Source: TPersistent); procedure TProjectCompilerOptions.Assign(Source: TPersistent);
begin begin
inherited Assign(Source); inherited Assign(Source);
@ -3067,6 +3214,12 @@ begin
and inherited IsEqual(CompOpts); and inherited IsEqual(CompOpts);
end; end;
procedure TProjectCompilerOptions.InvalidateOptions;
begin
if (Project=nil) then exit;
// TODO: propagate change to all dependants projects
end;
procedure TProjectCompilerOptions.UpdateGlobals; procedure TProjectCompilerOptions.UpdateGlobals;
begin begin
FGlobals.TargetCPU:=TargetCPU; FGlobals.TargetCPU:=TargetCPU;
@ -3127,15 +3280,207 @@ end;
{ TProjectDefineTemplates } { TProjectDefineTemplates }
procedure TProjectDefineTemplates.SetActive(const AValue: boolean);
begin
if FActive=AValue then exit;
FActive:=AValue;
if not FActive then Clear else AllChanged;
end;
procedure TProjectDefineTemplates.UpdateMain;
begin
//DebugLn('TProjectDefineTemplates.UpdateMain ',Project.IDAsString,' Active=',dbgs(Active));
// update the package block define template (the container for all other
// define templates of the project)
if (FMain=nil) and (not Project.Destroying) then begin
// create the main project template
FMain:=CreateProjectTemplateWithID(Project.IDAsWord);
FMain.SetDefineOwner(Owner,false);
FMain.SetFlags([dtfAutoGenerated],[],false);
end else
FMain.Name:=Project.IDAsWord;
// ClearCache is here unnessary, because it is only a block
end;
procedure TProjectDefineTemplates.UpdateDefinesForOutputDirectory;
begin
//DebugLn('TProjectDefineTemplates.UpdateDefinesForOutputDirectory ',Project.IDAsString);
if (not Project.NeedsDefineTemplates) or (not Active) then exit;
if FMain=nil then UpdateMain;
if FOutputDir=nil then begin
//DebugLn('TProjectDefineTemplates.UpdateDefinesForOutputDirectory ',Project.IDAsString,' creating FOutputDir');
FOutputDir:=TDefineTemplate.Create(ProjectOutputDirDefTemplName,
'Output directoy of project', '', Project.GetOutputDirectory, da_Directory
);
FOutputDir.SetDefineOwner(Project,false);
FOutputDir.SetFlags([dtfAutoGenerated],[],false);
FMain.AddChild(FOutputDir);
end else begin
FOutputDir.Value:=Project.GetOutputDirectory;
end;
if (FOutPutSrcPath=nil)
or (fLastOutputDirSrcPathIDAsString<>Project.IDAsString) then begin
fLastOutputDirSrcPathIDAsString:=Project.IDAsString;
FOutputSrcPath:=TDefineTemplate.Create('CompiledSrcPath',
lisPkgDefsCompiledSrcPathAddition, CompiledSrcPathMacroName,
'$PkgSrcPath('+fLastOutputDirSrcPathIDAsString+');'
+'$('+CompiledSrcPathMacroName+')',
da_Define);
FOutputSrcPath.SetDefineOwner(Project,false);
FOutputSrcPath.SetFlags([dtfAutoGenerated],[],false);
CodeToolBoss.DefineTree.ReplaceChild(FOutputDir,FOutputSrcPath,
FOutputSrcPath.Name);
end;
end;
procedure TProjectDefineTemplates.UpdateDefinesForSourceDirectories;
var
NewSourceDirs: TStringList;
i: Integer;
SrcDirDefTempl: TDefineTemplate;
UnitPathDefTempl: TDefineTemplate;
IncPathDefTempl: TDefineTemplate;
IDHasChanged: Boolean;
SrcDirMarkDefTempl: TDefineTemplate;
SrcPathDefTempl: TDefineTemplate;
begin
//DebugLn('TProjectDefineTemplates.UpdateDefinesForSourceDirectories ',Project.IDAsString,' Active=',dbgs(Active));
if (not Project.NeedsDefineTemplates) or (not Active) then exit;
// quick check if something has changed
IDHasChanged:=fLastSourceDirsIDAsString<>Project.IDAsString;
if (fLastSourceDirectories<>nil)
and (fLastSourceDirStamp=Project.SourceDirectories.TimeStamp)
and (not IDHasChanged) then
exit;
fLastSourceDirStamp:=Project.SourceDirectories.TimeStamp;
fLastSourceDirsIDAsString:=Project.IDAsString;
NewSourceDirs:=Project.SourceDirectories.CreateFileList;
try
// real check if something has changed
if (fLastSourceDirectories<>nil)
and (NewSourceDirs.Count=fLastSourceDirectories.Count)
and (not IDHasChanged) then begin
i:=NewSourceDirs.Count-1;
while (i>=0)
and (CompareFilenames(NewSourceDirs[i],fLastSourceDirectories[i])=0) do
dec(i);
if i<0 then exit;
end;
// clear old define templates
if fLastSourceDirectories<>nil then begin
for i:=0 to fLastSourceDirectories.Count-1 do begin
SrcDirDefTempl:=TDefineTemplate(fLastSourceDirectories.Objects[i]);
SrcDirDefTempl.Unbind;
SrcDirDefTempl.Free;
end;
fLastSourceDirectories.Clear;
end else
fLastSourceDirectories:=TStringList.Create;
// build source directory define templates
fLastSourceDirectories.Assign(NewSourceDirs);
if (FMain=nil) and (fLastSourceDirectories.Count>0) then UpdateMain;
for i:=0 to fLastSourceDirectories.Count-1 do begin
// create directory template
SrcDirDefTempl:=TDefineTemplate.Create('Source Directory '+IntToStr(i+1),
fLastSourceDirectories[i],'',fLastSourceDirectories[i],da_Directory);
fLastSourceDirectories.Objects[i]:=SrcDirDefTempl;
// add project source directory marker
SrcDirMarkDefTempl:=TDefineTemplate.Create('ProjectSrcDirMark',
lisProjProjectSourceDirectoryMark, '#ProjectSrcMark'+Project.IDAsWord,
'',
da_Define);
SrcDirDefTempl.AddChild(SrcDirMarkDefTempl);
// create unit path template for this directory
UnitPathDefTempl:=TDefineTemplate.Create('UnitPath', lisPkgDefsUnitPath,
'#UnitPath','$(#UnitPath);$ProjectUnitPath('+Project.IDAsString+')',
da_Define);
SrcDirDefTempl.AddChild(UnitPathDefTempl);
// create include path template for this directory
IncPathDefTempl:=TDefineTemplate.Create('IncPath','Include Path',
'#IncPath','$(#IncPath);$ProjectIncPath('+Project.IDAsString+')',
da_Define);
SrcDirDefTempl.AddChild(IncPathDefTempl);
// create src path template for this directory
SrcPathDefTempl:=TDefineTemplate.Create('SrcPath','Src Path',
'#SrcPath','$(#SrcPath);$ProjectSrcPath('+Project.IDAsString+')',
da_Define);
SrcDirDefTempl.AddChild(SrcPathDefTempl);
SrcDirDefTempl.SetDefineOwner(Project,false);
SrcDirDefTempl.SetFlags([dtfAutoGenerated],[],false);
// add directory
FMain.AddChild(SrcDirDefTempl);
end;
CodeToolBoss.DefineTree.ClearCache;
finally
NewSourceDirs.Free;
end;
end;
procedure TProjectDefineTemplates.UpdateDefinesForCustomDefines;
var
OptionsDefTempl: TDefineTemplate;
NewCustomOptions: String;
begin
if (not Project.NeedsDefineTemplates) or (not Active) then exit;
// check if something has changed
NewCustomOptions:=Project.CompilerOptions.GetCustomOptions;
if FLastCustomOptions=NewCustomOptions then exit;
FLastCustomOptions:=NewCustomOptions;
OptionsDefTempl:=CodeToolBoss.DefinePool.CreateFPCCommandLineDefines(
'Custom Options',FLastCustomOptions,false,Project);
if OptionsDefTempl=nil then begin
// no custom options -> delete old template
if FCustomDefines<>nil then begin
FCustomDefines.UnBind;
FCustomDefines.Free;
FCustomDefines:=nil;
end;
exit;
end;
// create custom options
// The custom options are enclosed by an
// IFDEF #ProjectSrcMark<PckId> template.
// Each source directory defines this variable, so that the settings can be
// activated for each source directory by a simple DEFINE.
if (FMain=nil) then UpdateMain;
if FCustomDefines=nil then begin
FCustomDefines:=TDefineTemplate.Create('Source Directory Additions',
'Additional defines for project source directories',
'#ProjectSrcMark'+Project.IDAsWord,'',
da_IfDef);
FMain.AddChild(FCustomDefines);
end else begin
FCustomDefines.Value:='#ProjectSrcMark'+Project.IDAsWord;
end;
FCustomDefines.ReplaceChild(OptionsDefTempl);
CodeToolBoss.DefineTree.ClearCache;
end;
constructor TProjectDefineTemplates.Create(OwnerProject: TProject); constructor TProjectDefineTemplates.Create(OwnerProject: TProject);
begin begin
inherited Create; inherited Create;
FProject:=OwnerProject; FOwnerProject:=OwnerProject;
end; end;
destructor TProjectDefineTemplates.Destroy; destructor TProjectDefineTemplates.Destroy;
begin begin
Clear; Clear;
fLastSourceDirectories.Free;
inherited Destroy; inherited Destroy;
end; end;
@ -3161,27 +3506,12 @@ begin
dec(FUpdateLock); dec(FUpdateLock);
if FUpdateLock=0 then begin if FUpdateLock=0 then begin
if ptfFlagsChanged in FFlags then CompilerFlagsChanged; if ptfFlagsChanged in FFlags then CompilerFlagsChanged;
if ptfSourceDirsChanged in FFlags then SourceDirectoriesChanged;
if ptfOutputDirChanged in FFlags then OutputDirectoryChanged;
if ptfCustomDefinesChanged in FFlags then CustomDefinesChanged;
end; end;
end; end;
procedure TProjectDefineTemplates.UpdateMain;
begin
// update the package block define template (the container for all other
// define templates of the package)
if (FMain=nil) and (not Owner.Destroying) then begin
// create the main project template
FMain:=CreateProjectTemplate(FProjectDir);
FMain.SetDefineOwner(Owner,false);
FMain.SetFlags([dtfAutoGenerated],[],false);
end;
// ClearCache is here unnessary, because it is only a block
end;
procedure TProjectDefineTemplates.UpdateDefinesForSourceDirectories;
begin
end;
procedure TProjectDefineTemplates.CompilerFlagsChanged; procedure TProjectDefineTemplates.CompilerFlagsChanged;
begin begin
if FUpdateLock>0 then begin if FUpdateLock>0 then begin
@ -3204,9 +3534,50 @@ begin
CodeToolBoss.DefineTree.ClearCache; CodeToolBoss.DefineTree.ClearCache;
end; end;
procedure TProjectDefineTemplates.ProjectIDChanged;
begin
if FUpdateLock>0 then begin
Include(FFlags,ptfIDChanged);
exit;
end;
Exclude(FFlags,ptfIDChanged);
UpdateMain;
UpdateDefinesForOutputDirectory;
UpdateDefinesForSourceDirectories;
UpdateDefinesForCustomDefines;
end;
procedure TProjectDefineTemplates.SourceDirectoriesChanged; procedure TProjectDefineTemplates.SourceDirectoriesChanged;
begin begin
if FUpdateLock>0 then begin
Include(FFlags,ptfSourceDirsChanged);
exit;
end;
Exclude(FFlags,ptfSourceDirsChanged);
UpdateDefinesForSourceDirectories;
CodeToolBoss.DefineTree.ClearCache;
end;
procedure TProjectDefineTemplates.OutputDirectoryChanged;
begin
if FUpdateLock>0 then begin
Include(FFlags,ptfOutputDirChanged);
exit;
end;
Exclude(FFlags,ptfOutputDirChanged);
UpdateDefinesForOutputDirectory;
CodeToolBoss.DefineTree.ClearCache;
end;
procedure TProjectDefineTemplates.CustomDefinesChanged;
begin
if FUpdateLock>0 then begin
Include(FFlags,ptfCustomDefinesChanged);
exit;
end;
Exclude(FFlags,ptfCustomDefinesChanged);
UpdateDefinesForCustomDefines;
CodeToolBoss.DefineTree.ClearCache;
end; end;
procedure TProjectDefineTemplates.UpdateGlobalValues; procedure TProjectDefineTemplates.UpdateGlobalValues;

View File

@ -874,11 +874,11 @@ msgstr "Schreibweise ignorieren"
#: lazarusidestrconsts:dlgcasesensitive #: lazarusidestrconsts:dlgcasesensitive
msgid "Case Sensitive" msgid "Case Sensitive"
msgstr "Klein/Groß beachten" msgstr "Klein/Gross beachten"
#: lazarusidestrconsts:lisfindfilecasesensitive #: lazarusidestrconsts:lisfindfilecasesensitive
msgid "Case sensitive" msgid "Case sensitive"
msgstr "Klein/Groß beachten" msgstr "Klein/Gross beachten"
#: lazarusidestrconsts:rslanguagecatalan #: lazarusidestrconsts:rslanguagecatalan
msgid "Catalan" msgid "Catalan"
@ -2078,7 +2078,7 @@ msgstr ""
#: lazarusidestrconsts:lisenclose #: lazarusidestrconsts:lisenclose
msgid "Enclose" msgid "Enclose"
msgstr "Einschließen" msgstr "Einschliessen"
#: lazarusidestrconsts:uemencloseselection #: lazarusidestrconsts:uemencloseselection
msgid "Enclose Selection" msgid "Enclose Selection"
@ -2238,7 +2238,7 @@ msgstr "Beispiel"
#: lazarusidestrconsts:lisexcludefilter #: lazarusidestrconsts:lisexcludefilter
msgid "Exclude Filter" msgid "Exclude Filter"
msgstr "Ausschließender Filter" msgstr "Ausschliessender Filter"
#: lazarusidestrconsts:srvk_execute #: lazarusidestrconsts:srvk_execute
msgid "Execute" msgid "Execute"

View File

@ -243,6 +243,7 @@ ResourceString
ifsVK_NUMPAD = 'Numpad %d'; ifsVK_NUMPAD = 'Numpad %d';
ifsVK_NUMLOCK = 'Numlock'; ifsVK_NUMLOCK = 'Numlock';
ifsVK_SCROLL = 'Scroll'; ifsVK_SCROLL = 'Scroll';
rsDocking = 'Docking';
implementation implementation

View File

@ -31,7 +31,8 @@ unit LDockTree;
interface interface
uses uses
Classes, SysUtils, LCLProc, LCLType, Forms, Controls, ExtCtrls; Classes, SysUtils, LCLProc, LCLType, Forms, Controls, ExtCtrls, Menus,
LCLStrConsts;
type type
TLazDockPages = class; TLazDockPages = class;
@ -154,7 +155,7 @@ type
out AControlBounds: TRect); override; out AControlBounds: TRect); override;
procedure DockControl(Control: TControl; InsertAt: TAlign; procedure DockControl(Control: TControl; InsertAt: TAlign;
DropCtl: TControl); DropCtl: TControl);
procedure UndockControl(Control: TControl); procedure UndockControl(Control: TControl; Float: boolean);
procedure InsertControl(Control: TControl; InsertAt: TAlign; procedure InsertControl(Control: TControl; InsertAt: TAlign;
DropCtl: TControl); override; DropCtl: TControl); override;
procedure LoadFromStream(Stream: TStream); override; procedure LoadFromStream(Stream: TStream); override;
@ -168,6 +169,66 @@ type
procedure ReplaceAnchoredControl(OldControl, NewControl: TControl); procedure ReplaceAnchoredControl(OldControl, NewControl: TControl);
property SplitterSize: integer read FSplitterSize write FSplitterSize default 5; property SplitterSize: integer read FSplitterSize write FSplitterSize default 5;
end; end;
TCustomLazControlDocker = class;
{ TCustomLazDockingManager }
TCustomLazDockingManager = class(TComponent)
private
FDockerCount: Integer;
FDockers: TFPList;
FManager: TAnchoredDockManager;
function GetDockers(Index: Integer): TCustomLazControlDocker;
protected
procedure Remove(Docker: TCustomLazControlDocker);
function Add(Docker: TCustomLazControlDocker): Integer;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
property Manager: TAnchoredDockManager read FManager;
property DockerCount: Integer read FDockerCount;
property Dockers[Index: Integer]: TCustomLazControlDocker read GetDockers;
end;
{ TLazDockingManager }
TLazDockingManager = class(TCustomLazDockingManager)
published
end;
{ TCustomLazControlDocker - a component to mark a form for the TLazDockingManager }
TCustomLazControlDocker = class(TComponent)
procedure PopupMenuItemClick(Sender: TObject);
private
FControl: TControl;
FExtendPopupMenu: boolean;
FManager: TCustomLazDockingManager;
FPopupMenuItem: TMenuItem;
procedure SetControl(const AValue: TControl);
procedure SetExtendPopupMenu(const AValue: boolean);
procedure SetManager(const AValue: TCustomLazDockingManager);
protected
procedure UpdatePopupMenu;
procedure Loaded; override;
public
constructor Create(TheOwner: TComponent); override;
property Control: TControl read FControl write SetControl;
property Manager: TCustomLazDockingManager read FManager write SetManager;
property ExtendPopupMenu: boolean read FExtendPopupMenu write SetExtendPopupMenu;
property PopupMenuItem: TMenuItem read FPopupMenuItem;
end;
{ TLazControlDocker }
TLazControlDocker = class(TCustomLazControlDocker)
published
property Control;
property Manager;
property ExtendPopupMenu;
end;
const const
DockAlignOrientations: array[TAlign] of TDockOrientation = ( DockAlignOrientations: array[TAlign] of TDockOrientation = (
@ -827,14 +888,14 @@ end;
procedure TAnchoredDockManager.DeletePages(Pages: TLazDockPages); procedure TAnchoredDockManager.DeletePages(Pages: TLazDockPages);
begin begin
if Pages.Parent<>nil then if Pages.Parent<>nil then
UndockControl(Pages); UndockControl(Pages,false);
Pages.Free; Pages.Free;
end; end;
procedure TAnchoredDockManager.DeleteDockForm(ADockForm: TLazDockForm); procedure TAnchoredDockManager.DeleteDockForm(ADockForm: TLazDockForm);
begin begin
if ADockForm.Parent<>nil then if ADockForm.Parent<>nil then
UndockControl(ADockForm); UndockControl(ADockForm,false);
ADockForm.Free; ADockForm.Free;
end; end;
@ -1088,7 +1149,7 @@ end;
It removes TLazDockSplitter, TLazDockPage and TLazDockPages if they are no It removes TLazDockSplitter, TLazDockPage and TLazDockPages if they are no
longer needed. longer needed.
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
procedure TAnchoredDockManager.UndockControl(Control: TControl); procedure TAnchoredDockManager.UndockControl(Control: TControl; Float: boolean);
{ {
Examples: Examples:
@ -1166,6 +1227,11 @@ var
var var
OldParentControl: TWinControl; OldParentControl: TWinControl;
begin begin
if Float then begin
Control.ManualFloat(Control.BoundsRect);
end else begin
Control.Parent:=nil;
end;
if ParentControl<>nil then begin if ParentControl<>nil then begin
OldParentControl:=ParentControl; OldParentControl:=ParentControl;
ParentControl:=nil; ParentControl:=nil;
@ -1286,7 +1352,7 @@ end;
procedure TAnchoredDockManager.RemoveControl(Control: TControl); procedure TAnchoredDockManager.RemoveControl(Control: TControl);
begin begin
UndockControl(Control); UndockControl(Control,false);
end; end;
procedure TAnchoredDockManager.ResetBounds(Force: Boolean); procedure TAnchoredDockManager.ResetBounds(Force: Boolean);
@ -1353,5 +1419,114 @@ begin
Result:=Parent as TLazDockPages; Result:=Parent as TLazDockPages;
end; end;
{ TCustomLazControlDocker }
procedure TCustomLazControlDocker.SetManager(
const AValue: TCustomLazDockingManager);
begin
if FManager=AValue then exit;
if FManager<>nil then FManager.Remove(Self);
FManager:=AValue;
if FManager<>nil then FManager.Add(Self);
end;
procedure TCustomLazControlDocker.UpdatePopupMenu;
// creates or deletes the PopupMenuItem to the PopupMenu of Control
begin
if [csDestroying,csDesigning]*ComponentState<>[] then exit;
if csLoading in ComponentState then exit;
if ExtendPopupMenu and (Control.PopupMenu<>nil) then begin
if (PopupMenuItem<>nil) and (PopupMenuItem.Parent<>Control.PopupMenu.Items)
then begin
// PopupMenuItem is in the old PopupMenu -> delete it
FreeAndNil(FPopupMenuItem);
end;
if (PopupMenuItem=nil) then begin
// create a new PopupMenuItem
FPopupMenuItem:=TMenuItem.Create(Self);
PopupMenuItem.Caption:=rsDocking;
PopupMenuItem.OnClick:=@PopupMenuItemClick;
end;
if PopupMenuItem.Parent=nil then begin
// add PopupMenuItem to Control.PopupMenu
Control.PopupMenu.Items.Add(PopupMenuItem);
end;
end else begin
// delete PopupMenuItem
FreeAndNil(FPopupMenuItem);
end;
end;
procedure TCustomLazControlDocker.Loaded;
begin
inherited Loaded;
UpdatePopupMenu;
end;
constructor TCustomLazControlDocker.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
if (not (csLoading in ComponentState))
and (TheOwner is TControl) then
// use as default
Control:=TControl(TheOwner);
ExtendPopupMenu:=true;
end;
procedure TCustomLazControlDocker.PopupMenuItemClick(Sender: TObject);
begin
end;
procedure TCustomLazControlDocker.SetControl(const AValue: TControl);
begin
if FControl=AValue then exit;
FControl:=AValue;
end;
procedure TCustomLazControlDocker.SetExtendPopupMenu(const AValue: boolean);
begin
if FExtendPopupMenu=AValue then exit;
FExtendPopupMenu:=AValue;
UpdatePopupMenu;
end;
{ TCustomLazDockingManager }
procedure TCustomLazDockingManager.Remove(Docker: TCustomLazControlDocker);
begin
FDockers.Remove(Docker);
end;
function TCustomLazDockingManager.Add(Docker: TCustomLazControlDocker): Integer;
begin
Result:=FDockers.Add(Docker);
end;
function TCustomLazDockingManager.GetDockers(Index: Integer
): TCustomLazControlDocker;
begin
Result:=TCustomLazControlDocker(FDockers[Index]);
end;
constructor TCustomLazDockingManager.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
FDockers:=TFPList.Create;
FManager:=TAnchoredDockManager.Create;
end;
destructor TCustomLazDockingManager.Destroy;
var
i: Integer;
begin
for i:=FDockers.Count-1 downto 0 do
Dockers[i].Manager:=nil;
FreeAndNil(FDockers);
FreeAndNil(FManager);
inherited Destroy;
end;
end. end.

View File

@ -3531,11 +3531,11 @@ begin
// update the package block define template (the container for all other // update the package block define template (the container for all other
// define templates of the package) // define templates of the package)
if FMain=nil then begin if FMain=nil then begin
FMain:=CreatePackageTemplateWithID(LazPackage.IDAsString); FMain:=CreatePackageTemplateWithID(LazPackage.IDAsWord);
FMain.SetDefineOwner(LazPackage,false); FMain.SetDefineOwner(LazPackage,false);
FMain.SetFlags([dtfAutoGenerated],[],false); FMain.SetFlags([dtfAutoGenerated],[],false);
end else end else
FMain.Name:=LazPackage.IDAsString; FMain.Name:=LazPackage.IDAsWord;
// ClearCache is here unnessary, because it is only a block // ClearCache is here unnessary, because it is only a block
end; end;