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 TAttFill att = pp->GetAttFill();
3980
3981 Int_t style0 = -1111, style = att.GetFillStyle();
3983 if (option && *option == 's') {
3984 style0 = style;
3985 att.SetFillStyle(0);
3986 pp->SetAttFill(att);
3987 style = 0;
3989 } else if (option && *option == 'l')
3991
3992 if (style >= 3100 && style < 4000) {
3993 Double_t xb[4] = {x1, x1, x2, x2};
3994 Double_t yb[4] = {y1, y2, y2, y1};
3996 } else if (pp->GetPS()) {
3997 draw_fill = kTRUE;
3998 if (style == 0)
4000 } else if ((style > 0) && (style < 1000)) {
4002 } else if ((style >= 1000) && (style < 2000)) {
4003 draw_fill = kTRUE;
4004 } else if (style > 3000 && style < 3100) {
4005 if (style < 3026)
4006 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
4007 //special case for TAttFillCanvas on real display
4008 if (att.GetFillColor() == 10) {
4009 // SL: reproduce old sequence of painting calls, can have some side effects on opaque pads
4010 att.SetFillColor(1);
4011 pp->SetAttFill(att);
4012 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
4013 att.SetFillColor(10);
4014 pp->SetAttFill(att);
4015 }
4016 } else if (style >= 4000 && style <= 4100) {
4017 // For style >=4000 we make the window transparent.
4018 // From 4000 to 4100 the window is 100% transparent to 100% opaque
4019
4020 //ignore this style option when this is the canvas itself
4021 if (this == fMother) {
4022 //It's clear, that virtual X checks a style (4000) and will render a hollow rect!
4023 if (pp->IsCocoa()) {
4024 style0 = style;
4025 att.SetFillStyle(1000);
4026 pp->SetAttFill(att);
4027 }
4028 draw_fill = kTRUE;
4029 } else {
4030 //draw background by blitting all bottom pads
4031 int px, py;
4032 XYtoAbsPixel(fX1, fY2, px, py);
4033
4034 if (fMother) {
4036 CopyBackgroundPixmaps(fMother, this, px, py);
4037 }
4038
4039 pp->SetOpacity(style - 4000);
4040 }
4041 } else if (style > 0)
4043
4044 if (draw_fill)
4045 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
4046
4047 if (draw_border)
4048 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow);
4049
4050 if (style0 != -1111) {
4051 att.SetFillStyle(style0);
4052 pp->SetAttFill(att);
4053 }
4054
4055 Modified();
4056}
4057
4058////////////////////////////////////////////////////////////////////////////////
4059/// Copy pixmaps of pads laying below pad "stop" into pad "stop". This
4060/// gives the effect of pad "stop" being transparent.
4061
4063{
4064 if (!start) return;
4065 TObject *obj;
4066 if (!fPrimitives) fPrimitives = new TList;
4067 TIter next(start->GetListOfPrimitives());
4068 while ((obj = next())) {
4069 if (obj->InheritsFrom(TPad::Class())) {
4070 if (obj == stop) break;
4071 ((TPad*)obj)->CopyBackgroundPixmap(x, y);
4072 ((TPad*)obj)->CopyBackgroundPixmaps((TPad*)obj, stop, x, y);
4073 }
4074 }
4075}
4076
4077////////////////////////////////////////////////////////////////////////////////
4078/// Copy pixmap of this pad as background of the current pad.
4079
4081{
4082 int px, py;
4083 XYtoAbsPixel(fX1, fY2, px, py);
4084 if (GetPainter())
4085 GetPainter()->CopyDrawable(GetPixmapID(), px-x, py-y);
4086}
4087
4088////////////////////////////////////////////////////////////////////////////////
4089
4091{
4092 Warning("TPad::PaintFillArea", "Float_t signature is obsolete. Use Double_t signature.");
4093}
4094
4095////////////////////////////////////////////////////////////////////////////////
4096/// Paint fill area in CurrentPad World coordinates.
4097
4099{
4100 if (nn < 3)
4101 return;
4105 } else {
4106 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4107 }
4108
4109 Int_t nc = 2*nn+1;
4110 std::vector<Double_t> x(nc, 0.);
4111 std::vector<Double_t> y(nc, 0.);
4112
4113 Int_t n = ClipPolygon(nn, xx, yy, nc, x.data(), y.data(), xmin, ymin, xmax, ymax);
4114 if (!n)
4115 return;
4116
4117 auto pp = GetPainter();
4118 if (!pp)
4119 return;
4120
4121 pp->OnPad(this);
4122
4123 // Paint the fill area with hatches
4124 Int_t fillstyle = pp->GetFillStyle();
4125 if (fillstyle >= 3100 && fillstyle < 4000)
4126 PaintFillAreaHatches(nn, x.data(), y.data(), fillstyle);
4127 else
4128 pp->DrawFillArea(n, x.data(), y.data());
4129
4130 Modified();
4131}
4132
4133////////////////////////////////////////////////////////////////////////////////
4134/// Paint fill area in CurrentPad NDC coordinates.
4135
4137{
4138 std::vector<Double_t> xw(n), yw(n);
4139 for (int i=0; i<n; i++) {
4140 xw[i] = fX1 + x[i]*(fX2 - fX1);
4141 yw[i] = fY1 + y[i]*(fY2 - fY1);
4142 }
4143 PaintFillArea(n, xw.data(), yw.data(), option);
4144}
4145
4146////////////////////////////////////////////////////////////////////////////////
4147/// This function paints hatched fill area according to the FillStyle value
4148/// The convention for the Hatch is the following:
4149///
4150/// `FillStyle = 3ijk`
4151///
4152/// - i (1-9) : specify the space between each hatch
4153/// 1 = minimum 9 = maximum
4154/// the final spacing is i*GetHatchesSpacing(). The hatches spacing
4155/// is set by SetHatchesSpacing()
4156/// - j (0-9) : specify angle between 0 and 90 degrees
4157/// * 0 = 0
4158/// * 1 = 10
4159/// * 2 = 20
4160/// * 3 = 30
4161/// * 4 = 45
4162/// * 5 = Not drawn
4163/// * 6 = 60
4164/// * 7 = 70
4165/// * 8 = 80
4166/// * 9 = 90
4167/// - k (0-9) : specify angle between 90 and 180 degrees
4168/// * 0 = 180
4169/// * 1 = 170
4170/// * 2 = 160
4171/// * 3 = 150
4172/// * 4 = 135
4173/// * 5 = Not drawn
4174/// * 6 = 120
4175/// * 7 = 110
4176/// * 8 = 100
4177/// * 9 = 90
4178
4180{
4181 static Double_t ang1[10] = { 0., 10., 20., 30., 45.,5., 60., 70., 80., 89.99};
4182 static Double_t ang2[10] = {180.,170.,160.,150.,135.,5.,120.,110.,100., 89.99};
4183
4184 Int_t fasi = FillStyle % 1000;
4185 Int_t idSPA = fasi / 100;
4186 Int_t iAng2 = (fasi - 100 * idSPA) / 10;
4187 Int_t iAng1 = fasi % 10;
4188 Double_t dy = 0.003 * idSPA * gStyle->GetHatchesSpacing();
4190 auto pp = GetPainter();
4191 if (!pp)
4192 return;
4193
4194 // Save the current line attributes and change to draw hatches
4195 TAttLine saveatt = pp->GetAttLine();
4196
4197 pp->SetAttLine({ pp->GetAttFill().GetFillColor(), 1, lw });
4198
4199 // Draw the hatches
4200 if (ang1[iAng1] != 5.)
4202 if (ang2[iAng2] != 5.)
4204
4205 pp->SetAttLine(saveatt);
4206}
4207
4208////////////////////////////////////////////////////////////////////////////////
4209/// This routine draw hatches inclined with the
4210/// angle "angle" and spaced of "dy" in normalized device
4211/// coordinates in the surface defined by n,xx,yy.
4212
4215{
4216 Int_t i, i1, i2, nbi;
4218 const Double_t angr = TMath::Pi()*(180.-angle)/180.;
4219 const Double_t epsil = 0.0001;
4220
4221 std::vector<Double_t> xli;
4222 std::vector<Double_t> yli;
4223
4224 Double_t xt1, xt2, yt1, yt2;
4225 Double_t x, y, x1, x2, y1, y2, a, b, xi, xip, xin, yi, yip;
4226
4227 Double_t rwxmin = gPad->GetX1();
4228 Double_t rwxmax = gPad->GetX2();
4229 Double_t rwymin = gPad->GetY1();
4230 Double_t rwymax = gPad->GetY2();
4231 ratiox = 1./(rwxmax-rwxmin);
4232 ratioy = 1./(rwymax-rwymin);
4233
4236 if (TMath::Abs(cosa) <= epsil) cosa=0.;
4237 if (TMath::Abs(sina) <= epsil) sina=0.;
4238 sinb = -sina;
4239 cosb = cosa;
4240
4241 // Values needed to compute the hatches in TRUE normalized space (NDC)
4242 Int_t iw = (Int_t)gPad->GetWw();
4243 Int_t ih = (Int_t)gPad->GetWh();
4245 gPad->GetPadPar(x1p,y1p,x2p,y2p);
4246 iw = (Int_t)(iw*x2p)-(Int_t)(iw*x1p);
4247 ih = (Int_t)(ih*y2p)-(Int_t)(ih*y1p);
4250
4251 // Search ymin and ymax
4252 ymin = 1.;
4253 ymax = 0.;
4254 for (i=1; i<=nn; i++) {
4255 x = wndc*ratiox*(xx[i-1]-rwxmin);
4256 y = hndc*ratioy*(yy[i-1]-rwymin);
4257 yrot = sina*x+cosa*y;
4258 if (yrot > ymax) ymax = yrot;
4259 if (yrot < ymin) ymin = yrot;
4260 }
4261
4262 Int_t yindx = (Int_t) (ymax/dy);
4263
4264 while (dy * yindx >= ymin) {
4265 ycur = dy * yindx--;
4266 nbi = 0;
4267
4268 xli.clear();
4269 yli.clear();
4270
4271 for (i=2; i<=nn+1; i++) {
4272 i2 = i;
4273 i1 = i-1;
4274 if (i == nn+1) i2=1;
4275
4276 x1 = wndc*ratiox*(xx[i1-1]-rwxmin);
4277 y1 = hndc*ratioy*(yy[i1-1]-rwymin);
4278 x2 = wndc*ratiox*(xx[i2-1]-rwxmin);
4279 y2 = hndc*ratioy*(yy[i2-1]-rwymin);
4280
4281 xt1 = cosa*x1-sina*y1;
4282 yt1 = sina*x1+cosa*y1;
4283 xt2 = cosa*x2-sina*y2;
4284 yt2 = sina*x2+cosa*y2;
4285
4286 // Line segment parallel to oy
4287 if (xt1 == xt2) {
4288 if (yt1 < yt2) {
4289 yi = yt1;
4290 yip = yt2;
4291 } else {
4292 yi = yt2;
4293 yip = yt1;
4294 }
4295 if ((yi <= ycur) && (ycur < yip)) {
4296 nbi++;
4297 xli.push_back(xt1);
4298 }
4299 continue;
4300 }
4301
4302 // Line segment parallel to ox
4303 if (yt1 == yt2) {
4304 if (yt1 == ycur) {
4305 nbi++;
4306 xli.push_back(xt1);
4307 nbi++;
4308 xli.push_back(xt2);
4309 }
4310 continue;
4311 }
4312
4313 // Other line segment
4314 a = (yt1-yt2)/(xt1-xt2);
4315 b = (yt2*xt1-xt2*yt1)/(xt1-xt2);
4316
4317 if (xt1 < xt2) {
4318 xi = xt1;
4319 xip = xt2;
4320 } else {
4321 xi = xt2;
4322 xip = xt1;
4323 }
4324
4325 xin = (ycur-b)/a;
4326
4327 if ((xi <= xin) && (xin < xip) &&
4328 (TMath::Min(yt1,yt2) <= ycur) &&
4329 (ycur < TMath::Max(yt1,yt2))) {
4330 nbi++;
4331 xli.push_back(xin);
4332 }
4333 }
4334
4335 // Sorting of the x coordinates intersections
4336 std::sort(xli.begin(), xli.end());
4337
4338 // Draw the hatches
4339 if ((nbi%2 != 0) || (nbi == 0))
4340 continue;
4341
4342 for (i=0; i<nbi; ++i) {
4343 // Rotate back the hatches - first calculate y coordinate
4344 Double_t ytmp = sinb*xli[i] + cosb*ycur;
4345 xli[i] = cosb*xli[i] - sinb*ycur;
4346 // Convert hatches' positions from true NDC to WC to handle cliping
4347 xli[i] = (xli[i]/wndc)*(rwxmax-rwxmin)+rwxmin;
4349 yli.push_back(ytmp);
4350 }
4351
4352 gPad->PaintSegments(nbi/2, xli.data(), yli.data());
4353 }
4354}
4355
4356////////////////////////////////////////////////////////////////////////////////
4357/// Paint line in CurrentPad World coordinates.
4358
4360{
4361 Double_t x[2] = {x1, x2}, y[2] = {y1, y2};
4362
4363 //If line is totally clipped, return
4365 if (Clip(x,y,fUxmin,fUymin,fUxmax,fUymax) == 2) return;
4366 } else {
4367 if (Clip(x,y,fX1,fY1,fX2,fY2) == 2) return;
4368 }
4369
4370 if (auto pp = GetPainter()) {
4371 pp->OnPad(this);
4372 pp->DrawLine(x[0], y[0], x[1], y[1]);
4373 }
4374
4375 Modified();
4376}
4377
4378////////////////////////////////////////////////////////////////////////////////
4379/// Paint line in normalized coordinates.
4380
4382{
4383 if (auto pp = GetPainter()) {
4384 pp->OnPad(this);
4385 pp->DrawLineNDC(u1, v1, u2, v2);
4386 }
4387
4388 Modified();
4389}
4390
4391////////////////////////////////////////////////////////////////////////////////
4392/// Paint 3-D line in the CurrentPad.
4393
4395{
4396 if (!fView) return;
4397
4398 // convert from 3-D to 2-D pad coordinate system
4399 Double_t xpad[6];
4400 Double_t temp[3];
4401 Int_t i;
4402 for (i=0;i<3;i++) temp[i] = p1[i];
4403 fView->WCtoNDC(temp, &xpad[0]);
4404 for (i=0;i<3;i++) temp[i] = p2[i];
4405 fView->WCtoNDC(temp, &xpad[3]);
4406 PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
4407}
4408
4409////////////////////////////////////////////////////////////////////////////////
4410/// Paint 3-D line in the CurrentPad.
4411
4413{
4414 if (!fView) return;
4415
4416 // convert from 3-D to 2-D pad coordinate system
4417 Double_t xpad[6];
4418 Double_t temp[3];
4419 Int_t i;
4420 for (i=0;i<3;i++) temp[i] = p1[i];
4421 fView->WCtoNDC(temp, &xpad[0]);
4422 for (i=0;i<3;i++) temp[i] = p2[i];
4423 fView->WCtoNDC(temp, &xpad[3]);
4424 PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
4425}
4426
4427////////////////////////////////////////////////////////////////////////////////
4428/// Paint 3-D marker in the CurrentPad.
4429
4431{
4432 if (!fView) return;
4433
4434 Double_t rmin[3], rmax[3];
4436
4437 // convert from 3-D to 2-D pad coordinate system
4438 Double_t xpad[3];
4439 Double_t temp[3];
4440 temp[0] = x;
4441 temp[1] = y;
4442 temp[2] = z;
4443 if (x<rmin[0] || x>rmax[0]) return;
4444 if (y<rmin[1] || y>rmax[1]) return;
4445 if (z<rmin[2] || z>rmax[2]) return;
4446 fView->WCtoNDC(temp, &xpad[0]);
4447 PaintPolyMarker(1, &xpad[0], &xpad[1]);
4448}
4449
4450////////////////////////////////////////////////////////////////////////////////
4451/// Paint polyline in CurrentPad World coordinates.
4452
4454{
4455 if (n < 2) return;
4456
4460 } else {
4461 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4462 }
4463 Int_t i, i1=-1,np=1;
4464 for (i=0; i<n-1; i++) {
4465 Double_t x1=x[i];
4466 Double_t y1=y[i];
4467 Double_t x2=x[i+1];
4468 Double_t y2=y[i+1];
4469 Int_t iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4470 if (iclip == 2) {
4471 i1 = -1;
4472 continue;
4473 }
4474 np++;
4475 if (i1 < 0)
4476 i1 = i;
4477 if (iclip == 0 && i < n-2)
4478 continue;
4479 if (auto pp = GetPainter()) {
4480 pp->OnPad(this);
4481 pp->DrawPolyLine(np, &x[i1], &y[i1]);
4482 }
4483 if (iclip) {
4484 x[i] = x1;
4485 y[i] = y1;
4486 x[i+1] = x2;
4487 y[i+1] = y2;
4488 }
4489 i1 = -1;
4490 np = 1;
4491 }
4492
4493 Modified();
4494}
4495
4496////////////////////////////////////////////////////////////////////////////////
4497/// Paint polyline in CurrentPad World coordinates.
4498///
4499/// If option[0] == 'C' no clipping
4500
4502{
4503 if (n < 2) return;
4504
4509 } else {
4510 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4511 if (option && (option[0] == 'C')) mustClip = kFALSE;
4512 }
4513
4514 Int_t i, i1=-1, np = 1, iclip = 0;
4515
4516 for (i=0; i < n-1; i++) {
4517 Double_t x1 = x[i];
4518 Double_t y1 = y[i];
4519 Double_t x2 = x[i+1];
4520 Double_t y2 = y[i+1];
4521 if (mustClip) {
4522 iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4523 if (iclip == 2) {
4524 i1 = -1;
4525 continue;
4526 }
4527 }
4528 np++;
4529 if (i1 < 0)
4530 i1 = i;
4531 if (iclip == 0 && i < n-2)
4532 continue;
4533 if (auto pp = GetPainter()) {
4534 pp->OnPad(this);
4535 pp->DrawPolyLine(np, &x[i1], &y[i1]);
4536 }
4537 if (iclip) {
4538 x[i] = x1;
4539 y[i] = y1;
4540 x[i+1] = x2;
4541 y[i+1] = y2;
4542 }
4543 i1 = -1;
4544 np = 1;
4545 }
4546
4547 Modified();
4548}
4549
4550////////////////////////////////////////////////////////////////////////////////
4551/// Paint polyline in CurrentPad NDC coordinates.
4552
4554{
4555 if (n <= 0)
4556 return;
4557
4558 if (auto pp = GetPainter()) {
4559 pp->OnPad(this);
4560 pp->DrawPolyLineNDC(n, x, y);
4561 }
4562
4563 Modified();
4564}
4565
4566////////////////////////////////////////////////////////////////////////////////
4567/// Paint 3-D polyline in the CurrentPad.
4568
4570{
4571 if (!fView) return;
4572
4573 // Loop on each individual line
4574 for (Int_t i = 1; i < n; i++)
4575 PaintLine3D(&p[3*i-3], &p[3*i]);
4576
4577 Modified();
4578}
4579
4580////////////////////////////////////////////////////////////////////////////////
4581/// Paint polymarker in CurrentPad World coordinates.
4582
4584{
4585 Int_t n = TMath::Abs(nn);
4587 if (nn > 0 || TestBit(TGraph::kClipFrame)) {
4589 } else {
4590 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4591 }
4592 Int_t i,i1=-1,np=0;
4593 for (i=0; i<n; i++) {
4594 if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
4595 np++;
4596 if (i1 < 0) i1 = i;
4597 if (i < n-1) continue;
4598 }
4599 if (np == 0)
4600 continue;
4601 if (auto pp = GetPainter()) {
4602 pp->OnPad(this);
4603 pp->DrawPolyMarker(np, &x[i1], &y[i1]);
4604 }
4605 i1 = -1;
4606 np = 0;
4607 }
4608 Modified();
4609}
4610
4611////////////////////////////////////////////////////////////////////////////////
4612/// Paint polymarker in CurrentPad World coordinates.
4613
4615{
4616 Int_t n = TMath::Abs(nn);
4618 if (nn > 0 || TestBit(TGraph::kClipFrame)) {
4620 } else {
4621 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4622 }
4623 Int_t i,i1=-1,np=0;
4624 for (i=0; i<n; i++) {
4625 if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
4626 np++;
4627 if (i1 < 0) i1 = i;
4628 if (i < n-1) continue;
4629 }
4630 if (np == 0)
4631 continue;
4632 if (auto pp = GetPainter()) {
4633 pp->OnPad(this);
4634 pp->DrawPolyMarker(np, &x[i1], &y[i1]);
4635 }
4636 i1 = -1;
4637 np = 0;
4638 }
4639 Modified();
4640}
4641
4642////////////////////////////////////////////////////////////////////////////////
4643/// Paint N individual segments
4644/// Provided arrays should have 2*n elements
4645/// IMPORTANT! Provided arrays can be modified after function call!
4646
4648{
4649 if (n < 1)
4650 return;
4651
4656 } else {
4657 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4658 if (option && *option == 'C') mustClip = kFALSE;
4659 }
4660
4661 if (!mustClip)
4662 isAny = kTRUE;
4663 else {
4664 for (Int_t i = 0; i < 2*n; i+=2) {
4665 Int_t iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4666 if (iclip == 2)
4667 x[i] = y[i] = x[i+1] = y[i+1] = 0;
4668 else
4669 isAny = kTRUE;
4670 }
4671 }
4672
4673 if (isAny)
4674 if (auto pp = GetPainter()) {
4675 pp->OnPad(this);
4676 pp->DrawSegments(n, x, y);
4677 }
4678
4679 Modified();
4680}
4681
4682
4683////////////////////////////////////////////////////////////////////////////////
4684/// Paint N individual segments in NDC coordinates
4685/// Provided arrays should have 2*n elements
4686/// IMPORTANT! Provided arrays can be modified after function call!
4687
4689{
4690 if (auto pp = GetPainter()) {
4691 pp->OnPad(this);
4692 pp->DrawSegmentsNDC(n, u, v);
4693 }
4694
4695 Modified();
4696}
4697
4698
4699////////////////////////////////////////////////////////////////////////////////
4700/// Paint text in CurrentPad World coordinates.
4701
4703{
4704 Modified();
4705
4706 if (auto pp = GetPainter()) {
4707 pp->OnPad(this);
4708 pp->DrawText(x, y, text, TVirtualPadPainter::kClear);
4709 }
4710}
4711
4712////////////////////////////////////////////////////////////////////////////////
4713/// Paint text in CurrentPad World coordinates.
4714
4715void TPad::PaintText(Double_t x, Double_t y, const wchar_t *text)
4716{
4717 Modified();
4718
4719 if (auto pp = GetPainter()) {
4720 pp->OnPad(this);
4721 pp->DrawText(x, y, text, TVirtualPadPainter::kClear);
4722 }
4723}
4724
4725////////////////////////////////////////////////////////////////////////////////
4726/// Paint text with URL in CurrentPad World coordinates.
4727
4728void TPad::PaintTextUrl(Double_t x, Double_t y, const char *text, const char *url)
4729{
4730 Modified();
4731
4732 if (auto pp = GetPainter()) {
4733 pp->OnPad(this);
4734 pp->DrawTextUrl(x, y, text, url);
4735 }
4736}
4737
4738////////////////////////////////////////////////////////////////////////////////
4739/// Paint text in CurrentPad NDC coordinates.
4740
4742{
4743 Modified();
4744
4745 if (auto pp = GetPainter()) {
4746 pp->OnPad(this);
4747 pp->DrawTextNDC(u, v, text, TVirtualPadPainter::kClear);
4748 }
4749}
4750
4751////////////////////////////////////////////////////////////////////////////////
4752/// Paint text in CurrentPad NDC coordinates.
4753
4755{
4756 Modified();
4757
4758 if (auto pp = GetPainter()) {
4759 pp->OnPad(this);
4760 pp->DrawTextNDC(u, v, text, TVirtualPadPainter::kClear);
4761 }
4762}
4763
4764////////////////////////////////////////////////////////////////////////////////
4765/// Search for an object at pixel position px,py.
4766///
4767/// Check if point is in this pad.
4768///
4769/// If yes, check if it is in one of the sub-pads
4770///
4771/// If found in the pad, compute closest distance of approach
4772/// to each primitive.
4773///
4774/// If one distance of approach is found to be within the limit Distancemaximum
4775/// the corresponding primitive is selected and the routine returns.
4776
4778{
4779 //the two following statements are necessary under NT (multithreaded)
4780 //when a TCanvas object is being created and a thread calling TPad::Pick
4781 //before the TPad constructor has completed in the other thread
4782 if (!gPad) return nullptr; //Andy Haas
4783 if (!GetListOfPrimitives()) return nullptr; //Andy Haas
4784
4785 Int_t dist;
4786 // Search if point is in pad itself
4787 Double_t x = AbsPixeltoX(px);
4788 Double_t y = AbsPixeltoY(py);
4789 if (this != gPad->GetCanvas()) {
4790 if (!((x >= fX1 && x <= fX2) && (y >= fY1 && y <= fY2))) return nullptr;
4791 }
4792
4793 // search for a primitive in this pad or its sub-pads
4794 static TObjOptLink dummyLink(nullptr,""); //place holder for when no link available
4795
4796 TContext ctxt(this, kFALSE); // since no drawing will be done, don't use cd() for efficiency reasons
4797
4798 TPad *pick = nullptr;
4799 TPad *picked = this;
4800 pickobj = nullptr;
4802 dummyLink.SetObject(this);
4803 pickobj = &dummyLink;
4804 }
4805
4806 // Loop backwards over the list of primitives. The first non-pad primitive
4807 // found is the selected one. However, we have to keep going down the
4808 // list to see if there is maybe a pad overlaying the primitive. In that
4809 // case look into the pad for a possible primitive. Once a pad has been
4810 // found we can terminate the loop.
4811 Bool_t gotPrim = kFALSE; // true if found a non pad primitive
4813
4814 //We can have 3d stuff in pad. If canvas prefers to draw
4815 //such stuff with OpenGL, the selection of 3d objects is
4816 //a gl viewer business so, in first cycle we do not
4817 //call DistancetoPrimitive for TAtt3D descendants.
4818 //In case of gl we first try to select 2d object first.
4819
4820 while (lnk) {
4821 TObject *obj = lnk->GetObject();
4822
4823 //If canvas prefers GL, all 3d objects must be drawn/selected by
4824 //gl viewer
4825 if (obj->InheritsFrom(TAtt3D::Class()) && fEmbeddedGL) {
4826 lnk = lnk->Prev();
4827 continue;
4828 }
4829
4830 fPadPointer = obj;
4831 if (obj->InheritsFrom(TPad::Class())) {
4832 pick = ((TPad*)obj)->Pick(px, py, pickobj);
4833 if (pick) {
4834 picked = pick;
4835 break;
4836 }
4837 } else if (!gROOT->GetEditorMode()) {
4838 if (!gotPrim) {
4839 if (!obj->TestBit(kCannotPick)) {
4840 dist = obj->DistancetoPrimitive(px, py);
4841 if (dist < fgMaxPickDistance) {
4842 pickobj = lnk;
4843 gotPrim = kTRUE;
4844 if (dist == 0) break;
4845 }
4846 }
4847 }
4848 }
4849
4850 lnk = lnk->Prev();
4851 }
4852
4853 //if no primitive found, check if we have a TView
4854 //if yes, return the view except if you are in the lower or upper X range
4855 //of the pad.
4856 //In case canvas prefers gl, fView existence
4857 //automatically means viewer3d existence. (?)
4858
4859 if (fView && !gotPrim) {
4860 Double_t dx = 0.05*(fUxmax-fUxmin);
4861 if ((x > fUxmin + dx) && (x < fUxmax-dx)) {
4862
4863 if (fEmbeddedGL) {
4864 //No 2d stuff was selected, but we have gl-viewer. Let it select an object in
4865 //scene (or select itself). In any case it'll internally call
4866 //gPad->SetSelected(ptr) as, for example, hist painter does.
4867 py -= Int_t((1 - GetHNDC() - GetYlowNDC()) * GetWh());
4868 px -= Int_t(GetXlowNDC() * GetWw());
4870 }
4871 else
4872 dummyLink.SetObject(fView);
4873 }
4874 }
4875
4876 if (picked->InheritsFrom(TButton::Class())) {
4878 if (!button->IsEditable()) pickobj = nullptr;
4879 }
4880
4881 if (TestBit(kCannotPick)) {
4882
4883 if (picked == this) {
4884 // cannot pick pad itself!
4885 picked = nullptr;
4886 }
4887
4888 }
4889
4890 return picked;
4891}
4892
4893////////////////////////////////////////////////////////////////////////////////
4894/// Pop pad to the top of the stack.
4895
4897{
4899 return;
4900 if (!fPrimitives)
4901 fPrimitives = new TList;
4902 if (this == fMother->GetListOfPrimitives()->Last())
4903 return;
4904
4906 while (auto obj = next())
4907 if (obj == this) {
4908 TString opt = next.GetOption();
4909 fMother->Remove(this, kFALSE); // do not issue modified
4910 fMother->Add(this, opt.Data());
4911 return;
4912 }
4913}
4914
4915////////////////////////////////////////////////////////////////////////////////
4916/// This method is equivalent to `SaveAs("filename")`. See TPad::SaveAs for details.
4917
4918void TPad::Print(const char *filename) const
4919{
4920 ((TPad*)this)->SaveAs(filename);
4921}
4922
4923////////////////////////////////////////////////////////////////////////////////
4924/// Auxiliary function. Returns kTRUE if list contains an object inherited
4925/// from TImage
4926
4928{
4929 TIter next(li);
4930
4931 while (auto obj = next()) {
4932 if (obj->InheritsFrom(TImage::Class())) {
4933 return kTRUE;
4934 } else if (obj->InheritsFrom(TPad::Class())) {
4935 if (ContainsTImage(((TPad*)obj)->GetListOfPrimitives())) {
4936 return kTRUE;
4937 }
4938 }
4939 }
4940 return kFALSE;
4941}
4942
4943////////////////////////////////////////////////////////////////////////////////
4944/// Save Canvas contents in a file in one of various formats.
4945///
4946/// \anchor TPadPrint
4947/// option can be:
4948///
4949/// - `ps`: a Postscript file is produced (default). [See special cases](\ref TPadPrintPS).
4950/// - `Portrait`: Postscript file is produced (Portrait)
4951/// - `Landscape`: Postscript file is produced (Landscape)
4952/// - `eps`: an Encapsulated Postscript file is produced
4953/// - `Preview`: an [Encapsulated Postscript file with preview](\ref TPadPrintPreview) is produced.
4954/// - `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.
4955/// - `Title:`: The character string after `Title:` becomes a table
4956/// of content entry (for PDF files).
4957/// - `EmbedFonts`: a [PDF file with embedded fonts](\ref TPadPrintEmbedFonts) is generated.
4958/// - `svg`: a SVG file is produced
4959/// - `tex`: a TeX file is produced
4960/// - `Standalone`: a [standalone TeX file](\ref TPadPrintStandalone) is produced.
4961/// - `gif`: a GIF file is produced
4962/// - `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
4963/// - `xpm`: a XPM file is produced
4964/// - `png`: a PNG file is produced
4965/// - `jpg`: a JPEG file is produced. NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
4966/// - `tiff`: a TIFF file is produced
4967/// - `cxx`: a C++ macro file is produced
4968/// - `xml`: a XML file
4969/// - `json`: a JSON file
4970/// - `root`: a ROOT binary file
4971///
4972/// `filename` = 0 - filename is defined by `GetName` and its
4973/// extension is defined with the option
4974///
4975/// When Postscript output is selected (`ps`, `eps`), the canvas is saved
4976/// to `filename.ps` or `filename.eps`. The aspect ratio of the canvas is preserved
4977/// on the Postscript file. When the "ps" option is selected, the Postscript
4978/// page will be landscape format if the canvas is in landscape format, otherwise
4979/// portrait format is selected.
4980///
4981/// The physical size of the Postscript page is the one selected in the
4982/// current style. This size can be modified via TStyle::SetPaperSize.
4983///
4984/// Examples:
4985/// ~~~ {.cpp}
4986/// gStyle->SetPaperSize(TStyle::kA4); //default
4987/// gStyle->SetPaperSize(TStyle::kUSLetter);
4988/// ~~~
4989/// where TStyle::kA4 and TStyle::kUSLetter are defined in the enum
4990/// EPaperSize in TStyle.h
4991///
4992/// An alternative is to call:
4993/// ~~~ {.cpp}
4994/// gStyle->SetPaperSize(20,26); same as kA4
4995/// or gStyle->SetPaperSize(20,24); same as kUSLetter
4996/// ~~~
4997/// The above numbers take into account some margins and are in centimeters.
4998///
4999/// \anchor TPadPrintPreview
5000/// ### The "Preview" option
5001///
5002/// The "Preview" option allows to generate a preview (in the TIFF format) within
5003/// the Encapsulated Postscript file. This preview can be used by programs like
5004/// MSWord to visualize the picture on screen. The "Preview" option relies on the
5005/// ["epstool" command](http://www.cs.wisc.edu/~ghost/gsview/epstool.htm).
5006///
5007/// Example:
5008/// ~~~ {.cpp}
5009/// canvas->Print("example.eps","Preview");
5010/// ~~~
5011///
5012/// \anchor TPadPrintEmbedFonts
5013/// ### The "EmbedFonts" option
5014///
5015/// The "EmbedFonts" option allows to embed the fonts used in a PDF file inside
5016/// that file. This option relies on the ["gs" command](https://ghostscript.com).
5017///
5018/// Example:
5019/// ~~~ {.cpp}
5020/// canvas->Print("example.pdf","EmbedFonts");
5021/// ~~~
5022///
5023/// \anchor TPadPrintStandalone
5024/// ### The "Standalone" option
5025/// The "Standalone" option allows to generate a TeX file ready to be processed by
5026/// tools like `pdflatex`.
5027///
5028/// Example:
5029/// ~~~ {.cpp}
5030/// canvas->Print("example.tex","Standalone");
5031/// ~~~
5032///
5033/// \anchor TPadPrintPS
5034/// ### Writing several canvases to the same Postscript or PDF file:
5035///
5036/// - if the Postscript or PDF file name finishes with "(", the file is not closed
5037/// - if the Postscript or PDF file name finishes with ")" and the file has been opened
5038/// with "(", the file is closed.
5039///
5040/// Example:
5041/// ~~~ {.cpp}
5042/// {
5043/// TCanvas c1("c1");
5044/// h1.Draw();
5045/// c1.Print("c1.ps("); //write canvas and keep the ps file open
5046/// h2.Draw();
5047/// c1.Print("c1.ps"); canvas is added to "c1.ps"
5048/// h3.Draw();
5049/// c1.Print("c1.ps)"); canvas is added to "c1.ps" and ps file is closed
5050/// }
5051/// ~~~
5052/// In the previous example replacing "ps" by "pdf" will create a multi-pages PDF file.
5053///
5054/// Note that the following sequence writes the canvas to "c1.ps" and closes the ps file.:
5055/// ~~~ {.cpp}
5056/// TCanvas c1("c1");
5057/// h1.Draw();
5058/// c1.Print("c1.ps");
5059/// ~~~
5060/// The `TCanvas::Print("file.ps(")` mechanism is very useful, but it can be
5061/// a little inconvenient to have the action of opening/closing a file
5062/// being atomic with printing a page. Particularly if pages are being
5063/// generated in some loop one needs to detect the special cases of first
5064/// and last page and then munge the argument to Print() accordingly.
5065///
5066/// The "[" and "]" can be used instead of "(" and ")" to open / close without
5067/// actual printing.
5068///
5069/// Example:
5070/// ~~~ {.cpp}
5071/// c1.Print("file.ps["); // No actual print, just open file.ps
5072/// for (int i=0; i<10; ++i) {
5073/// // fill canvas for context i
5074/// // ...
5075///
5076/// c1.Print("file.ps"); // actually print canvas to file
5077/// }// end loop
5078/// c1.Print("file.ps]"); // No actual print, just close.
5079/// ~~~
5080/// As before, the same macro is valid for PDF files.
5081///
5082/// It is possible to print a canvas into an animated GIF file by specifying the
5083/// file name as "myfile.gif+" or "myfile.gif+NN", where NN*10ms is delay
5084/// between the subimages' display. If NN is omitted the delay between
5085/// subimages is zero. Each picture is added in the animation thanks to a loop
5086/// similar to the following one:
5087/// ~~~ {.cpp}
5088/// for (int i=0; i<10; ++i) {
5089/// // fill canvas for context i
5090/// // ...
5091///
5092/// c1.Print("file.gif+5"); // print canvas to GIF file with 50ms delays
5093/// }// end loop
5094/// ~~~
5095/// The delay between each frame must be specified in each Print() statement.
5096/// If the file "myfile.gif" already exists, the new frame are appended at
5097/// the end of the file. To avoid this, delete it first with `gSystem->Unlink(myfile.gif);`
5098/// If you want the gif file to repeat or loop forever, check TASImage::WriteImage documentation
5099
5101{
5102 if (!GetCanvas())
5103 return;
5104
5106
5107 // "[" and "]" are special characters for ExpandPathName. When they are at the end
5108 // of the file name (see help) they must be removed before doing ExpandPathName.
5109 if (fs1.EndsWith("[")) {
5110 fs1.Replace((fs1.Length()-1),1," ");
5112 fs1.Replace((fs1.Length()-1),1,"[");
5113 } else if (fs1.EndsWith("]")) {
5114 fs1.Replace((fs1.Length()-1),1," ");
5116 fs1.Replace((fs1.Length()-1),1,"]");
5117 } else {
5119 }
5120
5121 // Set the default option as "Postscript" (Should be a data member of TPad)
5122 const char *opt_default = "ps";
5123
5124 TString opt = !option ? opt_default : option;
5126
5127 Bool_t title = kFALSE;
5128 if (strstr(opt,"Title:")) title = kTRUE;
5129
5130 if (!fs1.Length()) {
5131 psname = GetName();
5132 psname += opt;
5133 } else {
5134 psname = fs1;
5135 }
5136
5137 // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
5138 if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
5139 psname = GetName();
5140 psname.Append(fs1);
5141 psname.Prepend("/");
5142 psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
5143 }
5144
5145 // Save pad/canvas in alternative formats
5147 if (!title && strstr(opt, "gif+")) {
5149 image = kTRUE;
5150 } else if (!title && strstr(opt, "gif")) {
5152 image = kTRUE;
5153 } else if (!title && strstr(opt, "png")) {
5155 image = kTRUE;
5156 } else if (!title && strstr(opt, "jpg")) {
5158 image = kTRUE;
5159 } else if (!title && strstr(opt, "tiff")) {
5161 image = kTRUE;
5162 } else if (!title && strstr(opt, "xpm")) {
5164 image = kTRUE;
5165 } else if (!title && strstr(opt, "bmp")) {
5167 image = kTRUE;
5168 }
5169
5170 if (GetCanvas()->IsWeb() && GetPainter() &&
5171 (strstr(opt,"svg") || strstr(opt,"pdf") || (gtype == TImage::kJpeg) || (gtype == TImage::kPng))) {
5172 GetPainter()->SaveImage(this, psname.Data(), gtype);
5173 return;
5174 }
5175
5176 if (!GetCanvas()->IsBatch() && GetPainter())
5178
5179
5180 if (!gROOT->IsBatch() && image) {
5182 Int_t wid = (this == GetCanvas()) ? GetCanvas()->GetCanvasID() : GetPixmapID();
5183 Color_t hc = gPad->GetCanvas()->GetHighLightColor();
5184 gPad->GetCanvas()->SetHighLightColor(-1);
5185 gPad->Modified();
5186 gPad->Update();
5187 if (GetPainter()) {
5189 GetPainter()->SaveImage(this, psname.Data(), gtype);
5190 }
5191 if (!gSystem->AccessPathName(psname.Data())) {
5192 Info("Print", "GIF file %s has been created", psname.Data());
5193 }
5194 gPad->GetCanvas()->SetHighLightColor(hc);
5195 return;
5196 }
5197 if (gtype != TImage::kUnknown) {
5198 Color_t hc = gPad->GetCanvas()->GetHighLightColor();
5199 gPad->GetCanvas()->SetHighLightColor(-1);
5200 gPad->Modified();
5201 gPad->Update();
5202 gPad->GetCanvasImp()->UpdateDisplay(1, kTRUE);
5203 if (GetPainter())
5204 GetPainter()->SaveImage(this, psname, gtype);
5205 if (!gSystem->AccessPathName(psname)) {
5206 Info("Print", "file %s has been created", psname.Data());
5207 }
5208 gPad->GetCanvas()->SetHighLightColor(hc);
5209 } else {
5210 Warning("Print", "Unsupported image format %s", psname.Data());
5211 }
5212 return;
5213 }
5214
5215 //==============Save pad/canvas as a C++ script==============================
5216 if (!title && strstr(opt,"cxx")) {
5217 GetCanvas()->SaveSource(psname, "");
5218 return;
5219 }
5220
5221 //==============Save pad/canvas as a root file===============================
5222 if (!title && strstr(opt,"root")) {
5223 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5224 return;
5225 }
5226
5227 //==============Save pad/canvas as a XML file================================
5228 if (!title && strstr(opt,"xml")) {
5229 // Plugin XML driver
5230 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5231 return;
5232 }
5233
5234 //==============Save pad/canvas as a JSON file================================
5235 if (!title && strstr(opt,"json")) {
5236 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5237 return;
5238 }
5239
5240 //==============Save pad/canvas as a SVG file================================
5241 if (!title && strstr(opt,"svg")) {
5242 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5243
5245 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5246 noScreen = kTRUE;
5248 }
5249
5250 TContext ctxt(this, kTRUE);
5251
5252 if (!gVirtualPS) {
5253 // Plugin Postscript/SVG driver
5254 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "svg")) {
5255 if (h->LoadPlugin() == -1)
5256 return;
5257 h->ExecPlugin(0);
5258 }
5259 }
5260
5261 // Create a new SVG file
5262 if (gVirtualPS) {
5267 }
5268
5269 Paint();
5270 if (noScreen)
5272
5274 Info("Print", "SVG file %s has been created", psname.Data());
5275
5276 delete gVirtualPS;
5277 gVirtualPS = nullptr;
5278
5279 return;
5280 }
5281
5282 //==============Save pad/canvas as a TeX file================================
5283 if (!title && (strstr(opt,"tex") || strstr(opt,"Standalone"))) {
5284 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5285
5287 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5288 noScreen = kTRUE;
5290 }
5291
5292 TContext ctxt(this, kTRUE);
5293
5294 if (!gVirtualPS) {
5295 // Plugin Postscript/SVG driver
5296 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "tex")) {
5297 if (h->LoadPlugin() == -1)
5298 return;
5299 h->ExecPlugin(0);
5300 }
5301 }
5302
5304 if (strstr(opt,"Standalone")) standalone = kTRUE;
5305
5306 // Create a new TeX file
5307 if (gVirtualPS) {
5309 if (standalone) gVirtualPS->SetTitle("Standalone");
5313 }
5314 Paint();
5316
5317 if (!gSystem->AccessPathName(psname)) {
5318 if (standalone) {
5319 Info("Print", "Standalone TeX file %s has been created", psname.Data());
5320 } else{
5321 Info("Print", "TeX file %s has been created", psname.Data());
5322 }
5323 }
5324
5325 delete gVirtualPS;
5326 gVirtualPS = nullptr;
5327
5328 return;
5329 }
5330
5331 //==============Save pad/canvas as a Postscript file=========================
5332
5333 // in case we read directly from a Root file and the canvas
5334 // is not on the screen, set batch mode
5335
5338 if (!image) {
5339 // The parenthesis mechanism is only valid for PS and PDF files.
5340 copen = psname.EndsWith("("); if (copen) psname[psname.Length()-1] = 0;
5341 cclose = psname.EndsWith(")"); if (cclose) psname[psname.Length()-1] = 0;
5342 copenb = psname.EndsWith("["); if (copenb) psname[psname.Length()-1] = 0;
5343 ccloseb = psname.EndsWith("]"); if (ccloseb) psname[psname.Length()-1] = 0;
5344 }
5345 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5347 if (copen || copenb) mustClose = kFALSE;
5348 if (cclose || ccloseb) mustClose = kTRUE;
5349
5351 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5352 noScreen = kTRUE;
5354 }
5355 Int_t pstype = 111;
5358 Double_t ratio = ycanvas/xcanvas;
5359 if (ratio < 1) pstype = 112;
5360 if (strstr(opt,"Portrait")) pstype = 111;
5361 if (strstr(opt,"Landscape")) pstype = 112;
5362 if (strstr(opt,"eps")) pstype = 113;
5363 if (strstr(opt,"Preview")) pstype = 113;
5364
5365 TContext ctxt(this, kTRUE);
5367
5368 if (!gVirtualPS || mustOpen) {
5369
5370 const char *pluginName = "ps"; // Plugin Postscript driver
5371 if (strstr(opt,"pdf") || title || strstr(opt,"EmbedFonts"))
5372 pluginName = "pdf";
5373 else if (image)
5374 pluginName = "image"; // Plugin TImageDump driver
5375
5376 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", pluginName)) {
5377 if (h->LoadPlugin() == -1)
5378 return;
5379 h->ExecPlugin(0);
5380 }
5381
5382 // Create a new Postscript, PDF or image file
5383 if (gVirtualPS)
5385 const Ssiz_t titlePos = opt.Index("Title:");
5386 if (titlePos != kNPOS) {
5387 if (gVirtualPS)
5388 gVirtualPS->SetTitle(opt.Data()+titlePos+6);
5389 opt.Replace(titlePos,opt.Length(),"pdf");
5390 }
5391 if (gVirtualPS)
5393 if (gVirtualPS)
5395 if (!copenb) {
5396 if (!strstr(opt,"pdf") || image) {
5398 }
5399 Paint();
5400 }
5402
5403 if (mustClose) {
5404 gROOT->GetListOfSpecials()->Remove(gVirtualPS);
5405 delete gVirtualPS;
5406 gVirtualPS = psave;
5407 } else {
5408 gROOT->GetListOfSpecials()->Add(gVirtualPS);
5409 gVirtualPS = nullptr;
5410 }
5411
5412 if (!gSystem->AccessPathName(psname)) {
5413 if (!copen) Info("Print", "%s file %s has been created", opt.Data(), psname.Data());
5414 else Info("Print", "%s file %s has been created using the current canvas", opt.Data(), psname.Data());
5415 }
5416 } else {
5417 // Append to existing Postscript, PDF or GIF file
5418 if (!ccloseb) {
5420 Paint();
5421 }
5422 const Ssiz_t titlePos = opt.Index("Title:");
5423 if (titlePos != kNPOS) {
5424 gVirtualPS->SetTitle(opt.Data()+titlePos+6);
5425 opt.Replace(titlePos,opt.Length(),"pdf");
5426 } else if (!ccloseb) {
5427 gVirtualPS->SetTitle("PDF");
5428 }
5429 if (mustClose) {
5430 if (cclose) Info("Print", "Current canvas added to %s file %s and file closed", opt.Data(), psname.Data());
5431 else Info("Print", "%s file %s has been closed", opt.Data(), psname.Data());
5432 gROOT->GetListOfSpecials()->Remove(gVirtualPS);
5433 delete gVirtualPS;
5434 gVirtualPS = nullptr;
5435 } else {
5436 Info("Print", "Current canvas added to %s file %s", opt.Data(), psname.Data());
5437 gVirtualPS = nullptr;
5438 }
5439 }
5440
5441 if (strstr(opt,"Preview"))
5442 gSystem->Exec(TString::Format("epstool --quiet -t6p %s %s", psname.Data(), psname.Data()).Data());
5443 if (strstr(opt,"EmbedFonts")) {
5444 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",
5445 psname.Data()).Data());
5446 gSystem->Rename("pdf_temp.pdf", psname.Data());
5447 }
5448
5449}
5450
5451////////////////////////////////////////////////////////////////////////////////
5452/// Set world coordinate system for the pad.
5453/// Emits signal "RangeChanged()", in the slot get the range
5454/// via GetRange().
5455
5457{
5458 if ((x1 >= x2) || (y1 >= y2)) {
5459 Error("Range", "illegal world coordinates range: x1=%f, y1=%f, x2=%f, y2=%f",x1,y1,x2,y2);
5460 return;
5461 }
5462
5463 fUxmin = x1;
5464 fUxmax = x2;
5465 fUymin = y1;
5466 fUymax = y2;
5467
5468 if (fX1 == x1 && fY1 == y1 && fX2 == x2 && fY2 == y2) return;
5469
5470 fX1 = x1;
5471 fY1 = y1;
5472 fX2 = x2;
5473 fY2 = y2;
5474
5475 // compute pad conversion coefficients
5476 ResizePad();
5477
5478 if (gPad == this && GetPainter())
5480
5481 // emit signal
5482 RangeChanged();
5483}
5484
5485////////////////////////////////////////////////////////////////////////////////
5486/// Set axis coordinate system for the pad.
5487/// The axis coordinate system is a subset of the world coordinate system
5488/// xmin,ymin is the origin of the current coordinate system,
5489/// xmax is the end of the X axis, ymax is the end of the Y axis.
5490/// By default a margin of 10 per cent is left on all sides of the pad
5491/// Emits signal "RangeAxisChanged()", in the slot get the axis range
5492/// via GetRangeAxis().
5493
5495{
5496 if ((xmin >= xmax) || (ymin >= ymax)) {
5497 Error("RangeAxis", "illegal axis coordinates range: xmin=%f, ymin=%f, xmax=%f, ymax=%f",
5498 xmin, ymin, xmax, ymax);
5499 return;
5500 }
5501
5502 fUxmin = xmin;
5503 fUymin = ymin;
5504 fUxmax = xmax;
5505 fUymax = ymax;
5506
5507 // emit signal
5509}
5510
5511////////////////////////////////////////////////////////////////////////////////
5512/// Recursively remove object from a pad and its sub-pads.
5513
5515{
5516 if (fCanvas) {
5517 if (obj == fCanvas->GetSelected()) fCanvas->SetSelected(nullptr);
5518 if (obj == fCanvas->GetClickSelected()) fCanvas->SetClickSelected(nullptr);
5519 }
5520 if (obj == fView) fView = nullptr;
5521 if (!fPrimitives) return;
5524 if (nold != fPrimitives->GetSize()) fModified = kTRUE;
5525}
5526
5527////////////////////////////////////////////////////////////////////////////////
5528/// Remove object from list of primitives
5529/// When \par modified set to kTRUE (default) pad will be marked as modified - if object really removed
5530/// Returns result of GetListOfPrimitives()->Remove(obj) or nullptr if list of primitives not exists
5531
5533{
5534 TObject *res = nullptr;
5535 if (fPrimitives)
5536 res = fPrimitives->Remove(obj);
5537 if (res && modified)
5538 Modified();
5539 return res;
5540}
5541
5542////////////////////////////////////////////////////////////////////////////////
5543/// Redraw the frame axis.
5544///
5545/// Redrawing axis may be necessary in case of superimposed histograms
5546/// when one or more histograms have a fill color.
5547///
5548/// Instead of calling this function, it may be more convenient
5549/// to call directly `h1->Draw("sameaxis")` where h1 is the pointer
5550/// to the first histogram drawn in the pad.
5551///
5552/// By default, if the pad has the options gridx or/and gridy activated,
5553/// the grid is not drawn by this function.
5554///
5555/// If option="g" is specified, this will force the drawing of the grid
5556/// on top of the picture
5557///
5558/// To redraw the axis tick marks do:
5559/// ~~~ {.cpp}
5560/// gPad->RedrawAxis();
5561/// ~~~
5562/// To redraw the axis grid do:
5563/// ~~~ {.cpp}
5564/// gPad->RedrawAxis("G");
5565/// ~~~
5566/// To redraw the axis tick marks and the axis grid do:
5567/// ~~~ {.cpp}
5568/// gPad->RedrawAxis();
5569/// gPad->RedrawAxis("G");
5570/// ~~~
5571///
5572/// If option="f" is specified, this will force the drawing of the frame
5573/// around the plot.
5574
5576{
5577 TString opt = option;
5578 opt.ToLower();
5579
5580 TContext ctxt(this, kTRUE);
5581
5582 TH1 *hobj = nullptr;
5583
5584 // Get the first histogram drawing the axis in the list of primitives
5585 if (!fPrimitives) fPrimitives = new TList;
5586 TIter next(fPrimitives);
5587 TObject *obj;
5588 while ((obj = next())) {
5589 if (obj->InheritsFrom(TH1::Class())) {
5590 hobj = (TH1*)obj;
5591 break;
5592 }
5593 if (obj->InheritsFrom(TMultiGraph::Class())) {
5594 TMultiGraph *mg = (TMultiGraph*)obj;
5595 if (mg) hobj = mg->GetHistogram();
5596 break;
5597 }
5598 if (obj->InheritsFrom(TGraph::Class())) {
5599 TGraph *g = (TGraph*)obj;
5600 if (g) hobj = g->GetHistogram();
5601 break;
5602 }
5603 if (obj->InheritsFrom(THStack::Class())) {
5604 THStack *hs = (THStack*)obj;
5605 if (hs) hobj = hs->GetHistogram();
5606 break;
5607 }
5608 }
5609
5610 if (hobj) {
5611 if (opt.Contains("g")) hobj->DrawCopy("sameaxig");
5612 else hobj->DrawCopy("sameaxis");
5613 }
5614
5615 if (opt.Contains("f")) {
5616 auto b = new TBox(gPad->GetUxmin(), gPad->GetUymin(),
5617 gPad->GetUxmax(), gPad->GetUymax());
5618 b->SetFillStyle(0);
5619 b->SetLineStyle(gPad->GetFrameLineStyle());
5620 b->SetLineWidth(gPad->GetFrameLineWidth());
5621 b->SetLineColor(gPad->GetFrameLineColor());
5622 b->Draw();
5623 }
5624}
5625
5626////////////////////////////////////////////////////////////////////////////////
5627/// Compute pad conversion coefficients.
5628///
5629/// ### Conversion from x to px
5630///
5631/// \f[\frac{x-xmin}{xrange} = \frac{px-pxlow}{pxrange}\f]
5632/// with:
5633/// \f[ xrange = xmax-xmin \f]
5634/// \f[ pxrange = pxmax-pxmin \f]
5635///
5636/// \f[
5637/// \Rightarrow px = \frac{pxrange(x-xmin)}{xrange} + pxlow = fXtoPixelk + fXtoPixel \times x
5638/// \f]
5639///
5640/// \f[
5641/// \Rightarrow fXtoPixelk = pxlow - pxrange \frac{xmin}{xrange}
5642/// \f]
5643/// \f[
5644/// fXtoPixel = \frac{pxrange}{xrange}
5645/// \f]
5646/// where:
5647/// \f[
5648/// pxlow = fAbsXlowNDC \times fCw
5649/// \f]
5650/// \f[
5651/// pxrange = fAbsWNDC \times fCw
5652/// \f]
5653///
5654/// ### Conversion from y to py
5655///
5656/// \f[\frac{y-ymin}{yrange} = \frac{py-pylow}{pyrange}\f]
5657/// with:
5658/// \f[ yrange = ymax-ymin \f]
5659/// \f[ pyrange = pymax-pymin \f]
5660///
5661/// \f[
5662/// \Rightarrow py = \frac{pyrange(y-xmin)}{yrange} + pylow = fYtoPixelk + fYtoPixel \times y
5663/// \f]
5664///
5665/// \f[
5666/// \Rightarrow fYtoPixelk = pylow - pyrange \frac{ymin}{yrange}
5667/// \f]
5668/// \f[
5669/// fYtoPixel = \frac{pyrange}{yrange}
5670/// \f]
5671/// where:
5672/// \f[
5673/// pylow = fAbsYlowNDC \times fCh
5674/// \f]
5675/// \f[
5676/// pyrange = fAbsHNDC \times fCh
5677/// \f]
5678///
5679/// ### Conversion from px to x
5680///
5681/// \f[
5682/// \Rightarrow x = \frac{xrange(px-pxlow)}{pxrange}+ xmin = fPixeltoXk + fPixeltoX \times px
5683/// \f]
5684///
5685/// \f[
5686/// \Rightarrow fPixeltoXk = xmin - pxlow \times\frac{xrange}{pxrange}
5687/// \f]
5688/// \f[
5689/// fPixeltoX = \frac{xrange}{pxrange}
5690/// \f]
5691///
5692/// ### Conversion from py to y
5693///
5694/// \f[
5695/// \Rightarrow y = \frac{yrange(py-pylow)}{pyrange}+ ymin = fPixeltoYk + fPixeltoY \times py
5696/// \f]
5697///
5698/// \f[
5699/// \Rightarrow fPixeltoYk = ymin - pylow \times\frac{yrange}{pyrange}
5700/// \f]
5701/// \f[
5702/// fPixeltoY = \frac{yrange}{pyrange}
5703/// \f]
5704///
5705/// ### Computation of the coefficients in case of LOG scales
5706///
5707/// #### Conversion from pixel coordinates to world coordinates
5708///
5709/// \f[
5710/// u = \frac{Log(x) - Log(xmin)}{Log(xmax) - Log(xmin)} = \frac{Log(x/xmin)}{Log(xmax/xmin)} = \frac{px - pxlow}{pxrange}
5711/// \f]
5712///
5713/// \f[ \Rightarrow Log(\frac{x}{xmin}) = u \times Log(\frac{xmax}{xmin}) \f]
5714/// \f[ x = xmin \times e^{(u \times Log(\frac{xmax}{xmin})} \f]
5715/// Let:
5716/// \f[ alfa = \frac{Log(\frac{xmax}{xmin})}{fAbsWNDC} \f]
5717///
5718/// \f[ x = xmin \times e^{(-alfa \times pxlow)} + e^{(alfa \times px)} \f]
5719/// \f[ x = fPixeltoXk \times e^{(fPixeltoX \times px)} \f]
5720/// \f[ ==> fPixeltoXk = xmin \times e^{(-alfa*pxlow)} \f]
5721/// \f[ fPixeltoX = alfa \f]
5722///
5723/// \f[
5724/// v = \frac{Log(y) - Log(ymin)}{Log(ymax) - Log(ymin)} = \frac{Log(y/ymin)}{Log(ymax/ymin)} = \frac{py - pylow}{pyrange}
5725/// \f]
5726/// Let:
5727/// \f[ beta = Log(\frac{ymax}{ymin}) \f]
5728/// \f[ Log(\frac{y}{ymin}) = beta \times pylow - beta \times py \f]
5729/// \f[ \frac{y}{ymin} = e^{(beta \times pylow - beta \times py)} \f]
5730/// \f[ y = ymin \times e^{(beta \times pylow)} \times e^{(-beta \times py)}\f]
5731/// \f[ \Rightarrow y = fPixeltoYk \times e^{(fPixeltoY \times py)} \f]
5732/// \f[ fPixeltoYk = ymin \times e^{(beta \times pylow)} \f]
5733/// \f[ fPixeltoY = -beta \f]
5734///
5735/// #### Conversion from World coordinates to pixel coordinates
5736///
5737/// \f[ px = pxlow + u*pxrange \f]
5738/// \f[ = pxlow + Log(x/xmin)/alfa \f]
5739/// \f[ = pxlow -Log(xmin)/alfa + Log(x)/alfa \f]
5740/// \f[ = fXtoPixelk + fXtoPixel*Log(x) \f]
5741/// \f[ \Rightarrow fXtoPixelk = pxlow -Log(xmin)/alfa \f]
5742/// \f[ \Rightarrow fXtoPixel = 1/alfa \f]
5743///
5744/// \f[ py = pylow - Log(y/ymin)/beta \f]
5745/// \f[ = fYtoPixelk + fYtoPixel*Log(y) \f]
5746/// \f[ \Rightarrow fYtoPixelk = pylow - Log(ymin)/beta \f]
5747/// \f[ fYtoPixel = 1/beta \f]
5748
5750{
5751
5752 if (!gPad) {
5753 Error("ResizePad", "Cannot resize pad. No current pad available.");
5754 return;
5755 }
5756 if (gPad->GetWw()==0.0||gPad->GetWh()==0.0) {
5757 Warning("ResizePad", "gPad has at least one zero dimension.");
5758 return;
5759 }
5760 if (fX1==fX2||fY1==fY2) {
5761 Warning("ResizePad", "The pad has at least one zero dimension.");
5762 return;
5763 }
5764 // Recompute subpad positions in case pad has been moved/resized
5765 TPad *parent = fMother;
5766 if (this == gPad->GetCanvas()) {
5769 fAbsWNDC = fWNDC;
5770 fAbsHNDC = fHNDC;
5771 }
5772 else {
5773 if (parent->GetAbsHNDC()==0.0||parent->GetAbsWNDC()==0.0||fHNDC==0.0||fWNDC==0.0) {
5774 Warning("ResizePad", "The parent pad has at least one zero dimension.");
5775 return;
5776 }
5777 fAbsXlowNDC = fXlowNDC*parent->GetAbsWNDC() + parent->GetAbsXlowNDC();
5778 fAbsYlowNDC = fYlowNDC*parent->GetAbsHNDC() + parent->GetAbsYlowNDC();
5779 fAbsWNDC = fWNDC*parent->GetAbsWNDC();
5780 fAbsHNDC = fHNDC*parent->GetAbsHNDC();
5781 }
5782
5783 Double_t ww = (Double_t)gPad->GetWw();
5784 Double_t wh = (Double_t)gPad->GetWh();
5789
5790 // Linear X axis
5791 Double_t rounding = 0.; // was used before to adjust somehow wrong int trunctation by coordiantes transformation
5792 Double_t xrange = fX2 - fX1;
5793 fXtoAbsPixelk = rounding + pxlow - pxrange*fX1/xrange; //origin at left
5797 fPixeltoXk = fX1;
5799 // Linear Y axis
5800 Double_t yrange = fY2 - fY1;
5801 fYtoAbsPixelk = rounding + pylow - pyrange*fY1/yrange; //origin at top
5805 fPixeltoYk = fY1;
5807
5808 // Coefficients to convert from pad NDC coordinates to pixel coordinates
5809
5816
5817 // Coefficients to convert from canvas pixels to pad world coordinates
5818
5819 // Resize all sub-pads
5820 if (!fPrimitives)
5821 fPrimitives = new TList;
5822 TIter next(GetListOfPrimitives());
5823 while (auto obj = next()) {
5824 if (obj->InheritsFrom(TPad::Class()))
5825 ((TPad *)obj)->ResizePad(option);
5826 }
5827
5828 // Reset all current sizes
5829 if (gPad->IsBatch())
5830 fPixmapID = 0;
5831 else if (auto pp = GetPainter()) {
5832 if (pp->IsNative()) {
5833 // TODO: check if this is necessary
5834 auto attl = pp->GetAttLine();
5835 attl.SetLineColor(-1);
5836 pp->SetAttLine(attl);
5837 auto attt = pp->GetAttText();
5838 attt.SetTextSize(-1);
5839 pp->SetAttText(attt);
5840 // create or re-create off-screen pixmap
5841 if (fPixmapID) {
5842 int w = TMath::Abs(XtoPixel(fX2) - XtoPixel(fX1));
5843 int h = TMath::Abs(YtoPixel(fY2) - YtoPixel(fY1));
5844 //protection in case of wrong pad parameters.
5845 //without this protection, the OpenPixmap or ResizePixmap crashes with
5846 //the message "Error in <RootX11ErrorHandler>: BadValue (integer parameter out of range for operation)"
5847 //resulting in a frozen xterm
5850 Warning("ResizePad", "Inf/NaN propagated to the pad. Check drawn objects.");
5851 if (w <= 0 || w > 10000) {
5852 Warning("ResizePad", "%s width changed from %d to %d\n",GetName(),w,10);
5853 w = 10;
5854 }
5855 if (h <= 0 || h > 10000) {
5856 Warning("ResizePad", "%s height changed from %d to %d\n",GetName(),h,10);
5857 h = 10;
5858 }
5859 if (fPixmapID == -1) // this case is handled via the ctor
5860 fPixmapID = pp->CreateDrawable(w, h);
5861 else if (pp->ResizeDrawable(fPixmapID, w, h)) {
5862 Resized();
5863 Modified(kTRUE);
5864 }
5865 }
5866 }
5867 }
5868 if (fView) {
5869 if (gPad == this) {
5870 fView->ResizePad();
5871 } else {
5872 TContext ctxt(this, kTRUE);
5873 fView->ResizePad();
5874 }
5875 }
5876}
5877
5878////////////////////////////////////////////////////////////////////////////////
5879/// Save the pad content in a file.
5880///
5881/// The file's format used to save the pad is determined by the `filename` extension:
5882///
5883/// - if `filename` is empty, the file produced is `padname.ps`
5884/// - if `filename` starts with a dot, the padname is added in front
5885/// - if `filename` ends with `.ps`, a Postscript file is produced
5886/// - if `filename` ends with `.eps`, an Encapsulated Postscript file is produced
5887/// - 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.
5888/// - if `filename` ends with `.svg`, a SVG file is produced
5889/// - if `filename` ends with `.tex`, a TeX file is produced
5890/// - if `filename` ends with `.gif`, a GIF file is produced
5891/// - 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
5892/// - if `filename` ends with `.xpm`, a XPM file is produced
5893/// - if `filename` ends with `.png`, a PNG file is produced
5894/// - if `filename` ends with `.bmp`, a BMP file is produced
5895/// - if `filename` ends with `.jpg` or `.jpeg` a JPEG file is produced NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
5896/// - if `filename` ends with `.tiff`, a TIFF file is produced
5897/// - if `filename` ends with `.C`, `.cxx`,`.cpp` or `.cc`, a C++ macro file is produced
5898/// - if `filename` ends with `.root`, a Root file is produced
5899/// - if `filename` ends with `.xml`, a XML file is produced
5900/// - if `filename` ends with `.json`, a JSON file is produced
5901///
5902/// \remarks
5903/// - The parameter `option` is not used.
5904/// - This method calls [TPad::Print(const char *filename, Option_t *option)](\ref TPadPrint)
5905/// the value of `option` is determined by the `filename` extension.
5906/// - Postscript and PDF formats allow to have [several pictures in one file](\ref TPadPrintPS).
5907
5908void TPad::SaveAs(const char *filename, Option_t * /*option*/) const
5909{
5912
5913 if (!lenfil) { psname = GetName(); psname.Append(".ps"); }
5914 else psname = filename;
5915
5916 // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
5917 if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
5918 psname = GetName();
5919 psname.Append(filename);
5920 psname.Prepend("/");
5921 psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
5922 }
5923
5924 if (psname.EndsWith(".gif"))
5925 ((TPad*)this)->Print(psname,"gif");
5926 else if (psname.Contains(".gif+"))
5927 ((TPad*)this)->Print(psname,"gif+");
5928 else if (psname.EndsWith(".C") || psname.EndsWith(".cxx") || psname.EndsWith(".cpp") || psname.EndsWith(".cc"))
5929 ((TPad*)this)->Print(psname,"cxx");
5930 else if (psname.EndsWith(".root"))
5931 ((TPad*)this)->Print(psname,"root");
5932 else if (psname.EndsWith(".xml"))
5933 ((TPad*)this)->Print(psname,"xml");
5934 else if (psname.EndsWith(".json"))
5935 ((TPad*)this)->Print(psname,"json");
5936 else if (psname.EndsWith(".eps"))
5937 ((TPad*)this)->Print(psname,"eps");
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(".pdf)"))
5947 ((TPad*)this)->Print(psname,"pdf");
5948 else if (psname.EndsWith(".svg"))
5949 ((TPad*)this)->Print(psname,"svg");
5950 else if (psname.EndsWith(".tex"))
5951 ((TPad*)this)->Print(psname,"tex");
5952 else if (psname.EndsWith(".xpm"))
5953 ((TPad*)this)->Print(psname,"xpm");
5954 else if (psname.EndsWith(".png"))
5955 ((TPad*)this)->Print(psname,"png");
5956 else if (psname.EndsWith(".jpg"))
5957 ((TPad*)this)->Print(psname,"jpg");
5958 else if (psname.EndsWith(".jpeg"))
5959 ((TPad*)this)->Print(psname,"jpg");
5960 else if (psname.EndsWith(".bmp"))
5961 ((TPad*)this)->Print(psname,"bmp");
5962 else if (psname.EndsWith(".tiff"))
5963 ((TPad*)this)->Print(psname,"tiff");
5964 else
5965 ((TPad*)this)->Print(psname,"ps");
5966}
5967
5968////////////////////////////////////////////////////////////////////////////////
5969/// Save primitives in this pad on the C++ source file out.
5970
5971void TPad::SavePrimitive(std::ostream &out, Option_t * option /*= ""*/)
5972{
5973 TContext ctxt(this, kFALSE); // not interactive
5974
5976
5977 // check for space in the pad name
5978 auto p = padName.Index(" ");
5979 if (p != kNPOS)
5980 padName.Resize(p);
5981
5982 TString opt = option;
5983 if (!opt.Contains("toplevel")) {
5984 static Int_t pcounter = 0;
5985 padName += TString::Format("__%d", pcounter++);
5986 padName = gInterpreter->MapCppName(padName);
5987 }
5988
5989 const char *pname = padName.Data();
5990 const char *cname = padName.Data();
5991
5992 if (padName.Length() == 0) {
5993 pname = "unnamed";
5994 if (this == gPad->GetCanvas())
5995 cname = "c1";
5996 else
5997 cname = "pad";
5998 }
5999
6000 // Write pad parameters
6001 if (this != gPad->GetCanvas()) {
6002 out << " \n";
6003 out << "// ------------>Primitives in pad: " << GetName() << "\n";
6004 out << " TPad *" << cname << " = new TPad(\"" << GetName() << "\", \""
6005 << TString(GetTitle()).ReplaceSpecialCppChars() << "\", " << fXlowNDC << ", " << fYlowNDC << ", "
6006 << fXlowNDC + fWNDC << ", " << fYlowNDC + fHNDC << ");\n";
6007 out << " " << cname << "->Draw();\n";
6008 out << " " << cname << "->cd();\n";
6009 }
6010 out << " " << cname << "->Range(" << fX1 << "," << fY1 << "," << fX2 << "," << fY2 << ");\n";
6011 TView *view = GetView();
6012 if (view) {
6013 Double_t rmin[3], rmax[3];
6014 view->GetRange(rmin, rmax);
6015 out << " TView::CreateView(1)->SetRange(" << rmin[0] << ", " << rmin[1] << ", " << rmin[2] << ", " << rmax[0]
6016 << ", " << rmax[1] << ", " << rmax[2] << ");\n";
6017 }
6018
6019 SaveFillAttributes(out, cname, -1, -1);
6020
6021 if (GetBorderMode() != 1)
6022 out << " " << cname << "->SetBorderMode(" << GetBorderMode() << ");\n";
6023 if (GetBorderSize() != 4)
6024 out << " " << cname << "->SetBorderSize(" << GetBorderSize() << ");\n";
6025 if (GetLogx())
6026 out << " " << cname << "->SetLogx();\n";
6027 if (GetLogy())
6028 out << " " << cname << "->SetLogy();\n";
6029 if (GetLogz())
6030 out << " " << cname << "->SetLogz();\n";
6031 if (GetGridx())
6032 out << " " << cname << "->SetGridx();\n";
6033 if (GetGridy())
6034 out << " " << cname << "->SetGridy();\n";
6035 if (GetTickx())
6036 out << " " << cname << "->SetTickx(" << GetTickx() << ");\n";
6037 if (GetTicky())
6038 out << " " << cname << "->SetTicky(" << GetTicky() << ");\n";
6039 if (GetTheta() != 30)
6040 out << " " << cname << "->SetTheta(" << GetTheta() << ");\n";
6041 if (GetPhi() != 30)
6042 out << " " << cname << "->SetPhi(" << GetPhi() << ");\n";
6043 if (TMath::Abs(fLeftMargin - 0.1) > 0.01)
6044 out << " " << cname << "->SetLeftMargin(" << GetLeftMargin() << ");\n";
6045 if (TMath::Abs(fRightMargin - 0.1) > 0.01)
6046 out << " " << cname << "->SetRightMargin(" << GetRightMargin() << ");\n";
6047 if (TMath::Abs(fTopMargin - 0.1) > 0.01)
6048 out << " " << cname << "->SetTopMargin(" << GetTopMargin() << ");\n";
6049 if (TMath::Abs(fBottomMargin - 0.1) > 0.01)
6050 out << " " << cname << "->SetBottomMargin(" << GetBottomMargin() << ");\n";
6051
6053 out << " " << cname << "->SetFrameFillColor(" << TColor::SavePrimitiveColor(GetFrameFillColor()) << ");\n";
6054 if (GetFrameFillStyle() != 1001)
6055 out << " " << cname << "->SetFrameFillStyle(" << GetFrameFillStyle() << ");\n";
6056 if (GetFrameLineStyle() != 1)
6057 out << " " << cname << "->SetFrameLineStyle(" << GetFrameLineStyle() << ");\n";
6058 if (GetFrameLineColor() != 1)
6059 out << " " << cname << "->SetFrameLineColor(" << TColor::SavePrimitiveColor(GetFrameLineColor()) << ");\n";
6060 if (GetFrameLineWidth() != 1)
6061 out << " " << cname << "->SetFrameLineWidth(" << GetFrameLineWidth() << ");\n";
6062 if (GetFrameBorderMode() != 0)
6063 out << " " << cname << "->SetFrameBorderMode(" << GetFrameBorderMode() << ");\n";
6064 if (GetFrameBorderSize() != 1)
6065 out << " " << cname << "->SetFrameBorderSize(" << GetFrameBorderSize() << ");\n";
6066
6067 TFrame *frame = fFrame;
6068 if (!frame)
6069 frame = (TFrame *)GetPrimitive("TFrame");
6070 if (frame) {
6071 if (frame->GetFillColor() != GetFillColor())
6072 out << " " << cname << "->SetFrameFillColor(" << TColor::SavePrimitiveColor(frame->GetFillColor()) << ");\n";
6073 if (frame->GetFillStyle() != 1001)
6074 out << " " << cname << "->SetFrameFillStyle(" << frame->GetFillStyle() << ");\n";
6075 if (frame->GetLineStyle() != 1)
6076 out << " " << cname << "->SetFrameLineStyle(" << frame->GetLineStyle() << ");\n";
6077 if (frame->GetLineColor() != 1)
6078 out << " " << cname << "->SetFrameLineColor(" << TColor::SavePrimitiveColor(frame->GetLineColor()) << ");\n";
6079 if (frame->GetLineWidth() != 1)
6080 out << " " << cname << "->SetFrameLineWidth(" << frame->GetLineWidth() << ");\n";
6081 if (frame->GetBorderMode() != 0)
6082 out << " " << cname << "->SetFrameBorderMode(" << frame->GetBorderMode() << ");\n";
6083 if (frame->GetBorderSize() != 1)
6084 out << " " << cname << "->SetFrameBorderSize(" << frame->GetBorderSize() << ");\n";
6085 }
6086
6087 TIter next(GetListOfPrimitives());
6088
6089 while (auto obj = next()) {
6090 obj->SavePrimitive(out, (Option_t *)next.GetOption());
6091 if (obj->InheritsFrom(TPad::Class())) {
6092 if (opt.Contains("toplevel"))
6093 out << " " << pname << "->cd();\n";
6094 else
6095 out << " " << cname << "->cd();\n";
6096 }
6097 }
6098 out << " " << cname << "->Modified();\n";
6099}
6100
6101////////////////////////////////////////////////////////////////////////////////
6102/// Fix pad aspect ratio to current value if fixed is true.
6103
6105{
6106 if (fixed) {
6107 if (!fFixedAspectRatio) {
6108 if (fHNDC != 0.)
6110 else {
6111 Error("SetAspectRatio", "cannot fix aspect ratio, height of pad is 0");
6112 return;
6113 }
6115 }
6116 } else {
6118 fAspectRatio = 0;
6119 }
6120}
6121
6122////////////////////////////////////////////////////////////////////////////////
6123/// Set pad editable yes/no
6124/// If a pad is not editable:
6125/// - one cannot modify the pad and its objects via the mouse.
6126/// - one cannot add new objects to the pad
6127
6129{
6130 fEditable = mode;
6131
6132 TObject *obj;
6133 if (!fPrimitives) fPrimitives = new TList;
6134 TIter next(GetListOfPrimitives());
6135 while ((obj = next())) {
6136 if (obj->InheritsFrom(TPad::Class())) {
6137 TPad *pad = (TPad*)obj;
6138 pad->SetEditable(mode);
6139 }
6140 }
6141}
6142
6143////////////////////////////////////////////////////////////////////////////////
6144/// Override TAttFill::FillStyle for TPad because we want to handle style=0
6145/// as style 4000.
6146
6148{
6149 if (fstyle == 0) fstyle = 4000;
6151}
6152
6153////////////////////////////////////////////////////////////////////////////////
6154/// Set Lin/Log scale for X
6155/// - value = 0 X scale will be linear
6156/// - value = 1 X scale will be logarithmic (base 10)
6157/// - value > 1 reserved for possible support of base e or other
6158
6160{
6161 fLogx = value;
6162 delete fView; fView = nullptr;
6163 Modified();
6165}
6166
6167////////////////////////////////////////////////////////////////////////////////
6168/// Set Lin/Log scale for Y
6169/// - value = 0 Y scale will be linear
6170/// - value = 1 Y scale will be logarithmic (base 10)
6171/// - value > 1 reserved for possible support of base e or other
6172
6174{
6175 fLogy = value;
6176 delete fView; fView = nullptr;
6177 Modified();
6179}
6180
6181////////////////////////////////////////////////////////////////////////////////
6182/// Set Lin/Log scale for Z
6183
6185{
6186 fLogz = value;
6187 delete fView; fView = nullptr;
6188 Modified();
6190}
6191
6192////////////////////////////////////////////////////////////////////////////////
6193/// Set canvas range for pad and resize the pad. If the aspect ratio
6194/// was fixed before the call it will be un-fixed.
6195
6197{
6198 // Reorder points to make sure xlow,ylow is bottom left point and
6199 // xup,yup is top right point.
6200 if (xup < xlow) {
6201 Double_t x = xlow;
6202 xlow = xup;
6203 xup = x;
6204 }
6205 if (yup < ylow) {
6206 Double_t y = ylow;
6207 ylow = yup;
6208 yup = y;
6209 }
6210
6211 // Check if the new pad position is valid.
6212 if ((xlow < 0) || (xlow > 1) || (ylow < 0) || (ylow > 1)) {
6213 Error("TPad", "illegal bottom left position: x=%f, y=%f", xlow, ylow);
6214 return;
6215 }
6216 if ((xup < 0) || (xup > 1) || (yup < 0) || (yup > 1)) {
6217 Error("TPad", "illegal top right position: x=%f, y=%f", xup, yup);
6218 return;
6219 }
6220 if (xup-xlow <= 0) {
6221 Error("TPad", "illegal width: %f", xup-xlow);
6222 return;
6223 }
6224 if (yup-ylow <= 0) {
6225 Error("TPad", "illegal height: %f", yup-ylow);
6226 return;
6227 }
6228
6229 fXlowNDC = xlow;
6230 fYlowNDC = ylow;
6231 fXUpNDC = xup;
6232 fYUpNDC = yup;
6233 fWNDC = xup - xlow;
6234 fHNDC = yup - ylow;
6235
6237
6238 ResizePad();
6239}
6240
6241////////////////////////////////////////////////////////////////////////////////
6242/// Set all pad parameters.
6243
6244void TPad::SetPad(const char *name, const char *title,
6245 Double_t xlow, Double_t ylow, Double_t xup, Double_t yup,
6247{
6248 fName = name;
6249 fTitle = title;
6250 SetFillStyle(1001);
6255 if (color >= 0) SetFillColor(color);
6258 else fBorderSize = bordersize;
6260 else fBorderMode = bordermode;
6261
6262 SetPad(xlow, ylow, xup, yup);
6263}
6264
6265////////////////////////////////////////////////////////////////////////////////
6266/// Set the current TView. Delete previous view if view=0
6267
6269{
6270 if (!view) delete fView;
6271 fView = view;
6272}
6273
6274////////////////////////////////////////////////////////////////////////////////
6275/// Set postscript fill area attributes.
6276///
6277/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6278
6280{
6281 if (auto pp = GetPainter())
6282 if (pp->GetPS())
6283 pp->SetAttFill({color, style});
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->GetPS())
6295 pp->SetAttLine({color, style, lwidth});
6296}
6297
6298////////////////////////////////////////////////////////////////////////////////
6299/// Set postscript marker attributes.
6300///
6301/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6302
6304{
6305 if (auto pp = GetPainter())
6306 if (pp->GetPS())
6307 pp->SetAttMarker({color, style, msize});
6308}
6309
6310////////////////////////////////////////////////////////////////////////////////
6311/// Set postscript text attributes.
6312///
6313/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6314
6316{
6317 if (auto pp = GetPainter())
6318 if (pp->GetPS()) {
6319 if (font % 10 > 2) {
6322 Float_t dy;
6323 if (wh < hh) {
6325 tsize = dy/(GetX2()-GetX1());
6326 } else {
6328 tsize = dy/(GetY2()-GetY1());
6329 }
6330 }
6331 pp->SetAttText({align, angle, color, font, tsize});
6332 }
6333}
6334
6335////////////////////////////////////////////////////////////////////////////////
6336/// Draw Arrows to indicated equal distances of Objects with given BBoxes.
6337/// Used by ShowGuidelines
6338
6340{
6341 Int_t lineColor = TColor::GetColor(239, 202, 0);
6342 Int_t x1,x2,y1,y2;
6343 x1 = x2 = y1 = y2 = 0;
6344 if (mode == 'x') {
6345 if (aBBox.fX<bBBox.fX) {
6346 x1 = aBBox.fX+aBBox.fWidth;
6347 x2 = bBBox.fX;
6348 }
6349 else {
6350 x1 = bBBox.fX+bBBox.fWidth;
6351 x2 = aBBox.fX;
6352 }
6353
6354 if ((aBBox.fY > bBBox.fY) && (aBBox.fY + aBBox.fHeight < bBBox.fY + bBBox.fHeight))
6355 y1 = y2 = aBBox.fY + TMath::Nint(0.5*(Double_t)(aBBox.fHeight))+1;
6356 else if ((bBBox.fY > aBBox.fY) && (bBBox.fY + bBBox.fHeight < aBBox.fY + aBBox.fHeight))
6357 y1 = y2 = bBBox.fY + TMath::Nint(0.5*(Double_t)(bBBox.fHeight))+1;
6358 else if (aBBox.fY>bBBox.fY) y1 = y2 = aBBox.fY-TMath::Nint(0.5*(Double_t)(aBBox.fY-(bBBox.fY+bBBox.fHeight)));
6359 else y1 = y2 = bBBox.fY-TMath::Nint(0.5*(Double_t)(bBBox.fY-(aBBox.fY+aBBox.fHeight)));
6360 }
6361 else if (mode == 'y') {
6362 if (aBBox.fY<bBBox.fY) {
6363 y1 = aBBox.fY+aBBox.fHeight;
6364 y2 = bBBox.fY;
6365 }
6366 else {
6367 y1 = bBBox.fY+bBBox.fHeight;
6368 y2 = aBBox.fY;
6369 }
6370 if ((aBBox.fX > bBBox.fX) && (aBBox.fX + aBBox.fWidth < bBBox.fX + bBBox.fWidth))
6371 x1 = x2 = aBBox.fX + TMath::Nint(0.5*(Double_t)(aBBox.fWidth))+1;
6372 else if ((bBBox.fX > aBBox.fX) && (bBBox.fX + bBBox.fWidth < aBBox.fX + aBBox.fWidth))
6373 x1 = x2 = bBBox.fX + TMath::Nint(0.5*(Double_t)(bBBox.fWidth))+1;
6374 else if (aBBox.fX>bBBox.fX) x1 = x2 = aBBox.fX+TMath::Nint(0.5*(Double_t)(bBBox.fX+bBBox.fWidth-aBBox.fX));
6375 else x1 = x2 = bBBox.fX+TMath::Nint(0.5*(Double_t)(aBBox.fX+aBBox.fWidth-bBBox.fX));
6376 }
6377
6378 TArrow *A = new TArrow(gPad->PixeltoX(x1), gPad->PixeltoY(y1-gPad->VtoPixel(0)), gPad->PixeltoX(x2), gPad->PixeltoY(y2-gPad->VtoPixel(0)), 0.01, "<|>");
6379 A->SetBit(kCanDelete);
6381 A->SetLineWidth(1);
6383 A->Draw();
6384
6385 return;
6386}
6387
6388////////////////////////////////////////////////////////////////////////////////
6389/// struct used by ShowGuidelines to store the distance Field between objects
6390/// in the canvas.
6391
6392struct dField {
6396 char fdir;
6397
6398
6400 : fa(nullptr), fb(nullptr), fdist(0), fdir(' ')
6401 {}
6402
6404 : fa(a), fb(b), fdist(dist), fdir(direction)
6405 {}
6406};
6407
6408////////////////////////////////////////////////////////////////////////////////
6409/// Shows lines to indicate if a TAttBBox2D object is aligned to
6410/// the center or to another object, shows distance arrows if two
6411/// objects on screen have the same distance to another object
6412/// Call from primitive in Execute Event, in ButtonMotion after
6413/// the new coordinates have been set, to 'stick'
6414/// once when button is up to delete lines
6415///
6416/// modes: t (Top), b (bottom), l (left), r (right), i (inside)
6417/// in resize modes (t,b,l,r) only size arrows are sticky
6418///
6419/// in mode, the function gets the point on the element that is clicked to
6420/// move (i) or resize (all others). The expected values are:
6421/// \image html gpad_pad5.png
6422
6423void TPad::ShowGuidelines(TObject *object, const Int_t event, const char mode, const bool cling )
6424{
6425 // When the object is moved with arrow or when the ShowGuideLines flag
6426 // is off we do show guide lines.
6427 if ((event == kArrowKeyRelease) || (event == kArrowKeyPress) ||
6428 !gEnv->GetValue("Canvas.ShowGuideLines", 0)) return;
6429
6430 std::vector<dField> curDist;
6431 std::vector<dField> otherDist;
6432 Int_t pMX, pMY;
6433 Double_t MX, MY;
6435 TList *prims;
6436 UInt_t n;
6438 aBBox = bBBox = Rectangle_t();
6439 TLine *L;
6440 TArrow *A;
6441 Int_t dSizeArrow = 12; // distance of arrows indicating same size from BBox in px
6442 Bool_t movedX, movedY; // make sure the current object is moved just once
6443 movedX = movedY = false;
6444 Bool_t resize = false; // indicates resize mode
6445 Bool_t log = gPad->GetLogx() || gPad->GetLogy();
6446 if (mode != 'i') resize = true;
6447
6448 TPad *is_pad = dynamic_cast<TPad *>( object );
6449
6451
6452 if (is_pad && is_pad->GetMother())
6453 is_pad->GetMother()->cd();
6454
6455 static TPad *tmpGuideLinePad = nullptr;
6456
6457 //delete all existing Guidelines and create new invisible pad
6458 if (tmpGuideLinePad) {
6459 ctxt.PadDeleted(tmpGuideLinePad);
6460 auto guidePadClicked = (object == tmpGuideLinePad); // in case of funny button click combination.
6461 tmpGuideLinePad->Delete();
6462 tmpGuideLinePad = nullptr;
6463 if (guidePadClicked) return;
6464 }
6465
6466 // Get Primitives
6467 prims = gPad->GetListOfPrimitives();
6468 n = TMath::Min(15,prims->GetSize());
6469 Int_t lineColor = TColor::GetColor(239, 202, 0);
6470
6471 TAttBBox2D *cur = dynamic_cast<TAttBBox2D *>( object );
6472 if (cur) {
6473 //create invisible TPad above gPad
6474 if (!tmpGuideLinePad){
6475 tmpGuideLinePad = new TPad("tmpGuideLinePad", "tmpGuideLinePad", 0, 0, 1, 1);
6476 Double_t x1, y1, x2, y2;
6477 gPad->GetRange(x1, y1, x2, y2);
6478 tmpGuideLinePad->Range(x1, y1, x2, y2);
6479 tmpGuideLinePad->SetFillStyle(0);
6480 tmpGuideLinePad->SetFillColor(0);
6481 tmpGuideLinePad->Draw();
6482 tmpGuideLinePad->cd();
6483 gPad->GetRange(x1, y1, x2, y2);
6484 }
6485 if (cling && !log) threshold = 7;
6486 else threshold = 1;
6487
6488 Rectangle_t BBox = cur->GetBBox();
6489 TPoint center = cur->GetBBoxCenter();
6490
6491 otherDist.clear();
6492 curDist.clear();
6493
6494 switch (event) {
6495
6496 case kButton1Down:
6497 case kButton1Motion:
6498 MX = gPad->GetX1() + 0.5 * (gPad->GetX2()-gPad->GetX1());
6499 MY = gPad->GetY1() + 0.5 * (gPad->GetY2()-gPad->GetY1());
6500 pMX = gPad->XtoPixel(MX);
6501 pMY = gPad->YtoPixel(MY);
6502 // Middlelines
6503 if (TMath::Abs(pMX-center.GetX())<threshold) {
6504 if (cling && (!resize)) {
6505 cur->SetBBoxCenterX(pMX);
6506 center = cur->GetBBoxCenter();
6507 BBox = cur->GetBBox();
6508 center = cur->GetBBoxCenter();
6509 }
6510 L = new TLine(MX, gPad->GetY1(), MX, gPad->GetY2());
6511 L->SetBit(kCanDelete);
6512 L->SetLineColor(lineColor);
6513 L->Draw();
6514 }
6515 if (TMath::Abs(pMY-center.GetY())<threshold) {
6516 if (cling && (!resize)) {
6517 cur->SetBBoxCenterY(pMY);
6518 center = cur->GetBBoxCenter();
6519 BBox = cur->GetBBox();
6520 center = cur->GetBBoxCenter();
6521 }
6522 L = new TLine(gPad->GetX1(), MY, gPad->GetX2(), MY);
6523 L->SetBit(kCanDelete);
6524 L->SetLineColor(lineColor);
6525 L->Draw();
6526 }
6527 // Alignment to other objects
6528 for (UInt_t i = 0; i<n; i++) {
6529 TAttBBox2D *other = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6530 if (other) {
6531 if (other != cur) {
6532 TPoint centerOther = other->GetBBoxCenter();
6533 if (TMath::Abs(center.GetX()-centerOther.GetX())<threshold) {
6534 if (cling && (!resize)) {
6535 cur->SetBBoxCenterX(centerOther.GetX());
6536 BBox = cur->GetBBox();
6537 center = cur->GetBBoxCenter();
6538 }
6539 L = new TLine(gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(center.GetY()-gPad->VtoPixel(0)),
6540 gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)));
6541 L->SetLineColor(lineColor);
6542 L->Draw();
6543 L->SetBit(kCanDelete);
6544 }
6545 if (TMath::Abs(center.GetY()-centerOther.GetY())<threshold) {
6546 if (cling && (!resize)) {
6547 cur->SetBBoxCenterY(centerOther.GetY());
6548 BBox = cur->GetBBox();
6549 center = cur->GetBBoxCenter();
6550 }
6551 L = new TLine(gPad->PixeltoX(center.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)),
6552 gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)));
6553 L->SetBit(kCanDelete);
6554 L->SetLineColor(lineColor);
6555 L->Draw();
6556 }
6557 }
6558 }
6559 }
6560 // Get Distances between objects
6561 for (UInt_t i = 0; i<n; i++) {
6562 TAttBBox2D *a = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6563 if (a) {
6564 aBBox = a->GetBBox();
6565 for (UInt_t j = i+1; j<n; j++) {
6566 TAttBBox2D *b = dynamic_cast<TAttBBox2D *>( prims->At(j) );
6567 if (b) {
6568 bBBox = b->GetBBox();
6569
6570 //only when bounding boxes overlap in x or y direction
6571 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
6572 if ((aBBox.fY+aBBox.fHeight<bBBox.fY)||(bBBox.fY+bBBox.fHeight<aBBox.fY)) {//No overlap in Y-direction required
6573 dField abDist = dField();
6574 if (aBBox.fY>bBBox.fY) abDist = dField(a, b, TMath::Abs(aBBox.fY-(bBBox.fY+bBBox.fHeight)), 'y');
6575 else abDist = dField(a, b, TMath::Abs(bBBox.fY-(aBBox.fY+aBBox.fHeight)), 'y');
6576 if ((b != cur)&&(a != cur)) otherDist.push_back(abDist);
6577 else curDist.push_back(abDist);
6578 }
6579 } 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
6580 if ((aBBox.fX+aBBox.fWidth<bBBox.fX)||(bBBox.fX+bBBox.fWidth<aBBox.fX)) {//No overlap in x-direction required
6581 dField abDist = dField();
6582 if (aBBox.fX>bBBox.fX) abDist = dField(a, b, TMath::Abs(aBBox.fX-(bBBox.fX+bBBox.fWidth)), 'x');
6583 else abDist = dField(a, b, TMath::Abs(bBBox.fX-(aBBox.fX+aBBox.fWidth)), 'x');
6584 if ((b != cur)&&(a != cur)) otherDist.push_back(abDist);
6585 else curDist.push_back(abDist);
6586 }
6587 }
6588 }
6589 }
6590 }
6591 }
6592 // Show equal distances
6593 for (UInt_t i = 0; i<curDist.size(); i++) {
6594 for (UInt_t j = 0; j<otherDist.size(); j++) {
6595 if ((curDist[i].fdir == otherDist[j].fdir) && (otherDist[j].fdir=='x') && (TMath::Abs(curDist[i].fdist-otherDist[j].fdist)<threshold)) {
6596 if (cling && (!movedX) && (!resize)) {
6597 if ((cur->GetBBoxCenter().fX < curDist[i].fb->GetBBoxCenter().fX)||(cur->GetBBoxCenter().fX < curDist[i].fa->GetBBoxCenter().fX))
6598 cur->SetBBoxCenterX(cur->GetBBoxCenter().fX - otherDist[j].fdist + curDist[i].fdist);
6599 else cur->SetBBoxCenterX(cur->GetBBoxCenter().fX + otherDist[j].fdist - curDist[i].fdist);
6600 movedX = true;
6601 }
6602 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'x');
6603 DrawDist(otherDist[j].fa->GetBBox(), otherDist[j].fb->GetBBox(), 'x');
6604 }
6605 if ((curDist[i].fdir == otherDist[j].fdir) && (otherDist[j].fdir=='y') && (TMath::Abs(curDist[i].fdist-otherDist[j].fdist)<threshold)) {
6606 if (cling && (!movedY) && (!resize)) {
6607 if ((cur->GetBBoxCenter().fY < curDist[i].fb->GetBBoxCenter().fY)||(cur->GetBBoxCenter().fY < curDist[i].fa->GetBBoxCenter().fY))
6608 cur->SetBBoxCenterY(cur->GetBBoxCenter().fY - otherDist[j].fdist + curDist[i].fdist);
6609 else cur->SetBBoxCenterY(cur->GetBBoxCenter().fY + otherDist[j].fdist - curDist[i].fdist);
6610 movedY = true;
6611 }
6612 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'y');
6613 DrawDist(otherDist[j].fa->GetBBox(), otherDist[j].fb->GetBBox(), 'y');
6614 }
6615 }
6616 for (UInt_t j = i; j<curDist.size(); j++) {
6617 if (i!=j) {
6618 if ((curDist[i].fdir == curDist[j].fdir) && (curDist[j].fdir=='x') && (TMath::Abs(curDist[i].fdist-curDist[j].fdist)<threshold)) {
6619 if (cling && (!movedX) && (!resize)) {
6620 if ((cur->GetBBoxCenter().fX < curDist[i].fb->GetBBoxCenter().fX)||(cur->GetBBoxCenter().fX < curDist[i].fa->GetBBoxCenter().fX))
6621 cur->SetBBoxCenterX(cur->GetBBoxCenter().fX - floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6622 else cur->SetBBoxCenterX(cur->GetBBoxCenter().fX + floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6623 }
6624 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'x');
6625 DrawDist(curDist[j].fa->GetBBox(), curDist[j].fb->GetBBox(), 'x');
6626 }
6627
6628 if ((curDist[i].fdir == curDist[j].fdir) && (curDist[j].fdir=='y') && (TMath::Abs(curDist[i].fdist-curDist[j].fdist)<threshold)) {
6629 if (cling && (!movedY) && (!resize)) {
6630 if ((cur->GetBBoxCenter().fY < curDist[i].fb->GetBBoxCenter().fY)||(cur->GetBBoxCenter().fY < curDist[i].fa->GetBBoxCenter().fY))
6631 cur->SetBBoxCenterY(cur->GetBBoxCenter().fY - floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6632 else cur->SetBBoxCenterY(cur->GetBBoxCenter().fY + floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6633 }
6634 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'y');
6635 DrawDist(curDist[j].fa->GetBBox(), curDist[j].fb->GetBBox(), 'y');
6636 }
6637 }
6638 }
6639 }
6640 if (resize) {
6641 // Show equal Sizes
6642 for (UInt_t i = 0; i<n; i++) {
6643 TAttBBox2D *a = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6644 if (a && (cur != a)) {
6645 aBBox = a->GetBBox();
6646
6647 if ((TMath::Abs(aBBox.fWidth - BBox.fWidth)<threshold) && (mode != 't') && (mode != 'b')) {
6648 if (cling) {
6649 if (mode == 'l') cur->SetBBoxX1(BBox.fX + BBox.fWidth - aBBox.fWidth);
6650 if (mode == 'r') cur->SetBBoxX2(BBox.fX + aBBox.fWidth);
6651 if ((mode == '1')||(mode == '4')) cur->SetBBoxX1(BBox.fX + BBox.fWidth - aBBox.fWidth);
6652 if ((mode == '2')||(mode == '3')) cur->SetBBoxX2(BBox.fX + aBBox.fWidth);
6653 BBox = cur->GetBBox();
6654 }
6655
6656 A = new TArrow(gPad->PixeltoX(aBBox.fX), gPad->PixeltoY(aBBox.fY-dSizeArrow-gPad->VtoPixel(0)),
6657 gPad->PixeltoX(aBBox.fX+aBBox.fWidth), gPad->PixeltoY(aBBox.fY-dSizeArrow-gPad->VtoPixel(0)), 0.01, "<|>");
6658 A->SetBit(kCanDelete);
6661 A->Draw();
6662
6663 A = new TArrow(gPad->PixeltoX(BBox.fX), gPad->PixeltoY(BBox.fY-dSizeArrow-gPad->VtoPixel(0)),
6664 gPad->PixeltoX(BBox.fX+BBox.fWidth), gPad->PixeltoY(BBox.fY-dSizeArrow-gPad->VtoPixel(0)), 0.01, "<|>");
6665 A->SetBit(kCanDelete);
6668 A->Draw();
6669 }
6670 if ((TMath::Abs(aBBox.fHeight - BBox.fHeight)<threshold) && (mode != 'r') && (mode != 'l')) {
6671 if (cling) {
6672 if (mode == 't') cur->SetBBoxY1(BBox.fY + BBox.fHeight - aBBox.fHeight);
6673 if (mode == 'b') cur->SetBBoxY2(BBox.fY + aBBox.fHeight);
6674 if ((mode == '1')||(mode == '2')) cur->SetBBoxY1(BBox.fY + BBox.fHeight - aBBox.fHeight);
6675 if ((mode == '3')||(mode == '4')) cur->SetBBoxY2(BBox.fY + aBBox.fHeight);
6676 BBox = cur->GetBBox();
6677 }
6678 A = new TArrow(gPad->PixeltoX(aBBox.fX-dSizeArrow), gPad->PixeltoY(aBBox.fY-gPad->VtoPixel(0)),
6679 gPad->PixeltoX(aBBox.fX-dSizeArrow), gPad->PixeltoY(aBBox.fY+aBBox.fHeight-gPad->VtoPixel(0)), 0.01, "<|>");
6680 A->SetBit(kCanDelete);
6683 A->Draw();
6684
6685 A = new TArrow(gPad->PixeltoX(BBox.fX-dSizeArrow), gPad->PixeltoY(BBox.fY-gPad->VtoPixel(0)),
6686 gPad->PixeltoX(BBox.fX-dSizeArrow), gPad->PixeltoY(BBox.fY+BBox.fHeight-gPad->VtoPixel(0)), 0.01, "<|>");
6687 A->SetBit(kCanDelete);
6690 A->Draw();
6691 }
6692 }
6693 }
6694 }
6695
6696 break;
6697
6698 case kButton1Up:
6699 if (tmpGuideLinePad) {
6700 // All the arrows and lines in that pad are also deleted because
6701 // they all have the bit kCanDelete on.
6702 tmpGuideLinePad->Delete();
6703 tmpGuideLinePad = nullptr;
6704 }
6705 break;
6706 }
6707 }
6708
6709 gPad->Modified(kTRUE);
6710}
6711
6712////////////////////////////////////////////////////////////////////////////////
6713/// Return kTRUE if the crosshair has been activated (via SetCrosshair).
6714
6716{
6717 return (Bool_t)GetCrosshair();
6718}
6719
6720////////////////////////////////////////////////////////////////////////////////
6721/// Return the crosshair type (from the mother canvas)
6722/// crosshair type = 0 means no crosshair.
6723
6725{
6726 if (this == (TPad*)fCanvas)
6727 return fCrosshair;
6728 return fCanvas ? fCanvas->GetCrosshair() : 0;
6729}
6730
6731////////////////////////////////////////////////////////////////////////////////
6732/// Set crosshair active/inactive.
6733/// - If crhair != 0, a crosshair will be drawn in the pad and its sub-pads.
6734/// - If the canvas crhair = 1 , the crosshair spans the full canvas.
6735/// - If the canvas crhair > 1 , the crosshair spans only the pad.
6736
6738{
6739 if (!fCanvas) return;
6741 fCrosshairPos = 0;
6742
6743 if (this != (TPad*)fCanvas) fCanvas->SetCrosshair(crhair);
6744}
6745
6746////////////////////////////////////////////////////////////////////////////////
6747/// static function to set the maximum Pick Distance fgMaxPickDistance
6748/// This parameter is used in TPad::Pick to select an object if
6749/// its DistancetoPrimitive returns a value < fgMaxPickDistance
6750/// The default value is 5 pixels. Setting a smaller value will make
6751/// picking more precise but also more difficult
6752
6757
6758////////////////////////////////////////////////////////////////////////////////
6759/// Set tool tip text associated with this pad. The delay is in
6760/// milliseconds (minimum 250). To remove tool tip call method with
6761/// text = 0.
6762
6764{
6765 if (fTip) {
6767 fTip = nullptr;
6768 }
6769
6770 if (text && strlen(text))
6771 fTip = CreateToolTip((TBox*)nullptr, text, delayms);
6772}
6773
6774////////////////////////////////////////////////////////////////////////////////
6775/// Set pad vertical (default) or horizontal
6776
6778{
6779 if (vert) ResetBit(kHori);
6780 else SetBit(kHori);
6781}
6782
6783////////////////////////////////////////////////////////////////////////////////
6784/// Stream a class object.
6785
6787{
6788 UInt_t R__s, R__c;
6791 TObject *obj;
6792 if (b.IsReading()) {
6793 Version_t v = b.ReadVersion(&R__s, &R__c);
6794 if (v > 5) {
6795 if (!gPad)
6796 gPad = new TCanvas(GetName());
6797 fMother = (TPad*)gPad;
6799 TContext ctxt(this, kFALSE);
6800 fPixmapID = -1; // -1 means pixmap will be created by ResizePad()
6801 gReadLevel++;
6802 gROOT->SetReadingObject(kTRUE);
6803
6804 b.ReadClassBuffer(TPad::Class(), this, v, R__s, R__c);
6805
6806 //Set the kCanDelete bit in all objects in the pad such that when the pad
6807 //is deleted all objects in the pad are deleted too.
6808 //Also set must cleanup bit which normally set for all primitives add to pad,
6809 // but may be reset in IO like TH1::Streamer does
6810 TIter next(fPrimitives);
6811 while ((obj = next())) {
6812 obj->SetBit(kCanDelete);
6813 obj->SetBit(kMustCleanup);
6814 }
6815
6816 fModified = kTRUE;
6817 fPadPointer = nullptr;
6818 gReadLevel--;
6819 if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
6820 gROOT->SetReadingObject(kFALSE);
6821 return;
6822 }
6823
6824 //====process old versions before automatic schema evolution
6825 if (v < 5) { //old TPad in single precision
6826 if (v < 3) { //old TPad derived from TWbox
6827 b.ReadVersion(); // TVirtualPad::Streamer(b)
6828 b.ReadVersion(); // TWbox::Streamer(b)
6829 b.ReadVersion(); // TBox::Streamer(b)
6833 b >> single; fX1 = single;
6834 b >> single; fY1 = single;
6835 b >> single; fX2 = single;
6836 b >> single; fY2 = single;
6837 b >> fBorderSize;
6838 b >> fBorderMode;
6840 } else { //new TPad
6843 b >> single; fX1 = single;
6844 b >> single; fY1 = single;
6845 b >> single; fX2 = single;
6846 b >> single; fY2 = single;
6847 b >> fBorderSize;
6848 b >> fBorderMode;
6849 }
6850 b >> fLogx;
6851 b >> fLogy;
6852 b >> fLogz;
6854 b >> single; fXtoPixelk = single;
6855 b >> single; fXtoPixel = single;
6857 b >> single; fYtoPixelk = single;
6858 b >> single; fYtoPixel = single;
6860 b >> single; fUtoPixelk = single;
6861 b >> single; fUtoPixel = single;
6863 b >> single; fVtoPixelk = single;
6864 b >> single; fVtoPixel = single;
6866 b >> single; fPixeltoXk = single;
6867 b >> single; fPixeltoX = single;
6869 b >> single; fPixeltoYk = single;
6870 b >> single; fPixeltoY = single;
6871 b >> single; fXlowNDC = single;
6872 b >> single; fYlowNDC = single;
6873 b >> single; fWNDC = single;
6874 b >> single; fHNDC = single;
6875 b >> single; fAbsXlowNDC = single;
6876 b >> single; fAbsYlowNDC = single;
6877 b >> single; fAbsWNDC = single;
6878 b >> single; fAbsHNDC = single;
6879 b >> single; fUxmin = single;
6880 b >> single; fUymin = single;
6881 b >> single; fUxmax = single;
6882 b >> single; fUymax = single;
6883 } else {
6886 b >> fX1;
6887 b >> fY1;
6888 b >> fX2;
6889 b >> fY2;
6890 b >> fBorderSize;
6891 b >> fBorderMode;
6892 b >> fLogx;
6893 b >> fLogy;
6894 b >> fLogz;
6895 b >> fXtoAbsPixelk;
6896 b >> fXtoPixelk;
6897 b >> fXtoPixel;
6898 b >> fYtoAbsPixelk;
6899 b >> fYtoPixelk;
6900 b >> fYtoPixel;
6901 b >> fUtoAbsPixelk;
6902 b >> fUtoPixelk;
6903 b >> fUtoPixel;
6904 b >> fVtoAbsPixelk;
6905 b >> fVtoPixelk;
6906 b >> fVtoPixel;
6907 b >> fAbsPixeltoXk;
6908 b >> fPixeltoXk;
6909 b >> fPixeltoX;
6910 b >> fAbsPixeltoYk;
6911 b >> fPixeltoYk;
6912 b >> fPixeltoY;
6913 b >> fXlowNDC;
6914 b >> fYlowNDC;
6915 b >> fWNDC;
6916 b >> fHNDC;
6917 b >> fAbsXlowNDC;
6918 b >> fAbsYlowNDC;
6919 b >> fAbsWNDC;
6920 b >> fAbsHNDC;
6921 b >> fUxmin;
6922 b >> fUymin;
6923 b >> fUxmax;
6924 b >> fUymax;
6925 }
6926
6927 if (!gPad)
6928 gPad = new TCanvas(GetName());
6929 if (gReadLevel == 0)
6931 else
6932 fMother = (TPad *)gPad;
6933 if (!fMother)
6934 fMother = (TPad *)gPad;
6935 if (fMother)
6937 gPad = fMother;
6938 fPixmapID = -1; // -1 means pixmap will be created by ResizePad()
6939 //-------------------------
6940 // read objects and their drawing options
6941 // b >> fPrimitives;
6942 gReadLevel++;
6943 gROOT->SetReadingObject(kTRUE);
6944 fPrimitives = new TList;
6945 b >> nobjects;
6946 if (nobjects > 0) {
6947 TContext ctxt(this, kFALSE);
6948 char drawoption[64];
6949 for (Int_t i = 0; i < nobjects; i++) {
6950 b >> obj;
6951 b >> nch;
6952 b.ReadFastArray(drawoption,nch);
6954 gPad = this; // gPad may be modified in b >> obj if obj is a pad
6955 }
6956 }
6957 gReadLevel--;
6958 gROOT->SetReadingObject(kFALSE);
6959 //////////////////////////////////////////////////////////////////////////
6960
6961 if (v > 3) {
6962 b >> fExecs;
6963 }
6964 fName.Streamer(b);
6965 fTitle.Streamer(b);
6966 b >> fPadPaint;
6967 fModified = kTRUE;
6968 b >> fGridx;
6969 b >> fGridy;
6970 b >> fFrame;
6971 b >> fView;
6972 if (v < 5) {
6973 b >> single; fTheta = single;
6974 b >> single; fPhi = single;
6975 } else {
6976 b >> fTheta;
6977 b >> fPhi;
6978 }
6979 fPadPointer = nullptr;
6980 b >> fNumber;
6981 b >> fAbsCoord;
6982 if (v > 1) {
6983 b >> fTickx;
6984 b >> fTicky;
6985 } else {
6986 fTickx = fTicky = 0;
6987 }
6988 if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
6989 b.CheckByteCount(R__s, R__c, TPad::IsA());
6990 //====end of old versions
6991
6992 } else {
6993 b.WriteClassBuffer(TPad::Class(),this);
6994 }
6995}
6996
6997////////////////////////////////////////////////////////////////////////////////
6998/// Force a copy of current style for all objects in pad.
6999
7001{
7002 if (gStyle->IsReading()) {
7014 fLogx = gStyle->GetOptLogx();
7015 fLogy = gStyle->GetOptLogy();
7016 fLogz = gStyle->GetOptLogz();
7017 } else {
7032 }
7033
7034 if (!fPrimitives) fPrimitives = new TList;
7035 TIter next(GetListOfPrimitives());
7036 TObject *obj;
7037
7038 while ((obj = next())) {
7039 obj->UseCurrentStyle();
7040 }
7041
7042 TPaveText *title = (TPaveText*)FindObject("title");
7043 if (title) {
7044 if (gStyle->IsReading()) {
7046 title->SetTextFont(gStyle->GetTitleFont(""));
7049 if (!gStyle->GetOptTitle()) delete title;
7050 } else {
7052 gStyle->SetTitleFont(title->GetTextFont());
7055 }
7056 }
7058
7059 if (gStyle->IsReading()) Modified();
7060}
7061
7062////////////////////////////////////////////////////////////////////////////////
7063/// Loop and sleep until a primitive with name=pname is found in the pad.
7064///
7065/// If emode is given, the editor is automatically set to emode, ie
7066/// it is not required to have the editor control bar.
7067///
7068/// The possible values for emode are:
7069/// - emode = "" (default). User will select the mode via the editor bar
7070/// - emode = "Arc", "Line", "Arrow", "Button", "Diamond", "Ellipse",
7071/// - emode = "Pad","pave", "PaveLabel","PaveText", "PavesText",
7072/// - emode = "PolyLine", "CurlyLine", "CurlyArc", "Text", "Marker", "CutG"
7073///
7074/// If emode is specified and it is not valid, "PolyLine" is assumed. If emode
7075/// is not specified or ="", an attempt is to use pname[1...]
7076///
7077/// for example if pname="TArc", emode="Arc" will be assumed.
7078/// When this function is called within a macro, the macro execution
7079/// is suspended until a primitive corresponding to the arguments
7080/// is found in the pad.
7081///
7082/// If CRTL/C is typed in the pad, the function returns 0.
7083///
7084/// While this function is executing, one can use the mouse, interact
7085/// with the graphics pads, use the Inspector, Browser, TreeViewer, etc.
7086///
7087/// Examples:
7088/// ~~~ {.cpp}
7089/// c1.WaitPrimitive(); // Return the first created primitive
7090/// // whatever it is.
7091/// // If a double-click with the mouse is executed
7092/// // in the pad or any key pressed, the function
7093/// // returns 0.
7094/// c1.WaitPrimitive("ggg"); // Set the editor in mode "PolyLine/Graph"
7095/// // Create a polyline, then using the context
7096/// // menu item "SetName", change the name
7097/// // of the created TGraph to "ggg"
7098/// c1.WaitPrimitive("TArc");// Set the editor in mode "Arc". Returns
7099/// // as soon as a TArc object is created.
7100/// c1.WaitPrimitive("lat","Text"); // Set the editor in Text/Latex mode.
7101/// // Create a text object, then Set its name to "lat"
7102/// ~~~
7103/// The following macro waits for 10 primitives of any type to be created.
7104///
7105/// ~~~ {.cpp}
7106///{
7107/// TCanvas c1("c1");
7108/// TObject *obj;
7109/// for (Int_t i=0;i<10;i++) {
7110/// obj = gPad->WaitPrimitive();
7111/// if (!obj) break;
7112/// printf("Loop i=%d, found objIsA=%s, name=%s\n",
7113/// i,obj->ClassName(),obj->GetName());
7114/// }
7115///}
7116/// ~~~
7117///
7118/// If ROOT runs in batch mode a call to this method does nothing.
7119
7120TObject *TPad::WaitPrimitive(const char *pname, const char *emode)
7121{
7122 if (!gPad || IsWeb())
7123 return nullptr;
7124
7125 if (emode && strlen(emode)) gROOT->SetEditorMode(emode);
7126 if (gROOT->GetEditorMode() == 0 && pname && strlen(pname) > 2) gROOT->SetEditorMode(&pname[1]);
7127
7128 if (!fPrimitives) fPrimitives = new TList;
7130 TObject *oldlast = gPad->GetListOfPrimitives() ? gPad->GetListOfPrimitives()->Last() : nullptr;
7131 TObject *obj = nullptr;
7133 Bool_t hasname = pname && (strlen(pname) > 0);
7134 if ((!pname || !pname[0]) && (!emode || !emode[0])) testlast = kTRUE;
7135 if (testlast) gROOT->SetEditorMode();
7136 while (!gSystem->ProcessEvents() && gROOT->GetSelectedPad() && gPad) {
7137 if (gROOT->GetEditorMode() == 0) {
7138 if (hasname) {
7139 obj = FindObject(pname);
7140 if (obj) return obj;
7141 }
7142 if (testlast) {
7143 if (!gPad->GetListOfPrimitives()) return nullptr;
7144 obj = gPad->GetListOfPrimitives()->Last();
7145 if (obj != oldlast) return obj;
7146 Int_t event = GetEvent();
7147 if (event == kButton1Double || event == kKeyPress) {
7148 //the following statement is required against other loop executions
7149 //before returning
7150 fCanvas->HandleInput((EEventType)-1,0,0);
7151 return nullptr;
7152 }
7153 }
7154 }
7155 gSystem->Sleep(10);
7156 }
7157
7158 return nullptr;
7159}
7160
7161////////////////////////////////////////////////////////////////////////////////
7162/// Create a tool tip and return its pointer.
7163
7165{
7166 if (gPad->IsBatch()) return nullptr;
7167 return (TObject*)gROOT->ProcessLineFast(TString::Format("new TGToolTip((TBox*)0x%zx,\"%s\",%d)",
7168 (size_t)box,text,(Int_t)delayms).Data());
7169}
7170
7171////////////////////////////////////////////////////////////////////////////////
7172/// Delete tool tip object.
7173
7175{
7176 // delete tip;
7177 if (!tip) return;
7178 gROOT->ProcessLineFast(TString::Format("delete (TGToolTip*)0x%zx", (size_t)tip).Data());
7179}
7180
7181////////////////////////////////////////////////////////////////////////////////
7182/// Reset tool tip, i.e. within time specified in CreateToolTip the
7183/// tool tip will pop up.
7184
7186{
7187 if (!tip) return;
7188 // tip->Reset(this);
7189 gROOT->ProcessLineFast(TString::Format("((TGToolTip*)0x%zx)->Reset((TPad*)0x%zx)",
7190 (size_t)tip,(size_t)this).Data());
7191}
7192
7193////////////////////////////////////////////////////////////////////////////////
7194/// Hide tool tip.
7195
7197{
7198 if (!tip) return;
7199 // tip->Hide();
7200 gROOT->ProcessLineFast(TString::Format("((TGToolTip*)0x%zx)->Hide()", (size_t)tip).Data());
7201}
7202
7203////////////////////////////////////////////////////////////////////////////////
7204/// Deprecated: use TPad::GetViewer3D() instead
7205
7207{
7208 ::Info("TPad::x3d()", "This function is deprecated. Use %s->GetViewer3D(\"x3d\") instead",this->GetName());
7209
7210 // Default on GetViewer3D is pad - for x3d it was x3d...
7211 if (!type || !type[0]) {
7212 type = "x3d";
7213 }
7215}
7216
7217////////////////////////////////////////////////////////////////////////////////
7218/// Create/obtain handle to 3D viewer. Valid types are:
7219/// - 'pad' - pad drawing via TViewer3DPad
7220/// any others registered with plugin manager supporting TVirtualViewer3D
7221/// If an invalid/null type is requested then the current viewer is returned
7222/// (if any), otherwise a default 'pad' type is returned
7223
7225{
7227
7228 if ((!type || !*type || (strstr(type, "gl") && !strstr(type, "ogl"))) && (!fCanvas || !fCanvas->UseGL()))
7229 type = "pad";
7230
7231 if (type && *type) {
7232 if (gPluginMgr->FindHandler("TVirtualViewer3D", type))
7233 validType = kTRUE;
7234 }
7235
7236 // Invalid/null type requested?
7237 if (!validType) {
7238 // Return current viewer if there is one
7239 if (fViewer3D)
7240 return fViewer3D;
7241 // otherwise default to the pad
7242 else
7243 type = "pad";
7244 }
7245
7246 // Ensure we can create the new viewer before removing any existing one
7247 TVirtualViewer3D *newViewer = nullptr;
7248
7250
7251 // External viewers need to be created via plugin manager via interface...
7252 if (!strstr(type,"pad")) {
7254
7255 if (!newViewer) {
7256 Warning("GetViewer3D", "Cannot create 3D viewer of type: %s", type);
7257 // Return the existing viewer
7258 return fViewer3D;
7259 }
7260
7261 if (strstr(type, "gl") && !strstr(type, "ogl")) {
7264 Modified();
7265 } else {
7267 }
7268
7269 } else {
7270 newViewer = new TViewer3DPad(*this);
7271 }
7272
7273 // If we had a previous viewer destroy it now
7274 // In this case we do take responsibility for destroying viewer
7275 // c.f. ReleaseViewer3D
7276 delete fViewer3D;
7277
7278 // Set and return new viewer
7280
7281 // Ensure any new external viewer is painted
7282 // For internal TViewer3DPad type we assume this is being
7283 // create on demand due to a paint - so this is not required
7284 if (createdExternal) {
7285 Modified();
7286 Update();
7287 }
7288
7289 return fViewer3D;
7290}
7291
7292////////////////////////////////////////////////////////////////////////////////
7293/// Release current (external) viewer
7294
7296{
7297 fViewer3D = nullptr;
7298
7299 // We would like to ensure the pad is repainted
7300 // when external viewer is closed down. However
7301 // a modify/paint call here will repaint the pad
7302 // before the external viewer window actually closes.
7303 // So the pad would have to be redraw twice over.
7304 // Currently we just have to live with the pad staying blank
7305 // any click in pad will refresh.
7306}
7307
7308////////////////////////////////////////////////////////////////////////////////
7309/// Get GL device.
7310
7312{
7313 return fGLDevice;
7314}
7315
7316////////////////////////////////////////////////////////////////////////////////
7317/// Emit RecordPave() signal.
7318
7320{
7321 Emit("RecordPave(const TObject*)", (Longptr_t)obj);
7322}
7323
7324////////////////////////////////////////////////////////////////////////////////
7325/// Emit RecordLatex() signal.
7326
7328{
7329 Emit("RecordLatex(const TObject*)", (Longptr_t)obj);
7330}
7331
7332////////////////////////////////////////////////////////////////////////////////
7333/// Get pad painter from TCanvas.
7334
7336{
7337 if (!fCanvas) return nullptr;
7338 return fCanvas->GetCanvasPainter();
7339}
7340
7341////////////////////////////////////////////////////////////////////////////////
7342/// Return the bounding Box of the Pad
7343
7345{
7346 Rectangle_t BBox{0, 0, 0, 0};
7347 if (gPad) {
7348 BBox.fX = gPad->XtoPixel(fXlowNDC * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1());
7349 BBox.fY = gPad->YtoPixel((fYlowNDC + fHNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1());
7350 BBox.fWidth = gPad->XtoPixel((fXlowNDC + fWNDC) * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1()) -
7351 gPad->XtoPixel(fXlowNDC * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1());
7352 BBox.fHeight = gPad->YtoPixel((fYlowNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1()) -
7353 gPad->YtoPixel((fYlowNDC + fHNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1());
7354 }
7355 return BBox;
7356}
7357
7358////////////////////////////////////////////////////////////////////////////////
7359/// Return the center of the Pad as TPoint in pixels
7360
7362{
7363 TPoint p(0, 0);
7364 if (gPad) {
7365 Double_t x = ((fXlowNDC + 0.5 * fWNDC) * (gPad->GetX2() - gPad->GetX1())) + gPad->GetX1();
7366 Double_t y = ((fYlowNDC + 0.5 * fHNDC) * (gPad->GetY2() - gPad->GetY1())) + gPad->GetY1();
7367 p.SetX(gPad->XtoPixel(x));
7368 p.SetY(gPad->YtoPixel(y));
7369 }
7370 return p;
7371}
7372
7373////////////////////////////////////////////////////////////////////////////////
7374/// Set center of the Pad
7375
7377{
7378 if (!gPad)
7379 return;
7380 fXlowNDC = (gPad->PixeltoX(p.GetX()) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1()) - 0.5 * fWNDC;
7381 fYlowNDC =
7382 (gPad->PixeltoY(p.GetY() - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - 0.5 * fHNDC;
7383 ResizePad();
7384}
7385
7386////////////////////////////////////////////////////////////////////////////////
7387/// Set X coordinate of the center of the Pad
7388
7390{
7391 if (!gPad)
7392 return;
7393 fXlowNDC = (gPad->PixeltoX(x) - gPad->GetX1())/(gPad->GetX2()-gPad->GetX1())-0.5*fWNDC;
7394 ResizePad();
7395}
7396
7397////////////////////////////////////////////////////////////////////////////////
7398/// Set Y coordinate of the center of the Pad
7399
7401{
7402 if (!gPad)
7403 return;
7404 fYlowNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - 0.5 * fHNDC;
7405 ResizePad();
7406}
7407
7408////////////////////////////////////////////////////////////////////////////////
7409/// Set lefthandside of BoundingBox to a value
7410/// (resize in x direction on left)
7411
7413{
7414 if (!gPad)
7415 return;
7416 fXlowNDC = (gPad->PixeltoX(x) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1());
7418 ResizePad();
7419}
7420
7421////////////////////////////////////////////////////////////////////////////////
7422/// Set right hand side of BoundingBox to a value
7423/// (resize in x direction on right)
7424
7426{
7427 if (!gPad)
7428 return;
7429 fWNDC = (gPad->PixeltoX(x) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1()) - fXlowNDC;
7430 ResizePad();
7431}
7432
7433////////////////////////////////////////////////////////////////////////////////
7434/// Set top of BoundingBox to a value (resize in y direction on top)
7435
7437{
7438 if (!gPad)
7439 return;
7440 fHNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - fYlowNDC;
7441 ResizePad();
7442}
7443
7444////////////////////////////////////////////////////////////////////////////////
7445/// Set bottom of BoundingBox to a value
7446/// (resize in y direction on bottom)
7447
7449{
7450 if (!gPad)
7451 return;
7452 fYlowNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1());
7454 ResizePad();
7455}
7456
7457////////////////////////////////////////////////////////////////////////////////
7458/// Mark pad modified
7459/// Will be repainted when TCanvas::Update() will be called next time
7460
7462{
7463 if (!fModified && flag) Emit("Modified()");
7464 fModified = flag;
7465}
7466
7467////////////////////////////////////////////////////////////////////////////////
7468/// Convert absolute pixel into X/Y coordinates
7469
7475
7476
7477////////////////////////////////////////////////////////////////////////////////
7478/// Convert pixel to X coordinate
7479
7481{
7482 if (fAbsCoord) return fAbsPixeltoXk + px*fPixeltoX;
7483 else return fPixeltoXk + px*fPixeltoX;
7484}
7485
7486////////////////////////////////////////////////////////////////////////////////
7487/// Convert pixel to Y coordinate
7488
7490{
7491 if (fAbsCoord) return fAbsPixeltoYk + py*fPixeltoY;
7492 else return fPixeltoYk + py*fPixeltoY;
7493}
7494
7495////////////////////////////////////////////////////////////////////////////////
7496/// Convert pixel to X/Y coordinates
7497
7503
7504////////////////////////////////////////////////////////////////////////////////
7505/// Convert X/Y into absolute pixel coordinates - integer
7506
7512
7513////////////////////////////////////////////////////////////////////////////////
7514/// Check value for valid range for pixel values
7515
7517{
7518 return v < -kMaxPixel ? -kMaxPixel : (v > kMaxPixel ? kMaxPixel : v);
7519}
7520
7521////////////////////////////////////////////////////////////////////////////////
7522/// Convert X/Y into absolute pixel coordinates - doble
7523/// Introduced to avoid pixel rounding problems
7524
7530
7531////////////////////////////////////////////////////////////////////////////////
7532/// Convert X/Y into pixel coordinates - integer
7533
7535{
7536 xpixel = XtoPixel(x);
7537 ypixel = YtoPixel(y);
7538}
7539
7540////////////////////////////////////////////////////////////////////////////////
7541/// Convert X/Y into pixel coordinates - double
7542
7548
7549////////////////////////////////////////////////////////////////////////////////
7550/// Convert X NDC to pixel
7551
7556
7557////////////////////////////////////////////////////////////////////////////////
7558/// Convert Y NDC to pixel
7559
7564
7565////////////////////////////////////////////////////////////////////////////////
7566/// Convert X NDC to absolute pixel
7567
7572
7573////////////////////////////////////////////////////////////////////////////////
7574/// Convert Y NDC to absolute pixel
7575
7580
7581////////////////////////////////////////////////////////////////////////////////
7582/// Convert X coordinate to absolute pixel
7583
7588
7589////////////////////////////////////////////////////////////////////////////////
7590/// Convert X coordinate to pixel
7591
7596
7597////////////////////////////////////////////////////////////////////////////////
7598/// Convert Y coordinate to absolute pixel
7599
7604
7605////////////////////////////////////////////////////////////////////////////////
7606/// Convert a vertical distance [y1,y2] to pixel
7607
7609{
7610 double h1 = fYtoAbsPixelk + y1 * fYtoPixel;
7611 double h2 = fYtoAbsPixelk + y2 * fYtoPixel;
7612 return TMath::Nint(pixel_boundary(std::abs(h1 - h2)));
7613}
7614
7615////////////////////////////////////////////////////////////////////////////////
7616/// Convert a horizontal distance [x1,x2] to pixel
7617
7619{
7620 double w1 = fXtoAbsPixelk + x1 * fXtoPixel;
7621 double w2 = fXtoAbsPixelk + x2 * fXtoPixel;
7622 return TMath::Nint(pixel_boundary(std::abs(w1 - w2)));
7623}
7624
7625
7626////////////////////////////////////////////////////////////////////////////////
7627/// Convert Y coordinate to pixel
7628
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:146
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:7516
static Int_t gReadLevel
Definition TPad.cxx:68
static Bool_t ContainsTImage(TList *li)
Auxiliary function.
Definition TPad.cxx:4927
#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
const_iterator begin() const
const_iterator end() const
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
Fill Area Attributes class.
Definition TAttFill.h:21
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
Line Attributes class.
Definition TAttLine.h:21
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:4741
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:6303
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:7560
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:6268
TVirtualViewer3D * GetViewer3D(Option_t *type="") override
Create/obtain handle to 3D viewer.
Definition TPad.cxx:7224
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:4213
void PaintLine3D(Float_t *p1, Float_t *p2) override
Paint 3-D line in the CurrentPad.
Definition TPad.cxx:4394
static Int_t fgMaxPickDistance
Maximum Pick Distance.
Definition TPad.h:115
void ResizePad(Option_t *option="") override
Compute pad conversion coefficients.
Definition TPad.cxx:5749
void PaintMarker3D(Double_t x, Double_t y, Double_t z) override
Paint 3-D marker in the CurrentPad.
Definition TPad.cxx:4430
void PaintPolyMarker(Int_t n, Float_t *x, Float_t *y, Option_t *option="") override
Paint polymarker in CurrentPad World coordinates.
Definition TPad.cxx:4583
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:7327
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:4062
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:5971
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:7436
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:6184
Bool_t fEmbeddedGL
!
Definition TPad.h:87
Int_t UtoAbsPixel(Double_t u) const override
Convert X NDC to absolute pixel.
Definition TPad.cxx:7568
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:7592
void SetAttFillPS(Color_t color, Style_t style) override
Set postscript fill area attributes.
Definition TPad.cxx:6279
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:7400
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:4080
~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:7174
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:7470
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:5532
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:6128
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:6753
void PixeltoXY(Double_t xpixel, Double_t ypixel, Double_t &x, Double_t &y) override
Convert pixel to X/Y coordinates.
Definition TPad.cxx:7498
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:7425
void SetBBoxX1(const Int_t x) override
Set lefthandside of BoundingBox to a value (resize in x direction on left)
Definition TPad.cxx:7412
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:6147
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:6244
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:7608
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:7534
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:7000
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:7576
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:5456
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:7507
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:7120
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:6315
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:7489
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:4777
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:4136
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:7629
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:4359
Int_t GetGLDevice() override
Get GL device.
Definition TPad.cxx:7311
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:7319
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:6173
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:7206
Bool_t HasCrosshair() const override
Return kTRUE if the crosshair has been activated (via SetCrosshair).
Definition TPad.cxx:6715
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:4090
void Modified(Bool_t flag=true) override
Mark pad modified Will be repainted when TCanvas::Update() will be called next time.
Definition TPad.cxx:7461
void RecursiveRemove(TObject *obj) override
Recursively remove object from a pad and its sub-pads.
Definition TPad.cxx:5514
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:7196
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:6763
void PaintPolyLine(Int_t n, Float_t *x, Float_t *y, Option_t *option="") override
Paint polyline in CurrentPad World coordinates.
Definition TPad.cxx:4453
Int_t WtoAbsPixel(Double_t x1, Double_t x2) const override
Convert a horizontal distance [x1,x2] to pixel.
Definition TPad.cxx:7618
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:4647
void Streamer(TBuffer &) override
Stream a class object.
Definition TPad.cxx:6786
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:4688
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:7552
TPoint GetBBoxCenter() override
Return the center of the Pad as TPoint in pixels.
Definition TPad.cxx:7361
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:6104
Short_t GetBorderSize() const override
Definition TPad.h:201
void RedrawAxis(Option_t *option="") override
Redraw the frame axis.
Definition TPad.cxx:5575
void DrawDist(Rectangle_t aBBox, Rectangle_t bBBox, char mode)
Draw Arrows to indicated equal distances of Objects with given BBoxes.
Definition TPad.cxx:6339
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:7600
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:4179
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:5494
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:7185
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:7344
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:6777
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:4702
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:5908
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:4381
void Print(const char *filename="") const override
This method is equivalent to SaveAs("filename"). See TPad::SaveAs for details.
Definition TPad.cxx:4918
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:7335
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:6423
Int_t GetCrosshair() const
Return the crosshair type (from the mother canvas) crosshair type = 0 means no crosshair.
Definition TPad.cxx:6724
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:7376
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:7480
void PaintPolyLineNDC(Int_t n, Double_t *x, Double_t *y, Option_t *option="") override
Paint polyline in CurrentPad NDC coordinates.
Definition TPad.cxx:4553
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:4728
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:4569
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:6159
void ReleaseViewer3D(Option_t *type="") override
Release current (external) viewer.
Definition TPad.cxx:7295
void SetCrosshair(Int_t crhair=1) override
Set crosshair active/inactive.
Definition TPad.cxx:6737
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:7389
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:7164
@ 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:4896
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:7584
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:7448
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
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:6392
TAttBBox2D * fb
Definition TPad.cxx:6394
dField()
Definition TPad.cxx:6399
char fdir
Definition TPad.cxx:6396
dField(TAttBBox2D *a, TAttBBox2D *b, Int_t dist, char direction)
Definition TPad.cxx:6403
TAttBBox2D * fa
Definition TPad.cxx:6393
Int_t fdist
Definition TPad.cxx:6395
TMarker m
Definition textangle.C:8