Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TRecorder.cxx
Go to the documentation of this file.
1// @(#)root/gui:$Id$
2// Author: Katerina Opocenska 11/09/2008
3
4/*************************************************************************
5* Copyright (C) 1995-2008, 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
13/** \class TRecorder
14 \ingroup guirecorder
15
16Class provides direct recorder/replayer interface for a user.
17See 'ROOT EVENT RECORDING SYSTEM' for more information about usage.
18
19Implementation uses C++ design pattern State. Functionality of
20recorder is divided into 4 classes according to the current
21state of recorder.
22
23Internally, there is a pointer to TRecorderState object.
24This object changes whenever state of recorder is changed.
25States of recorder are the following:
26
27 - INACTIVE Implemented in TRecorderInactive class.
28 Default state after TRecorder object is created.
29
30 - RECORDING Implemented in TRecorderRecording class.
31
32 - REPLAYING Implemented in TRecorderReplaying class.
33
34 - PAUSED Implemented in TRecorderPause class.
35 Pause of replaying.
36
37Every command for TRecorder is just passed
38to TRecordeState object.
39Depending on the current state of recorder, this command is passed
40to some of the above mentioned classes and if valid, handled there.
41
42
43Switching between states is not possible from outside. States are
44switched directly by state objects via:
45
46ChangeState(TRecorderState* newstate, Bool_t deletePreviousState);
47
48When recorder is switched to a new state, the old state object is
49typically deleted. The only exception is switching from REPLAYING
50state to PAUSED state. The previous state (REPLAYING) is not
51deleted in order to be used again after TRecorder::Resume call.
52
53### STATE TRANSITIONS:
54
55 - INACTIVE -> RECORDING via TRecorder::Start (Starts recording)
56 - RECORDING -> INACTIVE via TRecorder::Stop (Stops recording)
57
58 - INACTIVE -> REPLAYING via TRecorder::Replay (Starts replaying)
59 - REPLAYING -> INACTIVE via TRecorder::ReplayStop (Stops replaying)
60
61 - REPLAYING -> PAUSED via TRecorder::Pause (Pause replaying)
62 - PAUSED -> REPLAYING via TRecorder::Resume (Resumes replaying)
63
64 - PAUSED -> INACTIVE via TRecorder::ReplayStop (Stops paused replaying)
65
66*/
67
68
69#include "TRecorder.h"
70
71#include "TROOT.h"
72#include "TFile.h"
73#include "TTimer.h"
74#include "TTree.h"
75#include "TSystem.h"
76#include "TMutex.h"
77#include "TGButton.h"
78#include "TGFileDialog.h"
79#include "TGLabel.h"
80#include "TGWindow.h"
81#include "Buttons.h"
82#include "TKey.h"
83#include "TPaveLabel.h"
84#include "TLatex.h"
85#include "TVirtualDragManager.h"
86#include "TGPicture.h"
87#include "KeySymbols.h"
88#include "TVirtualX.h"
89
90#include <iomanip>
91
92// Names of ROOT GUI events. Used for listing event logs.
93const char *kRecEventNames[] = {
94 "KeyPress",
95 "KeyRelease",
96 "ButtonPress",
97 "ButtonRelease",
98 "MotionNotify",
99 "EnterNotify",
100 "LeaveNotify",
101 "FocusIn",
102 "FocusOut",
103 "Expose",
104 "ConfigureNotify",
105 "MapNotify",
106 "UnmapNotify",
107 "DestroyNotify",
108 "ClientMessage",
109 "SelectionClear",
110 "SelectionRequest",
111 "SelectionNotify",
112 "ColormapNotify",
113 "ButtonDoubleClick",
114 "OtherEvent"
115};
116
117// Names of TTrees in the TFile with recorded events
118const char *kCmdEventTree = "CmdEvents"; // Name of TTree with commandline events
119const char *kGuiEventTree = "GuiEvents"; // Name of TTree with GUI events
120const char *kWindowsTree = "WindowsTree"; // Name of TTree with window IDs
121const char *kExtraEventTree = "ExtraEvents"; // Name of TTree with extra events (PaveLabels and Texts)
122const char *kBranchName = "MainBranch"; // Name of the main branch in all TTrees
123
124
125
126//_____________________________________________________________________________
127//
128// TGCursorWindow
129//
130// Window used as fake mouse cursor wile replaying events.
131//_____________________________________________________________________________
132
133class TGCursorWindow : public TGFrame {
134
135protected:
136 Pixmap_t fPic, fMask; // Pixmaps used as Window shape
137
138public:
140 ~TGCursorWindow() override;
141};
142
146
147////////////////////////////////////////////////////////////////////////////////
148/// TGCursorWindow constructor.
149
151 TGFrame(gClient->GetDefaultRoot(), 32, 32, kTempFrame)
152{
154 const TGPicture *pbg = fClient->GetPicture("recursor.png");
155 fPic = pbg->GetPicture();
156 fMask = pbg->GetMask();
157
158 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
160
162 wattr.fSaveUnder = kTRUE;
163 wattr.fOverrideRedirect = kTRUE;
164
165 gVirtualX->ChangeWindowAttributes(fId, &wattr);
166}
167
168////////////////////////////////////////////////////////////////////////////////
169/// Destructor.
170
174
175////////////////////////////////////////////////////////////////////////////////
176/// Creates initial INACTIVE state for the recorder
177
183
184////////////////////////////////////////////////////////////////////////////////
185/// Creates a recorder with filename to replay or to record,
186/// depending on option (NEW or RECREATE will start recording,
187/// READ will start replaying)
188
190{
191 TString opt(option);
192 fFilename = "";
194 if ((opt == "NEW") || (opt == "RECREATE"))
196 else
198}
199
200////////////////////////////////////////////////////////////////////////////////
201/// Destructor.
202
204{
205 delete fRecorderState;
206}
207
208////////////////////////////////////////////////////////////////////////////////
209/// Browse the recorder from a ROOT file. This allows to replay a
210/// session from the browser.
211
216
217////////////////////////////////////////////////////////////////////////////////
218/// Starts recording events
219
225
226////////////////////////////////////////////////////////////////////////////////
227/// Stopps recording events
228
233
234////////////////////////////////////////////////////////////////////////////////
235/// Replays events from 'filename'
236
242
243////////////////////////////////////////////////////////////////////////////////
244/// Pauses replaying
245
247{
248 fRecorderState->Pause(this);
249}
250
251////////////////////////////////////////////////////////////////////////////////
252/// Resumes replaying
253
255{
256 fRecorderState->Resume(this);
257}
258
259////////////////////////////////////////////////////////////////////////////////
260/// Cancels replaying
261
266
267////////////////////////////////////////////////////////////////////////////////
268/// Prints out recorded commandline events
269
271{
273}
274
275////////////////////////////////////////////////////////////////////////////////
276/// Prints out recorded GUI events
277
279{
281}
282
283////////////////////////////////////////////////////////////////////////////////
284/// Changes state from the current to the passed one (newstate)
285/// Deletes the old state if delPreviousState = KTRUE
286
294
295////////////////////////////////////////////////////////////////////////////////
296/// Get current state of recorder.
297
302
303
304////////////////////////////////////////////////////////////////////////////////
305/// Save previous canvases in a .root file
306
311
312//______________________________________________________________________________
313// Represents state of TRecorder when replaying
314
315
316////////////////////////////////////////////////////////////////////////////////
317/// Allocates all necessary data structures used for replaying
318/// What is allocated here is deleted in destructor
319
321{
322 fCanv = 0;
323 fCmdTree = 0;
324 fCmdTreeCounter = 0;
326 fExtraTree = 0;
329 fGuiTree = 0;
330 fGuiTreeCounter = 0;
331 fNextEvent = 0;
332 fRecorder = 0;
333 fRegWinCounter = 0;
336 fWin = 0;
337 fWinTree = 0;
338 fWinTreeEntries = 0;
340 fCmdEvent = new TRecCmdEvent();
341 fGuiEvent = new TRecGuiEvent();
343 fWindowList = new TList();
344 fTimer = new TTimer();
345 fMutex = new TMutex(kFALSE);
346 if (!gCursorWin)
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Closes all signal-slot connections
352/// Frees all memory allocated in constructor.
353
355{
356 fTimer->Disconnect(fTimer, "Timeout()", this, "ReplayRealtime()");
357 fTimer->TurnOff();
358 // delete fTimer;
359
360 gClient->Disconnect(gClient, "RegisteredWindow(Window_t)", this,
361 "RegisterWindow(Window_t)");
362
363 if (fFile) {
364 fFile->Close();
365 delete fFile;
366 }
367
368 delete fWindowList;
369 delete fCmdEvent;
370 delete fGuiEvent;
371 delete fExtraEvent;
372 delete fMutex;
373 if (gCursorWin)
374 gCursorWin->DeleteWindow();
375 gCursorWin = 0;
376}
377
378////////////////////////////////////////////////////////////////////////////////
379/// Initialization of data structures for replaying.
380/// Start of replaying.
381///
382/// Return value:
383/// - kTRUE = everything is OK and replaying has begun
384/// - kFALSE = non existing or invalid log file, replaying has not started
385
388{
389 fWin = 0;
390 fGuiTreeCounter = 0;
391 fCmdTreeCounter = 0;
393 fRegWinCounter = 0;
394 fRecorder = 0;
395
397
399
400 fEventReplayed = 1;
401
402 fRecorder = r;
404
405 if (!fFile || fFile->IsZombie() || !fFile->IsOpen())
406 return kFALSE;
407
412
413 if (!fCmdTree || !fWinTree || ! fGuiTree || ! fExtraTree) {
414 Error("TRecorderReplaying::Initialize",
415 "The ROOT file is not valid event logfile.");
416 return kFALSE;
417 }
418
419 try {
424 }
425 catch(...) {
426 Error("TRecorderReplaying::Initialize",
427 "The ROOT file is not valid event logfile");
428 return kFALSE;
429 }
430
431 // No event to replay in given ROOT file
432 if (!PrepareNextEvent()) {
433 Info("TRecorderReplaying::Initialize",
434 "Log file empty. No event to replay.");
435 return kFALSE;
436 }
437
438 // Number of registered windows during recording
440
441 // When a window is registered during replaying,
442 // TRecorderReplaying::RegisterWindow(Window_t) is called
443 gClient->Connect("RegisteredWindow(Window_t)", "TRecorderReplaying",
444 this, "RegisterWindow(Window_t)");
445
446 Info("TRecorderReplaying::Initialize", "Replaying of file %s started",
447 fFile->GetName());
448
450 if (f && !f->IsZombie()) {
451 TIter nextkey(f->GetListOfKeys());
452 TKey *key;
453 TObject *obj;
454 while ((key = (TKey*)nextkey())) {
456 obj = key->ReadObj();
457 if (!obj->InheritsFrom("TCanvas"))
458 continue;
459 fCanv = (TCanvas*) obj;
460 fCanv->Draw();
461 }
462 TCanvas *canvas;
463 TIter nextc(gROOT->GetListOfCanvases());
464 while ((canvas = (TCanvas*)nextc())) {
465 canvas->SetWindowSize(canvas->GetWindowWidth(),
466 canvas->GetWindowHeight());
467 }
469 f->Close();
470 }
471
472 gPad = nullptr;
473 // Starts replaying
474 fTimer->Connect("Timeout()","TRecorderReplaying",this,"ReplayRealtime()");
475 fTimer->Start(0);
476
477 return kTRUE;
478}
479
480////////////////////////////////////////////////////////////////////////////////
481/// Creates mapping for the newly registered window w and adds this
482/// mapping to fWindowList
483///
484/// Called by signal whenever a new window is registered during replaying.
485///
486/// The new window ID is mapped to the old one with the same number in the
487/// list of registered windows.
488/// It means that 1st new window is mapped to the 1st original,
489/// 2nd to the 2nd, Nth new to the Nth original.
490
492{
493 if (fFilterStatusBar) {
494 TGWindow *win = gClient->GetWindowById(w);
495 if (win) {
496 if (win->GetParent()->InheritsFrom("TGStatusBar")) {
498 return;
499 }
500 }
501 }
502
503 // Get original window ID that was registered as 'fRegWinCounter'th
506 }
507 else {
508 // More windows registered when replaying then when recording.
509 // Cannot continue
510 Error("TRecorderReplaying::RegisterWindow",
511 "More windows registered than expected");
512 //ReplayStop(fRecorder);
513 return;
514 }
515
516 if ((gDebug > 0) && (fWaitingForWindow)) {
517 std::ios::fmtflags f = std::cout.flags(); // store flags
518 std::cout << " Window registered: new ID: " << std::hex << w <<
519 " previous ID: " << fWin << std::dec << std::endl;
520 std::cout.flags( f ); // restore flags (reset std::hex)
521 }
522
523 // Lock mutex for guarding access to fWindowList
524 fMutex->Lock();
525
526 // Increases counter of registered windows
528
529 // Creates new mapping of original window (fWin) and a new one (w)
530 TRecWinPair *ids = new TRecWinPair(fWin, w);
531 // Saves the newly created mapping
532 fWindowList->Add(ids);
533
534 // If we are waiting for this window to be registered
535 // (Replaying was stopped because of that)
537
538 if (gDebug > 0) {
539 std::ios::fmtflags f = std::cout.flags(); // store flags
540 std::cout << " Window " << std::hex << fGuiEvent->fWindow <<
541 " registered." << std::dec << std::endl;
542 std::cout.flags( f ); // restore flags (reset std::hex)
543 }
544
546 // Sets that we do not wait for this window anymore
548
549 // Start replaying of events again
550 fTimer->Start(25);
551 }
552 fMutex->UnLock();
553}
554
555////////////////////////////////////////////////////////////////////////////////
556/// All references to the old windows (IDs) in fNextEvent are replaced by
557/// new ones according to the mappings in fWindowList
558
560{
561 // Lock mutex for guarding access to fWindowList
562 fMutex->Lock();
563
564 TRecWinPair *ids;
566
567 Bool_t found = kFALSE;
568
569 // Iterates through the whole list of mappings
570 while ((ids = (TRecWinPair*)it.Next())) {
571 // Window that the event belongs to
572 if (!found && fGuiEvent->fWindow == 0) {
573 fGuiEvent->fWindow = gVirtualX->GetDefaultRootWindow();
574 found = kTRUE;
575 }
576 else if (!found && ids->fKey == fGuiEvent->fWindow) {
577 fGuiEvent->fWindow = ids->fValue;
578 found = kTRUE;
579 }
580 for (Int_t i = 0; i < 5; ++i) {
581 if ((Long_t) ids->fKey == fGuiEvent->fUser[i])
582 fGuiEvent->fUser[i] = ids->fValue;
583 }
584 if (fGuiEvent->fMasked && ids->fKey == fGuiEvent->fMasked) {
585 fGuiEvent->fMasked = ids->fValue;
586 }
587 }
588
589 if (!found && fGuiEvent->fWindow == 0) {
590 fGuiEvent->fWindow = gVirtualX->GetDefaultRootWindow();
591 found = kTRUE;
592 }
593 // Mapping for the event found
594 if (found) {
595 fMutex->UnLock();
596 return kTRUE;
597 }
598
599 if (gDebug > 0) {
600 // save actual formatting flags
601 std::ios_base::fmtflags org_flags = std::cout.flags();
602 std::cout << "fGuiTreeCounter = " << std::dec << fGuiTreeCounter <<
603 " No mapping found for ID " << std::hex << fGuiEvent->fWindow << std::endl;
605 // restore original formatting flags
606 std::cout.flags(org_flags);
607 }
608
609 // Stopps timer and waits for the appropriate window to be registered
610 fTimer->Stop();
612
613 fMutex->UnLock();
614 return kFALSE;
615}
616
617////////////////////////////////////////////////////////////////////////////////
618
620{
621 // Not all the recorded events are replayed.
622 // Some of them are generated automatically in ROOT
623 // as a consequence of other events.
624 //
625 // RETURN VALUE:
626 // - kTRUE = passed TRecGuiEvent *e should be filtered
627 // (should not be replayed)
628 // - kFALSE = passed TRecGuiEvent *e should not be filtered
629 // (should be replayed)
630
631 // We do not replay any client messages except closing of windows
632 if (e->fType == kClientMessage) {
633 if ((e->fFormat == 32) && (e->fHandle != TRecGuiEvent::kROOT_MESSAGE)
634 && ((Atom_t)e->fUser[0] == TRecGuiEvent::kWM_DELETE_WINDOW))
635 return kFALSE;
636 else
637 return kTRUE;
638 }
639
640 // See TRecorderRecording::SetTypeOfConfigureNotify to get know
641 // which kConfigureNotify events are filtered
642 if (e->fType == kConfigureNotify && e->fUser[4] == TRecGuiEvent::kCNFilter) {
643 return kTRUE;
644 }
645
646 if (e->fType == kOtherEvent) {
647 if (e->fFormat >= kGKeyPress && e->fFormat < kOtherEvent)
648 return kFALSE;
649 return kTRUE;
650 }
651
652 return kFALSE;
653}
654
655////////////////////////////////////////////////////////////////////////////////
656/// Finds the next event in log file to replay and sets it to fNextEvent
657///
658/// Reads both from CmdTree and GuiTree and chooses that event that becomes
659/// earlier
660/// - fCmdTreeCounter determines actual position in fCmdTree
661/// - fGuiTreeCounter determines actual position in fCmdTree
662///
663/// If GUI event should be replayed, we must first make sure that there is
664/// appropriate mapping for this event
665///
666/// RETURN VALUE:
667/// kFALSE = there is no event to be replayed
668/// kTRUE = there is still at least one event to be replayed. Cases:
669/// - fNextEvent = 0 => We are waiting for the appropriate
670/// window to be registered
671/// - fNextEvent != 0 => fNextEvent can be replayed (windows are
672/// ready)
673
675{
676 fCmdEvent = 0;
677 fGuiEvent = 0;
678 fExtraEvent = 0;
679 fNextEvent = 0;
680
681 // Reads the next unreplayed commandline event to fCmdEvent
684
685 // Reads the next unreplayed extra event to fExtraEvent
688
689 // Reads the next unreplayed GUI event to fGuiEvent
690 // Skips GUI events that should not be replayed (FilterEvent call)
691 while (fGuiTree->GetEntries() > fGuiTreeCounter) {
694 break;
696 }
697
698 // Chooses which one will be fNextEvent (the next event to be replayed)
699 if (fCmdEvent && fGuiEvent && fExtraEvent) {
700 // If there are all uf them, compares their times and chooses the
701 // earlier one
702 if ((fCmdEvent->GetTime() <= fGuiEvent->GetTime()) &&
705 else {
708 else
710 }
711 }
712 else if (fCmdEvent && fGuiEvent) {
713 // If there are both of them, compares their times and chooses the
714 // earlier one
715 if (fCmdEvent->GetTime() <= fGuiEvent->GetTime())
717 else
719 }
720 else if (fCmdEvent && fExtraEvent ) {
721 // If there are both of them, compares their times and chooses the
722 // earlier one
725 else
727 }
728 else if (fGuiEvent && fExtraEvent) {
729 // If there are both of them, compares their times and chooses the
730 // earlier one
733 else
735 }
736
737 // Nor commandline neither event to replay
738 else if (!fCmdEvent && !fGuiEvent && !fExtraEvent)
739 fNextEvent = 0;
740 // Only GUI event to replay
741 else if (fGuiEvent)
743 // Only commandline event to replay
744 else if (fCmdEvent)
746 else
748
749 // Nothing to replay
750 if (fNextEvent == 0)
751 return kFALSE;
752
753 // Commandline event to replay
754 if (fNextEvent == fCmdEvent)
756
757 // Extra event to replay
758 if (fNextEvent == fExtraEvent)
760
761 // GUI event to replay
762 if (fNextEvent == fGuiEvent) {
763 // We have the new window to send this event to
766 // We do not have it yet (waiting for registration)
767 else
768 fNextEvent = 0;
769 }
770 return kTRUE;
771}
772
773////////////////////////////////////////////////////////////////////////////////
774/// ButtonPress and ButtonRelease must be sometimes replayed more times
775/// Example: pressing of a button opens small window and user chooses
776/// something from that window (color)
777/// Window must be opened while user is choosing
778
780{
781 if (!fGuiEvent) {
782 Error("TRecorderReplaying::CanOverlap()", "fGuiEvent = 0");
783 return kFALSE;
784 }
785
786 // only GUI events overlapping is allowed
788 return kFALSE;
789
790
791 if (gDebug > 0) {
792 std::cout << "Event overlapping " <<
793 kRecEventNames[((TRecGuiEvent*)fNextEvent)->fType] << std::endl;
795 }
796
797 // GUI event
799
800 // Overlapping allowed for ButtonPress, ButtonRelease and MotionNotify
801 if (e->fType == kButtonPress || e->fType == kButtonRelease ||
802 e->fType == kMotionNotify)
803 return kTRUE;
804
805 return kFALSE;
806}
807
808////////////////////////////////////////////////////////////////////////////////
809/// Replays the next event.
810///
811/// It is called when fTimer times out.
812/// Every time fTimer is set again to time equal to time difference between
813/// current two events being replayed.
814///
815/// It can happen that execution of an event lasts different time during the
816/// recording and during the replaying.
817/// If fTimer times out too early and the previous event has not been yet
818/// replayed, it is usually postponed in order
819/// to keep events execution in the right order.
820/// The exceptions are determined by TRecorderReplaying::CanOverlap()
821///
822
824{
826 char str[2];
827
828 if ((gROOT->GetEditorMode() == kText) ||
829 (gROOT->GetEditorMode() == kPaveLabel)){
830 gROOT->SetEditorMode();
831 }
832
833 // If there are automatically generated ROOT events in the queue, they
834 // are let to be handled first
835 if (gVirtualX->EventsPending()) {
837 return;
838 }
839
840 // Previous event has not been replayed yet and it is not allowed for
841 // this event to be replayed more times
842 if (!fEventReplayed && !CanOverlap())
843 return;
844
845 // Event to replay prepared
846 if (fNextEvent) {
847 // Sets that fNextEvent has not been replayed yet
848 fEventReplayed = 0;
849
850 // Remembers its execution time to compute time difference with
851 // the next event
853
854 // Special execution of events causing potential deadlocks
857 if (ev->fType == kGKeyPress && ev->fState & kKeyControlMask) {
858 Event_t *e = ev->CreateEvent(ev);
859 gVirtualX->LookupString(e, str, sizeof(str), keysym);
860 // catch the ctrl-s event
861 if ((keysym & ~0x20) == kKey_S) {
862 fEventReplayed = 1;
864 ev->ReplayEvent(fShowMouseCursor);
865 return;
866 }
867 }
868 }
869
870 // REPLAYS CURRENT EVENT
872
873 // Sets that fNextEvent has been replayed
874 fEventReplayed = 1;
875 }
876
877 // Prepares new event for replaying
878 if (!PrepareNextEvent()) {
879 // No more events to be replayed (replaying has finished).
880
881 // Switches recorder back to INACTIVE state
882 Info("TRecorderReplaying::ReplayRealtime", "Replaying finished");
884 return;
885 }
886 else {
887 // We have event to replay here.
888
889 // It will be replayed with the same time difference to the previous
890 // one as when recording.
891 // After given time, timer will call this method again
892 if (fNextEvent)
894 }
895}
896
897////////////////////////////////////////////////////////////////////////////////
898/// Pauses replaying
899
901{
902 fTimer->Stop();
903 r->ChangeState(new TRecorderPaused(this), kFALSE);
904 Info("TRecorderReplaying::Pause", "Replaying paused.");
905}
906
907////////////////////////////////////////////////////////////////////////////////
908/// Cancels replaying
909
911{
912 Info("TRecorderReplaying::ReplayStop", "Replaying cancelled");
913 r->ChangeState(new TRecorderInactive());
914}
915
916////////////////////////////////////////////////////////////////////////////////
917/// Continues previously paused replaying
918
924
925//______________________________________________________________________________
926// Represents state of TRecorder after its creation
927
928
929////////////////////////////////////////////////////////////////////////////////
930/// Switches from INACTIVE state to RECORDING and starts recording
931
934{
935 // const char *filename = name of ROOT file where to store recorded events
936 // Option_t *option = option for creation of ROOT file
937 // Window_t *w = list of IDs of recorder windows (if GUI for
938 // recorder is used) [0 by default]
939 // Int_t winCount = number of IDs it this list [0 by default]
940
942 if (rec->StartRecording()) {
943 r->ChangeState(rec);
944 r->fFilename = gSystem->BaseName(filename);
945 }
946 else
947 delete rec;
948}
949
950////////////////////////////////////////////////////////////////////////////////
951/// Switches from INACTIVE state of recorder to REPLAYING
952/// Return kTRUE if replaying has started or kFALSE if it is not possible
953/// (bad file etc.)
954
958{
959 // const char *filename = name of ROOT file from where to replay recorded
960 // events
961 // TRecorder::EReplayModes mode = mode of replaying
962
964
965 if (replay->Initialize(r, showMouseCursor, mode)) {
966 r->ChangeState(replay);
967 r->fFilename = gSystem->BaseName(filename);
968 return kTRUE;
969 }
970 else {
971 delete replay;
972 return kFALSE;
973 }
974}
975
976////////////////////////////////////////////////////////////////////////////////
977/// Prints out commandline events recorded in given file
978
980{
981 /*
982 if (!TClassTable::GetDict(" TRecCmdEvent")) {
983 Error("TRecorderInactive::List", " TRecCmdEvent not in dictionary.");
984 return;
985 }*/
986
987 TFile *file = TFile::Open(filename);
988 if (!file) return;
989 if (file->IsZombie() || !file->IsOpen()) {
990 delete file;
991 return;
992 }
993 TTree *t1 = (TTree*)file->Get(kCmdEventTree);
994
995 if (!t1) {
996 Error("TRecorderInactive::List",
997 "The ROOT file is not valid event logfile.");
998 delete file;
999 return;
1000 }
1001
1002 TRecCmdEvent *fCmdEvent = new TRecCmdEvent();
1003 t1->SetBranchAddress(kBranchName, &fCmdEvent);
1004
1005 Int_t entries = t1->GetEntries();
1006 for (Int_t i = 0; i < entries; ++i) {
1007 t1->GetEntry(i);
1008 std::cout << "[" << i << "] " << "fTime=" <<
1009 (ULong64_t) fCmdEvent->GetTime() << " fText=" <<
1010 fCmdEvent->GetText() << std::endl;
1011 }
1012 std::cout << std::endl;
1013
1014 delete fCmdEvent;
1015 delete file;
1016}
1017
1018////////////////////////////////////////////////////////////////////////////////
1019/// Prints out GUI events recorded in given file
1020
1022{
1023 /*
1024 if (!TClassTable::GetDict("TRecGuiEvent")) {
1025 Error("TRecorderInactive::ListGui",
1026 "TRecGuiEvent not in the dictionary.");
1027 return;
1028 }*/
1029
1030 TFile *file = TFile::Open(filename);
1031 if (!file) return;
1032 if (file->IsZombie() || !file->IsOpen()) {
1033 delete file;
1034 return;
1035 }
1036 TTree *t1 = (TTree*)file->Get(kGuiEventTree);
1037
1038 if (!t1) {
1039 Error("TRecorderInactive::ListGui",
1040 "The ROOT file is not valid event logfile.");
1041 delete file;
1042 return;
1043 }
1044
1046 t1->SetBranchAddress(kBranchName, &guiEvent);
1047
1048 Int_t entries = t1->GetEntries();
1049
1050 for (Int_t i = 0; i < entries ; ++i) {
1051 t1->GetEntry(i);
1053 }
1054
1055 delete file;
1056 delete guiEvent;
1057}
1058
1059////////////////////////////////////////////////////////////////////////////////
1060/// Prints out attributes of one GUI event TRecGuiEvent *e
1061/// Int_n n is number of event if called in cycle
1062
1064{
1065 std::ios::fmtflags f = std::cout.flags(); // store flags
1066 std::cout << "[" << n << "] " << std::dec << std::setw(10)
1067 << e->GetTime().AsString() << std::setw(15) << kRecEventNames[e->fType]
1068 << " fW:" << std::hex << e->fWindow
1069 << " t:" << std::dec << e->fTime
1070 << " x:" << DisplayValid(e->fX)
1071 << " y:" << DisplayValid(e->fY)
1072 << " fXR:" << DisplayValid(e->fXRoot)
1073 << " fYR:" << DisplayValid(e->fYRoot)
1074 << " c:" << DisplayValid(e->fCode)
1075 << " s:" << DisplayValid(e->fState)
1076 << " w:" << DisplayValid(e->fWidth)
1077 << " h:" << DisplayValid(e->fHeight)
1078 << " cnt:" << DisplayValid(e->fCount)
1079 << " se:" << e->fSendEvent
1080 << " h:" << e->fHandle
1081 << " fF:" << DisplayValid(e->fFormat)
1082 << " | ";
1083
1084 for (Int_t i=0; i<5; ++i)
1085 if (DisplayValid(e->fUser[i]) != -1)
1086 std::cout << "[" << i << "]=" << DisplayValid(e->fUser[i]);
1087
1088 if (e->fMasked)
1089 std::cout << " | fM:" << std::hex << e->fMasked;
1090
1091 std::cout << std::endl;
1092 std::cout.flags( f ); // restore flags (reset std::hex)
1093}
1094
1095////////////////////////////////////////////////////////////////////////////////
1096/// Save previous canvases in a .root file
1097
1099{
1100 fCollect = gROOT->GetListOfCanvases();
1102 if (f && !f->IsZombie()) {
1103 fCollect->Write();
1104 f->Close();
1105 delete f;
1106 }
1107}
1108
1109//______________________________________________________________________________
1110// Represents state of TRecorder when paused
1111
1112
1113////////////////////////////////////////////////////////////////////////////////
1114/// Remember the recorder state that is paused
1115
1120
1121////////////////////////////////////////////////////////////////////////////////
1122/// Continues replaying
1123
1125{
1127 Info("TRecorderPaused::Resume", "Replaying resumed");
1128
1129 // Switches back to the previous replaying state
1130 r->ChangeState(fReplayingState);
1131}
1132
1133////////////////////////////////////////////////////////////////////////////////
1134/// Replaying is cancelled
1135
1137{
1138 delete fReplayingState;
1139
1140 Info("TRecorderReplaying::ReplayStop", "Replaying cancelled");
1141 r->ChangeState(new TRecorderInactive());
1142}
1143
1144
1145//______________________________________________________________________________
1146// Represents state of TRecorder when recording events
1147
1148
1149////////////////////////////////////////////////////////////////////////////////
1150/// Initializes TRecorderRecording for recording
1151/// What is allocated here is deleted in destructor
1152
1156{
1157 fRecorder = r;
1158 fBeginPave = 0;
1159
1160 // Remember window IDs of GUI recorder (appropriate events are
1161 // filtered = not recorded)
1164 for(Int_t i=0; i < fFilteredIdsCount; ++i)
1165 fFilteredIds[i] = w[i];
1166
1167 // No unhandled commandline event in the beginning
1169
1170 // Filer pave events (mouse button move)
1172
1173 // No registered windows in the beginning
1174 fRegWinCounter = 0;
1175
1176 // New timer for recording
1177 fTimer = new TTimer(25, kTRUE);
1178
1179 fMouseTimer = new TTimer(50, kTRUE);
1180 fMouseTimer->Connect("Timeout()", "TRecorderRecording", this,
1181 "RecordMousePosition()");
1182
1183 // File where store recorded events
1185
1186 // TTrees with windows, commandline events and GUi events
1187 fWinTree = new TTree(kWindowsTree, "Windows");
1188 fCmdTree = new TTree(kCmdEventTree, "Commandline events");
1189 fGuiTree = new TTree(kGuiEventTree, "GUI events");
1190 fExtraTree = new TTree(kExtraEventTree, "Extra events");
1191
1192 fWin = 0;
1193 fCmdEvent = new TRecCmdEvent();
1194 fGuiEvent = new TRecGuiEvent();
1196}
1197
1198////////////////////////////////////////////////////////////////////////////////
1199/// Freeing of allocated memory
1200
1202{
1203 delete[] fFilteredIds;
1204
1205 if (fFile)
1206 delete fFile;
1207 delete fMouseTimer;
1208 delete fTimer;
1209 delete fCmdEvent;
1210 delete fGuiEvent;
1211 delete fExtraEvent;
1212}
1213
1214////////////////////////////////////////////////////////////////////////////////
1215/// Connects appropriate signals and slots in order to gain all registered
1216/// windows and processed events in ROOT and then starts recording
1217
1219{
1220 if (!fFile || fFile->IsZombie() || !fFile->IsOpen())
1221 return kFALSE;
1222
1223 // When user types something in the commandline,
1224 // TRecorderRecording::RecordCmdEvent(const char *line) is called
1225 gApplication->Connect("LineProcessed(const char*)", "TRecorderRecording",
1226 this, "RecordCmdEvent(const char*)");
1227
1228 // When a new window in ROOT is registered,
1229 // TRecorderRecording::RegisterWindow(Window_t) is called
1230 gClient->Connect("RegisteredWindow(Window_t)", "TRecorderRecording", this,
1231 "RegisterWindow(Window_t)");
1232
1233 // When a GUI event (different from kConfigureNotify) is processed in
1234 // TGClient::HandleEvent or in TGClient::HandleMaskEvent,
1235 // TRecorderRecording::RecordGuiEvent(Event_t*, Window_t) is called
1236 gClient->Connect("ProcessedEvent(Event_t*, Window_t)", "TRecorderRecording",
1237 this, "RecordGuiEvent(Event_t*, Window_t)");
1238
1239 // When a kConfigureNotify event is processed in TGFrame::HandleEvent,
1240 // TRecorderRecording::RecordGuiCNEvent(Event_t*) is called
1241 TQObject::Connect("TGFrame", "ProcessedConfigure(Event_t*)",
1242 "TRecorderRecording", this, "RecordGuiCNEvent(Event_t*)");
1243
1244 // When a PaveLabel is created, TRecorderRecording::RecordPave(TObject*)
1245 // is called
1246 TQObject::Connect("TPad", "RecordPave(const TObject*)", "TRecorderRecording",
1247 this, "RecordPave(const TObject*)");
1248
1249 // When a Text is created, TRecorderRecording::RecordText() is called
1250 TQObject::Connect("TPad", "RecordLatex(const TObject*)",
1251 "TRecorderRecording", this, "RecordText(const TObject*)");
1252
1253 // When a PaveLabel is created, TRecorderRecording::FilterEventPave()
1254 // is called to filter mouse clicks events.
1255 TQObject::Connect("TPad", "EventPave()", "TRecorderRecording", this,
1256 "FilterEventPave()");
1257
1258 // When starting editing a TLatex or a TPaveLabel, StartEditing()
1259 // is called to memorize edition starting time.
1260 TQObject::Connect("TPad", "StartEditing()", "TRecorderRecording", this,
1261 "StartEditing()");
1262
1263 // Gui Builder specific events.
1264 TQObject::Connect("TGuiBldDragManager", "TimerEvent(Event_t*)",
1265 "TRecorderRecording", this, "RecordGuiBldEvent(Event_t*)");
1266
1267 // Creates in TTrees appropriate branches to store registered windows,
1268 // commandline events and GUI events
1269 fWinTree->Branch(kBranchName, &fWin, "fWin/l");
1270 fCmdTree->Branch(kBranchName, " TRecCmdEvent", &fCmdEvent);
1271 fGuiTree->Branch(kBranchName, "TRecGuiEvent", &fGuiEvent);
1272 fExtraTree->Branch(kBranchName, "TRecExtraEvent", &fExtraEvent);
1273
1274 Int_t numCanvases = gROOT->GetListOfCanvases()->LastIndex();
1275
1276 if (numCanvases >= 0){
1277
1278 TIter nextwindow (gClient->GetListOfWindows());
1279 TGWindow *twin;
1281 while ((twin = (TGWindow*) nextwindow())) {
1282 twin2 = (Window_t) twin->GetId();
1283 if (IsFiltered(twin2)) {
1284 if (gDebug > 0) {
1285 std::cout << "WindowID "<< twin2 << " filtered" << std::endl;
1286 }
1287 }
1288 else if (twin != gClient->GetRoot()) {
1290 }
1291 }
1292 //Info("TRecorderRecording::StartRecording", "Previous Canvases");
1293 }
1294
1295 // Starts the timer for recording
1296 fTimer->TurnOn();
1297
1298 // start mouse events recording timer
1299 fMouseTimer->Start(50);
1300
1301 Info("TRecorderRecording::StartRecording", "Recording started. Log file: %s",
1302 fFile->GetName());
1303
1304 return kTRUE;
1305}
1306
1307////////////////////////////////////////////////////////////////////////////////
1308/// Disconnects all slots and stopps recording.
1309
1311{
1312 TQObject::Disconnect("TGuiBldDragManager", "TimerEvent(Event_t*)", this,
1313 "RecordGuiBldEvent(Event_t*)");
1314 TQObject::Disconnect("TGFrame", "ProcessedConfigure(Event_t*)", this,
1315 "RecordGuiCNEvent(Event_t*)");
1316 TQObject::Disconnect("TPad", "RecordPave(const TObject*)", this,
1317 "RecordPave(const TObject*)");
1318 TQObject::Disconnect("TPad", "RecordLatex(const TObject*)", this,
1319 "RecordText(const TObject*)");
1320 TQObject::Disconnect("TPad", "EventPave()", this, "FilterEventPave()");
1321 TQObject::Disconnect("TPad", "StartEditing()", this, "StartEditing()");
1322 gClient->Disconnect(gClient, "ProcessedEvent(Event_t*, Window_t)", this,
1323 "RecordGuiEvent(Event_t*, Window_t)");
1324 gClient->Disconnect(gClient, "RegisteredWindow(Window_t)", this,
1325 "RegisterWindow(Window_t)");
1326 gApplication->Disconnect(gApplication, "LineProcessed(const char*)", this,
1327 "RecordCmdEvent(const char*)");
1328
1329 // Decides if to store the last event. It is stored if GUI recorder is used,
1330 // otherwise it is 'TEventRecorded::Stop' and should not be stored
1332 fCmdTree->Fill();
1333
1334 fRecorder->Write("recorder");
1335 fFile->Write();
1336 fFile->Close();
1337 fTimer->TurnOff();
1338
1340
1341 Info("TRecorderRecording::Stop", "Recording finished.");
1342
1344}
1345
1346////////////////////////////////////////////////////////////////////////////////
1347/// This method is called when RegisteredWindow(Window_t) is emitted from
1348/// TGClient.
1349
1351{
1352 // Stores ID of the registered window in appropriate TTree
1353 fWin = (ULong64_t) w;
1354 fWinTree->Fill();
1355}
1356
1357////////////////////////////////////////////////////////////////////////////////
1358/// Records commandline event (text and time) ans saves the previous
1359/// commandline event
1360/// This 1 event delay in saving ensures that the last commandline events
1361/// 'TRecorder::Stop' will be not stored
1362
1364{
1365 // If there is some previously recorded event, saves it in TTree now
1366 if (fCmdEventPending)
1367 fCmdTree->Fill();
1368
1369 // Fill information about this new commandline event: command text and
1370 // time of event execution
1372 fCmdEvent->SetText((char*)line);
1373
1374 // This event will be stored next time (if it is not the last one
1375 // 'TRecorder::Stop')
1377 return;
1378}
1379
1380////////////////////////////////////////////////////////////////////////////////
1381/// Records GUI Event_t *e different from kConfigureNotify (they are
1382/// recorded in TRecorderRecording::RecordGuiCNEvent)
1383///
1384/// It is called via signal-slot when an event is processed in
1385/// TGClient::HandleEvent(Event_t *event)
1386/// or in TGClient::HandleMaskEvent(Event_t *event, Window_t wid)
1387///
1388/// If signal is emitted from TGClient::HandleEvent(Event_t *event),
1389/// then wid = 0
1390
1392{
1393 // If this event is caused by a recorder itself (GUI recorder),
1394 // it is not recorded
1395 if (fFilteredIdsCount && IsFiltered(e->fWindow))
1396 return;
1397
1398 // Doesn't record the mouse clicks when a pavelabel is recorded
1399 if (fFilterEventPave && (e->fCode == 1)) {
1401 return;
1402 }
1404
1405 // don't record any copy/paste event, as event->fUser[x] parameters
1406 // will be invalid when replaying on a different OS
1407 if (e->fType == kSelectionClear || e->fType == kSelectionRequest ||
1408 e->fType == kSelectionNotify)
1409 return;
1410
1411 // Copies all items of e to fGuiEvent
1412 CopyEvent(e, wid);
1413
1414 // Saves time of recording
1416
1417 // Saves recorded event itself in TTree
1418 fGuiTree->Fill();
1419}
1420
1421////////////////////////////////////////////////////////////////////////////////
1422/// Special case for the gui builder, having a timer handling some of the
1423/// events.
1424
1426{
1427 e->fFormat = e->fType;
1428 e->fType = kOtherEvent;
1429
1430 // Copies all items of e to fGuiEvent
1431 CopyEvent(e, 0);
1432
1433 // Saves time of recording
1435
1436 // Saves recorded event itself in TTree
1437 fGuiTree->Fill();
1438}
1439
1440////////////////////////////////////////////////////////////////////////////////
1441/// Try to record all mouse moves...
1442
1444{
1445 Window_t dum;
1446 Event_t ev;
1447 ev.fCode = 0;
1448 ev.fType = kMotionNotify;
1449 ev.fState = 0;
1450 ev.fWindow = 0;
1451 ev.fUser[0] = ev.fUser[1] = ev.fUser[2] = ev.fUser[3] = ev.fUser[4] = 0;
1452 ev.fCount = 0;
1453 ev.fFormat = 0;
1454 ev.fHandle = 0;
1455 ev.fHeight = 0;
1456 ev.fSendEvent = 0;
1457 ev.fTime = 0;
1458 ev.fWidth = 0;
1459
1460 gVirtualX->QueryPointer(gVirtualX->GetDefaultRootWindow(), dum, dum,
1461 ev.fXRoot, ev.fYRoot, ev.fX, ev.fY, ev.fState);
1462 ev.fXRoot -= gDecorWidth;
1463 ev.fYRoot -= gDecorHeight;
1464
1465 RecordGuiEvent(&ev, 0);
1466 fMouseTimer->Reset();
1467}
1468
1469////////////////////////////////////////////////////////////////////////////////
1470/// Records GUI Event_t *e of type kConfigureNotify.
1471/// It is called via signal-slot when an kConfigureNotify event is processed
1472/// in TGFrame::HandleEvent
1473
1475{
1476 // If this event is caused by a recorder itself, it is not recorded
1477 if (fFilteredIdsCount && IsFiltered(e->fWindow))
1478 return;
1479
1480 // Sets fUser[4] value to one of EConfigureNotifyType
1481 // According to this value, event is or is not replayed in the future
1483
1484 // Copies all items of e to fGuiEvent
1485 CopyEvent(e, 0);
1486
1487 // Saves time of recording
1489
1490 // Saves recorded event itself in TTree
1491 fGuiTree->Fill();
1492}
1493
1494////////////////////////////////////////////////////////////////////////////////
1495/// Records TPaveLabel object created in TCreatePrimitives::Pave()
1496
1498{
1501 TPaveLabel *pavel = (TPaveLabel *) obj;
1502 const char *label;
1503 label = pavel->GetLabel();
1504 TString aux = "";
1505 TString cad = "";
1506 cad = "TPaveLabel *p = new TPaveLabel(";
1507 cad += pavel->GetX1();
1508 cad += ",";
1509 cad += pavel->GetY1();
1510 cad += ",";
1511 cad += pavel->GetX2();
1512 cad += ",";
1513 cad += pavel->GetY2();
1514 cad += ",\"\"); p->Draw(); gPad->Modified(); gPad->Update();";
1515 Int_t i, len = (Int_t)strlen(label);
1516 interval /= (len + 2);
1518 for (i=0; i < len; ++i) {
1519 cad = "p->SetLabel(\"";
1520 cad += (aux += label[i]);
1521 cad += "\"); ";
1522#ifndef R__WIN32
1523 cad += " p->SetTextFont(83); p->SetTextSizePixels(14); ";
1524#endif
1525 cad += " gPad->Modified(); gPad->Update();";
1528 }
1529 cad = "p->SetTextFont(";
1530 cad += pavel->GetTextFont();
1531 cad += "); p->SetTextSize(";
1532 cad += pavel->GetTextSize();
1533 cad += "); gPad->Modified(); gPad->Update();";
1536}
1537
1538////////////////////////////////////////////////////////////////////////////////
1539/// Records TLatex object created in TCreatePrimitives::Text()
1540
1542{
1545 TLatex *texto = (TLatex *) obj;
1546 const char *label;
1547 label = texto->GetTitle();
1548 TString aux = "";
1549 TString cad = "";
1550 cad = "TLatex *l = new TLatex(";
1551 cad += texto->GetX();
1552 cad += ",";
1553 cad += texto->GetY();
1554 cad += ",\"\"); l->Draw(); gPad->Modified(); gPad->Update();";
1555 Int_t i, len = (Int_t)strlen(label);
1556 interval /= (len + 2);
1558 for (i=0; i < len; ++i) {
1559 cad = "l->SetTitle(\"";
1560 cad += (aux += label[i]);
1561 cad += "\"); ";
1562#ifndef R__WIN32
1563 cad += " l->SetTextFont(83); l->SetTextSizePixels(14); ";
1564#endif
1565 cad += " gPad->Modified(); gPad->Update();";
1568 }
1569 cad = "l->SetTextFont(";
1570 cad += texto->GetTextFont();
1571 cad += "); l->SetTextSize(";
1572 cad += texto->GetTextSize();
1573 cad += "); gPad->Modified(); gPad->Update();";
1574 cad += " TVirtualPad *spad = gPad->GetCanvas()->GetSelectedPad();";
1575 cad += " gPad->GetCanvas()->Selected(spad, l, kButton1Down);";
1578}
1579
1580////////////////////////////////////////////////////////////////////////////////
1581/// Change the state of the flag to kTRUE when you are recording a pavelabel.
1582
1587
1588////////////////////////////////////////////////////////////////////////////////
1589/// Memorize the starting time of editinga TLatex or a TPaveLabel
1590
1595
1596////////////////////////////////////////////////////////////////////////////////
1597/// Records TLatex or TPaveLabel object created in TCreatePrimitives,
1598/// ExtTime is needed for the correct replay of these events.
1599
1606
1607////////////////////////////////////////////////////////////////////////////////
1608/// Copies all items of given event to fGuiEvent
1609
1611{
1612 fGuiEvent->fType = e->fType;
1613 fGuiEvent->fWindow = e->fWindow;
1614 fGuiEvent->fTime = e->fTime;
1615
1616 fGuiEvent->fX = e->fX;
1617 fGuiEvent->fY = e->fY;
1618 fGuiEvent->fXRoot = e->fXRoot;
1619 fGuiEvent->fYRoot = e->fYRoot;
1620
1621 fGuiEvent->fCode = e->fCode;
1622 fGuiEvent->fState = e->fState;
1623
1624 fGuiEvent->fWidth = e->fWidth;
1625 fGuiEvent->fHeight = e->fHeight;
1626
1627 fGuiEvent->fCount = e->fCount;
1628 fGuiEvent->fSendEvent = e->fSendEvent;
1629 fGuiEvent->fHandle = e->fHandle;
1630 fGuiEvent->fFormat = e->fFormat;
1631
1634
1635 for(Int_t i=0; i<5; ++i)
1636 fGuiEvent->fUser[i] = e->fUser[i];
1637
1640
1641 if (e->fType == kGKeyPress || e->fType == kKeyRelease) {
1642 char tmp[10] = {0};
1643 UInt_t keysym = 0;
1644 gVirtualX->LookupString(e, tmp, sizeof(tmp), keysym);
1646 }
1647
1649}
1650
1651////////////////////////////////////////////////////////////////////////////////
1652/// Returns kTRUE if passed id belongs to window IDs of recorder GUI itself
1653
1655{
1656 for(Int_t i=0; i < fFilteredIdsCount; ++i)
1657 if (id == fFilteredIds[i])
1658 return kTRUE;
1659
1660 return kFALSE;
1661}
1662
1663////////////////////////////////////////////////////////////////////////////////
1664/// Sets type of kConfigureNotify event to one of EConfigureNotify
1665///
1666/// On Linux parameters of GUI event kConfigureNotify are different
1667/// than parameters of the same event executed on Windows.
1668/// Therefore we need to distinguish [on Linux], if the event is movement
1669/// or resize event.
1670/// On Windows, we do not need to distinguish them.
1671
1673{
1674 // On both platforms, we mark the events matching the criteria
1675 // (automatically generated in ROOT) as events that should be filtered
1676 // when replaying (TRecGuiEvent::kCNFilter)
1677 if ((e->fX == 0 && e->fY == 0)) { // || e->fFormat == 32 ) {
1678 e->fUser[4] = TRecGuiEvent::kCNFilter;
1679 return;
1680 }
1681
1682#ifdef WIN32
1683
1684 // No need to distinguish between move and resize on Windows
1685 e->fUser[4] = TRecGuiEvent::kCNMoveResize;
1686
1687#else
1688
1689 TGWindow *w = gClient->GetWindowById(e->fWindow);
1690 if (w) {
1691 TGFrame *t = (TGFrame *)w;
1692
1693 // If this event does not cause any change in position or size ->
1694 // automatically generated event
1695 if (t->GetWidth() == e->fWidth && t->GetHeight() == e->fHeight &&
1696 e->fX == t->GetX() && e->fY == t->GetY()) {
1697 e->fUser[4] = TRecGuiEvent::kCNFilter;
1698 }
1699 else {
1700 // Size of the window did not change -> move
1701 if (t->GetWidth() == e->fWidth && t->GetHeight() == e->fHeight) {
1702 e->fUser[4] = TRecGuiEvent::kCNMove;
1703 }
1704 // Size of the window changed -> resize
1705 else {
1706 e->fUser[4] = TRecGuiEvent::kCNResize;
1707 }
1708 }
1709 }
1710
1711#endif
1712}
1713
1714
1715
1716//______________________________________________________________________________
1717// The GUI for the recorder
1718
1719
1720////////////////////////////////////////////////////////////////////////////////
1721/// The GUI for the recorder
1722
1724 TGMainFrame(p ? p : gClient->GetRoot(), w, h)
1725{
1729 fRecorder = new TRecorder();
1730 fFilteredIds[0] = GetId();
1731
1732 // Create a horizontal frame widget with buttons
1733 hframe = new TGHorizontalFrame(this, 200, 75, kChildFrame | kFixedHeight,
1734 (Pixel_t)0x000000);
1735 fFilteredIds[1] = hframe->GetId();
1736
1737 // LABEL WITH TIME
1738
1740 (Pixel_t)0x000000);
1741 fFilteredIds[2] = vframe->GetId();
1742
1743 TGLabel *fStatusLabel = new TGLabel(vframe, "Status:");
1744 fStatusLabel->SetTextColor(0x7cffff);
1745 fStatusLabel->SetBackgroundColor((Pixel_t)0x000000);
1747 2, 2, 2, 2));
1748 fFilteredIds[3] = fStatusLabel->GetId();
1749
1750 TGLabel *fTimeLabel = new TGLabel(vframe, "Time: ");
1751 fTimeLabel->SetTextColor(0x7cffff);
1752 fTimeLabel->SetBackgroundColor((Pixel_t)0x000000);
1754 2, 2, 13, 2));
1755 fFilteredIds[4] = fTimeLabel->GetId();
1756
1758
1760 (Pixel_t)0x000000);
1761 fFilteredIds[5] = vframe->GetId();
1762
1763 fStatus = new TGLabel(vframe, "Inactive");
1764 fStatus->SetTextColor(0x7cffff);
1767 2, 2, 2, 2));
1768 fFilteredIds[6] = fStatus->GetId();
1769
1770 fTimeDisplay = new TGLabel(vframe, "00:00:00");
1771 fTimeDisplay->SetTextColor(0x7cffff);
1772 fTimeDisplay->SetTextFont("Helvetica -34", kFALSE);
1775 2, 2, 2, 2));
1777
1779 10, 0, 0, 0));
1780 AddFrame(hframe, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
1781
1782 // Create a horizontal frame widget with buttons
1783 hframe = new TGHorizontalFrame(this, 200, 200);
1784 fFilteredIds[8] = hframe->GetId();
1785
1786 // START-STOP button
1787 fStartStop = new TGPictureButton(hframe,gClient->GetPicture("record.png"));
1788 fStartStop->SetStyle(gClient->GetStyle());
1789 fStartStop->Connect("Clicked()","TGRecorder",this,"StartStop()");
1791 2, 2, 2, 2));
1792 fStartStop->Resize(40,40);
1794
1795 // REPLAY button
1796 fReplay = new TGPictureButton(hframe,gClient->GetPicture("replay.png"));
1797 fReplay->SetStyle(gClient->GetStyle());
1798 fReplay->Connect("Clicked()","TGRecorder",this,"Replay()");
1800 2, 2, 2, 2));
1801 fReplay->Resize(40,40);
1802 fFilteredIds[10] = fReplay->GetId();
1803
1804 // MOUSE CURSOR CHECKBOX
1805 fCursorCheckBox = new TGCheckButton(this,"Show mouse cursor");
1808
1809 // Timer
1810 fTimer = new TTimer(25);
1811 fTimer->Connect("Timeout()", "TGRecorder", this, "Update()");
1812
1813 AddFrame(hframe, new TGLayoutHints(kLHintsCenterX, 2, 2, 2, 2));
1814
1816 SetWindowName("ROOT Event Recorder");
1817 MapSubwindows();
1818 Layout();
1819 MapWindow();
1820
1821 SetDefault();
1822}
1823
1824////////////////////////////////////////////////////////////////////////////////
1825/// Sets GUI to the default inactive state
1826
1828{
1829 fTimeDisplay->SetText("00:00:00");
1830
1831 fReplay->SetPicture(gClient->GetPicture("replay.png"));
1833
1836
1837 fStartStop->SetPicture(gClient->GetPicture("record.png"));
1839}
1840
1841////////////////////////////////////////////////////////////////////////////////
1842/// Called when fTimer timeouts (every 0.025 second)
1843/// Updates GUI of recorder
1844
1846{
1847 struct tm *running;
1848 static int cnt = 0;
1849 TString stime;
1850 time( &fElapsed );
1851 time_t elapsed_time = (time_t)difftime( fElapsed, fStart );
1853
1854 switch(fRecorder->GetState()) {
1855
1856 // When recording or replaying, updates timer
1857 // and displays new value of seconds counter
1860
1861 // Every whole second: updates timer and displays new value
1862 if (cnt >= 10) {
1864 fStatus->SetText("Replaying");
1865 else
1866 fStatus->SetText("Recording");
1867 stime.Form("%02d:%02d:%02d", running->tm_hour,
1868 running->tm_min, running->tm_sec);
1869 fTimeDisplay->SetText(stime.Data());
1870
1871 cnt = 0;
1872 if (gVirtualX->EventsPending()) {
1873 fStatus->SetText("Waiting...");
1874 fStatus->SetTextColor((Pixel_t)0xff0000);
1875 }
1876 else {
1877 fStatus->SetTextColor((Pixel_t)0x7cffff);
1878 }
1879 fStatus->Resize();
1881 }
1882 else
1883 ++cnt;
1884
1885 // Changes background color according to the queue of pending events
1886 fTimer->Reset();
1887 break;
1888
1889 // End of replaying or recording. Sets recorder GUI to default state
1891 fStatus->SetText("Inactive");
1892 fStatus->SetTextColor((Pixel_t)0x7cffff);
1893 fStatus->Resize();
1894 fTimer->TurnOff();
1895 SetDefault();
1896 break;
1897
1898 default:
1899 break;
1900 }
1901}
1902
1903////////////////////////////////////////////////////////////////////////////////
1904/// Handles push of the fStartStop button
1905/// according to the current recorder state
1906
1908{
1909 static const char *gFiletypes[] = {
1910 "All files", "*", "Text files", "*.txt", "ROOT files", "*.root", 0, 0
1911 };
1912 TGFileInfo fi;
1913
1914 switch(fRecorder->GetState()) {
1915
1916 // Starts recording
1918
1919 fi.fFileTypes = gFiletypes;
1920 fi.fOverwrite = kFALSE;
1921
1922 new TGFileDialog(gClient->GetDefaultRoot(),
1923 gClient->GetDefaultRoot(),
1924 kFDSave,&fi);
1925
1926 if (fi.fFilename && strlen(fi.fFilename)) {
1927
1928 if (!gROOT->GetListOfCanvases()->IsEmpty()) {
1929 fRecorder->PrevCanvases(fi.fFilename, "RECREATE");
1930 fRecorder->Start(fi.fFilename, "UPDATE", fFilteredIds,
1932 }
1933 else {
1934 fRecorder->Start(fi.fFilename, "RECREATE", fFilteredIds,
1936 }
1938 fStartStop->SetPicture(gClient->GetPicture("stop.png"));
1940 fTimer->TurnOn();
1941 time( &fStart );
1942 }
1943 break;
1944
1945 // Stops recording
1948 break;
1949
1950 // Pauses replaying
1952 fRecorder->Pause();
1953 fStartStop->SetPicture(gClient->GetPicture("replay.png"));
1954 break;
1955
1956 // Resumes replaying
1957 case TRecorder::kPaused:
1958 fRecorder->Resume();
1959 fStartStop->SetPicture(gClient->GetPicture("pause.png"));
1960 break;
1961
1962 default:
1963 break;
1964 } // switch
1965}
1966
1967////////////////////////////////////////////////////////////////////////////////
1968/// Handles push of fReplay button
1969/// according to the current recorder state
1970
1972{
1973 TGFileInfo fi;
1974
1975 switch(fRecorder->GetState()) {
1976
1977 // Starts replaying
1979
1980 new TGFileDialog(gClient->GetDefaultRoot(),
1981 gClient->GetDefaultRoot(),
1982 kFDOpen, &fi);
1983
1984 if (fi.fFilename && strlen(fi.fFilename)) {
1985 if (fRecorder->Replay(fi.fFilename, fCursorCheckBox->IsOn())) {
1986
1987 fTimer->TurnOn();
1988 time( &fStart );
1989
1990 fReplay->SetPicture(gClient->GetPicture("stop.png"));
1991 fStartStop->SetPicture(gClient->GetPicture("pause.png"));
1992
1993 if (fCursorCheckBox->IsOn())
1995
1997 }
1998 }
1999 break;
2000
2001 // Stops replaying
2003 case TRecorder::kPaused:
2005 break;
2006
2007 default:
2008 break;
2009
2010 } // switch
2011}
2012
2013////////////////////////////////////////////////////////////////////////////////
2014/// Destructor. Cleanup the GUI.
2015
2017{
2018 fTimer->TurnOff();
2019 delete fTimer;
2020 Cleanup();
2021}
2022
2023//______________________________________________________________________________
2024// Helper class
2025
2026
2027////////////////////////////////////////////////////////////////////////////////
2028/// Replays stored GUI event
2029
2031{
2032 Int_t px, py, dx, dy;
2034 Event_t *e = CreateEvent(this);
2035
2036 // don't try to replay any copy/paste event, as event->fUser[x]
2037 // parameters are invalid on different OSes
2038 if (e->fType == kSelectionClear || e->fType == kSelectionRequest ||
2039 e->fType == kSelectionNotify) {
2040 delete e;
2041 return;
2042 }
2043
2044 // Replays movement/resize event
2045 if (e->fType == kConfigureNotify) {
2046 TGWindow *w = gClient->GetWindowById(e->fWindow);
2047
2048 // Theoretically, w should always exist (we found the right mapping,
2049 // otherwise we would not get here).
2050 // Anyway, it can happen that it was destroyed by some earlier ROOT event
2051 // We give higher priority to automatically generated
2052 // ROOT events in TRecorderReplaying::ReplayRealtime.
2053
2054 if (w) {
2056 if (e->fUser[4] == TRecGuiEvent::kCNMove) {
2057 // Linux: movement of the window
2058 // first get window attribute to compensate the border size
2059 gVirtualX->GetWindowAttributes(e->fWindow, attr);
2060 if ((e->fX - attr.fX > 0) && (e->fY - attr.fY > 0))
2061 w->Move(e->fX - attr.fX, e->fY - attr.fY);
2062 }
2063 else {
2064 if (e->fUser[4] == TRecGuiEvent::kCNResize) {
2065 // Linux: resize of the window
2066 w->Resize(e->fWidth, e->fHeight);
2067 }
2068 else {
2069 if (e->fUser[4] == TRecGuiEvent::kCNMoveResize) {
2070 // Windows: movement or resize of the window
2071 w->MoveResize(e->fX, e->fY, e->fWidth, e->fHeight);
2072 }
2073 else {
2074 if (gDebug > 0)
2075 Error("TRecGuiEvent::ReplayEvent",
2076 "kConfigureNotify: Unknown value: fUser[4] = %ld ",
2077 e->fUser[4]);
2078 }
2079 }
2080 }
2081 }
2082 else {
2083 // w = 0
2084 if (gDebug > 0)
2085 Error("TRecGuiEvent::ReplayEvent",
2086 "kConfigureNotify: Window does not exist anymore ");
2087 }
2088 delete e;
2089 return;
2090
2091 } // kConfigureNotify
2092
2093 if (showMouseCursor && e->fType == kButtonPress) {
2094 gVirtualX->TranslateCoordinates(e->fWindow, gVirtualX->GetDefaultRootWindow(),
2095 e->fX, e->fY, px, py, wtarget);
2096 dx = px - gCursorWin->GetX();
2097 dy = py - gCursorWin->GetY();
2098 if (std::abs(dx) > 5) gDecorWidth += dx;
2099 if (std::abs(dy) > 5) gDecorHeight += dy;
2100 }
2101 // Displays fake mouse cursor for MotionNotify event
2102 if (showMouseCursor && e->fType == kMotionNotify) {
2103 if (gCursorWin && e->fWindow == gVirtualX->GetDefaultRootWindow()) {
2104 if (!gCursorWin->IsMapped()) {
2105 gCursorWin->MapRaised();
2106 }
2107 if (gVirtualX->GetDrawMode() == TVirtualX::kCopy) {
2108//#ifdef R__MACOSX
2109 // this may have side effects (e.g. stealing focus)
2110 gCursorWin->RaiseWindow();
2111//#endif
2112 gCursorWin->Move(e->fXRoot + gDecorWidth, e->fYRoot + gDecorHeight);
2113 }
2114 }
2115 }
2116
2117 // Lets all the other events to be handled the same way as when recording
2118 // first, special case for the gui builder, having a timer handling
2119 // some of the events
2120 if (e->fType == kOtherEvent && e->fFormat >= kGKeyPress &&
2121 e->fFormat < kOtherEvent) {
2122 e->fType = (EGEventType)e->fFormat;
2123 if (gDragManager)
2125 delete e;
2126 return;
2127 }
2128 else { // then the normal cases
2129 if (!fMasked)
2130 gClient->HandleEvent(e);
2131 else
2132 gClient->HandleMaskEvent(e, fMasked);
2133 }
2134 delete e;
2135}
2136
2137////////////////////////////////////////////////////////////////////////////////
2138/// Converts TRecGuiEvent type to Event_t type
2139
2141{
2142 Event_t *e = new Event_t();
2143
2144 // Copies all data items
2145
2146 e->fType = ge->fType;
2147 e->fWindow = ge->fWindow;
2148 e->fTime = ge->fTime;
2149
2150 e->fX = ge->fX;
2151 e->fY = ge->fY;
2152 e->fXRoot = ge->fXRoot;
2153 e->fYRoot = ge->fYRoot;
2154
2155 e->fCode = ge->fCode;
2156 e->fState = ge->fState;
2157
2158 e->fWidth = ge->fWidth;
2159 e->fHeight = ge->fHeight;
2160
2161 e->fCount = ge->fCount;
2162 e->fSendEvent = ge->fSendEvent;
2163
2164 e->fHandle = ge->fHandle;
2165 e->fFormat = ge->fFormat;
2166
2167 if (e->fHandle == TRecGuiEvent::kROOT_MESSAGE)
2168 e->fHandle = gROOT_MESSAGE;
2169
2170 for(Int_t i=0; i<5; ++i)
2171 e->fUser[i] = ge->fUser[i];
2172
2173 if (e->fUser[0] == TRecGuiEvent::kWM_DELETE_WINDOW)
2174 e->fUser[0] = gWM_DELETE_WINDOW;
2175
2176 if (ge->fType == kGKeyPress || ge->fType == kKeyRelease) {
2177 e->fCode = gVirtualX->KeysymToKeycode(ge->fCode);
2178#ifdef R__WIN32
2179 e->fUser[1] = 1;
2180 e->fUser[2] = e->fCode;
2181#endif
2182 }
2183
2184 return e;
2185}
2186
@ kPaveLabel
Definition Buttons.h:31
@ kText
Definition Buttons.h:30
Handle_t Atom_t
WM token.
Definition GuiTypes.h:37
EGEventType
Definition GuiTypes.h:59
@ kSelectionClear
Definition GuiTypes.h:63
@ kConfigureNotify
Definition GuiTypes.h:62
@ kGKeyPress
Definition GuiTypes.h:60
@ kButtonRelease
Definition GuiTypes.h:60
@ kSelectionNotify
Definition GuiTypes.h:63
@ kButtonPress
Definition GuiTypes.h:60
@ kMotionNotify
Definition GuiTypes.h:61
@ kClientMessage
Definition GuiTypes.h:63
@ kSelectionRequest
Definition GuiTypes.h:63
@ kOtherEvent
Definition GuiTypes.h:64
@ kKeyRelease
Definition GuiTypes.h:60
const Mask_t kWAOverrideRedirect
Definition GuiTypes.h:149
Handle_t Pixmap_t
Pixmap handle.
Definition GuiTypes.h:30
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
const Mask_t kWASaveUnder
Definition GuiTypes.h:150
@ kChildFrame
Definition GuiTypes.h:379
@ kTempFrame
Definition GuiTypes.h:393
@ kFixedHeight
Definition GuiTypes.h:389
const Mask_t kKeyControlMask
Definition GuiTypes.h:197
ULong_t Pixel_t
Pixel value.
Definition GuiTypes.h:40
@ kKey_S
Definition KeySymbols.h:144
#define f(i)
Definition RSha256.hxx:104
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
unsigned long long ULong64_t
Portable unsigned long integer 8 bytes.
Definition RtypesCore.h:84
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
R__EXTERN TApplication * gApplication
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
#define gClient
Definition TGClient.h:157
@ kFDOpen
@ kFDSave
@ kDeepCleanup
Definition TGFrame.h:42
@ kLHintsExpandY
Definition TGLayout.h:31
@ kLHintsLeft
Definition TGLayout.h:24
@ kLHintsCenterX
Definition TGLayout.h:25
@ kLHintsTop
Definition TGLayout.h:27
@ kLHintsExpandX
Definition TGLayout.h:30
static const char * gFiletypes[]
winID h TVirtualViewer3D TVirtualGLPainter p
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 ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
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 r
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 ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
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 win
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t attr
Option_t Option_t TPoint TPoint const char mode
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
#define gROOT
Definition TROOT.h:411
const char * kCmdEventTree
const char * kRecEventNames[]
Definition TRecorder.cxx:93
const char * kExtraEventTree
static Int_t gDecorHeight
const char * kWindowsTree
const char * kGuiEventTree
static Int_t gDecorWidth
const char * kBranchName
static TGCursorWindow * gCursorWin
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
R__EXTERN TVirtualDragManager * gDragManager
#define gPad
#define gVirtualX
Definition TVirtualX.h:337
R__EXTERN Atom_t gROOT_MESSAGE
Definition TVirtualX.h:40
R__EXTERN Atom_t gWM_DELETE_WINDOW
Definition TVirtualX.h:38
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
The Canvas class.
Definition TCanvas.h:23
void SetWindowSize(UInt_t ww, UInt_t wh)
Set canvas window size.
Definition TCanvas.cxx:2146
UInt_t GetWindowHeight() const
Definition TCanvas.h:162
void Draw(Option_t *option="") override
Draw a canvas.
Definition TCanvas.cxx:852
UInt_t GetWindowWidth() const
Definition TCanvas.h:161
Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) override
Write all objects in this collection.
TObject * Get(const char *namecycle) override
Return pointer to object identified by namecycle.
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:131
virtual Bool_t IsOpen() const
Returns kTRUE in case file is open and kFALSE if file is not open.
Definition TFile.cxx:1458
Int_t Write(const char *name=nullptr, Int_t opt=0, Int_t bufsize=0) override
Write memory objects to this file.
Definition TFile.cxx:2466
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:3764
void Close(Option_t *option="") override
Close a file.
Definition TFile.cxx:958
virtual void SetOn(Bool_t on=kTRUE, Bool_t emit=kFALSE)
Definition TGButton.h:120
virtual void SetStyle(UInt_t newstyle)
Set the button style (modern or classic).
Definition TGButton.cxx:265
virtual void SetEnabled(Bool_t e=kTRUE)
Set enabled or disabled state of button.
Definition TGButton.cxx:453
Selects different options.
Definition TGButton.h:264
virtual void SetDisabledAndSelected(Bool_t)
Set the state of a check button to disabled and either on or off.
Bool_t IsOn() const override
Definition TGButton.h:310
const TGPicture * GetPicture(const char *name)
Get picture from the picture pool.
Definition TGClient.cxx:288
virtual void AddFrame(TGFrame *f, TGLayoutHints *l=nullptr)
Add frame to the composite frame using the specified layout hints.
Definition TGFrame.cxx:1109
virtual void Cleanup()
Cleanup and delete all objects contained in this composite frame.
Definition TGFrame.cxx:959
void MapSubwindows() override
Map all sub windows that are part of the composite frame.
Definition TGFrame.cxx:1156
void Layout() override
Layout the elements of the composite frame.
Definition TGFrame.cxx:1249
void SetCleanup(Int_t mode=kLocalCleanup) override
Turn on automatic cleanup of child frames in dtor.
Definition TGFrame.cxx:1064
void SetEditDisabled(UInt_t on=1) override
Set edit disable flag for this frame and subframes.
Definition TGFrame.cxx:1014
~TGCursorWindow() override
Destructor.
TGCursorWindow()
TGCursorWindow constructor.
This class creates a file selection dialog.
A subclasses of TGWindow, and is used as base class for some simple widgets (buttons,...
Definition TGFrame.h:80
void Resize(UInt_t w=0, UInt_t h=0) override
Resize the frame.
Definition TGFrame.cxx:597
void SetBackgroundColor(Pixel_t back) override
Set background color (override from TGWindow base class).
Definition TGFrame.cxx:304
void MapWindow() override
map window
Definition TGFrame.h:206
Int_t GetX() const
Definition TGFrame.h:233
UInt_t GetHeight() const
Definition TGFrame.h:227
Int_t GetY() const
Definition TGFrame.h:234
UInt_t GetWidth() const
Definition TGFrame.h:226
A composite frame that layout their children in horizontal way.
Definition TGFrame.h:387
This class handles GUI labels.
Definition TGLabel.h:24
virtual void SetTextColor(Pixel_t color, Bool_t global=kFALSE)
Changes text color.
Definition TGLabel.cxx:361
virtual void SetText(TGString *newText)
Set new text in label.
Definition TGLabel.cxx:179
virtual void SetTextFont(TGFont *font, Bool_t global=kFALSE)
Changes text font specified by pointer to TGFont object.
Definition TGLabel.cxx:323
This class describes layout hints used by the layout classes.
Definition TGLayout.h:50
Defines top level windows that interact with the system Window Manager.
Definition TGFrame.h:399
void SetWindowName(const char *name=nullptr) override
Set window name. This is typically done via the window manager.
Definition TGFrame.cxx:1780
TGClient * fClient
Connection to display server.
Definition TGObject.h:25
Handle_t GetId() const
Definition TGObject.h:41
Handle_t fId
X11/Win32 Window identifier.
Definition TGObject.h:24
Yield an action as soon as it is clicked.
Definition TGButton.h:228
virtual void SetPicture(const TGPicture *new_pic)
Change a picture in a picture button.
The TGPicture class implements pictures and icons used in the different GUI elements and widgets.
Definition TGPicture.h:25
Window_t fFilteredIds[fgWidgetsCount]
Definition TRecorder.h:646
time_t fStart
Definition TRecorder.h:643
TGPictureButton * fStartStop
Definition TRecorder.h:635
TGRecorder(const TGWindow *p=nullptr, UInt_t w=230, UInt_t h=150)
The GUI for the recorder.
TGLabel * fTimeDisplay
Definition TRecorder.h:639
TGCheckButton * fCursorCheckBox
Definition TRecorder.h:640
TTimer * fTimer
Definition TRecorder.h:642
void StartStop()
Handles push of the fStartStop button according to the current recorder state.
TGPictureButton * fReplay
Definition TRecorder.h:636
TRecorder * fRecorder
Definition TRecorder.h:633
void Update()
Called when fTimer timeouts (every 0.025 second) Updates GUI of recorder.
static const Int_t fgWidgetsCount
Definition TRecorder.h:645
TGLabel * fStatus
Definition TRecorder.h:638
~TGRecorder() override
Destructor. Cleanup the GUI.
time_t fElapsed
Definition TRecorder.h:643
void SetDefault()
Sets GUI to the default inactive state.
void Replay()
Handles push of fReplay button according to the current recorder state.
A composite frame that layout their children in vertical way.
Definition TGFrame.h:376
ROOT GUI Window base class.
Definition TGWindow.h:23
virtual void SetBackgroundPixmap(Pixmap_t pixmap)
set background pixmap
Definition TGWindow.cxx:246
@ kEditDisableGrab
window grab cannot be edited
Definition TGWindow.h:59
@ kEditDisable
disable edit of this window
Definition TGWindow.h:57
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition TKey.cxx:760
To draw Mathematical Formula.
Definition TLatex.h:18
Iterator of linked list.
Definition TList.h:191
TObject * Next() override
Return next object in the list. Returns 0 when no more objects in list.
Definition TList.cxx:1110
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:81
Int_t UnLock() override
Unlock the mutex.
Definition TMutex.cxx:67
Int_t Lock() override
Lock the mutex.
Definition TMutex.cxx:45
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Mother of all ROOT objects.
Definition TObject.h:41
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:159
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition TObject.cxx:964
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
A Pave (see TPave) with a text centered in the Pave.
Definition TPaveLabel.h:20
SCoord_t fY
Definition TPoint.h:36
SCoord_t fX
Definition TPoint.h:35
Bool_t Connect(const char *signal, const char *receiver_class, void *receiver, const char *slot)
Non-static method is used to connect from the signal of this object to the receiver slot.
Definition TQObject.cxx:865
Bool_t Disconnect(const char *signal=nullptr, void *receiver=nullptr, const char *slot=nullptr)
Disconnects signal of this object from slot of receiver.
Class used for storing information about 1 commandline event.
Definition TRecorder.h:92
const char * GetText() const
Definition TRecorder.h:106
void SetText(const char *text)
Definition TRecorder.h:101
virtual void ReplayEvent(Bool_t showMouseCursor=kTRUE)=0
virtual void SetTime(TTime t)
Definition TRecorder.h:72
virtual TTime GetTime() const
Definition TRecorder.h:67
virtual ERecEventType GetType() const =0
class TRecExtraEvent
Definition TRecorder.h:137
void SetText(TString text)
Definition TRecorder.h:146
class TRecGuiEvent
Definition TRecorder.h:181
EGEventType fType
Definition TRecorder.h:188
UInt_t fCode
Definition TRecorder.h:195
Int_t fFormat
Definition TRecorder.h:202
Long_t fUser[5]
Definition TRecorder.h:203
static Event_t * CreateEvent(TRecGuiEvent *ge)
Converts TRecGuiEvent type to Event_t type.
Window_t fMasked
Definition TRecorder.h:207
Handle_t fHandle
Definition TRecorder.h:201
UInt_t fHeight
Definition TRecorder.h:198
UInt_t fWidth
Definition TRecorder.h:197
void ReplayEvent(Bool_t showMouseCursor=kTRUE) override
Replays stored GUI event.
Bool_t fSendEvent
Definition TRecorder.h:200
UInt_t fState
Definition TRecorder.h:196
Window_t fWindow
Definition TRecorder.h:189
Time_t fTime
Definition TRecorder.h:190
Class used for storing of window IDs mapping.
Definition TRecorder.h:250
Window_t fValue
Definition TRecorder.h:255
Window_t fKey
Definition TRecorder.h:254
Represents state of TRecorder just after its creation.
Definition TRecorder.h:564
void ListGui(const char *filename) override
Prints out GUI events recorded in given file.
void ListCmd(const char *filename) override
Prints out commandline events recorded in given file.
void Start(TRecorder *r, const char *filename, Option_t *option, Window_t *w=nullptr, Int_t winCount=0) override
Switches from INACTIVE state to RECORDING and starts recording.
TSeqCollection * fCollect
Definition TRecorder.h:567
void PrevCanvases(const char *filename, Option_t *option) override
Save previous canvases in a .root file.
static void DumpRootEvent(TRecGuiEvent *e, Int_t n)
Prints out attributes of one GUI event TRecGuiEvent *e Int_n n is number of event if called in cycle.
static long DisplayValid(Long_t n)
Definition TRecorder.h:582
Bool_t Replay(TRecorder *r, const char *filename, Bool_t showMouseCursor, TRecorder::EReplayModes mode) override
Switches from INACTIVE state of recorder to REPLAYING Return kTRUE if replaying has started or kFALSE...
void ReplayStop(TRecorder *r) override
Replaying is cancelled.
TRecorderReplaying * fReplayingState
Definition TRecorder.h:607
void Resume(TRecorder *r) override
Continues replaying.
TRecorderPaused(TRecorderReplaying *state)
Remember the recorder state that is paused.
Represents state of TRecorder when recording events.
Definition TRecorder.h:488
TRecExtraEvent * fExtraEvent
Definition TRecorder.h:511
TRecCmdEvent * fCmdEvent
Definition TRecorder.h:510
void FilterEventPave()
Change the state of the flag to kTRUE when you are recording a pavelabel.
TRecorder * fRecorder
Definition TRecorder.h:495
void RecordMousePosition()
Try to record all mouse moves...
friend class TRecorderInactive
Definition TRecorder.h:526
TRecGuiEvent * fGuiEvent
Definition TRecorder.h:509
~TRecorderRecording() override
Freeing of allocated memory.
Long64_t fBeginPave
Definition TRecorder.h:501
TRecorderRecording(TRecorder *r, const char *filename, Option_t *option, Window_t *w, Int_t winCount)
Initializes TRecorderRecording for recording What is allocated here is deleted in destructor.
void RegisterWindow(Window_t w)
This method is called when RegisteredWindow(Window_t) is emitted from TGClient.
Bool_t StartRecording()
Connects appropriate signals and slots in order to gain all registered windows and processed events i...
Bool_t fFilterEventPave
Definition TRecorder.h:523
void StartEditing()
Memorize the starting time of editinga TLatex or a TPaveLabel.
void RecordGuiBldEvent(Event_t *e)
Special case for the gui builder, having a timer handling some of the events.
void RecordPave(const TObject *obj)
Records TPaveLabel object created in TCreatePrimitives::Pave()
Bool_t IsFiltered(Window_t id)
Returns kTRUE if passed id belongs to window IDs of recorder GUI itself.
Window_t * fFilteredIds
Definition TRecorder.h:521
TTimer * fMouseTimer
Definition TRecorder.h:500
void SetTypeOfConfigureNotify(Event_t *e)
Sets type of kConfigureNotify event to one of EConfigureNotify.
void RecordGuiCNEvent(Event_t *e)
Records GUI Event_t *e of type kConfigureNotify.
void RecordExtraEvent(TString line, TTime extTime)
Records TLatex or TPaveLabel object created in TCreatePrimitives, ExtTime is needed for the correct r...
Bool_t fCmdEventPending
Definition TRecorder.h:513
void RecordGuiEvent(Event_t *e, Window_t wid)
Records GUI Event_t *e different from kConfigureNotify (they are recorded in TRecorderRecording::Reco...
void RecordText(const TObject *obj)
Records TLatex object created in TCreatePrimitives::Text()
void Stop(TRecorder *r, Bool_t guiCommand) override
Disconnects all slots and stopps recording.
void CopyEvent(Event_t *e, Window_t wid)
Copies all items of given event to fGuiEvent.
void RecordCmdEvent(const char *line)
Records commandline event (text and time) ans saves the previous commandline event This 1 event delay...
Represents state of TRecorder when replaying previously recorded events.
Definition TRecorder.h:396
Bool_t FilterEvent(TRecGuiEvent *e)
friend class TRecorderPaused
Definition TRecorder.h:460
friend class TRecorderInactive
Definition TRecorder.h:459
TRecEvent * fNextEvent
Definition TRecorder.h:437
TRecGuiEvent * fGuiEvent
Definition TRecorder.h:422
void Pause(TRecorder *r) override
Pauses replaying.
TRecCmdEvent * fCmdEvent
Definition TRecorder.h:423
Bool_t RemapWindowReferences()
All references to the old windows (IDs) in fNextEvent are replaced by new ones according to the mappi...
Bool_t fFilterStatusBar
Definition TRecorder.h:456
Bool_t fWaitingForWindow
Definition TRecorder.h:442
TRecExtraEvent * fExtraEvent
Definition TRecorder.h:424
virtual void Continue()
Continues previously paused replaying.
Bool_t CanOverlap()
ButtonPress and ButtonRelease must be sometimes replayed more times Example: pressing of a button ope...
void ReplayStop(TRecorder *r) override
Cancels replaying.
~TRecorderReplaying() override
Closes all signal-slot connections Frees all memory allocated in constructor.
Bool_t fShowMouseCursor
Definition TRecorder.h:454
TRecorderReplaying(const char *filename)
Allocates all necessary data structures used for replaying What is allocated here is deleted in destr...
Bool_t PrepareNextEvent()
Finds the next event in log file to replay and sets it to fNextEvent.
TRecorder * fRecorder
Definition TRecorder.h:405
Bool_t Initialize(TRecorder *r, Bool_t showMouseCursor, TRecorder::EReplayModes mode)
Initialization of data structures for replaying.
void RegisterWindow(Window_t w)
Creates mapping for the newly registered window w and adds this mapping to fWindowList.
void ReplayRealtime()
Replays the next event.
Abstract class that defines interface for a state of recorder.
Definition TRecorder.h:361
virtual void PrevCanvases(const char *, Option_t *)
Definition TRecorder.h:378
virtual void Resume(TRecorder *)
Definition TRecorder.h:372
virtual void Start(TRecorder *, const char *, Option_t *, Window_t *, Int_t)
Definition TRecorder.h:368
virtual void ListCmd(const char *)
Definition TRecorder.h:375
virtual void ReplayStop(TRecorder *)
Definition TRecorder.h:373
virtual void Pause(TRecorder *)
Definition TRecorder.h:371
virtual void ListGui(const char *)
Definition TRecorder.h:376
virtual TRecorder::ERecorderState GetState() const =0
virtual Bool_t Replay(TRecorder *, const char *, Bool_t, TRecorder::EReplayModes)
Definition TRecorder.h:370
virtual void Stop(TRecorder *, Bool_t)
Definition TRecorder.h:369
Class provides direct recorder/replayer interface for a user.
Definition TRecorder.h:266
~TRecorder() override
Destructor.
friend class TRecorderInactive
Definition TRecorder.h:275
void Replay()
Definition TRecorder.h:318
void Stop(Bool_t guiCommand=kFALSE)
Stopps recording events.
void ReplayStop()
Cancels replaying.
void Resume()
Resumes replaying.
TRecorderState * fRecorderState
Definition TRecorder.h:268
virtual TRecorder::ERecorderState GetState() const
Get current state of recorder.
TString fFilename
Definition TRecorder.h:280
void ListGui(const char *filename)
Prints out recorded GUI events.
void Start(const char *filename, Option_t *option="RECREATE", Window_t *w=nullptr, Int_t winCount=0)
Starts recording events.
void Pause()
Pauses replaying.
void Browse(TBrowser *) override
Browse the recorder from a ROOT file.
void ListCmd(const char *filename)
Prints out recorded commandline events.
Bool_t Replay(const char *filename, Bool_t showMouseCursor=kTRUE, TRecorder::EReplayModes mode=kRealtime)
Replays events from 'filename'.
TRecorder()
Creates initial INACTIVE state for the recorder.
void PrevCanvases(const char *filename, Option_t *option)
Save previous canvases in a .root file.
void ChangeState(TRecorderState *newstate, Bool_t deletePreviousState=kTRUE)
Changes state from the current to the passed one (newstate) Deletes the old state if delPreviousState...
Basic string class.
Definition TString.h:138
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition TSystem.cxx:944
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:414
Basic time type with millisecond precision.
Definition TTime.h:27
Handles synchronous and a-synchronous timer events.
Definition TTimer.h:51
TTime GetAbsTime() const
Definition TTimer.h:78
virtual void TurnOff()
Remove timer from system timer list.
Definition TTimer.cxx:234
virtual void Start(Long_t milliSec=-1, Bool_t singleShot=kFALSE)
Starts the timer with a milliSec timeout.
Definition TTimer.cxx:216
virtual void TurnOn()
Add the timer to the system timer list.
Definition TTimer.cxx:246
void Reset()
Reset the timer.
Definition TTimer.cxx:162
virtual void Stop()
Definition TTimer.h:94
A TTree represents a columnar dataset.
Definition TTree.h:89
virtual Int_t Fill()
Fill all branches.
Definition TTree.cxx:4653
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr, TClass *realClass, EDataType datatype, bool isptr, bool suppressMissingBranchError)
Definition TTree.cxx:8637
virtual Int_t GetEntry(Long64_t entry, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition TTree.cxx:5718
virtual Long64_t GetEntries() const
Definition TTree.h:502
TBranch * Branch(const char *name, T *obj, Int_t bufsize=32000, Int_t splitlevel=99)
Add a new branch, and infer the data type from the type of obj being passed.
Definition TTree.h:389
virtual Bool_t HandleTimerEvent(Event_t *, TTimer *)
TLine * line
const Int_t n
Definition legend1.C:16
Event structure.
Definition GuiTypes.h:174
Attributes that can be used when creating or changing a window.
Definition GuiTypes.h:93
Window attributes that can be inquired.
Definition GuiTypes.h:114
auto * t1
Definition textangle.C:20