114 ClassImp(TQUndoManager);
116 static TQCommand *gActiveCommand = 0;
121 void TQCommand::Init(
const char *clname,
void *obj,
const char *redo,
const char *undo)
123 TString credo( CompressName(redo) );
124 TString cundo( CompressName(undo) );
126 fNRargs = fNUargs = -1;
130 fRedo = redo ?
new TQConnection(clname, obj, credo) : 0;
131 fUndo = undo ?
new TQConnection(clname, obj, cundo) : fRedo;
138 if (!obj && !redo && !undo) {
169 TQCommand::TQCommand(
const char *clname,
void *obj,
const char *redo,
170 const char *undo) : TList(), TQObject()
172 Init(clname, obj, redo, undo);
200 TQCommand::TQCommand(TObject *obj,
const char *redo,
const char *undo) :
203 if (obj) Init(obj->ClassName(), obj, redo, undo);
204 else Init(0, 0, redo, undo);
210 TQCommand::TQCommand(
const TQCommand &com) : TList(), TQObject()
212 fRedo =
new TQConnection(*(com.fRedo));
213 fUndo =
new TQConnection(*(com.fUndo));
217 fNRargs = com.fNRargs;
218 fNUargs = com.fNUargs;
221 fRedoArgs =
new Long_t[fNRargs];
222 for (
int i = 0; i< fNRargs; i++) {
223 fRedoArgs[i] = com.fRedoArgs[i];
227 fUndoArgs =
new Long_t[fNUargs];
228 for (
int i = 0; i < fNUargs; i++) {
229 fUndoArgs[i] = com.fUndoArgs[i];
232 fStatus = com.fStatus;
233 fNewDelete = com.fNewDelete;
236 fObject = com.fObject;
242 while ((obj = (TQCommand*)next())) {
243 TList::Add(
new TQCommand(*obj));
250 TQCommand::~TQCommand()
252 if (fRedo != fUndo)
delete fUndo;
277 TQCommand *TQCommand::GetCommand()
279 return gActiveCommand;
286 void TQCommand::Delete(Option_t *opt)
298 TString ostr = lnk->GetOption();
299 if (ostr.Contains(opt)) {
300 TObject *obj = lnk->GetObject();
301 lnk->SetObject(
nullptr);
315 Bool_t TQCommand::CanMerge(TQCommand *)
const
317 return (!fRedo && !fUndo);
330 void TQCommand::Merge(TQCommand *c)
338 Long64_t TQCommand::Merge(TCollection *collection,TFileMergeInfo*)
340 TIter next(collection);
341 while (TObject* o = next()) {
342 TQCommand *command =
dynamic_cast<TQCommand*
> (o);
345 "Cannot merge - an object which doesn't inherit from TQCommand found in the list");
361 void TQCommand::Add(TObject *obj, Option_t *opt)
363 if (!obj->InheritsFrom(TQCommand::Class()))
return;
365 TQCommand *o = (TQCommand *)obj;
366 TQCommand *c = (TQCommand *)Last();
370 if (c->CanCompress(o) || (c->IsEqual(o) && ostr.Contains(
"compress"))) {
375 TList::AddLast(o, opt);
376 if (o->CanRedo() && ostr.Contains(
"radd")) o->Redo();
377 if (o->CanUndo() && ostr.Contains(
"uadd")) o->Undo();
388 Bool_t TQCommand::CanCompress(TQCommand *c)
const
390 return (IsEqual(c) && IsSetter());
403 void TQCommand::Compress(TQCommand *c)
405 for (
int i = 0; i < fNRargs; i++) {
406 fRedoArgs[i] = c->fRedoArgs[i];
419 Bool_t TQCommand::IsEqual(
const TObject* obj)
const
421 if (!obj->InheritsFrom(TQCommand::Class()))
return kFALSE;
422 TQCommand *c = (TQCommand *)obj;
423 if (!fRedo || !fUndo || (c->GetObject() != fObject))
return kFALSE;
425 TString cname = fRedo->GetClassName();
426 TString rname = fRedo->GetName();
428 return ((cname == c->GetRedo()->GetClassName()) &&
429 (rname == c->GetRedo()->GetName()));
441 Bool_t TQCommand::IsSetter()
const
443 TString redo = GetRedoName();
444 TString undo = GetUndoName();
446 if (!redo || !undo || (redo != undo))
return kFALSE;
448 return (redo.BeginsWith(
"Set") ||
449 redo.BeginsWith(
"set") ||
450 redo.BeginsWith(
"Move") ||
451 redo.BeginsWith(
"move") ||
452 redo.BeginsWith(
"Resize") ||
453 redo.BeginsWith(
"resize"));
466 void TQCommand::SetArgs(Int_t narg, ...)
471 fNRargs = fNUargs = narg;
478 if (fNRargs != narg ) {
481 fRedoArgs =
new Long_t[narg];
483 if (fNUargs != narg ) {
486 fUndoArgs =
new Long_t[narg];
488 fNRargs = fNUargs = narg;
491 for (i = 0; i < fNRargs; i++) {
492 fRedoArgs[i] = va_arg(ap, Long_t);
494 for (i = 0; i < fNUargs; i++) {
495 fUndoArgs[i] = va_arg(ap, Long_t);
509 void TQCommand::SetRedoArgs(Int_t narg, ...)
521 if (fNRargs != narg ) {
524 fRedoArgs =
new Long_t[narg];
528 for (
int i = 0; i < fNRargs; i++) {
529 fRedoArgs[i] = va_arg(ap, Long_t);
543 void TQCommand::SetUndoArgs(Int_t narg, ...)
555 if (fNUargs != narg ) {
558 fUndoArgs =
new Long_t[narg];
562 for (
int i = 0; i < fNUargs; i++) {
563 fUndoArgs[i] = va_arg(ap, Long_t);
572 Bool_t TQCommand::CanRedo()
const
574 return (fStatus <= 0);
581 Bool_t TQCommand::CanUndo()
const
583 return (fStatus > 0);
589 void TQCommand::Redo(Option_t *)
591 Bool_t done = kFALSE;
594 gActiveCommand =
this;
598 fRedo->ExecuteMethod(fRedoArgs, fNRargs);
601 }
else if (!fNRargs) {
603 fRedo->ExecuteMethod();
611 TQCommand *c = (TQCommand *)lnk->GetObject();
617 if (done) Emit(
"Redo()");
627 void TQCommand::Undo(Option_t *)
629 Bool_t done = kFALSE;
632 gActiveCommand =
this;
637 TQCommand *c = (TQCommand *)lnk->GetObject();
638 TString opt = lnk->GetOption();
639 auto sav = lnk->PrevSP();
642 if (opt.Contains(
"remove")) {
643 delete lnk->GetObject();
650 fUndo->ExecuteMethod(fUndoArgs, fNUargs);
653 }
else if (!fNUargs) {
655 fUndo->ExecuteMethod();
660 if (done) Emit(
"Undo()");
671 const char *TQCommand::GetName()
const
673 const Int_t maxname = 100;
678 R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
688 if (fRedo->GetClassName()) {
689 name = fRedo->GetClassName();
692 name += fRedo->GetName();
695 TObjLink *lnk = fFirst.get();
697 while (lnk && (fName.Length() < maxname)) {
698 c = (TQCommand *)lnk->GetObject();
700 name += c->GetName();
704 TQCommand *m =
const_cast<TQCommand*
>(
this);
714 const char *TQCommand::GetTitle()
const
716 if (!fTitle.IsNull())
717 return fTitle.Data();
720 TTHREAD_TLS_DECL_ARG(TString, title, GetName());
723 title += fUndo->GetClassName();
725 if (fUndo->GetName())
726 title += fUndo->GetName();
737 const char *TQCommand::GetRedoName()
const
739 return (fRedo ? fRedo->GetName() : 0);
745 const char *TQCommand::GetUndoName()
const
747 return (fUndo ? fUndo->GetName() : 0);
753 Long_t *TQCommand::GetRedoArgs()
const
761 Long_t *TQCommand::GetUndoArgs()
const
769 Int_t TQCommand::GetNRargs()
const
777 Int_t TQCommand::GetNUargs()
const
785 void *TQCommand::GetObject()
const
793 Int_t TQCommand::GetStatus()
const
801 Bool_t TQCommand::IsMacro()
const
803 return (!fRedo && !fUndo);
809 Bool_t TQCommand::IsUndoing()
const
817 Bool_t TQCommand::IsRedoing()
const
825 Bool_t TQCommand::IsExecuting()
const
833 void TQCommand::SetName(
const char *name)
841 void TQCommand::SetTitle(
const char *title)
849 void TQCommand::ls(Option_t *)
const
851 TString name = GetName();
852 printf(
"%d %s\n", fStatus, name.Data());
854 TObjLink *lnk = fFirst.get();
857 lnk->GetObject()->ls();
865 void TQCommand::PrintCollectionHeader(Option_t* )
const
867 TROOT::IndentLevel();
868 printf(
"%d %s\n", fStatus, GetName());
878 TQUndoManager::TQUndoManager() : TQCommand(0, 0, 0, 0)
890 TQUndoManager::~TQUndoManager()
902 void TQUndoManager::ls(Option_t *option)
const
905 TObjLink *lnk = fFirst.get();
907 if (lnk == fCursor) {
912 TQCommand *com = (TQCommand*)lnk->GetObject();
922 void TQUndoManager::PrintCollectionEntry(TObject* entry, Option_t* option,
925 TQCommand *com = (TQCommand*) entry;
926 TROOT::IndentLevel();
927 if (fCursor && fCursor->GetObject() == entry) {
939 void TQUndoManager::SetLogging(Bool_t on)
947 fLogBook =
new TList();
960 void TQUndoManager::Add(TObject *obj, Option_t *opt)
962 if (!obj->InheritsFrom(TQCommand::Class()))
return;
964 TQCommand *o = (TQCommand *)obj;
966 Bool_t onredo = fCursor && fCursor->Next();
967 TString ostr = onredo ?
"1radd" :
"0radd";
968 if (opt) ostr += opt;
980 if (fCursor && fCursor->Next()) {
981 TObjLink *lnk = fCursor->Next();
985 delete lnk->GetObject();
993 if (c->CanCompress(o) || c->CanMerge(o) ||
994 ostr.Contains(
"merge") || ostr.Contains(
"compress")) {
996 c->Add(o, ostr.Data());
1002 TList::AddLast(obj, ostr.Data());
1003 fCursor = fLast.get();
1006 if ((fSize > 0) && ((UInt_t)fSize > fLimit)) {
1014 void TQUndoManager::CurrentChanged(TQCommand *c)
1016 Emit(
"CurrentChanged(TQCommand*)", (
long)c);
1022 void TQUndoManager::Undo(Option_t *option)
1024 Bool_t done = kFALSE;
1025 if (!CanUndo())
return;
1027 TQCommand *sav = fCurrent;
1028 TQCommand *c = (TQCommand*)fCursor->GetObject();
1033 fCurrent->Undo(option);
1036 fCursor = fCursor->Prev() ? fCursor->Prev() : fFirst.get();
1038 fCursor = fCursor->Prev();
1039 fCurrent = (TQCommand*)fCursor->GetObject();
1041 fCurrent->Undo(option);
1045 if (done && fLogging && fLogBook) {
1046 fLogBook->Add(
new TQCommand(*fCurrent));
1048 if (sav != fCurrent) CurrentChanged(fCurrent);
1054 void TQUndoManager::Redo(Option_t *option)
1056 Bool_t done = kFALSE;
1057 if (!CanRedo())
return;
1059 TQCommand *sav = fCurrent;
1060 TQCommand *c = (TQCommand*)fCursor->GetObject();
1065 fCurrent->Redo(option);
1068 fCursor = fCursor->Next() ? fCursor->Next() : fLast.get();
1070 fCursor = fCursor->Next();
1071 fCurrent = (TQCommand*)fCursor->GetObject();
1073 fCurrent->Redo(option);
1077 if (done && fLogging && fLogBook) {
1078 fLogBook->Add(
new TQCommand(*fCurrent));
1080 if (sav != fCurrent) CurrentChanged(fCurrent);
1086 Bool_t TQUndoManager::CanRedo()
const
1088 if (!fCursor)
return kFALSE;
1090 TQCommand *c = (TQCommand*)fCursor->GetObject();
1091 if (c->CanRedo())
return kTRUE;
1093 c = fCursor->Next() ? (TQCommand*)fCursor->Next()->GetObject() : 0;
1094 return (c && c->CanRedo());
1100 Bool_t TQUndoManager::CanUndo()
const
1102 if (!fCursor)
return kFALSE;
1104 TQCommand *c = (TQCommand*)fCursor->GetObject();
1105 if (c->CanUndo())
return kTRUE;
1107 c = fCursor->Prev() ? (TQCommand*)fCursor->Prev()->GetObject() : 0;
1108 return (c && c->CanUndo());
1114 Bool_t TQUndoManager::IsLogging()
const
1122 TQCommand *TQUndoManager::GetCurrent()
const
1130 TQCommand *TQUndoManager::GetCursor()
const
1132 return (TQCommand*)(fCursor ? fCursor->GetObject() : 0);
1138 void TQUndoManager::SetLimit(UInt_t limit)
1146 UInt_t TQUndoManager::GetLimit()
const