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