diff --git a/components/projectgroups/languages/projectgroupstrconst.de.po b/components/projectgroups/languages/projectgroupstrconst.de.po index 2d09dee7b0..71c1e2dc4a 100644 --- a/components/projectgroups/languages/projectgroupstrconst.de.po +++ b/components/projectgroups/languages/projectgroupstrconst.de.po @@ -280,6 +280,10 @@ msgstr "Projektgruppe speichern" msgid "Read error" msgstr "Lesefehler" +#: projectgroupstrconst.lisredo +msgid "Redo" +msgstr "" + #: projectgroupstrconst.lisremovetarget msgctxt "projectgroupstrconst.lisremovetarget" msgid "Remove target" @@ -477,6 +481,10 @@ msgstr "Kann Datei \"%s\" nicht laden" msgid "Unable to write project group file \"%s\"%s%s" msgstr "Kann Projektgruppen-Datei \"%s\"%s%s nicht schreiben" +#: projectgroupstrconst.lisundo +msgid "Undo" +msgstr "" + #: projectgroupstrconst.liswriteerror msgid "Write error" msgstr "Schreibfehler" diff --git a/components/projectgroups/languages/projectgroupstrconst.fr.po b/components/projectgroups/languages/projectgroupstrconst.fr.po index 0dae706e25..af8154c038 100644 --- a/components/projectgroups/languages/projectgroupstrconst.fr.po +++ b/components/projectgroups/languages/projectgroupstrconst.fr.po @@ -272,6 +272,10 @@ msgstr "Enregistrer le groupe de projets" msgid "Read error" msgstr "Erreur de lecture" +#: projectgroupstrconst.lisredo +msgid "Redo" +msgstr "" + #: projectgroupstrconst.lisremovetarget msgctxt "projectgroupstrconst.lisremovetarget" msgid "Remove target" @@ -469,6 +473,10 @@ msgstr "Impossible de charger le fichier \"%s\"" msgid "Unable to write project group file \"%s\"%s%s" msgstr "Impossible d'écrire le fichier du groupe de projets \"%s\"%s%s" +#: projectgroupstrconst.lisundo +msgid "Undo" +msgstr "" + #: projectgroupstrconst.liswriteerror msgid "Write error" msgstr "Erreur d'écriture" diff --git a/components/projectgroups/languages/projectgroupstrconst.hu.po b/components/projectgroups/languages/projectgroupstrconst.hu.po index 36501815b1..a1070484f3 100644 --- a/components/projectgroups/languages/projectgroupstrconst.hu.po +++ b/components/projectgroups/languages/projectgroupstrconst.hu.po @@ -279,6 +279,10 @@ msgstr "Projektcsoport mentése" msgid "Read error" msgstr "Olvasási hiba" +#: projectgroupstrconst.lisredo +msgid "Redo" +msgstr "" + #: projectgroupstrconst.lisremovetarget msgctxt "projectgroupstrconst.lisremovetarget" msgid "Remove target" @@ -476,6 +480,10 @@ msgstr "A(z) \"%s\" fájl betöltése nem lehetséges" msgid "Unable to write project group file \"%s\"%s%s" msgstr "Nem lehet írni a projektcsoport fájlját: \"%s\"%s%s" +#: projectgroupstrconst.lisundo +msgid "Undo" +msgstr "" + #: projectgroupstrconst.liswriteerror msgid "Write error" msgstr "Írási hiba" diff --git a/components/projectgroups/languages/projectgroupstrconst.it.po b/components/projectgroups/languages/projectgroupstrconst.it.po index 4fd50c3b0b..1c18b85cc8 100644 --- a/components/projectgroups/languages/projectgroupstrconst.it.po +++ b/components/projectgroups/languages/projectgroupstrconst.it.po @@ -275,6 +275,10 @@ msgstr "Salva gruppo di progetti" msgid "Read error" msgstr "Errore di lettura" +#: projectgroupstrconst.lisredo +msgid "Redo" +msgstr "" + #: projectgroupstrconst.lisremovetarget msgctxt "projectgroupstrconst.lisremovetarget" msgid "Remove target" @@ -476,6 +480,10 @@ msgstr "Non posso caricare il file \"%s\"" msgid "Unable to write project group file \"%s\"%s%s" msgstr "Non posso scrivere il file gruppo di progetti \"%s\"%s%s" +#: projectgroupstrconst.lisundo +msgid "Undo" +msgstr "" + #: projectgroupstrconst.liswriteerror msgid "Write error" msgstr "Errore di scrittura" diff --git a/components/projectgroups/languages/projectgroupstrconst.lt.po b/components/projectgroups/languages/projectgroupstrconst.lt.po index 6274ae9323..5bcb1b883a 100644 --- a/components/projectgroups/languages/projectgroupstrconst.lt.po +++ b/components/projectgroups/languages/projectgroupstrconst.lt.po @@ -280,6 +280,10 @@ msgstr "Įrašyti projekto grupę" msgid "Read error" msgstr "Klaida skaitant" +#: projectgroupstrconst.lisredo +msgid "Redo" +msgstr "" + #: projectgroupstrconst.lisremovetarget msgctxt "projectgroupstrconst.lisremovetarget" msgid "Remove target" @@ -477,6 +481,10 @@ msgstr "Nepavyko įkelti failo „%s“" msgid "Unable to write project group file \"%s\"%s%s" msgstr "Nepavyko rašyti į projekto grupės failą „%s“%s%s" +#: projectgroupstrconst.lisundo +msgid "Undo" +msgstr "" + #: projectgroupstrconst.liswriteerror msgid "Write error" msgstr "Klaida rašant" diff --git a/components/projectgroups/languages/projectgroupstrconst.pot b/components/projectgroups/languages/projectgroupstrconst.pot index 8f2605b52b..1e6824fc39 100644 --- a/components/projectgroups/languages/projectgroupstrconst.pot +++ b/components/projectgroups/languages/projectgroupstrconst.pot @@ -257,6 +257,10 @@ msgstr "" msgid "Read error" msgstr "" +#: projectgroupstrconst.lisredo +msgid "Redo" +msgstr "" + #: projectgroupstrconst.lisremovetarget msgctxt "projectgroupstrconst.lisremovetarget" msgid "Remove target" @@ -454,6 +458,10 @@ msgstr "" msgid "Unable to write project group file \"%s\"%s%s" msgstr "" +#: projectgroupstrconst.lisundo +msgid "Undo" +msgstr "" + #: projectgroupstrconst.liswriteerror msgid "Write error" msgstr "" diff --git a/components/projectgroups/languages/projectgroupstrconst.pt_BR.po b/components/projectgroups/languages/projectgroupstrconst.pt_BR.po index 1de62182d6..7723ab0f39 100644 --- a/components/projectgroups/languages/projectgroupstrconst.pt_BR.po +++ b/components/projectgroups/languages/projectgroupstrconst.pt_BR.po @@ -272,6 +272,10 @@ msgstr "Salvar grupo de projeto" msgid "Read error" msgstr "Erro leitura" +#: projectgroupstrconst.lisredo +msgid "Redo" +msgstr "" + #: projectgroupstrconst.lisremovetarget msgctxt "projectgroupstrconst.lisremovetarget" msgid "Remove target" @@ -469,6 +473,10 @@ msgstr "Incapaz de carregar arquivo \"%s\"" msgid "Unable to write project group file \"%s\"%s%s" msgstr "Incapaz de gravar arquivo grupo de projeto \"%s\"%s%s" +#: projectgroupstrconst.lisundo +msgid "Undo" +msgstr "" + #: projectgroupstrconst.liswriteerror msgid "Write error" msgstr "Erro gravação" diff --git a/components/projectgroups/languages/projectgroupstrconst.ru.po b/components/projectgroups/languages/projectgroupstrconst.ru.po index 294e84df16..e3c22f9c1d 100644 --- a/components/projectgroups/languages/projectgroupstrconst.ru.po +++ b/components/projectgroups/languages/projectgroupstrconst.ru.po @@ -272,6 +272,10 @@ msgstr "Сохранить группу проектов" msgid "Read error" msgstr "Ошибка чтения" +#: projectgroupstrconst.lisredo +msgid "Redo" +msgstr "" + #: projectgroupstrconst.lisremovetarget msgctxt "projectgroupstrconst.lisremovetarget" msgid "Remove target" @@ -469,6 +473,10 @@ msgstr "Невозможно загрузить файл \"%s\"" msgid "Unable to write project group file \"%s\"%s%s" msgstr "Невозможно записать файл группы проектов \"%s\"%s%s" +#: projectgroupstrconst.lisundo +msgid "Undo" +msgstr "" + #: projectgroupstrconst.liswriteerror msgid "Write error" msgstr "Ошибка записи" diff --git a/components/projectgroups/languages/projectgroupstrconst.uk.po b/components/projectgroups/languages/projectgroupstrconst.uk.po index af8538bfcc..230c678db5 100644 --- a/components/projectgroups/languages/projectgroupstrconst.uk.po +++ b/components/projectgroups/languages/projectgroupstrconst.uk.po @@ -273,6 +273,10 @@ msgstr "Зберегти групу проектів" msgid "Read error" msgstr "Помилка читання" +#: projectgroupstrconst.lisredo +msgid "Redo" +msgstr "" + #: projectgroupstrconst.lisremovetarget msgctxt "projectgroupstrconst.lisremovetarget" msgid "Remove target" @@ -470,6 +474,10 @@ msgstr "Неможливо завантажити файл \"%s\"" msgid "Unable to write project group file \"%s\"%s%s" msgstr "Неможливо записати файл групи проектів \"%s\"%s%s" +#: projectgroupstrconst.lisundo +msgid "Undo" +msgstr "" + #: projectgroupstrconst.liswriteerror msgid "Write error" msgstr "Помилка запису" diff --git a/components/projectgroups/languages/projectgroupstrconst.zh_CN.po b/components/projectgroups/languages/projectgroupstrconst.zh_CN.po index cefc66f372..77a8bb2f24 100644 --- a/components/projectgroups/languages/projectgroupstrconst.zh_CN.po +++ b/components/projectgroups/languages/projectgroupstrconst.zh_CN.po @@ -280,6 +280,10 @@ msgstr "保存工程组" msgid "Read error" msgstr "读取错误" +#: projectgroupstrconst.lisredo +msgid "Redo" +msgstr "" + #: projectgroupstrconst.lisremovetarget msgctxt "projectgroupstrconst.lisremovetarget" msgid "Remove target" @@ -477,6 +481,10 @@ msgstr "不能加载文件\"%s\"" msgid "Unable to write project group file \"%s\"%s%s" msgstr "不能写入工程组文件\"%s\"%s%s" +#: projectgroupstrconst.lisundo +msgid "Undo" +msgstr "" + #: projectgroupstrconst.liswriteerror msgid "Write error" msgstr "写入错误" diff --git a/components/projectgroups/projectgroup.pp b/components/projectgroups/projectgroup.pp index 6bccece642..068b965272 100644 --- a/components/projectgroups/projectgroup.pp +++ b/components/projectgroups/projectgroup.pp @@ -43,6 +43,7 @@ uses // IdeIntf PackageIntf, ProjectIntf, MenuIntf, LazIDEIntf, IDEDialogs, CompOptsIntf, BaseIDEIntf, IDECommands, IDEExternToolIntf, MacroIntf, IDEMsgIntf, + ToolBarIntf, // ProjectGroups ProjectGroupIntf, ProjectGroupStrConst; @@ -80,6 +81,7 @@ type function PerformAction(AAction: TPGTargetAction): TPGActionResult; override; function PerformNextTarget(AAction: TPGTargetAction): TPGActionResult; procedure ActiveChanged(Sender: TPGCompileTarget); override; + procedure SetParent(NewParent: TPGCompileTarget); virtual; public destructor Destroy; override; procedure LoadTarget(Recursively: boolean); virtual; @@ -113,37 +115,35 @@ type FActiveTarget: TPGCompileTarget; FOnFileNameChange: TNotifyEvent; FOnTargetActiveChanged: TTargetEvent; - FOnTargetAdded: TTargetEvent; + FOnTargetInserted: TTargetEvent; FOnTargetDeleted: TTargetEvent; - FOnTargetReadded: TTargetEvent; FOnTargetsExchanged: TTargetExchangeEvent; FTargets: TFPObjectList; - FRemovedTargets: TFPObjectList; protected procedure SetFileName(AValue: String); override; function GetTarget(Index: Integer): TPGCompileTarget; override; function GetTargetCount: Integer; override; - function GetRemovedTargetCount: Integer; override; - function GetRemovedTarget(Index: Integer): TPGCompileTarget; override; function GetActiveTarget: TPGCompileTarget; override; procedure SetActiveTarget(AValue: TPGCompileTarget); override; + procedure DoTargetDeleted(Sender: TObject; Target: TPGCompileTarget); + procedure DoTargetInserted(Sender: TObject; Target: TPGCompileTarget); public constructor Create(aCompileTarget: TIDECompileTarget); destructor Destroy; override; procedure Clear; + procedure CheckInvalidCycle(const aFilename: string); function IndexOfTarget(const Target: TPGCompileTarget): Integer; override; - function IndexOfRemovedTarget(const Target: TPGCompileTarget): Integer; override; function AddTarget(Const AFileName: String): TPGCompileTarget; override; - procedure ReAddTarget(Target: TPGCompileTarget); override; + function InsertTarget(const Target: TPGCompileTarget; Index: Integer + ): Integer; override; procedure RemoveTarget(Index: Integer); override; - procedure ExchangeTargets(ASource, ATarget: Integer); override; + procedure ExchangeTargets(OldIndex, NewIndex: Integer); override; procedure ActiveTargetChanged(T: TPGCompileTarget); function LoadFromFile(Options: TProjectGroupLoadOptions): Boolean; function SaveToFile: Boolean; property OnFileNameChange: TNotifyEvent Read FOnFileNameChange Write FOnFileNameChange; - property OnTargetAdded: TTargetEvent Read FOnTargetAdded Write FOnTargetAdded; + property OnTargetInserted: TTargetEvent Read FOnTargetInserted Write FOnTargetInserted; property OnTargetDeleted: TTargetEvent Read FOnTargetDeleted Write FOnTargetDeleted; - property OnTargetReadded: TTargetEvent Read FOnTargetReadded Write FOnTargetReadded; property OnTargetActiveChanged: TTargetEvent Read FOnTargetActiveChanged Write FOnTargetActiveChanged; property OnTargetsExchanged: TTargetExchangeEvent Read FOnTargetsExchanged Write FOnTargetsExchanged; end; @@ -177,10 +177,27 @@ type property ShowTargetPaths: boolean read FShowTargetPaths write SetShowTargetPaths; end; + { TPGUndoItem } + + TPGUndoItem = class + end; + + { TPGUndoDelete } + + TPGUndoDelete = class(TPGUndoItem) + public + Group: TIDEProjectGroup; + Target: TIDECompileTarget; // owned by this undo item + InFrontFile, BehindFile: string; + destructor Destroy; override; + end; + { TIDEProjectGroupManager } TIDEProjectGroupManager = Class(TProjectGroupManager) private + FUndoList: TObjectList; // list of TPGUndoItem + FRedoList: TObjectList; // list of TPGUndoItem FOptions: TIDEProjectGroupOptions; procedure AddToRecentGroups(aFilename: string); function GetNewFileName: Boolean; @@ -189,6 +206,8 @@ type protected function GetCurrentProjectGroup: TProjectGroup; override; function ShowProjectGroupEditor: Boolean; + procedure TargetDeleting(Group: TIDEProjectGroup; Index: integer); + function GroupExists(Group: TIDEProjectGroup): boolean; public constructor Create; destructor Destroy; override; @@ -201,6 +220,10 @@ type procedure DoSaveClick(Sender: TObject); procedure DoSaveAsClick(Sender: TObject); // Public interface + function CanUndo: boolean; override; + function CanRedo: boolean; override; + procedure Undo; override; + procedure Redo; override; procedure LoadProjectGroup(AFileName: string; AOptions: TProjectGroupLoadOptions); override; procedure SaveProjectGroup; override; public @@ -217,6 +240,7 @@ var IDEProjectGroupManager: TIDEProjectGroupManager; + ViewProjGrpShortCutX: TIDEShortCut; ProjectGroupEditorMenuRoot: TIDEMenuSection = nil; PGEditMenuSectionFiles, // e.g. sort files, clean up files PGEditMenuSectionAddRemove, // e.g. add unit, add dependency @@ -231,6 +255,8 @@ var PGCmdCategory: TIDECommandCategory; // IDE main bar menu items + ViewProjectGroupsCommand: TIDECommand; + ViewProjectGroupsButtonCommand: TIDEButtonCommand; CmdOpenProjectGroup: TIDECommand; MnuCmdOpenProjectGroup: TIDEMenuCommand; CmdSaveProjectGroup: TIDECommand; @@ -255,6 +281,8 @@ var MnuCmdTargetProperties, MnuCmdTargetUninstall, MnuCmdTargetCopyFilename: TIDEMenuCommand; + MnuCmdProjGrpUndo: TIDEMenuCommand; + MnuCmdProjGrpRedo: TIDEMenuCommand; function LoadXML(aFilename: string; Quiet: boolean): TXMLConfig; function CreateXML(aFilename: string; Quiet: boolean): TXMLConfig; @@ -322,6 +350,14 @@ begin Result:=FindDefaultExecutablePath('lazbuild'+ExeExt); end; +{ TPGUndoDelete } + +destructor TPGUndoDelete.Destroy; +begin + FreeAndNil(Target); + inherited Destroy; +end; + { TIDEProjectGroupOptions } function TIDEProjectGroupOptions.GetModified: boolean; @@ -465,13 +501,55 @@ begin end; end; +procedure TIDEProjectGroupManager.TargetDeleting(Group: TIDEProjectGroup; + Index: integer); +var + UndoDelete: TPGUndoDelete; + Target: TIDECompileTarget; +begin + UndoDelete:=TPGUndoDelete.Create; + FUndoList.Add(UndoDelete); + Target:=Group.Targets[Index] as TIDECompileTarget; + UndoDelete.Target:=Target; + UndoDelete.Group:=Group; + if Index>0 then + UndoDelete.InFrontFile:=Group.Targets[Index-1].Filename; + if Index+10; +end; + +function TIDEProjectGroupManager.CanRedo: boolean; +begin + Result:=FRedoList.Count>0; +end; + +procedure TIDEProjectGroupManager.Undo; +var + Item: TPGUndoItem; + UndoDelete: TPGUndoDelete; + Target: TIDECompileTarget; + Group: TIDEProjectGroup; + i: Integer; +begin + if not CanUndo then exit; + Item:=TPGUndoItem(FUndoList[FUndoList.Count-1]); + FUndoList.OwnsObjects:=false; + FUndoList.Delete(FUndoList.Count-1); + FUndoList.OwnsObjects:=true; + try + if Item is TPGUndoDelete then + begin + UndoDelete:=TPGUndoDelete(Item); + Target:=UndoDelete.Target; + UndoDelete.Target:=nil; + Group:=UndoDelete.Group; + if GroupExists(Group) then + begin + if Group.IndexOfTarget(Target.Filename)>=0 then + exit; + i:=Group.IndexOfTarget(UndoDelete.InFrontFile); + if i>=0 then + inc(i) + else begin + i:=Group.IndexOfTarget(UndoDelete.BehindFile); + if i<0 then + i:=Group.TargetCount; + end; + Group.InsertTarget(Target,i); + end; + end; + finally + Item.Free; + end; +end; + +procedure TIDEProjectGroupManager.Redo; +begin + +end; + procedure TIDEProjectGroupManager.LoadProjectGroup(AFileName: string; AOptions: TProjectGroupLoadOptions); begin @@ -657,16 +790,6 @@ begin Result:=FTargets.Count; end; -function TIDEProjectGroup.GetRemovedTargetCount: Integer; -begin - Result:=FRemovedTargets.Count; -end; - -function TIDEProjectGroup.GetRemovedTarget(Index: Integer): TPGCompileTarget; -begin - Result:=TPGCompileTarget(FRemovedTargets[Index]); -end; - function TIDEProjectGroup.GetActiveTarget: TPGCompileTarget; begin Result:=FActiveTarget; @@ -681,6 +804,24 @@ begin AValue.Activate; end; +procedure TIDEProjectGroup.DoTargetDeleted(Sender: TObject; + Target: TPGCompileTarget); +begin + if Assigned(OnTargetDeleted) then + OnTargetDeleted(Sender,Target); + if Parent<>nil then + TIDEProjectGroup(Parent).DoTargetDeleted(Sender,Target); +end; + +procedure TIDEProjectGroup.DoTargetInserted(Sender: TObject; + Target: TPGCompileTarget); +begin + if Assigned(OnTargetInserted) then + OnTargetInserted(Sender,Target); + if Parent<>nil then + TIDEProjectGroup(Parent).DoTargetInserted(Sender,Target); +end; + constructor TIDEProjectGroup.Create(aCompileTarget: TIDECompileTarget); begin inherited Create; @@ -692,13 +833,11 @@ begin FParent:=FCompileTarget.Parent.ProjectGroup; end; FTargets:=TFPObjectList.Create(True); - FRemovedTargets:=TFPObjectList.Create(True); end; destructor TIDEProjectGroup.Destroy; begin FreeAndNil(FTargets); - FreeAndNil(FRemovedTargets); FreeAndNil(FCompileTarget); inherited Destroy; end; @@ -706,7 +845,18 @@ end; procedure TIDEProjectGroup.Clear; begin FTargets.Clear; - FRemovedTargets.Clear; +end; + +procedure TIDEProjectGroup.CheckInvalidCycle(const aFilename: string); +var + Group: TProjectGroup; +begin + Group:=Self; + while Group<>nil do begin + if CompareFilenames(AFileName,Group.FileName)=0 then + raise Exception.Create(lisInvalidCycleAProjectGroupCannotHaveItselfAsTarget); + Group:=Group.Parent; + end; end; function TIDEProjectGroup.IndexOfTarget(const Target: TPGCompileTarget): Integer; @@ -714,74 +864,62 @@ begin Result:=FTargets.IndexOf(Target); end; -function TIDEProjectGroup.IndexOfRemovedTarget(const Target: TPGCompileTarget - ): Integer; -begin - Result:=FRemovedTargets.IndexOf(Target); -end; - function TIDEProjectGroup.AddTarget(const AFileName: String): TPGCompileTarget; -var - Root: TIDEProjectGroup; begin Result:=Nil; if not FilenameIsAbsolute(AFileName) then - RaiseGDBException(AFileName); - if CompareFilenames(AFileName,FileName)=0 then - raise Exception.Create(lisInvalidCycleAProjectGroupCannotHaveItselfAsTarget); + RaiseGDBException('TIDEProjectGroup.AddTarget [20190629165305] '+AFileName); + CheckInvalidCycle(AFileName); Result:=TIDECompileTarget.Create(CompileTarget); Result.FileName:=AFileName; FTargets.Add(Result); IncreaseChangeStamp; - Root:=TIDEProjectGroup(GetRootGroup); - if Assigned(Root.OnTargetAdded) then - Root.OnTargetAdded(Self,Result); + DoTargetInserted(Self,Result); end; -procedure TIDEProjectGroup.ReAddTarget(Target: TPGCompileTarget); -var - Root: TIDEProjectGroup; +function TIDEProjectGroup.InsertTarget(const Target: TPGCompileTarget; + Index: Integer): Integer; begin - if (Target=nil) or (not Target.Removed) then - raise Exception.Create(''); - FRemovedTargets.OwnsObjects:=false; - FRemovedTargets.Remove(Target); - FRemovedTargets.OwnsObjects:=true; - FTargets.Add(Target); - Target.Removed:=false; - Modified:=true; - Root:=TIDEProjectGroup(GetRootGroup); - if Assigned(Root.OnTargetReadded) then - Root.OnTargetReadded(Self,Target); + if Target=nil then + RaiseGDBException('TIDEProjectGroup.InsertTarget [20190629165001]'); + if Target.Parent<>nil then + RaiseGDBException(Target.Filename); + CheckInvalidCycle(Target.FileName); + if Index<0 then + RaiseGDBException('TIDEProjectGroup.InsertTarget [20190629165007]'); + if Index>TargetCount then + RaiseGDBException('TIDEProjectGroup.InsertTarget [20190629165009]'); + FTargets.Insert(Index,Target); + TIDECompileTarget(Target).SetParent(CompileTarget); + IncreaseChangeStamp; + DoTargetInserted(Self,Target); + Result:=FTargets.IndexOf(Target); end; procedure TIDEProjectGroup.RemoveTarget(Index: Integer); var Target: TPGCompileTarget; - Root: TIDEProjectGroup; begin Target:=Targets[Index]; + IDEProjectGroupManager.TargetDeleting(Self,Index); Target.DeActivate; FTargets.OwnsObjects:=false; FTargets.Delete(Index); FTargets.OwnsObjects:=true; - FRemovedTargets.Add(Target); - Target.Removed:=true; + TIDECompileTarget(Target).SetParent(nil); Modified:=true; - Root:=TIDEProjectGroup(GetRootGroup); - if Assigned(Root.OnTargetDeleted) then - Root.OnTargetDeleted(Self,Target); + DoTargetDeleted(Self,Target); end; -procedure TIDEProjectGroup.ExchangeTargets(ASource, ATarget: Integer); +procedure TIDEProjectGroup.ExchangeTargets(OldIndex, NewIndex: Integer); var Root: TIDEProjectGroup; begin - if ASource=ATarget then exit; - FTargets.Exchange(ASource,ATarget); + if OldIndex=NewIndex then exit; + FTargets.Exchange(OldIndex,NewIndex); Root:=TIDEProjectGroup(GetRootGroup); if Assigned(Root.OnTargetsExchanged) then - Root.OnTargetsExchanged(Self,GetTarget(ASource),GetTarget(ATarget)); + Root.OnTargetsExchanged(Self,GetTarget(OldIndex),GetTarget(NewIndex)); IncreaseChangeStamp; end; @@ -845,11 +983,13 @@ begin end else if (pgloRemoveInvalid in Options) then begin - Target:=TIDECompileTarget(AddTarget(TargetFileName)); - Target.Removed:=True; + // remove = do not load it end else if (pgloSkipInvalid in options) then - // Do nothing + begin + Target:=TIDECompileTarget(AddTarget(TargetFileName)); + Target.Missing:=True; + end else if (pgloErrorInvalid in options) then exit else @@ -858,18 +998,14 @@ begin [mrYes,lisRemoveTarget, mrNo,lisAbortLoadingProjectGroup, mrYesToAll,lisSkipAllTargets],'') of - mrYes : - begin - Target:=TIDECompileTarget(AddTarget(TargetFileName)); - Target.Removed:=True; - end; + mrYes: ; mrNo: exit; mrYesToAll: begin Target:=TIDECompileTarget(AddTarget(TargetFileName)); - Target.Removed:=True; - Include(Options,pgloRemoveInvalid); + Target.Missing:=True; + Include(Options,pgloSkipInvalid); end; else exit; @@ -911,7 +1047,6 @@ begin For i:=0 to TargetCount-1 do begin aTarget:=TIDECompileTarget(GetTarget(i)); - if aTarget.Removed then continue; APath:=Format(ARoot+'/Targets/Target%d/',[ACount]); RelativeFileName:=ExtractRelativepath(TargetPath,aTarget.FileName); StringReplace(RelativeFileName,'\','/',[rfReplaceAll]); // normalize, so that files look the same x-platform, for less svn changes @@ -936,7 +1071,6 @@ begin For i:=0 to TargetCount-1 do begin aTarget:=TIDECompileTarget(GetTarget(i)); - if aTarget.Removed then continue; if aTarget.TargetType=ttProjectGroup then begin SubPG:=TIDEProjectGroup(aTarget.ProjectGroup); @@ -966,7 +1100,7 @@ begin case TargetType of ttProject: LoadProject_GroupSettings(XMLConfig,aPath); end; - if not Removed then + if not Missing then if XMLConfig.GetValue(APath+'Active',False) then Activate; end; @@ -977,7 +1111,7 @@ begin case TargetType of ttProject: SaveProject_GroupSettings(XMLConfig,aPath); end; - XMLConfig.SetDeleteValue(APath+'Active',Active and not Removed,False); + XMLConfig.SetDeleteValue(APath+'Active',Active and not Missing,False); end; procedure TIDECompileTarget.UnLoadTarget; @@ -1642,5 +1776,10 @@ begin (GetRootProjectGroup as TIDEProjectGroup).ActiveTargetChanged(Sender); end; +procedure TIDECompileTarget.SetParent(NewParent: TPGCompileTarget); +begin + FParent:=NewParent; +end; + end. diff --git a/components/projectgroups/projectgroupeditor.lfm b/components/projectgroups/projectgroupeditor.lfm index 772467ad42..e6c4864202 100644 --- a/components/projectgroups/projectgroupeditor.lfm +++ b/components/projectgroups/projectgroupeditor.lfm @@ -56,35 +56,34 @@ object ProjectGroupEditorForm: TProjectGroupEditorForm Left = 326 Height = 46 Top = 2 - Width = 10 Caption = 'ToolButton1' Style = tbsSeparator end object TBTargetUp: TToolButton - Left = 390 + Left = 388 Top = 2 Action = ATargetEarlier end object TBTargetLater: TToolButton - Left = 434 + Left = 432 Top = 2 Action = ATargetLater end object TBMore: TToolButton - Left = 517 + Left = 515 Top = 2 Caption = 'More...' DropdownMenu = PopupMenuMore Style = tbsDropDown end object TBActivate: TToolButton - Left = 336 + Left = 334 Top = 2 Action = ATargetActivate Visible = False end object TBReload: TToolButton - Left = 471 + Left = 469 Top = 2 Action = AProjectGroupReload end @@ -970,6 +969,12 @@ object ProjectGroupEditorForm: TProjectGroupEditorForm object PMISaveAs: TMenuItem Action = AProjectGroupSaveAs end + object PMIUndo: TMenuItem + Action = AProjectGroupUndo + end + object PMIRedo: TMenuItem + Action = AProjectGroupRedo + end end object ActionListMain: TActionList Images = ImageListMain @@ -1092,6 +1097,18 @@ object ProjectGroupEditorForm: TProjectGroupEditorForm ImageIndex = 25 OnExecute = AProjectGroupReloadExecute end + object AProjectGroupUndo: TAction + Category = 'ProjectGroupActions' + Caption = 'Undo' + OnExecute = AProjectGroupUndoExecute + OnUpdate = AProjectGroupUndoUpdate + end + object AProjectGroupRedo: TAction + Category = 'ProjectGroupActions' + Caption = 'Redo' + OnExecute = AProjectGroupRedoExecute + OnUpdate = AProjectGroupRedoUpdate + end end object PopupMenuTree: TPopupMenu Images = ImageListMain diff --git a/components/projectgroups/projectgroupeditor.pas b/components/projectgroups/projectgroupeditor.pas index 8cbf50e187..e33d35623e 100644 --- a/components/projectgroups/projectgroupeditor.pas +++ b/components/projectgroups/projectgroupeditor.pas @@ -28,10 +28,8 @@ type TNodeType = ( ntUnknown, ntProjectGroup, - ntTargets, - ntRemovedTargets, ntTarget, - ntRemovedTarget, + ntMissingTarget, ntBuildModes, ntBuildMode, ntFiles, @@ -45,11 +43,12 @@ type Target, ParentTarget: TPGCompileTarget; Value: string; // ntFile = Filename, ntDependency = PkgName, ntBuildMode = BuildMode name end; - TTargetNodes = Array[Boolean] of TTreeNode; { TProjectGroupEditorForm } TProjectGroupEditorForm = class(TForm) + AProjectGroupRedo: TAction; + AProjectGroupUndo: TAction; AProjectGroupReload: TAction; ATargetCompileFromHere: TAction; ATargetCopyFilename: TAction; @@ -70,6 +69,8 @@ type AProjectGroupSave: TAction; ActionListMain: TActionList; ImageListMain: TImageList; + PMIRedo: TMenuItem; + PMIUndo: TMenuItem; PMICompileFromHere: TMenuItem; PMIRunMenuItem: TMenuItem; PMICopyFilenameMenuItem: TMenuItem; @@ -103,11 +104,15 @@ type procedure AProjectGroupAddExistingExecute(Sender: TObject); procedure AProjectGroupDeleteExecute(Sender: TObject); procedure AProjectGroupDeleteUpdate(Sender: TObject); + procedure AProjectGroupRedoExecute(Sender: TObject); + procedure AProjectGroupRedoUpdate(Sender: TObject); procedure AProjectGroupReloadExecute(Sender: TObject); procedure AProjectGroupSaveAsExecute(Sender: TObject); procedure AProjectGroupSaveAsUpdate(Sender: TObject); procedure AProjectGroupSaveExecute(Sender: TObject); procedure AProjectGroupSaveUpdate(Sender: TObject); + procedure AProjectGroupUndoExecute(Sender: TObject); + procedure AProjectGroupUndoUpdate(Sender: TObject); procedure ATargetActivateExecute(Sender: TObject); procedure ATargetActivateUpdate(Sender: TObject); procedure ATargetCompileCleanExecute(Sender: TObject); @@ -144,14 +149,12 @@ type FProjectGroup: TProjectGroup; FProjectGroupTVNode: TTreeNode; FActiveTarget: TPGCompileTarget; - FTargetNodes: TTargetNodes; // Project group callbacks procedure InitTVNode(Node: TTreeNode; Const ACaption: String; ANodeData: TNodeData); procedure OnProjectGroupDestroy(Sender: TObject); procedure OnProjectGroupFileNameChanged(Sender: TObject); - procedure OnTargetAdded(Sender: TObject; Target: TPGCompileTarget); - procedure OnTargetReadded(Sender: TObject; Target: TPGCompileTarget); + procedure OnTargetInserted(Sender: TObject; Target: TPGCompileTarget); procedure OnTargetDeleted(Sender: TObject; Target: TPGCompileTarget); procedure OnTargetActiveChanged(Sender: TObject; Target: TPGCompileTarget); procedure OnTargetExchanged(Sender: TObject; Target1, Target2: TPGCompileTarget); @@ -160,7 +163,7 @@ type procedure SetEventCallBacks(AProjectGroup: TProjectGroup); // Some helpers procedure SetProjectGroup(AValue: TProjectGroup); - procedure ShowDependencies(AParent: TTreeNode; T: TPGCompileTarget; Out PD: TTargetNodes); + function ShowDependencies(AParent: TTreeNode; T: TPGCompileTarget): TTreeNode; procedure ShowFileName; procedure Perform(ATargetAction: TPGTargetAction); function GetActiveTarget: TPGCompileTarget; @@ -180,7 +183,7 @@ type procedure FillPackageNode(TVNode: TTreeNode; T: TPGCompileTarget); procedure FillProjectNode(TVNode: TTreeNode; T: TPGCompileTarget); procedure FillTargetNode(TVNode: TTreeNode; T: TPGCompileTarget); - procedure FillProjectGroupNode(TVNode: TTreeNode; AProjectGroup: TProjectGroup; Out TargetNodes: TTargetNodes); + procedure FillProjectGroupNode(TVNode: TTreeNode; AProjectGroup: TProjectGroup); function GetNodeImageIndex(ANodeType: TNodeType; ANodeData: TPGCompileTarget ): Integer; function SelectedNodeData: TNodeData; function SelectedTarget: TPGCompileTarget; @@ -219,24 +222,18 @@ implementation var // Nodelist image indexes NIProjectGroup : integer = 0; - NITargets : integer = 1; - NIRemovedTargerts : integer = 2; NITargetProject : integer = 3; NITargetPackage : integer = 4; NITargetProjectGroup : integer = 5; - NIRemovedTargetProject : integer = 3; - NIRemovedTargetPackage : integer = 4; - NIRemovedTargetProjectGroup: integer = 5; + NIMissingTargetProject : integer = 3; + NIMissingTargetPackage : integer = 4; + NIMissingTargetProjectGroup: integer = 5; NIBuildModes : integer = 12; NIBuildMode : integer = 12; NIFiles : integer = 16; NIFile : integer = 17; - //NIRemovedFiles : integer = 18; - //NIRemovedFile : integer = 17; NIDependencies : integer = 1; NIDependency : integer = 1; - //NIRemovedDependencies : integer = 2; - //NIRemovedDependency : integer = 2; // Node state image index NSIActive : Integer = 20; // State index for active. @@ -309,9 +306,8 @@ begin PG:=AProjectGroup as TIDEProjectGroup; PG.RemoveAllHandlersOfObject(Self); PG.OnFileNameChange:=Nil; - PG.OnTargetAdded:=Nil; + PG.OnTargetInserted:=Nil; PG.OnTargetDeleted:=Nil; - PG.OnTargetReadded:=Nil; PG.OnTargetActiveChanged:=Nil; PG.OnTargetsExchanged:=Nil; end; @@ -323,9 +319,8 @@ begin PG:=AProjectGroup as TIDEProjectGroup; PG.AddHandlerOnDestroy(@OnProjectGroupDestroy); PG.OnFileNameChange:=@OnProjectGroupFileNameChanged; - PG.OnTargetAdded:=@OnTargetAdded; + PG.OnTargetInserted:=@OnTargetInserted; PG.OnTargetDeleted:=@OnTargetDeleted; - PG.OnTargetReadded:=@OnTargetReadded; PG.OnTargetActiveChanged:=@OnTargetActiveChanged; PG.OnTargetsExchanged:=@OnTargetExchanged; end; @@ -387,6 +382,16 @@ begin UpdateIDEMenuCommandFromAction(Sender,MnuCmdSaveProjectGroup); end; +procedure TProjectGroupEditorForm.AProjectGroupUndoExecute(Sender: TObject); +begin + IDEProjectGroupManager.Undo; +end; + +procedure TProjectGroupEditorForm.AProjectGroupUndoUpdate(Sender: TObject); +begin + (Sender as TAction).Enabled:=IDEProjectGroupManager.CanUndo; +end; + procedure TProjectGroupEditorForm.ATargetEarlierExecute(Sender: TObject); Var T: TNodeData; @@ -518,6 +523,8 @@ begin SetItem(MnuCmdTargetLater,@ATargetLaterExecute); SetItem(MnuCmdTargetEarlier,@ATargetEarlierExecute); SetItem(MnuCmdTargetCopyFilename,@ATargetCopyFilenameExecute); + SetItem(MnuCmdProjGrpUndo,@AProjectGroupUndoExecute); + SetItem(MnuCmdProjGrpRedo,@AProjectGroupRedoExecute); end; procedure TProjectGroupEditorForm.FormDestroy(Sender: TObject); @@ -572,17 +579,8 @@ begin PG.Perform(ND.Target,taOpen) end; end; - ntRemovedTarget: - begin - PG:=ND.Target.GetOwnerProjectGroup; - if PG=nil then exit; - case ND.Target.TargetType of - ttProject, - ttPackage, - ttPascalFile: - PG.Perform(ND.Target,taOpen); - end; - end; + ntMissingTarget: + ; ntFile: begin // open file in source editor @@ -656,32 +654,19 @@ begin SBPG.Panels[piActiveTarget].Text:=s; end; -procedure TProjectGroupEditorForm.OnTargetAdded(Sender: TObject; +procedure TProjectGroupEditorForm.OnTargetInserted(Sender: TObject; Target: TPGCompileTarget); Var N: TTreeNode; begin (Target as TIDECompileTarget).LoadTarget(true); if Sender<>ProjectGroup then exit; // ToDo: sub groups - N:=CreateTargetNode(FTargetNodes[False],ntTarget,Target); - FillTargetNode(N,Target); - TVPG.Selected:=N; - UpdateStatusBarTargetCount; -end; - -procedure TProjectGroupEditorForm.OnTargetReadded(Sender: TObject; - Target: TPGCompileTarget); -var - N, NewNode: TTreeNode; -begin - if Sender<>ProjectGroup then exit; // ToDo: sub groups - N:=FindTVNodeOfTarget(Target); TVPG.BeginUpdate; try - TVPG.Items.Delete(N); - NewNode:=CreateTargetNode(FTargetNodes[False],ntTarget,Target); - FillTargetNode(NewNode,Target); - TVPG.Selected:=FProjectGroupTVNode; + N:=CreateTargetNode(FProjectGroupTVNode,ntTarget,Target); + N.Index:=Target.GetIndex; + FillTargetNode(N,Target); + TVPG.Selected:=N; finally TVPG.EndUpdate; end; @@ -698,7 +683,6 @@ begin TVPG.BeginUpdate; try TVPG.Items.Delete(N); - CreateTargetNode(FTargetNodes[True],ntRemovedTarget,Target); TVPG.Selected:=FProjectGroupTVNode; finally TVPG.EndUpdate; @@ -747,7 +731,7 @@ begin if FProjectGroup=nil then exit; P:=FProjectGroup.FileName; ProjectGroupManager.SaveProjectGroup; - if CompareFilenames(ExtractFilePath(P),ExtractFilePath(FProjectGroup.FileName))<>0 then + if P<>FProjectGroup.FileName then ShowProjectGroup; end; @@ -760,30 +744,26 @@ var begin if FProjectGroup=nil then exit; aTarget:=TIDECompileTarget(SelectedTarget); - if (aTarget<>nil) and aTarget.Removed then - aTarget.Parent.ProjectGroup.ReAddTarget(aTarget) - else begin - InitIDEFileDialog(OpenDialogTarget); - OpenDialogTarget.Filter := lisLazarusProjectsLpi + '|*.lpi' - + '|' + lisLazarusPackagesLpk + '|*.lpk' - + '|' + lisLazarusProjectGroupsLpg + '|*.lpg' - + '|' + lisPascalFilePasPpP + '|*.pas;*.pp;*.p'; - If OpenDialogTarget.Execute then - for i:=0 to OpenDialogTarget.Files.Count-1 do + InitIDEFileDialog(OpenDialogTarget); + OpenDialogTarget.Filter := lisLazarusProjectsLpi + '|*.lpi' + + '|' + lisLazarusPackagesLpk + '|*.lpk' + + '|' + lisLazarusProjectGroupsLpg + '|*.lpg' + + '|' + lisPascalFilePasPpP + '|*.pas;*.pp;*.p'; + If OpenDialogTarget.Execute then + for i:=0 to OpenDialogTarget.Files.Count-1 do + begin + aTarget:=FProjectGroup.AddTarget(OpenDialogTarget.Files[i]) as TIDECompileTarget; + aTarget.LoadTarget(true); + if aTarget.BuildModeCount>1 then begin - aTarget:=FProjectGroup.AddTarget(OpenDialogTarget.Files[i]) as TIDECompileTarget; - aTarget.LoadTarget(true); - if aTarget.BuildModeCount>1 then - begin - aMode:=aTarget.BuildModes[0]; - aMode.Compile:=true; - // ToDo: implement changed notification - TVNode:=FindTVNodeOfBuildMode(aMode); - TVNode.StateIndex:=NSIChecked; - end; + aMode:=aTarget.BuildModes[0]; + aMode.Compile:=true; + // ToDo: implement changed notification + TVNode:=FindTVNodeOfBuildMode(aMode); + TVNode.StateIndex:=NSIChecked; end; - StoreIDEFileDialog(OpenDialogTarget); - end; + end; + StoreIDEFileDialog(OpenDialogTarget); end; procedure TProjectGroupEditorForm.ATargetActivateUpdate(Sender: TObject); @@ -814,13 +794,17 @@ begin begin PG:=TIDEProjectGroup(ProjectGroup); if PG.Modified then begin + // ToDo: revert IDEMessageDialog(lisNeedSave, lisPleaseSaveYourChangesBeforeReloadingTheProjectGrou, mtError,[mbOK]); exit; end; ProjectGroup:=nil; - PG.LoadFromFile([pgloLoadRecursively]); - ProjectGroup:=PG; + try + PG.LoadFromFile([pgloLoadRecursively]); + finally + ProjectGroup:=PG; + end; end; end; @@ -850,12 +834,12 @@ begin ND:=SelectedNodeData; if ND<>nil then begin if ND.Target<>nil then begin - Result:=(not ND.Target.Removed) and (ATargetAction in ND.Target.AllowedActions); + Result:=(not ND.Target.Missing) and (ATargetAction in ND.Target.AllowedActions); end else begin aTarget:=GetNearestTargget(TVPG.Selected); case ND.NodeType of ntBuildMode: - Result:=(not aTarget.Removed) + Result:=(not aTarget.Missing) and (ATargetAction in [taCompile,taCompileClean,taCompileFromHere,taRun]); end; end; @@ -920,10 +904,21 @@ Var T: TPGCompileTarget; begin T:=SelectedTarget; - (Sender as TAction).Enabled:=(T<>nil) and (T<>ProjectGroup.CompileTarget) and Not T.Removed; + (Sender as TAction).Enabled:=(T<>nil) and (T<>ProjectGroup.CompileTarget); UpdateIDEMenuCommandFromAction(Sender,MnuCmdTargetRemove); end; +procedure TProjectGroupEditorForm.AProjectGroupRedoExecute(Sender: TObject); +begin + // ToDo + writeln('TProjectGroupEditorForm.AProjectGroupRedoExecute Todo'); +end; + +procedure TProjectGroupEditorForm.AProjectGroupRedoUpdate(Sender: TObject); +begin + (Sender as TAction).Enabled:=IDEProjectGroupManager.CanRedo; +end; + procedure TProjectGroupEditorForm.ATargetCopyFilenameExecute(Sender: TObject); var ND: TNodeData; @@ -1006,8 +1001,6 @@ Var begin FActiveTarget:=nil; FProjectGroupTVNode:=Nil; - FTargetNodes[False]:=Nil; - FTargetNodes[True]:=Nil; For I:=0 to TVPG.Items.Count-1 do begin N:=TVPG.Items[I]; @@ -1021,8 +1014,6 @@ function TProjectGroupEditorForm.GetNodeImageIndex(ANodeType: TNodeType; begin case ANodeType of ntProjectGroup: Result:=NIProjectGroup; - ntTargets: Result:=NITargets; - ntRemovedTargets: Result:=NIRemovedTargerts; ntTarget : Case ANodeData.TargetType of ttProject: Result:=NITargetProject; @@ -1030,11 +1021,11 @@ begin ttProjectGroup: Result:=NITargetProjectGroup; ttPascalFile: Result:=NIFile; end; - ntRemovedTarget: + ntMissingTarget: Case ANodeData.TargetType of - ttProject: Result:=NIRemovedTargetProject; - ttPackage: Result:=NIRemovedTargetPackage; - ttProjectGroup: Result:=NIRemovedTargetProjectGroup; + ttProject: Result:=NIMissingTargetProject; + ttPackage: Result:=NIMissingTargetPackage; + ttProjectGroup: Result:=NIMissingTargetProjectGroup; ttPascalFile: Result:=NIFile; end; ntBuildModes: Result:=NIBuildModes; @@ -1374,12 +1365,10 @@ begin FreeNodeData; ShowFileName; // Needs FProjectGroupTVNode TVPG.Items.Clear; - FTargetNodes[False]:=Nil; - FTargetNodes[True]:=Nil; if FProjectGroup<>nil then begin FProjectGroupTVNode:=CreateTargetNode(Nil, ntProjectGroup,ProjectGroup.CompileTarget); - FillProjectGroupNode(FProjectGroupTVNode,FProjectGroup,FTargetNodes); + FillProjectGroupNode(FProjectGroupTVNode,FProjectGroup); N:=FindTVNodeOfTarget(FActiveTarget); if (N=Nil) then begin @@ -1404,64 +1393,58 @@ begin end; procedure TProjectGroupEditorForm.FillProjectGroupNode(TVNode: TTreeNode; - AProjectGroup: TProjectGroup; out TargetNodes: TTargetNodes); + AProjectGroup: TProjectGroup); Const - TNT: Array[Boolean] of TNodeType = (ntTarget,ntRemovedTarget); + TNT: Array[Boolean] of TNodeType = (ntTarget,ntMissingTarget); Var T: TPGCompileTarget; - aTargetsNode,TN: TTreeNode; + TN: TTreeNode; I: Integer; begin TVPG.BeginUpdate; try ClearChildNodes(TVNode); - aTargetsNode:=CreateSectionNode(TVNode,lisNodeTargets,ntTargets); - TargetNodes[False]:=aTargetsNode; - TargetNodes[True]:=CreateSectionNode(TVNode,lisNodeRemovedTargets,ntTargets); // 2 Passes: one to show all nodes, one to fill them with target-specific data. // Display all nodes For I:=0 to AProjectGroup.TargetCount-1 do begin T:=AProjectGroup.Targets[i]; - CreateTargetNode(TargetNodes[T.Removed],TNT[T.Removed],T); + CreateTargetNode(TVNode,TNT[T.Missing],T); end; // Fill all nodes. - For I:=0 to aTargetsNode.Count-1 do + For I:=0 to TVNode.Count-1 do begin - TN:=aTargetsNode.Items[i]; + TN:=TVNode.Items[i]; FillTargetNode(TN,TargetFromNode(TN)); end; TVNode.Expand(False); - TargetNodes[False].Expand(False); - TargetNodes[True].Expand(False); finally TVPG.EndUpdate; end; end; -procedure TProjectGroupEditorForm.ShowDependencies(AParent: TTreeNode; - T: TPGCompileTarget; out PD: TTargetNodes); +function TProjectGroupEditorForm.ShowDependencies(AParent: TTreeNode; + T: TPGCompileTarget): TTreeNode; Var i: Integer; Pkg: TIDEPackage; PkgName: String; begin - PD[False]:=CreateSectionNode(AParent,lisNodeDependencies,ntDependencies); - PD[True]:=nil; //CreateNode(AParent,lisNodeRemovedDependencies,ntRemovedDependencies,Nil,AProjectGroup); + Result:=CreateSectionNode(AParent,lisNodeDependencies,ntDependencies); For i:=0 to T.RequiredPackageCount-1 do begin PkgName:=T.RequiredPackages[i].PackageName; Pkg:=PackageEditingInterface.FindPackageWithName(PkgName); if Pkg<>nil then PkgName:=Pkg.Name; - CreateSubNode(PD[False],ntDependency,T,PkgName); + CreateSubNode(Result,ntDependency,T,PkgName); end; end; procedure TProjectGroupEditorForm.FillProjectNode(TVNode: TTreeNode; T: TPGCompileTarget); Var - FileNodes,DepNodes: TTargetNodes; + FilesNode: TTreeNode; i: Integer; BuildModeNode, SubTVNode: TTreeNode; aMode: TPGBuildMode; @@ -1485,12 +1468,11 @@ begin end; end; // files - FileNodes[False]:=CreateSectionNode(TVNode,lisNodeFiles,ntFiles); - FileNodes[True]:=nil; //CreateNode(TVNode,lisNodeRemovedFiles,ntFiles,Nil,AProjectGroup); + FilesNode:=CreateSectionNode(TVNode,lisNodeFiles,ntFiles); for i:=0 to T.FileCount-1 do - CreateSubNode(FileNodes[False],ntFile,T,T.Files[i]); + CreateSubNode(FilesNode,ntFile,T,T.Files[i]); // dependencies - ShowDependencies(TVNode,T,DepNodes); + ShowDependencies(TVNode,T); finally TVPG.EndUpdate; end; @@ -1499,17 +1481,16 @@ end; procedure TProjectGroupEditorForm.FillPackageNode(TVNode: TTreeNode; T: TPGCompileTarget); Var - PF,PD: TTargetNodes; + FilesNode: TTreeNode; i: Integer; begin TVPG.BeginUpdate; try ClearChildNodes(TVNode); - PF[False]:=CreateSectionNode(TVNode,lisNodeFiles,ntFiles); - PF[True]:=nil; //CreateNode(TVNode,lisNodeRemovedFiles,ntFiles,Nil,AProjectGroup); + FilesNode:=CreateSectionNode(TVNode,lisNodeFiles,ntFiles); for i:=0 to T.FileCount-1 do - CreateSubNode(PF[False],ntFile,T,T.Files[i]); - ShowDependencies(TVNode,T,PD); + CreateSubNode(FilesNode,ntFile,T,T.Files[i]); + ShowDependencies(TVNode,T); finally TVPG.EndUpdate; end; @@ -1517,8 +1498,6 @@ end; procedure TProjectGroupEditorForm.FillTargetNode(TVNode: TTreeNode; T: TPGCompileTarget); -Var - PN: TTargetNodes; begin TVPG.BeginUpdate; try @@ -1530,7 +1509,7 @@ begin case T.TargetType of ttProject: FillProjectNode(TVNode,T); ttPackage: FillPackageNode(TVNode,T); - ttProjectGroup: FillProjectgroupNode(TVNode,T.ProjectGroup,PN); + ttProjectGroup: FillProjectgroupNode(TVNode,T.ProjectGroup); ttPascalFile: ; end; finally diff --git a/components/projectgroups/projectgroupintf.pp b/components/projectgroups/projectgroupintf.pp index 7b0812da74..bdf85e7478 100644 --- a/components/projectgroups/projectgroupintf.pp +++ b/components/projectgroups/projectgroupintf.pp @@ -72,7 +72,7 @@ Type FActive: Boolean; FFilename: string; FTargetType: TPGTargetType; - FRemoved: boolean; + FMissing: boolean; protected FParent: TPGCompileTarget; FProjectGroup: TProjectGroup; @@ -86,7 +86,7 @@ Type function Perform(AAction: TPGTargetAction): TPGActionResult; function PerformAction(AAction: TPGTargetAction): TPGActionResult; virtual; abstract; procedure SetFilename(const AValue: string); virtual; - procedure SetRemoved(const AValue: boolean); virtual; + procedure SetMissing(const AValue: boolean); virtual; procedure SetTargetType(AValue: TPGTargetType); virtual; procedure DoDeactivateChildren; procedure ActiveChanged(Sender: TPGCompileTarget); virtual; abstract; @@ -105,13 +105,14 @@ Type procedure Modified; virtual; abstract; property Parent: TPGCompileTarget read FParent; property Filename: string read FFilename write SetFilename; // Absolute, not relative. - property Removed: boolean read FRemoved write SetRemoved; + property Missing: boolean read FMissing write SetMissing; property TargetType: TPGTargetType read FTargetType write SetTargetType; property Active: Boolean Read FActive; + function GetIndex: Integer; // Currently allowed actions. property AllowedActions: TPGTargetActions Read GetAllowedActions; // - property ProjectGroup: TProjectGroup read FProjectGroup; // set if TargetType is ttProjectGroup + property ProjectGroup: TProjectGroup read FProjectGroup; // only set if TargetType=ttProjectGroup property BuildModes[Index: integer]: TPGBuildMode read GetBuildModes; property BuildModeCount: integer read GetBuildModeCount; property Files[Index: integer]: string read GetFiles; @@ -140,8 +141,6 @@ Type function GetModified: Boolean; virtual; function GetTargetCount: Integer; virtual; abstract; function GetTarget(Index: Integer): TPGCompileTarget; virtual; abstract; - function GetRemovedTargetCount: Integer; virtual; abstract; - function GetRemovedTarget(Index: Integer): TPGCompileTarget; virtual; abstract; procedure DoCallNotifyHandler(HandlerType: TProjectGroupHandler; Sender: TObject); overload; procedure AddHandler(HandlerType: TProjectGroupHandler; @@ -154,7 +153,7 @@ Type destructor Destroy; override; function GetRootGroup: TProjectGroup; property FileName: String Read FFileName Write SetFileName; // absolute - property CompileTarget: TPGCompileTarget read FCompileTarget; + property CompileTarget: TPGCompileTarget read FCompileTarget; // this group as target property Parent: TProjectGroup read FParent; // actions function Perform(Index: Integer; AAction: TPGTargetAction): TPGActionResult; @@ -163,20 +162,16 @@ Type function ActionAllowsFrom(Index: Integer; AAction: TPGTargetAction): Boolean; virtual; function PerformFrom(AIndex: Integer; AAction: TPGTargetAction): TPGActionResult; virtual; // targets - function IndexOfTarget(Const Target: TPGCompileTarget): Integer; virtual; abstract; - function IndexOfTarget(Const AFilename: String): Integer; virtual; - function IndexOfRemovedTarget(Const Target: TPGCompileTarget): Integer; virtual; abstract; - function IndexOfRemovedTarget(Const AFilename: String): Integer; virtual; + function IndexOfTarget(Const Target: TPGCompileTarget): Integer; overload; virtual; abstract; + function IndexOfTarget(Const AFilename: String): Integer; overload; virtual; function AddTarget(Const AFileName: String): TPGCompileTarget; virtual; abstract; - procedure ReAddTarget(Target: TPGCompileTarget); virtual; abstract; + function InsertTarget(Const Target: TPGCompileTarget; Index: Integer): Integer; virtual; abstract; procedure ExchangeTargets(ASource, ATarget: Integer); virtual; abstract; procedure RemoveTarget(Index: Integer); virtual; abstract; procedure RemoveTarget(Const AFileName: String); procedure RemoveTarget(Target: TPGCompileTarget); property Targets[Index: Integer]: TPGCompileTarget Read GetTarget; property TargetCount: Integer Read GetTargetCount; - property RemovedTargets[Index: Integer]: TPGCompileTarget Read GetRemovedTarget; - property RemovedTargetCount: Integer Read GetRemovedTargetCount; property ActiveTarget: TPGCompileTarget Read GetActiveTarget Write SetActiveTarget; public // modified @@ -191,8 +186,8 @@ Type end; TProjectGroupLoadOption = ( - pgloRemoveInvalid, // Mark non-existing targets from group as removed. - pgloSkipInvalid, // Ignore non-existing, add as-is. + pgloRemoveInvalid, // Remove non-existing targets from group automatically while loading + pgloSkipInvalid, // Mark non-existing as Missing. pgloErrorInvalid, // Stop with error on non-existing. pgloSkipDialog, // do not show Project Group editor. pgloLoadRecursively // load all sub nodes @@ -207,6 +202,10 @@ Type public procedure LoadProjectGroup(AFileName: string; AOptions: TProjectGroupLoadOptions); virtual; abstract; procedure SaveProjectGroup; virtual; abstract; + function CanUndo: boolean; virtual; abstract; + function CanRedo: boolean; virtual; abstract; + procedure Undo; virtual; abstract; + procedure Redo; virtual; abstract; property CurrentProjectGroup: TProjectGroup Read GetCurrentProjectGroup; // Always top-level. end; @@ -372,8 +371,8 @@ begin while Result and (Index=0) and (CompareFilenames(AFileName,GetRemovedTarget(Result).Filename)<>0) do - Dec(Result); -end; - procedure TProjectGroup.RemoveTarget(const AFileName: String); begin RemoveTarget(IndexOfTarget(AFileName)) @@ -445,6 +436,16 @@ end; { TPGCompileTarget } +function TPGCompileTarget.GetIndex: Integer; +var + Group: TProjectGroup; +begin + if Parent=nil then exit(0); + Group:=Parent.ProjectGroup; + if Group=nil then exit(0); + Result:=Group.IndexOfTarget(Self); +end; + function TPGCompileTarget.GetAllowedActions: TPGTargetActions; begin Result:=PGTargetActions[TargetType]; @@ -515,10 +516,10 @@ begin ProjectGroup.FileName:=Filename; end; -procedure TPGCompileTarget.SetRemoved(const AValue: boolean); +procedure TPGCompileTarget.SetMissing(const AValue: boolean); begin - if Removed=AValue then exit; - FRemoved:=AValue; + if Missing=AValue then exit; + FMissing:=AValue; end; procedure TPGCompileTarget.Activate; diff --git a/components/projectgroups/projectgroupstrconst.pas b/components/projectgroups/projectgroupstrconst.pas index bd61f7a577..3172be83ab 100644 --- a/components/projectgroups/projectgroupstrconst.pas +++ b/components/projectgroups/projectgroupstrconst.pas @@ -27,6 +27,8 @@ Resourcestring lisTargetAdd = 'Add target'; lisTargetRemove = 'Remove target'; + lisUndo = 'Undo'; + lisRedo = 'Redo'; lisTargetCompile = 'Compile'; lisProjectGroups = 'Project Groups'; lisTargetCompileClean = 'Compile clean'; diff --git a/components/projectgroups/regprojectgroup.pp b/components/projectgroups/regprojectgroup.pp index f332582dcc..8ab95c2af8 100644 --- a/components/projectgroups/regprojectgroup.pp +++ b/components/projectgroups/regprojectgroup.pp @@ -8,7 +8,7 @@ interface uses Classes, SysUtils, ProjectGroupIntf, MenuIntf, IDECommands, ToolBarIntf, - ProjectGroupStrConst, ProjectGroup, ProjectGroupEditor; + ProjectGroupStrConst, ProjectGroup, ProjectGroupEditor, LCLType; procedure RegisterProjectGroupEditorMenuItems; procedure Register; @@ -46,7 +46,7 @@ begin PGEditMenuSectionAddRemove:=MnuSection; RegisterMenuCmd(MnuCmdTargetAdd,MnuSection,'TargetAdd',lisTargetAdd); RegisterMenuCmd(MnuCmdTargetRemove,MnuSection,'TargetRemove',lisTargetRemove); - // ToDo: undo + // ToDo: redo MnuSection:=RegisterIDEMenuSection(MnuRoot,'Use'); PGEditMenuSectionUse:=MnuSection; @@ -61,8 +61,9 @@ begin MnuSection:=RegisterIDEMenuSection(MnuRoot,'Misc'); PGEditMenuSectionMisc:=MnuSection; - RegisterMenuCmd(MnuCmdTargetCopyFilename,MnuSection,'CopyFilename',lisTargetCopyFilename); + RegisterMenuCmd(MnuCmdProjGrpUndo, MnuSection, 'Undo', lisUndo); + RegisterMenuCmd(MnuCmdProjGrpRedo, MnuSection, 'Redo', lisRedo); // ToDo: View source (project) // ToDo: find in files @@ -71,6 +72,11 @@ begin // ToDo: D&D order compile targets end; +procedure ViewProjectGroupsClicked(Sender: TObject); +begin + ShowProjectGroupEditor(Sender,IDEProjectGroupManager.CurrentProjectGroup); +end; + procedure Register; procedure RegisterMnuCmd(out Cmd: TIDECommand; out MenuCmd: TIDEMenuCommand; @@ -82,8 +88,11 @@ procedure Register; RegisterIDEButtonCommand(Cmd); end; +var + IDECommandCategory: TIDECommandCategory; begin IDEProjectGroupManager:=TIDEProjectGroupManager.Create; + ProjectGroupManager:=IDEProjectGroupManager; IDEProjectGroupManager.Options.LoadSafe; PGCmdCategory:=RegisterIDECommandCategory(nil,ProjectGroupCmdCategoryName,lisProjectGroups); @@ -105,8 +114,23 @@ begin IDEProjectGroupManager.UpdateRecentProjectGroupMenu; - ProjectGroupManager:=IDEProjectGroupManager; SetProjectGroupEditorCallBack; + + RegisterIDEMenuCommand(itmViewMainWindows, 'mnuProjectGroups', + lisProjectGroups, nil, @ViewProjectGroupsClicked); + + ViewProjGrpShortCutX := IDEShortCut(VK_UNKNOWN, [], VK_UNKNOWN, []); + IDECommandCategory := IDECommandList.FindCategoryByName(CommandCategoryViewName); + if IDECommandCategory <> nil then + begin + ViewProjectGroupsCommand := RegisterIDECommand(IDECommandCategory, 'Project Groups', + lisProjectGroups, ViewProjGrpShortCutX, nil, @ViewProjectGroupsClicked); + if ViewProjectGroupsCommand <> nil then + begin + ViewProjectGroupsButtonCommand := RegisterIDEButtonCommand(ViewProjectGroupsCommand); + if ViewProjectGroupsButtonCommand=nil then ; + end; + end; end; finalization