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