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
125
126
127//_____________________________________________________________________________
128//
129// TGCursorWindow
130//
131// Window used as fake mouse cursor wile replaying events.
132//_____________________________________________________________________________
133
134class TGCursorWindow : public TGFrame {
135
136protected:
137 Pixmap_t fPic, fMask; // Pixmaps used as Window shape
138
139public:
141 virtual ~TGCursorWindow();
142};
143
147
148////////////////////////////////////////////////////////////////////////////////
149/// TGCursorWindow constructor.
150
152 TGFrame(gClient->GetDefaultRoot(), 32, 32, kTempFrame)
153{
155 const TGPicture *pbg = fClient->GetPicture("recursor.png");
156 fPic = pbg->GetPicture();
157 fMask = pbg->GetMask();
158
159 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
161
163 wattr.fSaveUnder = kTRUE;
164 wattr.fOverrideRedirect = kTRUE;
165
166 gVirtualX->ChangeWindowAttributes(fId, &wattr);
167}
168
169////////////////////////////////////////////////////////////////////////////////
170/// Destructor.
171
173{
174}
175
176////////////////////////////////////////////////////////////////////////////////
177/// Creates initial INACTIVE state for the recorder
178
180{
181 fFilename = "";
183}
184
185////////////////////////////////////////////////////////////////////////////////
186/// Creates a recorder with filename to replay or to record,
187/// depending on option (NEW or RECREATE will start recording,
188/// READ will start replaying)
189
190TRecorder::TRecorder(const char *filename, Option_t *option)
191{
192 TString opt(option);
193 fFilename = "";
195 if ((opt == "NEW") || (opt == "RECREATE"))
196 Start(filename, option);
197 else
198 Replay(filename);
199}
200
201////////////////////////////////////////////////////////////////////////////////
202/// Destructor.
203
205{
206 delete fRecorderState;
207}
208
209////////////////////////////////////////////////////////////////////////////////
210/// Browse the recorder from a ROOT file. This allows to replay a
211/// session from the browser.
212
214{
216}
217
218////////////////////////////////////////////////////////////////////////////////
219/// Starts recording events
220
221void TRecorder::Start(const char *filename, Option_t *option, Window_t *w,
222 Int_t winCount)
223{
224 fRecorderState->Start(this, filename, option, w, winCount);
225}
226
227////////////////////////////////////////////////////////////////////////////////
228/// Stopps recording events
229
230void TRecorder::Stop(Bool_t guiCommand)
231{
232 fRecorderState->Stop(this, guiCommand);
233}
234
235////////////////////////////////////////////////////////////////////////////////
236/// Replays events from 'filename'
237
238Bool_t TRecorder::Replay(const char *filename, Bool_t showMouseCursor,
240{
241 return fRecorderState->Replay(this, filename, showMouseCursor, mode);
242}
243
244////////////////////////////////////////////////////////////////////////////////
245/// Pauses replaying
246
248{
249 fRecorderState->Pause(this);
250}
251
252////////////////////////////////////////////////////////////////////////////////
253/// Resumes replaying
254
256{
257 fRecorderState->Resume(this);
258}
259
260////////////////////////////////////////////////////////////////////////////////
261/// Cancels replaying
262
264{
266}
267
268////////////////////////////////////////////////////////////////////////////////
269/// Prints out recorded commandline events
270
271void TRecorder::ListCmd(const char *filename)
272{
273 fRecorderState->ListCmd(filename);
274}
275
276////////////////////////////////////////////////////////////////////////////////
277/// Prints out recorded GUI events
278
279void TRecorder::ListGui(const char *filename)
280{
281 fRecorderState->ListGui(filename);
282}
283
284////////////////////////////////////////////////////////////////////////////////
285/// Changes state from the current to the passed one (newstate)
286/// Deletes the old state if delPreviousState = KTRUE
287
288void TRecorder::ChangeState(TRecorderState *newstate, Bool_t delPreviousState)
289{
290 if (delPreviousState)
291 delete fRecorderState;
292
293 fRecorderState = newstate;
294}
295
296////////////////////////////////////////////////////////////////////////////////
297/// Get current state of recorder.
298
300{
301 return fRecorderState->GetState();
302}
303
304
305////////////////////////////////////////////////////////////////////////////////
306/// Save previous canvases in a .root file
307
308void TRecorder::PrevCanvases(const char *filename, Option_t *option)
309{
310 fRecorderState->PrevCanvases(filename,option);
311}
312
313//______________________________________________________________________________
314// Represents state of TRecorder when replaying
315
317
318////////////////////////////////////////////////////////////////////////////////
319/// Allocates all necessary data structures used for replaying
320/// What is allocated here is deleted in destructor
321
323{
324 fCanv = 0;
325 fCmdTree = 0;
326 fCmdTreeCounter = 0;
328 fExtraTree = 0;
331 fGuiTree = 0;
332 fGuiTreeCounter = 0;
333 fNextEvent = 0;
334 fRecorder = 0;
335 fRegWinCounter = 0;
338 fWin = 0;
339 fWinTree = 0;
340 fWinTreeEntries = 0;
341 fFile = TFile::Open(filename);
342 fCmdEvent = new TRecCmdEvent();
343 fGuiEvent = new TRecGuiEvent();
345 fWindowList = new TList();
346 fTimer = new TTimer();
347 fMutex = new TMutex(kFALSE);
348 if (!gCursorWin)
350}
351
352////////////////////////////////////////////////////////////////////////////////
353/// Closes all signal-slot connections
354/// Frees all memory allocated in constructor.
355
357{
358 fTimer->Disconnect(fTimer, "Timeout()", this, "ReplayRealtime()");
359 fTimer->TurnOff();
360 // delete fTimer;
361
362 gClient->Disconnect(gClient, "RegisteredWindow(Window_t)", this,
363 "RegisterWindow(Window_t)");
364
365 if (fFile) {
366 fFile->Close();
367 delete fFile;
368 }
369
370 delete fWindowList;
371 delete fCmdEvent;
372 delete fGuiEvent;
373 delete fExtraEvent;
374 delete fMutex;
375 if (gCursorWin)
377 gCursorWin = 0;
378}
379
380////////////////////////////////////////////////////////////////////////////////
381/// Initialization of data structures for replaying.
382/// Start of replaying.
383///
384/// Return value:
385/// - kTRUE = everything is OK and replaying has begun
386/// - kFALSE = non existing or invalid log file, replaying has not started
387
390{
391 fWin = 0;
392 fGuiTreeCounter = 0;
393 fCmdTreeCounter = 0;
395 fRegWinCounter = 0;
396 fRecorder = 0;
397
399
401
402 fEventReplayed = 1;
403
404 fRecorder = r;
405 fShowMouseCursor = showMouseCursor;
406
407 if (!fFile || fFile->IsZombie() || !fFile->IsOpen())
408 return kFALSE;
409
414
415 if (!fCmdTree || !fWinTree || ! fGuiTree || ! fExtraTree) {
416 Error("TRecorderReplaying::Initialize",
417 "The ROOT file is not valid event logfile.");
418 return kFALSE;
419 }
420
421 try {
426 }
427 catch(...) {
428 Error("TRecorderReplaying::Initialize",
429 "The ROOT file is not valid event logfile");
430 return kFALSE;
431 }
432
433 // No event to replay in given ROOT file
434 if (!PrepareNextEvent()) {
435 Info("TRecorderReplaying::Initialize",
436 "Log file empty. No event to replay.");
437 return kFALSE;
438 }
439
440 // Number of registered windows during recording
442
443 // When a window is registered during replaying,
444 // TRecorderReplaying::RegisterWindow(Window_t) is called
445 gClient->Connect("RegisteredWindow(Window_t)", "TRecorderReplaying",
446 this, "RegisterWindow(Window_t)");
447
448 Info("TRecorderReplaying::Initialize", "Replaying of file %s started",
449 fFile->GetName());
450
452 if (f && !f->IsZombie()) {
453 TIter nextkey(f->GetListOfKeys());
454 TKey *key;
455 TObject *obj;
456 while ((key = (TKey*)nextkey())) {
458 obj = key->ReadObj();
459 if (!obj->InheritsFrom("TCanvas"))
460 continue;
461 fCanv = (TCanvas*) obj;
462 fCanv->Draw();
463 }
464 TCanvas *canvas;
465 TIter nextc(gROOT->GetListOfCanvases());
466 while ((canvas = (TCanvas*)nextc())) {
467 canvas->SetWindowSize(canvas->GetWindowWidth(),
468 canvas->GetWindowHeight());
469 }
471 f->Close();
472 }
473
474 gPad = 0;
475 // Starts replaying
476 fTimer->Connect("Timeout()","TRecorderReplaying",this,"ReplayRealtime()");
477 fTimer->Start(0);
478
479 return kTRUE;
480}
481
482////////////////////////////////////////////////////////////////////////////////
483/// Creates mapping for the newly registered window w and adds this
484/// mapping to fWindowList
485///
486/// Called by signal whenever a new window is registered during replaying.
487///
488/// The new window ID is mapped to the old one with the same number in the
489/// list of registered windows.
490/// It means that 1st new window is mapped to the 1st original,
491/// 2nd to the 2nd, Nth new to the Nth original.
492
494{
495 if (fFilterStatusBar) {
496 TGWindow *win = gClient->GetWindowById(w);
497 if (win) {
498 if (win->GetParent()->InheritsFrom("TGStatusBar")) {
500 return;
501 }
502 }
503 }
504
505 // Get original window ID that was registered as 'fRegWinCounter'th
508 }
509 else {
510 // More windows registered when replaying then when recording.
511 // Cannot continue
512 Error("TRecorderReplaying::RegisterWindow",
513 "More windows registered than expected");
514 //ReplayStop(fRecorder);
515 return;
516 }
517
518 if ((gDebug > 0) && (fWaitingForWindow)) {
519 std::ios::fmtflags f = std::cout.flags(); // store flags
520 std::cout << " Window registered: new ID: " << std::hex << w <<
521 " previous ID: " << fWin << std::dec << std::endl;
522 std::cout.flags( f ); // restore flags (reset std::hex)
523 }
524
525 // Lock mutex for guarding access to fWindowList
526 fMutex->Lock();
527
528 // Increases counter of registered windows
530
531 // Creates new mapping of original window (fWin) and a new one (w)
532 TRecWinPair *ids = new TRecWinPair(fWin, w);
533 // Saves the newly created mapping
534 fWindowList->Add(ids);
535
536 // If we are waiting for this window to be registered
537 // (Replaying was stopped because of that)
539
540 if (gDebug > 0) {
541 std::ios::fmtflags f = std::cout.flags(); // store flags
542 std::cout << " Window " << std::hex << fGuiEvent->fWindow <<
543 " registered." << std::dec << std::endl;
544 std::cout.flags( f ); // restore flags (reset std::hex)
545 }
546
548 // Sets that we do not wait for this window anymore
550
551 // Start replaying of events again
552 fTimer->Start(25);
553 }
554 fMutex->UnLock();
555}
556
557////////////////////////////////////////////////////////////////////////////////
558/// All references to the old windows (IDs) in fNextEvent are replaced by
559/// new ones according to the mappings in fWindowList
560
562{
563 // Lock mutex for guarding access to fWindowList
564 fMutex->Lock();
565
566 TRecWinPair *ids;
568
569 Bool_t found = kFALSE;
570
571 // Iterates through the whole list of mappings
572 while ((ids = (TRecWinPair*)it.Next())) {
573 // Window that the event belongs to
574 if (!found && fGuiEvent->fWindow == 0) {
575 fGuiEvent->fWindow = gVirtualX->GetDefaultRootWindow();
576 found = kTRUE;
577 }
578 else if (!found && ids->fKey == fGuiEvent->fWindow) {
579 fGuiEvent->fWindow = ids->fValue;
580 found = kTRUE;
581 }
582 for (Int_t i = 0; i < 5; ++i) {
583 if ((Long_t) ids->fKey == fGuiEvent->fUser[i])
584 fGuiEvent->fUser[i] = ids->fValue;
585 }
586 if (fGuiEvent->fMasked && ids->fKey == fGuiEvent->fMasked) {
587 fGuiEvent->fMasked = ids->fValue;
588 }
589 }
590
591 if (!found && fGuiEvent->fWindow == 0) {
592 fGuiEvent->fWindow = gVirtualX->GetDefaultRootWindow();
593 found = kTRUE;
594 }
595 // Mapping for the event found
596 if (found) {
597 fMutex->UnLock();
598 return kTRUE;
599 }
600
601 if (gDebug > 0) {
602 // save actual formatting flags
603 std::ios_base::fmtflags org_flags = std::cout.flags();
604 std::cout << "fGuiTreeCounter = " << std::dec << fGuiTreeCounter <<
605 " No mapping found for ID " << std::hex << fGuiEvent->fWindow << std::endl;
607 // restore original formatting flags
608 std::cout.flags(org_flags);
609 }
610
611 // Stopps timer and waits for the appropriate window to be registered
612 fTimer->Stop();
614
615 fMutex->UnLock();
616 return kFALSE;
617}
618
619////////////////////////////////////////////////////////////////////////////////
620
622{
623 // Not all the recorded events are replayed.
624 // Some of them are generated automatically in ROOT
625 // as a consequence of other events.
626 //
627 // RETURN VALUE:
628 // - kTRUE = passed TRecGuiEvent *e should be filtered
629 // (should not be replayed)
630 // - kFALSE = passed TRecGuiEvent *e should not be filtered
631 // (should be replayed)
632
633 // We do not replay any client messages except closing of windows
634 if (e->fType == kClientMessage) {
635 if ((e->fFormat == 32) && (e->fHandle != TRecGuiEvent::kROOT_MESSAGE)
636 && ((Atom_t)e->fUser[0] == TRecGuiEvent::kWM_DELETE_WINDOW))
637 return kFALSE;
638 else
639 return kTRUE;
640 }
641
642 // See TRecorderRecording::SetTypeOfConfigureNotify to get know
643 // which kConfigureNotify events are filtered
644 if (e->fType == kConfigureNotify && e->fUser[4] == TRecGuiEvent::kCNFilter) {
645 return kTRUE;
646 }
647
648 if (e->fType == kOtherEvent) {
649 if (e->fFormat >= kGKeyPress && e->fFormat < kOtherEvent)
650 return kFALSE;
651 return kTRUE;
652 }
653
654 return kFALSE;
655}
656
657////////////////////////////////////////////////////////////////////////////////
658/// Finds the next event in log file to replay and sets it to fNextEvent
659///
660/// Reads both from CmdTree and GuiTree and chooses that event that becomes
661/// earlier
662/// - fCmdTreeCounter determines actual position in fCmdTree
663/// - fGuiTreeCounter determines actual position in fCmdTree
664///
665/// If GUI event should be replayed, we must first make sure that there is
666/// appropriate mapping for this event
667///
668/// RETURN VALUE:
669/// kFALSE = there is no event to be replayed
670/// kTRUE = there is still at least one event to be replayed. Cases:
671/// - fNextEvent = 0 => We are waiting for the appropriate
672/// window to be registered
673/// - fNextEvent != 0 => fNextEvent can be replayed (windows are
674/// ready)
675
677{
678 fCmdEvent = 0;
679 fGuiEvent = 0;
680 fExtraEvent = 0;
681 fNextEvent = 0;
682
683 // Reads the next unreplayed commandline event to fCmdEvent
686
687 // Reads the next unreplayed extra event to fExtraEvent
690
691 // Reads the next unreplayed GUI event to fGuiEvent
692 // Skips GUI events that should not be replayed (FilterEvent call)
693 while (fGuiTree->GetEntries() > fGuiTreeCounter) {
696 break;
698 }
699
700 // Chooses which one will be fNextEvent (the next event to be replayed)
701 if (fCmdEvent && fGuiEvent && fExtraEvent) {
702 // If there are all uf them, compares their times and chooses the
703 // earlier one
704 if ((fCmdEvent->GetTime() <= fGuiEvent->GetTime()) &&
707 else {
710 else
712 }
713 }
714 else if (fCmdEvent && fGuiEvent) {
715 // If there are both of them, compares their times and chooses the
716 // earlier one
717 if (fCmdEvent->GetTime() <= fGuiEvent->GetTime())
719 else
721 }
722 else if (fCmdEvent && fExtraEvent ) {
723 // If there are both of them, compares their times and chooses the
724 // earlier one
727 else
729 }
730 else if (fGuiEvent && fExtraEvent) {
731 // If there are both of them, compares their times and chooses the
732 // earlier one
735 else
737 }
738
739 // Nor commandline neither event to replay
740 else if (!fCmdEvent && !fGuiEvent && !fExtraEvent)
741 fNextEvent = 0;
742 // Only GUI event to replay
743 else if (fGuiEvent)
745 // Only commandline event to replay
746 else if (fCmdEvent)
748 else
750
751 // Nothing to replay
752 if (fNextEvent == 0)
753 return kFALSE;
754
755 // Commandline event to replay
756 if (fNextEvent == fCmdEvent)
758
759 // Extra event to replay
760 if (fNextEvent == fExtraEvent)
762
763 // GUI event to replay
764 if (fNextEvent == fGuiEvent) {
765 // We have the new window to send this event to
768 // We do not have it yet (waiting for registration)
769 else
770 fNextEvent = 0;
771 }
772 return kTRUE;
773}
774
775////////////////////////////////////////////////////////////////////////////////
776/// ButtonPress and ButtonRelease must be sometimes replayed more times
777/// Example: pressing of a button opens small window and user chooses
778/// something from that window (color)
779/// Window must be opened while user is choosing
780
782{
783 if (!fGuiEvent) {
784 Error("TRecorderReplaying::CanOverlap()", "fGuiEvent = 0");
785 return kFALSE;
786 }
787
788 // only GUI events overlapping is allowed
790 return kFALSE;
791
792
793 if (gDebug > 0) {
794 std::cout << "Event overlapping " <<
795 kRecEventNames[((TRecGuiEvent*)fNextEvent)->fType] << std::endl;
797 }
798
799 // GUI event
801
802 // Overlapping allowed for ButtonPress, ButtonRelease and MotionNotify
803 if (e->fType == kButtonPress || e->fType == kButtonRelease ||
804 e->fType == kMotionNotify)
805 return kTRUE;
806
807 return kFALSE;
808}
809
810////////////////////////////////////////////////////////////////////////////////
811/// Replays the next event.
812///
813/// It is called when fTimer times out.
814/// Every time fTimer is set again to time equal to time difference between
815/// current two events being replayed.
816///
817/// It can happen that execution of an event lasts different time during the
818/// recording and during the replaying.
819/// If fTimer times out too early and the previous event has not been yet
820/// replayed, it is usually postponed in order
821/// to keep events execution in the right order.
822/// The exceptions are determined by TRecorderReplaying::CanOverlap()
823///
824
826{
827 UInt_t keysym;
828 char str[2];
829
830 if ((gROOT->GetEditorMode() == kText) ||
831 (gROOT->GetEditorMode() == kPaveLabel)){
832 gROOT->SetEditorMode();
833 }
834
835 // If there are automatically generated ROOT events in the queue, they
836 // are let to be handled first
837 if (gVirtualX->EventsPending()) {
839 return;
840 }
841
842 // Previous event has not been replayed yet and it is not allowed for
843 // this event to be replayed more times
844 if (!fEventReplayed && !CanOverlap())
845 return;
846
847 // Event to replay prepared
848 if (fNextEvent) {
849 // Sets that fNextEvent has not been replayed yet
850 fEventReplayed = 0;
851
852 // Remembers its execution time to compute time difference with
853 // the next event
855
856 // Special execution of events causing potential deadlocks
859 if (ev->fType == kGKeyPress && ev->fState & kKeyControlMask) {
860 Event_t *e = ev->CreateEvent(ev);
861 gVirtualX->LookupString(e, str, sizeof(str), keysym);
862 // catch the ctrl-s event
863 if ((keysym & ~0x20) == kKey_S) {
864 fEventReplayed = 1;
867 return;
868 }
869 }
870 }
871
872 // REPLAYS CURRENT EVENT
874
875 // Sets that fNextEvent has been replayed
876 fEventReplayed = 1;
877 }
878
879 // Prepares new event for replaying
880 if (!PrepareNextEvent()) {
881 // No more events to be replayed (replaying has finished).
882
883 // Switches recorder back to INACTIVE state
884 Info("TRecorderReplaying::ReplayRealtime", "Replaying finished");
886 return;
887 }
888 else {
889 // We have event to replay here.
890
891 // It will be replayed with the same time difference to the previous
892 // one as when recording.
893 // After given time, timer will call this method again
894 if (fNextEvent)
896 }
897}
898
899////////////////////////////////////////////////////////////////////////////////
900/// Pauses replaying
901
903{
904 fTimer->Stop();
905 r->ChangeState(new TRecorderPaused(this), kFALSE);
906 Info("TRecorderReplaying::Pause", "Replaying paused.");
907}
908
909////////////////////////////////////////////////////////////////////////////////
910/// Cancels replaying
911
913{
914 Info("TRecorderReplaying::ReplayStop", "Replaying cancelled");
915 r->ChangeState(new TRecorderInactive());
916}
917
918////////////////////////////////////////////////////////////////////////////////
919/// Continues previously paused replaying
920
922{
923 if (fNextEvent)
925}
926
927//______________________________________________________________________________
928// Represents state of TRecorder after its creation
929
931
932////////////////////////////////////////////////////////////////////////////////
933/// Switches from INACTIVE state to RECORDING and starts recording
934
935void TRecorderInactive::Start(TRecorder *r, const char *filename,
936 Option_t *option, Window_t *w, Int_t winCount)
937{
938 // const char *filename = name of ROOT file where to store recorded events
939 // Option_t *option = option for creation of ROOT file
940 // Window_t *w = list of IDs of recorder windows (if GUI for
941 // recorder is used) [0 by default]
942 // Int_t winCount = number of IDs it this list [0 by default]
943
944 TRecorderRecording *rec = new TRecorderRecording(r, filename, option, w, winCount);
945 if (rec->StartRecording()) {
946 r->ChangeState(rec);
947 r->fFilename = gSystem->BaseName(filename);
948 }
949 else
950 delete rec;
951}
952
953////////////////////////////////////////////////////////////////////////////////
954/// Switches from INACTIVE state of recorder to REPLAYING
955/// Return kTRUE if replaying has started or kFALSE if it is not possible
956/// (bad file etc.)
957
959 Bool_t showMouseCursor,
961{
962 // const char *filename = name of ROOT file from where to replay recorded
963 // events
964 // TRecorder::EReplayModes mode = mode of replaying
965
966 TRecorderReplaying *replay = new TRecorderReplaying(filename);
967
968 if (replay->Initialize(r, showMouseCursor, mode)) {
969 r->ChangeState(replay);
970 r->fFilename = gSystem->BaseName(filename);
971 return kTRUE;
972 }
973 else {
974 delete replay;
975 return kFALSE;
976 }
977}
978
979////////////////////////////////////////////////////////////////////////////////
980/// Prints out commandline events recorded in given file
981
982void TRecorderInactive::ListCmd(const char *filename)
983{
984 /*
985 if (!TClassTable::GetDict(" TRecCmdEvent")) {
986 Error("TRecorderInactive::List", " TRecCmdEvent not in dictionary.");
987 return;
988 }*/
989
990 TFile *file = TFile::Open(filename);
991 if (!file) return;
992 if (file->IsZombie() || !file->IsOpen()) {
993 delete file;
994 return;
995 }
996 TTree *t1 = (TTree*)file->Get(kCmdEventTree);
997
998 if (!t1) {
999 Error("TRecorderInactive::List",
1000 "The ROOT file is not valid event logfile.");
1001 delete file;
1002 return;
1003 }
1004
1005 TRecCmdEvent *fCmdEvent = new TRecCmdEvent();
1006 t1->SetBranchAddress(kBranchName, &fCmdEvent);
1007
1008 Int_t entries = t1->GetEntries();
1009 for (Int_t i = 0; i < entries; ++i) {
1010 t1->GetEntry(i);
1011 std::cout << "[" << i << "] " << "fTime=" <<
1012 (ULong64_t) fCmdEvent->GetTime() << " fText=" <<
1013 fCmdEvent->GetText() << std::endl;
1014 }
1015 std::cout << std::endl;
1016
1017 delete fCmdEvent;
1018 delete file;
1019}
1020
1021////////////////////////////////////////////////////////////////////////////////
1022/// Prints out GUI events recorded in given file
1023
1024void TRecorderInactive::ListGui(const char *filename)
1025{
1026 /*
1027 if (!TClassTable::GetDict("TRecGuiEvent")) {
1028 Error("TRecorderInactive::ListGui",
1029 "TRecGuiEvent not in the dictionary.");
1030 return;
1031 }*/
1032
1033 TFile *file = TFile::Open(filename);
1034 if (!file) return;
1035 if (file->IsZombie() || !file->IsOpen()) {
1036 delete file;
1037 return;
1038 }
1039 TTree *t1 = (TTree*)file->Get(kGuiEventTree);
1040
1041 if (!t1) {
1042 Error("TRecorderInactive::ListGui",
1043 "The ROOT file is not valid event logfile.");
1044 delete file;
1045 return;
1046 }
1047
1048 TRecGuiEvent *guiEvent = new TRecGuiEvent();
1049 t1->SetBranchAddress(kBranchName, &guiEvent);
1050
1051 Int_t entries = t1->GetEntries();
1052
1053 for (Int_t i = 0; i < entries ; ++i) {
1054 t1->GetEntry(i);
1055 DumpRootEvent(guiEvent, i);
1056 }
1057
1058 delete file;
1059 delete guiEvent;
1060}
1061
1062////////////////////////////////////////////////////////////////////////////////
1063/// Prints out attributes of one GUI event TRecGuiEvent *e
1064/// Int_n n is number of event if called in cycle
1065
1067{
1068 std::ios::fmtflags f = std::cout.flags(); // store flags
1069 std::cout << "[" << n << "] " << std::dec << std::setw(10)
1070 << e->GetTime().AsString() << std::setw(15) << kRecEventNames[e->fType]
1071 << " fW:" << std::hex << e->fWindow
1072 << " t:" << std::dec << e->fTime
1073 << " x:" << DisplayValid(e->fX)
1074 << " y:" << DisplayValid(e->fY)
1075 << " fXR:" << DisplayValid(e->fXRoot)
1076 << " fYR:" << DisplayValid(e->fYRoot)
1077 << " c:" << DisplayValid(e->fCode)
1078 << " s:" << DisplayValid(e->fState)
1079 << " w:" << DisplayValid(e->fWidth)
1080 << " h:" << DisplayValid(e->fHeight)
1081 << " cnt:" << DisplayValid(e->fCount)
1082 << " se:" << e->fSendEvent
1083 << " h:" << e->fHandle
1084 << " fF:" << DisplayValid(e->fFormat)
1085 << " | ";
1086
1087 for (Int_t i=0; i<5; ++i)
1088 if (DisplayValid(e->fUser[i]) != -1)
1089 std::cout << "[" << i << "]=" << DisplayValid(e->fUser[i]);
1090
1091 if (e->fMasked)
1092 std::cout << " | fM:" << std::hex << e->fMasked;
1093
1094 std::cout << std::endl;
1095 std::cout.flags( f ); // restore flags (reset std::hex)
1096}
1097
1098////////////////////////////////////////////////////////////////////////////////
1099/// Save previous canvases in a .root file
1100
1101void TRecorderInactive::PrevCanvases(const char *filename, Option_t *option)
1102{
1103 fCollect = gROOT->GetListOfCanvases();
1104 TFile *f = TFile::Open(filename, option);
1105 if (f && !f->IsZombie()) {
1106 fCollect->Write();
1107 f->Close();
1108 delete f;
1109 }
1110}
1111
1112//______________________________________________________________________________
1113// Represents state of TRecorder when paused
1114
1116
1117////////////////////////////////////////////////////////////////////////////////
1118/// Remember the recorder state that is paused
1119
1121{
1122 fReplayingState = state;
1123}
1124
1125////////////////////////////////////////////////////////////////////////////////
1126/// Continues replaying
1127
1129{
1131 Info("TRecorderPaused::Resume", "Replaying resumed");
1132
1133 // Switches back to the previous replaying state
1134 r->ChangeState(fReplayingState);
1135}
1136
1137////////////////////////////////////////////////////////////////////////////////
1138/// Replaying is cancelled
1139
1141{
1142 delete fReplayingState;
1143
1144 Info("TRecorderReplaying::ReplayStop", "Replaying cancelled");
1145 r->ChangeState(new TRecorderInactive());
1146}
1147
1148
1149//______________________________________________________________________________
1150// Represents state of TRecorder when recording events
1151
1153
1154////////////////////////////////////////////////////////////////////////////////
1155/// Initializes TRecorderRecording for recording
1156/// What is allocated here is deleted in destructor
1157
1159 Option_t *option, Window_t *w,
1160 Int_t winCount)
1161{
1162 fRecorder = r;
1163 fBeginPave = 0;
1164
1165 // Remember window IDs of GUI recorder (appropriate events are
1166 // filtered = not recorded)
1167 fFilteredIdsCount = winCount;
1169 for(Int_t i=0; i < fFilteredIdsCount; ++i)
1170 fFilteredIds[i] = w[i];
1171
1172 // No unhandled commandline event in the beginning
1174
1175 // Filer pave events (mouse button move)
1177
1178 // No registered windows in the beginning
1179 fRegWinCounter = 0;
1180
1181 // New timer for recording
1182 fTimer = new TTimer(25, kTRUE);
1183
1184 fMouseTimer = new TTimer(50, kTRUE);
1185 fMouseTimer->Connect("Timeout()", "TRecorderRecording", this,
1186 "RecordMousePosition()");
1187
1188 // File where store recorded events
1189 fFile = TFile::Open(filename, option);
1190
1191 // TTrees with windows, commandline events and GUi events
1192 fWinTree = new TTree(kWindowsTree, "Windows");
1193 fCmdTree = new TTree(kCmdEventTree, "Commandline events");
1194 fGuiTree = new TTree(kGuiEventTree, "GUI events");
1195 fExtraTree = new TTree(kExtraEventTree, "Extra events");
1196
1197 fWin = 0;
1198 fCmdEvent = new TRecCmdEvent();
1199 fGuiEvent = new TRecGuiEvent();
1201}
1202
1203////////////////////////////////////////////////////////////////////////////////
1204/// Freeing of allocated memory
1205
1207{
1208 delete[] fFilteredIds;
1209
1210 if (fFile)
1211 delete fFile;
1212 delete fMouseTimer;
1213 delete fTimer;
1214 delete fCmdEvent;
1215 delete fGuiEvent;
1216 delete fExtraEvent;
1217}
1218
1219////////////////////////////////////////////////////////////////////////////////
1220/// Connects appropriate signals and slots in order to gain all registered
1221/// windows and processed events in ROOT and then starts recording
1222
1224{
1225 if (!fFile || fFile->IsZombie() || !fFile->IsOpen())
1226 return kFALSE;
1227
1228 // When user types something in the commandline,
1229 // TRecorderRecording::RecordCmdEvent(const char *line) is called
1230 gApplication->Connect("LineProcessed(const char*)", "TRecorderRecording",
1231 this, "RecordCmdEvent(const char*)");
1232
1233 // When a new window in ROOT is registered,
1234 // TRecorderRecording::RegisterWindow(Window_t) is called
1235 gClient->Connect("RegisteredWindow(Window_t)", "TRecorderRecording", this,
1236 "RegisterWindow(Window_t)");
1237
1238 // When a GUI event (different from kConfigureNotify) is processed in
1239 // TGClient::HandleEvent or in TGClient::HandleMaskEvent,
1240 // TRecorderRecording::RecordGuiEvent(Event_t*, Window_t) is called
1241 gClient->Connect("ProcessedEvent(Event_t*, Window_t)", "TRecorderRecording",
1242 this, "RecordGuiEvent(Event_t*, Window_t)");
1243
1244 // When a kConfigureNotify event is processed in TGFrame::HandleEvent,
1245 // TRecorderRecording::RecordGuiCNEvent(Event_t*) is called
1246 TQObject::Connect("TGFrame", "ProcessedConfigure(Event_t*)",
1247 "TRecorderRecording", this, "RecordGuiCNEvent(Event_t*)");
1248
1249 // When a PaveLabel is created, TRecorderRecording::RecordPave(TObject*)
1250 // is called
1251 TQObject::Connect("TPad", "RecordPave(const TObject*)", "TRecorderRecording",
1252 this, "RecordPave(const TObject*)");
1253
1254 // When a Text is created, TRecorderRecording::RecordText() is called
1255 TQObject::Connect("TPad", "RecordLatex(const TObject*)",
1256 "TRecorderRecording", this, "RecordText(const TObject*)");
1257
1258 // When a PaveLabel is created, TRecorderRecording::FilterEventPave()
1259 // is called to filter mouse clicks events.
1260 TQObject::Connect("TPad", "EventPave()", "TRecorderRecording", this,
1261 "FilterEventPave()");
1262
1263 // When starting editing a TLatex or a TPaveLabel, StartEditing()
1264 // is called to memorize edition starting time.
1265 TQObject::Connect("TPad", "StartEditing()", "TRecorderRecording", this,
1266 "StartEditing()");
1267
1268 // Gui Builder specific events.
1269 TQObject::Connect("TGuiBldDragManager", "TimerEvent(Event_t*)",
1270 "TRecorderRecording", this, "RecordGuiBldEvent(Event_t*)");
1271
1272 // Creates in TTrees appropriate branches to store registered windows,
1273 // commandline events and GUI events
1274 fWinTree->Branch(kBranchName, &fWin, "fWin/l");
1275 fCmdTree->Branch(kBranchName, " TRecCmdEvent", &fCmdEvent);
1276 fGuiTree->Branch(kBranchName, "TRecGuiEvent", &fGuiEvent);
1277 fExtraTree->Branch(kBranchName, "TRecExtraEvent", &fExtraEvent);
1278
1279 Int_t numCanvases = gROOT->GetListOfCanvases()->LastIndex();
1280
1281 if (numCanvases >= 0){
1282
1283 TIter nextwindow (gClient->GetListOfWindows());
1284 TGWindow *twin;
1285 Window_t twin2;
1286 Int_t cnt = 0;
1287 while ((twin = (TGWindow*) nextwindow())) {
1288 twin2 = (Window_t) twin->GetId();
1289 if (IsFiltered(twin2)) {
1290 if (gDebug > 0) {
1291 std::cout << "WindowID "<< twin2 << " filtered" << std::endl;
1292 }
1293 }
1294 else if (twin != gClient->GetRoot()) {
1295 RegisterWindow(twin2);
1296 }
1297 cnt++;
1298 }
1299 //Info("TRecorderRecording::StartRecording", "Previous Canvases");
1300 }
1301
1302 // Starts the timer for recording
1303 fTimer->TurnOn();
1304
1305 // start mouse events recording timer
1306 fMouseTimer->Start(50);
1307
1308 Info("TRecorderRecording::StartRecording", "Recording started. Log file: %s",
1309 fFile->GetName());
1310
1311 return kTRUE;
1312}
1313
1314////////////////////////////////////////////////////////////////////////////////
1315/// Disconnects all slots and stopps recording.
1316
1318{
1319 TQObject::Disconnect("TGuiBldDragManager", "TimerEvent(Event_t*)", this,
1320 "RecordGuiBldEvent(Event_t*)");
1321 TQObject::Disconnect("TGFrame", "ProcessedConfigure(Event_t*)", this,
1322 "RecordGuiCNEvent(Event_t*)");
1323 TQObject::Disconnect("TPad", "RecordPave(const TObject*)", this,
1324 "RecordPave(const TObject*)");
1325 TQObject::Disconnect("TPad", "RecordLatex(const TObject*)", this,
1326 "RecordText(const TObject*)");
1327 TQObject::Disconnect("TPad", "EventPave()", this, "FilterEventPave()");
1328 TQObject::Disconnect("TPad", "StartEditing()", this, "StartEditing()");
1329 gClient->Disconnect(gClient, "ProcessedEvent(Event_t*, Window_t)", this,
1330 "RecordGuiEvent(Event_t*, Window_t)");
1331 gClient->Disconnect(gClient, "RegisteredWindow(Window_t)", this,
1332 "RegisterWindow(Window_t)");
1333 gApplication->Disconnect(gApplication, "LineProcessed(const char*)", this,
1334 "RecordCmdEvent(const char*)");
1335
1336 // Decides if to store the last event. It is stored if GUI recorder is used,
1337 // otherwise it is 'TEventRecorded::Stop' and should not be stored
1338 if (fCmdEventPending && guiCommand)
1339 fCmdTree->Fill();
1340
1341 fRecorder->Write("recorder");
1342 fFile->Write();
1343 fFile->Close();
1344 fTimer->TurnOff();
1345
1347
1348 Info("TRecorderRecording::Stop", "Recording finished.");
1349
1351}
1352
1353////////////////////////////////////////////////////////////////////////////////
1354/// This method is called when RegisteredWindow(Window_t) is emitted from
1355/// TGClient.
1356
1358{
1359 // Stores ID of the registered window in appropriate TTree
1360 fWin = (ULong64_t) w;
1361 fWinTree->Fill();
1362}
1363
1364////////////////////////////////////////////////////////////////////////////////
1365/// Records commandline event (text and time) ans saves the previous
1366/// commandline event
1367/// This 1 event delay in saving ensures that the last commandline events
1368/// 'TRecorder::Stop' will be not stored
1369
1371{
1372 // If there is some previously recorded event, saves it in TTree now
1373 if (fCmdEventPending)
1374 fCmdTree->Fill();
1375
1376 // Fill information about this new commandline event: command text and
1377 // time of event execution
1379 fCmdEvent->SetText((char*)line);
1380
1381 // This event will be stored next time (if it is not the last one
1382 // 'TRecorder::Stop')
1384 return;
1385}
1386
1387////////////////////////////////////////////////////////////////////////////////
1388/// Records GUI Event_t *e different from kConfigureNotify (they are
1389/// recorded in TRecorderRecording::RecordGuiCNEvent)
1390///
1391/// It is called via signal-slot when an event is processed in
1392/// TGClient::HandleEvent(Event_t *event)
1393/// or in TGClient::HandleMaskEvent(Event_t *event, Window_t wid)
1394///
1395/// If signal is emitted from TGClient::HandleEvent(Event_t *event),
1396/// then wid = 0
1397
1399{
1400 // If this event is caused by a recorder itself (GUI recorder),
1401 // it is not recorded
1402 if (fFilteredIdsCount && IsFiltered(e->fWindow))
1403 return;
1404
1405 // Doesn't record the mouse clicks when a pavelabel is recorded
1406 if (fFilterEventPave && (e->fCode == 1)) {
1408 return;
1409 }
1411
1412 // don't record any copy/paste event, as event->fUser[x] parameters
1413 // will be invalid when replaying on a different OS
1414 if (e->fType == kSelectionClear || e->fType == kSelectionRequest ||
1415 e->fType == kSelectionNotify)
1416 return;
1417
1418 // Copies all items of e to fGuiEvent
1419 CopyEvent(e, wid);
1420
1421 // Saves time of recording
1423
1424 // Saves recorded event itself in TTree
1425 fGuiTree->Fill();
1426}
1427
1428////////////////////////////////////////////////////////////////////////////////
1429/// Special case for the gui builder, having a timer handling some of the
1430/// events.
1431
1433{
1434 e->fFormat = e->fType;
1435 e->fType = kOtherEvent;
1436
1437 // Copies all items of e to fGuiEvent
1438 CopyEvent(e, 0);
1439
1440 // Saves time of recording
1442
1443 // Saves recorded event itself in TTree
1444 fGuiTree->Fill();
1445}
1446
1447////////////////////////////////////////////////////////////////////////////////
1448/// Try to record all mouse moves...
1449
1451{
1452 Window_t dum;
1453 Event_t ev;
1454 ev.fCode = 0;
1455 ev.fType = kMotionNotify;
1456 ev.fState = 0;
1457 ev.fWindow = 0;
1458 ev.fUser[0] = ev.fUser[1] = ev.fUser[2] = ev.fUser[3] = ev.fUser[4] = 0;
1459 ev.fCount = 0;
1460 ev.fFormat = 0;
1461 ev.fHandle = 0;
1462 ev.fHeight = 0;
1463 ev.fSendEvent = 0;
1464 ev.fTime = 0;
1465 ev.fWidth = 0;
1466
1467 gVirtualX->QueryPointer(gVirtualX->GetDefaultRootWindow(), dum, dum,
1468 ev.fXRoot, ev.fYRoot, ev.fX, ev.fY, ev.fState);
1469 ev.fXRoot -= gDecorWidth;
1470 ev.fYRoot -= gDecorHeight;
1471
1472 RecordGuiEvent(&ev, 0);
1473 fMouseTimer->Reset();
1474}
1475
1476////////////////////////////////////////////////////////////////////////////////
1477/// Records GUI Event_t *e of type kConfigureNotify.
1478/// It is called via signal-slot when an kConfigureNotify event is processed
1479/// in TGFrame::HandleEvent
1480
1482{
1483 // If this event is caused by a recorder itself, it is not recorded
1484 if (fFilteredIdsCount && IsFiltered(e->fWindow))
1485 return;
1486
1487 // Sets fUser[4] value to one of EConfigureNotifyType
1488 // According to this value, event is or is not replayed in the future
1490
1491 // Copies all items of e to fGuiEvent
1492 CopyEvent(e, 0);
1493
1494 // Saves time of recording
1496
1497 // Saves recorded event itself in TTree
1498 fGuiTree->Fill();
1499}
1500
1501////////////////////////////////////////////////////////////////////////////////
1502/// Records TPaveLabel object created in TCreatePrimitives::Pave()
1503
1505{
1506 Long64_t extratime = fBeginPave;
1507 Long64_t interval = (Long64_t)fTimer->GetAbsTime() - fBeginPave;
1508 TPaveLabel *pavel = (TPaveLabel *) obj;
1509 const char *label;
1510 label = pavel->GetLabel();
1511 TString aux = "";
1512 TString cad = "";
1513 cad = "TPaveLabel *p = new TPaveLabel(";
1514 cad += pavel->GetX1();
1515 cad += ",";
1516 cad += pavel->GetY1();
1517 cad += ",";
1518 cad += pavel->GetX2();
1519 cad += ",";
1520 cad += pavel->GetY2();
1521 cad += ",\"\"); p->Draw(); gPad->Modified(); gPad->Update();";
1522 Int_t i, len = (Int_t)strlen(label);
1523 interval /= (len + 2);
1524 RecordExtraEvent(cad, extratime);
1525 for (i=0; i < len; ++i) {
1526 cad = "p->SetLabel(\"";
1527 cad += (aux += label[i]);
1528 cad += "\"); ";
1529#ifndef R__WIN32
1530 cad += " p->SetTextFont(83); p->SetTextSizePixels(14); ";
1531#endif
1532 cad += " gPad->Modified(); gPad->Update();";
1533 extratime += interval;
1534 RecordExtraEvent(cad, extratime);
1535 }
1536 cad = "p->SetTextFont(";
1537 cad += pavel->GetTextFont();
1538 cad += "); p->SetTextSize(";
1539 cad += pavel->GetTextSize();
1540 cad += "); gPad->Modified(); gPad->Update();";
1541 extratime += interval;
1542 RecordExtraEvent(cad, extratime);
1543}
1544
1545////////////////////////////////////////////////////////////////////////////////
1546/// Records TLatex object created in TCreatePrimitives::Text()
1547
1549{
1550 Long64_t extratime = fBeginPave;
1551 Long64_t interval = (Long64_t)fTimer->GetAbsTime() - fBeginPave;
1552 TLatex *texto = (TLatex *) obj;
1553 const char *label;
1554 label = texto->GetTitle();
1555 TString aux = "";
1556 TString cad = "";
1557 cad = "TLatex *l = new TLatex(";
1558 cad += texto->GetX();
1559 cad += ",";
1560 cad += texto->GetY();
1561 cad += ",\"\"); l->Draw(); gPad->Modified(); gPad->Update();";
1562 Int_t i, len = (Int_t)strlen(label);
1563 interval /= (len + 2);
1564 RecordExtraEvent(cad, extratime);
1565 for (i=0; i < len; ++i) {
1566 cad = "l->SetTitle(\"";
1567 cad += (aux += label[i]);
1568 cad += "\"); ";
1569#ifndef R__WIN32
1570 cad += " l->SetTextFont(83); l->SetTextSizePixels(14); ";
1571#endif
1572 cad += " gPad->Modified(); gPad->Update();";
1573 extratime += interval;
1574 RecordExtraEvent(cad, extratime);
1575 }
1576 cad = "l->SetTextFont(";
1577 cad += texto->GetTextFont();
1578 cad += "); l->SetTextSize(";
1579 cad += texto->GetTextSize();
1580 cad += "); gPad->Modified(); gPad->Update();";
1581 cad += " TVirtualPad *spad = gPad->GetCanvas()->GetSelectedPad();";
1582 cad += " gPad->GetCanvas()->Selected(spad, l, kButton1Down);";
1583 extratime += interval;
1584 RecordExtraEvent(cad, extratime);
1585}
1586
1587////////////////////////////////////////////////////////////////////////////////
1588/// Change the state of the flag to kTRUE when you are recording a pavelabel.
1589
1591{
1593}
1594
1595////////////////////////////////////////////////////////////////////////////////
1596/// Memorize the starting time of editinga TLatex or a TPaveLabel
1597
1599{
1601}
1602
1603////////////////////////////////////////////////////////////////////////////////
1604/// Records TLatex or TPaveLabel object created in TCreatePrimitives,
1605/// ExtTime is needed for the correct replay of these events.
1606
1608{
1609 fExtraEvent->SetTime(extTime);
1611 fExtraTree->Fill();
1612}
1613
1614////////////////////////////////////////////////////////////////////////////////
1615/// Copies all items of given event to fGuiEvent
1616
1618{
1619 fGuiEvent->fType = e->fType;
1620 fGuiEvent->fWindow = e->fWindow;
1621 fGuiEvent->fTime = e->fTime;
1622
1623 fGuiEvent->fX = e->fX;
1624 fGuiEvent->fY = e->fY;
1625 fGuiEvent->fXRoot = e->fXRoot;
1626 fGuiEvent->fYRoot = e->fYRoot;
1627
1628 fGuiEvent->fCode = e->fCode;
1629 fGuiEvent->fState = e->fState;
1630
1631 fGuiEvent->fWidth = e->fWidth;
1632 fGuiEvent->fHeight = e->fHeight;
1633
1634 fGuiEvent->fCount = e->fCount;
1635 fGuiEvent->fSendEvent = e->fSendEvent;
1636 fGuiEvent->fHandle = e->fHandle;
1637 fGuiEvent->fFormat = e->fFormat;
1638
1641
1642 for(Int_t i=0; i<5; ++i)
1643 fGuiEvent->fUser[i] = e->fUser[i];
1644
1647
1648 if (e->fType == kGKeyPress || e->fType == kKeyRelease) {
1649 char tmp[10] = {0};
1650 UInt_t keysym = 0;
1651 gVirtualX->LookupString(e, tmp, sizeof(tmp), keysym);
1652 fGuiEvent->fCode = keysym;
1653 }
1654
1655 fGuiEvent->fMasked = wid;
1656}
1657
1658////////////////////////////////////////////////////////////////////////////////
1659/// Returns kTRUE if passed id belongs to window IDs of recorder GUI itself
1660
1662{
1663 for(Int_t i=0; i < fFilteredIdsCount; ++i)
1664 if (id == fFilteredIds[i])
1665 return kTRUE;
1666
1667 return kFALSE;
1668}
1669
1670////////////////////////////////////////////////////////////////////////////////
1671/// Sets type of kConfigureNotify event to one of EConfigureNotify
1672///
1673/// On Linux parameters of GUI event kConfigureNotify are different
1674/// than parameters of the same event executed on Windows.
1675/// Therefore we need to distinguish [on Linux], if the event is movement
1676/// or resize event.
1677/// On Windows, we do not need to distinguish them.
1678
1680{
1681 // On both platforms, we mark the events matching the criteria
1682 // (automatically generated in ROOT) as events that should be filtered
1683 // when replaying (TRecGuiEvent::kCNFilter)
1684 if ((e->fX == 0 && e->fY == 0)) { // || e->fFormat == 32 ) {
1685 e->fUser[4] = TRecGuiEvent::kCNFilter;
1686 return;
1687 }
1688
1689#ifdef WIN32
1690
1691 // No need to distinguish between move and resize on Windows
1692 e->fUser[4] = TRecGuiEvent::kCNMoveResize;
1693
1694#else
1695
1696 TGWindow *w = gClient->GetWindowById(e->fWindow);
1697 if (w) {
1698 TGFrame *t = (TGFrame *)w;
1699
1700 // If this event does not cause any change in position or size ->
1701 // automatically generated event
1702 if (t->GetWidth() == e->fWidth && t->GetHeight() == e->fHeight &&
1703 e->fX == t->GetX() && e->fY == t->GetY()) {
1704 e->fUser[4] = TRecGuiEvent::kCNFilter;
1705 }
1706 else {
1707 // Size of the window did not change -> move
1708 if (t->GetWidth() == e->fWidth && t->GetHeight() == e->fHeight) {
1709 e->fUser[4] = TRecGuiEvent::kCNMove;
1710 }
1711 // Size of the window changed -> resize
1712 else {
1713 e->fUser[4] = TRecGuiEvent::kCNResize;
1714 }
1715 }
1716 }
1717
1718#endif
1719}
1720
1721
1722
1723//______________________________________________________________________________
1724// The GUI for the recorder
1725
1727
1728////////////////////////////////////////////////////////////////////////////////
1729/// The GUI for the recorder
1730
1732 TGMainFrame(p ? p : gClient->GetRoot(), w, h)
1733{
1734 TGHorizontalFrame *hframe;
1735 TGVerticalFrame *vframe;
1737 fRecorder = new TRecorder();
1738 fFilteredIds[0] = GetId();
1739
1740 // Create a horizontal frame widget with buttons
1741 hframe = new TGHorizontalFrame(this, 200, 75, kChildFrame | kFixedHeight,
1742 (Pixel_t)0x000000);
1743 fFilteredIds[1] = hframe->GetId();
1744
1745 // LABEL WITH TIME
1746
1747 vframe = new TGVerticalFrame(hframe, 200, 75, kChildFrame | kFixedHeight,
1748 (Pixel_t)0x000000);
1749 fFilteredIds[2] = vframe->GetId();
1750
1751 TGLabel *fStatusLabel = new TGLabel(vframe, "Status:");
1752 fStatusLabel->SetTextColor(0x7cffff);
1753 fStatusLabel->SetBackgroundColor((Pixel_t)0x000000);
1754 vframe->AddFrame(fStatusLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,
1755 2, 2, 2, 2));
1756 fFilteredIds[3] = fStatusLabel->GetId();
1757
1758 TGLabel *fTimeLabel = new TGLabel(vframe, "Time: ");
1759 fTimeLabel->SetTextColor(0x7cffff);
1760 fTimeLabel->SetBackgroundColor((Pixel_t)0x000000);
1761 vframe->AddFrame(fTimeLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,
1762 2, 2, 13, 2));
1763 fFilteredIds[4] = fTimeLabel->GetId();
1764
1765 hframe->AddFrame(vframe, new TGLayoutHints(kLHintsLeft | kLHintsExpandY));
1766
1767 vframe = new TGVerticalFrame(hframe, 200, 75, kChildFrame | kFixedHeight,
1768 (Pixel_t)0x000000);
1769 fFilteredIds[5] = vframe->GetId();
1770
1771 fStatus = new TGLabel(vframe, "Inactive");
1772 fStatus->SetTextColor(0x7cffff);
1775 2, 2, 2, 2));
1776 fFilteredIds[6] = fStatus->GetId();
1777
1778 fTimeDisplay = new TGLabel(vframe, "00:00:00");
1779 fTimeDisplay->SetTextColor(0x7cffff);
1780 fTimeDisplay->SetTextFont("Helvetica -34", kFALSE);
1783 2, 2, 2, 2));
1785
1786 hframe->AddFrame(vframe, new TGLayoutHints(kLHintsLeft | kLHintsExpandY,
1787 10, 0, 0, 0));
1788 AddFrame(hframe, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
1789
1790 // Create a horizontal frame widget with buttons
1791 hframe = new TGHorizontalFrame(this, 200, 200);
1792 fFilteredIds[8] = hframe->GetId();
1793
1794 // START-STOP button
1795 fStartStop = new TGPictureButton(hframe,gClient->GetPicture("record.png"));
1796 fStartStop->SetStyle(gClient->GetStyle());
1797 fStartStop->Connect("Clicked()","TGRecorder",this,"StartStop()");
1799 2, 2, 2, 2));
1800 fStartStop->Resize(40,40);
1802
1803 // REPLAY button
1804 fReplay = new TGPictureButton(hframe,gClient->GetPicture("replay.png"));
1805 fReplay->SetStyle(gClient->GetStyle());
1806 fReplay->Connect("Clicked()","TGRecorder",this,"Replay()");
1808 2, 2, 2, 2));
1809 fReplay->Resize(40,40);
1810 fFilteredIds[10] = fReplay->GetId();
1811
1812 // MOUSE CURSOR CHECKBOX
1813 fCursorCheckBox = new TGCheckButton(this,"Show mouse cursor");
1816
1817 // Timer
1818 fTimer = new TTimer(25);
1819 fTimer->Connect("Timeout()", "TGRecorder", this, "Update()");
1820
1821 AddFrame(hframe, new TGLayoutHints(kLHintsCenterX, 2, 2, 2, 2));
1822
1824 SetWindowName("ROOT Event Recorder");
1825 MapSubwindows();
1826 Layout();
1827 MapWindow();
1828
1829 SetDefault();
1830}
1831
1832////////////////////////////////////////////////////////////////////////////////
1833/// Sets GUI to the default inactive state
1834
1836{
1837 fTimeDisplay->SetText("00:00:00");
1838
1839 fReplay->SetPicture(gClient->GetPicture("replay.png"));
1841
1844
1845 fStartStop->SetPicture(gClient->GetPicture("record.png"));
1847}
1848
1849////////////////////////////////////////////////////////////////////////////////
1850/// Called when fTimer timeouts (every 0.025 second)
1851/// Updates GUI of recorder
1852
1854{
1855 struct tm *running;
1856 static int cnt = 0;
1857 TString stime;
1858 time( &fElapsed );
1859 time_t elapsed_time = (time_t)difftime( fElapsed, fStart );
1860 running = gmtime( &elapsed_time );
1861
1862 switch(fRecorder->GetState()) {
1863
1864 // When recording or replaying, updates timer
1865 // and displays new value of seconds counter
1868
1869 // Every whole second: updates timer and displays new value
1870 if (cnt >= 10) {
1872 fStatus->SetText("Replaying");
1873 else
1874 fStatus->SetText("Recording");
1875 stime.Form("%02d:%02d:%02d", running->tm_hour,
1876 running->tm_min, running->tm_sec);
1877 fTimeDisplay->SetText(stime.Data());
1878
1879 cnt = 0;
1880 if (gVirtualX->EventsPending()) {
1881 fStatus->SetText("Waiting...");
1882 fStatus->SetTextColor((Pixel_t)0xff0000);
1883 }
1884 else {
1885 fStatus->SetTextColor((Pixel_t)0x7cffff);
1886 }
1887 fStatus->Resize();
1889 }
1890 else
1891 ++cnt;
1892
1893 // Changes background color according to the queue of pending events
1894 fTimer->Reset();
1895 break;
1896
1897 // End of replaying or recording. Sets recorder GUI to default state
1899 fStatus->SetText("Inactive");
1900 fStatus->SetTextColor((Pixel_t)0x7cffff);
1901 fStatus->Resize();
1902 fTimer->TurnOff();
1903 SetDefault();
1904 break;
1905
1906 default:
1907 break;
1908 }
1909}
1910
1911////////////////////////////////////////////////////////////////////////////////
1912/// Handles push of the fStartStop button
1913/// according to the current recorder state
1914
1916{
1917 static const char *gFiletypes[] = {
1918 "All files", "*", "Text files", "*.txt", "ROOT files", "*.root", 0, 0
1919 };
1920 TGFileInfo fi;
1921
1922 switch(fRecorder->GetState()) {
1923
1924 // Starts recording
1926
1928 fi.fOverwrite = kFALSE;
1929
1930 new TGFileDialog(gClient->GetDefaultRoot(),
1931 gClient->GetDefaultRoot(),
1932 kFDSave,&fi);
1933
1934 if (fi.fFilename && strlen(fi.fFilename)) {
1935
1936 if (!gROOT->GetListOfCanvases()->IsEmpty()) {
1937 fRecorder->PrevCanvases(fi.fFilename, "RECREATE");
1938 fRecorder->Start(fi.fFilename, "UPDATE", fFilteredIds,
1940 }
1941 else {
1942 fRecorder->Start(fi.fFilename, "RECREATE", fFilteredIds,
1944 }
1946 fStartStop->SetPicture(gClient->GetPicture("stop.png"));
1948 fTimer->TurnOn();
1949 time( &fStart );
1950 }
1951 break;
1952
1953 // Stops recording
1956 break;
1957
1958 // Pauses replaying
1960 fRecorder->Pause();
1961 fStartStop->SetPicture(gClient->GetPicture("replay.png"));
1962 break;
1963
1964 // Resumes replaying
1965 case TRecorder::kPaused:
1966 fRecorder->Resume();
1967 fStartStop->SetPicture(gClient->GetPicture("pause.png"));
1968 break;
1969
1970 default:
1971 break;
1972 } // switch
1973}
1974
1975////////////////////////////////////////////////////////////////////////////////
1976/// Handles push of fReplay button
1977/// according to the current recorder state
1978
1980{
1981 TGFileInfo fi;
1982
1983 switch(fRecorder->GetState()) {
1984
1985 // Starts replaying
1987
1988 new TGFileDialog(gClient->GetDefaultRoot(),
1989 gClient->GetDefaultRoot(),
1990 kFDOpen, &fi);
1991
1992 if (fi.fFilename && strlen(fi.fFilename)) {
1994
1995 fTimer->TurnOn();
1996 time( &fStart );
1997
1998 fReplay->SetPicture(gClient->GetPicture("stop.png"));
1999 fStartStop->SetPicture(gClient->GetPicture("pause.png"));
2000
2001 if (fCursorCheckBox->IsOn())
2003
2005 }
2006 }
2007 break;
2008
2009 // Stops replaying
2011 case TRecorder::kPaused:
2013 break;
2014
2015 default:
2016 break;
2017
2018 } // switch
2019}
2020
2021////////////////////////////////////////////////////////////////////////////////
2022/// Destructor. Cleanup the GUI.
2023
2025{
2026 fTimer->TurnOff();
2027 delete fTimer;
2028 Cleanup();
2029}
2030
2031//______________________________________________________________________________
2032// Helper class
2033
2036
2037////////////////////////////////////////////////////////////////////////////////
2038/// Replays stored GUI event
2039
2041{
2042 Int_t px, py, dx, dy;
2043 Window_t wtarget;
2044 Event_t *e = CreateEvent(this);
2045
2046 // don't try to replay any copy/paste event, as event->fUser[x]
2047 // parameters are invalid on different OSes
2048 if (e->fType == kSelectionClear || e->fType == kSelectionRequest ||
2049 e->fType == kSelectionNotify) {
2050 delete e;
2051 return;
2052 }
2053
2054 // Replays movement/resize event
2055 if (e->fType == kConfigureNotify) {
2056 TGWindow *w = gClient->GetWindowById(e->fWindow);
2057
2058 // Theoretically, w should always exist (we found the right mapping,
2059 // otherwise we would not get here).
2060 // Anyway, it can happen that it was destroyed by some earlier ROOT event
2061 // We give higher priority to automatically generated
2062 // ROOT events in TRecorderReplaying::ReplayRealtime.
2063
2064 if (w) {
2065 WindowAttributes_t attr;
2066 if (e->fUser[4] == TRecGuiEvent::kCNMove) {
2067 // Linux: movement of the window
2068 // first get window attribute to compensate the border size
2069 gVirtualX->GetWindowAttributes(e->fWindow, attr);
2070 if ((e->fX - attr.fX > 0) && (e->fY - attr.fY > 0))
2071 w->Move(e->fX - attr.fX, e->fY - attr.fY);
2072 }
2073 else {
2074 if (e->fUser[4] == TRecGuiEvent::kCNResize) {
2075 // Linux: resize of the window
2076 w->Resize(e->fWidth, e->fHeight);
2077 }
2078 else {
2079 if (e->fUser[4] == TRecGuiEvent::kCNMoveResize) {
2080 // Windows: movement or resize of the window
2081 w->MoveResize(e->fX, e->fY, e->fWidth, e->fHeight);
2082 }
2083 else {
2084 if (gDebug > 0)
2085 Error("TRecGuiEvent::ReplayEvent",
2086 "kConfigureNotify: Unknown value: fUser[4] = %ld ",
2087 e->fUser[4]);
2088 }
2089 }
2090 }
2091 }
2092 else {
2093 // w = 0
2094 if (gDebug > 0)
2095 Error("TRecGuiEvent::ReplayEvent",
2096 "kConfigureNotify: Window does not exist anymore ");
2097 }
2098 delete e;
2099 return;
2100
2101 } // kConfigureNotify
2102
2103 if (showMouseCursor && e->fType == kButtonPress) {
2104 gVirtualX->TranslateCoordinates(e->fWindow, gVirtualX->GetDefaultRootWindow(),
2105 e->fX, e->fY, px, py, wtarget);
2106 dx = px - gCursorWin->GetX();
2107 dy = py - gCursorWin->GetY();
2108 if (TMath::Abs(dx) > 5) gDecorWidth += dx;
2109 if (TMath::Abs(dy) > 5) gDecorHeight += dy;
2110 }
2111 // Displays fake mouse cursor for MotionNotify event
2112 if (showMouseCursor && e->fType == kMotionNotify) {
2113 if (gCursorWin && e->fWindow == gVirtualX->GetDefaultRootWindow()) {
2114 if (!gCursorWin->IsMapped()) {
2116 }
2117 if (gVirtualX->GetDrawMode() == TVirtualX::kCopy) {
2118//#ifdef R__MACOSX
2119 // this may have side effects (e.g. stealing focus)
2121//#endif
2122 gCursorWin->Move(e->fXRoot + gDecorWidth, e->fYRoot + gDecorHeight);
2123 }
2124 }
2125 }
2126
2127 // Lets all the other events to be handled the same way as when recording
2128 // first, special case for the gui builder, having a timer handling
2129 // some of the events
2130 if (e->fType == kOtherEvent && e->fFormat >= kGKeyPress &&
2131 e->fFormat < kOtherEvent) {
2132 e->fType = (EGEventType)e->fFormat;
2133 if (gDragManager)
2135 delete e;
2136 return;
2137 }
2138 else { // then the normal cases
2139 if (!fMasked)
2140 gClient->HandleEvent(e);
2141 else
2142 gClient->HandleMaskEvent(e, fMasked);
2143 }
2144 delete e;
2145}
2146
2147////////////////////////////////////////////////////////////////////////////////
2148/// Converts TRecGuiEvent type to Event_t type
2149
2151{
2152 Event_t *e = new Event_t();
2153
2154 // Copies all data items
2155
2156 e->fType = ge->fType;
2157 e->fWindow = ge->fWindow;
2158 e->fTime = ge->fTime;
2159
2160 e->fX = ge->fX;
2161 e->fY = ge->fY;
2162 e->fXRoot = ge->fXRoot;
2163 e->fYRoot = ge->fYRoot;
2164
2165 e->fCode = ge->fCode;
2166 e->fState = ge->fState;
2167
2168 e->fWidth = ge->fWidth;
2169 e->fHeight = ge->fHeight;
2170
2171 e->fCount = ge->fCount;
2172 e->fSendEvent = ge->fSendEvent;
2173
2174 e->fHandle = ge->fHandle;
2175 e->fFormat = ge->fFormat;
2176
2177 if (e->fHandle == TRecGuiEvent::kROOT_MESSAGE)
2178 e->fHandle = gROOT_MESSAGE;
2179
2180 for(Int_t i=0; i<5; ++i)
2181 e->fUser[i] = ge->fUser[i];
2182
2183 if (e->fUser[0] == TRecGuiEvent::kWM_DELETE_WINDOW)
2184 e->fUser[0] = gWM_DELETE_WINDOW;
2185
2186 if (ge->fType == kGKeyPress || ge->fType == kKeyRelease) {
2187 e->fCode = gVirtualX->KeysymToKeycode(ge->fCode);
2188#ifdef R__WIN32
2189 e->fUser[1] = 1;
2190 e->fUser[2] = e->fCode;
2191#endif
2192 }
2193
2194 return e;
2195}
2196
@ kPaveLabel
Definition Buttons.h:31
@ kText
Definition Buttons.h:30
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
const Mask_t kWASaveUnder
Definition GuiTypes.h:150
Handle_t Pixmap_t
Pixmap handle.
Definition GuiTypes.h:30
@ kChildFrame
Definition GuiTypes.h:379
@ kTempFrame
Definition GuiTypes.h:393
@ kFixedHeight
Definition GuiTypes.h:389
Handle_t Atom_t
WM token.
Definition GuiTypes.h:37
const Mask_t kKeyControlMask
Definition GuiTypes.h:197
ULong_t Pixel_t
Pixel value.
Definition GuiTypes.h:40
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
@ kKey_S
Definition KeySymbols.h:144
ROOT::R::TRInterface & r
Definition Object.C:4
#define f(i)
Definition RSha256.hxx:104
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
int Int_t
Definition RtypesCore.h:45
const Bool_t kFALSE
Definition RtypesCore.h:101
long Long_t
Definition RtypesCore.h:54
long long Long64_t
Definition RtypesCore.h:80
unsigned long long ULong64_t
Definition RtypesCore.h:81
const Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:364
R__EXTERN TApplication * gApplication
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:220
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:187
#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[]
Int_t gDebug
Definition TROOT.cxx:592
#define gROOT
Definition TROOT.h:404
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:559
R__EXTERN TVirtualDragManager * gDragManager
#define gPad
#define gVirtualX
Definition TVirtualX.h:338
R__EXTERN Atom_t gROOT_MESSAGE
Definition TVirtualX.h:40
R__EXTERN Atom_t gWM_DELETE_WINDOW
Definition TVirtualX.h:38
virtual Float_t GetTextSize() const
Return the text size.
Definition TAttText.h:36
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:35
Double_t GetX1() const
Definition TBox.h:50
Double_t GetX2() const
Definition TBox.h:51
Double_t GetY1() const
Definition TBox.h:52
Double_t GetY2() const
Definition TBox.h:53
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:2199
UInt_t GetWindowHeight() const
Definition TCanvas.h:160
void Draw(Option_t *option="") override
Draw a canvas.
Definition TCanvas.cxx:843
UInt_t GetWindowWidth() const
Definition TCanvas.h:159
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write all objects in this collection.
TObject * Get(const char *namecycle) override
Return pointer to object identified by namecycle.
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition TFile.h:54
virtual Bool_t IsOpen() const
Returns kTRUE in case file is open and kFALSE if file is not open.
Definition TFile.cxx:1407
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:4025
Int_t Write(const char *name=nullptr, Int_t opt=0, Int_t bufsiz=0) override
Write memory objects to this file.
Definition TFile.cxx:2374
void Close(Option_t *option="") override
Close a file.
Definition TFile.cxx:899
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:271
virtual void SetEnabled(Bool_t e=kTRUE)
Set enabled or disabled state of button.
Definition TGButton.cxx:459
Selects different options.
Definition TGButton.h:264
virtual Bool_t IsOn() const
Definition TGButton.h:311
virtual void SetDisabledAndSelected(Bool_t)
Set the state of a check button to disabled and either on or off.
const TGPicture * GetPicture(const char *name)
Get picture from the picture pool.
Definition TGClient.cxx:289
virtual void AddFrame(TGFrame *f, TGLayoutHints *l=0)
Add frame to the composite frame using the specified layout hints.
Definition TGFrame.cxx:1117
virtual void Cleanup()
Cleanup and delete all objects contained in this composite frame.
Definition TGFrame.cxx:967
virtual void Layout()
Layout the elements of the composite frame.
Definition TGFrame.cxx:1257
virtual void SetCleanup(Int_t mode=kLocalCleanup)
Turn on automatic cleanup of child frames in dtor.
Definition TGFrame.cxx:1072
virtual void MapSubwindows()
Map all sub windows that are part of the composite frame.
Definition TGFrame.cxx:1164
virtual void SetEditDisabled(UInt_t on=1)
Set edit disable flag for this frame and subframes.
Definition TGFrame.cxx:1022
virtual ~TGCursorWindow()
Destructor.
TGCursorWindow()
TGCursorWindow constructor.
This class creates a file selection dialog.
char * fFilename
selected file name
const char ** fFileTypes
file types used to filter selectable files
Bool_t fOverwrite
if true overwrite the file with existing name on save
A subclasses of TGWindow, and is used as base class for some simple widgets (buttons,...
Definition TGFrame.h:80
virtual void MapRaised()
map raised
Definition TGFrame.h:205
virtual void SetBackgroundColor(Pixel_t back)
Set background color (override from TGWindow base class).
Definition TGFrame.cxx:312
Int_t GetX() const
Definition TGFrame.h:231
virtual void DeleteWindow()
Delete window.
Definition TGFrame.cxx:276
virtual void Move(Int_t x, Int_t y)
Move frame.
Definition TGFrame.cxx:593
virtual void Resize(UInt_t w=0, UInt_t h=0)
Resize the frame.
Definition TGFrame.cxx:605
UInt_t GetHeight() const
Definition TGFrame.h:225
Int_t GetY() const
Definition TGFrame.h:232
virtual void MapWindow()
map window
Definition TGFrame.h:204
UInt_t GetWidth() const
Definition TGFrame.h:224
A composite frame that layout their children in horizontal way.
Definition TGFrame.h:386
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:362
virtual void SetText(TGString *newText)
Set new text in label.
Definition TGLabel.cxx:180
virtual void SetTextFont(TGFont *font, Bool_t global=kFALSE)
Changes text font specified by pointer to TGFont object.
Definition TGLabel.cxx:324
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:398
void SetWindowName(const char *name=0)
Set window name. This is typically done via the window manager.
Definition TGFrame.cxx:1788
TGClient * fClient
Connection to display server.
Definition TGObject.h:27
Handle_t GetId() const
Definition TGObject.h:37
Handle_t fId
X11/Win32 Window identifier.
Definition TGObject.h:26
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
Pixmap_t GetMask() const
Definition TGPicture.h:55
Pixmap_t GetPicture() const
Definition TGPicture.h:54
Provides GUI for TRecorder class.
Definition TRecorder.h:631
Window_t fFilteredIds[fgWidgetsCount]
Definition TRecorder.h:646
time_t fStart
Definition TRecorder.h:643
TGPictureButton * fStartStop
Definition TRecorder.h:635
virtual ~TGRecorder()
Destructor. Cleanup the GUI.
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
TGRecorder(const TGWindow *p=0, UInt_t w=230, UInt_t h=150)
The GUI for the recorder.
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
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:375
ROOT GUI Window base class.
Definition TGWindow.h:23
virtual void Move(Int_t x, Int_t y)
Move the window.
Definition TGWindow.cxx:271
virtual void SetBackgroundPixmap(Pixmap_t pixmap)
set background pixmap
Definition TGWindow.cxx:248
@ kEditDisableGrab
window grab cannot be edited
Definition TGWindow.h:52
@ kEditDisable
disable edit of this window
Definition TGWindow.h:50
virtual void MoveResize(Int_t x, Int_t y, UInt_t w, UInt_t h)
Move and resize the window.
Definition TGWindow.cxx:287
const TGWindow * GetParent() const
Definition TGWindow.h:76
virtual Bool_t IsMapped()
Returns kTRUE if window is mapped on screen, kFALSE otherwise.
Definition TGWindow.cxx:295
virtual void Resize(UInt_t w, UInt_t h)
Resize the window.
Definition TGWindow.cxx:279
virtual void RaiseWindow()
raise window
Definition TGWindow.cxx:208
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:750
To draw Mathematical Formula.
Definition TLatex.h:18
Iterator of linked list.
Definition TList.h:191
TObject * Next()
Return next object in the list. Returns 0 when no more objects in list.
Definition TList.cxx:1111
A doubly linked list.
Definition TList.h:38
virtual void Add(TObject *obj)
Definition TList.h:81
Int_t UnLock()
Unlock the mutex.
Definition TMutex.cxx:68
Int_t Lock()
Lock the mutex.
Definition TMutex.cxx:46
virtual const char * GetTitle() const
Returns title of object.
Definition TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Mother of all ROOT objects.
Definition TObject.h:41
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition TObject.cxx:868
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:153
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:515
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:963
A Pave (see TPave) with a text centered in the Pave.
Definition TPaveLabel.h:20
const char * GetLabel() const
Definition TPaveLabel.h:42
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:869
Bool_t Disconnect(const char *signal=0, void *receiver=0, const char *slot=0)
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
virtual void ReplayEvent(Bool_t showMouseCursor=kTRUE)
Replays stored GUI event.
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
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
virtual void ListCmd(const char *filename)
Prints out commandline events recorded in given file.
virtual void Start(TRecorder *r, const char *filename, Option_t *option, Window_t *w=0, Int_t winCount=0)
Switches from INACTIVE state to RECORDING and starts recording.
void PrevCanvases(const char *filename, Option_t *option)
Save previous canvases in a .root file.
TSeqCollection * fCollect
Definition TRecorder.h:567
virtual Bool_t Replay(TRecorder *r, const char *filename, Bool_t showMouseCursor, TRecorder::EReplayModes mode)
Switches from INACTIVE state of recorder to REPLAYING Return kTRUE if replaying has started or kFALSE...
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
virtual void ListGui(const char *filename)
Prints out GUI events recorded in given file.
Represents state of TRecorder when replaying was paused by a user.
Definition TRecorder.h:603
TRecorderReplaying * fReplayingState
Definition TRecorder.h:607
virtual void Resume(TRecorder *r)
Continues replaying.
TRecorderPaused(TRecorderReplaying *state)
Remember the recorder state that is paused.
virtual void ReplayStop(TRecorder *r)
Replaying is cancelled.
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
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.
virtual void Stop(TRecorder *r, Bool_t guiCommand)
Disconnects all slots and stopps recording.
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()
virtual ~TRecorderRecording()
Freeing of allocated memory.
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 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
virtual void ReplayStop(TRecorder *r)
Cancels replaying.
virtual ~TRecorderReplaying()
Closes all signal-slot connections Frees all memory allocated in constructor.
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...
virtual void Pause(TRecorder *r)
Pauses replaying.
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
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 Start(const char *filename, Option_t *option="RECREATE", Window_t *w=0, Int_t winCount=0)
Starts recording events.
void ListGui(const char *filename)
Prints out recorded GUI events.
void Pause()
Pauses replaying.
void Browse(TBrowser *)
Browse the recorder from a ROOT file.
void ListCmd(const char *filename)
Prints out recorded commandline events.
virtual ~TRecorder()
Destructor.
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:136
const char * Data() const
Definition TString.h:369
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2314
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition TSystem.cxx:935
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:419
Double_t GetX() const
Definition TText.h:53
Double_t GetY() const
Definition TText.h:61
Basic time type with millisecond precision.
Definition TTime.h:27
const char * AsString() const
Return the time as a string.
Definition TTime.cxx:28
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:229
virtual void Start(Long_t milliSec=-1, Bool_t singleShot=kFALSE)
Starts the timer with a milliSec timeout.
Definition TTimer.cxx:211
virtual void TurnOn()
Add the timer to the system timer list.
Definition TTimer.cxx:241
void Reset()
Reset the timer.
Definition TTimer.cxx:157
virtual void Stop()
Definition TTimer.h:94
A TTree represents a columnar dataset.
Definition TTree.h:79
virtual Int_t Fill()
Fill all branches.
Definition TTree.cxx:4594
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:5622
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition TTree.cxx:8356
virtual Long64_t GetEntries() const
Definition TTree.h:460
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:350
virtual Bool_t HandleTimerEvent(Event_t *, TTimer *)
TLine * line
const Int_t n
Definition legend1.C:16
Short_t Abs(Short_t d)
Definition TMathBase.h:120
Definition file.py:1
Event structure.
Definition GuiTypes.h:174
EGEventType fType
of event (see EGEventType)
Definition GuiTypes.h:175
Int_t fY
pointer x, y coordinates in event window
Definition GuiTypes.h:178
Int_t fXRoot
Definition GuiTypes.h:179
Bool_t fSendEvent
true if event came from SendEvent
Definition GuiTypes.h:184
Handle_t fHandle
general resource handle (used for atoms or windows)
Definition GuiTypes.h:185
Int_t fFormat
Next fields only used by kClientMessageEvent.
Definition GuiTypes.h:186
UInt_t fWidth
Definition GuiTypes.h:182
UInt_t fHeight
width and height of exposed area
Definition GuiTypes.h:182
Int_t fCount
if non-zero, at least this many more exposes
Definition GuiTypes.h:183
Window_t fWindow
window reported event is relative to
Definition GuiTypes.h:176
UInt_t fState
key or button mask
Definition GuiTypes.h:181
Int_t fYRoot
coordinates relative to root
Definition GuiTypes.h:179
Int_t fX
Definition GuiTypes.h:178
Time_t fTime
time event event occurred in ms
Definition GuiTypes.h:177
UInt_t fCode
key or button code
Definition GuiTypes.h:180
Longptr_t fUser[5]
5 longs can be used by client message events NOTE: only [0], [1] and [2] may be used.
Definition GuiTypes.h:187
Attributes that can be used when creating or changing a window.
Definition GuiTypes.h:93
Bool_t fOverrideRedirect
boolean value for override-redirect
Definition GuiTypes.h:107
Mask_t fMask
bit mask specifying which fields are valid
Definition GuiTypes.h:110
Bool_t fSaveUnder
should bits under be saved (popups)?
Definition GuiTypes.h:104
Window attributes that can be inquired.
Definition GuiTypes.h:114
Int_t fY
location of window
Definition GuiTypes.h:115
auto * t1
Definition textangle.C:20