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