Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TQCommand.cxx
Go to the documentation of this file.
1// @(#)root/base:$Id$
2// Author: Valeriy Onuchin 04/27/2004
3
4/*************************************************************************
5 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TQCommand
13\ingroup Base
14
15The Command design pattern is based on the idea, that all editing
16in an application is done by creating instances of command objects.
17Command objects apply changes to the edited object and then are
18stored on a command stack. Furthermore, each command knows how to
19undo its changes to bring the edited object back to its previous
20state. As long as the application only uses command objects to
21change the state of the edited object, it is possible to undo
22a sequence of commands by traversing the command stack downwards and
23calling the "undo" method of each command in turn. It is also
24possible to redo a sequence of commands by traversing the command
25stack upwards and calling the "redo" method of each command.
26
27
28Examples:
29
301. Create a new command
31~~~ {.cpp}
32 TQCommand *com = new TQCommand("TH1", hpx, "SetFillColor(Color_t)"
33 "SetFillColor(Color_t)");
34~~~
35 - 1st parameter - the name of class
36 - 2nd parameter - object
37 - 3rd parameter - the name of do/redo method
38 - 4th parameter - the name of undo method
39 Since redo,undo methods are the same, undo name can be omitted, e.g.
40~~~ {.cpp}
41 TQCommand *com = new TQCommand("TH1", hpx, "SetFillColor(Color_t)");
42~~~
43 For objects derived from TObject class name can be omitted, e.g.
44~~~ {.cpp}
45 TQCommand *com = new TQCommand(hpx, "SetFillColor(Color_t)");
46~~~
47
482. Setting undo, redo parameters.
49~~~ {.cpp}
50 Color_t old_color = hpx->GetFillColor();
51 Color_t new_color = 4; // blue color
52
53 com->SetRedoArgs(1, new_color);
54 com->SetUndoArgs(1, old_color);
55~~~
56 1st argument - the number of undo, redo parameters
57 the other arguments - undo, redo values
58 Since the number of undo,redo parameters is the same one can use
59~~~ {.cpp}
60 com->SetArgs(1, new_color, old_color);
61~~~
62
633. Undo, redo method execution
64~~~ {.cpp}
65 com->Redo(); // execute redo method
66 com->Undo(); // execute undo method
67~~~
68
694. Merged commands
70 It possible to group several commands together so an end user
71 can undo and redo them with one command.
72~~~ {.cpp}
73 TQCommand *update = new TQCommand(gPad, "Modified()");
74 com->Add(update);
75~~~
76
775. Macro commands
78 "Merging" allows to create macro commands, e.g.
79~~~ {.cpp}
80 TQCommand *macro = new TQCommand("my macro");
81 macro->Add(com1);
82 macro->Add(com2);
83 ...
84~~~
85 During Redo operation commands composing macro command are executed
86 sequentially in direct order (first in first out). During Undo,
87 they are executed in reverse order (last in first out).
88
896. Undo manager.
90 TQUndoManager is recorder of undo and redo operations. This is
91 command history list which can be traversed backwards and upwards
92 performing undo and redo operations.
93 To register command TQUndoManager::Add(TObject*) method is used.
94~~~ {.cpp}
95 TQUndoManager *history = new TQUndoManager();
96 history->Add(com);
97~~~
98 TQUndoManager::Add automatically invokes execution of command's Redo method.
99
100Use TQUndoManager::Undo to undo commands in history list.
101Redo is Undo for undo action. Use TQUndoManager::Redo method for that
102*/
103
104#include "TQCommand.h"
105#include "TQConnection.h"
106#include "TDataType.h"
107#include "stdarg.h"
108#include "TROOT.h"
109#include "ThreadLocalStorage.h"
110#include "TVirtualRWMutex.h"
111
114
115static TQCommand *gActiveCommand = nullptr;
116
117////////////////////////////////////////////////////////////////////////////////
118/// Common protected method used in several constructors
119
120void TQCommand::Init(const char *clname, void *obj, const char *redo, const char *undo)
121{
122 TString credo( CompressName(redo) );
123 TString cundo( CompressName(undo) );
124
125 fNRargs = fNUargs = -1;
127 fObject = obj;
128
129 fRedo = redo ? new TQConnection(clname, obj, credo) : nullptr;
130 fUndo = undo ? new TQConnection(clname, obj, cundo) : fRedo;
131
132 fRedoArgs = nullptr;
133 fUndoArgs = nullptr;
134 fStatus = 0;
135 fState = 0;
136
137 if (!obj && !redo && !undo) { // macros
138 fName = clname;
139 }
140}
141
142////////////////////////////////////////////////////////////////////////////////
143/// Constructor.
144///
145/// Input parameters:
146/// 1. clname - class name.
147/// 2. obj - an object
148/// 3. redo - method or function to do/redo operation
149/// 4. undo - method or function to undo operation
150///
151/// Comments:
152/// - if either clname or obj is NULL that means that redo/undo is function
153/// - to specify default arguments for redo/undo method/function
154/// '=' must precede to argument value.
155///
156/// Example:
157/// ~~~ {.cpp}
158/// TQCommand("TPad", gPad, "SetEditable(=kTRUE)", "SetEditable(=kFALSE)");
159/// ~~~
160/// undo method can be same as redo one. In that case undo parameter
161/// can be omitted.
162///
163/// Example:
164/// ~~~ {.cpp}
165/// TQCommand("TPad", gPad, "SetFillStyle(Style_t)");
166/// ~~~
167
168TQCommand::TQCommand(const char *clname, void *obj, const char *redo,
169 const char *undo) : TList(), TQObject()
170{
171 Init(clname, obj, redo, undo);
172}
173
174////////////////////////////////////////////////////////////////////////////////
175/// Constructor.
176///
177/// Input parameters:
178/// 1. obj - an object
179/// 2. redo - method or function to do/redo operation
180/// 3. undo - method or function to undo operation
181///
182/// Comments:
183/// to specify default arguments for redo/undo method/function
184/// '=' must precede to argument value.
185///
186/// Example:
187/// ~~~ {.cpp}
188/// TQCommand(gPad, "SetEditable(=kTRUE)", "SetEditable(=kFALSE)");
189/// ~~~
190///
191/// undo method can be same as redo one. In that case "undo"
192/// can parameter be omitted.
193///
194/// Example:
195/// ~~~ {.cpp}
196/// TQCommand(gPad, "SetFillStyle(Style_t)");
197/// ~~~
198
199TQCommand::TQCommand(TObject *obj, const char *redo, const char *undo) :
200 TList(), TQObject()
201{
202 if (obj) Init(obj->ClassName(), obj, redo, undo);
203 else Init(nullptr, nullptr, redo, undo);
204}
205
206////////////////////////////////////////////////////////////////////////////////
207/// Copy constructor.
208
210{
211 fRedo = new TQConnection(*(com.fRedo));
212 fUndo = new TQConnection(*(com.fUndo));
213
214 fRedoArgs = nullptr;
215 fUndoArgs = nullptr;
216 fNRargs = com.fNRargs;
217 fNUargs = com.fNUargs;
218
219 if (fNRargs > 0) {
220 fRedoArgs = new Long_t[fNRargs];
221 for (int i = 0; i< fNRargs; i++) {
222 fRedoArgs[i] = com.fRedoArgs[i];
223 }
224 }
225 if (fNUargs > 0) {
226 fUndoArgs = new Long_t[fNUargs];
227 for (int i = 0; i < fNUargs; i++) {
228 fUndoArgs[i] = com.fUndoArgs[i];
229 }
230 }
231 fStatus = com.fStatus;
233 fName = com.fName;
234 fTitle = com.fTitle;
235 fObject = com.fObject;
236 fState = com.fState;
237
238 // copy merged commands
239 TIter next(&com);
240 TQCommand *obj;
241 while ((obj = (TQCommand*)next())) {
242 TList::Add(new TQCommand(*obj));
243 }
244}
245
246////////////////////////////////////////////////////////////////////////////////
247/// dtor.
248
250{
251 if (fRedo != fUndo) delete fUndo;
252
253 delete fRedo;
254 delete [] fRedoArgs;
255 delete [] fUndoArgs;
256
257 Delete();
258}
259
260////////////////////////////////////////////////////////////////////////////////
261/// Return a command which is doing redo/undo action.
262///
263/// This static method allows to set undo parameters dynamically, i.e.
264/// during execution of Redo function.
265///
266/// Example:
267/// For redo actions like TGTextEdit::DelChar() it is not possible to
268/// know ahead what character will be deleted.
269/// To set arguments for undo action ( e.g. TGTextEdit::InsChar(char)),
270/// one needs to call TQCommand::SetUndoArgs(1, character) from
271/// inside of TGTextEdit::DelChar() method, i.e.
272/// ~~~ {.cpp}
273/// TQCommand::GetCommand()->SetUndoArgs(1, somechar);
274/// ~~~
275
277{
278 return gActiveCommand;
279}
280
281////////////////////////////////////////////////////////////////////////////////
282/// If "opt" is not zero delete every merged command which option string is
283/// equal to "opt". If "opt" is zero - delete all merged commands.
284
286{
287 if (!opt) {
289 return;
290 }
291
292 auto lnk = fFirst;
293 decltype(lnk) sav;
294
295 while (lnk) {
296 sav = lnk->NextSP();
297 TString ostr = lnk->GetOption();
298 if (ostr.Contains(opt)) { // remove command
299 TObject *obj = lnk->GetObject();
300 lnk->SetObject(nullptr);
301 delete obj;
302 Remove(lnk);
303 }
304 lnk = sav;
305 }
306}
307
308////////////////////////////////////////////////////////////////////////////////
309/// Two commands can be merged if they can be composed into
310/// a single command (Macro command).
311///
312/// To allow merging commands user might override this function.
313
315{
316 return (!fRedo && !fUndo);
317}
318
319////////////////////////////////////////////////////////////////////////////////
320/// Add command to the list of merged commands.
321/// This make it possible to group complex actions together so an end user
322/// can undo and redo them with one command. Execution of TQUndoManager::Undo(),
323/// TQUndoManager::Redo() methods only invokes the top level command as a whole.
324///
325/// Merge method is analogous to logical join operation.
326///
327/// Note: Merge method invokes redo action.
328
330{
331 Add(c, "merge");
332}
333
334////////////////////////////////////////////////////////////////////////////////
335/// Merge a collection of TQCommand.
336
338{
339 TIter next(collection);
340 while (TObject* o = next()) {
341 TQCommand *command = dynamic_cast<TQCommand*> (o);
342 if (!command) {
343 Error("Merge",
344 "Cannot merge - an object which doesn't inherit from TQCommand found in the list");
345 return -1;
346 }
347 Merge(command);
348 }
349 return GetEntries();
350}
351
352////////////////////////////////////////////////////////////////////////////////
353/// Add command to the list of merged commands.
354///
355/// Option string can contain substrings:
356/// - "compress" - try to compress input command
357/// - "radd" - execute redo action of input command
358/// - "uadd" - execute undo action of input command
359
361{
362 if (!obj->InheritsFrom(TQCommand::Class())) return;
363
364 TQCommand *o = (TQCommand *)obj;
365 TQCommand *c = (TQCommand *)Last();
366 TString ostr = opt;
367
368 if (c) {
369 if (c->CanCompress(o) || (c->IsEqual(o) && ostr.Contains("compress"))) {
370 c->Compress(o);
371 return;
372 }
373 }
374 TList::AddLast(o, opt);
375 if (o->CanRedo() && ostr.Contains("radd")) o->Redo();
376 if (o->CanUndo() && ostr.Contains("uadd")) o->Undo();
377}
378
379////////////////////////////////////////////////////////////////////////////////
380/// By default, commands can be compressed if they are:
381///
382/// - equal
383/// - setter commands
384///
385/// More complicated commands might want to override this function.
386
388{
389 return (IsEqual(c) && IsSetter());
390}
391
392////////////////////////////////////////////////////////////////////////////////
393/// Compress command. Compression is analogous to arithmetic "addition operation".
394///
395/// Note:
396/// - The compressed command will be deleted.
397/// - Execution Compress method invokes Redo action with new redo arguments
398/// inherited from compressed command.
399///
400/// More complicated commands might want to override this function.
401
403{
404 for (int i = 0; i < fNRargs; i++) {
405 fRedoArgs[i] = c->fRedoArgs[i];
406 }
407 Redo();
408 fStatus--; //do not change the state of command
409 delete c;
410}
411
412////////////////////////////////////////////////////////////////////////////////
413/// Equal comparison. The commands are equal if they are
414/// applied to the same object and have the same Redo/Undo actions
415///
416/// More complicated commands might want to override this function.
417
419{
420 if (!obj->InheritsFrom(TQCommand::Class())) return kFALSE;
421 TQCommand *c = (TQCommand *)obj;
422 if (!fRedo || !fUndo || (c->GetObject() != fObject)) return kFALSE;
423
425 TString rname = fRedo->GetName();
426
427 return ((cname == c->GetRedo()->GetClassName()) &&
428 (rname == c->GetRedo()->GetName()));
429}
430
431////////////////////////////////////////////////////////////////////////////////
432/// Returns kTRUE is command if Redo is the same as Undo function
433/// and is the setter action.
434///
435/// By default, all functions with names like "SetXXX" or "setXXX"
436/// considered as setters. Another type of setters are Move, Resize operations
437///
438/// More complicated commands might want to override this function.
439
441{
442 TString redo = GetRedoName();
443 TString undo = GetUndoName();
444
445 if (!redo || !undo || (redo != undo)) return kFALSE;
446
447 return (redo.BeginsWith("Set") ||
448 redo.BeginsWith("set") ||
449 redo.BeginsWith("Move") ||
450 redo.BeginsWith("move") ||
451 redo.BeginsWith("Resize") ||
452 redo.BeginsWith("resize"));
453}
454
455////////////////////////////////////////////////////////////////////////////////
456/// Set do/redo and undo parameters. The format is
457/// SetArgs(number_of_params, redo_params, undo_params)
458///
459/// Example:
460/// ~~~ {.cpp}
461/// move_command->SetArgs(2, 100, 100, 200, 200);
462/// ~~~
463/// 2 params, (100,100) - do/redo position, (200,200) - undo position
464
466{
467 if (narg < 0) {
468 return;
469 } else if (!narg) { // no arguments
470 fNRargs = fNUargs = narg;
471 return;
472 }
473
474 va_list ap;
475 va_start(ap, narg);
476
477 if (fNRargs != narg ) {
478 delete [] fRedoArgs;
479 }
480 fRedoArgs = new Long_t[narg];
481
482 if (fNUargs != narg ) {
483 delete [] fUndoArgs;
484 }
485 fUndoArgs = new Long_t[narg];
486
487 fNRargs = fNUargs = narg;
488
489 Int_t i;
490 for (i = 0; i < fNRargs; i++) {
491 fRedoArgs[i] = va_arg(ap, Long_t);
492 }
493 for (i = 0; i < fNUargs; i++) {
494 fUndoArgs[i] = va_arg(ap, Long_t);
495 }
496 va_end(ap);
497}
498
499////////////////////////////////////////////////////////////////////////////////
500/// Set redo parameters. The format is
501/// SetRedoArgs(number_of_params, params)
502///
503/// Example:
504/// ~~~ {.cpp}
505/// move_command->SetRedoArgs(2, 100, 100);
506/// ~~~
507
509{
510 if (narg < 0) {
511 return;
512 } else if (!narg) { // no arguments
513 fNRargs = 0;
514 return;
515 }
516
517 va_list ap;
518 va_start(ap, narg);
519
520 if (fNRargs != narg ) {
521 delete [] fRedoArgs;
522 }
523 fRedoArgs = new Long_t[narg];
524
525 fNRargs = narg;
526
527 for (int i = 0; i < fNRargs; i++) {
528 fRedoArgs[i] = va_arg(ap, Long_t);
529 }
530 va_end(ap);
531}
532
533////////////////////////////////////////////////////////////////////////////////
534/// Set undo parameters. The format is
535/// SetUndoArgs(number_of_params, params)
536///
537/// Example:
538/// ~~~ {.cpp}
539/// move_command->SetUndoArgs(2, 200, 200);
540/// ~~~
541
543{
544 if (narg < 0) {
545 return;
546 } else if (!narg) { // no arguments
547 fNUargs = narg;
548 return;
549 }
550
551 va_list ap;
552 va_start(ap, narg);
553
554 if (fNUargs != narg ) {
555 delete [] fUndoArgs;
556 }
557 fUndoArgs = new Long_t[narg];
558
559 fNUargs = narg;
560
561 for (int i = 0; i < fNUargs; i++) {
562 fUndoArgs[i] = va_arg(ap, Long_t);
563 }
564 va_end(ap);
565}
566
567////////////////////////////////////////////////////////////////////////////////
568/// Returns kTRUE if Redo action is possible, kFALSE if it's not.
569/// By default, only single sequential redo action is possible.
570
572{
573 return (fStatus <= 0);
574}
575
576////////////////////////////////////////////////////////////////////////////////
577/// Returns kTRUE if Undo action is possible, kFALSE if it's not.
578/// By default, only single trial undo action is possible.
579
581{
582 return (fStatus > 0);
583}
584
585////////////////////////////////////////////////////////////////////////////////
586/// Execute command and then merge commands
587
589{
590 Bool_t done = kFALSE;
591 fState = 1;
592
593 gActiveCommand = this;
594
595 if (fNRargs > 0) {
596 if (fRedo) {
598 done = kTRUE;
599 }
600 } else if (!fNRargs) {
601 if (fRedo) {
603 done = kTRUE;
604 }
605 }
606
607 // execute merged commands
608 auto lnk = fFirst;
609 while (lnk) {
610 TQCommand *c = (TQCommand *)lnk->GetObject();
611 c->Redo();
612 done = kTRUE;
613 lnk = lnk->NextSP();
614 }
615
616 if (done) Emit("Redo()");
617 fStatus++;
618 fState = 0;
619 gActiveCommand = nullptr;
620}
621
622////////////////////////////////////////////////////////////////////////////////
623/// Un-execute all merged commands and the command.
624/// Merged commands are executed in reverse order.
625
627{
628 Bool_t done = kFALSE;
629 fState = -1;
630
631 gActiveCommand = this;
632
633 // unexecute merged commands
634 auto lnk = fLast;
635 while (lnk) {
636 TQCommand *c = (TQCommand *)lnk->GetObject();
637 TString opt = lnk->GetOption();
638 auto sav = lnk->PrevSP();
639 c->Undo();
640 done = kTRUE;
641 if (opt.Contains("remove")) { // remove command
642 delete lnk->GetObject();
643 Remove(lnk);
644 }
645 lnk = sav;
646 }
647 if (fNUargs > 0) {
648 if (fUndo) {
650 done = kTRUE;
651 }
652 } else if (!fNUargs) {
653 if (fUndo) {
655 done = kTRUE;
656 }
657 }
658
659 if (done) Emit("Undo()");
660 fStatus--;
661 fState = 0;
662 gActiveCommand = nullptr;
663}
664
665////////////////////////////////////////////////////////////////////////////////
666/// Returns the command name. Default name is "ClassName::RedoName(args)"
667/// If list of merged commands is not empty the name is
668/// "ClassName::RedoName(args):cname1:cname2 ..."
669
670const char *TQCommand::GetName() const
671{
672 const Int_t maxname = 100;
673
674 if (!fName.IsNull())
675 return fName.Data();
676
678
679 // In case another thread already did the work while
680 // we were waiting.
681 if (!fName.IsNull())
682 return fName.Data();
683
685
686 if (fRedo) {
687 if (fRedo->GetClassName()) {
689 }
690 name += "::";
691 name += fRedo->GetName();
692 }
693 TQCommand *c;
694 TObjLink *lnk = fFirst.get();
695
696 while (lnk && (fName.Length() < maxname)) {
697 c = (TQCommand *)lnk->GetObject();
698 name += ":";
699 name += c->GetName();
700 lnk = lnk->Next();
701 }
702
703 TQCommand *m = const_cast<TQCommand*>(this);
704 m->fName = name;
705
706 return fName;
707}
708
709////////////////////////////////////////////////////////////////////////////////
710/// Returns command description.
711/// By default, "ClassName::RedoName(args)_ClassName::UndoName(args)"
712
713const char *TQCommand::GetTitle() const
714{
715 if (!fTitle.IsNull())
716 return fTitle.Data();
717
718 if (fUndo) {
719 TTHREAD_TLS_DECL_ARG(TString, title, GetName());
720
721 title += "_";
722 title += fUndo->GetClassName();
723 title += "::";
724 if (fUndo->GetName())
725 title += fUndo->GetName();
726
727 return title.Data();
728 } else {
729 return GetName();
730 }
731}
732
733////////////////////////////////////////////////////////////////////////////////
734/// Returns the name of redo command
735
736const char *TQCommand::GetRedoName() const
737{
738 return (fRedo ? fRedo->GetName() : nullptr);
739}
740
741////////////////////////////////////////////////////////////////////////////////
742/// Returns the name of undo command
743
744const char *TQCommand::GetUndoName() const
745{
746 return (fUndo ? fUndo->GetName() : nullptr);
747}
748
749////////////////////////////////////////////////////////////////////////////////
750/// Returns a pointer to array of redo arguments
751
753{
754 return fRedoArgs;
755}
756
757////////////////////////////////////////////////////////////////////////////////
758/// Returns a pointer to array of undo arguments
759
761{
762 return fUndoArgs;
763}
764
765////////////////////////////////////////////////////////////////////////////////
766/// Returns a number of redo arguments
767
769{
770 return fNRargs;
771}
772
773////////////////////////////////////////////////////////////////////////////////
774/// Returns a number of undo arguments
775
777{
778 return fNUargs;
779}
780
781////////////////////////////////////////////////////////////////////////////////
782/// Returns an object for which undo redo actions are applied
783
785{
786 return fObject;
787}
788
789////////////////////////////////////////////////////////////////////////////////
790/// Returns a number of sequential undo or redo operations
791
793{
794 return fStatus;
795}
796
797////////////////////////////////////////////////////////////////////////////////
798/// Returns kTRUE if neither redo nor undo action specified
799
801{
802 return (!fRedo && !fUndo);
803}
804
805////////////////////////////////////////////////////////////////////////////////
806/// Undo action is in progress
807
809{
810 return (fState < 0);
811}
812
813////////////////////////////////////////////////////////////////////////////////
814/// Redo action is in progress
815
817{
818 return (fState > 0);
819}
820
821////////////////////////////////////////////////////////////////////////////////
822/// Returns kTRUE if command execution is in progress
823
825{
826 return fState;
827}
828
829////////////////////////////////////////////////////////////////////////////////
830/// Sets name of the command
831
832void TQCommand::SetName(const char *name)
833{
834 fName = name;
835}
836
837////////////////////////////////////////////////////////////////////////////////
838/// Sets description of the command
839
840void TQCommand::SetTitle(const char *title)
841{
842 fTitle = title;
843}
844
845////////////////////////////////////////////////////////////////////////////////
846/// ls this command and merged commands
847
849{
850 TString name = GetName();
851 printf("%d %s\n", fStatus, name.Data());
852
853 TObjLink *lnk = fFirst.get();
854 while (lnk) {
855 printf("\t");
856 lnk->GetObject()->ls();
857 lnk = lnk->Next();
858 }
859}
860
861////////////////////////////////////////////////////////////////////////////////
862/// Print collection header.
863
865{
867 printf("%d %s\n", fStatus, GetName());
868}
869
870/** \class TQUndoManager
871Recorder of operations for undo and redo
872*/
873
874////////////////////////////////////////////////////////////////////////////////
875/// Constructor
876
877TQUndoManager::TQUndoManager() : TQCommand(nullptr, nullptr, nullptr, nullptr)
878{
879 fCursor = nullptr;
880 fLimit = kMaxUInt; // maximum value for UInt_t
882 fLogBook = nullptr;
883 fCurrent = nullptr;
884}
885
886////////////////////////////////////////////////////////////////////////////////
887/// Destructor
888
890{
891 Delete();
892
893 if (fLogBook) {
894 delete fLogBook;
895 }
896}
897
898////////////////////////////////////////////////////////////////////////////////
899/// Lists all commands in stack
900
902{
903 if (!IsEmpty()) {
904 TObjLink *lnk = fFirst.get();
905 while (lnk) {
906 if (lnk == fCursor) {
907 printf("->");
908 } else {
909 printf(" ");
910 }
911 TQCommand *com = (TQCommand*)lnk->GetObject();
912 com->ls(option);
913 lnk = lnk->Next();
914 }
915 }
916}
917
918////////////////////////////////////////////////////////////////////////////////
919/// Print collection entry.
920
922 Int_t /*recurse*/) const
923{
924 TQCommand *com = (TQCommand*) entry;
926 if (fCursor && fCursor->GetObject() == entry) {
927 printf("->");
928 } else {
929 printf(" ");
930 }
931 com->ls(option);
932}
933
934////////////////////////////////////////////////////////////////////////////////
935/// Start logging. Delete all previous log records
936/// Note: logging is not implemented yet
937
939{
940 fLogging = on;
941
942 if (fLogging) {
943 if (fLogBook) {
944 fLogBook->Delete();
945 } else {
946 fLogBook = new TList();
947 }
948 }
949}
950
951////////////////////////////////////////////////////////////////////////////////
952/// Add command to the stack of commands.
953/// Command's redo action will be executed.
954///
955/// option string can contain the following substrings:
956/// - "merge" - input command will be merged
957/// - "compress" - input command will be compressed
958
960{
961 if (!obj->InheritsFrom(TQCommand::Class())) return;
962
963 TQCommand *o = (TQCommand *)obj;
964 TQCommand *c;
965 Bool_t onredo = fCursor && fCursor->Next();
966 TString ostr = onredo ? "1radd" : "0radd"; // execute redo on add
967 if (opt) ostr += opt;
968
969 if (fState) { // undo/redo in progress
970 c = fCurrent;
971 if (c) {
972 fCurrent = o;
973 c->Add(o, "remove"); // add nested command
974 }
975 return;
976 }
977
978 // delete all commands after cursor position
979 if (fCursor && fCursor->Next()) {
980 TObjLink *lnk = fCursor->Next();
981 TObjLink *sav;
982 while (lnk) {
983 sav = lnk->Next();
984 delete lnk->GetObject();
985 Remove(lnk);
986 lnk = sav;
987 }
988 }
989
990 c = GetCursor();
991 if (c) {
992 if (c->CanCompress(o) || c->CanMerge(o) ||
993 ostr.Contains("merge") || ostr.Contains("compress")) {
994 fState = 1;
995 c->Add(o, ostr.Data());
996 fState = 0;
997 return;
998 }
999 }
1000
1001 TList::AddLast(obj, ostr.Data());
1002 fCursor = fLast.get();
1003 Redo(ostr.Data());
1004
1005 if ((fSize > 0) && ((UInt_t)fSize > fLimit)) {
1006 Remove(fFirst);
1007 }
1008}
1009
1010////////////////////////////////////////////////////////////////////////////////
1011/// emit signal
1012
1014{
1015 Emit("CurrentChanged(TQCommand*)", (Longptr_t)c);
1016}
1017
1018////////////////////////////////////////////////////////////////////////////////
1019/// Performs undo action. Move cursor position backward in history stack
1020
1022{
1023 Bool_t done = kFALSE;
1024 if (!CanUndo()) return;
1025
1026 TQCommand *sav = fCurrent;
1028
1029 if (c->CanUndo()) {
1030 fState = -1;
1031 fCurrent = c;
1033 fState = 0;
1034 done = kTRUE;
1035 fCursor = fCursor->Prev() ? fCursor->Prev() : fFirst.get();
1036 } else {
1037 fCursor = fCursor->Prev();
1039 fState = -1;
1041 fState = 0;
1042 done = kTRUE;
1043 }
1044 if (done && fLogging && fLogBook) {
1046 }
1047 if (sav != fCurrent) CurrentChanged(fCurrent);
1048}
1049
1050////////////////////////////////////////////////////////////////////////////////
1051/// Performs redo action. Move cursor position forward in history stack
1052
1054{
1055 Bool_t done = kFALSE;
1056 if (!CanRedo()) return;
1057
1058 TQCommand *sav = fCurrent;
1060
1061 if (c->CanRedo()) {
1062 fState = 1;
1063 fCurrent = c;
1065 fState = 0;
1066 done = kTRUE;
1067 fCursor = fCursor->Next() ? fCursor->Next() : fLast.get();
1068 } else {
1069 fCursor = fCursor->Next();
1071 fState = 1;
1073 fState = 0;
1074 done = kTRUE;
1075 }
1076 if (done && fLogging && fLogBook) {
1078 }
1079 if (sav != fCurrent) CurrentChanged(fCurrent);
1080}
1081
1082////////////////////////////////////////////////////////////////////////////////
1083/// Returns kTRUE if redo action is possible
1084
1086{
1087 if (!fCursor) return kFALSE;
1088
1090 if (c->CanRedo()) return kTRUE;
1091
1092 c = fCursor->Next() ? (TQCommand*)fCursor->Next()->GetObject() : nullptr;
1093 return (c && c->CanRedo());
1094}
1095
1096////////////////////////////////////////////////////////////////////////////////
1097/// Returns kTRUE if undo action is possible
1098
1100{
1101 if (!fCursor) return kFALSE;
1102
1104 if (c->CanUndo()) return kTRUE;
1105
1106 c = fCursor->Prev() ? (TQCommand*)fCursor->Prev()->GetObject() : nullptr;
1107 return (c && c->CanUndo());
1108}
1109
1110////////////////////////////////////////////////////////////////////////////////
1111/// Returns kTRUE if logging is ON
1112
1114{
1115 return fLogging;
1116}
1117
1118////////////////////////////////////////////////////////////////////////////////
1119/// Returns the last executed command
1120
1122{
1123 return fCurrent;
1124}
1125
1126////////////////////////////////////////////////////////////////////////////////
1127/// Returns a command correspondent to the current cursor position in stack
1128
1130{
1131 return (TQCommand*)(fCursor ? fCursor->GetObject() : nullptr);
1132}
1133
1134////////////////////////////////////////////////////////////////////////////////
1135/// Returns a maximum number of commands which could be located in stack
1136
1138{
1139 fLimit = limit;
1140}
1141
1142////////////////////////////////////////////////////////////////////////////////
1143/// Returns a maximum number of commands which could be located in stack
1144
1146{
1147 return fLimit;
1148}
#define c(i)
Definition RSha256.hxx:101
long Longptr_t
Definition RtypesCore.h:82
long Long_t
Definition RtypesCore.h:54
constexpr UInt_t kMaxUInt
Definition RtypesCore.h:111
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
long long Long64_t
Definition RtypesCore.h:80
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char cname
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void on
char name[80]
Definition TGX11.cxx:110
static TQCommand * gActiveCommand
#define R__WRITE_LOCKGUARD(mutex)
Collection abstract base class.
Definition TCollection.h:65
virtual Int_t GetEntries() const
virtual Bool_t IsEmpty() const
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:822
void AddLast(TObject *obj) override
Add object at the end of the list.
Definition TList.cxx:152
TObject * Last() const override
Return the last object in the list. Returns 0 when list is empty.
Definition TList.cxx:693
TObjLinkPtr_t fLast
pointer to first entry in linked list
Definition TList.h:47
TObjLinkPtr_t fFirst
Definition TList.h:46
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
TList()
Definition TList.h:72
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition TObject.cxx:574
The Command design pattern is based on the idea, that all editing in an application is done by creati...
Definition TQCommand.h:27
Bool_t IsRedoing() const
Redo action is in progress.
virtual void SetArgs(Int_t nargs,...)
Set do/redo and undo parameters.
virtual void Undo(Option_t *option="")
Un-execute all merged commands and the command.
virtual Bool_t CanCompress(TQCommand *c) const
By default, commands can be compressed if they are:
TString fName
Definition TQCommand.h:41
virtual Bool_t CanMerge(TQCommand *c) const
Two commands can be merged if they can be composed into a single command (Macro command).
virtual void SetRedoArgs(Int_t nargs,...)
Set redo parameters.
Int_t GetNUargs() const
Returns a number of undo arguments.
TQCommand(const char *cl=nullptr, void *object=nullptr, const char *redo=nullptr, const char *undo=nullptr)
Constructor.
Long_t * GetRedoArgs() const
Returns a pointer to array of redo arguments.
Int_t fState
Definition TQCommand.h:38
void Delete(Option_t *option="") override
If "opt" is not zero delete every merged command which option string is equal to "opt".
Int_t fStatus
Definition TQCommand.h:39
virtual Bool_t CanRedo() const
Returns kTRUE if Redo action is possible, kFALSE if it's not.
virtual Bool_t CanUndo() const
Returns kTRUE if Undo action is possible, kFALSE if it's not.
Long_t * fUndoArgs
Definition TQCommand.h:35
void Add(TObject *obj, Option_t *opt) override
Add command to the list of merged commands.
const char * GetUndoName() const
Returns the name of undo command.
virtual Bool_t IsSetter() const
Returns kTRUE is command if Redo is the same as Undo function and is the setter action.
const char * GetRedoName() const
Returns the name of redo command.
Int_t fNRargs
Definition TQCommand.h:36
virtual void Compress(TQCommand *c)
Compress command.
const char * GetName() const override
Returns the command name.
virtual void SetUndoArgs(Int_t nargs,...)
Set undo parameters.
virtual void SetName(const char *name)
Sets name of the command.
Int_t fNUargs
Definition TQCommand.h:37
Bool_t IsUndoing() const
Undo action is in progress.
void * fObject
Definition TQCommand.h:43
TQConnection * fRedo
Definition TQCommand.h:32
virtual void Merge(TQCommand *c)
Add command to the list of merged commands.
static TClass * Class()
void * GetObject() const
Returns an object for which undo redo actions are applied.
virtual ~TQCommand()
dtor.
virtual void Init(const char *cl, void *object, const char *redo, const char *undo)
Common protected method used in several constructors.
Bool_t IsExecuting() const
Returns kTRUE if command execution is in progress.
TString fTitle
Definition TQCommand.h:42
TQConnection * fUndo
Definition TQCommand.h:33
void PrintCollectionHeader(Option_t *option) const override
Print collection header.
const char * GetTitle() const override
Returns command description.
Bool_t IsEqual(const TObject *obj) const override
Equal comparison.
Long_t * fRedoArgs
Definition TQCommand.h:34
Int_t GetStatus() const
Returns a number of sequential undo or redo operations.
virtual void Redo(Option_t *option="")
Execute command and then merge commands.
Bool_t fNewDelete
Definition TQCommand.h:40
Bool_t IsMacro() const
Returns kTRUE if neither redo nor undo action specified.
Long_t * GetUndoArgs() const
Returns a pointer to array of undo arguments.
static TQCommand * GetCommand()
Return a command which is doing redo/undo action.
Int_t GetNRargs() const
Returns a number of redo arguments.
virtual void SetTitle(const char *title)
Sets description of the command.
void ls(Option_t *option="") const override
ls this command and merged commands
TQConnection class is an internal class, used in the object communication mechanism.
const char * GetClassName() const
const char * GetName() const override
Returns name of connection (aka name of slot)
void ExecuteMethod(Int_t nargs, va_list va)=delete
This is the ROOT implementation of the Qt object communication mechanism (see also http://www....
Definition TQObject.h:48
static TString CompressName(const char *method_name)
Removes "const" words and blanks from full (with prototype) method name and resolve any typedefs in t...
Definition TQObject.cxx:98
void Emit(const char *signal, const T &arg)
Activate signal with single parameter.
Definition TQObject.h:164
Recorder of operations for undo and redo.
Definition TQCommand.h:103
Bool_t fLogging
Definition TQCommand.h:110
virtual ~TQUndoManager()
Destructor.
Bool_t CanUndo() const override
Returns kTRUE if undo action is possible.
void ls(Option_t *option="") const override
Lists all commands in stack.
TList * fLogBook
Definition TQCommand.h:109
TQUndoManager()
Constructor.
UInt_t GetLimit() const
Returns a maximum number of commands which could be located in stack.
UInt_t fLimit
Definition TQCommand.h:108
void Redo(Option_t *option="") override
Performs redo action. Move cursor position forward in history stack.
Bool_t IsLogging() const
Returns kTRUE if logging is ON.
TQCommand * GetCursor() const
Returns a command correspondent to the current cursor position in stack.
TQCommand * GetCurrent() const
Returns the last executed command.
void Add(TObject *obj, Option_t *opt) override
Add command to the stack of commands.
void PrintCollectionEntry(TObject *entry, Option_t *option, Int_t recurse) const override
Print collection entry.
Bool_t CanRedo() const override
Returns kTRUE if redo action is possible.
void Undo(Option_t *option="") override
Performs undo action. Move cursor position backward in history stack.
virtual void SetLogging(Bool_t on=kTRUE)
Start logging.
TObjLink * fCursor
Definition TQCommand.h:106
virtual void CurrentChanged(TQCommand *c)
emit signal
virtual void SetLimit(UInt_t limit)
Returns a maximum number of commands which could be located in stack.
TQCommand * fCurrent
Definition TQCommand.h:107
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:2870
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:421
const char * Data() const
Definition TString.h:380
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:627
Bool_t IsNull() const
Definition TString.h:418
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:636
R__EXTERN TVirtualRWMutex * gCoreMutex
TMarker m
Definition textangle.C:8