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