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