Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TPad.cxx
Go to the documentation of this file.
1// @(#)root/gpad:$Id$
2// Author: Rene Brun 12/12/94
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, 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#include <cstring>
13#include <cstdlib>
14#include <iostream>
15#include <locale>
16#include <memory>
17
18#include "TROOT.h"
19#include "TBuffer.h"
20#include "TError.h"
21#include "TMath.h"
22#include "TSystem.h"
23#include "TStyle.h"
24#include "TFile.h"
25#include "TH1.h"
26#include "TH2.h"
27#include "TH3.h"
28#include "TClass.h"
29#include "TBaseClass.h"
30#include "TClassTable.h"
31#include "TVirtualPS.h"
32#include "TVirtualX.h"
33#include "TVirtualViewer3D.h"
34#include "TView.h"
35#include "TPoint.h"
36#include "TGraph.h"
37#include "TMultiGraph.h"
38#include "THStack.h"
39#include "TPaveText.h"
40#include "TPaveStats.h"
41#include "TGroupButton.h"
42#include "TBrowser.h"
43#include "TVirtualGL.h"
44#include "TString.h"
45#include "TDataMember.h"
46#include "TMethod.h"
47#include "TDataType.h"
48#include "TFrame.h"
49#include "TWbox.h"
50#include "TExec.h"
51#include "TDatime.h"
52#include "TColor.h"
53#include "TCanvas.h"
54#include "TCanvasImp.h"
55#include "TPluginManager.h"
56#include "TEnv.h"
57#include "TImage.h"
58#include "TViewer3DPad.h"
59#include "TCreatePrimitives.h"
60#include "TLegend.h"
61#include "TAtt3D.h"
62#include "TVirtualPadPainter.h"
63#include "strlcpy.h"
64#include "snprintf.h"
65
66#include "TVirtualMutex.h"
67
68static Int_t gReadLevel = 0;
69
71
72/** \class TPad
73\ingroup gpad
74
75The most important graphics class in the ROOT system.
76
77A Pad is contained in a Canvas.
78
79A Pad may contain other pads (unlimited pad hierarchy).
80
81A pad is a linked list of primitives of any type (graphics objects,
82histograms, detectors, tracks, etc.).
83
84Adding a new element into a pad is in general performed by the Draw
85member function of the object classes.
86
87It is important to realize that the pad is a linked list of references
88to the original object.
89For example, in case of a histogram, the histogram.Draw() operation
90only stores a reference to the histogram object and not a graphical
91representation of this histogram.
92When the mouse is used to change (say the bin content), the bin content
93of the original histogram is changed.
94
95The convention used in ROOT is that a Draw operation only adds
96a reference to the object. The effective drawing is performed
97when the canvas receives a signal to be painted.
98
99\image html gpad_pad1.png
100
101This signal is generally sent when typing carriage return in the
102command input or when a graphical operation has been performed on one
103of the pads of this canvas.
104When a Canvas/Pad is repainted, the member function Paint for all
105objects in the Pad linked list is invoked.
106
107\image html gpad_pad2.png
108
109When the mouse is moved on the Pad, The member function DistancetoPrimitive
110is called for all the elements in the pad. DistancetoPrimitive returns
111the distance in pixels to this object.
112
113When the object is within the distance window, the member function
114ExecuteEvent is called for this object.
115
116In ExecuteEvent, move, changes can be performed on the object.
117
118For examples of DistancetoPrimitive and ExecuteEvent functions,
119see classes
120~~~ {.cpp}
121 TLine::DistancetoPrimitive, TLine::ExecuteEvent
122 TBox::DistancetoPrimitive, TBox::ExecuteEvent
123 TH1::DistancetoPrimitive, TH1::ExecuteEvent
124~~~
125A Pad supports linear and log scales coordinate systems.
126The transformation coefficients are explained in TPad::ResizePad.
127*/
128
129////////////////////////////////////////////////////////////////////////////////
130/// Pad default constructor.
131
133{
135 fTip = nullptr;
136 fPadPointer = nullptr;
137 fPrimitives = nullptr;
138 fExecs = nullptr;
139 fCanvas = nullptr;
140 fPadPaint = 0;
141 fPixmapID = -1;
142 fGLDevice = -1;
145 fTheta = 30;
146 fPhi = 30;
147 fNumber = 0;
150 fCrosshair = 0;
151 fCrosshairPos = 0;
152 fPadView3D = nullptr;
153 fMother = (TPad*)gPad;
154
155 fAbsHNDC = 0.;
156 fAbsPixeltoXk = 0.;
157 fAbsPixeltoYk = 0.;
158 fAbsWNDC = 0.;
159 fAbsXlowNDC = 0.;
160 fAbsYlowNDC = 0.;
161 fBorderMode = 0;
162 fBorderSize = 0;
163 fPixeltoX = 0;
164 fPixeltoXk = 0.;
165 fPixeltoY = 0.;
166 fPixeltoYk = 0.;
167 fUtoAbsPixelk = 0.;
168 fUtoPixel = 0.;
169 fUtoPixelk = 0.;
170 fVtoAbsPixelk = 0.;
171 fVtoPixel = 0.;
172 fVtoPixelk = 0.;
173 fXtoAbsPixelk = 0.;
174 fXtoPixel = 0.;
175 fXtoPixelk = 0.;
176 fYtoAbsPixelk = 0.;
177 fYtoPixel = 0.;
178 fYtoPixelk = 0.;
179 fXUpNDC = 0.;
180 fYUpNDC = 0.;
181
183 fAspectRatio = 0.;
184
187 fCGnx = 0;
188 fCGny = 0;
189
190 fLogx = 0;
191 fLogy = 0;
192 fLogz = 0;
193 fGridx = false;
194 fGridy = false;
195 fTickx = 0;
196 fTicky = 0;
197 fFrame = nullptr;
198 fView = nullptr;
199
200 fUxmin = fUymin = fUxmax = fUymax = 0;
201
202 // Set default world coordinates to NDC [0,1]
203 fX1 = 0;
204 fX2 = 1;
205 fY1 = 0;
206 fY2 = 1;
207
208 // Set default pad range
209 fXlowNDC = 0;
210 fYlowNDC = 0;
211 fWNDC = 1;
212 fHNDC = 1;
213
214 fViewer3D = nullptr;
216
217 // the following line is temporarily disabled. It has side effects
218 // when the pad is a TDrawPanelHist or a TFitPanel.
219 // the line was supposed to fix a problem with DrawClonePad
220 // gROOT->SetSelectedPad(this);
221}
222
223////////////////////////////////////////////////////////////////////////////////
224/// Pad constructor.
225///
226/// A pad is a linked list of primitives.
227/// A pad is contained in a canvas. It may contain other pads.
228/// A pad has attributes. When a pad is created, the attributes
229/// defined in the current style are copied to the pad attributes.
230///
231/// \param[in] name pad name
232/// \param[in] title pad title
233/// \param[in] xlow [0,1] is the position of the bottom left point of the pad
234/// expressed in the mother pad reference system
235/// \param[in] ylow [0,1] is the Y position of this point.
236/// \param[in] xup [0,1] is the x position of the top right point of the pad
237/// expressed in the mother pad reference system
238/// \param[in] yup [0,1] is the Y position of this point.
239/// \param[in] color pad color
240/// \param[in] bordersize border size in pixels
241/// \param[in] bordermode border mode
242/// - bordermode = -1 box looks as it is behind the screen
243/// - bordermode = 0 no special effects
244/// - bordermode = 1 box looks as it is in front of the screen
245
246TPad::TPad(const char *name, const char *title, Double_t xlow,
247 Double_t ylow, Double_t xup, Double_t yup,
249 : TVirtualPad(name,title,xlow,ylow,xup,yup,color,bordersize,bordermode)
250{
252 fTip = nullptr;
255 if (gPad) fCanvas = gPad->GetCanvas();
256 else fCanvas = (TCanvas*)this;
257 fMother = (TPad*)gPad;
258 fPrimitives = new TList;
259 fExecs = new TList;
260 fPadPointer = nullptr;
261 fTheta = 30;
262 fPhi = 30;
267 fFrame = nullptr;
268 fView = nullptr;
269 fPadPaint = 0;
270 fPadView3D = nullptr;
271 fPixmapID = -1; // -1 means pixmap will be created by ResizePad()
274 fNumber = 0;
277 fCrosshair = 0;
278 fCrosshairPos = 0;
279
280 fVtoAbsPixelk = 0.;
281 fVtoPixelk = 0.;
282 fVtoPixel = 0.;
283 fAbsPixeltoXk = 0.;
284 fPixeltoXk = 0.;
285 fPixeltoX = 0;
286 fAbsPixeltoYk = 0.;
287 fPixeltoYk = 0.;
288 fPixeltoY = 0.;
289 fXlowNDC = 0;
290 fYlowNDC = 0;
291 fWNDC = 1;
292 fHNDC = 1;
293 fXUpNDC = 0.;
294 fYUpNDC = 0.;
295 fAbsXlowNDC = 0.;
296 fAbsYlowNDC = 0.;
297 fAbsWNDC = 0.;
298 fAbsHNDC = 0.;
299 fXtoAbsPixelk = 0.;
300 fXtoPixelk = 0.;
301 fXtoPixel = 0.;
302 fYtoAbsPixelk = 0.;
303 fYtoPixelk = 0.;
304 fYtoPixel = 0.;
305 fUtoAbsPixelk = 0.;
306 fUtoPixelk = 0.;
307 fUtoPixel = 0.;
308
309 fUxmin = fUymin = fUxmax = fUymax = 0;
313
315 fAspectRatio = 0.;
316
319 fCGnx = 0;
320 fCGny = 0;
321
322 fViewer3D = nullptr;
323
325 // Set default world coordinates to NDC [0,1]
326 fX1 = 0;
327 fX2 = 1;
328 fY1 = 0;
329 fY2 = 1;
330
331 if (!gPad) {
332 Error("TPad", "You must create a TCanvas before creating a TPad");
333 MakeZombie();
334 return;
335 }
336
338
340
341 if ((xlow < 0) || (xlow > 1) || (ylow < 0) || (ylow > 1)) {
342 Error("TPad", "illegal bottom left position: x=%f, y=%f", xlow, ylow);
343 zombie = kTRUE;
344 } else if ((xup < 0) || (xup > 1) || (yup < 0) || (yup > 1)) {
345 Error("TPad", "illegal top right position: x=%f, y=%f", xup, yup);
346 zombie = kTRUE;
347 } else if (xup-xlow <= 0) {
348 Error("TPad", "illegal width: %f", xup-xlow);
349 zombie = kTRUE;
350 } else if (yup-ylow <= 0) {
351 Error("TPad", "illegal height: %f", yup-ylow);
352 zombie = kTRUE;
353 }
354
355 if (zombie) {
356 // error in creating pad occurred, make this pad a zombie
357 MakeZombie();
358 return;
359 }
360
361
365
366 fUxmin = fUymin = fUxmax = fUymax = 0;
367
368 // Set pad parameters and Compute conversion coefficients
369 SetPad(name, title, xlow, ylow, xup, yup, color, bordersize, bordermode);
370 Range(0, 0, 1, 1);
373}
374
375
376////////////////////////////////////////////////////////////////////////////////
377/// Pad destructor.
378
380{
381 if (ROOT::Detail::HasBeenDeleted(this)) return;
382 Close();
385 auto primitives = fPrimitives;
386 // In some cases, fPrimitives has the kMustCleanup bit set which will lead
387 // its destructor to call RecursiveRemove and since this pad is still
388 // likely to be (indirectly) in the list of cleanups, we must set
389 // fPrimitives to nullptr to avoid TPad::RecursiveRemove from calling
390 // a member function of a partially destructed object.
391 fPrimitives = nullptr;
392 delete primitives;
394 delete fViewer3D;
395
396 // Required since we overload TObject::Hash.
398 if (this == gPad)
399 gPad = nullptr;
400}
401
402////////////////////////////////////////////////////////////////////////////////
403/// Add an object to list of primitives with specified draw option
404/// When \par modified set to kTRUE (default) pad will be marked as modified
405/// Let avoid usage of gPad when drawing object(s) in canvas or in subpads.
406///
407/// ~~~{.cpp}
408/// auto c1 = new TCanvas("c1","Canvas with subpoads", 600, 600);
409/// c1->Divide(2,2);
410///
411/// for (Int_t n = 1; n <= 4; ++n) {
412/// auto h1 = new TH1I(TString::Format("hist_%d",n), "Random hist", 100, -5, 5);
413/// h1->FillRandom("gaus", 2000 + n*1000);
414/// c1->GetPad(n)->Add(h1);
415/// }
416/// ~~~
417
419{
420 if (!obj)
421 return;
422
423 if (!fPrimitives)
424 fPrimitives = new TList;
425
426 obj->SetBit(kMustCleanup);
427
428 fPrimitives->Add(obj, opt);
429
430 if (modified)
431 Modified();
432}
433
434////////////////////////////////////////////////////////////////////////////////
435/// Add an object as first in list of primitives with specified draw option
436/// When \par modified set to kTRUE (default) pad will be marked as modified
437/// Let avoid usage of gPad when drawing object(s) in canvas or in subpads.
438
440{
441 if (!obj)
442 return;
443
444 if (!fPrimitives)
445 fPrimitives = new TList;
446
447 obj->SetBit(kMustCleanup);
448
449 fPrimitives->AddFirst(obj, opt);
450
451 if (modified)
452 Modified();
453}
454
455////////////////////////////////////////////////////////////////////////////////
456/// Add a new TExec object to the list of Execs.
457///
458/// When an event occurs in the pad (mouse click, etc) the list of C++ commands
459/// in the list of Execs are executed via TPad::AutoExec.
460///
461/// When a pad event occurs (mouse move, click, etc) all the commands
462/// contained in the fExecs list are executed in the order found in the list.
463///
464/// This facility is activated by default. It can be deactivated by using
465/// the canvas "Option" menu.
466///
467/// The following examples of TExec commands are provided in the tutorials:
468/// macros exec1.C and exec2.C.
469///
470/// ### Example1 of use of exec1.C
471///
472/// ~~~ {.cpp}
473/// Root > TFile f("hsimple.root")
474/// Root > hpx.Draw()
475/// Root > c1.AddExec("ex1",".x exec1.C")
476/// ~~~
477///
478/// At this point you can use the mouse to click on the contour of
479/// the histogram hpx. When the mouse is clicked, the bin number and its
480/// contents are printed.
481///
482/// ### Example2 of use of exec1.C
483///
484/// ~~~ {.cpp}
485/// Root > TFile f("hsimple.root")
486/// Root > hpxpy.Draw()
487/// Root > c1.AddExec("ex2",".x exec2.C")
488/// ~~~
489///
490/// When moving the mouse in the canvas, a second canvas shows the
491/// projection along X of the bin corresponding to the Y position
492/// of the mouse. The resulting histogram is fitted with a gaussian.
493/// A "dynamic" line shows the current bin position in Y.
494/// This more elaborated example can be used as a starting point
495/// to develop more powerful interactive applications exploiting the C++
496/// interpreter as a development engine.
497
498void TPad::AddExec(const char *name, const char *command)
499{
500 if (!fExecs) fExecs = new TList;
501 TExec *ex = new TExec(name,command);
502 fExecs->Add(ex);
503}
504
505////////////////////////////////////////////////////////////////////////////////
506/// Execute the list of Execs when a pad event occurs.
507
509{
510 if (GetCrosshair())
512
513 if (!fExecs)
514 return;
515 TIter next(fExecs);
516 while (auto exec = (TExec*)next())
517 exec->Exec();
518}
519
520////////////////////////////////////////////////////////////////////////////////
521/// Browse pad.
522
524{
525 cd();
527}
528
529////////////////////////////////////////////////////////////////////////////////
530/// Build a legend from the graphical objects in the pad.
531///
532/// A simple method to build automatically a TLegend from the primitives in a TPad.
533///
534/// Only those deriving from TAttLine, TAttMarker and TAttFill are added, excluding
535/// TPave and TFrame derived classes.
536///
537/// \return The built TLegend
538///
539/// \param[in] x1, y1, x2, y2 The TLegend coordinates
540/// \param[in] title The legend title. By default it is " "
541/// \param[in] option The TLegend option
542///
543/// The caller program owns the returned TLegend.
544///
545/// If the pad contains some TMultiGraph or THStack the individual
546/// graphs or histograms in them are added to the TLegend.
547///
548/// ### Automatic placement of the legend
549/// If `x1` is equal to `x2` and `y1` is equal to `y2` the legend will be automatically
550/// placed to avoid overlapping with the existing primitives already displayed.
551/// `x1` is considered as the width of the legend and `y1` the height. By default
552/// the legend is automatically placed with width = `x1`= `x2` = 0.3 and
553/// height = `y1`= `y2` = 0.21.
554
556 const char* title, Option_t *option)
557{
559 if (!lop) return nullptr;
560 TList *lof = nullptr;
561 TLegend *leg = nullptr;
562 TObject *obj = nullptr;
563 TIter next(lop);
564 TString mes;
565 TString opt;
566
567 auto AddEntryFromListOfFunctions = [&]() {
569 while ((obj = nextobj())) {
570 if (obj->InheritsFrom(TNamed::Class())) {
571 if (strlen(obj->GetTitle()))
572 mes = obj->GetTitle();
573 else
574 mes = obj->GetName();
575 } else {
576 mes = obj->ClassName();
577 }
578 leg->AddEntry(obj, mes.Data(), "lpf");
579 }
580 };
581
582 while(auto o = next()) {
583 if ((o->InheritsFrom(TAttLine::Class()) || o->InheritsFrom(TAttMarker::Class()) ||
584 o->InheritsFrom(TAttFill::Class())) &&
585 ( !(o->InheritsFrom(TFrame::Class())) && !(o->InheritsFrom(TPave::Class())) )) {
586 if (!leg)
587 leg = new TLegend(x1, y1, x2, y2, title);
588 if (o->InheritsFrom(TNamed::Class()) && strlen(o->GetTitle()))
589 mes = o->GetTitle();
590 else if (strlen(o->GetName()))
591 mes = o->GetName();
592 else
593 mes = o->ClassName();
594 if (option && strlen(option)) {
595 opt = option;
596 } else {
597 if (o->InheritsFrom(TAttLine::Class()))
598 opt += "l";
599 if (o->InheritsFrom(TAttMarker::Class()))
600 opt += "p";
601 if (o->InheritsFrom(TAttFill::Class()))
602 opt += "f";
603 }
604 leg->AddEntry(o,mes.Data(), opt.Data());
605 if (o->InheritsFrom(TH1::Class())) {
606 lof = ((TH1 *)o)->GetListOfFunctions();
608 }
609 if (o->InheritsFrom(TGraph::Class())) {
610 lof = ((TGraph *)o)->GetListOfFunctions();
612 }
613 } else if (o->InheritsFrom(TMultiGraph::Class())) {
614 if (!leg)
615 leg = new TLegend(x1, y1, x2, y2, title);
616 TList * grlist = ((TMultiGraph *)o)->GetListOfGraphs();
618 TGraph *gr = nullptr;
619 while ((obj = nextgraph())) {
620 gr = (TGraph*) obj;
621 if (strlen(gr->GetTitle()))
622 mes = gr->GetTitle();
623 else if (strlen(gr->GetName()))
624 mes = gr->GetName();
625 else
626 mes = gr->ClassName();
627 if (option && strlen(option))
628 opt = option;
629 else
630 opt = "lpf";
631 leg->AddEntry(obj, mes.Data(), opt);
632 }
633 lof = ((TMultiGraph *)o)->GetListOfFunctions();
635 } else if (o->InheritsFrom(THStack::Class())) {
636 if (!leg)
637 leg = new TLegend(x1, y1, x2, y2, title);
638 TList * hlist = ((THStack *)o)->GetHists();
640 while ((obj = nexthist())) {
641 TH1 *hist = (TH1*) obj;
642 if (strlen(hist->GetTitle()))
643 mes = hist->GetTitle();
644 else if (strlen(hist->GetName()))
645 mes = hist->GetName();
646 else
647 mes = hist->ClassName();
648 if (option && strlen(option))
649 opt = option;
650 else
651 opt = "lpf";
652 leg->AddEntry( obj, mes.Data(), opt );
653 }
654 }
655 opt = "";
656 }
657 if (leg) {
658 TContext ctxt(this, kTRUE);
659 leg->Draw();
660 } else {
661 Info("BuildLegend", "No object(s) to build a TLegend.");
662 }
663 return leg;
664}
665
666////////////////////////////////////////////////////////////////////////////////
667/// Set Current pad.
668///
669/// When a canvas/pad is divided via TPad::Divide, one can directly
670/// set the current path to one of the subdivisions.
671/// See TPad::Divide for the convention to number sub-pads.
672///
673/// Returns the new current pad, or 0 in case of failure.
674///
675/// For example:
676/// ~~~ {.cpp}
677/// c1.Divide(2,3); // create 6 pads (2 divisions along x, 3 along y).
678/// ~~~
679/// To set the current pad to the bottom right pad, do
680/// ~~~ {.cpp}
681/// c1.cd(6);
682/// ~~~
683/// Note1: c1.cd() is equivalent to c1.cd(0) and sets the current pad
684/// to c1 itself.
685///
686/// Note2: after a statement like c1.cd(6), the global variable gPad
687/// points to the current pad. One can use gPad to set attributes
688/// of the current pad.
689///
690/// Note3: One can get a pointer to one of the sub-pads of pad with:
691/// TPad *subpad = (TPad*)pad->GetPad(subpadnumber);
692
694{
695 if (!subpadnumber) {
696 gPad = this;
697 if (!gPad->IsBatch() && GetPainter()) GetPainter()->SelectDrawable(fPixmapID);
698 if (!fPrimitives) fPrimitives = new TList;
699 return gPad;
700 }
701
702 if (!fPrimitives) fPrimitives = new TList;
703 TIter next(fPrimitives);
704 while (auto obj = next()) {
705 if (obj->InheritsFrom(TPad::Class())) {
706 Int_t n = ((TPad*)obj)->GetNumber();
707 if (n == subpadnumber) {
708 return ((TPad*)obj)->cd();
709 }
710 }
711 }
712 return nullptr;
713}
714
715////////////////////////////////////////////////////////////////////////////////
716/// Delete all pad primitives.
717///
718/// If the bit kClearAfterCR has been set for this pad, the Clear function
719/// will execute only after having pressed a CarriageReturn
720/// Set the bit with `mypad->SetBit(TPad::kClearAfterCR)`
721
723{
724 if (!IsEditable()) return;
725
727
728 if (!fPadPaint) {
731 if (fFrame) {
733 fFrame = nullptr;
734 }
735 }
736 if (fCanvas) fCanvas->Cleared(this);
737
738 cd();
739
740 if (TestBit(kClearAfterCR)) {
741 // Intentional do not use the return value of getchar,
742 // we just want to get it and forget it
743 getchar();
744 }
745
746 auto pp = GetPainter();
747 // If pad painter uses PS, ClearDrawable() start new page
748 if (pp) {
749 if (pp->IsNative())
750 pp->ClearDrawable();
751 else if (this == GetCanvas())
752 pp->NewPage();
753 }
754
756 fCrosshairPos = 0;
758 fCollideGrid.clear();
759 fCGnx = 0;
760 fCGny = 0;
762}
763
764////////////////////////////////////////////////////////////////////////////////
765/// Clipping routine: Cohen Sutherland algorithm.
766///
767/// - If Clip ==2 the segment is outside the boundary.
768/// - If Clip ==1 the segment has one point outside the boundary.
769/// - If Clip ==0 the segment is inside the boundary.
770///
771/// \param[inout] x[],y[] Segment coordinates (2 points)
772/// \param[in] xclipl,yclipb,xclipr,yclipt Clipping boundary
773
775{
776 const Float_t kP=10000;
777 Int_t clip = 0;
778
779 for (Int_t i=0;i<2;i++) {
780 if (TMath::Abs(xclipl-x[i]) <= TMath::Abs(xclipr-xclipl)/kP) x[i] = xclipl;
781 if (TMath::Abs(xclipr-x[i]) <= TMath::Abs(xclipr-xclipl)/kP) x[i] = xclipr;
782 if (TMath::Abs(yclipb-y[i]) <= TMath::Abs(yclipt-yclipb)/kP) y[i] = yclipb;
783 if (TMath::Abs(yclipt-y[i]) <= TMath::Abs(yclipt-yclipb)/kP) y[i] = yclipt;
784 }
785
786 // Compute the first endpoint codes.
789
790 Double_t xt=0, yt=0;
791 Int_t clipped = 0; //this variable could be used in a future version
792 while(code1 + code2) {
793 clipped = 1;
794
795 // The line lies entirely outside the clipping boundary
796 if (code1&code2) {
797 clip = 2;
798 return clip;
799 }
800
801 // The line is subdivided into several parts
802 Int_t ic = code1;
803 if (ic == 0) ic = code2;
804 if (ic & 0x1) {
805 yt = y[0] + (y[1]-y[0])*(xclipl-x[0])/(x[1]-x[0]);
806 xt = xclipl;
807 }
808 if (ic & 0x2) {
809 yt = y[0] + (y[1]-y[0])*(xclipr-x[0])/(x[1]-x[0]);
810 xt = xclipr;
811 }
812 if (ic & 0x4) {
813 xt = x[0] + (x[1]-x[0])*(yclipb-y[0])/(y[1]-y[0]);
814 yt = yclipb;
815 }
816 if (ic & 0x8) {
817 xt = x[0] + (x[1]-x[0])*(yclipt-y[0])/(y[1]-y[0]);
818 yt = yclipt;
819 }
820 if (ic == code1) {
821 x[0] = xt;
822 y[0] = yt;
824 } else {
825 x[1] = xt;
826 y[1] = yt;
828 }
829 }
830 clip = clipped;
831 return clip;
832}
833
834/// @copydoc TPad::Clip(Float_t*,Float_t*,Float_t,Float_t,Float_t,Float_t)
835
837{
838 const Double_t kP = 10000;
839 Int_t clip = 0;
840
841 for (Int_t i=0;i<2;i++) {
842 if (TMath::Abs(xclipl-x[i]) <= TMath::Abs(xclipr-xclipl)/kP) x[i] = xclipl;
843 if (TMath::Abs(xclipr-x[i]) <= TMath::Abs(xclipr-xclipl)/kP) x[i] = xclipr;
844 if (TMath::Abs(yclipb-y[i]) <= TMath::Abs(yclipt-yclipb)/kP) y[i] = yclipb;
845 if (TMath::Abs(yclipt-y[i]) <= TMath::Abs(yclipt-yclipb)/kP) y[i] = yclipt;
846 }
847
848 // Compute the first endpoint codes.
849 Int_t code1 = 0;
850 if (x[0] < xclipl) code1 = code1 | 0x1;
851 if (x[0] > xclipr) code1 = code1 | 0x2;
852 if (y[0] < yclipb) code1 = code1 | 0x4;
853 if (y[0] > yclipt) code1 = code1 | 0x8;
854 Int_t code2 = 0;
855 if (x[1] < xclipl) code2 = code2 | 0x1;
856 if (x[1] > xclipr) code2 = code2 | 0x2;
857 if (y[1] < yclipb) code2 = code2 | 0x4;
858 if (y[1] > yclipt) code2 = code2 | 0x8;
859
860 Double_t xt=0, yt=0;
861 Int_t clipped = 0; //this variable could be used in a future version
862 while(code1 + code2) {
863 clipped = 1;
864
865 // The line lies entirely outside the clipping boundary
866 if (code1&code2) {
867 clip = 2;
868 return clip;
869 }
870
871 // The line is subdivided into several parts
872 Int_t ic = code1;
873 if (ic == 0) ic = code2;
874 if (ic & 0x1) {
875 yt = y[0] + (y[1]-y[0])*(xclipl-x[0])/(x[1]-x[0]);
876 xt = xclipl;
877 }
878 if (ic & 0x2) {
879 yt = y[0] + (y[1]-y[0])*(xclipr-x[0])/(x[1]-x[0]);
880 xt = xclipr;
881 }
882 if (ic & 0x4) {
883 xt = x[0] + (x[1]-x[0])*(yclipb-y[0])/(y[1]-y[0]);
884 yt = yclipb;
885 }
886 if (ic & 0x8) {
887 xt = x[0] + (x[1]-x[0])*(yclipt-y[0])/(y[1]-y[0]);
888 yt = yclipt;
889 }
890 if (ic == code1) {
891 x[0] = xt;
892 y[0] = yt;
894 } else {
895 x[1] = xt;
896 y[1] = yt;
898 }
899 }
900 clip = clipped;
901 return clip;
902}
903
904////////////////////////////////////////////////////////////////////////////////
905/// Compute the endpoint codes for TPad::Clip.
906
908{
909 Int_t code = 0;
910 if (x < xcl1) code = code | 0x1;
911 if (x > xcl2) code = code | 0x2;
912 if (y < ycl1) code = code | 0x4;
913 if (y > ycl2) code = code | 0x8;
914 return code;
915}
916
917////////////////////////////////////////////////////////////////////////////////
918/// Clip polygon using the Sutherland-Hodgman algorithm.
919///
920/// \param[in] n Number of points in the polygon to
921/// be clipped
922/// \param[in] x,y Polygon x[n], y[n] do be clipped vertices
923/// \param[in] xclipl,yclipb,xclipr,yclipt Clipping boundary
924/// \param[out] nn Number of points in xc and yc
925/// \param[out] xc,yc Clipped polygon vertices. The Int_t
926/// returned by this function is
927/// the number of points in the clipped
928/// polygon. These vectors must
929/// be allocated by the calling function.
930/// A size of 2*n for each is
931/// enough.
932///
933/// Sutherland and Hodgman's polygon-clipping algorithm uses a divide-and-conquer
934/// strategy: It solves a series of simple and identical problems that, when
935/// combined, solve the overall problem. The simple problem is to clip a polygon
936/// against a single infinite clip edge. Four clip edges, each defining one boundary
937/// of the clip rectangle, successively clip a polygon against a clip rectangle.
938///
939/// Steps of Sutherland-Hodgman's polygon-clipping algorithm:
940///
941/// * Polygons can be clipped against each edge of the window one at a time.
942/// Windows/edge intersections, if any, are easy to find since the X or Y coordinates
943/// are already known.
944/// * Vertices which are kept after clipping against one window edge are saved for
945/// clipping against the remaining edges.
946/// * Note that the number of vertices usually changes and will often increases.
947///
948/// The clip boundary determines a visible and invisible region. The edges from
949/// vertex i to vertex i+1 can be one of four types:
950///
951/// * Case 1 : Wholly inside visible region - save endpoint
952/// * Case 2 : Exit visible region - save the intersection
953/// * Case 3 : Wholly outside visible region - save nothing
954/// * Case 4 : Enter visible region - save intersection and endpoint
955
957{
958 if (n <= 0)
959 return 0;
960
961 Int_t nc, nc2;
962 Double_t x1, y1, x2, y2, slope; // Segment to be clipped
963
964 std::vector<Double_t> xc2(nn), yc2(nn);
965
966 // Clip against the left boundary
967 x1 = x[n - 1];
968 y1 = y[n - 1];
969 nc2 = 0;
970 Int_t i;
971 for (i = 0; i < n; i++) {
972 x2 = x[i]; y2 = y[i];
973 if (x1 == x2) {
974 slope = 0;
975 } else {
976 slope = (y2-y1)/(x2-x1);
977 }
978 if (x1 >= xclipl) {
979 if (x2 < xclipl) {
980 xc2[nc2] = xclipl; yc2[nc2++] = slope*(xclipl-x1)+y1;
981 } else {
982 xc2[nc2] = x2; yc2[nc2++] = y2;
983 }
984 } else {
985 if (x2 >= xclipl) {
986 xc2[nc2] = xclipl; yc2[nc2++] = slope*(xclipl-x1)+y1;
987 xc2[nc2] = x2; yc2[nc2++] = y2;
988 }
989 }
990 x1 = x2; y1 = y2;
991 }
992
993 // Clip against the top boundary
994 if (nc2 > 0) {
995 x1 = xc2[nc2 - 1];
996 y1 = yc2[nc2 - 1];
997 }
998 nc = 0;
999 for (i = 0; i < nc2; i++) {
1000 x2 = xc2[i]; y2 = yc2[i];
1001 if (y1 == y2) {
1002 slope = 0;
1003 } else {
1004 slope = (x2-x1)/(y2-y1);
1005 }
1006 if (y1 <= yclipt) {
1007 if (y2 > yclipt) {
1008 xc[nc] = x1+(yclipt-y1)*slope; yc[nc++] = yclipt;
1009 } else {
1010 xc[nc] = x2; yc[nc++] = y2;
1011 }
1012 } else {
1013 if (y2 <= yclipt) {
1014 xc[nc] = x1+(yclipt-y1)*slope; yc[nc++] = yclipt;
1015 xc[nc] = x2; yc[nc++] = y2;
1016 }
1017 }
1018 x1 = x2; y1 = y2;
1019 }
1020
1021 // Clip against the right boundary
1022 if (nc > 0) {
1023 x1 = xc[nc - 1];
1024 y1 = yc[nc - 1];
1025 nc2 = 0;
1026 for (i = 0; i < nc; i++) {
1027 x2 = xc[i]; y2 = yc[i];
1028 if (x1 == x2) {
1029 slope = 0;
1030 } else {
1031 slope = (y2-y1)/(x2-x1);
1032 }
1033 if (x1 <= xclipr) {
1034 if (x2 > xclipr) {
1035 xc2[nc2] = xclipr; yc2[nc2++] = slope*(xclipr-x1)+y1;
1036 } else {
1037 xc2[nc2] = x2; yc2[nc2++] = y2;
1038 }
1039 } else {
1040 if (x2 <= xclipr) {
1041 xc2[nc2] = xclipr; yc2[nc2++] = slope*(xclipr-x1)+y1;
1042 xc2[nc2] = x2; yc2[nc2++] = y2;
1043 }
1044 }
1045 x1 = x2; y1 = y2;
1046 }
1047
1048 // Clip against the bottom boundary
1049 if (nc2 > 0) {
1050 x1 = xc2[nc2 - 1];
1051 y1 = yc2[nc2 - 1];
1052 }
1053 nc = 0;
1054 for (i = 0; i < nc2; i++) {
1055 x2 = xc2[i]; y2 = yc2[i];
1056 if (y1 == y2) {
1057 slope = 0;
1058 } else {
1059 slope = (x2-x1)/(y2-y1);
1060 }
1061 if (y1 >= yclipb) {
1062 if (y2 < yclipb) {
1063 xc[nc] = x1+(yclipb-y1)*slope; yc[nc++] = yclipb;
1064 } else {
1065 xc[nc] = x2; yc[nc++] = y2;
1066 }
1067 } else {
1068 if (y2 >= yclipb) {
1069 xc[nc] = x1+(yclipb-y1)*slope; yc[nc++] = yclipb;
1070 xc[nc] = x2; yc[nc++] = y2;
1071 }
1072 }
1073 x1 = x2; y1 = y2;
1074 }
1075 }
1076
1077 if (nc < 3)
1078 nc = 0;
1079 return nc;
1080}
1081
1082////////////////////////////////////////////////////////////////////////////////
1083/// Delete all primitives in pad and pad itself.
1084/// Pad cannot be used anymore after this call.
1085/// Emits signal "Closed()".
1086
1088{
1089 if (ROOT::Detail::HasBeenDeleted(this)) return;
1090 if (!fMother) return;
1092
1093 if (fPrimitives)
1094 fPrimitives->Clear();
1095 if (fView) {
1097 fView = nullptr;
1098 }
1099 if (fFrame) {
1101 fFrame = nullptr;
1102 }
1103
1104 // emit signal
1105 if (IsA() != TCanvas::Class())
1106 Closed();
1107
1108 if (fPixmapID != -1) {
1109 if (gPad) {
1110 if (!gPad->IsBatch() && GetPainter())
1112 }
1113 fPixmapID = -1;
1114
1115 if (!gROOT->GetListOfCanvases()) return;
1116 if (fMother == this) {
1117 gROOT->GetListOfCanvases()->Remove(this);
1118 return; // in case of TCanvas
1119 }
1120
1121 // remove from the mother's list of primitives
1122 if (fMother) {
1123 fMother->Remove(this, kFALSE); // do not produce modified
1124
1125 if (gPad == this)
1126 fMother->cd();
1127 }
1128 if (fCanvas) {
1129 if (fCanvas->GetPadSave() == this)
1131 if (fCanvas->GetSelectedPad() == this)
1132 fCanvas->SetSelectedPad(nullptr);
1133 if (fCanvas->GetClickSelectedPad() == this)
1134 fCanvas->SetClickSelectedPad(nullptr);
1135 }
1136 }
1137
1138 fMother = nullptr;
1139 if (gROOT->GetSelectedPad() == this)
1140 gROOT->SetSelectedPad(nullptr);
1141}
1142
1143////////////////////////////////////////////////////////////////////////////////
1144/// Copy the pixmap of the pad to the canvas.
1145
1147{
1148 int px, py;
1149 XYtoAbsPixel(fX1, fY2, px, py);
1150
1151 if (fPixmapID != -1)
1152 if (auto pp = GetPainter())
1153 pp->CopyDrawable(fPixmapID, px, py);
1154}
1155
1156////////////////////////////////////////////////////////////////////////////////
1157/// Copy the sub-pixmaps of the pad to the canvas.
1158
1160{
1161 if (!fPrimitives)
1162 fPrimitives = new TList;
1163 TIter next(GetListOfPrimitives());
1164 while (auto obj = next()) {
1165 if (auto pad = dynamic_cast<TPad*>(obj)) {
1166 pad->CopyPixmap();
1167 pad->CopyPixmaps();
1168 }
1169 }
1170
1171 if (this == gPad)
1173}
1174
1175////////////////////////////////////////////////////////////////////////////////
1176/// Remove TExec name from the list of Execs.
1177
1178void TPad::DeleteExec(const char *name)
1179{
1180 if (!fExecs) fExecs = new TList;
1182 if (!ex) return;
1183 fExecs->Remove(ex);
1184 delete ex;
1185}
1186
1187////////////////////////////////////////////////////////////////////////////////
1188/// Compute distance from point px,py to a box.
1189///
1190/// Compute the closest distance of approach from point px,py to the
1191/// edges of this pad.
1192/// The distance is computed in pixels units.
1193
1195{
1196 Int_t pxl, pyl, pxt, pyt;
1197 Int_t px1 = gPad->XtoAbsPixel(fX1);
1198 Int_t py1 = gPad->YtoAbsPixel(fY1);
1199 Int_t px2 = gPad->XtoAbsPixel(fX2);
1200 Int_t py2 = gPad->YtoAbsPixel(fY2);
1201 if (px1 < px2) {pxl = px1; pxt = px2;}
1202 else {pxl = px2; pxt = px1;}
1203 if (py1 < py2) {pyl = py1; pyt = py2;}
1204 else {pyl = py2; pyt = py1;}
1205
1206 // Are we inside the box?
1207 // ======================
1208 if ( (px > pxl && px < pxt) && (py > pyl && py < pyt) ) {
1209 if (GetFillStyle()) return 0; //*-* if pad is filled
1210 }
1211
1212 // Are we on the edges?
1213 // ====================
1214 Int_t dxl = TMath::Abs(px - pxl);
1215 if (py < pyl) dxl += pyl - py;
1216 if (py > pyt) dxl += py - pyt;
1217 Int_t dxt = TMath::Abs(px - pxt);
1218 if (py < pyl) dxt += pyl - py;
1219 if (py > pyt) dxt += py - pyt;
1220 Int_t dyl = TMath::Abs(py - pyl);
1221 if (px < pxl) dyl += pxl - px;
1222 if (px > pxt) dyl += px - pxt;
1223 Int_t dyt = TMath::Abs(py - pyt);
1224 if (px < pxl) dyt += pxl - px;
1225 if (px > pxt) dyt += px - pxt;
1226
1227 Int_t distance = dxl;
1228 if (dxt < distance) distance = dxt;
1229 if (dyl < distance) distance = dyl;
1230 if (dyt < distance) distance = dyt;
1231
1232 return distance - Int_t(0.5*fLineWidth);
1233}
1234
1235////////////////////////////////////////////////////////////////////////////////
1236/// Automatic pad generation by division.
1237///
1238/// - The current canvas is divided in nx by ny equal divisions (pads).
1239/// - xmargin defines the horizontal spacing around each pad as a percentage of the canvas
1240/// width. Therefore, the distance between two adjacent pads along the x-axis is equal
1241/// to twice the xmargin value.
1242/// - ymargin defines the vertical spacing around each pad as a percentage of the canvas
1243/// height. Therefore, the distance between two adjacent pads along the y-axis is equal
1244/// to twice the ymargin value.
1245/// - color is the color of the new pads. If 0, color is the canvas color.
1246///
1247/// Pads are automatically named `canvasname_n` where `n` is the division number
1248/// starting from top left pad.
1249///
1250/// Example if canvasname=c1 , nx=2, ny=3:
1251///
1252/// \image html gpad_pad3.png
1253///
1254/// Once a pad is divided into sub-pads, one can set the current pad
1255/// to a subpad with a given division number as illustrated above
1256/// with TPad::cd(subpad_number).
1257///
1258/// For example, to set the current pad to c1_4, one can do:
1259/// ~~~ {.cpp}
1260/// c1->cd(4)
1261/// ~~~
1262/// __Note1:__ c1.cd() is equivalent to c1.cd(0) and sets the current pad
1263/// to c1 itself.
1264///
1265/// __Note2:__ after a statement like c1.cd(6), the global variable gPad
1266/// points to the current pad. One can use gPad to set attributes
1267/// of the current pad.
1268///
1269/// __Note3:__ in case xmargin < 0 or ymargin < 0, there is no space
1270/// between pads. The current pad margins are recomputed to
1271/// optimize the layout in order to have similar frames' areas.
1272/// See the following example:
1273///
1274/// ~~~ {.cpp}
1275/// void divpad(Int_t nx=3, Int_t ny=2) {
1276/// gStyle->SetOptStat(0);
1277/// auto C = new TCanvas();
1278/// C->SetMargin(0.3, 0.3, 0.3, 0.3);
1279/// C->Divide(nx,ny,-1);
1280/// Int_t number = 0;
1281/// auto h = new TH1F("","",100,-3.3,3.3);
1282/// h->GetXaxis()->SetLabelFont(43);
1283/// h->GetXaxis()->SetLabelSize(12);
1284/// h->GetYaxis()->SetLabelFont(43);
1285/// h->GetYaxis()->SetLabelSize(12);
1286/// h->GetYaxis()->SetNdivisions(505);
1287/// h->SetMaximum(30*nx*ny);
1288/// h->SetFillColor(42);
1289/// for (Int_t i=0;i<nx*ny;i++) {
1290/// number++;
1291/// C->cd(number);
1292/// h->FillRandom("gaus",1000);
1293/// h->DrawCopy();
1294/// }
1295/// }
1296/// ~~~
1297
1299{
1300 if (!IsEditable()) return;
1301
1302 if (gThreadXAR) {
1303 void *arr[7];
1304 arr[1] = this; arr[2] = (void*)&nx;arr[3] = (void*)& ny;
1305 arr[4] = (void*)&xmargin; arr[5] = (void *)& ymargin; arr[6] = (void *)&color;
1306 if ((*gThreadXAR)("PDCD", 7, arr, nullptr)) return;
1307 }
1308
1310
1311 cd();
1312 if (nx <= 0) nx = 1;
1313 if (ny <= 0) ny = 1;
1314 Int_t ix, iy;
1315 Double_t x1, y1, x2, y2, dx, dy;
1316 TPad *pad;
1317 TString name, title;
1318 Int_t n = 0;
1319 if (color == 0) color = GetFillColor();
1320 if (xmargin >= 0 && ymargin >= 0) {
1321 //general case
1322 dy = 1/Double_t(ny);
1323 dx = 1/Double_t(nx);
1324 for (iy=0;iy<ny;iy++) {
1325 y2 = 1 - iy*dy - ymargin;
1326 y1 = y2 - dy + 2*ymargin;
1327 if (y1 < 0) y1 = 0;
1328 if (y1 > y2) continue;
1329 for (ix=0;ix<nx;ix++) {
1330 x1 = ix*dx + xmargin;
1331 x2 = x1 +dx -2*xmargin;
1332 if (x1 > x2) continue;
1333 n++;
1334 name.Form("%s_%d", GetName(), n);
1335 pad = new TPad(name.Data(), name.Data(), x1, y1, x2, y2, color);
1336 pad->SetNumber(n);
1337 pad->Draw();
1338 }
1339 }
1340 } else {
1341 // special case when xmargin < 0 or ymargin < 0
1346 xl /= (1-xl+xr)*nx;
1347 xr /= (1-xl+xr)*nx;
1348 yb /= (1-yb+yt)*ny;
1349 yt /= (1-yb+yt)*ny;
1354 dx = (1-xl-xr)/nx;
1355 dy = (1-yb-yt)/ny;
1356 Int_t number = 0;
1357 for (Int_t i=0;i<nx;i++) {
1358 x1 = i*dx+xl;
1359 x2 = x1 + dx;
1360 if (i == 0) x1 = 0;
1361 if (i == nx-1) x2 = 1-xr;
1362 for (Int_t j=0;j<ny;j++) {
1363 number = j*nx + i +1;
1364 y2 = 1 -j*dy -yt;
1365 y1 = y2 - dy;
1366 if (j == 0) y2 = 1-yt;
1367 if (j == ny-1) y1 = 0;
1368 name.Form("%s_%d", GetName(), number);
1369 title.Form("%s_%d", GetTitle(), number);
1370 pad = new TPad(name.Data(), title.Data(), x1, y1, x2, y2, color);
1371 pad->SetNumber(number);
1372 pad->SetBorderMode(0);
1373 if (i == 0) pad->SetLeftMargin(xl*nx);
1374 else pad->SetLeftMargin(0);
1375 pad->SetRightMargin(0);
1376 pad->SetTopMargin(0);
1377 if (j == ny-1) pad->SetBottomMargin(yb*ny);
1378 else pad->SetBottomMargin(0);
1379 pad->Draw();
1380 }
1381 }
1382 }
1383 Modified();
1384}
1385
1386////////////////////////////////////////////////////////////////////////////////
1387/// Divide the canvas according to ratios.
1388///
1389/// The current canvas is divided in nx by ny according to the width and height ratios.
1390/// If the ratios are not specified they are assumed to be equal.
1391///
1392/// Pads are automatically named `canvasname_n` where `n` is the division number
1393/// starting from top left pad.
1394///
1395/// Top and left margins can be defined.
1396
1398 const std::vector<double>& widthRatios,
1399 const std::vector<double>& heightRatios,
1400 const double canvasTopMargin,
1401 const double canvasLeftMargin
1402 )
1403{
1404 cd();
1405
1406 int wrs = widthRatios.size();
1407 int hrs = heightRatios.size();
1408 int nxl = TMath::Min(nx,wrs), nyl = TMath::Min(ny,hrs);
1409
1410 if (wrs==0) nxl = nx;
1411 if (hrs==0) nyl = ny;
1412
1413 int pn = 1;
1414 double xr = 0.;
1415 double yr = 0.;
1416 double x = 0.;
1417 double y = 1.;
1418 double x1, y1, x2, y2;
1419
1420 // Check the validity of the margins
1422 Error("DivideRatios", "The canvas top margin must be >= 0 and <= 1");
1423 return;
1424 } else {
1425 y = 1.- canvasTopMargin;
1426 }
1428 Error("DivideRatios", "The canvas left margin must be >= 0 and <= 1");
1429 return;
1430 }
1431
1432 // Check the validity of the ratios
1434 if (hrs) {
1435 for (int i=0; i<nyl; i++) {
1436 yr = heightRatios[i];
1438 if (yr <0 || yr >1 ) {
1439 Error("DivideRatios", "Y ratios plus the top margin must be >= 0 and <= 1");
1440 return;
1441 }
1442 }
1443 }
1444 if (sumOfHeightRatios > 1.) {
1445 Error("DivideRatios", "The sum of Y ratios plus the top margin must be <= 1 %g",sumOfHeightRatios);
1446 return;
1447 }
1449 if (wrs) {
1450 for (int j=0; j<nxl; j++) {
1451 xr = widthRatios[j];
1453 if (xr <0 || xr >1 ) {
1454 Error("DivideRatios", "X ratios must be >= 0 and <= 1");
1455 return;
1456 }
1457 }
1458 }
1459 if (sumOfWidthRatios > 1.) {
1460 Error("DivideRatios", "The sum of X ratios must be <= 1 %g ",sumOfWidthRatios);
1461 return;
1462 }
1463
1464 // Create the pads according to the ratios
1465 for (int i=0; i<nyl; i++) {
1467 if (hrs) yr = heightRatios[i];
1468 else yr = 1./nyl;
1469 for (int j=0; j<nxl; j++) {
1470 if (wrs) xr = widthRatios[j];
1471 else xr = 1./nxl;
1472 x1 = TMath::Max(0., x);
1473 y1 = TMath::Max(0., y - yr);
1474 x2 = TMath::Min(1., x + xr);
1475 y2 = TMath::Min(1., y);
1476 auto pad = new TPad(TString::Format("%s_%d", GetName(), pn),
1477 TString::Format("%s_%d", GetName(), pn),
1478 x1, y1, x2 ,y2);
1479 pad->SetNumber(pn);
1480 pad->Draw();
1481 x = x + xr;
1482 pn++;
1483 }
1484 y = y - yr;
1485 }
1486}
1487
1488////////////////////////////////////////////////////////////////////////////////
1489/// "n" is the total number of sub-pads. The number of sub-pads along the X
1490/// and Y axis are computed according to the square root of n.
1491
1493{
1494 Int_t w = 1, h = 1;
1495 if (!fCanvas) {
1496 Error("DivideSquare", "No canvas associated with this pad.");
1497 return;
1498 }
1502 if (w*h < n) w++;
1503 } else {
1506 if (w*h < n) h++;
1507 }
1508
1509 Divide( w, h, xmargin, ymargin, color);
1510}
1511
1512////////////////////////////////////////////////////////////////////////////////
1513/// Draw Pad in Current pad (re-parent pad if necessary).
1514
1516{
1517 // if no canvas opened yet create a default canvas
1518 if (!gPad) {
1519 gROOT->MakeDefCanvas();
1520 }
1521
1522 // pad cannot be in itself and it can only be in one other pad at a time
1523 if (!fPrimitives) fPrimitives = new TList;
1524 if (gPad != this) {
1526 fMother->Remove(this, kFALSE);
1528 fCanvas = gPad->GetCanvas();
1529 //
1530 fMother = (TPad*)gPad;
1531 if (oldMother != fMother || fPixmapID == -1) ResizePad();
1532 }
1533
1534 if (fCanvas && fCanvas->IsWeb()) {
1535 Modified();
1537 } else {
1538 Paint();
1539 }
1540
1541 if (gPad->IsRetained() && gPad != this && fMother)
1542 fMother->Add(this, option);
1543}
1544
1545////////////////////////////////////////////////////////////////////////////////
1546/// Draw class inheritance tree of the class to which obj belongs.
1547///
1548/// If a class B inherits from a class A, description of B is drawn
1549/// on the right side of description of A.
1550///
1551/// Member functions overridden by B are shown in class A with a blue line
1552/// crossing-out the corresponding member function.
1553
1555{
1556 if (!classobj) return;
1557 char dname[256];
1558 const Int_t kMAXLEVELS = 10;
1559 TClass *clevel[kMAXLEVELS], *cl, *cll;
1560 TBaseClass *base, *cinherit;
1561 TText *ptext = nullptr;
1562 TString opt=option;
1563 Double_t x,y,dy,y1,v1,v2,dv;
1564 Int_t nd,nf,nc,nkd,nkf,i,j;
1565 TPaveText *pt;
1566 Int_t maxlev = 4;
1567 if (opt.Contains("2")) maxlev = 2;
1568 if (opt.Contains("3")) maxlev = 3;
1569 if (opt.Contains("5")) maxlev = 5;
1570 if (opt.Contains("6")) maxlev = 6;
1571 if (opt.Contains("7")) maxlev = 7;
1572
1573 // Clear and Set Pad range
1574 Double_t xpad = 20.5;
1575 Double_t ypad = 27.5;
1576 Clear();
1577 Range(0,0,xpad,ypad);
1578
1579 // Find number of levels
1580 Int_t nlevel = 0;
1581 TClass *obj = (TClass*)classobj;
1582 clevel[nlevel] = obj;
1583 TList *lbase = obj->GetListOfBases();
1584 while(lbase) {
1585 base = (TBaseClass*)lbase->First();
1586 if (!base) break;
1587 if (!base->GetClassPointer()) break;
1588 nlevel++;
1589 clevel[nlevel] = base->GetClassPointer();
1590 lbase = clevel[nlevel]->GetListOfBases();
1591 if (nlevel >= maxlev-1) break;
1592 }
1593 Int_t maxelem = 0;
1594 Int_t ncdraw = 0;
1596 for (ilevel=nlevel;ilevel>=0;ilevel--) {
1597 cl = clevel[ilevel];
1598 nelem = cl->GetNdata() + cl->GetNmethods();
1599 if (nelem > maxelem) maxelem = nelem;
1600 nc = (nelem/50) + 1;
1601 ncdraw += nc;
1602 }
1603
1604 Double_t tsizcm = 0.40;
1605 Double_t x1 = 0.25;
1606 Double_t x2 = 0;
1607 Double_t dx = 3.5;
1608 if (ncdraw > 4) {
1609 dx = dx - 0.42*Double_t(ncdraw-5);
1610 if (dx < 1.3) dx = 1.3;
1611 tsizcm = tsizcm - 0.03*Double_t(ncdraw-5);
1612 if (tsizcm < 0.27) tsizcm = 0.27;
1613 }
1614 Double_t tsiz = 1.2*tsizcm/ypad;
1615
1616 // Now loop on levels
1617 for (ilevel=nlevel;ilevel>=0;ilevel--) {
1618 cl = clevel[ilevel];
1619 nelem = cl->GetNdata() + cl->GetNmethods();
1620 if (nelem > maxelem) maxelem = nelem;
1621 nc = (nelem/50) + 1;
1622 dy = 0.45;
1623 if (ilevel < nlevel) x1 = x2 + 0.5;
1624 x2 = x1 + nc*dx;
1625 v2 = ypad - 0.5;
1626 lbase = cl->GetListOfBases();
1627 cinherit = nullptr;
1628 if (lbase) cinherit = (TBaseClass*)lbase->First();
1629
1630 do {
1631 nd = cl->GetNdata();
1632 nf = cl->GetNmethods() - 2; //do not show default constructor and destructor
1633 if (cl->GetListOfMethods()->FindObject("Dictionary")) {
1634 nf -= 6; // do not count the Dictionary/ClassDef functions
1635 }
1636 nkf= nf/nc +1;
1637 nkd= nd/nc +1;
1638 if (nd == 0) nkd=0;
1639 if (nf == 0) nkf=0;
1640 y1 = v2 - 0.7;
1641 v1 = y1 - Double_t(nkf+nkd+nc-1)*dy;
1642 dv = v2 - v1;
1643
1644 // Create a new PaveText
1645 pt = new TPaveText(x1,v1,x2,v2);
1647 pt->SetFillColor(19);
1648 pt->Draw();
1649 pt->SetTextColor(4);
1650 pt->SetTextFont(61);
1651 pt->SetTextAlign(12);
1653 TBox *box = pt->AddBox(0,(y1+0.01-v1)/dv,0,(v2-0.01-v1)/dv);
1654 if (box) box->SetFillColor(17);
1655 pt->AddLine(0,(y1-v1)/dv,0,(y1-v1)/dv);
1656 TText *title = pt->AddText(0.5,(0.5*(y1+v2)-v1)/dv,(char*)cl->GetName());
1657 title->SetTextAlign(22);
1658 title->SetTextSize(0.6*(v2-y1)/ypad);
1659
1660 // Draw data Members
1661 i = 0;
1662 x = 0.03;
1663 y = y1 + 0.5*dy;
1664 TDataMember *d;
1666 while ((d = (TDataMember *) nextd())) {
1667 if (i >= nkd) { i = 1; y = y1 - 0.5*dy; x += 1/Double_t(nc); }
1668 else { i++; y -= dy; }
1669
1670 // Take in account the room the array index will occupy
1671
1672 Int_t dim = d->GetArrayDim();
1673 Int_t indx = 0;
1674 snprintf(dname,256,"%s",d->GetName());
1675 Int_t ldname = 0;
1676 while (indx < dim ){
1677 ldname = strlen(dname);
1678 snprintf(&dname[ldname],256-ldname,"[%d]",d->GetMaxIndex(indx));
1679 indx++;
1680 }
1681 pt->AddText(x,(y-v1)/dv,dname);
1682 }
1683
1684 // Draw a separator line
1685 Double_t ysep;
1686 if (nd) {
1687 ysep = y1 - Double_t(nkd)*dy;
1688 pt->AddLine(0,(ysep-v1)/dv,0,(ysep-v1)/dv);
1689 ysep -= 0.5*dy;
1690 } else ysep = y1;
1691
1692 // Draw Member Functions
1693 Int_t fcount = 0;
1694 i = 0;
1695 x = 0.03;
1696 y = ysep + 0.5*dy;
1697 TMethod *m;
1699 while ((m = (TMethod *) nextm())) {
1700 if (
1701 !strcmp( m->GetName(), "Dictionary" ) ||
1702 !strcmp( m->GetName(), "Class_Version" ) ||
1703 !strcmp( m->GetName(), "DeclFileName" ) ||
1704 !strcmp( m->GetName(), "DeclFileLine" ) ||
1705 !strcmp( m->GetName(), "ImplFileName" ) ||
1706 !strcmp( m->GetName(), "ImplFileLine" )
1707 ) continue;
1708 fcount++;
1709 if (fcount > nf) break;
1710 if (i >= nkf) { i = 1; y = ysep - 0.5*dy; x += 1/Double_t(nc); }
1711 else { i++; y -= dy; }
1712
1713 ptext = pt->AddText(x,(y-v1)/dv,m->GetName());
1714 // Check if method is overloaded in a derived class
1715 // If yes, Change the color of the text to blue
1716 for (j=ilevel-1;j>=0;j--) {
1717 if (cl == clevel[ilevel]) {
1718 if (clevel[j]->GetMethodAny((char*)m->GetName())) {
1719 ptext->SetTextColor(15);
1720 break;
1721 }
1722 }
1723 }
1724 }
1725
1726 // Draw second inheritance classes for this class
1727 cll = nullptr;
1728 if (cinherit) {
1729 cinherit = (TBaseClass*)lbase->After(cinherit);
1730 if (cinherit) {
1731 cl = cinherit->GetClassPointer();
1732 cll = cl;
1733 v2 = v1 -0.4;
1734 dy = 0.35;
1735 }
1736 }
1737 } while (cll);
1738 }
1739 Update();
1740}
1741
1742////////////////////////////////////////////////////////////////////////////////
1743/// Function called to draw a crosshair in the canvas
1744///
1745/// Example:
1746/// ~~~ {.cpp}
1747/// Root > TFile f("hsimple.root");
1748/// Root > hpxpy.Draw();
1749/// Root > c1.SetCrosshair();
1750/// ~~~
1751/// When moving the mouse in the canvas, a crosshair is drawn
1752///
1753/// - if the canvas fCrosshair = 1 , the crosshair spans the full canvas
1754/// - if the canvas fCrosshair > 1 , the crosshair spans only the pad
1755
1757{
1758 if (!gPad || (gPad->GetEvent() == kMouseEnter))
1759 return;
1760
1761 TPad *cpad = (TPad*)gPad;
1762 TCanvas *canvas = cpad->GetCanvas();
1763 // switch off double buffer and select canvas drawable
1764 canvas->FeedbackMode(kTRUE);
1765
1766 auto pp = GetPainter();
1767
1768 //erase old position and draw a line at current position
1769 Double_t umin, umax, vmin, vmax, u, v;
1770 Int_t px = cpad->GetEventX();
1771 Int_t py = cpad->GetEventY() + 1;
1772 if (canvas->GetCrosshair() > 1) { //crosshair only in the current pad
1773 umin = GetAbsXlowNDC();
1775 vmin = GetAbsYlowNDC();
1777 } else { //default; crosshair spans the full canvas
1778 umin = 0;
1779 umax = 1;
1780 vmin = 0;
1781 vmax = 1;
1782 }
1783
1784 TContext ctxt(canvas);
1785
1786 pp->SetAttLine({1,1,1});
1787
1788 if ((fCrosshairPos != 0) && !pp->IsCocoa()) {
1789 // xor does not supported on Cocoa, implemented differently
1790 Int_t pxold = fCrosshairPos % 10000;
1791 Int_t pyold = fCrosshairPos / 10000;
1792 u = 1. * pxold / canvas->GetWw();
1793 v = 1. - 1. * pyold / canvas->GetWh();
1794 pp->DrawLineNDC(umin, v, umax, v);
1795 pp->DrawLineNDC(u, vmin, u, vmax);
1796 }
1797
1798 if (cpad->GetEvent() == kButton1Down ||
1799 cpad->GetEvent() == kButton1Up ||
1800 cpad->GetEvent() == kMouseLeave) {
1801 fCrosshairPos = 0;
1802 return;
1803 }
1804
1805 u = 1. * px / canvas->GetWw();
1806 v = 1. - 1. * py / canvas->GetWh();
1807 pp->DrawLineNDC(umin, v, umax, v);
1808 pp->DrawLineNDC(u, vmin, u, vmax);
1809
1810 fCrosshairPos = px + 10000*py;
1811}
1812
1813////////////////////////////////////////////////////////////////////////////////
1814/// Draw an empty pad frame with X and Y axis.
1815///
1816/// \return The pointer to the histogram used to draw the frame.
1817///
1818/// \param[in] xmin X axis lower limit
1819/// \param[in] xmax X axis upper limit
1820/// \param[in] ymin Y axis lower limit
1821/// \param[in] ymax Y axis upper limit
1822/// \param[in] title Pad title.If title is of the form "stringt;stringx;stringy"
1823/// the pad title is set to stringt, the x axis title to
1824/// stringx, the y axis title to stringy.
1825///
1826/// #### Example:
1827///
1828/// Begin_Macro(source)
1829/// {
1830/// auto c = new TCanvas("c","c",200,10,500,300);
1831///
1832/// const Int_t n = 50;
1833/// auto g = new TGraph();
1834/// for (Int_t i=0;i<n;i++) g->SetPoint(i,i*0.1,100*sin(i*0.1+0.2));
1835///
1836/// auto frame = c->DrawFrame(0, -110, 2, 110);
1837/// frame->GetXaxis()->SetTitle("X axis");
1838///
1839/// g->Draw("L*");
1840/// }
1841/// End_Macro
1842
1844{
1845 if (!IsEditable())
1846 return nullptr;
1847
1848 if (this != gPad) {
1849 Warning("DrawFrame", "Must be called for the current pad only");
1850 if (gPad) return gPad->DrawFrame(xmin,ymin,xmax,ymax,title);
1851 }
1852
1853 cd();
1854
1855 TH1F *hframe = (TH1F*)FindObject("hframe");
1856 if (hframe) delete hframe;
1857 Int_t nbins = 1000;
1858 //if log scale in X, use variable bin size linear with log(x)
1859 //this gives a better precision when zooming on the axis
1860 if (fLogx && xmin > 0 && xmax > xmin) {
1863 Double_t dx = (xmaxl-xminl)/nbins;
1864 std::vector<Double_t> xbins(nbins+1);
1865 xbins[0] = xmin;
1866 for (Int_t i=1;i<=nbins;i++) {
1867 xbins[i] = TMath::Exp(xminl+i*dx);
1868 }
1869 hframe = new TH1F("hframe",title,nbins,xbins.data());
1870 } else {
1871 hframe = new TH1F("hframe",title,nbins,xmin,xmax);
1872 }
1873 hframe->SetBit(TH1::kNoStats);
1874 hframe->SetBit(kCanDelete);
1875 hframe->SetMinimum(ymin);
1876 hframe->SetMaximum(ymax);
1877 hframe->GetYaxis()->SetLimits(ymin,ymax);
1878 hframe->SetDirectory(nullptr);
1879 hframe->Draw(" ");
1880 Update();
1881 cd();
1882 return hframe;
1883}
1884
1885////////////////////////////////////////////////////////////////////////////////
1886/// Static function to Display Color Table in a pad.
1887
1889{
1890 Int_t i, j;
1891 Int_t color;
1892 Double_t xlow, ylow, xup, yup, hs, ws;
1893 Double_t x1, y1, x2, y2;
1894 x1 = y1 = 0;
1895 x2 = y2 = 20;
1896
1897 gPad->SetFillColor(0);
1898 gPad->Clear();
1899 gPad->Range(x1,y1,x2,y2);
1900
1901 TText text(0,0,"");
1902 text.SetTextFont(61);
1903 text.SetTextSize(0.07);
1904 text.SetTextAlign(22);
1905
1906 TBox box;
1907
1908 // Draw color table boxes.
1909 hs = (y2-y1)/Double_t(5);
1910 ws = (x2-x1)/Double_t(10);
1911 for (i=0;i<10;i++) {
1912 xlow = x1 + ws*(Double_t(i)+0.1);
1913 xup = x1 + ws*(Double_t(i)+0.9);
1914 for (j=0;j<5;j++) {
1915 ylow = y1 + hs*(Double_t(j)+0.1);
1916 yup = y1 + hs*(Double_t(j)+0.9);
1917 color = 10*j + i;
1918 box.SetFillStyle(1001);
1919 box.SetFillColor(color);
1920 box.DrawBox(xlow, ylow, xup, yup);
1921 box.SetFillStyle(0);
1922 box.SetLineColor(1);
1923 box.DrawBox(xlow, ylow, xup, yup);
1924 if (color == 1) text.SetTextColor(0);
1925 else text.SetTextColor(1);
1926 text.DrawText(0.5*(xlow+xup), 0.5*(ylow+yup), TString::Format("%d",color).Data());
1927 }
1928 }
1929}
1930
1931////////////////////////////////////////////////////////////////////////////////
1932/// Execute action corresponding to one event.
1933///
1934/// This member function is called when a TPad object is clicked.
1935///
1936/// If the mouse is clicked in one of the 4 corners of the pad (pA,pB,pC,pD)
1937/// the pad is resized with the rubber rectangle.
1938///
1939/// If the mouse is clicked inside the pad, the pad is moved.
1940///
1941/// If the mouse is clicked on the 4 edges (pL,pR,pTop,pBot), the pad is scaled
1942/// parallel to this edge.
1943///
1944/// \image html gpad_pad4.png
1945///
1946/// Note that this function duplicates on purpose the functionality
1947/// already implemented in TBox::ExecuteEvent.
1948/// If somebody modifies this function, may be similar changes should also
1949/// be applied to TBox::ExecuteEvent.
1950
1952{
1953 const Int_t kMaxDiff = 5;
1954 const Int_t kMinSize = 20;
1955 static Int_t pxorg, pyorg;
1956 static Int_t px1, px2, py1, py2, pxl, pyl, pxt, pyt, pxold, pyold;
1957 static Int_t px1p, px2p, py1p, py2p, pxlp, pylp, pxtp, pytp;
1958 static Bool_t pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE;
1959 Int_t wx, wy;
1963
1964 if (!IsEditable() && event != kMouseEnter) return;
1965 TVirtualPad *parent = GetMother();
1966 if (!parent->IsEditable()) return;
1967
1968 HideToolTip(event);
1969
1970 if (fXlowNDC < 0 && event != kButton1Down) return;
1971 if (fYlowNDC < 0 && event != kButton1Down) return;
1972
1973 // keep old mouse position
1974 if (event == kButton1Down) {
1975 pxorg = px;
1976 pyorg = py;
1977 }
1978
1979 Int_t newcode = gROOT->GetEditorMode();
1980 if (newcode)
1981 pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE;
1982 switch (newcode) {
1983 case kPad:
1984 TCreatePrimitives::Pad(event,px,py,0);
1985 break;
1986 case kMarker:
1987 case kText:
1988 TCreatePrimitives::Text(event,px,py,newcode);
1989 break;
1990 case kLine:
1991 TCreatePrimitives::Line(event,px,py,kLine);
1992 break;
1993 case kArrow:
1994 TCreatePrimitives::Line(event,px,py,kArrow);
1995 break;
1996 case kCurlyLine:
1998 break;
1999 case kCurlyArc:
2001 break;
2002 case kPolyLine:
2004 break;
2005 case kCutG:
2007 break;
2008 case kArc:
2009 TCreatePrimitives::Ellipse(event,px,py,kArc);
2010 break;
2011 case kEllipse:
2013 break;
2014 case kButton:
2015 case kPave:
2016 case kPaveLabel:
2017 case kPaveText:
2018 case kPavesText:
2019 case kDiamond:
2020 TCreatePrimitives::Pave(event,px,py,newcode);
2021 return;
2022 default:
2023 break;
2024 }
2025 if (newcode)
2026 return;
2027
2028 auto pp = GetPainter();
2029
2030 auto action = [this,pp,parent](Bool_t paint, Int_t _x1, Int_t _y1, Int_t _x2, Int_t _y2) {
2031 auto x1 = AbsPixeltoX(_x1);
2032 auto y1 = AbsPixeltoY(_y1);
2033 auto x2 = AbsPixeltoX(_x2);
2034 auto y2 = AbsPixeltoY(_y2);
2035 if (paint) {
2036 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow);
2037 } else {
2038 // Get parent corners pixels coordinates
2039 Int_t parentpx1 = fMother->XtoAbsPixel(parent->GetX1());
2040 Int_t parentpx2 = fMother->XtoAbsPixel(parent->GetX2());
2041 Int_t parentpy1 = fMother->YtoAbsPixel(parent->GetY1());
2042 Int_t parentpy2 = fMother->YtoAbsPixel(parent->GetY2());
2043
2044 // Get pad new corners pixels coordinates
2049
2050 // Compute new pad positions in the NDC space of parent
2055 }
2056 };
2057
2058 switch (event) {
2059
2060 case kMouseEnter:
2061 if (fTip)
2063 break;
2064
2065 case kArrowKeyPress:
2066 case kButton1Down:
2067
2070 pp->SetAttLine({GetFillColor() > 0 ? GetFillColor() : (Color_t) 1, GetLineStyle(), 2});
2071
2072 // No break !!!
2073
2074 case kMouseMotion:
2075
2076 px1 = XtoAbsPixel(fX1);
2077 py1 = YtoAbsPixel(fY1);
2078 px2 = XtoAbsPixel(fX2);
2079 py2 = YtoAbsPixel(fY2);
2080
2081 if (px1 < px2) {
2082 pxl = px1;
2083 pxt = px2;
2084 } else {
2085 pxl = px2;
2086 pxt = px1;
2087 }
2088 if (py1 < py2) {
2089 pyl = py1;
2090 pyt = py2;
2091 } else {
2092 pyl = py2;
2093 pyt = py1;
2094 }
2095
2096 px1p = parent->XtoAbsPixel(parent->GetX1()) + parent->GetBorderSize();
2097 py1p = parent->YtoAbsPixel(parent->GetY1()) - parent->GetBorderSize();
2098 px2p = parent->XtoAbsPixel(parent->GetX2()) - parent->GetBorderSize();
2099 py2p = parent->YtoAbsPixel(parent->GetY2()) + parent->GetBorderSize();
2100
2101 if (px1p < px2p) {
2102 pxlp = px1p;
2103 pxtp = px2p;
2104 } else {
2105 pxlp = px2p;
2106 pxtp = px1p;
2107 }
2108 if (py1p < py2p) {
2109 pylp = py1p;
2110 pytp = py2p;
2111 } else {
2112 pylp = py2p;
2113 pytp = py1p;
2114 }
2115
2116 pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE;
2117
2118 // case pA
2119 if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) {
2120 pxold = pxl; pyold = pyl; pA = kTRUE;
2122 }
2123 // case pB
2124 if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) {
2125 pxold = pxt; pyold = pyl; pB = kTRUE;
2127 }
2128 // case pC
2129 if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) {
2130 pxold = pxt; pyold = pyt; pC = kTRUE;
2132 }
2133 // case pD
2134 if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) {
2135 pxold = pxl; pyold = pyt; pD = kTRUE;
2137 }
2138
2139 if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
2140 TMath::Abs(py - pyl) < kMaxDiff) { // top edge
2141 pxold = pxl; pyold = pyl; pTop = kTRUE;
2143 }
2144
2145 if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
2146 TMath::Abs(py - pyt) < kMaxDiff) { // bottom edge
2147 pxold = pxt; pyold = pyt; pBot = kTRUE;
2149 }
2150
2151 if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) &&
2152 TMath::Abs(px - pxl) < kMaxDiff) { // left edge
2153 pxold = pxl; pyold = pyl; pL = kTRUE;
2155 }
2156
2157 if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) &&
2158 TMath::Abs(px - pxt) < kMaxDiff) { // right edge
2159 pxold = pxt; pyold = pyt; pR = kTRUE;
2161 }
2162
2163 if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
2164 (py > pyl+kMaxDiff && py < pyt-kMaxDiff)) { // inside box
2165 pxold = px; pyold = py; pINSIDE = kTRUE;
2166 if (event == kButton1Down)
2168 else
2170 }
2171
2172 fResizing = pA || pB || pC || pD || pTop || pL || pR || pBot;
2173
2174 if (!fResizing && !pINSIDE)
2176
2177 break;
2178
2179 case kArrowKeyRelease:
2180 case kButton1Motion:
2181
2182 if (TestBit(kCannotMove)) break;
2183 wx = wy = 0;
2184
2185 if (pA) {
2186 if (!ropaque) action(kTRUE, pxold, pyt, pxt, pyold);
2187 if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; }
2188 if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; }
2189 if (px < pxlp) { px = pxlp; wx = px; }
2190 if (py < pylp) { py = pylp; wy = py; }
2191 if (fixedr) {
2192 Double_t dy = Double_t(TMath::Abs(pxt-px))/parent->UtoPixel(1.) /
2194 Int_t npy2 = pyt - TMath::Abs(parent->VtoAbsPixel(dy) -
2195 parent->VtoAbsPixel(0));
2196 if (npy2 < pylp) {
2197 px = pxold;
2198 py = pyold;
2199 } else
2200 py = npy2;
2201
2202 wx = wy = 0;
2203 }
2204 if (!ropaque) action(kTRUE, px, pyt, pxt, py);
2205 }
2206 if (pB) {
2207 if (!ropaque) action(kTRUE, pxl, pyt, pxold, pyold);
2208 if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; }
2209 if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; }
2210 if (px > pxtp) { px = pxtp; wx = px; }
2211 if (py < pylp) { py = pylp; wy = py; }
2212 if (fixedr) {
2213 Double_t dy = Double_t(TMath::Abs(pxl-px))/parent->UtoPixel(1.) /
2215 Int_t npy2 = pyt - TMath::Abs(parent->VtoAbsPixel(dy) -
2216 parent->VtoAbsPixel(0));
2217 if (npy2 < pylp) {
2218 px = pxold;
2219 py = pyold;
2220 } else
2221 py = npy2;
2222
2223 wx = wy = 0;
2224 }
2225 if (!ropaque) action(kTRUE, pxl, pyt, px, py);
2226 }
2227 if (pC) {
2228 if (!ropaque) action(kTRUE, pxl, pyl, pxold, pyold);
2229 if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; }
2230 if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; }
2231 if (px > pxtp) { px = pxtp; wx = px; }
2232 if (py > pytp) { py = pytp; wy = py; }
2233 if (fixedr) {
2234 Double_t dy = Double_t(TMath::Abs(pxl-px))/parent->UtoPixel(1.) /
2236 Int_t npy2 = pyl + TMath::Abs(parent->VtoAbsPixel(dy) -
2237 parent->VtoAbsPixel(0));
2238 if (npy2 > pytp) {
2239 px = pxold;
2240 py = pyold;
2241 } else
2242 py = npy2;
2243
2244 wx = wy = 0;
2245 }
2246 if (!ropaque) action(kTRUE, pxl, pyl, px, py);
2247 }
2248 if (pD) {
2249 if (!ropaque) action(kTRUE, pxold, pyold, pxt, pyl);
2250 if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; }
2251 if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; }
2252 if (px < pxlp) { px = pxlp; wx = px; }
2253 if (py > pytp) { py = pytp; wy = py; }
2254 if (fixedr) {
2255 Double_t dy = Double_t(TMath::Abs(pxt-px))/parent->UtoPixel(1.) /
2257 Int_t npy2 = pyl + TMath::Abs(parent->VtoAbsPixel(dy) -
2258 parent->VtoAbsPixel(0));
2259 if (npy2 > pytp) {
2260 px = pxold;
2261 py = pyold;
2262 } else
2263 py = npy2;
2264
2265 wx = wy = 0;
2266 }
2267 if (!ropaque) action(kTRUE, px, py, pxt, pyl);
2268 }
2269 if (pTop) {
2270 if (!ropaque) action(kTRUE, px1, py1, px2, py2);
2271 py2 += py - pyold;
2272 if (py2 > py1-kMinSize) { py2 = py1-kMinSize; wy = py2; }
2273 if (py2 < py2p) { py2 = py2p; wy = py2; }
2274 if (fixedr) {
2275 Double_t dx = Double_t(TMath::Abs(py2-py1))/parent->VtoPixel(0) *
2277 Int_t npx2 = px1 + parent->UtoPixel(dx);
2278 if (npx2 > px2p)
2279 py2 -= py - pyold;
2280 else
2281 px2 = npx2;
2282 }
2283 if (!ropaque) action(kTRUE, px1, py1, px2, py2);
2284 }
2285 if (pBot) {
2286 if (!ropaque) action(kTRUE, px1, py1, px2, py2);
2287 py1 += py - pyold;
2288 if (py1 < py2+kMinSize) { py1 = py2+kMinSize; wy = py1; }
2289 if (py1 > py1p) { py1 = py1p; wy = py1; }
2290 if (fixedr) {
2291 Double_t dx = Double_t(TMath::Abs(py2-py1))/parent->VtoPixel(0) *
2293 Int_t npx2 = px1 + parent->UtoPixel(dx);
2294 if (npx2 > px2p)
2295 py1 -= py - pyold;
2296 else
2297 px2 = npx2;
2298 }
2299 if (!ropaque) action(kTRUE, px1, py1, px2, py2);
2300 }
2301 if (pL) {
2302 if (!ropaque) action(kTRUE, px1, py1, px2, py2);
2303 px1 += px - pxold;
2304 if (px1 > px2-kMinSize) { px1 = px2-kMinSize; wx = px1; }
2305 if (px1 < px1p) { px1 = px1p; wx = px1; }
2306 if (fixedr) {
2307 Double_t dy = Double_t(TMath::Abs(px2-px1))/parent->UtoPixel(1.) /
2309 Int_t npy2 = py1 - TMath::Abs(parent->VtoAbsPixel(dy) -
2310 parent->VtoAbsPixel(0));
2311 if (npy2 < py2p)
2312 px1 -= px - pxold;
2313 else
2314 py2 = npy2;
2315 }
2316 if (!ropaque) action(kTRUE, px1, py1, px2, py2);
2317 }
2318 if (pR) {
2319 if (!ropaque) action(kTRUE, px1, py1, px2, py2);
2320 px2 += px - pxold;
2321 if (px2 < px1+kMinSize) { px2 = px1+kMinSize; wx = px2; }
2322 if (px2 > px2p) { px2 = px2p; wx = px2; }
2323 if (fixedr) {
2324 Double_t dy = Double_t(TMath::Abs(px2-px1))/parent->UtoPixel(1.) /
2326 Int_t npy2 = py1 - TMath::Abs(parent->VtoAbsPixel(dy) -
2327 parent->VtoAbsPixel(0));
2328 if (npy2 < py2p)
2329 px2 -= px - pxold;
2330 else
2331 py2 = npy2;
2332 }
2333 if (!ropaque) action(kTRUE, px1, py1, px2, py2);
2334 }
2335 if (pINSIDE) {
2336 if (!opaque) action(kTRUE, px1, py1, px2, py2); // draw the old box
2337 Int_t dx = px - pxold;
2338 Int_t dy = py - pyold;
2339 px1 += dx; py1 += dy; px2 += dx; py2 += dy;
2340 if (px1 < px1p) { dx = px1p - px1; px1 += dx; px2 += dx; wx = px+dx; }
2341 if (px2 > px2p) { dx = px2 - px2p; px1 -= dx; px2 -= dx; wx = px-dx; }
2342 if (py1 > py1p) { dy = py1 - py1p; py1 -= dy; py2 -= dy; wy = py-dy; }
2343 if (py2 < py2p) { dy = py2p - py2; py1 += dy; py2 += dy; wy = py+dy; }
2344 if (!opaque) action(kTRUE, px1, py1, px2, py2); // draw the new box
2345 }
2346
2347 if (wx || wy) {
2348 if (wx) px = wx;
2349 if (wy) py = wy;
2350 GetCanvasImp()->Warp(px, py);
2351 }
2352
2353 pxold = px;
2354 pyold = py;
2355
2356 if ((!fResizing && opaque) || (fResizing && ropaque)) {
2357 if (px != pxorg || py != pyorg) {
2358 if (pA)
2360 if (pB)
2362 if (pC)
2364 if (pD)
2366 if (pTop || pBot || pL || pR || pINSIDE)
2367 action(kFALSE, px1, py1, px2, py2);
2368 }
2369
2370 // Reset pad parameters and recompute conversion coefficients
2371 ResizePad();
2372
2373 if (pINSIDE) gPad->ShowGuidelines(this, event);
2374 if (pTop) gPad->ShowGuidelines(this, event, 't', true);
2375 if (pBot) gPad->ShowGuidelines(this, event, 'b', true);
2376 if (pL) gPad->ShowGuidelines(this, event, 'l', true);
2377 if (pR) gPad->ShowGuidelines(this, event, 'r', true);
2378 if (pA) gPad->ShowGuidelines(this, event, '1', true);
2379 if (pB) gPad->ShowGuidelines(this, event, '2', true);
2380 if (pC) gPad->ShowGuidelines(this, event, '3', true);
2381 if (pD) gPad->ShowGuidelines(this, event, '4', true);
2382
2383 Modified(kTRUE);
2384 }
2385
2386 break;
2387
2388 case kButton1Up:
2389
2390 if (gROOT->IsEscaped()) {
2391 gROOT->SetEscape(kFALSE);
2392 break;
2393 }
2394
2395 if (opaque||ropaque) {
2396 ShowGuidelines(this, event);
2397 } else {
2398 if (pA)
2400 if (pB)
2402 if (pC)
2404 if (pD)
2406 if (pTop || pBot || pL || pR || pINSIDE)
2407 action(kFALSE, px1, py1, px2, py2);
2408
2409 if (pA || pB || pC || pD || pTop || pL || pR || pBot)
2410 Modified(kTRUE);
2411
2412 pp->SetAttLine({-1, 1, -1});
2413
2414 // Reset pad parameters and recompute conversion coefficients
2415 ResizePad();
2416
2417 // emit signal
2418 RangeChanged();
2419 }
2420
2421 break;
2422
2423 case kButton1Locate:
2424
2425 ExecuteEvent(kButton1Down, px, py);
2426
2427 while (true) {
2428 px = py = 0;
2429 event = GetCanvasImp()->RequestLocator(px, py);
2430
2432
2433 if (event != -1) { // button is released
2434 ExecuteEvent(kButton1Up, px, py);
2435 return;
2436 }
2437 }
2438
2439 case kButton2Down:
2440
2441 Pop();
2442 break;
2443
2444 }
2445}
2446
2447////////////////////////////////////////////////////////////////////////////////
2448/// Execute action corresponding to one event for a TAxis object
2449/// (called by TAxis::ExecuteEvent.)
2450/// This member function is called when an axis is clicked with the locator
2451///
2452/// The axis range is set between the position where the mouse is pressed
2453/// and the position where it is released.
2454///
2455/// If the mouse position is outside the current axis range when it is released
2456/// the axis is unzoomed with the corresponding proportions.
2457///
2458/// Note that the mouse does not need to be in the pad or even canvas
2459/// when it is released.
2460
2462{
2463 if (!IsEditable()) return;
2464 if (!axis) return;
2466
2467 TView *view = GetView();
2468 static Int_t axisNumber;
2469 static Double_t ratio1, ratio2;
2471 Int_t nbd, inc, bin1, bin2, first, last;
2472 Double_t temp, xmin,xmax;
2473 Bool_t opaque = gPad->OpaqueMoving();
2474 bool resetAxisRange = false;
2475 static std::unique_ptr<TBox> zoombox;
2476 Double_t zbx1=0,zbx2=0,zby1=0,zby2=0;
2477
2478 // The CONT4 option, used to paint TH2, is a special case; it uses a 3D
2479 // drawing technique to paint a 2D plot.
2480 TString opt = axis->GetParent()->GetDrawOption();
2481 opt.ToLower();
2483 if (strstr(opt,"cont4")) {
2484 view = nullptr;
2485 kCont4 = kTRUE;
2486 }
2487
2488 auto pp = GetPainter();
2489
2490 switch (event) {
2491
2492 case kButton1Down:
2493 axisNumber = 1;
2494 if (!strcmp(axis->GetName(),"xaxis"))
2495 axisNumber = IsVertical() ? 1 : 2;
2496 if (!strcmp(axis->GetName(),"yaxis"))
2497 axisNumber = IsVertical() ? 2 : 1;
2498 if (!strcmp(axis->GetName(),"zaxis"))
2499 axisNumber = 3;
2500 if (view) {
2501 view->GetDistancetoAxis(axisNumber, px, py, ratio1);
2502 } else {
2503 if (axisNumber == 1) {
2504 ratio1 = (AbsPixeltoX(px) - GetUxmin())/(GetUxmax() - GetUxmin());
2506 py1old = GetUymin();
2507 px2old = px1old;
2508 py2old = GetUymax();
2509 } else if (axisNumber == 2) {
2510 ratio1 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
2512 px1old = GetUxmin();
2513 px2old = GetUxmax();
2514 py2old = py1old;
2515 } else {
2516 ratio1 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
2518 px1old = GetUxmax();
2520 py2old = py1old;
2521 }
2522 if (!opaque) {
2524 } else {
2525 if (axisNumber == 1) {
2526 zbx1 = px1old;
2527 zbx2 = px2old;
2528 zby1 = GetUymin();
2529 zby2 = GetUymax();
2530 } else if (axisNumber == 2) {
2531 zbx1 = GetUxmin();
2532 zbx2 = GetUxmax();
2533 zby1 = py1old;
2534 zby2 = py2old;
2535 }
2536 if (GetLogx()) {
2537 zbx1 = TMath::Power(10,zbx1);
2538 zbx2 = TMath::Power(10,zbx2);
2539 }
2540 if (GetLogy()) {
2541 zby1 = TMath::Power(10,zby1);
2542 zby2 = TMath::Power(10,zby2);
2543 }
2544 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
2545 Int_t ci = TColor::GetColor("#7d7dff");
2546 TColor *zoomcolor = gROOT->GetColor(ci);
2547 if (!pp->IsSupportAlpha() || !zoomcolor)
2548 zoombox->SetFillStyle(3002);
2549 else
2550 zoomcolor->SetAlpha(0.5);
2551 zoombox->SetFillColor(ci);
2552 zoombox->Draw();
2553 gPad->Modified();
2554 gPad->Update();
2555 }
2556 }
2557 if (!opaque)
2558 pp->SetAttLine({-1, 1, 1});
2559 // No break !!!
2560
2561 case kButton1Motion:
2562 if (view) {
2563 view->GetDistancetoAxis(axisNumber, px, py, ratio2);
2564 } else {
2565 if (!opaque)
2567 if (axisNumber == 1) {
2568 ratio2 = (AbsPixeltoX(px) - GetUxmin())/(GetUxmax() - GetUxmin());
2570 } else {
2571 ratio2 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
2573 }
2574 if (!opaque) {
2576 } else {
2577 if (axisNumber == 1) {
2578 zbx1 = px1old;
2579 zbx2 = px2old;
2580 zby1 = GetUymin();
2581 zby2 = GetUymax();
2582 } else if (axisNumber == 2) {
2583 zbx1 = GetUxmin();
2584 zbx2 = GetUxmax();
2585 zby1 = py1old;
2586 zby2 = py2old;
2587 }
2588 if (GetLogx()) {
2589 zbx1 = TMath::Power(10,zbx1);
2590 zbx2 = TMath::Power(10,zbx2);
2591 }
2592 if (GetLogy()) {
2593 zby1 = TMath::Power(10,zby1);
2594 zby2 = TMath::Power(10,zby2);
2595 }
2596 if (zoombox) {
2597 zoombox->SetX1(zbx1);
2598 zoombox->SetY1(zby1);
2599 zoombox->SetX2(zbx2);
2600 zoombox->SetY2(zby2);
2601 }
2602 gPad->Modified();
2603 gPad->Update();
2604 }
2605 }
2606 break;
2607
2608 case kWheelUp:
2609 nbd = (axis->GetLast()-axis->GetFirst());
2610 inc = TMath::Max(nbd/100,1);
2611 bin1 = axis->GetFirst()+inc;
2612 bin2 = axis->GetLast()-inc;
2613 bin1 = TMath::Max(bin1, 1);
2614 bin2 = TMath::Min(bin2, axis->GetNbins());
2615 if (bin2>bin1) {
2616 axis->SetRange(bin1,bin2);
2617 gPad->Modified();
2618 gPad->Update();
2619 }
2620 break;
2621
2622 case kWheelDown:
2623 nbd = (axis->GetLast()-axis->GetFirst());
2624 inc = TMath::Max(nbd/100,1);
2625 bin1 = axis->GetFirst()-inc;
2626 bin2 = axis->GetLast()+inc;
2627 bin1 = TMath::Max(bin1, 1);
2628 bin2 = TMath::Min(bin2, axis->GetNbins());
2629 resetAxisRange = (bin1 == 1 && axis->GetFirst() == 1 && bin2 == axis->GetNbins() && axis->GetLast() == axis->GetNbins());
2630 if (bin2>bin1) {
2631 axis->SetRange(bin1,bin2);
2632 }
2633 if (resetAxisRange)
2635 if (bin2>bin1) {
2636 gPad->Modified();
2637 gPad->Update();
2638 }
2639 break;
2640
2641 case kButton1Up:
2642 if (gROOT->IsEscaped()) {
2643 gROOT->SetEscape(kFALSE);
2644 if (opaque && zoombox)
2645 zoombox.reset();
2646 break;
2647 }
2648
2649 if (view) {
2650 view->GetDistancetoAxis(axisNumber, px, py, ratio2);
2651 if (ratio1 > ratio2) {
2652 temp = ratio1;
2653 ratio1 = ratio2;
2654 ratio2 = temp;
2655 }
2656 if (ratio2 - ratio1 > 0.05) {
2657 TH1 *hobj = (TH1*)axis->GetParent();
2658 if (axisNumber == 3 && hobj && hobj->GetDimension() != 3) {
2659 Float_t zmin = hobj->GetMinimum();
2660 Float_t zmax = hobj->GetMaximum();
2661 if(GetLogz()){
2662 if (zmin <= 0 && zmax > 0) zmin = TMath::Min((Double_t)1,
2663 (Double_t)0.001*zmax);
2664 zmin = TMath::Log10(zmin);
2665 zmax = TMath::Log10(zmax);
2666 }
2667 Float_t newmin = zmin + (zmax-zmin)*ratio1;
2668 Float_t newmax = zmin + (zmax-zmin)*ratio2;
2669 if (newmin < zmin) newmin = hobj->GetBinContent(hobj->GetMinimumBin());
2670 if (newmax > zmax) newmax = hobj->GetBinContent(hobj->GetMaximumBin());
2671 if (GetLogz()){
2672 newmin = TMath::Exp(2.302585092994*newmin);
2673 newmax = TMath::Exp(2.302585092994*newmax);
2674 }
2675 hobj->SetMinimum(newmin);
2676 hobj->SetMaximum(newmax);
2677 hobj->SetBit(TH1::kIsZoomed);
2678 } else {
2679 first = axis->GetFirst();
2680 last = axis->GetLast();
2681 bin1 = first + Int_t((last-first+1)*ratio1);
2682 bin2 = first + Int_t((last-first+1)*ratio2);
2683 bin1 = TMath::Max(bin1, 1);
2684 bin2 = TMath::Min(bin2, axis->GetNbins());
2685 axis->SetRange(bin1, bin2);
2686 }
2687 delete view;
2688 SetView(nullptr);
2689 Modified(kTRUE);
2690 }
2691 } else {
2692 if (axisNumber == 1) {
2693 ratio2 = (AbsPixeltoX(px) - GetUxmin())/(GetUxmax() - GetUxmin());
2694 xmin = GetUxmin() +ratio1*(GetUxmax() - GetUxmin());
2695 xmax = GetUxmin() +ratio2*(GetUxmax() - GetUxmin());
2696 if (GetLogx() && !kCont4) {
2697 xmin = PadtoX(xmin);
2698 xmax = PadtoX(xmax);
2699 }
2700 } else if (axisNumber == 2) {
2701 ratio2 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
2702 xmin = GetUymin() +ratio1*(GetUymax() - GetUymin());
2703 xmax = GetUymin() +ratio2*(GetUymax() - GetUymin());
2704 if (GetLogy() && !kCont4) {
2705 xmin = PadtoY(xmin);
2706 xmax = PadtoY(xmax);
2707 }
2708 } else {
2709 ratio2 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
2710 xmin = ratio1;
2711 xmax = ratio2;
2712 }
2713 if (xmin > xmax) {
2714 temp = xmin;
2715 xmin = xmax;
2716 xmax = temp;
2717 temp = ratio1;
2718 ratio1 = ratio2;
2719 ratio2 = temp;
2720 }
2721
2722 // xmin and xmax need to be adjusted in case of CONT4.
2723 if (kCont4) {
2724 Double_t low = axis->GetBinLowEdge(axis->GetFirst());
2725 Double_t up = axis->GetBinUpEdge(axis->GetLast());
2726 Double_t xmi = GetUxmin();
2727 Double_t xma = GetUxmax();
2728 xmin = ((xmin-xmi)/(xma-xmi))*(up-low)+low;
2729 xmax = ((xmax-xmi)/(xma-xmi))*(up-low)+low;
2730 }
2731
2732 if (!strcmp(axis->GetName(),"xaxis")) axisNumber = 1;
2733 if (!strcmp(axis->GetName(),"yaxis")) axisNumber = 2;
2734 if (ratio2 - ratio1 > 0.05) {
2735 //update object owning this axis
2736 TH1 *hobj1 = (TH1*)axis->GetParent();
2737 bin1 = axis->FindFixBin(xmin);
2738 bin2 = axis->FindFixBin(xmax);
2739 bin1 = TMath::Max(bin1, 1);
2740 bin2 = TMath::Min(bin2, axis->GetNbins());
2741 if (axisNumber == 1) axis->SetRange(bin1,bin2);
2742 if (axisNumber == 2 && hobj1) {
2743 if (hobj1->GetDimension() == 1) {
2744 if (hobj1->GetNormFactor() != 0) {
2745 Double_t norm = hobj1->GetSumOfWeights()/hobj1->GetNormFactor();
2746 xmin *= norm;
2747 xmax *= norm;
2748 }
2749 hobj1->SetMinimum(xmin);
2750 hobj1->SetMaximum(xmax);
2751 hobj1->SetBit(TH1::kIsZoomed);
2752 } else {
2753 axis->SetRange(bin1,bin2);
2754 }
2755 }
2756 //update all histograms in the pad
2757 TIter next(GetListOfPrimitives());
2758 TObject *obj;
2759 while ((obj= next())) {
2760 if (!obj->InheritsFrom(TH1::Class())) continue;
2761 TH1 *hobj = (TH1*)obj;
2762 if (hobj == hobj1) continue;
2763 bin1 = hobj->GetXaxis()->FindFixBin(xmin);
2764 bin2 = hobj->GetXaxis()->FindFixBin(xmax);
2765 if (axisNumber == 1) {
2766 hobj->GetXaxis()->SetRange(bin1,bin2);
2767 } else if (axisNumber == 2) {
2768 if (hobj->GetDimension() == 1) {
2771 if (hobj->GetNormFactor() != 0) {
2772 Double_t norm = hobj->GetSumOfWeights()/hobj->GetNormFactor();
2773 xxmin *= norm;
2774 xxmax *= norm;
2775 }
2776 hobj->SetMinimum(xxmin);
2777 hobj->SetMaximum(xxmax);
2778 hobj->SetBit(TH1::kIsZoomed);
2779 } else {
2780 bin1 = hobj->GetYaxis()->FindFixBin(xmin);
2781 bin2 = hobj->GetYaxis()->FindFixBin(xmax);
2782 hobj->GetYaxis()->SetRange(bin1,bin2);
2783 }
2784 }
2785 }
2786 Modified(kTRUE);
2787 }
2788 }
2789 if (!opaque) {
2790 pp->SetAttLine({-1, 1, 1});
2791 } else {
2792 if (zoombox) {
2793 zoombox.reset();
2794 gPad->Modified();
2795 gPad->Update();
2796 }
2797 }
2798 break;
2799 }
2800}
2801
2802////////////////////////////////////////////////////////////////////////////////
2803/// Search if object named name is inside this pad or in pads inside this pad.
2804///
2805/// In case name is in several sub-pads the first one is returned.
2806
2807TObject *TPad::FindObject(const char *name) const
2808{
2809 if (!fPrimitives) return nullptr;
2811 if (found) return found;
2812 TIter next(GetListOfPrimitives());
2813 while (auto cur = next()) {
2814 if (cur->InheritsFrom(TPad::Class())) {
2815 found = ((TPad*)cur)->FindObject(name);
2816 if (found) return found;
2817 }
2818 }
2819 return nullptr;
2820}
2821
2822////////////////////////////////////////////////////////////////////////////////
2823/// Search if obj is in pad or in pads inside this pad.
2824///
2825/// In case obj is in several sub-pads the first one is returned.
2826
2828{
2829 if (!fPrimitives) return nullptr;
2830 TObject *found = fPrimitives->FindObject(obj);
2831 if (found) return found;
2832 TIter next(GetListOfPrimitives());
2833 while (auto cur = next()) {
2834 if (cur->InheritsFrom(TPad::Class())) {
2835 found = ((TPad*)cur)->FindObject(obj);
2836 if (found) return found;
2837 }
2838 }
2839 return nullptr;
2840}
2841
2842////////////////////////////////////////////////////////////////////////////////
2843/// Get canvas identifier.
2844
2846{
2847 return fCanvas ? fCanvas->GetCanvasID() : -1;
2848}
2849
2850////////////////////////////////////////////////////////////////////////////////
2851/// Get canvas implementation pointer if any
2852
2854{
2855 return fCanvas ? fCanvas->GetCanvasImp() : nullptr;
2856}
2857
2858////////////////////////////////////////////////////////////////////////////////
2859/// Get Event.
2860
2862{
2863 return fCanvas ? fCanvas->GetEvent() : 0;
2864}
2865
2866////////////////////////////////////////////////////////////////////////////////
2867/// Get X event.
2868
2870{
2871 return fCanvas ? fCanvas->GetEventX() : 0;
2872}
2873
2874////////////////////////////////////////////////////////////////////////////////
2875/// Get Y event.
2876
2878{
2879 return fCanvas ? fCanvas->GetEventY() : 0;
2880}
2881
2882////////////////////////////////////////////////////////////////////////////////
2883/// Get virtual canvas.
2884
2886{
2887 return fCanvas ? (TVirtualPad*) fCanvas : nullptr;
2888}
2889
2890////////////////////////////////////////////////////////////////////////////////
2891/// Get highlight color.
2892
2894{
2895 return fCanvas ? fCanvas->GetHighLightColor() : 0;
2896}
2897
2898////////////////////////////////////////////////////////////////////////////////
2899/// Static function (see also TPad::SetMaxPickDistance)
2900
2905
2906////////////////////////////////////////////////////////////////////////////////
2907/// Get selected.
2908
2910{
2911 if (fCanvas == this) return nullptr;
2912 return fCanvas ? fCanvas->GetSelected() : nullptr;
2913}
2914
2915////////////////////////////////////////////////////////////////////////////////
2916/// Get selected pad.
2917
2919{
2920 if (fCanvas == this) return nullptr;
2921 return fCanvas ? fCanvas->GetSelectedPad() : nullptr;
2922}
2923
2924////////////////////////////////////////////////////////////////////////////////
2925/// Get save pad.
2926
2928{
2929 if (fCanvas == this) return nullptr;
2930 return fCanvas ? fCanvas->GetPadSave() : nullptr;
2931}
2932
2933////////////////////////////////////////////////////////////////////////////////
2934/// Get Wh.
2935
2937{
2938 return fCanvas ? fCanvas->GetWh() : 0;
2939}
2940
2941////////////////////////////////////////////////////////////////////////////////
2942/// Get Ww.
2943
2945{
2946 return fCanvas ? fCanvas->GetWw() : 0;
2947}
2948
2949////////////////////////////////////////////////////////////////////////////////
2950/// Hide tool tip depending on the event type. Typically tool tips
2951/// are hidden when event is not a kMouseEnter and not a kMouseMotion
2952/// event.
2953
2955{
2956 if (event != kMouseEnter && event != kMouseMotion && fTip)
2957 gPad->CloseToolTip(fTip);
2958}
2959
2960////////////////////////////////////////////////////////////////////////////////
2961/// Is pad in batch mode ?
2962
2964{
2965 return fCanvas ? fCanvas->IsBatch() : kFALSE;
2966}
2967
2968////////////////////////////////////////////////////////////////////////////////
2969/// Is pad retained ?
2970
2972{
2973 return fCanvas ? fCanvas->IsRetained() : kFALSE;
2974}
2975
2976////////////////////////////////////////////////////////////////////////////////
2977/// Is web ?
2979{
2980 return fCanvas ? fCanvas->IsWeb() : kFALSE;
2981}
2982
2983////////////////////////////////////////////////////////////////////////////////
2984/// Is pad moving in opaque mode ?
2985
2987{
2988 return fCanvas ? fCanvas->OpaqueMoving() : kFALSE;
2989}
2990
2991////////////////////////////////////////////////////////////////////////////////
2992/// Is pad resizing in opaque mode ?
2993
2995{
2996 return fCanvas ? fCanvas->OpaqueResizing() : kFALSE;
2997}
2998
2999////////////////////////////////////////////////////////////////////////////////
3000/// Set pad in batch mode.
3001
3003{
3005}
3006
3007////////////////////////////////////////////////////////////////////////////////
3008/// Set canvas size.
3009
3011{
3012 if (fCanvas) fCanvas->SetCanvasSize(ww,wh);
3013}
3014
3015////////////////////////////////////////////////////////////////////////////////
3016/// Set cursor type.
3017
3022
3023////////////////////////////////////////////////////////////////////////////////
3024/// Set double buffer mode ON or OFF.
3025
3030
3031////////////////////////////////////////////////////////////////////////////////
3032/// Set selected.
3033
3035{
3036 if (fCanvas) fCanvas->SetSelected(obj);
3037}
3038
3039////////////////////////////////////////////////////////////////////////////////
3040/// Update pad.
3041
3043{
3044 if (fCanvas) fCanvas->Update();
3045}
3046
3047////////////////////////////////////////////////////////////////////////////////
3048/// Asynchronous pad update.
3049/// In case of web-based canvas triggers update of the canvas on the client side,
3050/// but does not wait that real update is completed. Avoids blocking of caller thread.
3051/// Have to be used if called from other web-based widget to avoid logical dead-locks.
3052/// In case of normal canvas just canvas->Update() is performed.
3053
3055{
3056 if (fCanvas) fCanvas->UpdateAsync();
3057}
3058
3059////////////////////////////////////////////////////////////////////////////////
3060/// Get frame.
3061
3063{
3064 if (!fPrimitives) fPrimitives = new TList;
3066 if (!frame) frame = (TFrame*)GetListOfPrimitives()->FindObject("TFrame");
3067 fFrame = frame;
3068 if (!fFrame) {
3069 if (!frame) fFrame = new TFrame(0,0,1,1);
3079 } else {
3080 // Preexisting and now assigned to fFrame, let's make sure it is not
3081 // deleted twice (the bit might have been set in TPad::Streamer)
3083 }
3084 return fFrame;
3085}
3086
3087////////////////////////////////////////////////////////////////////////////////
3088/// Get primitive.
3089
3091{
3092 if (!fPrimitives) return nullptr;
3093 TIter next(fPrimitives);
3094 TObject *found, *obj;
3095 while ((obj=next())) {
3096 if (!strcmp(name, obj->GetName())) return obj;
3097 if (obj->InheritsFrom(TPad::Class())) continue;
3098 found = obj->FindObject(name);
3099 if (found) return found;
3100 }
3101 return nullptr;
3102}
3103
3104////////////////////////////////////////////////////////////////////////////////
3105/// Get a pointer to subpadnumber of this pad.
3106
3108{
3109 if (!subpadnumber) {
3110 return (TVirtualPad*)this;
3111 }
3112
3113 TObject *obj;
3114 if (!fPrimitives) return nullptr;
3115 TIter next(GetListOfPrimitives());
3116 while ((obj = next())) {
3117 if (obj->InheritsFrom(TVirtualPad::Class())) {
3118 TVirtualPad *pad = (TVirtualPad*)obj;
3119 if (pad->GetNumber() == subpadnumber) return pad;
3120 }
3121 }
3122 return nullptr;
3123}
3124
3125////////////////////////////////////////////////////////////////////////////////
3126/// Return lower and upper bounds of the pad in NDC coordinates.
3127
3128void TPad::GetPadPar(Double_t &xlow, Double_t &ylow, Double_t &xup, Double_t &yup)
3129{
3130 xlow = fXlowNDC;
3131 ylow = fYlowNDC;
3132 xup = fXlowNDC+fWNDC;
3133 yup = fYlowNDC+fHNDC;
3134}
3135
3136////////////////////////////////////////////////////////////////////////////////
3137/// Return pad world coordinates range.
3138
3140{
3141 x1 = fX1;
3142 y1 = fY1;
3143 x2 = fX2;
3144 y2 = fY2;
3145}
3146
3147////////////////////////////////////////////////////////////////////////////////
3148/// Return pad axis coordinates range.
3149
3151{
3152 xmin = fUxmin;
3153 ymin = fUymin;
3154 xmax = fUxmax;
3155 ymax = fUymax;
3156}
3157
3158////////////////////////////////////////////////////////////////////////////////
3159/// Highlight pad.
3160/// do not highlight when printing on Postscript
3161
3163{
3164 if (auto pp = GetPainter())
3165 if(!pp->IsNative())
3166 return;
3167
3168 if (color <= 0)
3169 return;
3170
3172
3173 // We do not want to have active(executable) buttons, etc highlighted
3174 // in this manner, unless we want to edit'em
3176 //When doing a DrawClone from the GUI you would do
3177 // - select an empty pad -
3178 // - right click on object -
3179 // - select DrawClone on menu -
3180 //
3181 // Without the SetSelectedPad(); in the HighLight function, the
3182 // above instruction lead to the clone to be drawn in the
3183 // same canvas as the original object. This is because the
3184 // 'right clicking' (via TCanvas::HandleInput) changes gPad
3185 // momentarily such that when DrawClone is called, it is
3186 // not the right value (for DrawClone). Should be FIXED.
3187 gROOT->SetSelectedPad(this);
3188 if (GetBorderMode() > 0)
3189 PaintBorder(set ? -color : -GetFillColor(), kFALSE);
3190 }
3191
3193}
3194
3195////////////////////////////////////////////////////////////////////////////////
3196/// List all primitives in pad.
3197
3199{
3201 std::cout <<IsA()->GetName()<<" fXlowNDC=" <<fXlowNDC<<" fYlowNDC="<<fYlowNDC<<" fWNDC="<<GetWNDC()<<" fHNDC="<<GetHNDC()
3202 <<" Name= "<<GetName()<<" Title= "<<GetTitle()<<" Option="<<option<<std::endl;
3204 if (!fPrimitives) return;
3207}
3208
3209////////////////////////////////////////////////////////////////////////////////
3210/// Increment (i==1) or set (i>1) the number of autocolor in the pad.
3211
3213{
3214 if (opt.Index("pfc")>=0 || opt.Index("plc")>=0 || opt.Index("pmc")>=0) {
3215 if (i==1) fNumPaletteColor++;
3216 else fNumPaletteColor = i;
3217 return fNumPaletteColor;
3218 } else {
3219 return 0;
3220 }
3221}
3222
3223////////////////////////////////////////////////////////////////////////////////
3224/// Get the next autocolor in the pad.
3225
3227{
3228 Int_t i = 0;
3229 Int_t ncolors = gStyle->GetNumberOfColors();
3230 if (fNumPaletteColor>1) {
3231 i = fNextPaletteColor*(ncolors/(fNumPaletteColor-1));
3232 if (i>=ncolors) i = ncolors-1;
3233 }
3236 return gStyle->GetColorPalette(i);
3237}
3238
3239////////////////////////////////////////////////////////////////////////////////
3240/// Initialise the grid used to find empty space when adding a box (Legend) in a pad
3241
3243{
3244 Int_t const cellSize = 10; // Size of an individual grid cell in pixels.
3245
3246 fCGnx = GetWw()/cellSize;
3247 fCGny = GetWh()/cellSize;
3248
3249 // Initialise the collide grid
3250 fCollideGrid.resize(fCGnx*fCGny);
3251 for (int i = 0; i < fCGnx; i++)
3252 for (int j = 0; j < fCGny; j++)
3253 fCollideGrid[i + j * fCGnx] = kTRUE;
3254
3255 // Fill the collide grid
3256 TIter iter(GetListOfPrimitives());
3257
3258 while(auto o = iter()) {
3259 if (o == oi)
3260 continue;
3261 if (o->InheritsFrom(TFrame::Class()))
3263 else if (o->InheritsFrom(TBox::Class()))
3265 else if (o->InheritsFrom(TH1::Class()))
3267 else if (o->InheritsFrom(TGraph::Class()))
3269 else if (o->InheritsFrom(TMultiGraph::Class())) {
3270 TIter nextgraph(((TMultiGraph *)o)->GetListOfGraphs());
3271 while (auto og = nextgraph())
3273 } else if (o->InheritsFrom(THStack::Class())) {
3274 TIter nexthist(((THStack *)o)->GetHists());
3275 while (auto oh = nexthist()) {
3276 if (oh->InheritsFrom(TH1::Class()))
3278 }
3279 }
3280 }
3281}
3282
3283////////////////////////////////////////////////////////////////////////////////
3284/// Check if a box of size w and h collide some primitives in the pad at
3285/// position i,j
3286
3288{
3289 for (int r = i; r < w + i; r++) {
3290 for (int c = j; c < h + j; c++) {
3291 if (!fCollideGrid[r + c * fCGnx])
3292 return kTRUE;
3293 }
3294 }
3295 return kFALSE;
3296}
3297
3298////////////////////////////////////////////////////////////////////////////////
3299/// Place a box in NDC space
3300///
3301/// \return `true` if the box could be placed, `false` if not.
3302///
3303/// \param[in] o pointer to the box to be placed
3304/// \param[in] w box width to be placed
3305/// \param[in] h box height to be placed
3306/// \param[out] xl x position of the bottom left corner of the placed box
3307/// \param[out] yb y position of the bottom left corner of the placed box
3308/// \param[in] option l=left, r=right, t=top, b=bottom, w=within margins. Order determines
3309/// priority for placement. Default is "lb" (prioritises horizontal over vertical)
3310
3312{
3313 FillCollideGrid(o);
3314
3315 Int_t iw = (int)(fCGnx*w);
3316 Int_t ih = (int)(fCGny*h);
3317
3318 Int_t nxbeg = 0;
3319 Int_t nybeg = 0;
3320 Int_t nxend = fCGnx-iw-1;
3321 Int_t nyend = fCGny-ih-1;
3322 Int_t dx = 1;
3323 Int_t dy = 1;
3324
3325 bool isFirstVertical = false;
3326 bool isFirstHorizontal = false;
3327
3328 for (std::size_t i = 0; option[i] != '\0'; ++i) {
3329 char letter = std::tolower(option[i]);
3330 if (letter == 'w') {
3335 } else if (letter == 't' || letter == 'b') {
3337 // go from top to bottom instead of bottom to top
3338 dy = letter == 't' ? -1 : 1;
3339 } else if (letter == 'l' || letter == 'r') {
3341 // go from right to left instead of left to right
3342 dx = letter == 'r' ? -1 : 1;
3343 }
3344 }
3345
3346 if(dx < 0) std::swap(nxbeg, nxend);
3347 if(dy < 0) std::swap(nybeg, nyend);
3348
3349 auto attemptPlacement = [&](Int_t i, Int_t j) {
3350 if (Collide(i, j, iw, ih)) {
3351 return false;
3352 } else {
3353 xl = (Double_t)(i) / (Double_t)(fCGnx);
3354 yb = (Double_t)(j) / (Double_t)(fCGny);
3355 return true;
3356 }
3357 };
3358
3359 if(!isFirstVertical) {
3360 for (Int_t i = nxbeg; i != nxend; i += dx) {
3361 for (Int_t j = nybeg; j != nyend; j += dy) {
3362 if (attemptPlacement(i, j)) return true;
3363 }
3364 }
3365 } else {
3366 // prioritizing vertical over horizontal
3367 for (Int_t j = nybeg; j != nyend; j += dy) {
3368 for (Int_t i = nxbeg; i != nxend; i += dx) {
3369 if (attemptPlacement(i, j)) return true;
3370 }
3371 }
3372 }
3373
3374 return kFALSE;
3375}
3376
3377#define NotFree(i, j) fCollideGrid[TMath::Max(TMath::Min(i+j*fCGnx,fCGnx*fCGny),0)] = kFALSE;
3378
3379////////////////////////////////////////////////////////////////////////////////
3380/// Mark as "not free" the cells along a line.
3381
3383{
3384 NotFree(x1, y1);
3385 NotFree(x2, y2);
3386 Int_t i, j, xt, yt;
3387
3388 // horizontal lines
3389 if (y1==y2) {
3390 for (i=x1+1; i<x2; i++) NotFree(i,y1);
3391 return;
3392 }
3393
3394 // vertical lines
3395 if (x1==x2) {
3396 for (i=y1+1; i<y2; i++) NotFree(x1,i);
3397 return;
3398 }
3399
3400 // other lines
3401 if (TMath::Abs(x2-x1)>TMath::Abs(y2-y1)) {
3402 if (x1>x2) {
3403 xt = x1; x1 = x2; x2 = xt;
3404 yt = y1; y1 = y2; y2 = yt;
3405 }
3406 for (i=x1+1; i<x2; i++) {
3407 j = (Int_t)((Double_t)(y2-y1)*(Double_t)((i-x1)/(Double_t)(x2-x1))+y1);
3408 NotFree(i,j);
3409 NotFree(i,(j+1));
3410 }
3411 } else {
3412 if (y1>y2) {
3413 yt = y1; y1 = y2; y2 = yt;
3414 xt = x1; x1 = x2; x2 = xt;
3415 }
3416 for (j=y1+1; j<y2; j++) {
3417 i = (Int_t)((Double_t)(x2-x1)*(Double_t)((j-y1)/(Double_t)(y2-y1))+x1);
3418 NotFree(i,j);
3419 NotFree((i+1),j);
3420 }
3421 }
3422}
3423
3424////////////////////////////////////////////////////////////////////////////////
3426{
3427 TBox *b = (TBox *)o;
3428 if (fCGnx==0||fCGny==0) return;
3429 Double_t xs = (fX2-fX1)/fCGnx;
3430 Double_t ys = (fY2-fY1)/fCGny;
3431
3432 Int_t x1 = (Int_t)((b->GetX1()-fX1)/xs);
3433 Int_t x2 = (Int_t)((b->GetX2()-fX1)/xs);
3434 Int_t y1 = (Int_t)((b->GetY1()-fY1)/ys);
3435 Int_t y2 = (Int_t)((b->GetY2()-fY1)/ys);
3436 for (int i = x1; i<=x2; i++) {
3437 for (int j = y1; j<=y2; j++) NotFree(i, j);
3438 }
3439}
3440
3441////////////////////////////////////////////////////////////////////////////////
3443{
3444 TFrame *f = (TFrame *)o;
3445 if (fCGnx==0||fCGny==0) return;
3446 Double_t xs = (fX2-fX1)/fCGnx;
3447 Double_t ys = (fY2-fY1)/fCGny;
3448
3449 Int_t x1 = (Int_t)((f->GetX1()-fX1)/xs);
3450 Int_t x2 = (Int_t)((f->GetX2()-fX1)/xs);
3451 Int_t y1 = (Int_t)((f->GetY1()-fY1)/ys);
3452 Int_t y2 = (Int_t)((f->GetY2()-fY1)/ys);
3453 Int_t i;
3454
3455 for (i = x1; i<=x2; i++) {
3456 NotFree(i, y1);
3457 NotFree(i, (y1-1));
3458 NotFree(i, (y1-2));
3459 }
3460 for (i = y1; i<=y2; i++) {
3461 NotFree(x1, i);
3462 NotFree((x1-1), i);
3463 NotFree((x1-2), i);
3464 }
3465}
3466
3467////////////////////////////////////////////////////////////////////////////////
3469{
3470 TGraph *g = (TGraph *)o;
3471 if (fCGnx==0||fCGny==0) return;
3472 Double_t xs = (fX2-fX1)/fCGnx;
3473 Double_t ys = (fY2-fY1)/fCGny;
3474
3475 Int_t n = g->GetN();
3476 Int_t s = TMath::Max(n/10,1);
3477 Double_t x1, x2, y1, y2;
3478 for (Int_t i=s; i<n; i=i+s) {
3479 g->GetPoint(TMath::Max(0,i-s),x1,y1);
3480 g->GetPoint(i ,x2,y2);
3481 if (fLogx) {
3482 if (x1 > 0) x1 = TMath::Log10(x1);
3483 else x1 = fUxmin;
3484 if (x2 > 0) x2 = TMath::Log10(x2);
3485 else x2 = fUxmin;
3486 }
3487 if (fLogy) {
3488 if (y1 > 0) y1 = TMath::Log10(y1);
3489 else y1 = fUymin;
3490 if (y2 > 0) y2 = TMath::Log10(y2);
3491 else y2 = fUymin;
3492 }
3493 LineNotFree((int)((x1-fX1)/xs), (int)((x2-fX1)/xs),
3494 (int)((y1-fY1)/ys), (int)((y2-fY1)/ys));
3495 }
3496}
3497
3498////////////////////////////////////////////////////////////////////////////////
3500{
3501 TH1 *h = (TH1 *)o;
3502 if (fCGnx==0||fCGny==0) return;
3503 if (o->InheritsFrom(TH2::Class())) return;
3504 if (o->InheritsFrom(TH3::Class())) return;
3505
3506 TString name = h->GetName();
3507 if (name.Index("hframe") >= 0) return;
3508
3509 Double_t xs = (fX2-fX1)/fCGnx;
3510 Double_t ys = (fY2-fY1)/fCGny;
3511
3512 bool haserrors = false;
3513 TString drawOption = h->GetDrawOption();
3514 drawOption.ToLower();
3515 drawOption.ReplaceAll("same","");
3516
3517 if (drawOption.Index("hist") < 0) {
3518 if (drawOption.Index("e") >= 0) haserrors = true;
3519 }
3520
3521 Int_t nx = h->GetNbinsX();
3522 Int_t x1, y1, y2;
3523 Int_t i, j;
3524 Double_t x1l, y1l, y2l;
3525
3526 for (i = 1; i<nx; i++) {
3527 if (haserrors) {
3528 x1l = h->GetBinCenter(i);
3529 if (fLogx) {
3530 if (x1l > 0) x1l = TMath::Log10(x1l);
3531 else x1l = fUxmin;
3532 }
3533 x1 = (Int_t)((x1l-fX1)/xs);
3534 y1l = h->GetBinContent(i)-h->GetBinErrorLow(i);
3535 if (fLogy) {
3536 if (y1l > 0) y1l = TMath::Log10(y1l);
3537 else y1l = fUymin;
3538 }
3539 y1 = (Int_t)((y1l-fY1)/ys);
3540 y2l = h->GetBinContent(i)+h->GetBinErrorUp(i);
3541 if (fLogy) {
3542 if (y2l > 0) y2l = TMath::Log10(y2l);
3543 else y2l = fUymin;
3544 }
3545 y2 = (Int_t)((y2l-fY1)/ys);
3546 for (j=y1; j<y2; j++) {
3547 NotFree(x1, j);
3548 }
3549 }
3550 x1l = h->GetBinLowEdge(i);
3551 if (fLogx) {
3552 if (x1l > 0) x1l = TMath::Log10(x1l);
3553 else x1l = fUxmin;
3554 }
3555 x1 = (Int_t)((x1l-fX1)/xs);
3556 y1l = h->GetBinContent(i);
3557 if (fLogy) {
3558 if (y1l > 0) y1l = TMath::Log10(y1l);
3559 else y1l = fUymin;
3560 }
3561 y1 = (Int_t)((y1l-fY1)/ys);
3562 NotFree(x1, y1);
3563 x1l = h->GetBinLowEdge(i)+h->GetBinWidth(i);
3564 if (fLogx) {
3565 if (x1l > 0) x1l = TMath::Log10(x1l);
3566 else x1l = fUxmin;
3567 }
3568 x1 = (int)((x1l-fX1)/xs);
3569 NotFree(x1, y1);
3570 }
3571
3572 // Extra objects in the list of function
3573 TPaveStats *ps = (TPaveStats*)h->GetListOfFunctions()->FindObject("stats");
3574 if (ps) FillCollideGridTBox(ps);
3575}
3576
3577////////////////////////////////////////////////////////////////////////////////
3578/// This method draws the collide grid on top of the canvas. This is used for
3579/// debugging only. At some point it will be removed.
3580
3582{
3583 if (fCGnx==0||fCGny==0) return;
3584
3585 TContext ctxt(this, kTRUE);
3586
3587 TBox box;
3588 box.SetFillColorAlpha(kRed,0.5);
3589
3590 Double_t xs = (fX2-fX1)/fCGnx;
3591 Double_t ys = (fY2-fY1)/fCGny;
3592
3593 Double_t X1L, X2L, Y1L, Y2L;
3594 Double_t t = 0.15;
3595 Double_t Y1, Y2;
3596 Double_t X1 = fX1;
3597 Double_t X2 = X1+xs;
3598
3599 for (int i = 0; i<fCGnx; i++) {
3600 Y1 = fY1;
3601 Y2 = Y1+ys;
3602 for (int j = 0; j<fCGny; j++) {
3603 if (GetLogx()) {
3604 X1L = TMath::Power(10,X1);
3605 X2L = TMath::Power(10,X2);
3606 } else {
3607 X1L = X1;
3608 X2L = X2;
3609 }
3610 if (GetLogy()) {
3611 Y1L = TMath::Power(10,Y1);
3612 Y2L = TMath::Power(10,Y2);
3613 } else {
3614 Y1L = Y1;
3615 Y2L = Y2;
3616 }
3617 if (!fCollideGrid[i + j*fCGnx]) {
3618 box.SetFillColorAlpha(kBlack,t);
3619 box.DrawBox(X1L, Y1L, X2L, Y2L);
3620 } else {
3621 box.SetFillColorAlpha(kRed,t);
3622 box.DrawBox(X1L, Y1L, X2L, Y2L);
3623 }
3624 Y1 = Y2;
3625 Y2 = Y1+ys;
3626 if (t==0.15) t = 0.1;
3627 else t = 0.15;
3628 }
3629 X1 = X2;
3630 X2 = X1+xs;
3631 }
3632}
3633
3634////////////////////////////////////////////////////////////////////////////////
3635/// Short cut to call Modified() and Update() in a single call.
3636/// On Mac with Cocoa, it performs an additional ProcessEvents().
3637
3639{
3640 Modified();
3641 Update();
3642#ifdef R__HAS_COCOA
3644#endif
3645}
3646
3647////////////////////////////////////////////////////////////////////////////////
3648/// Convert x from pad to X.
3649
3651{
3652 if (fLogx && x < 50) return Double_t(TMath::Exp(2.302585092994*x));
3653 return x;
3654}
3655
3656////////////////////////////////////////////////////////////////////////////////
3657/// Convert y from pad to Y.
3658
3660{
3661 if (fLogy && y < 50) return Double_t(TMath::Exp(2.302585092994*y));
3662 return y;
3663}
3664
3665////////////////////////////////////////////////////////////////////////////////
3666/// Convert x from X to pad.
3667
3669{
3670 if (fLogx) {
3671 if (x > 0) x = TMath::Log10(x);
3672 else x = fUxmin;
3673 }
3674 return x;
3675}
3676
3677////////////////////////////////////////////////////////////////////////////////
3678/// Convert y from Y to pad.
3679
3681{
3682 if (fLogy) {
3683 if (y > 0) y = TMath::Log10(y);
3684 else y = fUymin;
3685 }
3686 return y;
3687}
3688
3689////////////////////////////////////////////////////////////////////////////////
3690/// Paint all primitives in pad.
3691
3692void TPad::Paint(Option_t * /*option*/)
3693{
3694 if (!fPrimitives)
3695 fPrimitives = new TList;
3697 fViewer3D->PadPaint(this);
3699 if (GetGLDevice()!=-1 && gVirtualPS) {
3700 TContext ctxt(this, kFALSE);
3701 if (gGLManager) gGLManager->PrintViewer(GetViewer3D());
3702 }
3703 return;
3704 }
3705
3706 TVirtualPadPainter *oldpp = nullptr;
3708
3709 if (fCanvas) {
3710 // check if special PS painter should be assigned to TCanvas
3713 }
3714
3716 fPadPaint = 1;
3717
3718 {
3719 TContext ctxt(this, kTRUE);
3720
3722 PaintDate();
3723
3724 auto lnk = GetListOfPrimitives()->FirstLink();
3725
3726 while (lnk) {
3727 TObject *obj = lnk->GetObject();
3728
3729 // Create a pad 3D viewer if none exists and we encounter a 3D shape
3730 if (!fViewer3D && obj->InheritsFrom(TAtt3D::Class())) {
3731 GetViewer3D("pad");
3732 }
3733
3734 // Open a 3D scene if required
3735 if (fViewer3D && !fViewer3D->BuildingScene()) {
3738 }
3739
3740 obj->Paint(lnk->GetOption());
3741 lnk = lnk->Next();
3742 }
3743 }
3744
3745 fPadPaint = 0;
3747
3748 if (replace_pp && fCanvas)
3750
3751 // Close the 3D scene if we opened it. This must be done after modified
3752 // flag is cleared, as some viewers will invoke another paint by marking pad modified again
3753 if (began3DScene) {
3755 }
3756}
3757
3758////////////////////////////////////////////////////////////////////////////////
3759/// Paint the pad border.
3760/// Draw first a box as a normal filled box
3761
3762void TPad::PaintBorder(Color_t color, Bool_t /* tops */)
3763{
3764 auto pp = GetPainter();
3765 if (!pp)
3766 return;
3767
3768 pp->OnPad(this);
3769
3770 if (color >= 0) {
3771 TAttLine::Modify(); //Change line attributes only if necessary
3772 TAttFill::Modify(); //Change fill area attributes only if necessary
3773
3774 //With Cocoa we have a transparency. But we also have
3775 //pixmaps, and if you just paint a new content over the old one
3776 //with alpha < 1., you'll be able to see the old content.
3777 if (pp->IsNative() && pp->IsCocoa())
3778 pp->ClearDrawable();
3779
3780 PaintBox(fX1, fY1, fX2, fY2);
3781 }
3782 if (color < 0)
3783 color = -color;
3784 if (IsTransparent())
3785 return;
3786
3787 if (fBorderMode == 0)
3788 return;
3789
3790 // then paint 3d frame (depending on bordermode)
3791 // Paint a 3D frame around the pad.
3792
3793 TWbox box;
3794 box.SetFillColor(color);
3795 box.SetFillStyle(GetFillStyle());
3797
3798 box.PaintBorderOn(this, fX1, fY1, fX2, fY2,
3801}
3802
3803////////////////////////////////////////////////////////////////////////////////
3804/// Paint a frame border with Postscript - no longer used
3805
3811
3812////////////////////////////////////////////////////////////////////////////////
3813/// Paint the current date and time if the option `Date` is set on via `gStyle->SetOptDate()`
3814/// Paint the current file name if the option `File` is set on via `gStyle->SetOptFile()`
3815
3817{
3818 if (fCanvas == this) {
3819 if (gStyle->GetOptDate()) {
3820 TDatime dt;
3821 const char *dates;
3822 char iso[16];
3823 if (gStyle->GetOptDate() < 10) {
3824 //by default use format like "Wed Sep 25 17:10:35 2002"
3825 dates = dt.AsString();
3826 } else if (gStyle->GetOptDate() < 20) {
3827 //use ISO format like 2002-09-25
3828 strlcpy(iso,dt.AsSQLString(),16);
3829 dates = iso;
3830 } else {
3831 //use ISO format like 2002-09-25 17:10:35
3832 dates = dt.AsSQLString();
3833 }
3835 tdate.SetTextSize( gStyle->GetAttDate()->GetTextSize());
3836 tdate.SetTextFont( gStyle->GetAttDate()->GetTextFont());
3837 tdate.SetTextColor(gStyle->GetAttDate()->GetTextColor());
3838 tdate.SetTextAlign(gStyle->GetAttDate()->GetTextAlign());
3839 tdate.SetTextAngle(gStyle->GetAttDate()->GetTextAngle());
3840 tdate.SetNDC();
3841 tdate.Paint();
3842 }
3843 if (gStyle->GetOptFile() && gFile) {
3844 TText tfile(1. - gStyle->GetDateX(),gStyle->GetDateY(),gFile->GetName());
3848 tfile.SetTextAlign(31);
3850 tfile.SetNDC();
3851 tfile.Paint();
3852 }
3853 }
3854}
3855
3856////////////////////////////////////////////////////////////////////////////////
3857/// Paint histogram/graph frame.
3858
3860{
3861 if (!fPrimitives) fPrimitives = new TList;
3863 TFrame *frame = GetFrame();
3864 frame->SetX1(xmin);
3865 frame->SetX2(xmax);
3866 frame->SetY1(ymin);
3867 frame->SetY2(ymax);
3868 if (!glist->FindObject(fFrame)) {
3869 glist->AddFirst(frame);
3871 }
3872 frame->Paint();
3873}
3874
3875////////////////////////////////////////////////////////////////////////////////
3876/// Traverse pad hierarchy and (re)paint only modified pads.
3877
3879{
3881 if (IsModified()) {
3882 fViewer3D->PadPaint(this);
3884 }
3886 auto lnk = pList ? pList->FirstLink() : nullptr;
3887 while (lnk) {
3888 auto obj = lnk->GetObject();
3889 if (obj->InheritsFrom(TPad::Class()))
3890 ((TPad*)obj)->PaintModified();
3891 lnk = lnk->Next();
3892 }
3893 return;
3894 }
3895
3898 gVirtualPS = nullptr;
3899
3900 TVirtualPadPainter *oldpp = nullptr;
3902
3903 if (fCanvas) {
3904 // check if special PS painter should be assigned to TCanvas
3907 }
3908
3910 fPadPaint = 1;
3911 {
3912 TContext ctxt(this, kTRUE);
3913 if (IsModified() || IsTransparent()) {
3914 if ((fFillStyle < 3026) && (fFillStyle > 3000)) {
3915 auto pp = GetPainter();
3916 if (pp && pp->IsNative())
3917 pp->ClearDrawable();
3918 }
3920 }
3921
3922 PaintDate();
3923
3925 auto lnk = pList ? pList->FirstLink() : nullptr;
3926
3927 while (lnk) {
3928 TObject *obj = lnk->GetObject();
3929 if (obj->InheritsFrom(TPad::Class())) {
3930 ((TPad*)obj)->PaintModified();
3931 } else if (IsModified() || IsTransparent()) {
3932
3933 // Create a pad 3D viewer if none exists and we encounter a
3934 // 3D shape
3935 if (!fViewer3D && obj->InheritsFrom(TAtt3D::Class())) {
3936 GetViewer3D("pad");
3937 }
3938
3939 // Open a 3D scene if required
3940 if (fViewer3D && !fViewer3D->BuildingScene()) {
3943 }
3944
3945 obj->Paint(lnk->GetOption());
3946 }
3947 lnk = lnk->Next();
3948 }
3949 }
3950
3951 fPadPaint = 0;
3953
3954 // This must be done after modified flag is cleared, as some
3955 // viewers will invoke another paint by marking pad modified again
3956 if (began3DScene && fViewer3D)
3958
3959 if (replace_pp && fCanvas)
3961
3963}
3964
3965////////////////////////////////////////////////////////////////////////////////
3966/// Paint box in CurrentPad World coordinates.
3967///
3968/// - if option[0] = 's' the box is forced to be paint with style=0
3969/// - if option[0] = 'l' the box contour is drawn
3970
3972{
3973 auto pp = GetPainter();
3974 if (!pp)
3975 return;
3976
3977 pp->OnPad(this);
3978
3979 Int_t style0 = -1111, style = pp->GetFillStyle();
3981 if (option && *option == 's') {
3982 style0 = style;
3983 pp->SetFillStyle(0);
3984 style = 0;
3986 } else if (option && *option == 'l')
3988
3989 if (style >= 3100 && style < 4000) {
3990 Double_t xb[4] = {x1, x1, x2, x2};
3991 Double_t yb[4] = {y1, y2, y2, y1};
3993 } else if (!pp->IsNative()) {
3994 draw_fill = kTRUE;
3995 if (style == 0)
3997 } else if ((style > 0) && (style < 1000)) {
3999 } else if ((style >= 1000) && (style < 2000)) {
4000 draw_fill = kTRUE;
4001 } else if (style > 3000 && style < 3100) {
4002 if (style < 3026)
4003 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
4004 //special case for TAttFillCanvas on real display
4005 if (pp->GetFillColor() == 10) {
4006 // SL: reproduce old sequence of painting calls, can have some side effects on opaque pads
4007 pp->SetFillColor(1);
4008 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
4009 pp->SetFillColor(10);
4010 }
4011 } else if (style >= 4000 && style <= 4100) {
4012 // For style >=4000 we make the window transparent.
4013 // From 4000 to 4100 the window is 100% transparent to 100% opaque
4014
4015 //ignore this style option when this is the canvas itself
4016 if (this == fMother) {
4017 //It's clear, that virtual X checks a style (4000) and will render a hollow rect!
4018 if (pp->IsCocoa()) {
4019 style0 = style;
4020 pp->SetFillStyle(1000);
4021 }
4022 draw_fill = kTRUE;
4023 } else {
4024 //draw background by blitting all bottom pads
4025 int px, py;
4026 XYtoAbsPixel(fX1, fY2, px, py);
4027
4028 if (fMother) {
4030 CopyBackgroundPixmaps(fMother, this, px, py);
4031 }
4032
4033 pp->SetOpacity(style - 4000);
4034 }
4035 } else if (style > 0)
4037
4038 if (draw_fill)
4039 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
4040
4041 if (draw_border)
4042 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow);
4043
4044 if (style0 != -1111)
4045 pp->SetFillStyle(style0);
4046
4047 Modified();
4048}
4049
4050////////////////////////////////////////////////////////////////////////////////
4051/// Copy pixmaps of pads laying below pad "stop" into pad "stop". This
4052/// gives the effect of pad "stop" being transparent.
4053
4055{
4056 if (!start) return;
4057 TObject *obj;
4058 if (!fPrimitives) fPrimitives = new TList;
4059 TIter next(start->GetListOfPrimitives());
4060 while ((obj = next())) {
4061 if (obj->InheritsFrom(TPad::Class())) {
4062 if (obj == stop) break;
4063 ((TPad*)obj)->CopyBackgroundPixmap(x, y);
4064 ((TPad*)obj)->CopyBackgroundPixmaps((TPad*)obj, stop, x, y);
4065 }
4066 }
4067}
4068
4069////////////////////////////////////////////////////////////////////////////////
4070/// Copy pixmap of this pad as background of the current pad.
4071
4073{
4074 int px, py;
4075 XYtoAbsPixel(fX1, fY2, px, py);
4076 if (GetPainter())
4077 GetPainter()->CopyDrawable(GetPixmapID(), px-x, py-y);
4078}
4079
4080////////////////////////////////////////////////////////////////////////////////
4081
4083{
4084 Warning("TPad::PaintFillArea", "Float_t signature is obsolete. Use Double_t signature.");
4085}
4086
4087////////////////////////////////////////////////////////////////////////////////
4088/// Paint fill area in CurrentPad World coordinates.
4089
4091{
4092 if (nn < 3)
4093 return;
4097 } else {
4098 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4099 }
4100
4101 Int_t nc = 2*nn+1;
4102 std::vector<Double_t> x(nc, 0.);
4103 std::vector<Double_t> y(nc, 0.);
4104
4105 Int_t n = ClipPolygon(nn, xx, yy, nc, x.data(), y.data(), xmin, ymin, xmax, ymax);
4106 if (!n)
4107 return;
4108
4109 auto pp = GetPainter();
4110 if (!pp)
4111 return;
4112
4113 pp->OnPad(this);
4114
4115 // Paint the fill area with hatches
4116 Int_t fillstyle = pp->GetFillStyle();
4117 if (fillstyle >= 3100 && fillstyle < 4000)
4118 PaintFillAreaHatches(nn, x.data(), y.data(), fillstyle);
4119 else
4120 pp->DrawFillArea(n, x.data(), y.data());
4121
4122 Modified();
4123}
4124
4125////////////////////////////////////////////////////////////////////////////////
4126/// Paint fill area in CurrentPad NDC coordinates.
4127
4129{
4130 std::vector<Double_t> xw(n), yw(n);
4131 for (int i=0; i<n; i++) {
4132 xw[i] = fX1 + x[i]*(fX2 - fX1);
4133 yw[i] = fY1 + y[i]*(fY2 - fY1);
4134 }
4135 PaintFillArea(n, xw.data(), yw.data(), option);
4136}
4137
4138////////////////////////////////////////////////////////////////////////////////
4139/// This function paints hatched fill area according to the FillStyle value
4140/// The convention for the Hatch is the following:
4141///
4142/// `FillStyle = 3ijk`
4143///
4144/// - i (1-9) : specify the space between each hatch
4145/// 1 = minimum 9 = maximum
4146/// the final spacing is i*GetHatchesSpacing(). The hatches spacing
4147/// is set by SetHatchesSpacing()
4148/// - j (0-9) : specify angle between 0 and 90 degrees
4149/// * 0 = 0
4150/// * 1 = 10
4151/// * 2 = 20
4152/// * 3 = 30
4153/// * 4 = 45
4154/// * 5 = Not drawn
4155/// * 6 = 60
4156/// * 7 = 70
4157/// * 8 = 80
4158/// * 9 = 90
4159/// - k (0-9) : specify angle between 90 and 180 degrees
4160/// * 0 = 180
4161/// * 1 = 170
4162/// * 2 = 160
4163/// * 3 = 150
4164/// * 4 = 135
4165/// * 5 = Not drawn
4166/// * 6 = 120
4167/// * 7 = 110
4168/// * 8 = 100
4169/// * 9 = 90
4170
4172{
4173 static Double_t ang1[10] = { 0., 10., 20., 30., 45.,5., 60., 70., 80., 89.99};
4174 static Double_t ang2[10] = {180.,170.,160.,150.,135.,5.,120.,110.,100., 89.99};
4175
4176 Int_t fasi = FillStyle % 1000;
4177 Int_t idSPA = fasi / 100;
4178 Int_t iAng2 = (fasi - 100 * idSPA) / 10;
4179 Int_t iAng1 = fasi % 10;
4180 Double_t dy = 0.003 * idSPA * gStyle->GetHatchesSpacing();
4182 auto pp = GetPainter();
4183 if (!pp)
4184 return;
4185
4186 // Save the current line attributes and change to draw hatches
4187 auto lws = pp->GetLineWidth();
4188 auto lss = pp->GetLineStyle();
4189 auto lcs = pp->GetLineColor();
4190
4191 pp->SetLineStyle(1);
4192 pp->SetLineWidth(lw);
4193 pp->SetLineColor(pp->GetFillColor());
4194
4195 // Draw the hatches
4196 if (ang1[iAng1] != 5.)
4198 if (ang2[iAng2] != 5.)
4200
4201 pp->SetLineStyle(lss);
4202 pp->SetLineWidth(lws);
4203 pp->SetLineColor(lcs);
4204}
4205
4206////////////////////////////////////////////////////////////////////////////////
4207/// This routine draw hatches inclined with the
4208/// angle "angle" and spaced of "dy" in normalized device
4209/// coordinates in the surface defined by n,xx,yy.
4210
4213{
4214 Int_t i, i1, i2, nbi, m, inv;
4216 const Double_t angr = TMath::Pi()*(180.-angle)/180.;
4217 const Double_t epsil = 0.0001;
4218 const Int_t maxnbi = 100;
4220 Double_t ll, x, y, x1, x2, y1, y2, a, b, xi, xip, xin, yi, yip;
4221
4222 Double_t rwxmin = gPad->GetX1();
4223 Double_t rwxmax = gPad->GetX2();
4224 Double_t rwymin = gPad->GetY1();
4225 Double_t rwymax = gPad->GetY2();
4226 ratiox = 1./(rwxmax-rwxmin);
4227 ratioy = 1./(rwymax-rwymin);
4228
4231 if (TMath::Abs(cosa) <= epsil) cosa=0.;
4232 if (TMath::Abs(sina) <= epsil) sina=0.;
4233 sinb = -sina;
4234 cosb = cosa;
4235
4236 // Values needed to compute the hatches in TRUE normalized space (NDC)
4237 Int_t iw = (Int_t)gPad->GetWw();
4238 Int_t ih = (Int_t)gPad->GetWh();
4240 gPad->GetPadPar(x1p,y1p,x2p,y2p);
4241 iw = (Int_t)(iw*x2p)-(Int_t)(iw*x1p);
4242 ih = (Int_t)(ih*y2p)-(Int_t)(ih*y1p);
4245
4246 // Search ymin and ymax
4247 ymin = 1.;
4248 ymax = 0.;
4249 for (i=1; i<=nn; i++) {
4250 x = wndc*ratiox*(xx[i-1]-rwxmin);
4251 y = hndc*ratioy*(yy[i-1]-rwymin);
4252 yrot = sina*x+cosa*y;
4253 if (yrot > ymax) ymax = yrot;
4254 if (yrot < ymin) ymin = yrot;
4255 }
4256
4257 Int_t yindx = (Int_t) (ymax/dy);
4258
4259 while (dy * yindx >= ymin) {
4260 ycur = dy * yindx--;
4261 nbi = 0;
4262 for (i=2; i<=nn+1; i++) {
4263 i2 = i;
4264 i1 = i-1;
4265 if (i == nn+1) i2=1;
4266 x1 = wndc*ratiox*(xx[i1-1]-rwxmin);
4267 y1 = hndc*ratioy*(yy[i1-1]-rwymin);
4268 x2 = wndc*ratiox*(xx[i2-1]-rwxmin);
4269 y2 = hndc*ratioy*(yy[i2-1]-rwymin);
4270 xt1 = cosa*x1-sina*y1;
4271 yt1 = sina*x1+cosa*y1;
4272 xt2 = cosa*x2-sina*y2;
4273 yt2 = sina*x2+cosa*y2;
4274
4275 // Line segment parallel to oy
4276 if (xt1 == xt2) {
4277 if (yt1 < yt2) {
4278 yi = yt1;
4279 yip = yt2;
4280 } else {
4281 yi = yt2;
4282 yip = yt1;
4283 }
4284 if ((yi <= ycur) && (ycur < yip)) {
4285 nbi++;
4286 if (nbi >= maxnbi) return;
4287 xli[nbi-1] = xt1;
4288 }
4289 continue;
4290 }
4291
4292 // Line segment parallel to ox
4293 if (yt1 == yt2) {
4294 if (yt1 == ycur) {
4295 nbi++;
4296 if (nbi >= maxnbi) return;
4297 xli[nbi-1] = xt1;
4298 nbi++;
4299 if (nbi >= maxnbi) return;
4300 xli[nbi-1] = xt2;
4301 }
4302 continue;
4303 }
4304
4305 // Other line segment
4306 a = (yt1-yt2)/(xt1-xt2);
4307 b = (yt2*xt1-xt2*yt1)/(xt1-xt2);
4308 if (xt1 < xt2) {
4309 xi = xt1;
4310 xip = xt2;
4311 } else {
4312 xi = xt2;
4313 xip = xt1;
4314 }
4315 xin = (ycur-b)/a;
4316 if ((xi <= xin) && (xin < xip) &&
4317 (TMath::Min(yt1,yt2) <= ycur) &&
4318 (ycur < TMath::Max(yt1,yt2))) {
4319 nbi++;
4320 if (nbi >= maxnbi) return;
4321 xli[nbi-1] = xin;
4322 }
4323 }
4324
4325 // Sorting of the x coordinates intersections
4326 inv = 0;
4327 m = nbi-1;
4328L30:
4329 for (i=1; i<=m; i++) {
4330 if (xli[i] < xli[i-1]) {
4331 inv++;
4332 ll = xli[i-1];
4333 xli[i-1] = xli[i];
4334 xli[i] = ll;
4335 }
4336 }
4337 m--;
4338 if (inv == 0) goto L50;
4339 inv = 0;
4340 goto L30;
4341
4342 // Draw the hatches
4343L50:
4344 if ((nbi%2 != 0) || (nbi == 0))
4345 continue;
4346
4347 for (i=0; i<nbi; ++i) {
4348 // Rotate back the hatches - first calculate y coordinate
4349 yli[i] = sinb*xli[i] + cosb*ycur;
4350 xli[i] = cosb*xli[i] - sinb*ycur;
4351 // Convert hatches' positions from true NDC to WC to handle cliping
4352 xli[i] = (xli[i]/wndc)*(rwxmax-rwxmin)+rwxmin;
4353 yli[i] = (yli[i]/hndc)*(rwymax-rwymin)+rwymin;
4354 }
4355 gPad->PaintSegments(nbi/2, xli, yli);
4356 }
4357}
4358
4359////////////////////////////////////////////////////////////////////////////////
4360/// Paint line in CurrentPad World coordinates.
4361
4363{
4364 Double_t x[2] = {x1, x2}, y[2] = {y1, y2};
4365
4366 //If line is totally clipped, return
4368 if (Clip(x,y,fUxmin,fUymin,fUxmax,fUymax) == 2) return;
4369 } else {
4370 if (Clip(x,y,fX1,fY1,fX2,fY2) == 2) return;
4371 }
4372
4373 if (auto pp = GetPainter()) {
4374 pp->OnPad(this);
4375 pp->DrawLine(x[0], y[0], x[1], y[1]);
4376 }
4377
4378 Modified();
4379}
4380
4381////////////////////////////////////////////////////////////////////////////////
4382/// Paint line in normalized coordinates.
4383
4385{
4386 if (auto pp = GetPainter()) {
4387 pp->OnPad(this);
4388 pp->DrawLineNDC(u1, v1, u2, v2);
4389 }
4390
4391 Modified();
4392}
4393
4394////////////////////////////////////////////////////////////////////////////////
4395/// Paint 3-D line in the CurrentPad.
4396
4398{
4399 if (!fView) return;
4400
4401 // convert from 3-D to 2-D pad coordinate system
4402 Double_t xpad[6];
4403 Double_t temp[3];
4404 Int_t i;
4405 for (i=0;i<3;i++) temp[i] = p1[i];
4406 fView->WCtoNDC(temp, &xpad[0]);
4407 for (i=0;i<3;i++) temp[i] = p2[i];
4408 fView->WCtoNDC(temp, &xpad[3]);
4409 PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
4410}
4411
4412////////////////////////////////////////////////////////////////////////////////
4413/// Paint 3-D line in the CurrentPad.
4414
4416{
4417 if (!fView) return;
4418
4419 // convert from 3-D to 2-D pad coordinate system
4420 Double_t xpad[6];
4421 Double_t temp[3];
4422 Int_t i;
4423 for (i=0;i<3;i++) temp[i] = p1[i];
4424 fView->WCtoNDC(temp, &xpad[0]);
4425 for (i=0;i<3;i++) temp[i] = p2[i];
4426 fView->WCtoNDC(temp, &xpad[3]);
4427 PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
4428}
4429
4430////////////////////////////////////////////////////////////////////////////////
4431/// Paint 3-D marker in the CurrentPad.
4432
4434{
4435 if (!fView) return;
4436
4437 Double_t rmin[3], rmax[3];
4439
4440 // convert from 3-D to 2-D pad coordinate system
4441 Double_t xpad[3];
4442 Double_t temp[3];
4443 temp[0] = x;
4444 temp[1] = y;
4445 temp[2] = z;
4446 if (x<rmin[0] || x>rmax[0]) return;
4447 if (y<rmin[1] || y>rmax[1]) return;
4448 if (z<rmin[2] || z>rmax[2]) return;
4449 fView->WCtoNDC(temp, &xpad[0]);
4450 PaintPolyMarker(1, &xpad[0], &xpad[1]);
4451}
4452
4453////////////////////////////////////////////////////////////////////////////////
4454/// Paint polyline in CurrentPad World coordinates.
4455
4457{
4458 if (n < 2) return;
4459
4463 } else {
4464 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4465 }
4466 Int_t i, i1=-1,np=1;
4467 for (i=0; i<n-1; i++) {
4468 Double_t x1=x[i];
4469 Double_t y1=y[i];
4470 Double_t x2=x[i+1];
4471 Double_t y2=y[i+1];
4472 Int_t iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4473 if (iclip == 2) {
4474 i1 = -1;
4475 continue;
4476 }
4477 np++;
4478 if (i1 < 0)
4479 i1 = i;
4480 if (iclip == 0 && i < n-2)
4481 continue;
4482 if (auto pp = GetPainter()) {
4483 pp->OnPad(this);
4484 pp->DrawPolyLine(np, &x[i1], &y[i1]);
4485 }
4486 if (iclip) {
4487 x[i] = x1;
4488 y[i] = y1;
4489 x[i+1] = x2;
4490 y[i+1] = y2;
4491 }
4492 i1 = -1;
4493 np = 1;
4494 }
4495
4496 Modified();
4497}
4498
4499////////////////////////////////////////////////////////////////////////////////
4500/// Paint polyline in CurrentPad World coordinates.
4501///
4502/// If option[0] == 'C' no clipping
4503
4505{
4506 if (n < 2) return;
4507
4512 } else {
4513 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4514 if (option && (option[0] == 'C')) mustClip = kFALSE;
4515 }
4516
4517 Int_t i, i1=-1, np = 1, iclip = 0;
4518
4519 for (i=0; i < n-1; i++) {
4520 Double_t x1 = x[i];
4521 Double_t y1 = y[i];
4522 Double_t x2 = x[i+1];
4523 Double_t y2 = y[i+1];
4524 if (mustClip) {
4525 iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4526 if (iclip == 2) {
4527 i1 = -1;
4528 continue;
4529 }
4530 }
4531 np++;
4532 if (i1 < 0)
4533 i1 = i;
4534 if (iclip == 0 && i < n-2)
4535 continue;
4536 if (auto pp = GetPainter()) {
4537 pp->OnPad(this);
4538 pp->DrawPolyLine(np, &x[i1], &y[i1]);
4539 }
4540 if (iclip) {
4541 x[i] = x1;
4542 y[i] = y1;
4543 x[i+1] = x2;
4544 y[i+1] = y2;
4545 }
4546 i1 = -1;
4547 np = 1;
4548 }
4549
4550 Modified();
4551}
4552
4553////////////////////////////////////////////////////////////////////////////////
4554/// Paint polyline in CurrentPad NDC coordinates.
4555
4557{
4558 if (n <= 0)
4559 return;
4560
4561 if (auto pp = GetPainter()) {
4562 pp->OnPad(this);
4563 pp->DrawPolyLineNDC(n, x, y);
4564 }
4565
4566 Modified();
4567}
4568
4569////////////////////////////////////////////////////////////////////////////////
4570/// Paint 3-D polyline in the CurrentPad.
4571
4573{
4574 if (!fView) return;
4575
4576 // Loop on each individual line
4577 for (Int_t i = 1; i < n; i++)
4578 PaintLine3D(&p[3*i-3], &p[3*i]);
4579
4580 Modified();
4581}
4582
4583////////////////////////////////////////////////////////////////////////////////
4584/// Paint polymarker in CurrentPad World coordinates.
4585
4587{
4588 Int_t n = TMath::Abs(nn);
4590 if (nn > 0 || TestBit(TGraph::kClipFrame)) {
4592 } else {
4593 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4594 }
4595 Int_t i,i1=-1,np=0;
4596 for (i=0; i<n; i++) {
4597 if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
4598 np++;
4599 if (i1 < 0) i1 = i;
4600 if (i < n-1) continue;
4601 }
4602 if (np == 0)
4603 continue;
4604 if (auto pp = GetPainter()) {
4605 pp->OnPad(this);
4606 pp->DrawPolyMarker(np, &x[i1], &y[i1]);
4607 }
4608 i1 = -1;
4609 np = 0;
4610 }
4611 Modified();
4612}
4613
4614////////////////////////////////////////////////////////////////////////////////
4615/// Paint polymarker in CurrentPad World coordinates.
4616
4618{
4619 Int_t n = TMath::Abs(nn);
4621 if (nn > 0 || TestBit(TGraph::kClipFrame)) {
4623 } else {
4624 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4625 }
4626 Int_t i,i1=-1,np=0;
4627 for (i=0; i<n; i++) {
4628 if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
4629 np++;
4630 if (i1 < 0) i1 = i;
4631 if (i < n-1) continue;
4632 }
4633 if (np == 0)
4634 continue;
4635 if (auto pp = GetPainter()) {
4636 pp->OnPad(this);
4637 pp->DrawPolyMarker(np, &x[i1], &y[i1]);
4638 }
4639 i1 = -1;
4640 np = 0;
4641 }
4642 Modified();
4643}
4644
4645////////////////////////////////////////////////////////////////////////////////
4646/// Paint N individual segments
4647/// Provided arrays should have 2*n elements
4648/// IMPORTANT! Provided arrays can be modified after function call!
4649
4651{
4652 if (n < 1)
4653 return;
4654
4659 } else {
4660 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4661 if (option && *option == 'C') mustClip = kFALSE;
4662 }
4663
4664 if (!mustClip)
4665 isAny = kTRUE;
4666 else {
4667 for (Int_t i = 0; i < 2*n; i+=2) {
4668 Int_t iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4669 if (iclip == 2)
4670 x[i] = y[i] = x[i+1] = y[i+1] = 0;
4671 else
4672 isAny = kTRUE;
4673 }
4674 }
4675
4676 if (isAny)
4677 if (auto pp = GetPainter()) {
4678 pp->OnPad(this);
4679 pp->DrawSegments(n, x, y);
4680 }
4681
4682 Modified();
4683}
4684
4685
4686////////////////////////////////////////////////////////////////////////////////
4687/// Paint N individual segments in NDC coordinates
4688/// Provided arrays should have 2*n elements
4689/// IMPORTANT! Provided arrays can be modified after function call!
4690
4692{
4693 if (auto pp = GetPainter()) {
4694 pp->OnPad(this);
4695 pp->DrawSegmentsNDC(n, u, v);
4696 }
4697
4698 Modified();
4699}
4700
4701
4702////////////////////////////////////////////////////////////////////////////////
4703/// Paint text in CurrentPad World coordinates.
4704
4706{
4707 Modified();
4708
4709 if (auto pp = GetPainter()) {
4710 pp->OnPad(this);
4711 pp->DrawText(x, y, text, TVirtualPadPainter::kClear);
4712 }
4713}
4714
4715////////////////////////////////////////////////////////////////////////////////
4716/// Paint text in CurrentPad World coordinates.
4717
4718void TPad::PaintText(Double_t x, Double_t y, const wchar_t *text)
4719{
4720 Modified();
4721
4722 if (auto pp = GetPainter()) {
4723 pp->OnPad(this);
4724 pp->DrawText(x, y, text, TVirtualPadPainter::kClear);
4725 }
4726}
4727
4728////////////////////////////////////////////////////////////////////////////////
4729/// Paint text with URL in CurrentPad World coordinates.
4730
4731void TPad::PaintTextUrl(Double_t x, Double_t y, const char *text, const char *url)
4732{
4733 Modified();
4734
4735 if (auto pp = GetPainter()) {
4736 pp->OnPad(this);
4737 pp->DrawTextUrl(x, y, text, url);
4738 }
4739}
4740
4741////////////////////////////////////////////////////////////////////////////////
4742/// Paint text in CurrentPad NDC coordinates.
4743
4745{
4746 Modified();
4747
4748 if (auto pp = GetPainter()) {
4749 pp->OnPad(this);
4750 pp->DrawTextNDC(u, v, text, TVirtualPadPainter::kClear);
4751 }
4752}
4753
4754////////////////////////////////////////////////////////////////////////////////
4755/// Paint text in CurrentPad NDC coordinates.
4756
4758{
4759 Modified();
4760
4761 if (auto pp = GetPainter()) {
4762 pp->OnPad(this);
4763 pp->DrawTextNDC(u, v, text, TVirtualPadPainter::kClear);
4764 }
4765}
4766
4767////////////////////////////////////////////////////////////////////////////////
4768/// Search for an object at pixel position px,py.
4769///
4770/// Check if point is in this pad.
4771///
4772/// If yes, check if it is in one of the sub-pads
4773///
4774/// If found in the pad, compute closest distance of approach
4775/// to each primitive.
4776///
4777/// If one distance of approach is found to be within the limit Distancemaximum
4778/// the corresponding primitive is selected and the routine returns.
4779
4781{
4782 //the two following statements are necessary under NT (multithreaded)
4783 //when a TCanvas object is being created and a thread calling TPad::Pick
4784 //before the TPad constructor has completed in the other thread
4785 if (!gPad) return nullptr; //Andy Haas
4786 if (!GetListOfPrimitives()) return nullptr; //Andy Haas
4787
4788 Int_t dist;
4789 // Search if point is in pad itself
4790 Double_t x = AbsPixeltoX(px);
4791 Double_t y = AbsPixeltoY(py);
4792 if (this != gPad->GetCanvas()) {
4793 if (!((x >= fX1 && x <= fX2) && (y >= fY1 && y <= fY2))) return nullptr;
4794 }
4795
4796 // search for a primitive in this pad or its sub-pads
4797 static TObjOptLink dummyLink(nullptr,""); //place holder for when no link available
4798
4799 TContext ctxt(this, kFALSE); // since no drawing will be done, don't use cd() for efficiency reasons
4800
4801 TPad *pick = nullptr;
4802 TPad *picked = this;
4803 pickobj = nullptr;
4805 dummyLink.SetObject(this);
4806 pickobj = &dummyLink;
4807 }
4808
4809 // Loop backwards over the list of primitives. The first non-pad primitive
4810 // found is the selected one. However, we have to keep going down the
4811 // list to see if there is maybe a pad overlaying the primitive. In that
4812 // case look into the pad for a possible primitive. Once a pad has been
4813 // found we can terminate the loop.
4814 Bool_t gotPrim = kFALSE; // true if found a non pad primitive
4816
4817 //We can have 3d stuff in pad. If canvas prefers to draw
4818 //such stuff with OpenGL, the selection of 3d objects is
4819 //a gl viewer business so, in first cycle we do not
4820 //call DistancetoPrimitive for TAtt3D descendants.
4821 //In case of gl we first try to select 2d object first.
4822
4823 while (lnk) {
4824 TObject *obj = lnk->GetObject();
4825
4826 //If canvas prefers GL, all 3d objects must be drawn/selected by
4827 //gl viewer
4828 if (obj->InheritsFrom(TAtt3D::Class()) && fEmbeddedGL) {
4829 lnk = lnk->Prev();
4830 continue;
4831 }
4832
4833 fPadPointer = obj;
4834 if (obj->InheritsFrom(TPad::Class())) {
4835 pick = ((TPad*)obj)->Pick(px, py, pickobj);
4836 if (pick) {
4837 picked = pick;
4838 break;
4839 }
4840 } else if (!gROOT->GetEditorMode()) {
4841 if (!gotPrim) {
4842 if (!obj->TestBit(kCannotPick)) {
4843 dist = obj->DistancetoPrimitive(px, py);
4844 if (dist < fgMaxPickDistance) {
4845 pickobj = lnk;
4846 gotPrim = kTRUE;
4847 if (dist == 0) break;
4848 }
4849 }
4850 }
4851 }
4852
4853 lnk = lnk->Prev();
4854 }
4855
4856 //if no primitive found, check if we have a TView
4857 //if yes, return the view except if you are in the lower or upper X range
4858 //of the pad.
4859 //In case canvas prefers gl, fView existence
4860 //automatically means viewer3d existence. (?)
4861
4862 if (fView && !gotPrim) {
4863 Double_t dx = 0.05*(fUxmax-fUxmin);
4864 if ((x > fUxmin + dx) && (x < fUxmax-dx)) {
4865
4866 if (fEmbeddedGL) {
4867 //No 2d stuff was selected, but we have gl-viewer. Let it select an object in
4868 //scene (or select itself). In any case it'll internally call
4869 //gPad->SetSelected(ptr) as, for example, hist painter does.
4870 py -= Int_t((1 - GetHNDC() - GetYlowNDC()) * GetWh());
4871 px -= Int_t(GetXlowNDC() * GetWw());
4873 }
4874 else
4875 dummyLink.SetObject(fView);
4876 }
4877 }
4878
4879 if (picked->InheritsFrom(TButton::Class())) {
4881 if (!button->IsEditable()) pickobj = nullptr;
4882 }
4883
4884 if (TestBit(kCannotPick)) {
4885
4886 if (picked == this) {
4887 // cannot pick pad itself!
4888 picked = nullptr;
4889 }
4890
4891 }
4892
4893 return picked;
4894}
4895
4896////////////////////////////////////////////////////////////////////////////////
4897/// Pop pad to the top of the stack.
4898
4900{
4902 return;
4903 if (!fPrimitives)
4904 fPrimitives = new TList;
4905 if (this == fMother->GetListOfPrimitives()->Last())
4906 return;
4907
4909 while (auto obj = next())
4910 if (obj == this) {
4911 TString opt = next.GetOption();
4912 fMother->Remove(this, kFALSE); // do not issue modified
4913 fMother->Add(this, opt.Data());
4914 return;
4915 }
4916}
4917
4918////////////////////////////////////////////////////////////////////////////////
4919/// This method is equivalent to `SaveAs("filename")`. See TPad::SaveAs for details.
4920
4921void TPad::Print(const char *filename) const
4922{
4923 ((TPad*)this)->SaveAs(filename);
4924}
4925
4926////////////////////////////////////////////////////////////////////////////////
4927/// Auxiliary function. Returns kTRUE if list contains an object inherited
4928/// from TImage
4929
4931{
4932 TIter next(li);
4933
4934 while (auto obj = next()) {
4935 if (obj->InheritsFrom(TImage::Class())) {
4936 return kTRUE;
4937 } else if (obj->InheritsFrom(TPad::Class())) {
4938 if (ContainsTImage(((TPad*)obj)->GetListOfPrimitives())) {
4939 return kTRUE;
4940 }
4941 }
4942 }
4943 return kFALSE;
4944}
4945
4946////////////////////////////////////////////////////////////////////////////////
4947/// Save Canvas contents in a file in one of various formats.
4948///
4949/// \anchor TPadPrint
4950/// option can be:
4951///
4952/// - `ps`: a Postscript file is produced (default). [See special cases](\ref TPadPrintPS).
4953/// - `Portrait`: Postscript file is produced (Portrait)
4954/// - `Landscape`: Postscript file is produced (Landscape)
4955/// - `eps`: an Encapsulated Postscript file is produced
4956/// - `Preview`: an [Encapsulated Postscript file with preview](\ref TPadPrintPreview) is produced.
4957/// - `pdf`: a PDF file is produced NOTE: TMathText will be converted to TLatex; q.e.d., symbols only available in TMathText will not render properly.
4958/// - `Title:`: The character string after `Title:` becomes a table
4959/// of content entry (for PDF files).
4960/// - `EmbedFonts`: a [PDF file with embedded fonts](\ref TPadPrintEmbedFonts) is generated.
4961/// - `svg`: a SVG file is produced
4962/// - `tex`: a TeX file is produced
4963/// - `Standalone`: a [standalone TeX file](\ref TPadPrintStandalone) is produced.
4964/// - `gif`: a GIF file is produced
4965/// - `gif+NN`: an animated GIF file is produced, where NN is delay in 10ms units NOTE: See other variants for looping animation in TASImage::WriteImage
4966/// - `xpm`: a XPM file is produced
4967/// - `png`: a PNG file is produced
4968/// - `jpg`: a JPEG file is produced. NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
4969/// - `tiff`: a TIFF file is produced
4970/// - `cxx`: a C++ macro file is produced
4971/// - `xml`: a XML file
4972/// - `json`: a JSON file
4973/// - `root`: a ROOT binary file
4974///
4975/// `filename` = 0 - filename is defined by `GetName` and its
4976/// extension is defined with the option
4977///
4978/// When Postscript output is selected (`ps`, `eps`), the canvas is saved
4979/// to `filename.ps` or `filename.eps`. The aspect ratio of the canvas is preserved
4980/// on the Postscript file. When the "ps" option is selected, the Postscript
4981/// page will be landscape format if the canvas is in landscape format, otherwise
4982/// portrait format is selected.
4983///
4984/// The physical size of the Postscript page is the one selected in the
4985/// current style. This size can be modified via TStyle::SetPaperSize.
4986///
4987/// Examples:
4988/// ~~~ {.cpp}
4989/// gStyle->SetPaperSize(TStyle::kA4); //default
4990/// gStyle->SetPaperSize(TStyle::kUSLetter);
4991/// ~~~
4992/// where TStyle::kA4 and TStyle::kUSLetter are defined in the enum
4993/// EPaperSize in TStyle.h
4994///
4995/// An alternative is to call:
4996/// ~~~ {.cpp}
4997/// gStyle->SetPaperSize(20,26); same as kA4
4998/// or gStyle->SetPaperSize(20,24); same as kUSLetter
4999/// ~~~
5000/// The above numbers take into account some margins and are in centimeters.
5001///
5002/// \anchor TPadPrintPreview
5003/// ### The "Preview" option
5004///
5005/// The "Preview" option allows to generate a preview (in the TIFF format) within
5006/// the Encapsulated Postscript file. This preview can be used by programs like
5007/// MSWord to visualize the picture on screen. The "Preview" option relies on the
5008/// ["epstool" command](http://www.cs.wisc.edu/~ghost/gsview/epstool.htm).
5009///
5010/// Example:
5011/// ~~~ {.cpp}
5012/// canvas->Print("example.eps","Preview");
5013/// ~~~
5014///
5015/// \anchor TPadPrintEmbedFonts
5016/// ### The "EmbedFonts" option
5017///
5018/// The "EmbedFonts" option allows to embed the fonts used in a PDF file inside
5019/// that file. This option relies on the ["gs" command](https://ghostscript.com).
5020///
5021/// Example:
5022/// ~~~ {.cpp}
5023/// canvas->Print("example.pdf","EmbedFonts");
5024/// ~~~
5025///
5026/// \anchor TPadPrintStandalone
5027/// ### The "Standalone" option
5028/// The "Standalone" option allows to generate a TeX file ready to be processed by
5029/// tools like `pdflatex`.
5030///
5031/// Example:
5032/// ~~~ {.cpp}
5033/// canvas->Print("example.tex","Standalone");
5034/// ~~~
5035///
5036/// \anchor TPadPrintPS
5037/// ### Writing several canvases to the same Postscript or PDF file:
5038///
5039/// - if the Postscript or PDF file name finishes with "(", the file is not closed
5040/// - if the Postscript or PDF file name finishes with ")" and the file has been opened
5041/// with "(", the file is closed.
5042///
5043/// Example:
5044/// ~~~ {.cpp}
5045/// {
5046/// TCanvas c1("c1");
5047/// h1.Draw();
5048/// c1.Print("c1.ps("); //write canvas and keep the ps file open
5049/// h2.Draw();
5050/// c1.Print("c1.ps"); canvas is added to "c1.ps"
5051/// h3.Draw();
5052/// c1.Print("c1.ps)"); canvas is added to "c1.ps" and ps file is closed
5053/// }
5054/// ~~~
5055/// In the previous example replacing "ps" by "pdf" will create a multi-pages PDF file.
5056///
5057/// Note that the following sequence writes the canvas to "c1.ps" and closes the ps file.:
5058/// ~~~ {.cpp}
5059/// TCanvas c1("c1");
5060/// h1.Draw();
5061/// c1.Print("c1.ps");
5062/// ~~~
5063/// The `TCanvas::Print("file.ps(")` mechanism is very useful, but it can be
5064/// a little inconvenient to have the action of opening/closing a file
5065/// being atomic with printing a page. Particularly if pages are being
5066/// generated in some loop one needs to detect the special cases of first
5067/// and last page and then munge the argument to Print() accordingly.
5068///
5069/// The "[" and "]" can be used instead of "(" and ")" to open / close without
5070/// actual printing.
5071///
5072/// Example:
5073/// ~~~ {.cpp}
5074/// c1.Print("file.ps["); // No actual print, just open file.ps
5075/// for (int i=0; i<10; ++i) {
5076/// // fill canvas for context i
5077/// // ...
5078///
5079/// c1.Print("file.ps"); // actually print canvas to file
5080/// }// end loop
5081/// c1.Print("file.ps]"); // No actual print, just close.
5082/// ~~~
5083/// As before, the same macro is valid for PDF files.
5084///
5085/// It is possible to print a canvas into an animated GIF file by specifying the
5086/// file name as "myfile.gif+" or "myfile.gif+NN", where NN*10ms is delay
5087/// between the subimages' display. If NN is omitted the delay between
5088/// subimages is zero. Each picture is added in the animation thanks to a loop
5089/// similar to the following one:
5090/// ~~~ {.cpp}
5091/// for (int i=0; i<10; ++i) {
5092/// // fill canvas for context i
5093/// // ...
5094///
5095/// c1.Print("file.gif+5"); // print canvas to GIF file with 50ms delays
5096/// }// end loop
5097/// ~~~
5098/// The delay between each frame must be specified in each Print() statement.
5099/// If the file "myfile.gif" already exists, the new frame are appended at
5100/// the end of the file. To avoid this, delete it first with `gSystem->Unlink(myfile.gif);`
5101/// If you want the gif file to repeat or loop forever, check TASImage::WriteImage documentation
5102
5104{
5105 if (!GetCanvas())
5106 return;
5107
5109
5110 // "[" and "]" are special characters for ExpandPathName. When they are at the end
5111 // of the file name (see help) they must be removed before doing ExpandPathName.
5112 if (fs1.EndsWith("[")) {
5113 fs1.Replace((fs1.Length()-1),1," ");
5115 fs1.Replace((fs1.Length()-1),1,"[");
5116 } else if (fs1.EndsWith("]")) {
5117 fs1.Replace((fs1.Length()-1),1," ");
5119 fs1.Replace((fs1.Length()-1),1,"]");
5120 } else {
5122 }
5123
5124 // Set the default option as "Postscript" (Should be a data member of TPad)
5125 const char *opt_default = "ps";
5126
5127 TString opt = !option ? opt_default : option;
5129
5130 Bool_t title = kFALSE;
5131 if (strstr(opt,"Title:")) title = kTRUE;
5132
5133 if (!fs1.Length()) {
5134 psname = GetName();
5135 psname += opt;
5136 } else {
5137 psname = fs1;
5138 }
5139
5140 // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
5141 if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
5142 psname = GetName();
5143 psname.Append(fs1);
5144 psname.Prepend("/");
5145 psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
5146 }
5147
5148 // Save pad/canvas in alternative formats
5150 if (!title && strstr(opt, "gif+")) {
5152 image = kTRUE;
5153 } else if (!title && strstr(opt, "gif")) {
5155 image = kTRUE;
5156 } else if (!title && strstr(opt, "png")) {
5158 image = kTRUE;
5159 } else if (!title && strstr(opt, "jpg")) {
5161 image = kTRUE;
5162 } else if (!title && strstr(opt, "tiff")) {
5164 image = kTRUE;
5165 } else if (!title && strstr(opt, "xpm")) {
5167 image = kTRUE;
5168 } else if (!title && strstr(opt, "bmp")) {
5170 image = kTRUE;
5171 }
5172
5173 if (GetCanvas()->IsWeb() && GetPainter() &&
5174 (strstr(opt,"svg") || strstr(opt,"pdf") || (gtype == TImage::kJpeg) || (gtype == TImage::kPng))) {
5175 GetPainter()->SaveImage(this, psname.Data(), gtype);
5176 return;
5177 }
5178
5179 if (!GetCanvas()->IsBatch() && GetPainter())
5181
5182
5183 if (!gROOT->IsBatch() && image) {
5185 Int_t wid = (this == GetCanvas()) ? GetCanvas()->GetCanvasID() : GetPixmapID();
5186 Color_t hc = gPad->GetCanvas()->GetHighLightColor();
5187 gPad->GetCanvas()->SetHighLightColor(-1);
5188 gPad->Modified();
5189 gPad->Update();
5190 if (GetPainter()) {
5192 GetPainter()->SaveImage(this, psname.Data(), gtype);
5193 }
5194 if (!gSystem->AccessPathName(psname.Data())) {
5195 Info("Print", "GIF file %s has been created", psname.Data());
5196 }
5197 gPad->GetCanvas()->SetHighLightColor(hc);
5198 return;
5199 }
5200 if (gtype != TImage::kUnknown) {
5201 Color_t hc = gPad->GetCanvas()->GetHighLightColor();
5202 gPad->GetCanvas()->SetHighLightColor(-1);
5203 gPad->Modified();
5204 gPad->Update();
5205 gPad->GetCanvasImp()->UpdateDisplay(1, kTRUE);
5206 if (GetPainter())
5207 GetPainter()->SaveImage(this, psname, gtype);
5208 if (!gSystem->AccessPathName(psname)) {
5209 Info("Print", "file %s has been created", psname.Data());
5210 }
5211 gPad->GetCanvas()->SetHighLightColor(hc);
5212 } else {
5213 Warning("Print", "Unsupported image format %s", psname.Data());
5214 }
5215 return;
5216 }
5217
5218 //==============Save pad/canvas as a C++ script==============================
5219 if (!title && strstr(opt,"cxx")) {
5220 GetCanvas()->SaveSource(psname, "");
5221 return;
5222 }
5223
5224 //==============Save pad/canvas as a root file===============================
5225 if (!title && strstr(opt,"root")) {
5226 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5227 return;
5228 }
5229
5230 //==============Save pad/canvas as a XML file================================
5231 if (!title && strstr(opt,"xml")) {
5232 // Plugin XML driver
5233 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5234 return;
5235 }
5236
5237 //==============Save pad/canvas as a JSON file================================
5238 if (!title && strstr(opt,"json")) {
5239 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5240 return;
5241 }
5242
5243 //==============Save pad/canvas as a SVG file================================
5244 if (!title && strstr(opt,"svg")) {
5245 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5246
5248 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5249 noScreen = kTRUE;
5251 }
5252
5253 TContext ctxt(this, kTRUE);
5254
5255 if (!gVirtualPS) {
5256 // Plugin Postscript/SVG driver
5257 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "svg")) {
5258 if (h->LoadPlugin() == -1)
5259 return;
5260 h->ExecPlugin(0);
5261 }
5262 }
5263
5264 // Create a new SVG file
5265 if (gVirtualPS) {
5270 }
5271
5272 Paint();
5273 if (noScreen)
5275
5277 Info("Print", "SVG file %s has been created", psname.Data());
5278
5279 delete gVirtualPS;
5280 gVirtualPS = nullptr;
5281
5282 return;
5283 }
5284
5285 //==============Save pad/canvas as a TeX file================================
5286 if (!title && (strstr(opt,"tex") || strstr(opt,"Standalone"))) {
5287 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5288
5290 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5291 noScreen = kTRUE;
5293 }
5294
5295 TContext ctxt(this, kTRUE);
5296
5297 if (!gVirtualPS) {
5298 // Plugin Postscript/SVG driver
5299 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "tex")) {
5300 if (h->LoadPlugin() == -1)
5301 return;
5302 h->ExecPlugin(0);
5303 }
5304 }
5305
5307 if (strstr(opt,"Standalone")) standalone = kTRUE;
5308
5309 // Create a new TeX file
5310 if (gVirtualPS) {
5312 if (standalone) gVirtualPS->SetTitle("Standalone");
5316 }
5317 Paint();
5319
5320 if (!gSystem->AccessPathName(psname)) {
5321 if (standalone) {
5322 Info("Print", "Standalone TeX file %s has been created", psname.Data());
5323 } else{
5324 Info("Print", "TeX file %s has been created", psname.Data());
5325 }
5326 }
5327
5328 delete gVirtualPS;
5329 gVirtualPS = nullptr;
5330
5331 return;
5332 }
5333
5334 //==============Save pad/canvas as a Postscript file=========================
5335
5336 // in case we read directly from a Root file and the canvas
5337 // is not on the screen, set batch mode
5338
5341 if (!image) {
5342 // The parenthesis mechanism is only valid for PS and PDF files.
5343 copen = psname.EndsWith("("); if (copen) psname[psname.Length()-1] = 0;
5344 cclose = psname.EndsWith(")"); if (cclose) psname[psname.Length()-1] = 0;
5345 copenb = psname.EndsWith("["); if (copenb) psname[psname.Length()-1] = 0;
5346 ccloseb = psname.EndsWith("]"); if (ccloseb) psname[psname.Length()-1] = 0;
5347 }
5348 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5350 if (copen || copenb) mustClose = kFALSE;
5351 if (cclose || ccloseb) mustClose = kTRUE;
5352
5354 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5355 noScreen = kTRUE;
5357 }
5358 Int_t pstype = 111;
5361 Double_t ratio = ycanvas/xcanvas;
5362 if (ratio < 1) pstype = 112;
5363 if (strstr(opt,"Portrait")) pstype = 111;
5364 if (strstr(opt,"Landscape")) pstype = 112;
5365 if (strstr(opt,"eps")) pstype = 113;
5366 if (strstr(opt,"Preview")) pstype = 113;
5367
5368 TContext ctxt(this, kTRUE);
5370
5371 if (!gVirtualPS || mustOpen) {
5372
5373 const char *pluginName = "ps"; // Plugin Postscript driver
5374 if (strstr(opt,"pdf") || title || strstr(opt,"EmbedFonts"))
5375 pluginName = "pdf";
5376 else if (image)
5377 pluginName = "image"; // Plugin TImageDump driver
5378
5379 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", pluginName)) {
5380 if (h->LoadPlugin() == -1)
5381 return;
5382 h->ExecPlugin(0);
5383 }
5384
5385 // Create a new Postscript, PDF or image file
5386 if (gVirtualPS)
5388 const Ssiz_t titlePos = opt.Index("Title:");
5389 if (titlePos != kNPOS) {
5390 if (gVirtualPS)
5391 gVirtualPS->SetTitle(opt.Data()+titlePos+6);
5392 opt.Replace(titlePos,opt.Length(),"pdf");
5393 }
5394 if (gVirtualPS)
5396 if (gVirtualPS)
5398 if (!copenb) {
5399 if (!strstr(opt,"pdf") || image) {
5401 }
5402 Paint();
5403 }
5405
5406 if (mustClose) {
5407 gROOT->GetListOfSpecials()->Remove(gVirtualPS);
5408 delete gVirtualPS;
5409 gVirtualPS = psave;
5410 } else {
5411 gROOT->GetListOfSpecials()->Add(gVirtualPS);
5412 gVirtualPS = nullptr;
5413 }
5414
5415 if (!gSystem->AccessPathName(psname)) {
5416 if (!copen) Info("Print", "%s file %s has been created", opt.Data(), psname.Data());
5417 else Info("Print", "%s file %s has been created using the current canvas", opt.Data(), psname.Data());
5418 }
5419 } else {
5420 // Append to existing Postscript, PDF or GIF file
5421 if (!ccloseb) {
5423 Paint();
5424 }
5425 const Ssiz_t titlePos = opt.Index("Title:");
5426 if (titlePos != kNPOS) {
5427 gVirtualPS->SetTitle(opt.Data()+titlePos+6);
5428 opt.Replace(titlePos,opt.Length(),"pdf");
5429 } else if (!ccloseb) {
5430 gVirtualPS->SetTitle("PDF");
5431 }
5432 if (mustClose) {
5433 if (cclose) Info("Print", "Current canvas added to %s file %s and file closed", opt.Data(), psname.Data());
5434 else Info("Print", "%s file %s has been closed", opt.Data(), psname.Data());
5435 gROOT->GetListOfSpecials()->Remove(gVirtualPS);
5436 delete gVirtualPS;
5437 gVirtualPS = nullptr;
5438 } else {
5439 Info("Print", "Current canvas added to %s file %s", opt.Data(), psname.Data());
5440 gVirtualPS = nullptr;
5441 }
5442 }
5443
5444 if (strstr(opt,"Preview"))
5445 gSystem->Exec(TString::Format("epstool --quiet -t6p %s %s", psname.Data(), psname.Data()).Data());
5446 if (strstr(opt,"EmbedFonts")) {
5447 gSystem->Exec(TString::Format("gs -quiet -dSAFER -dNOPLATFONTS -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/printer -dCompatibilityLevel=1.4 -dMaxSubsetPct=100 -dSubsetFonts=true -dEmbedAllFonts=true -sOutputFile=pdf_temp.pdf -f %s",
5448 psname.Data()).Data());
5449 gSystem->Rename("pdf_temp.pdf", psname.Data());
5450 }
5451
5452}
5453
5454////////////////////////////////////////////////////////////////////////////////
5455/// Set world coordinate system for the pad.
5456/// Emits signal "RangeChanged()", in the slot get the range
5457/// via GetRange().
5458
5460{
5461 if ((x1 >= x2) || (y1 >= y2)) {
5462 Error("Range", "illegal world coordinates range: x1=%f, y1=%f, x2=%f, y2=%f",x1,y1,x2,y2);
5463 return;
5464 }
5465
5466 fUxmin = x1;
5467 fUxmax = x2;
5468 fUymin = y1;
5469 fUymax = y2;
5470
5471 if (fX1 == x1 && fY1 == y1 && fX2 == x2 && fY2 == y2) return;
5472
5473 fX1 = x1;
5474 fY1 = y1;
5475 fX2 = x2;
5476 fY2 = y2;
5477
5478 // compute pad conversion coefficients
5479 ResizePad();
5480
5481 if (gPad == this && GetPainter())
5483
5484 // emit signal
5485 RangeChanged();
5486}
5487
5488////////////////////////////////////////////////////////////////////////////////
5489/// Set axis coordinate system for the pad.
5490/// The axis coordinate system is a subset of the world coordinate system
5491/// xmin,ymin is the origin of the current coordinate system,
5492/// xmax is the end of the X axis, ymax is the end of the Y axis.
5493/// By default a margin of 10 per cent is left on all sides of the pad
5494/// Emits signal "RangeAxisChanged()", in the slot get the axis range
5495/// via GetRangeAxis().
5496
5498{
5499 if ((xmin >= xmax) || (ymin >= ymax)) {
5500 Error("RangeAxis", "illegal axis coordinates range: xmin=%f, ymin=%f, xmax=%f, ymax=%f",
5501 xmin, ymin, xmax, ymax);
5502 return;
5503 }
5504
5505 fUxmin = xmin;
5506 fUymin = ymin;
5507 fUxmax = xmax;
5508 fUymax = ymax;
5509
5510 // emit signal
5512}
5513
5514////////////////////////////////////////////////////////////////////////////////
5515/// Recursively remove object from a pad and its sub-pads.
5516
5518{
5519 if (fCanvas) {
5520 if (obj == fCanvas->GetSelected()) fCanvas->SetSelected(nullptr);
5521 if (obj == fCanvas->GetClickSelected()) fCanvas->SetClickSelected(nullptr);
5522 }
5523 if (obj == fView) fView = nullptr;
5524 if (!fPrimitives) return;
5527 if (nold != fPrimitives->GetSize()) fModified = kTRUE;
5528}
5529
5530////////////////////////////////////////////////////////////////////////////////
5531/// Remove object from list of primitives
5532/// When \par modified set to kTRUE (default) pad will be marked as modified - if object really removed
5533/// Returns result of GetListOfPrimitives()->Remove(obj) or nullptr if list of primitives not exists
5534
5536{
5537 TObject *res = nullptr;
5538 if (fPrimitives)
5539 res = fPrimitives->Remove(obj);
5540 if (res && modified)
5541 Modified();
5542 return res;
5543}
5544
5545////////////////////////////////////////////////////////////////////////////////
5546/// Redraw the frame axis.
5547///
5548/// Redrawing axis may be necessary in case of superimposed histograms
5549/// when one or more histograms have a fill color.
5550///
5551/// Instead of calling this function, it may be more convenient
5552/// to call directly `h1->Draw("sameaxis")` where h1 is the pointer
5553/// to the first histogram drawn in the pad.
5554///
5555/// By default, if the pad has the options gridx or/and gridy activated,
5556/// the grid is not drawn by this function.
5557///
5558/// If option="g" is specified, this will force the drawing of the grid
5559/// on top of the picture
5560///
5561/// To redraw the axis tick marks do:
5562/// ~~~ {.cpp}
5563/// gPad->RedrawAxis();
5564/// ~~~
5565/// To redraw the axis grid do:
5566/// ~~~ {.cpp}
5567/// gPad->RedrawAxis("G");
5568/// ~~~
5569/// To redraw the axis tick marks and the axis grid do:
5570/// ~~~ {.cpp}
5571/// gPad->RedrawAxis();
5572/// gPad->RedrawAxis("G");
5573/// ~~~
5574///
5575/// If option="f" is specified, this will force the drawing of the frame
5576/// around the plot.
5577
5579{
5580 TString opt = option;
5581 opt.ToLower();
5582
5583 TContext ctxt(this, kTRUE);
5584
5585 TH1 *hobj = nullptr;
5586
5587 // Get the first histogram drawing the axis in the list of primitives
5588 if (!fPrimitives) fPrimitives = new TList;
5589 TIter next(fPrimitives);
5590 TObject *obj;
5591 while ((obj = next())) {
5592 if (obj->InheritsFrom(TH1::Class())) {
5593 hobj = (TH1*)obj;
5594 break;
5595 }
5596 if (obj->InheritsFrom(TMultiGraph::Class())) {
5597 TMultiGraph *mg = (TMultiGraph*)obj;
5598 if (mg) hobj = mg->GetHistogram();
5599 break;
5600 }
5601 if (obj->InheritsFrom(TGraph::Class())) {
5602 TGraph *g = (TGraph*)obj;
5603 if (g) hobj = g->GetHistogram();
5604 break;
5605 }
5606 if (obj->InheritsFrom(THStack::Class())) {
5607 THStack *hs = (THStack*)obj;
5608 if (hs) hobj = hs->GetHistogram();
5609 break;
5610 }
5611 }
5612
5613 if (hobj) {
5614 if (opt.Contains("g")) hobj->DrawCopy("sameaxig");
5615 else hobj->DrawCopy("sameaxis");
5616 }
5617
5618 if (opt.Contains("f")) {
5619 auto b = new TBox(gPad->GetUxmin(), gPad->GetUymin(),
5620 gPad->GetUxmax(), gPad->GetUymax());
5621 b->SetFillStyle(0);
5622 b->SetLineStyle(gPad->GetFrameLineStyle());
5623 b->SetLineWidth(gPad->GetFrameLineWidth());
5624 b->SetLineColor(gPad->GetFrameLineColor());
5625 b->Draw();
5626 }
5627}
5628
5629////////////////////////////////////////////////////////////////////////////////
5630/// Compute pad conversion coefficients.
5631///
5632/// ### Conversion from x to px
5633///
5634/// \f[\frac{x-xmin}{xrange} = \frac{px-pxlow}{pxrange}\f]
5635/// with:
5636/// \f[ xrange = xmax-xmin \f]
5637/// \f[ pxrange = pxmax-pxmin \f]
5638///
5639/// \f[
5640/// \Rightarrow px = \frac{pxrange(x-xmin)}{xrange} + pxlow = fXtoPixelk + fXtoPixel \times x
5641/// \f]
5642///
5643/// \f[
5644/// \Rightarrow fXtoPixelk = pxlow - pxrange \frac{xmin}{xrange}
5645/// \f]
5646/// \f[
5647/// fXtoPixel = \frac{pxrange}{xrange}
5648/// \f]
5649/// where:
5650/// \f[
5651/// pxlow = fAbsXlowNDC \times fCw
5652/// \f]
5653/// \f[
5654/// pxrange = fAbsWNDC \times fCw
5655/// \f]
5656///
5657/// ### Conversion from y to py
5658///
5659/// \f[\frac{y-ymin}{yrange} = \frac{py-pylow}{pyrange}\f]
5660/// with:
5661/// \f[ yrange = ymax-ymin \f]
5662/// \f[ pyrange = pymax-pymin \f]
5663///
5664/// \f[
5665/// \Rightarrow py = \frac{pyrange(y-xmin)}{yrange} + pylow = fYtoPixelk + fYtoPixel \times y
5666/// \f]
5667///
5668/// \f[
5669/// \Rightarrow fYtoPixelk = pylow - pyrange \frac{ymin}{yrange}
5670/// \f]
5671/// \f[
5672/// fYtoPixel = \frac{pyrange}{yrange}
5673/// \f]
5674/// where:
5675/// \f[
5676/// pylow = fAbsYlowNDC \times fCh
5677/// \f]
5678/// \f[
5679/// pyrange = fAbsHNDC \times fCh
5680/// \f]
5681///
5682/// ### Conversion from px to x
5683///
5684/// \f[
5685/// \Rightarrow x = \frac{xrange(px-pxlow)}{pxrange}+ xmin = fPixeltoXk + fPixeltoX \times px
5686/// \f]
5687///
5688/// \f[
5689/// \Rightarrow fPixeltoXk = xmin - pxlow \times\frac{xrange}{pxrange}
5690/// \f]
5691/// \f[
5692/// fPixeltoX = \frac{xrange}{pxrange}
5693/// \f]
5694///
5695/// ### Conversion from py to y
5696///
5697/// \f[
5698/// \Rightarrow y = \frac{yrange(py-pylow)}{pyrange}+ ymin = fPixeltoYk + fPixeltoY \times py
5699/// \f]
5700///
5701/// \f[
5702/// \Rightarrow fPixeltoYk = ymin - pylow \times\frac{yrange}{pyrange}
5703/// \f]
5704/// \f[
5705/// fPixeltoY = \frac{yrange}{pyrange}
5706/// \f]
5707///
5708/// ### Computation of the coefficients in case of LOG scales
5709///
5710/// #### Conversion from pixel coordinates to world coordinates
5711///
5712/// \f[
5713/// u = \frac{Log(x) - Log(xmin)}{Log(xmax) - Log(xmin)} = \frac{Log(x/xmin)}{Log(xmax/xmin)} = \frac{px - pxlow}{pxrange}
5714/// \f]
5715///
5716/// \f[ \Rightarrow Log(\frac{x}{xmin}) = u \times Log(\frac{xmax}{xmin}) \f]
5717/// \f[ x = xmin \times e^{(u \times Log(\frac{xmax}{xmin})} \f]
5718/// Let:
5719/// \f[ alfa = \frac{Log(\frac{xmax}{xmin})}{fAbsWNDC} \f]
5720///
5721/// \f[ x = xmin \times e^{(-alfa \times pxlow)} + e^{(alfa \times px)} \f]
5722/// \f[ x = fPixeltoXk \times e^{(fPixeltoX \times px)} \f]
5723/// \f[ ==> fPixeltoXk = xmin \times e^{(-alfa*pxlow)} \f]
5724/// \f[ fPixeltoX = alfa \f]
5725///
5726/// \f[
5727/// v = \frac{Log(y) - Log(ymin)}{Log(ymax) - Log(ymin)} = \frac{Log(y/ymin)}{Log(ymax/ymin)} = \frac{py - pylow}{pyrange}
5728/// \f]
5729/// Let:
5730/// \f[ beta = Log(\frac{ymax}{ymin}) \f]
5731/// \f[ Log(\frac{y}{ymin}) = beta \times pylow - beta \times py \f]
5732/// \f[ \frac{y}{ymin} = e^{(beta \times pylow - beta \times py)} \f]
5733/// \f[ y = ymin \times e^{(beta \times pylow)} \times e^{(-beta \times py)}\f]
5734/// \f[ \Rightarrow y = fPixeltoYk \times e^{(fPixeltoY \times py)} \f]
5735/// \f[ fPixeltoYk = ymin \times e^{(beta \times pylow)} \f]
5736/// \f[ fPixeltoY = -beta \f]
5737///
5738/// #### Conversion from World coordinates to pixel coordinates
5739///
5740/// \f[ px = pxlow + u*pxrange \f]
5741/// \f[ = pxlow + Log(x/xmin)/alfa \f]
5742/// \f[ = pxlow -Log(xmin)/alfa + Log(x)/alfa \f]
5743/// \f[ = fXtoPixelk + fXtoPixel*Log(x) \f]
5744/// \f[ \Rightarrow fXtoPixelk = pxlow -Log(xmin)/alfa \f]
5745/// \f[ \Rightarrow fXtoPixel = 1/alfa \f]
5746///
5747/// \f[ py = pylow - Log(y/ymin)/beta \f]
5748/// \f[ = fYtoPixelk + fYtoPixel*Log(y) \f]
5749/// \f[ \Rightarrow fYtoPixelk = pylow - Log(ymin)/beta \f]
5750/// \f[ fYtoPixel = 1/beta \f]
5751
5753{
5754
5755 if (!gPad) {
5756 Error("ResizePad", "Cannot resize pad. No current pad available.");
5757 return;
5758 }
5759 if (gPad->GetWw()==0.0||gPad->GetWh()==0.0) {
5760 Warning("ResizePad", "gPad has at least one zero dimension.");
5761 return;
5762 }
5763 if (fX1==fX2||fY1==fY2) {
5764 Warning("ResizePad", "The pad has at least one zero dimension.");
5765 return;
5766 }
5767 // Recompute subpad positions in case pad has been moved/resized
5768 TPad *parent = fMother;
5769 if (this == gPad->GetCanvas()) {
5772 fAbsWNDC = fWNDC;
5773 fAbsHNDC = fHNDC;
5774 }
5775 else {
5776 if (parent->GetAbsHNDC()==0.0||parent->GetAbsWNDC()==0.0||fHNDC==0.0||fWNDC==0.0) {
5777 Warning("ResizePad", "The parent pad has at least one zero dimension.");
5778 return;
5779 }
5780 fAbsXlowNDC = fXlowNDC*parent->GetAbsWNDC() + parent->GetAbsXlowNDC();
5781 fAbsYlowNDC = fYlowNDC*parent->GetAbsHNDC() + parent->GetAbsYlowNDC();
5782 fAbsWNDC = fWNDC*parent->GetAbsWNDC();
5783 fAbsHNDC = fHNDC*parent->GetAbsHNDC();
5784 }
5785
5786 Double_t ww = (Double_t)gPad->GetWw();
5787 Double_t wh = (Double_t)gPad->GetWh();
5792
5793 // Linear X axis
5794 Double_t rounding = 0.; // was used before to adjust somehow wrong int trunctation by coordiantes transformation
5795 Double_t xrange = fX2 - fX1;
5796 fXtoAbsPixelk = rounding + pxlow - pxrange*fX1/xrange; //origin at left
5800 fPixeltoXk = fX1;
5802 // Linear Y axis
5803 Double_t yrange = fY2 - fY1;
5804 fYtoAbsPixelk = rounding + pylow - pyrange*fY1/yrange; //origin at top
5808 fPixeltoYk = fY1;
5810
5811 // Coefficients to convert from pad NDC coordinates to pixel coordinates
5812
5819
5820 // Coefficients to convert from canvas pixels to pad world coordinates
5821
5822 // Resize all sub-pads
5823 if (!fPrimitives)
5824 fPrimitives = new TList;
5825 TIter next(GetListOfPrimitives());
5826 while (auto obj = next()) {
5827 if (obj->InheritsFrom(TPad::Class()))
5828 ((TPad *)obj)->ResizePad(option);
5829 }
5830
5831 // Reset all current sizes
5832 if (gPad->IsBatch())
5833 fPixmapID = 0;
5834 else if (auto pp = GetPainter()) {
5835 if (pp->IsNative()) {
5836 pp->SetLineWidth(-1);
5837 pp->SetTextSize(-1);
5838 // create or re-create off-screen pixmap
5839 if (fPixmapID) {
5840 int w = TMath::Abs(XtoPixel(fX2) - XtoPixel(fX1));
5841 int h = TMath::Abs(YtoPixel(fY2) - YtoPixel(fY1));
5842 //protection in case of wrong pad parameters.
5843 //without this protection, the OpenPixmap or ResizePixmap crashes with
5844 //the message "Error in <RootX11ErrorHandler>: BadValue (integer parameter out of range for operation)"
5845 //resulting in a frozen xterm
5848 Warning("ResizePad", "Inf/NaN propagated to the pad. Check drawn objects.");
5849 if (w <= 0 || w > 10000) {
5850 Warning("ResizePad", "%s width changed from %d to %d\n",GetName(),w,10);
5851 w = 10;
5852 }
5853 if (h <= 0 || h > 10000) {
5854 Warning("ResizePad", "%s height changed from %d to %d\n",GetName(),h,10);
5855 h = 10;
5856 }
5857 if (fPixmapID == -1) // this case is handled via the ctor
5858 fPixmapID = pp->CreateDrawable(w, h);
5859 else if (pp->ResizeDrawable(fPixmapID, w, h)) {
5860 Resized();
5861 Modified(kTRUE);
5862 }
5863 }
5864 }
5865 }
5866 if (fView) {
5867 if (gPad == this) {
5868 fView->ResizePad();
5869 } else {
5870 TContext ctxt(this, kTRUE);
5871 fView->ResizePad();
5872 }
5873 }
5874}
5875
5876////////////////////////////////////////////////////////////////////////////////
5877/// Save the pad content in a file.
5878///
5879/// The file's format used to save the pad is determined by the `filename` extension:
5880///
5881/// - if `filename` is empty, the file produced is `padname.ps`
5882/// - if `filename` starts with a dot, the padname is added in front
5883/// - if `filename` ends with `.ps`, a Postscript file is produced
5884/// - if `filename` ends with `.eps`, an Encapsulated Postscript file is produced
5885/// - if `filename` ends with `.pdf`, a PDF file is produced NOTE: TMathText will be converted to TLatex; q.e.d., symbols only available in TMathText will not render properly.
5886/// - if `filename` ends with `.svg`, a SVG file is produced
5887/// - if `filename` ends with `.tex`, a TeX file is produced
5888/// - if `filename` ends with `.gif`, a GIF file is produced
5889/// - if `filename` ends with `.gif+NN`, an animated GIF file is produced See comments in TASImage::WriteImage for meaning of NN and other .gif sufix variants
5890/// - if `filename` ends with `.xpm`, a XPM file is produced
5891/// - if `filename` ends with `.png`, a PNG file is produced
5892/// - if `filename` ends with `.bmp`, a BMP file is produced
5893/// - if `filename` ends with `.jpg` or `.jpeg` a JPEG file is produced NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
5894/// - if `filename` ends with `.tiff`, a TIFF file is produced
5895/// - if `filename` ends with `.C`, `.cxx`,`.cpp` or `.cc`, a C++ macro file is produced
5896/// - if `filename` ends with `.root`, a Root file is produced
5897/// - if `filename` ends with `.xml`, a XML file is produced
5898/// - if `filename` ends with `.json`, a JSON file is produced
5899///
5900/// \remarks
5901/// - The parameter `option` is not used.
5902/// - This method calls [TPad::Print(const char *filename, Option_t *option)](\ref TPadPrint)
5903/// the value of `option` is determined by the `filename` extension.
5904/// - Postscript and PDF formats allow to have [several pictures in one file](\ref TPadPrintPS).
5905
5906void TPad::SaveAs(const char *filename, Option_t * /*option*/) const
5907{
5910
5911 if (!lenfil) { psname = GetName(); psname.Append(".ps"); }
5912 else psname = filename;
5913
5914 // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
5915 if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
5916 psname = GetName();
5917 psname.Append(filename);
5918 psname.Prepend("/");
5919 psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
5920 }
5921
5922 if (psname.EndsWith(".gif"))
5923 ((TPad*)this)->Print(psname,"gif");
5924 else if (psname.Contains(".gif+"))
5925 ((TPad*)this)->Print(psname,"gif+");
5926 else if (psname.EndsWith(".C") || psname.EndsWith(".cxx") || psname.EndsWith(".cpp") || psname.EndsWith(".cc"))
5927 ((TPad*)this)->Print(psname,"cxx");
5928 else if (psname.EndsWith(".root"))
5929 ((TPad*)this)->Print(psname,"root");
5930 else if (psname.EndsWith(".xml"))
5931 ((TPad*)this)->Print(psname,"xml");
5932 else if (psname.EndsWith(".json"))
5933 ((TPad*)this)->Print(psname,"json");
5934 else if (psname.EndsWith(".eps"))
5935 ((TPad*)this)->Print(psname,"eps");
5936 else if (psname.EndsWith(".pdf"))
5937 ((TPad*)this)->Print(psname,"pdf");
5938 else if (psname.EndsWith(".pdf["))
5939 ((TPad*)this)->Print(psname,"pdf");
5940 else if (psname.EndsWith(".pdf]"))
5941 ((TPad*)this)->Print(psname,"pdf");
5942 else if (psname.EndsWith(".pdf("))
5943 ((TPad*)this)->Print(psname,"pdf");
5944 else if (psname.EndsWith(".pdf)"))
5945 ((TPad*)this)->Print(psname,"pdf");
5946 else if (psname.EndsWith(".svg"))
5947 ((TPad*)this)->Print(psname,"svg");
5948 else if (psname.EndsWith(".tex"))
5949 ((TPad*)this)->Print(psname,"tex");
5950 else if (psname.EndsWith(".xpm"))
5951 ((TPad*)this)->Print(psname,"xpm");
5952 else if (psname.EndsWith(".png"))
5953 ((TPad*)this)->Print(psname,"png");
5954 else if (psname.EndsWith(".jpg"))
5955 ((TPad*)this)->Print(psname,"jpg");
5956 else if (psname.EndsWith(".jpeg"))
5957 ((TPad*)this)->Print(psname,"jpg");
5958 else if (psname.EndsWith(".bmp"))
5959 ((TPad*)this)->Print(psname,"bmp");
5960 else if (psname.EndsWith(".tiff"))
5961 ((TPad*)this)->Print(psname,"tiff");
5962 else
5963 ((TPad*)this)->Print(psname,"ps");
5964}
5965
5966////////////////////////////////////////////////////////////////////////////////
5967/// Save primitives in this pad on the C++ source file out.
5968
5969void TPad::SavePrimitive(std::ostream &out, Option_t * option /*= ""*/)
5970{
5971 TContext ctxt(this, kFALSE); // not interactive
5972
5974
5975 // check for space in the pad name
5976 auto p = padName.Index(" ");
5977 if (p != kNPOS)
5978 padName.Resize(p);
5979
5980 TString opt = option;
5981 if (!opt.Contains("toplevel")) {
5982 static Int_t pcounter = 0;
5983 padName += TString::Format("__%d", pcounter++);
5984 padName = gInterpreter->MapCppName(padName);
5985 }
5986
5987 const char *pname = padName.Data();
5988 const char *cname = padName.Data();
5989
5990 if (padName.Length() == 0) {
5991 pname = "unnamed";
5992 if (this == gPad->GetCanvas())
5993 cname = "c1";
5994 else
5995 cname = "pad";
5996 }
5997
5998 // Write pad parameters
5999 if (this != gPad->GetCanvas()) {
6000 out << " \n";
6001 out << "// ------------>Primitives in pad: " << GetName() << "\n";
6002 out << " TPad *" << cname << " = new TPad(\"" << GetName() << "\", \""
6003 << TString(GetTitle()).ReplaceSpecialCppChars() << "\", " << fXlowNDC << ", " << fYlowNDC << ", "
6004 << fXlowNDC + fWNDC << ", " << fYlowNDC + fHNDC << ");\n";
6005 out << " " << cname << "->Draw();\n";
6006 out << " " << cname << "->cd();\n";
6007 }
6008 out << " " << cname << "->Range(" << fX1 << "," << fY1 << "," << fX2 << "," << fY2 << ");\n";
6009 TView *view = GetView();
6010 if (view) {
6011 Double_t rmin[3], rmax[3];
6012 view->GetRange(rmin, rmax);
6013 out << " TView::CreateView(1)->SetRange(" << rmin[0] << ", " << rmin[1] << ", " << rmin[2] << ", " << rmax[0]
6014 << ", " << rmax[1] << ", " << rmax[2] << ");\n";
6015 }
6016
6017 SaveFillAttributes(out, cname, -1, -1);
6018
6019 if (GetBorderMode() != 1)
6020 out << " " << cname << "->SetBorderMode(" << GetBorderMode() << ");\n";
6021 if (GetBorderSize() != 4)
6022 out << " " << cname << "->SetBorderSize(" << GetBorderSize() << ");\n";
6023 if (GetLogx())
6024 out << " " << cname << "->SetLogx();\n";
6025 if (GetLogy())
6026 out << " " << cname << "->SetLogy();\n";
6027 if (GetLogz())
6028 out << " " << cname << "->SetLogz();\n";
6029 if (GetGridx())
6030 out << " " << cname << "->SetGridx();\n";
6031 if (GetGridy())
6032 out << " " << cname << "->SetGridy();\n";
6033 if (GetTickx())
6034 out << " " << cname << "->SetTickx(" << GetTickx() << ");\n";
6035 if (GetTicky())
6036 out << " " << cname << "->SetTicky(" << GetTicky() << ");\n";
6037 if (GetTheta() != 30)
6038 out << " " << cname << "->SetTheta(" << GetTheta() << ");\n";
6039 if (GetPhi() != 30)
6040 out << " " << cname << "->SetPhi(" << GetPhi() << ");\n";
6041 if (TMath::Abs(fLeftMargin - 0.1) > 0.01)
6042 out << " " << cname << "->SetLeftMargin(" << GetLeftMargin() << ");\n";
6043 if (TMath::Abs(fRightMargin - 0.1) > 0.01)
6044 out << " " << cname << "->SetRightMargin(" << GetRightMargin() << ");\n";
6045 if (TMath::Abs(fTopMargin - 0.1) > 0.01)
6046 out << " " << cname << "->SetTopMargin(" << GetTopMargin() << ");\n";
6047 if (TMath::Abs(fBottomMargin - 0.1) > 0.01)
6048 out << " " << cname << "->SetBottomMargin(" << GetBottomMargin() << ");\n";
6049
6051 out << " " << cname << "->SetFrameFillColor(" << TColor::SavePrimitiveColor(GetFrameFillColor()) << ");\n";
6052 if (GetFrameFillStyle() != 1001)
6053 out << " " << cname << "->SetFrameFillStyle(" << GetFrameFillStyle() << ");\n";
6054 if (GetFrameLineStyle() != 1)
6055 out << " " << cname << "->SetFrameLineStyle(" << GetFrameLineStyle() << ");\n";
6056 if (GetFrameLineColor() != 1)
6057 out << " " << cname << "->SetFrameLineColor(" << TColor::SavePrimitiveColor(GetFrameLineColor()) << ");\n";
6058 if (GetFrameLineWidth() != 1)
6059 out << " " << cname << "->SetFrameLineWidth(" << GetFrameLineWidth() << ");\n";
6060 if (GetFrameBorderMode() != 0)
6061 out << " " << cname << "->SetFrameBorderMode(" << GetFrameBorderMode() << ");\n";
6062 if (GetFrameBorderSize() != 1)
6063 out << " " << cname << "->SetFrameBorderSize(" << GetFrameBorderSize() << ");\n";
6064
6065 TFrame *frame = fFrame;
6066 if (!frame)
6067 frame = (TFrame *)GetPrimitive("TFrame");
6068 if (frame) {
6069 if (frame->GetFillColor() != GetFillColor())
6070 out << " " << cname << "->SetFrameFillColor(" << TColor::SavePrimitiveColor(frame->GetFillColor()) << ");\n";
6071 if (frame->GetFillStyle() != 1001)
6072 out << " " << cname << "->SetFrameFillStyle(" << frame->GetFillStyle() << ");\n";
6073 if (frame->GetLineStyle() != 1)
6074 out << " " << cname << "->SetFrameLineStyle(" << frame->GetLineStyle() << ");\n";
6075 if (frame->GetLineColor() != 1)
6076 out << " " << cname << "->SetFrameLineColor(" << TColor::SavePrimitiveColor(frame->GetLineColor()) << ");\n";
6077 if (frame->GetLineWidth() != 1)
6078 out << " " << cname << "->SetFrameLineWidth(" << frame->GetLineWidth() << ");\n";
6079 if (frame->GetBorderMode() != 0)
6080 out << " " << cname << "->SetFrameBorderMode(" << frame->GetBorderMode() << ");\n";
6081 if (frame->GetBorderSize() != 1)
6082 out << " " << cname << "->SetFrameBorderSize(" << frame->GetBorderSize() << ");\n";
6083 }
6084
6085 TIter next(GetListOfPrimitives());
6086
6087 while (auto obj = next()) {
6088 obj->SavePrimitive(out, (Option_t *)next.GetOption());
6089 if (obj->InheritsFrom(TPad::Class())) {
6090 if (opt.Contains("toplevel"))
6091 out << " " << pname << "->cd();\n";
6092 else
6093 out << " " << cname << "->cd();\n";
6094 }
6095 }
6096 out << " " << cname << "->Modified();\n";
6097}
6098
6099////////////////////////////////////////////////////////////////////////////////
6100/// Fix pad aspect ratio to current value if fixed is true.
6101
6103{
6104 if (fixed) {
6105 if (!fFixedAspectRatio) {
6106 if (fHNDC != 0.)
6108 else {
6109 Error("SetAspectRatio", "cannot fix aspect ratio, height of pad is 0");
6110 return;
6111 }
6113 }
6114 } else {
6116 fAspectRatio = 0;
6117 }
6118}
6119
6120////////////////////////////////////////////////////////////////////////////////
6121/// Set pad editable yes/no
6122/// If a pad is not editable:
6123/// - one cannot modify the pad and its objects via the mouse.
6124/// - one cannot add new objects to the pad
6125
6127{
6128 fEditable = mode;
6129
6130 TObject *obj;
6131 if (!fPrimitives) fPrimitives = new TList;
6132 TIter next(GetListOfPrimitives());
6133 while ((obj = next())) {
6134 if (obj->InheritsFrom(TPad::Class())) {
6135 TPad *pad = (TPad*)obj;
6136 pad->SetEditable(mode);
6137 }
6138 }
6139}
6140
6141////////////////////////////////////////////////////////////////////////////////
6142/// Override TAttFill::FillStyle for TPad because we want to handle style=0
6143/// as style 4000.
6144
6146{
6147 if (fstyle == 0) fstyle = 4000;
6149}
6150
6151////////////////////////////////////////////////////////////////////////////////
6152/// Set Lin/Log scale for X
6153/// - value = 0 X scale will be linear
6154/// - value = 1 X scale will be logarithmic (base 10)
6155/// - value > 1 reserved for possible support of base e or other
6156
6158{
6159 fLogx = value;
6160 delete fView; fView = nullptr;
6161 Modified();
6163}
6164
6165////////////////////////////////////////////////////////////////////////////////
6166/// Set Lin/Log scale for Y
6167/// - value = 0 Y scale will be linear
6168/// - value = 1 Y scale will be logarithmic (base 10)
6169/// - value > 1 reserved for possible support of base e or other
6170
6172{
6173 fLogy = value;
6174 delete fView; fView = nullptr;
6175 Modified();
6177}
6178
6179////////////////////////////////////////////////////////////////////////////////
6180/// Set Lin/Log scale for Z
6181
6183{
6184 fLogz = value;
6185 delete fView; fView = nullptr;
6186 Modified();
6188}
6189
6190////////////////////////////////////////////////////////////////////////////////
6191/// Set canvas range for pad and resize the pad. If the aspect ratio
6192/// was fixed before the call it will be un-fixed.
6193
6195{
6196 // Reorder points to make sure xlow,ylow is bottom left point and
6197 // xup,yup is top right point.
6198 if (xup < xlow) {
6199 Double_t x = xlow;
6200 xlow = xup;
6201 xup = x;
6202 }
6203 if (yup < ylow) {
6204 Double_t y = ylow;
6205 ylow = yup;
6206 yup = y;
6207 }
6208
6209 // Check if the new pad position is valid.
6210 if ((xlow < 0) || (xlow > 1) || (ylow < 0) || (ylow > 1)) {
6211 Error("TPad", "illegal bottom left position: x=%f, y=%f", xlow, ylow);
6212 return;
6213 }
6214 if ((xup < 0) || (xup > 1) || (yup < 0) || (yup > 1)) {
6215 Error("TPad", "illegal top right position: x=%f, y=%f", xup, yup);
6216 return;
6217 }
6218 if (xup-xlow <= 0) {
6219 Error("TPad", "illegal width: %f", xup-xlow);
6220 return;
6221 }
6222 if (yup-ylow <= 0) {
6223 Error("TPad", "illegal height: %f", yup-ylow);
6224 return;
6225 }
6226
6227 fXlowNDC = xlow;
6228 fYlowNDC = ylow;
6229 fXUpNDC = xup;
6230 fYUpNDC = yup;
6231 fWNDC = xup - xlow;
6232 fHNDC = yup - ylow;
6233
6235
6236 ResizePad();
6237}
6238
6239////////////////////////////////////////////////////////////////////////////////
6240/// Set all pad parameters.
6241
6242void TPad::SetPad(const char *name, const char *title,
6243 Double_t xlow, Double_t ylow, Double_t xup, Double_t yup,
6245{
6246 fName = name;
6247 fTitle = title;
6248 SetFillStyle(1001);
6253 if (color >= 0) SetFillColor(color);
6256 else fBorderSize = bordersize;
6258 else fBorderMode = bordermode;
6259
6260 SetPad(xlow, ylow, xup, yup);
6261}
6262
6263////////////////////////////////////////////////////////////////////////////////
6264/// Set the current TView. Delete previous view if view=0
6265
6267{
6268 if (!view) delete fView;
6269 fView = view;
6270}
6271
6272////////////////////////////////////////////////////////////////////////////////
6273/// Set postscript fill area attributes.
6274///
6275/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6276
6278{
6279 if (auto pp = GetPainter())
6280 if (!pp->IsNative()) {
6281 pp->SetFillColor(color);
6282 pp->SetFillStyle(style);
6283 }
6284}
6285
6286////////////////////////////////////////////////////////////////////////////////
6287/// Set postscript line attributes.
6288///
6289/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6290
6292{
6293 if (auto pp = GetPainter())
6294 if (!pp->IsNative()) {
6295 pp->SetLineColor(color);
6296 pp->SetLineStyle(style);
6297 pp->SetLineWidth(lwidth);
6298 }
6299}
6300
6301////////////////////////////////////////////////////////////////////////////////
6302/// Set postscript marker attributes.
6303///
6304/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6305
6307{
6308 if (auto pp = GetPainter())
6309 if (!pp->IsNative()) {
6310 pp->SetMarkerColor(color);
6311 pp->SetMarkerStyle(style);
6312 pp->SetMarkerSize(msize);
6313 }
6314}
6315
6316////////////////////////////////////////////////////////////////////////////////
6317/// Set postscript text attributes.
6318///
6319/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6320
6322{
6323 if (auto pp = GetPainter())
6324 if (!pp->IsNative()) {
6325 pp->SetTextAlign(align);
6326 pp->SetTextAngle(angle);
6327 pp->SetTextColor(color);
6328 pp->SetTextFont(font);
6329
6330 if (font%10 > 2) {
6333 Float_t dy;
6334 if (wh < hh) {
6336 tsize = dy/(GetX2()-GetX1());
6337 } else {
6339 tsize = dy/(GetY2()-GetY1());
6340 }
6341 }
6342 pp->SetTextSize(tsize);
6343 }
6344}
6345
6346////////////////////////////////////////////////////////////////////////////////
6347/// Draw Arrows to indicated equal distances of Objects with given BBoxes.
6348/// Used by ShowGuidelines
6349
6351{
6352 Int_t lineColor = TColor::GetColor(239, 202, 0);
6353 Int_t x1,x2,y1,y2;
6354 x1 = x2 = y1 = y2 = 0;
6355 if (mode == 'x') {
6356 if (aBBox.fX<bBBox.fX) {
6357 x1 = aBBox.fX+aBBox.fWidth;
6358 x2 = bBBox.fX;
6359 }
6360 else {
6361 x1 = bBBox.fX+bBBox.fWidth;
6362 x2 = aBBox.fX;
6363 }
6364
6365 if ((aBBox.fY > bBBox.fY) && (aBBox.fY + aBBox.fHeight < bBBox.fY + bBBox.fHeight))
6366 y1 = y2 = aBBox.fY + TMath::Nint(0.5*(Double_t)(aBBox.fHeight))+1;
6367 else if ((bBBox.fY > aBBox.fY) && (bBBox.fY + bBBox.fHeight < aBBox.fY + aBBox.fHeight))
6368 y1 = y2 = bBBox.fY + TMath::Nint(0.5*(Double_t)(bBBox.fHeight))+1;
6369 else if (aBBox.fY>bBBox.fY) y1 = y2 = aBBox.fY-TMath::Nint(0.5*(Double_t)(aBBox.fY-(bBBox.fY+bBBox.fHeight)));
6370 else y1 = y2 = bBBox.fY-TMath::Nint(0.5*(Double_t)(bBBox.fY-(aBBox.fY+aBBox.fHeight)));
6371 }
6372 else if (mode == 'y') {
6373 if (aBBox.fY<bBBox.fY) {
6374 y1 = aBBox.fY+aBBox.fHeight;
6375 y2 = bBBox.fY;
6376 }
6377 else {
6378 y1 = bBBox.fY+bBBox.fHeight;
6379 y2 = aBBox.fY;
6380 }
6381 if ((aBBox.fX > bBBox.fX) && (aBBox.fX + aBBox.fWidth < bBBox.fX + bBBox.fWidth))
6382 x1 = x2 = aBBox.fX + TMath::Nint(0.5*(Double_t)(aBBox.fWidth))+1;
6383 else if ((bBBox.fX > aBBox.fX) && (bBBox.fX + bBBox.fWidth < aBBox.fX + aBBox.fWidth))
6384 x1 = x2 = bBBox.fX + TMath::Nint(0.5*(Double_t)(bBBox.fWidth))+1;
6385 else if (aBBox.fX>bBBox.fX) x1 = x2 = aBBox.fX+TMath::Nint(0.5*(Double_t)(bBBox.fX+bBBox.fWidth-aBBox.fX));
6386 else x1 = x2 = bBBox.fX+TMath::Nint(0.5*(Double_t)(aBBox.fX+aBBox.fWidth-bBBox.fX));
6387 }
6388
6389 TArrow *A = new TArrow(gPad->PixeltoX(x1), gPad->PixeltoY(y1-gPad->VtoPixel(0)), gPad->PixeltoX(x2), gPad->PixeltoY(y2-gPad->VtoPixel(0)), 0.01, "<|>");
6390 A->SetBit(kCanDelete);
6392 A->SetLineWidth(1);
6394 A->Draw();
6395
6396 return;
6397}
6398
6399////////////////////////////////////////////////////////////////////////////////
6400/// struct used by ShowGuidelines to store the distance Field between objects
6401/// in the canvas.
6402
6403struct dField {
6407 char fdir;
6408
6409
6411 : fa(nullptr), fb(nullptr), fdist(0), fdir(' ')
6412 {}
6413
6415 : fa(a), fb(b), fdist(dist), fdir(direction)
6416 {}
6417};
6418
6419////////////////////////////////////////////////////////////////////////////////
6420/// Shows lines to indicate if a TAttBBox2D object is aligned to
6421/// the center or to another object, shows distance arrows if two
6422/// objects on screen have the same distance to another object
6423/// Call from primitive in Execute Event, in ButtonMotion after
6424/// the new coordinates have been set, to 'stick'
6425/// once when button is up to delete lines
6426///
6427/// modes: t (Top), b (bottom), l (left), r (right), i (inside)
6428/// in resize modes (t,b,l,r) only size arrows are sticky
6429///
6430/// in mode, the function gets the point on the element that is clicked to
6431/// move (i) or resize (all others). The expected values are:
6432/// \image html gpad_pad5.png
6433
6434void TPad::ShowGuidelines(TObject *object, const Int_t event, const char mode, const bool cling )
6435{
6436 // When the object is moved with arrow or when the ShowGuideLines flag
6437 // is off we do show guide lines.
6438 if ((event == kArrowKeyRelease) || (event == kArrowKeyPress) ||
6439 !gEnv->GetValue("Canvas.ShowGuideLines", 0)) return;
6440
6441 std::vector<dField> curDist;
6442 std::vector<dField> otherDist;
6443 Int_t pMX, pMY;
6444 Double_t MX, MY;
6446 TList *prims;
6447 UInt_t n;
6449 aBBox = bBBox = Rectangle_t();
6450 TLine *L;
6451 TArrow *A;
6452 Int_t dSizeArrow = 12; // distance of arrows indicating same size from BBox in px
6453 Bool_t movedX, movedY; // make sure the current object is moved just once
6454 movedX = movedY = false;
6455 Bool_t resize = false; // indicates resize mode
6456 Bool_t log = gPad->GetLogx() || gPad->GetLogy();
6457 if (mode != 'i') resize = true;
6458
6459 TPad *is_pad = dynamic_cast<TPad *>( object );
6460
6462
6463 if (is_pad && is_pad->GetMother())
6464 is_pad->GetMother()->cd();
6465
6466 static TPad *tmpGuideLinePad = nullptr;
6467
6468 //delete all existing Guidelines and create new invisible pad
6469 if (tmpGuideLinePad) {
6470 ctxt.PadDeleted(tmpGuideLinePad);
6471 auto guidePadClicked = (object == tmpGuideLinePad); // in case of funny button click combination.
6472 tmpGuideLinePad->Delete();
6473 tmpGuideLinePad = nullptr;
6474 if (guidePadClicked) return;
6475 }
6476
6477 // Get Primitives
6478 prims = gPad->GetListOfPrimitives();
6479 n = TMath::Min(15,prims->GetSize());
6480 Int_t lineColor = TColor::GetColor(239, 202, 0);
6481
6482 TAttBBox2D *cur = dynamic_cast<TAttBBox2D *>( object );
6483 if (cur) {
6484 //create invisible TPad above gPad
6485 if (!tmpGuideLinePad){
6486 tmpGuideLinePad = new TPad("tmpGuideLinePad", "tmpGuideLinePad", 0, 0, 1, 1);
6487 Double_t x1, y1, x2, y2;
6488 gPad->GetRange(x1, y1, x2, y2);
6489 tmpGuideLinePad->Range(x1, y1, x2, y2);
6490 tmpGuideLinePad->SetFillStyle(0);
6491 tmpGuideLinePad->SetFillColor(0);
6492 tmpGuideLinePad->Draw();
6493 tmpGuideLinePad->cd();
6494 gPad->GetRange(x1, y1, x2, y2);
6495 }
6496 if (cling && !log) threshold = 7;
6497 else threshold = 1;
6498
6499 Rectangle_t BBox = cur->GetBBox();
6500 TPoint center = cur->GetBBoxCenter();
6501
6502 otherDist.clear();
6503 curDist.clear();
6504
6505 switch (event) {
6506
6507 case kButton1Down:
6508 case kButton1Motion:
6509 MX = gPad->GetX1() + 0.5 * (gPad->GetX2()-gPad->GetX1());
6510 MY = gPad->GetY1() + 0.5 * (gPad->GetY2()-gPad->GetY1());
6511 pMX = gPad->XtoPixel(MX);
6512 pMY = gPad->YtoPixel(MY);
6513 // Middlelines
6514 if (TMath::Abs(pMX-center.GetX())<threshold) {
6515 if (cling && (!resize)) {
6516 cur->SetBBoxCenterX(pMX);
6517 center = cur->GetBBoxCenter();
6518 BBox = cur->GetBBox();
6519 center = cur->GetBBoxCenter();
6520 }
6521 L = new TLine(MX, gPad->GetY1(), MX, gPad->GetY2());
6522 L->SetBit(kCanDelete);
6523 L->SetLineColor(lineColor);
6524 L->Draw();
6525 }
6526 if (TMath::Abs(pMY-center.GetY())<threshold) {
6527 if (cling && (!resize)) {
6528 cur->SetBBoxCenterY(pMY);
6529 center = cur->GetBBoxCenter();
6530 BBox = cur->GetBBox();
6531 center = cur->GetBBoxCenter();
6532 }
6533 L = new TLine(gPad->GetX1(), MY, gPad->GetX2(), MY);
6534 L->SetBit(kCanDelete);
6535 L->SetLineColor(lineColor);
6536 L->Draw();
6537 }
6538 // Alignment to other objects
6539 for (UInt_t i = 0; i<n; i++) {
6540 TAttBBox2D *other = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6541 if (other) {
6542 if (other != cur) {
6543 TPoint centerOther = other->GetBBoxCenter();
6544 if (TMath::Abs(center.GetX()-centerOther.GetX())<threshold) {
6545 if (cling && (!resize)) {
6546 cur->SetBBoxCenterX(centerOther.GetX());
6547 BBox = cur->GetBBox();
6548 center = cur->GetBBoxCenter();
6549 }
6550 L = new TLine(gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(center.GetY()-gPad->VtoPixel(0)),
6551 gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)));
6552 L->SetLineColor(lineColor);
6553 L->Draw();
6554 L->SetBit(kCanDelete);
6555 }
6556 if (TMath::Abs(center.GetY()-centerOther.GetY())<threshold) {
6557 if (cling && (!resize)) {
6558 cur->SetBBoxCenterY(centerOther.GetY());
6559 BBox = cur->GetBBox();
6560 center = cur->GetBBoxCenter();
6561 }
6562 L = new TLine(gPad->PixeltoX(center.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)),
6563 gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)));
6564 L->SetBit(kCanDelete);
6565 L->SetLineColor(lineColor);
6566 L->Draw();
6567 }
6568 }
6569 }
6570 }
6571 // Get Distances between objects
6572 for (UInt_t i = 0; i<n; i++) {
6573 TAttBBox2D *a = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6574 if (a) {
6575 aBBox = a->GetBBox();
6576 for (UInt_t j = i+1; j<n; j++) {
6577 TAttBBox2D *b = dynamic_cast<TAttBBox2D *>( prims->At(j) );
6578 if (b) {
6579 bBBox = b->GetBBox();
6580
6581 //only when bounding boxes overlap in x or y direction
6582 if (((aBBox.fX<bBBox.fX) && (bBBox.fX-aBBox.fX<=aBBox.fWidth))||((aBBox.fX>bBBox.fX) && (aBBox.fX-bBBox.fX<=bBBox.fWidth))){ //BBoxes overlap in x direction
6583 if ((aBBox.fY+aBBox.fHeight<bBBox.fY)||(bBBox.fY+bBBox.fHeight<aBBox.fY)) {//No overlap in Y-direction required
6584 dField abDist = dField();
6585 if (aBBox.fY>bBBox.fY) abDist = dField(a, b, TMath::Abs(aBBox.fY-(bBBox.fY+bBBox.fHeight)), 'y');
6586 else abDist = dField(a, b, TMath::Abs(bBBox.fY-(aBBox.fY+aBBox.fHeight)), 'y');
6587 if ((b != cur)&&(a != cur)) otherDist.push_back(abDist);
6588 else curDist.push_back(abDist);
6589 }
6590 } else if (((aBBox.fY<bBBox.fY) && (bBBox.fY-aBBox.fY<=aBBox.fHeight))||((aBBox.fY>bBBox.fY) && (aBBox.fY-bBBox.fY<=bBBox.fHeight))) { //BBoxes overlap in y direction
6591 if ((aBBox.fX+aBBox.fWidth<bBBox.fX)||(bBBox.fX+bBBox.fWidth<aBBox.fX)) {//No overlap in x-direction required
6592 dField abDist = dField();
6593 if (aBBox.fX>bBBox.fX) abDist = dField(a, b, TMath::Abs(aBBox.fX-(bBBox.fX+bBBox.fWidth)), 'x');
6594 else abDist = dField(a, b, TMath::Abs(bBBox.fX-(aBBox.fX+aBBox.fWidth)), 'x');
6595 if ((b != cur)&&(a != cur)) otherDist.push_back(abDist);
6596 else curDist.push_back(abDist);
6597 }
6598 }
6599 }
6600 }
6601 }
6602 }
6603 // Show equal distances
6604 for (UInt_t i = 0; i<curDist.size(); i++) {
6605 for (UInt_t j = 0; j<otherDist.size(); j++) {
6606 if ((curDist[i].fdir == otherDist[j].fdir) && (otherDist[j].fdir=='x') && (TMath::Abs(curDist[i].fdist-otherDist[j].fdist)<threshold)) {
6607 if (cling && (!movedX) && (!resize)) {
6608 if ((cur->GetBBoxCenter().fX < curDist[i].fb->GetBBoxCenter().fX)||(cur->GetBBoxCenter().fX < curDist[i].fa->GetBBoxCenter().fX))
6609 cur->SetBBoxCenterX(cur->GetBBoxCenter().fX - otherDist[j].fdist + curDist[i].fdist);
6610 else cur->SetBBoxCenterX(cur->GetBBoxCenter().fX + otherDist[j].fdist - curDist[i].fdist);
6611 movedX = true;
6612 }
6613 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'x');
6614 DrawDist(otherDist[j].fa->GetBBox(), otherDist[j].fb->GetBBox(), 'x');
6615 }
6616 if ((curDist[i].fdir == otherDist[j].fdir) && (otherDist[j].fdir=='y') && (TMath::Abs(curDist[i].fdist-otherDist[j].fdist)<threshold)) {
6617 if (cling && (!movedY) && (!resize)) {
6618 if ((cur->GetBBoxCenter().fY < curDist[i].fb->GetBBoxCenter().fY)||(cur->GetBBoxCenter().fY < curDist[i].fa->GetBBoxCenter().fY))
6619 cur->SetBBoxCenterY(cur->GetBBoxCenter().fY - otherDist[j].fdist + curDist[i].fdist);
6620 else cur->SetBBoxCenterY(cur->GetBBoxCenter().fY + otherDist[j].fdist - curDist[i].fdist);
6621 movedY = true;
6622 }
6623 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'y');
6624 DrawDist(otherDist[j].fa->GetBBox(), otherDist[j].fb->GetBBox(), 'y');
6625 }
6626 }
6627 for (UInt_t j = i; j<curDist.size(); j++) {
6628 if (i!=j) {
6629 if ((curDist[i].fdir == curDist[j].fdir) && (curDist[j].fdir=='x') && (TMath::Abs(curDist[i].fdist-curDist[j].fdist)<threshold)) {
6630 if (cling && (!movedX) && (!resize)) {
6631 if ((cur->GetBBoxCenter().fX < curDist[i].fb->GetBBoxCenter().fX)||(cur->GetBBoxCenter().fX < curDist[i].fa->GetBBoxCenter().fX))
6632 cur->SetBBoxCenterX(cur->GetBBoxCenter().fX - floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6633 else cur->SetBBoxCenterX(cur->GetBBoxCenter().fX + floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6634 }
6635 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'x');
6636 DrawDist(curDist[j].fa->GetBBox(), curDist[j].fb->GetBBox(), 'x');
6637 }
6638
6639 if ((curDist[i].fdir == curDist[j].fdir) && (curDist[j].fdir=='y') && (TMath::Abs(curDist[i].fdist-curDist[j].fdist)<threshold)) {
6640 if (cling && (!movedY) && (!resize)) {
6641 if ((cur->GetBBoxCenter().fY < curDist[i].fb->GetBBoxCenter().fY)||(cur->GetBBoxCenter().fY < curDist[i].fa->GetBBoxCenter().fY))
6642 cur->SetBBoxCenterY(cur->GetBBoxCenter().fY - floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6643 else cur->SetBBoxCenterY(cur->GetBBoxCenter().fY + floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6644 }
6645 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'y');
6646 DrawDist(curDist[j].fa->GetBBox(), curDist[j].fb->GetBBox(), 'y');
6647 }
6648 }
6649 }
6650 }
6651 if (resize) {
6652 // Show equal Sizes
6653 for (UInt_t i = 0; i<n; i++) {
6654 TAttBBox2D *a = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6655 if (a && (cur != a)) {
6656 aBBox = a->GetBBox();
6657
6658 if ((TMath::Abs(aBBox.fWidth - BBox.fWidth)<threshold) && (mode != 't') && (mode != 'b')) {
6659 if (cling) {
6660 if (mode == 'l') cur->SetBBoxX1(BBox.fX + BBox.fWidth - aBBox.fWidth);
6661 if (mode == 'r') cur->SetBBoxX2(BBox.fX + aBBox.fWidth);
6662 if ((mode == '1')||(mode == '4')) cur->SetBBoxX1(BBox.fX + BBox.fWidth - aBBox.fWidth);
6663 if ((mode == '2')||(mode == '3')) cur->SetBBoxX2(BBox.fX + aBBox.fWidth);
6664 BBox = cur->GetBBox();
6665 }
6666
6667 A = new TArrow(gPad->PixeltoX(aBBox.fX), gPad->PixeltoY(aBBox.fY-dSizeArrow-gPad->VtoPixel(0)),
6668 gPad->PixeltoX(aBBox.fX+aBBox.fWidth), gPad->PixeltoY(aBBox.fY-dSizeArrow-gPad->VtoPixel(0)), 0.01, "<|>");
6669 A->SetBit(kCanDelete);
6672 A->Draw();
6673
6674 A = new TArrow(gPad->PixeltoX(BBox.fX), gPad->PixeltoY(BBox.fY-dSizeArrow-gPad->VtoPixel(0)),
6675 gPad->PixeltoX(BBox.fX+BBox.fWidth), gPad->PixeltoY(BBox.fY-dSizeArrow-gPad->VtoPixel(0)), 0.01, "<|>");
6676 A->SetBit(kCanDelete);
6679 A->Draw();
6680 }
6681 if ((TMath::Abs(aBBox.fHeight - BBox.fHeight)<threshold) && (mode != 'r') && (mode != 'l')) {
6682 if (cling) {
6683 if (mode == 't') cur->SetBBoxY1(BBox.fY + BBox.fHeight - aBBox.fHeight);
6684 if (mode == 'b') cur->SetBBoxY2(BBox.fY + aBBox.fHeight);
6685 if ((mode == '1')||(mode == '2')) cur->SetBBoxY1(BBox.fY + BBox.fHeight - aBBox.fHeight);
6686 if ((mode == '3')||(mode == '4')) cur->SetBBoxY2(BBox.fY + aBBox.fHeight);
6687 BBox = cur->GetBBox();
6688 }
6689 A = new TArrow(gPad->PixeltoX(aBBox.fX-dSizeArrow), gPad->PixeltoY(aBBox.fY-gPad->VtoPixel(0)),
6690 gPad->PixeltoX(aBBox.fX-dSizeArrow), gPad->PixeltoY(aBBox.fY+aBBox.fHeight-gPad->VtoPixel(0)), 0.01, "<|>");
6691 A->SetBit(kCanDelete);
6694 A->Draw();
6695
6696 A = new TArrow(gPad->PixeltoX(BBox.fX-dSizeArrow), gPad->PixeltoY(BBox.fY-gPad->VtoPixel(0)),
6697 gPad->PixeltoX(BBox.fX-dSizeArrow), gPad->PixeltoY(BBox.fY+BBox.fHeight-gPad->VtoPixel(0)), 0.01, "<|>");
6698 A->SetBit(kCanDelete);
6701 A->Draw();
6702 }
6703 }
6704 }
6705 }
6706
6707 break;
6708
6709 case kButton1Up:
6710 if (tmpGuideLinePad) {
6711 // All the arrows and lines in that pad are also deleted because
6712 // they all have the bit kCanDelete on.
6713 tmpGuideLinePad->Delete();
6714 tmpGuideLinePad = nullptr;
6715 }
6716 break;
6717 }
6718 }
6719
6720 gPad->Modified(kTRUE);
6721}
6722
6723////////////////////////////////////////////////////////////////////////////////
6724/// Return kTRUE if the crosshair has been activated (via SetCrosshair).
6725
6727{
6728 return (Bool_t)GetCrosshair();
6729}
6730
6731////////////////////////////////////////////////////////////////////////////////
6732/// Return the crosshair type (from the mother canvas)
6733/// crosshair type = 0 means no crosshair.
6734
6736{
6737 if (this == (TPad*)fCanvas)
6738 return fCrosshair;
6739 return fCanvas ? fCanvas->GetCrosshair() : 0;
6740}
6741
6742////////////////////////////////////////////////////////////////////////////////
6743/// Set crosshair active/inactive.
6744/// - If crhair != 0, a crosshair will be drawn in the pad and its sub-pads.
6745/// - If the canvas crhair = 1 , the crosshair spans the full canvas.
6746/// - If the canvas crhair > 1 , the crosshair spans only the pad.
6747
6749{
6750 if (!fCanvas) return;
6752 fCrosshairPos = 0;
6753
6754 if (this != (TPad*)fCanvas) fCanvas->SetCrosshair(crhair);
6755}
6756
6757////////////////////////////////////////////////////////////////////////////////
6758/// static function to set the maximum Pick Distance fgMaxPickDistance
6759/// This parameter is used in TPad::Pick to select an object if
6760/// its DistancetoPrimitive returns a value < fgMaxPickDistance
6761/// The default value is 5 pixels. Setting a smaller value will make
6762/// picking more precise but also more difficult
6763
6768
6769////////////////////////////////////////////////////////////////////////////////
6770/// Set tool tip text associated with this pad. The delay is in
6771/// milliseconds (minimum 250). To remove tool tip call method with
6772/// text = 0.
6773
6775{
6776 if (fTip) {
6778 fTip = nullptr;
6779 }
6780
6781 if (text && strlen(text))
6782 fTip = CreateToolTip((TBox*)nullptr, text, delayms);
6783}
6784
6785////////////////////////////////////////////////////////////////////////////////
6786/// Set pad vertical (default) or horizontal
6787
6789{
6790 if (vert) ResetBit(kHori);
6791 else SetBit(kHori);
6792}
6793
6794////////////////////////////////////////////////////////////////////////////////
6795/// Stream a class object.
6796
6798{
6799 UInt_t R__s, R__c;
6802 TObject *obj;
6803 if (b.IsReading()) {
6804 Version_t v = b.ReadVersion(&R__s, &R__c);
6805 if (v > 5) {
6806 if (!gPad)
6807 gPad = new TCanvas(GetName());
6808 fMother = (TPad*)gPad;
6810 TContext ctxt(this, kFALSE);
6811 fPixmapID = -1; // -1 means pixmap will be created by ResizePad()
6812 gReadLevel++;
6813 gROOT->SetReadingObject(kTRUE);
6814
6815 b.ReadClassBuffer(TPad::Class(), this, v, R__s, R__c);
6816
6817 //Set the kCanDelete bit in all objects in the pad such that when the pad
6818 //is deleted all objects in the pad are deleted too.
6819 //Also set must cleanup bit which normally set for all primitives add to pad,
6820 // but may be reset in IO like TH1::Streamer does
6821 TIter next(fPrimitives);
6822 while ((obj = next())) {
6823 obj->SetBit(kCanDelete);
6824 obj->SetBit(kMustCleanup);
6825 }
6826
6827 fModified = kTRUE;
6828 fPadPointer = nullptr;
6829 gReadLevel--;
6830 if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
6831 gROOT->SetReadingObject(kFALSE);
6832 return;
6833 }
6834
6835 //====process old versions before automatic schema evolution
6836 if (v < 5) { //old TPad in single precision
6837 if (v < 3) { //old TPad derived from TWbox
6838 b.ReadVersion(); // TVirtualPad::Streamer(b)
6839 b.ReadVersion(); // TWbox::Streamer(b)
6840 b.ReadVersion(); // TBox::Streamer(b)
6844 b >> single; fX1 = single;
6845 b >> single; fY1 = single;
6846 b >> single; fX2 = single;
6847 b >> single; fY2 = single;
6848 b >> fBorderSize;
6849 b >> fBorderMode;
6851 } else { //new TPad
6854 b >> single; fX1 = single;
6855 b >> single; fY1 = single;
6856 b >> single; fX2 = single;
6857 b >> single; fY2 = single;
6858 b >> fBorderSize;
6859 b >> fBorderMode;
6860 }
6861 b >> fLogx;
6862 b >> fLogy;
6863 b >> fLogz;
6865 b >> single; fXtoPixelk = single;
6866 b >> single; fXtoPixel = single;
6868 b >> single; fYtoPixelk = single;
6869 b >> single; fYtoPixel = single;
6871 b >> single; fUtoPixelk = single;
6872 b >> single; fUtoPixel = single;
6874 b >> single; fVtoPixelk = single;
6875 b >> single; fVtoPixel = single;
6877 b >> single; fPixeltoXk = single;
6878 b >> single; fPixeltoX = single;
6880 b >> single; fPixeltoYk = single;
6881 b >> single; fPixeltoY = single;
6882 b >> single; fXlowNDC = single;
6883 b >> single; fYlowNDC = single;
6884 b >> single; fWNDC = single;
6885 b >> single; fHNDC = single;
6886 b >> single; fAbsXlowNDC = single;
6887 b >> single; fAbsYlowNDC = single;
6888 b >> single; fAbsWNDC = single;
6889 b >> single; fAbsHNDC = single;
6890 b >> single; fUxmin = single;
6891 b >> single; fUymin = single;
6892 b >> single; fUxmax = single;
6893 b >> single; fUymax = single;
6894 } else {
6897 b >> fX1;
6898 b >> fY1;
6899 b >> fX2;
6900 b >> fY2;
6901 b >> fBorderSize;
6902 b >> fBorderMode;
6903 b >> fLogx;
6904 b >> fLogy;
6905 b >> fLogz;
6906 b >> fXtoAbsPixelk;
6907 b >> fXtoPixelk;
6908 b >> fXtoPixel;
6909 b >> fYtoAbsPixelk;
6910 b >> fYtoPixelk;
6911 b >> fYtoPixel;
6912 b >> fUtoAbsPixelk;
6913 b >> fUtoPixelk;
6914 b >> fUtoPixel;
6915 b >> fVtoAbsPixelk;
6916 b >> fVtoPixelk;
6917 b >> fVtoPixel;
6918 b >> fAbsPixeltoXk;
6919 b >> fPixeltoXk;
6920 b >> fPixeltoX;
6921 b >> fAbsPixeltoYk;
6922 b >> fPixeltoYk;
6923 b >> fPixeltoY;
6924 b >> fXlowNDC;
6925 b >> fYlowNDC;
6926 b >> fWNDC;
6927 b >> fHNDC;
6928 b >> fAbsXlowNDC;
6929 b >> fAbsYlowNDC;
6930 b >> fAbsWNDC;
6931 b >> fAbsHNDC;
6932 b >> fUxmin;
6933 b >> fUymin;
6934 b >> fUxmax;
6935 b >> fUymax;
6936 }
6937
6938 if (!gPad)
6939 gPad = new TCanvas(GetName());
6940 if (gReadLevel == 0)
6942 else
6943 fMother = (TPad *)gPad;
6944 if (!fMother)
6945 fMother = (TPad *)gPad;
6946 if (fMother)
6948 gPad = fMother;
6949 fPixmapID = -1; // -1 means pixmap will be created by ResizePad()
6950 //-------------------------
6951 // read objects and their drawing options
6952 // b >> fPrimitives;
6953 gReadLevel++;
6954 gROOT->SetReadingObject(kTRUE);
6955 fPrimitives = new TList;
6956 b >> nobjects;
6957 if (nobjects > 0) {
6958 TContext ctxt(this, kFALSE);
6959 char drawoption[64];
6960 for (Int_t i = 0; i < nobjects; i++) {
6961 b >> obj;
6962 b >> nch;
6963 b.ReadFastArray(drawoption,nch);
6965 gPad = this; // gPad may be modified in b >> obj if obj is a pad
6966 }
6967 }
6968 gReadLevel--;
6969 gROOT->SetReadingObject(kFALSE);
6970 //////////////////////////////////////////////////////////////////////////
6971
6972 if (v > 3) {
6973 b >> fExecs;
6974 }
6975 fName.Streamer(b);
6976 fTitle.Streamer(b);
6977 b >> fPadPaint;
6978 fModified = kTRUE;
6979 b >> fGridx;
6980 b >> fGridy;
6981 b >> fFrame;
6982 b >> fView;
6983 if (v < 5) {
6984 b >> single; fTheta = single;
6985 b >> single; fPhi = single;
6986 } else {
6987 b >> fTheta;
6988 b >> fPhi;
6989 }
6990 fPadPointer = nullptr;
6991 b >> fNumber;
6992 b >> fAbsCoord;
6993 if (v > 1) {
6994 b >> fTickx;
6995 b >> fTicky;
6996 } else {
6997 fTickx = fTicky = 0;
6998 }
6999 if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
7000 b.CheckByteCount(R__s, R__c, TPad::IsA());
7001 //====end of old versions
7002
7003 } else {
7004 b.WriteClassBuffer(TPad::Class(),this);
7005 }
7006}
7007
7008////////////////////////////////////////////////////////////////////////////////
7009/// Force a copy of current style for all objects in pad.
7010
7012{
7013 if (gStyle->IsReading()) {
7025 fLogx = gStyle->GetOptLogx();
7026 fLogy = gStyle->GetOptLogy();
7027 fLogz = gStyle->GetOptLogz();
7028 } else {
7043 }
7044
7045 if (!fPrimitives) fPrimitives = new TList;
7046 TIter next(GetListOfPrimitives());
7047 TObject *obj;
7048
7049 while ((obj = next())) {
7050 obj->UseCurrentStyle();
7051 }
7052
7053 TPaveText *title = (TPaveText*)FindObject("title");
7054 if (title) {
7055 if (gStyle->IsReading()) {
7057 title->SetTextFont(gStyle->GetTitleFont(""));
7060 if (!gStyle->GetOptTitle()) delete title;
7061 } else {
7063 gStyle->SetTitleFont(title->GetTextFont());
7066 }
7067 }
7069
7070 if (gStyle->IsReading()) Modified();
7071}
7072
7073////////////////////////////////////////////////////////////////////////////////
7074/// Loop and sleep until a primitive with name=pname is found in the pad.
7075///
7076/// If emode is given, the editor is automatically set to emode, ie
7077/// it is not required to have the editor control bar.
7078///
7079/// The possible values for emode are:
7080/// - emode = "" (default). User will select the mode via the editor bar
7081/// - emode = "Arc", "Line", "Arrow", "Button", "Diamond", "Ellipse",
7082/// - emode = "Pad","pave", "PaveLabel","PaveText", "PavesText",
7083/// - emode = "PolyLine", "CurlyLine", "CurlyArc", "Text", "Marker", "CutG"
7084///
7085/// If emode is specified and it is not valid, "PolyLine" is assumed. If emode
7086/// is not specified or ="", an attempt is to use pname[1...]
7087///
7088/// for example if pname="TArc", emode="Arc" will be assumed.
7089/// When this function is called within a macro, the macro execution
7090/// is suspended until a primitive corresponding to the arguments
7091/// is found in the pad.
7092///
7093/// If CRTL/C is typed in the pad, the function returns 0.
7094///
7095/// While this function is executing, one can use the mouse, interact
7096/// with the graphics pads, use the Inspector, Browser, TreeViewer, etc.
7097///
7098/// Examples:
7099/// ~~~ {.cpp}
7100/// c1.WaitPrimitive(); // Return the first created primitive
7101/// // whatever it is.
7102/// // If a double-click with the mouse is executed
7103/// // in the pad or any key pressed, the function
7104/// // returns 0.
7105/// c1.WaitPrimitive("ggg"); // Set the editor in mode "PolyLine/Graph"
7106/// // Create a polyline, then using the context
7107/// // menu item "SetName", change the name
7108/// // of the created TGraph to "ggg"
7109/// c1.WaitPrimitive("TArc");// Set the editor in mode "Arc". Returns
7110/// // as soon as a TArc object is created.
7111/// c1.WaitPrimitive("lat","Text"); // Set the editor in Text/Latex mode.
7112/// // Create a text object, then Set its name to "lat"
7113/// ~~~
7114/// The following macro waits for 10 primitives of any type to be created.
7115///
7116/// ~~~ {.cpp}
7117///{
7118/// TCanvas c1("c1");
7119/// TObject *obj;
7120/// for (Int_t i=0;i<10;i++) {
7121/// obj = gPad->WaitPrimitive();
7122/// if (!obj) break;
7123/// printf("Loop i=%d, found objIsA=%s, name=%s\n",
7124/// i,obj->ClassName(),obj->GetName());
7125/// }
7126///}
7127/// ~~~
7128///
7129/// If ROOT runs in batch mode a call to this method does nothing.
7130
7131TObject *TPad::WaitPrimitive(const char *pname, const char *emode)
7132{
7133 if (!gPad || IsWeb())
7134 return nullptr;
7135
7136 if (emode && strlen(emode)) gROOT->SetEditorMode(emode);
7137 if (gROOT->GetEditorMode() == 0 && pname && strlen(pname) > 2) gROOT->SetEditorMode(&pname[1]);
7138
7139 if (!fPrimitives) fPrimitives = new TList;
7141 TObject *oldlast = gPad->GetListOfPrimitives() ? gPad->GetListOfPrimitives()->Last() : nullptr;
7142 TObject *obj = nullptr;
7144 Bool_t hasname = pname && (strlen(pname) > 0);
7145 if ((!pname || !pname[0]) && (!emode || !emode[0])) testlast = kTRUE;
7146 if (testlast) gROOT->SetEditorMode();
7147 while (!gSystem->ProcessEvents() && gROOT->GetSelectedPad() && gPad) {
7148 if (gROOT->GetEditorMode() == 0) {
7149 if (hasname) {
7150 obj = FindObject(pname);
7151 if (obj) return obj;
7152 }
7153 if (testlast) {
7154 if (!gPad->GetListOfPrimitives()) return nullptr;
7155 obj = gPad->GetListOfPrimitives()->Last();
7156 if (obj != oldlast) return obj;
7157 Int_t event = GetEvent();
7158 if (event == kButton1Double || event == kKeyPress) {
7159 //the following statement is required against other loop executions
7160 //before returning
7161 fCanvas->HandleInput((EEventType)-1,0,0);
7162 return nullptr;
7163 }
7164 }
7165 }
7166 gSystem->Sleep(10);
7167 }
7168
7169 return nullptr;
7170}
7171
7172////////////////////////////////////////////////////////////////////////////////
7173/// Create a tool tip and return its pointer.
7174
7176{
7177 if (gPad->IsBatch()) return nullptr;
7178 return (TObject*)gROOT->ProcessLineFast(TString::Format("new TGToolTip((TBox*)0x%zx,\"%s\",%d)",
7179 (size_t)box,text,(Int_t)delayms).Data());
7180}
7181
7182////////////////////////////////////////////////////////////////////////////////
7183/// Delete tool tip object.
7184
7186{
7187 // delete tip;
7188 if (!tip) return;
7189 gROOT->ProcessLineFast(TString::Format("delete (TGToolTip*)0x%zx", (size_t)tip).Data());
7190}
7191
7192////////////////////////////////////////////////////////////////////////////////
7193/// Reset tool tip, i.e. within time specified in CreateToolTip the
7194/// tool tip will pop up.
7195
7197{
7198 if (!tip) return;
7199 // tip->Reset(this);
7200 gROOT->ProcessLineFast(TString::Format("((TGToolTip*)0x%zx)->Reset((TPad*)0x%zx)",
7201 (size_t)tip,(size_t)this).Data());
7202}
7203
7204////////////////////////////////////////////////////////////////////////////////
7205/// Hide tool tip.
7206
7208{
7209 if (!tip) return;
7210 // tip->Hide();
7211 gROOT->ProcessLineFast(TString::Format("((TGToolTip*)0x%zx)->Hide()", (size_t)tip).Data());
7212}
7213
7214////////////////////////////////////////////////////////////////////////////////
7215/// Deprecated: use TPad::GetViewer3D() instead
7216
7218{
7219 ::Info("TPad::x3d()", "This function is deprecated. Use %s->GetViewer3D(\"x3d\") instead",this->GetName());
7220
7221 // Default on GetViewer3D is pad - for x3d it was x3d...
7222 if (!type || !type[0]) {
7223 type = "x3d";
7224 }
7226}
7227
7228////////////////////////////////////////////////////////////////////////////////
7229/// Create/obtain handle to 3D viewer. Valid types are:
7230/// - 'pad' - pad drawing via TViewer3DPad
7231/// any others registered with plugin manager supporting TVirtualViewer3D
7232/// If an invalid/null type is requested then the current viewer is returned
7233/// (if any), otherwise a default 'pad' type is returned
7234
7236{
7238
7239 if ((!type || !*type || (strstr(type, "gl") && !strstr(type, "ogl"))) && (!fCanvas || !fCanvas->UseGL()))
7240 type = "pad";
7241
7242 if (type && *type) {
7243 if (gPluginMgr->FindHandler("TVirtualViewer3D", type))
7244 validType = kTRUE;
7245 }
7246
7247 // Invalid/null type requested?
7248 if (!validType) {
7249 // Return current viewer if there is one
7250 if (fViewer3D)
7251 return fViewer3D;
7252 // otherwise default to the pad
7253 else
7254 type = "pad";
7255 }
7256
7257 // Ensure we can create the new viewer before removing any existing one
7258 TVirtualViewer3D *newViewer = nullptr;
7259
7261
7262 // External viewers need to be created via plugin manager via interface...
7263 if (!strstr(type,"pad")) {
7265
7266 if (!newViewer) {
7267 Warning("GetViewer3D", "Cannot create 3D viewer of type: %s", type);
7268 // Return the existing viewer
7269 return fViewer3D;
7270 }
7271
7272 if (strstr(type, "gl") && !strstr(type, "ogl")) {
7275 Modified();
7276 } else {
7278 }
7279
7280 } else {
7281 newViewer = new TViewer3DPad(*this);
7282 }
7283
7284 // If we had a previous viewer destroy it now
7285 // In this case we do take responsibility for destroying viewer
7286 // c.f. ReleaseViewer3D
7287 delete fViewer3D;
7288
7289 // Set and return new viewer
7291
7292 // Ensure any new external viewer is painted
7293 // For internal TViewer3DPad type we assume this is being
7294 // create on demand due to a paint - so this is not required
7295 if (createdExternal) {
7296 Modified();
7297 Update();
7298 }
7299
7300 return fViewer3D;
7301}
7302
7303////////////////////////////////////////////////////////////////////////////////
7304/// Release current (external) viewer
7305
7307{
7308 fViewer3D = nullptr;
7309
7310 // We would like to ensure the pad is repainted
7311 // when external viewer is closed down. However
7312 // a modify/paint call here will repaint the pad
7313 // before the external viewer window actually closes.
7314 // So the pad would have to be redraw twice over.
7315 // Currently we just have to live with the pad staying blank
7316 // any click in pad will refresh.
7317}
7318
7319////////////////////////////////////////////////////////////////////////////////
7320/// Get GL device.
7321
7323{
7324 return fGLDevice;
7325}
7326
7327////////////////////////////////////////////////////////////////////////////////
7328/// Emit RecordPave() signal.
7329
7331{
7332 Emit("RecordPave(const TObject*)", (Longptr_t)obj);
7333}
7334
7335////////////////////////////////////////////////////////////////////////////////
7336/// Emit RecordLatex() signal.
7337
7339{
7340 Emit("RecordLatex(const TObject*)", (Longptr_t)obj);
7341}
7342
7343////////////////////////////////////////////////////////////////////////////////
7344/// Get pad painter from TCanvas.
7345
7347{
7348 if (!fCanvas) return nullptr;
7349 return fCanvas->GetCanvasPainter();
7350}
7351
7352////////////////////////////////////////////////////////////////////////////////
7353/// Return the bounding Box of the Pad
7354
7356{
7357 Rectangle_t BBox{0, 0, 0, 0};
7358 if (gPad) {
7359 BBox.fX = gPad->XtoPixel(fXlowNDC * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1());
7360 BBox.fY = gPad->YtoPixel((fYlowNDC + fHNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1());
7361 BBox.fWidth = gPad->XtoPixel((fXlowNDC + fWNDC) * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1()) -
7362 gPad->XtoPixel(fXlowNDC * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1());
7363 BBox.fHeight = gPad->YtoPixel((fYlowNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1()) -
7364 gPad->YtoPixel((fYlowNDC + fHNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1());
7365 }
7366 return BBox;
7367}
7368
7369////////////////////////////////////////////////////////////////////////////////
7370/// Return the center of the Pad as TPoint in pixels
7371
7373{
7374 TPoint p(0, 0);
7375 if (gPad) {
7376 Double_t x = ((fXlowNDC + 0.5 * fWNDC) * (gPad->GetX2() - gPad->GetX1())) + gPad->GetX1();
7377 Double_t y = ((fYlowNDC + 0.5 * fHNDC) * (gPad->GetY2() - gPad->GetY1())) + gPad->GetY1();
7378 p.SetX(gPad->XtoPixel(x));
7379 p.SetY(gPad->YtoPixel(y));
7380 }
7381 return p;
7382}
7383
7384////////////////////////////////////////////////////////////////////////////////
7385/// Set center of the Pad
7386
7388{
7389 if (!gPad)
7390 return;
7391 fXlowNDC = (gPad->PixeltoX(p.GetX()) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1()) - 0.5 * fWNDC;
7392 fYlowNDC =
7393 (gPad->PixeltoY(p.GetY() - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - 0.5 * fHNDC;
7394 ResizePad();
7395}
7396
7397////////////////////////////////////////////////////////////////////////////////
7398/// Set X coordinate of the center of the Pad
7399
7401{
7402 if (!gPad)
7403 return;
7404 fXlowNDC = (gPad->PixeltoX(x) - gPad->GetX1())/(gPad->GetX2()-gPad->GetX1())-0.5*fWNDC;
7405 ResizePad();
7406}
7407
7408////////////////////////////////////////////////////////////////////////////////
7409/// Set Y coordinate of the center of the Pad
7410
7412{
7413 if (!gPad)
7414 return;
7415 fYlowNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - 0.5 * fHNDC;
7416 ResizePad();
7417}
7418
7419////////////////////////////////////////////////////////////////////////////////
7420/// Set lefthandside of BoundingBox to a value
7421/// (resize in x direction on left)
7422
7424{
7425 if (!gPad)
7426 return;
7427 fXlowNDC = (gPad->PixeltoX(x) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1());
7429 ResizePad();
7430}
7431
7432////////////////////////////////////////////////////////////////////////////////
7433/// Set right hand side of BoundingBox to a value
7434/// (resize in x direction on right)
7435
7437{
7438 if (!gPad)
7439 return;
7440 fWNDC = (gPad->PixeltoX(x) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1()) - fXlowNDC;
7441 ResizePad();
7442}
7443
7444////////////////////////////////////////////////////////////////////////////////
7445/// Set top of BoundingBox to a value (resize in y direction on top)
7446
7448{
7449 if (!gPad)
7450 return;
7451 fHNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - fYlowNDC;
7452 ResizePad();
7453}
7454
7455////////////////////////////////////////////////////////////////////////////////
7456/// Set bottom of BoundingBox to a value
7457/// (resize in y direction on bottom)
7458
7460{
7461 if (!gPad)
7462 return;
7463 fYlowNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1());
7465 ResizePad();
7466}
7467
7468////////////////////////////////////////////////////////////////////////////////
7469/// Mark pad modified
7470/// Will be repainted when TCanvas::Update() will be called next time
7471
7473{
7474 if (!fModified && flag) Emit("Modified()");
7475 fModified = flag;
7476}
7477
7478////////////////////////////////////////////////////////////////////////////////
7479/// Convert absolute pixel into X/Y coordinates
7480
7486
7487
7488////////////////////////////////////////////////////////////////////////////////
7489/// Convert pixel to X coordinate
7490
7492{
7493 if (fAbsCoord) return fAbsPixeltoXk + px*fPixeltoX;
7494 else return fPixeltoXk + px*fPixeltoX;
7495}
7496
7497////////////////////////////////////////////////////////////////////////////////
7498/// Convert pixel to Y coordinate
7499
7501{
7502 if (fAbsCoord) return fAbsPixeltoYk + py*fPixeltoY;
7503 else return fPixeltoYk + py*fPixeltoY;
7504}
7505
7506////////////////////////////////////////////////////////////////////////////////
7507/// Convert pixel to X/Y coordinates
7508
7514
7515////////////////////////////////////////////////////////////////////////////////
7516/// Convert X/Y into absolute pixel coordinates - integer
7517
7523
7524////////////////////////////////////////////////////////////////////////////////
7525/// Check value for valid range for pixel values
7526
7528{
7529 return v < -kMaxPixel ? -kMaxPixel : (v > kMaxPixel ? kMaxPixel : v);
7530}
7531
7532////////////////////////////////////////////////////////////////////////////////
7533/// Convert X/Y into absolute pixel coordinates - doble
7534/// Introduced to avoid pixel rounding problems
7535
7541
7542////////////////////////////////////////////////////////////////////////////////
7543/// Convert X/Y into pixel coordinates - integer
7544
7546{
7547 xpixel = XtoPixel(x);
7548 ypixel = YtoPixel(y);
7549}
7550
7551////////////////////////////////////////////////////////////////////////////////
7552/// Convert X/Y into pixel coordinates - double
7553
7559
7560////////////////////////////////////////////////////////////////////////////////
7561/// Convert X NDC to pixel
7562
7567
7568////////////////////////////////////////////////////////////////////////////////
7569/// Convert Y NDC to pixel
7570
7575
7576////////////////////////////////////////////////////////////////////////////////
7577/// Convert X NDC to absolute pixel
7578
7583
7584////////////////////////////////////////////////////////////////////////////////
7585/// Convert Y NDC to absolute pixel
7586
7591
7592////////////////////////////////////////////////////////////////////////////////
7593/// Convert X coordinate to absolute pixel
7594
7599
7600////////////////////////////////////////////////////////////////////////////////
7601/// Convert X coordinate to pixel
7602
7607
7608////////////////////////////////////////////////////////////////////////////////
7609/// Convert Y coordinate to absolute pixel
7610
7615
7616////////////////////////////////////////////////////////////////////////////////
7617/// Convert a vertical distance [y1,y2] to pixel
7618
7620{
7621 double h1 = fYtoAbsPixelk + y1 * fYtoPixel;
7622 double h2 = fYtoAbsPixelk + y2 * fYtoPixel;
7623 return TMath::Nint(pixel_boundary(std::abs(h1 - h2)));
7624}
7625
7626////////////////////////////////////////////////////////////////////////////////
7627/// Convert a horizontal distance [x1,x2] to pixel
7628
7630{
7631 double w1 = fXtoAbsPixelk + x1 * fXtoPixel;
7632 double w2 = fXtoAbsPixelk + x2 * fXtoPixel;
7633 return TMath::Nint(pixel_boundary(std::abs(w1 - w2)));
7634}
7635
7636
7637////////////////////////////////////////////////////////////////////////////////
7638/// Convert Y coordinate to pixel
7639
EEventType
Definition Buttons.h:15
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton2Down
Definition Buttons.h:17
@ kKeyPress
Definition Buttons.h:20
@ kArrowKeyRelease
Definition Buttons.h:21
@ kButton1Double
Definition Buttons.h:24
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kArrowKeyPress
Definition Buttons.h:21
@ kMouseLeave
Definition Buttons.h:23
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kMouseEnter
Definition Buttons.h:23
@ kMarker
Definition Buttons.h:34
@ kCurlyArc
Definition Buttons.h:38
@ kPad
Definition Buttons.h:30
@ kPolyLine
Definition Buttons.h:28
@ kDiamond
Definition Buttons.h:37
@ kPave
Definition Buttons.h:31
@ kArrow
Definition Buttons.h:33
@ kPaveText
Definition Buttons.h:32
@ kCutG
Definition Buttons.h:38
@ kLine
Definition Buttons.h:33
@ kPavesText
Definition Buttons.h:32
@ kCurlyLine
Definition Buttons.h:38
@ kPaveLabel
Definition Buttons.h:31
@ kButton
Definition Buttons.h:37
@ kEllipse
Definition Buttons.h:32
@ kText
Definition Buttons.h:30
@ kArc
Definition Buttons.h:33
ECursor
Definition GuiTypes.h:373
@ kRightSide
Definition GuiTypes.h:374
@ kBottomSide
Definition GuiTypes.h:374
@ kTopLeft
Definition GuiTypes.h:373
@ kBottomRight
Definition GuiTypes.h:373
@ kTopSide
Definition GuiTypes.h:374
@ kLeftSide
Definition GuiTypes.h:374
@ kMove
Definition GuiTypes.h:375
@ kTopRight
Definition GuiTypes.h:373
@ kBottomLeft
Definition GuiTypes.h:373
@ kHand
Definition GuiTypes.h:375
@ kCross
Definition GuiTypes.h:375
const Int_t kMaxPixel
Max value for an int.
Definition GuiTypes.h:370
#define SafeDelete(p)
Definition RConfig.hxx:531
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
short Style_t
Style number (short)
Definition RtypesCore.h:96
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Color_t
Color number (short)
Definition RtypesCore.h:99
float Size_t
Attribute size (float)
Definition RtypesCore.h:103
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:89
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
short Width_t
Line width (short)
Definition RtypesCore.h:98
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
@ kRed
Definition Rtypes.h:67
@ kBlack
Definition Rtypes.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gDirectory
Definition TDirectory.h:385
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
#define gFile
Definition TFile.h:439
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 cursor
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 SetFillStyle
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 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 np
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 cname
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void SetCursor
Option_t Option_t SetFillColor
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 type
Option_t Option_t style
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t button
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
char name[80]
Definition TGX11.cxx:157
const Int_t kMAXLEVELS
Definition TGeometry.h:27
float xmin
float ymin
float xmax
float ymax
#define gInterpreter
Double_t pixel_boundary(Double_t v)
Check value for valid range for pixel values.
Definition TPad.cxx:7527
static Int_t gReadLevel
Definition TPad.cxx:68
static Bool_t ContainsTImage(TList *li)
Auxiliary function.
Definition TPad.cxx:4930
#define NotFree(i, j)
Definition TPad.cxx:3377
R__EXTERN TPluginManager * gPluginMgr
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:414
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
#define gGLManager
Definition TVirtualGL.h:159
#define R__LOCKGUARD(mutex)
R__EXTERN TVirtualPS * gVirtualPS
Definition TVirtualPS.h:84
#define gPad
R__EXTERN Int_t(* gThreadXAR)(const char *xact, Int_t nb, void **ar, Int_t *iret)
#define snprintf
Definition civetweb.c:1579
Draw all kinds of Arrows.
Definition TArrow.h:29
void Draw(Option_t *option="") override
Draw this arrow with its current attributes.
Definition TArrow.cxx:117
static TClass * Class()
Abstract base class for elements drawn in the editor.
Definition TAttBBox2D.h:19
virtual void Streamer(TBuffer &)
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:32
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:33
virtual void Modify()
Change current fill area attributes if necessary.
Definition TAttFill.cxx:215
Style_t fFillStyle
Fill area style.
Definition TAttFill.h:25
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:40
static TClass * Class()
virtual Bool_t IsTransparent() const
Definition TAttFill.h:49
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:42
virtual void SaveFillAttributes(std::ostream &out, const char *name, Int_t coldef=1, Int_t stydef=1001)
Save fill attributes as C++ statement(s) on output stream out.
Definition TAttFill.cxx:243
virtual void Streamer(TBuffer &)
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:36
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:46
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:38
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:47
static TClass * Class()
Width_t fLineWidth
Line width.
Definition TAttLine.h:26
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:44
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:37
virtual void Modify()
Change current line attributes if necessary.
Definition TAttLine.cxx:246
void Copy(TAttLine &attline) const
Copy this line attributes to a new TAttLine.
Definition TAttLine.cxx:176
static TClass * Class()
virtual void SetBottomMargin(Float_t bottommargin)
Set Pad bottom margin in fraction of the pad height.
Definition TAttPad.cxx:98
Color_t GetFrameFillColor() const
Definition TAttPad.h:53
virtual void SetLeftMargin(Float_t leftmargin)
Set Pad left margin in fraction of the pad width.
Definition TAttPad.cxx:108
Color_t GetFrameLineColor() const
Definition TAttPad.h:54
Style_t GetFrameLineStyle() const
Definition TAttPad.h:56
Float_t fRightMargin
RightMargin.
Definition TAttPad.h:22
Style_t GetFrameFillStyle() const
Definition TAttPad.h:55
Float_t fLeftMargin
LeftMargin.
Definition TAttPad.h:21
Float_t fTopMargin
TopMargin.
Definition TAttPad.h:24
Float_t GetLeftMargin() const
Definition TAttPad.h:44
Width_t GetFrameLineWidth() const
Definition TAttPad.h:57
Float_t GetBottomMargin() const
Definition TAttPad.h:43
virtual void SetRightMargin(Float_t rightmargin)
Set Pad right margin in fraction of the pad width.
Definition TAttPad.cxx:118
Float_t GetRightMargin() const
Definition TAttPad.h:45
Int_t GetFrameBorderMode() const
Definition TAttPad.h:59
virtual void SetTopMargin(Float_t topmargin)
Set Pad top margin in fraction of the pad height.
Definition TAttPad.cxx:128
Width_t GetFrameBorderSize() const
Definition TAttPad.h:58
Float_t fBottomMargin
BottomMargin.
Definition TAttPad.h:23
Float_t GetTopMargin() const
Definition TAttPad.h:46
virtual void Streamer(TBuffer &)
Stream an object of class TAttPad.
Definition TAttPad.cxx:149
virtual Float_t GetTextSize() const
Return the text size.
Definition TAttText.h:39
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:46
virtual Short_t GetTextAlign() const
Return the text alignment.
Definition TAttText.h:35
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:38
virtual Color_t GetTextColor() const
Return the text color.
Definition TAttText.h:37
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:47
virtual Float_t GetTextAngle() const
Return the text angle.
Definition TAttText.h:36
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:48
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:50
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:51
Class to manage histogram axis.
Definition TAxis.h:32
@ kAxisRange
Definition TAxis.h:66
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:422
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
Int_t GetNbins() const
Definition TAxis.h:127
virtual TObject * GetParent() const
Definition TAxis.h:130
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:1061
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
Each class (see TClass) has a linked list of its base class(es).
Definition TBaseClass.h:33
TClass * GetClassPointer(Bool_t load=kTRUE)
Get pointer to the base class TClass.
Create a Box.
Definition TBox.h:22
virtual void SetY2(Double_t y2)
Definition TBox.h:65
static TClass * Class()
virtual void SetX1(Double_t x1)
Definition TBox.h:62
virtual void SetX2(Double_t x2)
Definition TBox.h:63
virtual void SetY1(Double_t y1)
Definition TBox.h:64
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
Buffer base class used for serializing objects.
Definition TBuffer.h:43
A TButton object is a user interface object.
Definition TButton.h:18
static TClass * Class()
ABC describing GUI independent main window (with menubar, scrollbars and a drawing area).
Definition TCanvasImp.h:30
virtual Int_t RequestLocator(Int_t &x, Int_t &y)
Request current mouse pointer, redirect to gVirtualX.
virtual void Warp(Int_t ix, Int_t iy)
Change mouse pointer, redirect to gVirtualX.
The Canvas class.
Definition TCanvas.h:23
UInt_t GetWindowHeight() const
Definition TCanvas.h:164
TObject * GetClickSelected() const
Definition TCanvas.h:144
void ClearPadSave()
Definition TCanvas.h:142
TVirtualPad * GetClickSelectedPad() const
Definition TCanvas.h:149
void SetClickSelectedPad(TPad *pad)
Definition TCanvas.h:213
void SetSelectedPad(TPad *pad)
Definition TCanvas.h:212
void SetDoubleBuffer(Int_t mode=1) override
Set Double Buffer On/Off.
Definition TCanvas.cxx:1970
TCanvasImp * GetCanvasImp() const override
Definition TCanvas.h:160
Bool_t IsRetained() const override
Definition TCanvas.h:178
Int_t GetEventY() const override
Definition TCanvas.h:139
Bool_t IsBatch() const override
Definition TCanvas.h:173
TVirtualPadPainter * GetCanvasPainter()
Access and (probably) creation of pad painter.
Definition TCanvas.cxx:2615
Color_t GetHighLightColor() const override
Definition TCanvas.h:140
Bool_t EnsurePSPainter(Bool_t create, TVirtualPadPainter *&oldp)
Replace canvas painter For intenral use only - when creating PS images.
Definition TCanvas.cxx:2625
Bool_t IsGrayscale()
Check whether this canvas is to be drawn in grayscale mode.
Definition TCanvas.cxx:2566
void SaveSource(const char *filename="", Option_t *option="")
Save primitives in this canvas as a C++ macro file.
Definition TCanvas.cxx:1809
virtual void HandleInput(EEventType button, Int_t x, Int_t y)
Handle Input Events.
Definition TCanvas.cxx:1230
void UpdateAsync() override
Asynchronous pad update.
Definition TCanvas.cxx:2544
TObject * GetSelected() const override
Definition TCanvas.h:143
Int_t GetEventX() const override
Definition TCanvas.h:138
void SetCanvasSize(UInt_t ww, UInt_t wh) override
Set Width and Height of canvas to ww and wh respectively.
Definition TCanvas.cxx:1947
TVirtualPad * GetSelectedPad() const override
Definition TCanvas.h:148
void SetCursor(ECursor cursor) override
Set cursor.
Definition TCanvas.cxx:1961
Int_t GetCanvasID() const override
Definition TCanvas.h:159
UInt_t GetWindowWidth() const
Definition TCanvas.h:163
void FeedbackMode(Bool_t set)
Turn rubberband feedback mode on or off.
Definition TCanvas.cxx:1127
void SetClickSelected(TObject *obj)
Definition TCanvas.h:211
TVirtualPad * GetPadSave() const override
Definition TCanvas.h:141
void Update() override
Update canvas pad buffers.
Definition TCanvas.cxx:2488
virtual void Cleared(TVirtualPad *pad)
Emit pad Cleared signal.
Definition TCanvas.cxx:767
UInt_t GetWw() const override
Definition TCanvas.h:165
Bool_t OpaqueMoving() const override
Definition TCanvas.h:182
UInt_t GetWh() const override
Definition TCanvas.h:166
static TClass * Class()
void SetSelected(TObject *obj) override
Set selected canvas.
Definition TCanvas.cxx:2119
Int_t GetEvent() const override
Definition TCanvas.h:137
Bool_t IsWeb() const override
Is web canvas.
Definition TCanvas.cxx:1491
void SetBatch(Bool_t batch=kTRUE) override
Toggle batch mode.
Definition TCanvas.cxx:1929
Bool_t UseGL() const
Definition TCanvas.h:230
Bool_t OpaqueResizing() const override
Definition TCanvas.h:183
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
TList * GetListOfMethods(Bool_t load=kTRUE)
Return list containing the TMethods of a class.
Definition TClass.cxx:3855
Int_t GetNmethods()
Return the number of methods of this class Note that in case the list of methods is not yet created,...
Definition TClass.cxx:4616
Int_t GetNdata()
Return the number of data members of this class Note that in case the list of data members is not yet...
Definition TClass.cxx:4597
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition TClass.cxx:3813
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3679
void ls(Option_t *option="") const override
List (ls) all objects in this collection.
void Browse(TBrowser *b) override
Browse this collection (called by TBrowser).
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:22
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1926
static TString SavePrimitiveColor(Int_t ci)
Convert color in C++ statement which can be used in SetColor directives Produced statement either inc...
Definition TColor.cxx:2556
static void SetGrayscale(Bool_t set=kTRUE)
Set whether all colors should return grayscale values.
Definition TColor.cxx:2604
static void Pave(Int_t event, Int_t px, Int_t py, Int_t mode)
Create a new pavetext in gPad.
static void Line(Int_t event, Int_t px, Int_t py, Int_t mode)
Create a new line/arrow in this gPad.
static void PolyLine(Int_t event, Int_t px, Int_t py, Int_t mode)
Create a new PolyLine in gPad.
static void Text(Int_t event, Int_t px, Int_t py, Int_t mode)
Create a new TLatex at the cursor position in gPad.
static void Ellipse(Int_t event, Int_t px, Int_t py, Int_t mode)
Create a new arc/ellipse in this gPad.
static void Pad(Int_t event, Int_t px, Int_t py, Int_t)
Create a new pad in gPad.
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition TDatime.h:37
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:503
TExec is a utility class that can be used to execute a C++ command when some event happens in a pad.
Definition TExec.h:26
Define a Frame.
Definition TFrame.h:19
static TClass * Class()
void Paint(Option_t *option="") override
Paint this wbox with its current attributes.
Definition TFrame.cxx:127
void UseCurrentStyle() override
Replace current frame attributes by current style.
Definition TFrame.cxx:157
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
static TClass * Class()
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
@ kIsZoomed
Bit set when zooming on Y axis.
Definition TH1.h:407
static TClass * Class()
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
EImageFileTypes
Definition TImage.h:36
@ kBmp
Definition TImage.h:45
@ kPng
Definition TImage.h:40
@ kJpeg
Definition TImage.h:41
@ kXpm
Definition TImage.h:37
@ kAnimGif
Definition TImage.h:55
@ kUnknown
Definition TImage.h:54
@ kTiff
Definition TImage.h:49
@ kGif
Definition TImage.h:48
static TClass * Class()
Option_t * GetOption() const
This class displays a legend box (TPaveText) containing several legend entries.
Definition TLegend.h:23
Use the TLine constructor to create a simple line.
Definition TLine.h:22
Iterator of linked list.
Definition TList.h:196
Option_t * GetOption() const override
Returns the object option stored in the list.
Definition TList.cxx:1274
A doubly linked list.
Definition TList.h:38
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition TList.cxx:532
virtual TObjLink * LastLink() const
Definition TList.h:110
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void RecursiveRemove(TObject *obj) override
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition TList.cxx:894
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
void AddLast(TObject *obj) override
Add object at the end of the list.
Definition TList.cxx:149
TObject * Last() const override
Return the last object in the list. Returns 0 when list is empty.
Definition TList.cxx:823
virtual TObjLink * FirstLink() const
Definition TList.h:107
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
Each ROOT class (see TClass) has a linked list of methods.
Definition TMethod.h:38
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TH1F * GetHistogram()
Returns a pointer to the histogram used to draw the axis.
static TClass * Class()
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
static TClass * Class()
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:149
Mother of all ROOT objects.
Definition TObject.h:42
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Computes distance from point (px,py) to the object.
Definition TObject.cxx:281
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:459
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:994
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:224
virtual void UseCurrentStyle()
Set current style settings in this object This function is called when either TCanvas::UseCurrentStyl...
Definition TObject.cxx:906
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1081
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:422
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:885
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:546
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1095
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:504
void MakeZombie()
Definition TObject.h:55
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition TObject.cxx:290
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:628
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:76
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:73
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1069
The most important graphics class in the ROOT system.
Definition TPad.h:28
Short_t GetBorderMode() const override
Definition TPad.h:200
Bool_t OpaqueMoving() const override
Is pad moving in opaque mode ?
Definition TPad.cxx:2986
void PaintTextNDC(Double_t u, Double_t v, const char *text) override
Paint text in CurrentPad NDC coordinates.
Definition TPad.cxx:4744
Int_t GetTicky() const override
Definition TPad.h:240
virtual Int_t Clip(Float_t *x, Float_t *y, Float_t xclipl, Float_t yclipb, Float_t xclipr, Float_t yclipt)
Clipping routine: Cohen Sutherland algorithm.
Definition TPad.cxx:774
virtual void HideToolTip(Int_t event)
Hide tool tip depending on the event type.
Definition TPad.cxx:2954
Double_t fAbsYlowNDC
Absolute Y top left corner of pad in NDC [0,1].
Definition TPad.h:70
Double_t fXtoAbsPixelk
Conversion coefficient for X World to absolute pixel.
Definition TPad.h:41
void SetAttMarkerPS(Color_t color, Style_t style, Size_t msize) override
Set postscript marker attributes.
Definition TPad.cxx:6306
virtual void DivideSquare(Int_t n, Float_t xmargin=0.01, Float_t ymargin=0.01, Int_t color=0)
"n" is the total number of sub-pads.
Definition TPad.cxx:1492
void AbsCoordinates(Bool_t set) override
Definition TPad.h:167
static TClass * Class()
Bool_t IsBatch() const override
Is pad in batch mode ?
Definition TPad.cxx:2963
Double_t GetUymax() const override
Returns the maximum y-coordinate value visible on the pad. If log axis the returned value is in decad...
Definition TPad.h:235
void AddExec(const char *name, const char *command) override
Add a new TExec object to the list of Execs.
Definition TPad.cxx:498
Double_t fWNDC
Width of pad along X in Normalized Coordinates (NDC)
Definition TPad.h:66
Int_t NextPaletteColor() override
Get the next autocolor in the pad.
Definition TPad.cxx:3226
Int_t VtoPixel(Double_t v) const override
Convert Y NDC to pixel.
Definition TPad.cxx:7571
void PaintBorder(Color_t color, Bool_t tops)
Paint the pad border.
Definition TPad.cxx:3762
Double_t GetPhi() const override
Definition TPad.h:226
Bool_t IsEditable() const override
Definition TPad.h:273
void FillCollideGrid(TObject *o)
Initialise the grid used to find empty space when adding a box (Legend) in a pad.
Definition TPad.cxx:3242
void SetView(TView *view=nullptr) override
Set the current TView. Delete previous view if view=0.
Definition TPad.cxx:6266
TVirtualViewer3D * GetViewer3D(Option_t *type="") override
Create/obtain handle to 3D viewer.
Definition TPad.cxx:7235
Double_t fPixeltoYk
Conversion coefficient for pixel to Y World.
Definition TPad.h:59
void PaintHatches(Double_t dy, Double_t angle, Int_t nn, Double_t *xx, Double_t *yy)
This routine draw hatches inclined with the angle "angle" and spaced of "dy" in normalized device coo...
Definition TPad.cxx:4211
void PaintLine3D(Float_t *p1, Float_t *p2) override
Paint 3-D line in the CurrentPad.
Definition TPad.cxx:4397
static Int_t fgMaxPickDistance
Maximum Pick Distance.
Definition TPad.h:115
void ResizePad(Option_t *option="") override
Compute pad conversion coefficients.
Definition TPad.cxx:5752
void PaintMarker3D(Double_t x, Double_t y, Double_t z) override
Paint 3-D marker in the CurrentPad.
Definition TPad.cxx:4433
void PaintPolyMarker(Int_t n, Float_t *x, Float_t *y, Option_t *option="") override
Paint polymarker in CurrentPad World coordinates.
Definition TPad.cxx:4586
Double_t fPhi
phi angle to view as lego/surface
Definition TPad.h:80
Double_t fPixeltoY
yworld = fPixeltoYk + fPixeltoY*ypixel
Definition TPad.h:60
virtual void RecordLatex(const TObject *obj)
Emit RecordLatex() signal.
Definition TPad.cxx:7338
Double_t fAbsXlowNDC
Absolute X top left corner of pad in NDC [0,1].
Definition TPad.h:69
Double_t fVtoPixelk
Conversion coefficient for V NDC to pixel.
Definition TPad.h:52
Bool_t fGridx
Set to true if grid along X.
Definition TPad.h:100
TObject * fPadView3D
! 3D View of this TPad
Definition TPad.h:114
void CopyBackgroundPixmaps(TPad *start, TPad *stop, Int_t x, Int_t y)
Copy pixmaps of pads laying below pad "stop" into pad "stop".
Definition TPad.cxx:4054
Double_t GetUxmax() const override
Returns the maximum x-coordinate value visible on the pad. If log axis the returned value is in decad...
Definition TPad.h:233
void Divide(Int_t nx=1, Int_t ny=1, Float_t xmargin=0.01, Float_t ymargin=0.01, Int_t color=0) override
Automatic pad generation by division.
Definition TPad.cxx:1298
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save primitives in this pad on the C++ source file out.
Definition TPad.cxx:5969
Double_t fXtoPixel
xpixel = fXtoPixelk + fXtoPixel*xworld
Definition TPad.h:43
TList * fExecs
List of commands to be executed when a pad event occurs.
Definition TPad.h:108
Double_t PadtoY(Double_t y) const override
Convert y from pad to Y.
Definition TPad.cxx:3659
Int_t fTickx
Set to 1 if tick marks along X.
Definition TPad.h:89
void SetBBoxY1(const Int_t y) override
Set top of BoundingBox to a value (resize in y direction on top)
Definition TPad.cxx:7447
Int_t fTicky
Set to 1 if tick marks along Y.
Definition TPad.h:90
Int_t GetPixmapID() const override
Definition TPad.h:267
Bool_t GetGridx() const override
Definition TPad.h:236
Double_t fX2
X of upper X coordinate.
Definition TPad.h:38
Bool_t PlaceBox(TObject *o, Double_t w, Double_t h, Double_t &xl, Double_t &yb, Option_t *option="lb") override
Place a box in NDC space.
Definition TPad.cxx:3311
void SetLogz(Int_t value=1) override
Set Lin/Log scale for Z.
Definition TPad.cxx:6182
Bool_t fEmbeddedGL
!
Definition TPad.h:87
Int_t UtoAbsPixel(Double_t u) const override
Convert X NDC to absolute pixel.
Definition TPad.cxx:7579
void Browse(TBrowser *b) override
Browse pad.
Definition TPad.cxx:523
Int_t XtoPixel(Double_t x) const override
Convert X coordinate to pixel.
Definition TPad.cxx:7603
void SetAttFillPS(Color_t color, Style_t style) override
Set postscript fill area attributes.
Definition TPad.cxx:6277
Int_t fCGnx
! Size of the collide grid along x
Definition TPad.h:119
void SetBBoxCenterY(const Int_t y) override
Set Y coordinate of the center of the Pad.
Definition TPad.cxx:7411
Double_t fPixeltoX
xworld = fPixeltoXk + fPixeltoX*xpixel
Definition TPad.h:57
void CopyBackgroundPixmap(Int_t x, Int_t y)
Copy pixmap of this pad as background of the current pad.
Definition TPad.cxx:4072
~TPad() override
Pad destructor.
Definition TPad.cxx:379
Bool_t fCopyGLDevice
!
Definition TPad.h:86
Double_t fYtoPixel
ypixel = fYtoPixelk + fYtoPixel*yworld
Definition TPad.h:46
Double_t GetY2() const override
Definition TPad.h:244
void DeleteToolTip(TObject *tip) override
Delete tool tip object.
Definition TPad.cxx:7185
void Close(Option_t *option="") override
Delete all primitives in pad and pad itself.
Definition TPad.cxx:1087
void AbsPixeltoXY(Double_t xpixel, Double_t ypixel, Double_t &x, Double_t &y) override
Convert absolute pixel into X/Y coordinates.
Definition TPad.cxx:7481
Double_t fAbsWNDC
Absolute Width of pad along X in NDC.
Definition TPad.h:71
TObject * Remove(TObject *obj, Bool_t modified=kTRUE) override
Remove object from list of primitives When.
Definition TPad.cxx:5535
UInt_t GetWw() const override
Get Ww.
Definition TPad.cxx:2944
void PaintModified() override
Traverse pad hierarchy and (re)paint only modified pads.
Definition TPad.cxx:3878
void SetEditable(Bool_t mode=kTRUE) override
Set pad editable yes/no If a pad is not editable:
Definition TPad.cxx:6126
const char * GetTitle() const override
Returns title of object.
Definition TPad.h:262
void PaintDate()
Paint the current date and time if the option Date is set on via gStyle->SetOptDate() Paint the curre...
Definition TPad.cxx:3816
static void SetMaxPickDistance(Int_t maxPick=5)
static function to set the maximum Pick Distance fgMaxPickDistance This parameter is used in TPad::Pi...
Definition TPad.cxx:6764
void PixeltoXY(Double_t xpixel, Double_t ypixel, Double_t &x, Double_t &y) override
Convert pixel to X/Y coordinates.
Definition TPad.cxx:7509
void SetBBoxX2(const Int_t x) override
Set right hand side of BoundingBox to a value (resize in x direction on right)
Definition TPad.cxx:7436
void SetBBoxX1(const Int_t x) override
Set lefthandside of BoundingBox to a value (resize in x direction on left)
Definition TPad.cxx:7423
virtual Int_t ClippingCode(Double_t x, Double_t y, Double_t xcl1, Double_t ycl1, Double_t xcl2, Double_t ycl2)
Compute the endpoint codes for TPad::Clip.
Definition TPad.cxx:907
Double_t GetUymin() const override
Returns the minimum y-coordinate value visible on the pad. If log axis the returned value is in decad...
Definition TPad.h:231
Double_t fX1
X of lower X coordinate.
Definition TPad.h:36
TList * GetListOfPrimitives() const override
Definition TPad.h:246
void SetFillStyle(Style_t fstyle) override
Override TAttFill::FillStyle for TPad because we want to handle style=0 as style 4000.
Definition TPad.cxx:6145
Double_t AbsPixeltoY(Double_t py) override
Definition TPad.h:169
TH1F * DrawFrame(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, const char *title="") override
Draw an empty pad frame with X and Y axis.
Definition TPad.cxx:1843
Double_t fVtoPixel
ypixel = fVtoPixelk + fVtoPixel*vndc
Definition TPad.h:53
TCanvasImp * GetCanvasImp() const override
Get canvas implementation pointer if any.
Definition TPad.cxx:2853
Int_t GetEvent() const override
Get Event.
Definition TPad.cxx:2861
Double_t PadtoX(Double_t x) const override
Convert x from pad to X.
Definition TPad.cxx:3650
virtual void DrawCrosshair()
Function called to draw a crosshair in the canvas.
Definition TPad.cxx:1756
Double_t YtoPad(Double_t y) const override
Convert y from Y to pad.
Definition TPad.cxx:3680
virtual void RangeChanged()
Definition TPad.h:321
Double_t fUymin
Minimum value on the Y axis.
Definition TPad.h:75
void SetPad(const char *name, const char *title, Double_t xlow, Double_t ylow, Double_t xup, Double_t yup, Color_t color=35, Short_t bordersize=5, Short_t bordermode=-1) override
Set all pad parameters.
Definition TPad.cxx:6242
void SetCursor(ECursor cursor) override
Set cursor type.
Definition TPad.cxx:3018
Int_t GetCanvasID() const override
Get canvas identifier.
Definition TPad.cxx:2845
Int_t fLogz
(=0 if Z linear scale, =1 if log scale)
Definition TPad.h:93
Int_t HtoAbsPixel(Double_t y1, Double_t y2) const override
Convert a vertical distance [y1,y2] to pixel.
Definition TPad.cxx:7619
void XYtoPixel(Double_t x, Double_t y, Int_t &xpixel, Int_t &ypixel) const override
Convert X/Y into pixel coordinates - integer.
Definition TPad.cxx:7545
Double_t fYtoPixelk
Conversion coefficient for Y World to pixel.
Definition TPad.h:45
void UpdateAsync() override
Asynchronous pad update.
Definition TPad.cxx:3054
TPad()
Pad default constructor.
Definition TPad.cxx:132
void UseCurrentStyle() override
Force a copy of current style for all objects in pad.
Definition TPad.cxx:7011
static Int_t GetMaxPickDistance()
Static function (see also TPad::SetMaxPickDistance)
Definition TPad.cxx:2901
Int_t VtoAbsPixel(Double_t v) const override
Convert Y NDC to absolute pixel.
Definition TPad.cxx:7587
void Range(Double_t x1, Double_t y1, Double_t x2, Double_t y2) override
Set world coordinate system for the pad.
Definition TPad.cxx:5459
Double_t fUtoPixelk
Conversion coefficient for U NDC to pixel.
Definition TPad.h:49
void XYtoAbsPixel(Double_t x, Double_t y, Int_t &xpixel, Int_t &ypixel) const override
Convert X/Y into absolute pixel coordinates - integer.
Definition TPad.cxx:7518
Double_t fPixeltoXk
Conversion coefficient for pixel to X World.
Definition TPad.h:56
Bool_t IsModified() const override
Definition TPad.h:275
Double_t fY1
Y of lower Y coordinate.
Definition TPad.h:37
Int_t GetEventY() const override
Get Y event.
Definition TPad.cxx:2877
Int_t fGLDevice
! OpenGL off-screen pixmap identifier
Definition TPad.h:85
Double_t fYlowNDC
Y bottom left corner of pad in NDC [0,1].
Definition TPad.h:63
TObject * WaitPrimitive(const char *pname="", const char *emode="") override
Loop and sleep until a primitive with name=pname is found in the pad.
Definition TPad.cxx:7131
void SetAttTextPS(Int_t align, Float_t angle, Color_t color, Style_t font, Float_t tsize) override
Set postscript text attributes.
Definition TPad.cxx:6321
Bool_t fModified
Set to true when pad is modified.
Definition TPad.h:99
Double_t PixeltoY(Double_t py) override
Convert pixel to Y coordinate.
Definition TPad.cxx:7500
TLegend * BuildLegend(Double_t x1=0.3, Double_t y1=0.21, Double_t x2=0.3, Double_t y2=0.21, const char *title="", Option_t *option="") override
Build a legend from the graphical objects in the pad.
Definition TPad.cxx:555
virtual TPad * Pick(Int_t px, Int_t py, TObjLink *&pickobj)
Search for an object at pixel position px,py.
Definition TPad.cxx:4780
void Update() override
Update pad.
Definition TPad.cxx:3042
Int_t fNumber
pad number identifier
Definition TPad.h:88
void PaintFillAreaNDC(Int_t n, Double_t *x, Double_t *y, Option_t *option="") override
Paint fill area in CurrentPad NDC coordinates.
Definition TPad.cxx:4128
Double_t fAbsPixeltoXk
Conversion coefficient for absolute pixel to X World.
Definition TPad.h:55
void Clear(Option_t *option="") override
Delete all pad primitives.
Definition TPad.cxx:722
Int_t YtoPixel(Double_t y) const override
Convert Y coordinate to pixel.
Definition TPad.cxx:7640
Int_t GetTickx() const override
Definition TPad.h:239
void PaintLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) override
Paint line in CurrentPad World coordinates.
Definition TPad.cxx:4362
Int_t GetGLDevice() override
Get GL device.
Definition TPad.cxx:7322
Double_t fAspectRatio
ratio of w/h in case of fixed ratio
Definition TPad.h:82
virtual void RecordPave(const TObject *obj)
Emit RecordPave() signal.
Definition TPad.cxx:7330
void PaintBorderPS(Double_t xl, Double_t yl, Double_t xt, Double_t yt, Int_t bmode, Int_t bsize, Int_t dark, Int_t light) override
Paint a frame border with Postscript - no longer used.
Definition TPad.cxx:3806
Double_t fUymax
Maximum value on the Y axis.
Definition TPad.h:77
void SetLogy(Int_t value=1) override
Set Lin/Log scale for Y.
Definition TPad.cxx:6171
virtual Int_t ClipPolygon(Int_t n, Double_t *x, Double_t *y, Int_t nn, Double_t *xc, Double_t *yc, Double_t xclipl, Double_t yclipb, Double_t xclipr, Double_t yclipt)
Clip polygon using the Sutherland-Hodgman algorithm.
Definition TPad.cxx:956
void ExecuteEventAxis(Int_t event, Int_t px, Int_t py, TAxis *axis) override
Execute action corresponding to one event for a TAxis object (called by TAxis::ExecuteEvent....
Definition TPad.cxx:2461
void HighLight(Color_t col=kRed, Bool_t set=kTRUE) override
Highlight pad.
Definition TPad.cxx:3162
Double_t AbsPixeltoX(Double_t px) override
Definition TPad.h:168
void SetBatch(Bool_t batch=kTRUE) override
Set pad in batch mode.
Definition TPad.cxx:3002
TCanvas * fCanvas
! Pointer to mother canvas
Definition TPad.h:106
TVirtualPad * GetMother() const override
Definition TPad.h:260
TVirtualViewer3D * fViewer3D
! Current 3D viewer
Definition TPad.h:123
virtual void x3d(Option_t *type="")
Deprecated: use TPad::GetViewer3D() instead.
Definition TPad.cxx:7217
Bool_t HasCrosshair() const override
Return kTRUE if the crosshair has been activated (via SetCrosshair).
Definition TPad.cxx:6726
Bool_t IsRetained() const override
Is pad retained ?
Definition TPad.cxx:2971
Bool_t Collide(Int_t i, Int_t j, Int_t w, Int_t h)
Check if a box of size w and h collide some primitives in the pad at position i,j.
Definition TPad.cxx:3287
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute distance from point px,py to a box.
Definition TPad.cxx:1194
Bool_t fFixedAspectRatio
True if fixed aspect ratio.
Definition TPad.h:104
void PaintFillArea(Int_t n, Float_t *x, Float_t *y, Option_t *option="") override
Definition TPad.cxx:4082
void Modified(Bool_t flag=true) override
Mark pad modified Will be repainted when TCanvas::Update() will be called next time.
Definition TPad.cxx:7472
void RecursiveRemove(TObject *obj) override
Recursively remove object from a pad and its sub-pads.
Definition TPad.cxx:5517
void DivideRatios(Int_t nrows, Int_t ncolumns, const std::vector< double > &widthRatios={}, const std::vector< double > &heightRatios={}, const double canvasTopMargin=0., const double canvasLeftMargin=0.)
Divide the canvas according to ratios.
Definition TPad.cxx:1397
Bool_t HasFixedAspectRatio() const override
Definition TPad.h:271
void CloseToolTip(TObject *tip) override
Hide tool tip.
Definition TPad.cxx:7207
Double_t GetUxmin() const override
Returns the minimum x-coordinate value visible on the pad. If log axis the returned value is in decad...
Definition TPad.h:229
void SetToolTipText(const char *text, Long_t delayms=1000) override
Set tool tip text associated with this pad.
Definition TPad.cxx:6774
void PaintPolyLine(Int_t n, Float_t *x, Float_t *y, Option_t *option="") override
Paint polyline in CurrentPad World coordinates.
Definition TPad.cxx:4456
Int_t WtoAbsPixel(Double_t x1, Double_t x2) const override
Convert a horizontal distance [x1,x2] to pixel.
Definition TPad.cxx:7629
void ls(Option_t *option="") const override
List all primitives in pad.
Definition TPad.cxx:3198
TView * GetView() const override
Definition TPad.h:255
void ModifiedUpdate() override
Short cut to call Modified() and Update() in a single call.
Definition TPad.cxx:3638
Double_t fVtoAbsPixelk
Conversion coefficient for V NDC to absolute pixel.
Definition TPad.h:51
TVirtualPad * GetPadSave() const override
Get save pad.
Definition TPad.cxx:2927
void SetAttLinePS(Color_t color, Style_t style, Width_t lwidth) override
Set postscript line attributes.
Definition TPad.cxx:6291
TClass * IsA() const override
Definition TPad.h:428
virtual void Resized()
Definition TPad.h:328
TVirtualPad * GetVirtCanvas() const override
Get virtual canvas.
Definition TPad.cxx:2885
void DeleteExec(const char *name) override
Remove TExec name from the list of Execs.
Definition TPad.cxx:1178
void PaintSegments(Int_t n, Double_t *x, Double_t *y, Option_t *option="") override
Paint N individual segments Provided arrays should have 2*n elements IMPORTANT! Provided arrays can b...
Definition TPad.cxx:4650
void Streamer(TBuffer &) override
Stream a class object.
Definition TPad.cxx:6797
void PaintSegmentsNDC(Int_t n, Double_t *u, Double_t *v) override
Paint N individual segments in NDC coordinates Provided arrays should have 2*n elements IMPORTANT!...
Definition TPad.cxx:4691
TString fTitle
Pad title.
Definition TPad.h:110
void CopyPixmaps() override
Copy the sub-pixmaps of the pad to the canvas.
Definition TPad.cxx:1159
void CopyPixmap() override
Copy the pixmap of the pad to the canvas.
Definition TPad.cxx:1146
Double_t GetY1() const override
Definition TPad.h:243
Int_t UtoPixel(Double_t u) const override
Convert X NDC to pixel.
Definition TPad.cxx:7563
TPoint GetBBoxCenter() override
Return the center of the Pad as TPoint in pixels.
Definition TPad.cxx:7372
void FillCollideGridTFrame(TObject *o)
Definition TPad.cxx:3442
Bool_t GetGridy() const override
Definition TPad.h:237
void LineNotFree(Int_t x1, Int_t x2, Int_t y1, Int_t y2)
Mark as "not free" the cells along a line.
Definition TPad.cxx:3382
Double_t fAbsHNDC
Absolute Height of pad along Y in NDC.
Definition TPad.h:72
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute action corresponding to one event.
Definition TPad.cxx:1951
TObject * fTip
! tool tip associated with box
Definition TPad.h:33
void SetCanvasSize(UInt_t ww, UInt_t wh) override
Set canvas size.
Definition TPad.cxx:3010
Int_t GetLogz() const override
Definition TPad.h:259
virtual void AutoExec()
Execute the list of Execs when a pad event occurs.
Definition TPad.cxx:508
Bool_t fAbsCoord
Use absolute coordinates.
Definition TPad.h:102
Int_t fNumPaletteColor
Number of objects with an automatic color.
Definition TPad.h:116
Int_t fCrosshairPos
Position of crosshair.
Definition TPad.h:96
void FillCollideGridTGraph(TObject *o)
Definition TPad.cxx:3468
void SetFixedAspectRatio(Bool_t fixed=kTRUE) override
Fix pad aspect ratio to current value if fixed is true.
Definition TPad.cxx:6102
Short_t GetBorderSize() const override
Definition TPad.h:201
void RedrawAxis(Option_t *option="") override
Redraw the frame axis.
Definition TPad.cxx:5578
void DrawDist(Rectangle_t aBBox, Rectangle_t bBBox, char mode)
Draw Arrows to indicated equal distances of Objects with given BBoxes.
Definition TPad.cxx:6350
Int_t fLogx
(=0 if X linear scale, =1 if log scale)
Definition TPad.h:91
Double_t GetAbsWNDC() const override
Definition TPad.h:223
Int_t YtoAbsPixel(Double_t y) const override
Convert Y coordinate to absolute pixel.
Definition TPad.cxx:7611
Double_t fUtoPixel
xpixel = fUtoPixelk + fUtoPixel*undc
Definition TPad.h:50
Int_t fCrosshair
Crosshair type (0 if no crosshair requested)
Definition TPad.h:95
void PaintFillAreaHatches(Int_t n, Double_t *x, Double_t *y, Int_t FillStyle)
This function paints hatched fill area according to the FillStyle value The convention for the Hatch ...
Definition TPad.cxx:4171
void RangeAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax) override
Set axis coordinate system for the pad.
Definition TPad.cxx:5497
Double_t fUtoAbsPixelk
Conversion coefficient for U NDC to absolute pixel.
Definition TPad.h:48
void ResetToolTip(TObject *tip) override
Reset tool tip, i.e.
Definition TPad.cxx:7196
Double_t GetTheta() const override
Definition TPad.h:227
TList * fPrimitives
->List of primitives (subpads)
Definition TPad.h:107
UInt_t GetWh() const override
Get Wh.
Definition TPad.cxx:2936
TCanvas * GetCanvas() const override
Definition TPad.h:263
Short_t fBorderSize
pad bordersize in pixels
Definition TPad.h:97
void Add(TObject *obj, Option_t *opt="", Bool_t modified=kTRUE) override
Add an object to list of primitives with specified draw option When.
Definition TPad.cxx:418
TView * fView
! Pointer to 3-D view (if one exists)
Definition TPad.h:112
Rectangle_t GetBBox() override
Return the bounding Box of the Pad.
Definition TPad.cxx:7355
void Paint(Option_t *option="") override
Paint all primitives in pad.
Definition TPad.cxx:3692
void FillCollideGridTBox(TObject *o)
Definition TPad.cxx:3425
Double_t fTheta
theta angle to view as lego/surface
Definition TPad.h:79
void DrawCollideGrid()
This method draws the collide grid on top of the canvas.
Definition TPad.cxx:3581
TString fName
Pad name.
Definition TPad.h:109
void SetVertical(Bool_t vert=kTRUE) override
Set pad vertical (default) or horizontal.
Definition TPad.cxx:6788
void FillCollideGridTH1(TObject *o)
Definition TPad.cxx:3499
void GetPadPar(Double_t &xlow, Double_t &ylow, Double_t &xup, Double_t &yup) override
Return lower and upper bounds of the pad in NDC coordinates.
Definition TPad.cxx:3128
void PaintText(Double_t x, Double_t y, const char *text) override
Paint text in CurrentPad World coordinates.
Definition TPad.cxx:4705
Int_t fPadPaint
Set to 1 while painting the pad.
Definition TPad.h:94
static void DrawColorTable()
Static function to Display Color Table in a pad.
Definition TPad.cxx:1888
Double_t GetXlowNDC() const override
Definition TPad.h:213
void SaveAs(const char *filename="", Option_t *option="") const override
Save the pad content in a file.
Definition TPad.cxx:5906
Int_t fPixmapID
! Off-screen pixmap identifier
Definition TPad.h:84
Bool_t fEditable
True if canvas is editable.
Definition TPad.h:103
Double_t GetYlowNDC() const override
Definition TPad.h:214
TObject * FindObject(const char *name) const override
Search if object named name is inside this pad or in pads inside this pad.
Definition TPad.cxx:2807
Color_t GetHighLightColor() const override
Get highlight color.
Definition TPad.cxx:2893
Bool_t OpaqueResizing() const override
Is pad resizing in opaque mode ?
Definition TPad.cxx:2994
Double_t fXUpNDC
Definition TPad.h:64
std::vector< Bool_t > fCollideGrid
! Grid used to find empty space when adding a box (Legend) in a pad
Definition TPad.h:118
TVirtualPad * cd(Int_t subpadnumber=0) override
Set Current pad.
Definition TPad.cxx:693
Int_t GetLogy() const override
Definition TPad.h:258
void PaintLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2) override
Paint line in normalized coordinates.
Definition TPad.cxx:4384
void Print(const char *filename="") const override
This method is equivalent to SaveAs("filename"). See TPad::SaveAs for details.
Definition TPad.cxx:4921
Int_t GetEventX() const override
Get X event.
Definition TPad.cxx:2869
TFrame * GetFrame() override
Get frame.
Definition TPad.cxx:3062
Double_t fYUpNDC
Definition TPad.h:65
Double_t fYtoAbsPixelk
Conversion coefficient for Y World to absolute pixel.
Definition TPad.h:44
Double_t fXtoPixelk
Conversion coefficient for X World to pixel.
Definition TPad.h:42
Int_t fLogy
(=0 if Y linear scale, =1 if log scale)
Definition TPad.h:92
TFrame * fFrame
! Pointer to 2-D frame (if one exists)
Definition TPad.h:111
TVirtualPadPainter * GetPainter() override
Get pad painter from TCanvas.
Definition TPad.cxx:7346
void Draw(Option_t *option="") override
Draw Pad in Current pad (re-parent pad if necessary).
Definition TPad.cxx:1515
virtual void Closed()
Definition TPad.h:184
Double_t fHNDC
Height of pad along Y in Normalized Coordinates (NDC)
Definition TPad.h:67
void ShowGuidelines(TObject *object, const Int_t event, const char mode='i', const bool cling=true) override
Shows lines to indicate if a TAttBBox2D object is aligned to the center or to another object,...
Definition TPad.cxx:6434
Int_t GetCrosshair() const
Return the crosshair type (from the mother canvas) crosshair type = 0 means no crosshair.
Definition TPad.cxx:6735
void GetRangeAxis(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) override
Return pad axis coordinates range.
Definition TPad.cxx:3150
void PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t *option="") override
Paint box in CurrentPad World coordinates.
Definition TPad.cxx:3971
void DrawClassObject(const TObject *obj, Option_t *option="") override
Draw class inheritance tree of the class to which obj belongs.
Definition TPad.cxx:1554
Int_t fCGny
! Size of the collide grid along y
Definition TPad.h:120
Double_t fXlowNDC
X bottom left corner of pad in NDC [0,1].
Definition TPad.h:62
TObject * GetPrimitive(const char *name) const override
Get primitive.
Definition TPad.cxx:3090
Double_t fUxmin
Minimum value on the X axis.
Definition TPad.h:74
Double_t GetAbsHNDC() const override
Definition TPad.h:224
void SetBBoxCenter(const TPoint &p) override
Set center of the Pad.
Definition TPad.cxx:7387
Bool_t IsWeb() const override
Is web ?
Definition TPad.cxx:2978
void SetSelected(TObject *obj) override
Set selected.
Definition TPad.cxx:3034
TObject * GetSelected() const override
Get selected.
Definition TPad.cxx:2909
void GetRange(Double_t &x1, Double_t &y1, Double_t &x2, Double_t &y2) override
Return pad world coordinates range.
Definition TPad.cxx:3139
Double_t PixeltoX(Double_t px) override
Convert pixel to X coordinate.
Definition TPad.cxx:7491
void PaintPolyLineNDC(Int_t n, Double_t *x, Double_t *y, Option_t *option="") override
Paint polyline in CurrentPad NDC coordinates.
Definition TPad.cxx:4556
Bool_t IsVertical() const override
Definition TPad.h:277
Int_t IncrementPaletteColor(Int_t i, TString opt) override
Increment (i==1) or set (i>1) the number of autocolor in the pad.
Definition TPad.cxx:3212
void PaintPadFrame(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax) override
Paint histogram/graph frame.
Definition TPad.cxx:3859
Double_t GetAbsYlowNDC() const override
Definition TPad.h:222
Double_t fUxmax
Maximum value on the X axis.
Definition TPad.h:76
void AddFirst(TObject *obj, Option_t *opt="", Bool_t modified=kTRUE) override
Add an object as first in list of primitives with specified draw option When.
Definition TPad.cxx:439
Double_t fY2
Y of upper Y coordinate.
Definition TPad.h:39
void PaintTextUrl(Double_t x, Double_t y, const char *text, const char *url) override
Paint text with URL in CurrentPad World coordinates.
Definition TPad.cxx:4731
Double_t fAbsPixeltoYk
Conversion coefficient for absolute pixel to Y World.
Definition TPad.h:58
TVirtualPad * GetSelectedPad() const override
Get selected pad.
Definition TPad.cxx:2918
void PaintPolyLine3D(Int_t n, Double_t *p) override
Paint 3-D polyline in the CurrentPad.
Definition TPad.cxx:4572
TVirtualPad * GetPad(Int_t subpadnumber) const override
Get a pointer to subpadnumber of this pad.
Definition TPad.cxx:3107
Short_t fBorderMode
Bordermode (-1=down, 0 = no border, 1=up)
Definition TPad.h:98
void SetLogx(Int_t value=1) override
Set Lin/Log scale for X.
Definition TPad.cxx:6157
void ReleaseViewer3D(Option_t *type="") override
Release current (external) viewer.
Definition TPad.cxx:7306
void SetCrosshair(Int_t crhair=1) override
Set crosshair active/inactive.
Definition TPad.cxx:6748
void SetDoubleBuffer(Int_t mode=1) override
Set double buffer mode ON or OFF.
Definition TPad.cxx:3026
Int_t fNextPaletteColor
Next automatic color.
Definition TPad.h:117
void SetBBoxCenterX(const Int_t x) override
Set X coordinate of the center of the Pad.
Definition TPad.cxx:7400
Int_t GetLogx() const override
Definition TPad.h:257
TObject * fPadPointer
! free pointer
Definition TPad.h:113
Double_t GetX2() const override
Definition TPad.h:242
TObject * CreateToolTip(const TBox *b, const char *text, Long_t delayms) override
Create a tool tip and return its pointer.
Definition TPad.cxx:7175
@ kCannotMove
Fixed position.
Definition TPad.h:158
@ kClearAfterCR
Clear after CR.
Definition TPad.h:159
@ kHori
Pad is horizontal.
Definition TPad.h:155
@ kPrintingPS
PS Printing.
Definition TPad.h:157
@ kFraming
Frame is requested.
Definition TPad.h:154
Double_t GetWNDC() const override
Get width of pad along X in Normalized Coordinates (NDC)
Definition TPad.h:216
void Pop() override
Pop pad to the top of the stack.
Definition TPad.cxx:4899
Double_t GetAbsXlowNDC() const override
Definition TPad.h:221
Double_t GetX1() const override
Definition TPad.h:241
Double_t GetHNDC() const override
Get height of pad along Y in Normalized Coordinates (NDC)
Definition TPad.h:218
TPad * fMother
! pointer to mother of the list
Definition TPad.h:105
const char * GetName() const override
Returns name of object.
Definition TPad.h:261
Int_t XtoAbsPixel(Double_t x) const override
Convert X coordinate to absolute pixel.
Definition TPad.cxx:7595
Bool_t fGridy
Set to true if grid along Y.
Definition TPad.h:101
void SetBBoxY2(const Int_t y) override
Set bottom of BoundingBox to a value (resize in y direction on bottom)
Definition TPad.cxx:7459
Double_t XtoPad(Double_t x) const override
Convert x from X to pad.
Definition TPad.cxx:3668
The histogram statistics painter class.
Definition TPaveStats.h:18
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
virtual TLine * AddLine(Double_t x1=0, Double_t y1=0, Double_t x2=0, Double_t y2=0)
Add a new graphics line to this pavetext.
virtual TBox * AddBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Add a new graphics box to this pavetext.
void Draw(Option_t *option="") override
Draw this pavetext with its current attributes.
Int_t GetBorderSize() const
Definition TPave.h:56
virtual void SetBorderSize(Int_t bordersize=4)
Sets the border size of the TPave box and shadow.
Definition TPave.h:79
static TClass * Class()
TPluginHandler * FindHandler(const char *base, const char *uri=nullptr)
Returns the handler if there exists a handler for the specified URI.
SCoord_t GetY() const
Definition TPoint.h:47
SCoord_t GetX() const
Definition TPoint.h:46
void Emit(const char *signal, const T &arg)
Activate signal with single parameter.
Definition TQObject.h:164
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition TROOT.cxx:2897
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:2905
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2754
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
TString & ReplaceSpecialCppChars()
Find special characters which are typically used in printf() calls and replace them by appropriate es...
Definition TString.cxx:1121
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:703
const char * Data() const
Definition TString.h:384
virtual void Streamer(TBuffer &)
Stream a string object.
Definition TString.cxx:1418
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2384
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2362
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:660
Int_t GetOptLogy() const
Definition TStyle.h:250
void SetPadBorderMode(Int_t mode=1)
Definition TStyle.h:361
void SetPadTopMargin(Float_t margin=0.1)
Definition TStyle.h:363
void SetOptLogx(Int_t logx=1)
Definition TStyle.h:333
void SetPadBottomMargin(Float_t margin=0.1)
Definition TStyle.h:362
Int_t GetOptTitle() const
Definition TStyle.h:248
Int_t GetPadTickX() const
Definition TStyle.h:219
Bool_t IsReading() const
Definition TStyle.h:300
Color_t GetPadColor() const
Definition TStyle.h:210
void SetPadRightMargin(Float_t margin=0.1)
Definition TStyle.h:365
void SetTitleFont(Style_t font=62, Option_t *axis="X")
Definition TStyle.cxx:1776
Float_t GetPadRightMargin() const
Definition TStyle.h:216
void SetTitleBorderSize(Width_t size=2)
Definition TStyle.h:412
Float_t GetDateX() const
Definition TStyle.h:199
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1217
void SetPadTickY(Int_t ticky)
Definition TStyle.h:369
Color_t GetTitleFillColor() const
Definition TStyle.h:273
void SetPadTickX(Int_t tickx)
Definition TStyle.h:368
Int_t GetOptDate() const
Definition TStyle.h:244
Bool_t GetPadGridY() const
Definition TStyle.h:218
void SetPadGridX(Bool_t gridx)
Definition TStyle.h:366
void SetTitleTextColor(Color_t color=1)
Definition TStyle.h:409
Float_t GetPadLeftMargin() const
Definition TStyle.h:215
Double_t GetHatchesSpacing() const
Definition TStyle.h:203
Bool_t GetPadGridX() const
Definition TStyle.h:217
void SetPadLeftMargin(Float_t margin=0.1)
Definition TStyle.h:364
void SetPadGridY(Bool_t gridy)
Definition TStyle.h:367
void SetOptLogy(Int_t logy=1)
Definition TStyle.h:334
Int_t GetOptFile() const
Definition TStyle.h:245
TAttText * GetAttDate()
Definition TStyle.h:170
Int_t GetPadTickY() const
Definition TStyle.h:220
Width_t GetPadBorderSize() const
Definition TStyle.h:211
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
void SetTitleFillColor(Color_t color=1)
Definition TStyle.h:408
Float_t GetPadBottomMargin() const
Definition TStyle.h:213
void SetOptLogz(Int_t logz=1)
Definition TStyle.h:335
void SetPadColor(Color_t color=19)
Definition TStyle.h:359
Color_t GetTitleTextColor() const
Definition TStyle.h:274
Int_t GetOptLogx() const
Definition TStyle.h:249
Float_t GetDateY() const
Definition TStyle.h:200
Int_t GetPadBorderMode() const
Definition TStyle.h:212
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1176
Int_t GetOptLogz() const
Definition TStyle.h:251
void SetPadBorderSize(Width_t size=1)
Definition TStyle.h:360
Int_t GetHatchesLineWidth() const
Definition TStyle.h:202
Float_t GetPadTopMargin() const
Definition TStyle.h:214
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1285
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition TSystem.cxx:651
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1307
virtual int Rename(const char *from, const char *to)
Rename a file.
Definition TSystem.cxx:1361
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:435
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:414
Base class for several text objects.
Definition TText.h:22
void Paint(Option_t *option="") override
Paint this text with its current attributes.
Definition TText.cxx:686
virtual void SetNDC(Bool_t isNDC=kTRUE)
Set NDC mode on if isNDC = kTRUE, off otherwise.
Definition TText.cxx:816
See TView3D.
Definition TView.h:25
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual void ResizePad()=0
virtual void GetRange(Float_t *min, Float_t *max)=0
Provides 3D viewer interface (TVirtualViewer3D) support on a pad.
TVirtualPS is an abstract interface to Postscript, PDF, SVG.
Definition TVirtualPS.h:30
virtual void NewPage()=0
virtual void Open(const char *filename, Int_t type=-111)=0
virtual void DrawFrame(Double_t xl, Double_t yl, Double_t xt, Double_t yt, Int_t mode, Int_t border, Int_t dark, Int_t light)=0
To make it possible to use GL for 2D graphic in a TPad/TCanvas.
virtual void DestroyDrawable(Int_t device)=0
virtual void CopyDrawable(Int_t device, Int_t px, Int_t py)=0
virtual void SaveImage(TVirtualPad *pad, const char *fileName, Int_t type) const =0
virtual void SelectDrawable(Int_t device)=0
virtual void InvalidateCS()
Empty definition.
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
virtual Int_t YtoAbsPixel(Double_t y) const =0
virtual Double_t GetX2() const =0
virtual Int_t XtoAbsPixel(Double_t x) const =0
virtual Double_t GetY1() const =0
void Streamer(TBuffer &) override
Stream an object of class TVirtualPad.
virtual Int_t VtoPixel(Double_t v) const =0
static TClass * Class()
virtual Int_t VtoAbsPixel(Double_t v) const =0
virtual void RangeAxisChanged()
virtual Double_t GetY2() const =0
virtual Int_t UtoPixel(Double_t u) const =0
Bool_t fResizing
!true when resizing the pad
Definition TVirtualPad.h:54
virtual Short_t GetBorderSize() const =0
virtual Bool_t IsEditable() const =0
virtual Double_t GetX1() const =0
Abstract 3D shapes viewer.
virtual Bool_t BuildingScene() const =0
virtual void EndScene()=0
static TVirtualViewer3D * Viewer3D(TVirtualPad *pad=nullptr, Option_t *type="")
Create a Viewer 3D of specified type.
virtual void PadPaint(TVirtualPad *)
virtual void BeginScene()=0
virtual Bool_t CanLoopOnPrimitives() const
A TBox with a bordersize and a bordermode.
Definition TWbox.h:20
Short_t GetBorderSize() const
Definition TWbox.h:41
Short_t GetBorderMode() const
Definition TWbox.h:40
virtual void SetBorderMode(Short_t bordermode)
Definition TWbox.h:54
virtual void SetBorderSize(Short_t bordersize)
Definition TWbox.h:55
TPaveText * pt
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
TGraphErrors * gr
Definition legend1.C:25
Double_t ex[n]
Definition legend1.C:17
TH1F * h1
Definition legend1.C:5
leg
Definition legend1.C:34
R__ALWAYS_INLINE bool HasBeenDeleted(const TObject *obj)
Check if the TObject's memory has been deleted.
Definition TObject.h:409
void CallRecursiveRemoveIfNeeded(TObject &obj)
call RecursiveRemove for obj if gROOT is valid and obj.TestBit(kMustCleanup) is true.
Definition TROOT.h:403
Bool_t IsNaN(Double_t x)
Definition TMath.h:903
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:704
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t Exp(Double_t x)
Returns the base-e exponential function of x, which is e raised to the power x.
Definition TMath.h:720
Double_t Floor(Double_t x)
Rounds x downward, returning the largest integral value that is not greater than x.
Definition TMath.h:691
Double_t Ceil(Double_t x)
Rounds x upward, returning the smallest integral value that is not less than x.
Definition TMath.h:679
Int_t Finite(Double_t x)
Check if it is finite with a mask in order to be consistent in presence of fast math.
Definition TMath.h:781
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:767
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:732
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:605
constexpr Double_t Pi()
Definition TMath.h:40
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:773
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
void inv(rsa_NUMBER *, rsa_NUMBER *, rsa_NUMBER *)
Definition rsaaux.cxx:949
Rectangle structure (maps to the X11 XRectangle structure)
Definition GuiTypes.h:362
Short_t fX
Definition GuiTypes.h:363
UShort_t fHeight
Definition GuiTypes.h:364
Short_t fY
Definition GuiTypes.h:363
UShort_t fWidth
Definition GuiTypes.h:364
struct used by ShowGuidelines to store the distance Field between objects in the canvas.
Definition TPad.cxx:6403
TAttBBox2D * fb
Definition TPad.cxx:6405
dField()
Definition TPad.cxx:6410
char fdir
Definition TPad.cxx:6407
dField(TAttBBox2D *a, TAttBBox2D *b, Int_t dist, char direction)
Definition TPad.cxx:6414
TAttBBox2D * fa
Definition TPad.cxx:6404
Int_t fdist
Definition TPad.cxx:6406
TMarker m
Definition textangle.C:8