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 specified 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 specified 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 defines the horizontal spacing around each pad as a percentage of the canvas
1229/// width. Therefore, the distance between two adjacent pads along the x-axis is equal
1230/// to twice the xmargin value.
1231/// - ymargin defines the vertical spacing around each pad as a percentage of the canvas
1232/// height. Therefore, the distance between two adjacent pads along the y-axis is equal
1233/// to twice the ymargin value.
1234/// - color is the color of the new pads. If 0, color is the canvas color.
1235///
1236/// Pads are automatically named `canvasname_n` where `n` is the division number
1237/// starting from top left pad.
1238///
1239/// Example if canvasname=c1 , nx=2, ny=3:
1240///
1241/// \image html gpad_pad3.png
1242///
1243/// Once a pad is divided into sub-pads, one can set the current pad
1244/// to a subpad with a given division number as illustrated above
1245/// with TPad::cd(subpad_number).
1246///
1247/// For example, to set the current pad to c1_4, one can do:
1248/// ~~~ {.cpp}
1249/// c1->cd(4)
1250/// ~~~
1251/// __Note1:__ c1.cd() is equivalent to c1.cd(0) and sets the current pad
1252/// to c1 itself.
1253///
1254/// __Note2:__ after a statement like c1.cd(6), the global variable gPad
1255/// points to the current pad. One can use gPad to set attributes
1256/// of the current pad.
1257///
1258/// __Note3:__ in case xmargin < 0 or ymargin < 0, there is no space
1259/// between pads. The current pad margins are recomputed to
1260/// optimize the layout in order to have similar frames' areas.
1261/// See the following example:
1262///
1263/// ~~~ {.cpp}
1264/// void divpad(Int_t nx=3, Int_t ny=2) {
1265/// gStyle->SetOptStat(0);
1266/// auto C = new TCanvas();
1267/// C->SetMargin(0.3, 0.3, 0.3, 0.3);
1268/// C->Divide(nx,ny,-1);
1269/// Int_t number = 0;
1270/// auto h = new TH1F("","",100,-3.3,3.3);
1271/// h->GetXaxis()->SetLabelFont(43);
1272/// h->GetXaxis()->SetLabelSize(12);
1273/// h->GetYaxis()->SetLabelFont(43);
1274/// h->GetYaxis()->SetLabelSize(12);
1275/// h->GetYaxis()->SetNdivisions(505);
1276/// h->SetMaximum(30*nx*ny);
1277/// h->SetFillColor(42);
1278/// for (Int_t i=0;i<nx*ny;i++) {
1279/// number++;
1280/// C->cd(number);
1281/// h->FillRandom("gaus",1000);
1282/// h->DrawCopy();
1283/// }
1284/// }
1285/// ~~~
1286
1288{
1289 if (!IsEditable()) return;
1290
1291 if (gThreadXAR) {
1292 void *arr[7];
1293 arr[1] = this; arr[2] = (void*)&nx;arr[3] = (void*)& ny;
1294 arr[4] = (void*)&xmargin; arr[5] = (void *)& ymargin; arr[6] = (void *)&color;
1295 if ((*gThreadXAR)("PDCD", 7, arr, nullptr)) return;
1296 }
1297
1299
1300 cd();
1301 if (nx <= 0) nx = 1;
1302 if (ny <= 0) ny = 1;
1303 Int_t ix, iy;
1304 Double_t x1, y1, x2, y2, dx, dy;
1305 TPad *pad;
1306 TString name, title;
1307 Int_t n = 0;
1308 if (color == 0) color = GetFillColor();
1309 if (xmargin >= 0 && ymargin >= 0) {
1310 //general case
1311 dy = 1/Double_t(ny);
1312 dx = 1/Double_t(nx);
1313 for (iy=0;iy<ny;iy++) {
1314 y2 = 1 - iy*dy - ymargin;
1315 y1 = y2 - dy + 2*ymargin;
1316 if (y1 < 0) y1 = 0;
1317 if (y1 > y2) continue;
1318 for (ix=0;ix<nx;ix++) {
1319 x1 = ix*dx + xmargin;
1320 x2 = x1 +dx -2*xmargin;
1321 if (x1 > x2) continue;
1322 n++;
1323 name.Form("%s_%d", GetName(), n);
1324 pad = new TPad(name.Data(), name.Data(), x1, y1, x2, y2, color);
1325 pad->SetNumber(n);
1326 pad->Draw();
1327 }
1328 }
1329 } else {
1330 // special case when xmargin < 0 or ymargin < 0
1335 xl /= (1-xl+xr)*nx;
1336 xr /= (1-xl+xr)*nx;
1337 yb /= (1-yb+yt)*ny;
1338 yt /= (1-yb+yt)*ny;
1343 dx = (1-xl-xr)/nx;
1344 dy = (1-yb-yt)/ny;
1345 Int_t number = 0;
1346 for (Int_t i=0;i<nx;i++) {
1347 x1 = i*dx+xl;
1348 x2 = x1 + dx;
1349 if (i == 0) x1 = 0;
1350 if (i == nx-1) x2 = 1-xr;
1351 for (Int_t j=0;j<ny;j++) {
1352 number = j*nx + i +1;
1353 y2 = 1 -j*dy -yt;
1354 y1 = y2 - dy;
1355 if (j == 0) y2 = 1-yt;
1356 if (j == ny-1) y1 = 0;
1357 name.Form("%s_%d", GetName(), number);
1358 title.Form("%s_%d", GetTitle(), number);
1359 pad = new TPad(name.Data(), title.Data(), x1, y1, x2, y2, color);
1360 pad->SetNumber(number);
1361 pad->SetBorderMode(0);
1362 if (i == 0) pad->SetLeftMargin(xl*nx);
1363 else pad->SetLeftMargin(0);
1364 pad->SetRightMargin(0);
1365 pad->SetTopMargin(0);
1366 if (j == ny-1) pad->SetBottomMargin(yb*ny);
1367 else pad->SetBottomMargin(0);
1368 pad->Draw();
1369 }
1370 }
1371 }
1372 Modified();
1373}
1374
1375////////////////////////////////////////////////////////////////////////////////
1376/// Divide the canvas according to ratios.
1377///
1378/// The current canvas is divided in nx by ny according to the width and height ratios.
1379/// If the ratios are not specified they are assumed to be equal.
1380///
1381/// Pads are automatically named `canvasname_n` where `n` is the division number
1382/// starting from top left pad.
1383///
1384/// Top and left margins can be defined.
1385
1387 const std::vector<double>& widthRatios,
1388 const std::vector<double>& heightRatios,
1389 const double canvasTopMargin,
1390 const double canvasLeftMargin
1391 )
1392{
1393 cd();
1394
1395 int wrs = widthRatios.size();
1396 int hrs = heightRatios.size();
1397 int nxl = TMath::Min(nx,wrs), nyl = TMath::Min(ny,hrs);
1398
1399 if (wrs==0) nxl = nx;
1400 if (hrs==0) nyl = ny;
1401
1402 int pn = 1;
1403 double xr = 0.;
1404 double yr = 0.;
1405 double x = 0.;
1406 double y = 1.;
1407 double x1, y1, x2, y2;
1408
1409 // Check the validity of the margins
1411 Error("DivideRatios", "The canvas top margin must be >= 0 and <= 1");
1412 return;
1413 } else {
1414 y = 1.- canvasTopMargin;
1415 }
1417 Error("DivideRatios", "The canvas left margin must be >= 0 and <= 1");
1418 return;
1419 }
1420
1421 // Check the validity of the ratios
1423 if (hrs) {
1424 for (int i=0; i<nyl; i++) {
1425 yr = heightRatios[i];
1427 if (yr <0 || yr >1 ) {
1428 Error("DivideRatios", "Y ratios plus the top margin must be >= 0 and <= 1");
1429 return;
1430 }
1431 }
1432 }
1433 if (sumOfHeightRatios > 1.) {
1434 Error("DivideRatios", "The sum of Y ratios plus the top margin must be <= 1 %g",sumOfHeightRatios);
1435 return;
1436 }
1438 if (wrs) {
1439 for (int j=0; j<nxl; j++) {
1440 xr = widthRatios[j];
1442 if (xr <0 || xr >1 ) {
1443 Error("DivideRatios", "X ratios must be >= 0 and <= 1");
1444 return;
1445 }
1446 }
1447 }
1448 if (sumOfWidthRatios > 1.) {
1449 Error("DivideRatios", "The sum of X ratios must be <= 1 %g ",sumOfWidthRatios);
1450 return;
1451 }
1452
1453 // Create the pads according to the ratios
1454 for (int i=0; i<nyl; i++) {
1456 if (hrs) yr = heightRatios[i];
1457 else yr = 1./nyl;
1458 for (int j=0; j<nxl; j++) {
1459 if (wrs) xr = widthRatios[j];
1460 else xr = 1./nxl;
1461 x1 = TMath::Max(0., x);
1462 y1 = TMath::Max(0., y - yr);
1463 x2 = TMath::Min(1., x + xr);
1464 y2 = TMath::Min(1., y);
1465 auto pad = new TPad(TString::Format("%s_%d", GetName(), pn),
1466 TString::Format("%s_%d", GetName(), pn),
1467 x1, y1, x2 ,y2);
1468 pad->SetNumber(pn);
1469 pad->Draw();
1470 x = x + xr;
1471 pn++;
1472 }
1473 y = y - yr;
1474 }
1475}
1476
1477////////////////////////////////////////////////////////////////////////////////
1478/// "n" is the total number of sub-pads. The number of sub-pads along the X
1479/// and Y axis are computed according to the square root of n.
1480
1482{
1483 Int_t w = 1, h = 1;
1484 if (!fCanvas) {
1485 Error("DivideSquare", "No canvas associated with this pad.");
1486 return;
1487 }
1491 if (w*h < n) w++;
1492 } else {
1495 if (w*h < n) h++;
1496 }
1497
1498 Divide( w, h, xmargin, ymargin, color);
1499}
1500
1501////////////////////////////////////////////////////////////////////////////////
1502/// Draw Pad in Current pad (re-parent pad if necessary).
1503
1505{
1506 // if no canvas opened yet create a default canvas
1507 if (!gPad) {
1508 gROOT->MakeDefCanvas();
1509 }
1510
1511 // pad cannot be in itself and it can only be in one other pad at a time
1512 if (!fPrimitives) fPrimitives = new TList;
1513 if (gPad != this) {
1515 fMother->Remove(this, kFALSE);
1517 fCanvas = gPad->GetCanvas();
1518 //
1519 fMother = (TPad*)gPad;
1520 if (oldMother != fMother || fPixmapID == -1) ResizePad();
1521 }
1522
1523 if (fCanvas && fCanvas->IsWeb()) {
1524 Modified();
1526 } else {
1527 Paint();
1528 }
1529
1530 if (gPad->IsRetained() && gPad != this && fMother)
1531 fMother->Add(this, option);
1532}
1533
1534////////////////////////////////////////////////////////////////////////////////
1535/// Draw class inheritance tree of the class to which obj belongs.
1536///
1537/// If a class B inherits from a class A, description of B is drawn
1538/// on the right side of description of A.
1539///
1540/// Member functions overridden by B are shown in class A with a blue line
1541/// crossing-out the corresponding member function.
1542
1544{
1545 if (!classobj) return;
1546 char dname[256];
1547 const Int_t kMAXLEVELS = 10;
1548 TClass *clevel[kMAXLEVELS], *cl, *cll;
1549 TBaseClass *base, *cinherit;
1550 TText *ptext = nullptr;
1551 TString opt=option;
1552 Double_t x,y,dy,y1,v1,v2,dv;
1553 Int_t nd,nf,nc,nkd,nkf,i,j;
1554 TPaveText *pt;
1555 Int_t maxlev = 4;
1556 if (opt.Contains("2")) maxlev = 2;
1557 if (opt.Contains("3")) maxlev = 3;
1558 if (opt.Contains("5")) maxlev = 5;
1559 if (opt.Contains("6")) maxlev = 6;
1560 if (opt.Contains("7")) maxlev = 7;
1561
1562 // Clear and Set Pad range
1563 Double_t xpad = 20.5;
1564 Double_t ypad = 27.5;
1565 Clear();
1566 Range(0,0,xpad,ypad);
1567
1568 // Find number of levels
1569 Int_t nlevel = 0;
1570 TClass *obj = (TClass*)classobj;
1571 clevel[nlevel] = obj;
1572 TList *lbase = obj->GetListOfBases();
1573 while(lbase) {
1574 base = (TBaseClass*)lbase->First();
1575 if (!base) break;
1576 if (!base->GetClassPointer()) break;
1577 nlevel++;
1578 clevel[nlevel] = base->GetClassPointer();
1579 lbase = clevel[nlevel]->GetListOfBases();
1580 if (nlevel >= maxlev-1) break;
1581 }
1582 Int_t maxelem = 0;
1583 Int_t ncdraw = 0;
1585 for (ilevel=nlevel;ilevel>=0;ilevel--) {
1586 cl = clevel[ilevel];
1587 nelem = cl->GetNdata() + cl->GetNmethods();
1588 if (nelem > maxelem) maxelem = nelem;
1589 nc = (nelem/50) + 1;
1590 ncdraw += nc;
1591 }
1592
1593 Double_t tsizcm = 0.40;
1594 Double_t x1 = 0.25;
1595 Double_t x2 = 0;
1596 Double_t dx = 3.5;
1597 if (ncdraw > 4) {
1598 dx = dx - 0.42*Double_t(ncdraw-5);
1599 if (dx < 1.3) dx = 1.3;
1600 tsizcm = tsizcm - 0.03*Double_t(ncdraw-5);
1601 if (tsizcm < 0.27) tsizcm = 0.27;
1602 }
1603 Double_t tsiz = 1.2*tsizcm/ypad;
1604
1605 // Now loop on levels
1606 for (ilevel=nlevel;ilevel>=0;ilevel--) {
1607 cl = clevel[ilevel];
1608 nelem = cl->GetNdata() + cl->GetNmethods();
1609 if (nelem > maxelem) maxelem = nelem;
1610 nc = (nelem/50) + 1;
1611 dy = 0.45;
1612 if (ilevel < nlevel) x1 = x2 + 0.5;
1613 x2 = x1 + nc*dx;
1614 v2 = ypad - 0.5;
1615 lbase = cl->GetListOfBases();
1616 cinherit = nullptr;
1617 if (lbase) cinherit = (TBaseClass*)lbase->First();
1618
1619 do {
1620 nd = cl->GetNdata();
1621 nf = cl->GetNmethods() - 2; //do not show default constructor and destructor
1622 if (cl->GetListOfMethods()->FindObject("Dictionary")) {
1623 nf -= 6; // do not count the Dictionary/ClassDef functions
1624 }
1625 nkf= nf/nc +1;
1626 nkd= nd/nc +1;
1627 if (nd == 0) nkd=0;
1628 if (nf == 0) nkf=0;
1629 y1 = v2 - 0.7;
1630 v1 = y1 - Double_t(nkf+nkd+nc-1)*dy;
1631 dv = v2 - v1;
1632
1633 // Create a new PaveText
1634 pt = new TPaveText(x1,v1,x2,v2);
1636 pt->SetFillColor(19);
1637 pt->Draw();
1638 pt->SetTextColor(4);
1639 pt->SetTextFont(61);
1640 pt->SetTextAlign(12);
1642 TBox *box = pt->AddBox(0,(y1+0.01-v1)/dv,0,(v2-0.01-v1)/dv);
1643 if (box) box->SetFillColor(17);
1644 pt->AddLine(0,(y1-v1)/dv,0,(y1-v1)/dv);
1645 TText *title = pt->AddText(0.5,(0.5*(y1+v2)-v1)/dv,(char*)cl->GetName());
1646 title->SetTextAlign(22);
1647 title->SetTextSize(0.6*(v2-y1)/ypad);
1648
1649 // Draw data Members
1650 i = 0;
1651 x = 0.03;
1652 y = y1 + 0.5*dy;
1653 TDataMember *d;
1655 while ((d = (TDataMember *) nextd())) {
1656 if (i >= nkd) { i = 1; y = y1 - 0.5*dy; x += 1/Double_t(nc); }
1657 else { i++; y -= dy; }
1658
1659 // Take in account the room the array index will occupy
1660
1661 Int_t dim = d->GetArrayDim();
1662 Int_t indx = 0;
1663 snprintf(dname,256,"%s",d->GetName());
1664 Int_t ldname = 0;
1665 while (indx < dim ){
1666 ldname = strlen(dname);
1667 snprintf(&dname[ldname],256-ldname,"[%d]",d->GetMaxIndex(indx));
1668 indx++;
1669 }
1670 pt->AddText(x,(y-v1)/dv,dname);
1671 }
1672
1673 // Draw a separator line
1674 Double_t ysep;
1675 if (nd) {
1676 ysep = y1 - Double_t(nkd)*dy;
1677 pt->AddLine(0,(ysep-v1)/dv,0,(ysep-v1)/dv);
1678 ysep -= 0.5*dy;
1679 } else ysep = y1;
1680
1681 // Draw Member Functions
1682 Int_t fcount = 0;
1683 i = 0;
1684 x = 0.03;
1685 y = ysep + 0.5*dy;
1686 TMethod *m;
1688 while ((m = (TMethod *) nextm())) {
1689 if (
1690 !strcmp( m->GetName(), "Dictionary" ) ||
1691 !strcmp( m->GetName(), "Class_Version" ) ||
1692 !strcmp( m->GetName(), "DeclFileName" ) ||
1693 !strcmp( m->GetName(), "DeclFileLine" ) ||
1694 !strcmp( m->GetName(), "ImplFileName" ) ||
1695 !strcmp( m->GetName(), "ImplFileLine" )
1696 ) continue;
1697 fcount++;
1698 if (fcount > nf) break;
1699 if (i >= nkf) { i = 1; y = ysep - 0.5*dy; x += 1/Double_t(nc); }
1700 else { i++; y -= dy; }
1701
1702 ptext = pt->AddText(x,(y-v1)/dv,m->GetName());
1703 // Check if method is overloaded in a derived class
1704 // If yes, Change the color of the text to blue
1705 for (j=ilevel-1;j>=0;j--) {
1706 if (cl == clevel[ilevel]) {
1707 if (clevel[j]->GetMethodAny((char*)m->GetName())) {
1708 ptext->SetTextColor(15);
1709 break;
1710 }
1711 }
1712 }
1713 }
1714
1715 // Draw second inheritance classes for this class
1716 cll = nullptr;
1717 if (cinherit) {
1718 cinherit = (TBaseClass*)lbase->After(cinherit);
1719 if (cinherit) {
1720 cl = cinherit->GetClassPointer();
1721 cll = cl;
1722 v2 = v1 -0.4;
1723 dy = 0.35;
1724 }
1725 }
1726 } while (cll);
1727 }
1728 Update();
1729}
1730
1731////////////////////////////////////////////////////////////////////////////////
1732/// Function called to draw a crosshair in the canvas
1733///
1734/// Example:
1735/// ~~~ {.cpp}
1736/// Root > TFile f("hsimple.root");
1737/// Root > hpxpy.Draw();
1738/// Root > c1.SetCrosshair();
1739/// ~~~
1740/// When moving the mouse in the canvas, a crosshair is drawn
1741///
1742/// - if the canvas fCrosshair = 1 , the crosshair spans the full canvas
1743/// - if the canvas fCrosshair > 1 , the crosshair spans only the pad
1744
1746{
1747 if (!gPad || (gPad->GetEvent() == kMouseEnter)) return;
1748
1749 TPad *cpad = (TPad*)gPad;
1750 TCanvas *canvas = cpad->GetCanvas();
1751 canvas->FeedbackMode(kTRUE);
1752
1753 //erase old position and draw a line at current position
1754 Int_t pxmin,pxmax,pymin,pymax,px,py;
1755#ifndef R__HAS_COCOA
1756 Int_t pxold = fCrosshairPos%10000;
1757 Int_t pyold = fCrosshairPos/10000;
1758#endif // R__HAS_COCOA
1759 px = cpad->GetEventX();
1760 py = cpad->GetEventY()+1;
1761 if (canvas->GetCrosshair() > 1) { //crosshair only in the current pad
1762 pxmin = cpad->XtoAbsPixel(fX1);
1763 pxmax = cpad->XtoAbsPixel(fX2);
1764 pymin = cpad->YtoAbsPixel(fY1);
1765 pymax = cpad->YtoAbsPixel(fY2);
1766 } else { //default; crosshair spans the full canvas
1767 pxmin = 0;
1768 pxmax = canvas->GetWw();
1769 pymin = 0;
1770 pymax = cpad->GetWh();
1771 }
1772#ifndef R__HAS_COCOA
1773 // Not needed, no XOR with Cocoa.
1774 if(pxold) gVirtualX->DrawLine(pxold,pymin,pxold,pymax);
1775 if(pyold) gVirtualX->DrawLine(pxmin,pyold,pxmax,pyold);
1776#endif // R__HAS_COCOA
1777 if (cpad->GetEvent() == kButton1Down ||
1778 cpad->GetEvent() == kButton1Up ||
1779 cpad->GetEvent() == kMouseLeave) {
1780 fCrosshairPos = 0;
1781 return;
1782 }
1783 gVirtualX->DrawLine(px,pymin,px,pymax);
1784 gVirtualX->DrawLine(pxmin,py,pxmax,py);
1785 fCrosshairPos = px + 10000*py;
1786}
1787
1788////////////////////////////////////////////////////////////////////////////////
1789/// Draw an empty pad frame with X and Y axis.
1790///
1791/// \return The pointer to the histogram used to draw the frame.
1792///
1793/// \param[in] xmin X axis lower limit
1794/// \param[in] xmax X axis upper limit
1795/// \param[in] ymin Y axis lower limit
1796/// \param[in] ymax Y axis upper limit
1797/// \param[in] title Pad title.If title is of the form "stringt;stringx;stringy"
1798/// the pad title is set to stringt, the x axis title to
1799/// stringx, the y axis title to stringy.
1800///
1801/// #### Example:
1802///
1803/// Begin_Macro(source)
1804/// {
1805/// auto c = new TCanvas("c","c",200,10,500,300);
1806///
1807/// const Int_t n = 50;
1808/// auto g = new TGraph();
1809/// for (Int_t i=0;i<n;i++) g->SetPoint(i,i*0.1,100*sin(i*0.1+0.2));
1810///
1811/// auto frame = c->DrawFrame(0, -110, 2, 110);
1812/// frame->GetXaxis()->SetTitle("X axis");
1813///
1814/// g->Draw("L*");
1815/// }
1816/// End_Macro
1817
1819{
1820 if (!IsEditable())
1821 return nullptr;
1822
1823 if (this != gPad) {
1824 Warning("DrawFrame", "Must be called for the current pad only");
1825 if (gPad) return gPad->DrawFrame(xmin,ymin,xmax,ymax,title);
1826 }
1827
1828 cd();
1829
1830 TH1F *hframe = (TH1F*)FindObject("hframe");
1831 if (hframe) delete hframe;
1832 Int_t nbins = 1000;
1833 //if log scale in X, use variable bin size linear with log(x)
1834 //this gives a better precision when zooming on the axis
1835 if (fLogx && xmin > 0 && xmax > xmin) {
1838 Double_t dx = (xmaxl-xminl)/nbins;
1839 std::vector<Double_t> xbins(nbins+1);
1840 xbins[0] = xmin;
1841 for (Int_t i=1;i<=nbins;i++) {
1842 xbins[i] = TMath::Exp(xminl+i*dx);
1843 }
1844 hframe = new TH1F("hframe",title,nbins,xbins.data());
1845 } else {
1846 hframe = new TH1F("hframe",title,nbins,xmin,xmax);
1847 }
1848 hframe->SetBit(TH1::kNoStats);
1849 hframe->SetBit(kCanDelete);
1850 hframe->SetMinimum(ymin);
1851 hframe->SetMaximum(ymax);
1852 hframe->GetYaxis()->SetLimits(ymin,ymax);
1853 hframe->SetDirectory(nullptr);
1854 hframe->Draw(" ");
1855 Update();
1856 cd();
1857 return hframe;
1858}
1859
1860////////////////////////////////////////////////////////////////////////////////
1861/// Static function to Display Color Table in a pad.
1862
1864{
1865 Int_t i, j;
1866 Int_t color;
1867 Double_t xlow, ylow, xup, yup, hs, ws;
1868 Double_t x1, y1, x2, y2;
1869 x1 = y1 = 0;
1870 x2 = y2 = 20;
1871
1872 gPad->SetFillColor(0);
1873 gPad->Clear();
1874 gPad->Range(x1,y1,x2,y2);
1875
1876 TText text(0,0,"");
1877 text.SetTextFont(61);
1878 text.SetTextSize(0.07);
1879 text.SetTextAlign(22);
1880
1881 TBox box;
1882
1883 // Draw color table boxes.
1884 hs = (y2-y1)/Double_t(5);
1885 ws = (x2-x1)/Double_t(10);
1886 for (i=0;i<10;i++) {
1887 xlow = x1 + ws*(Double_t(i)+0.1);
1888 xup = x1 + ws*(Double_t(i)+0.9);
1889 for (j=0;j<5;j++) {
1890 ylow = y1 + hs*(Double_t(j)+0.1);
1891 yup = y1 + hs*(Double_t(j)+0.9);
1892 color = 10*j + i;
1893 box.SetFillStyle(1001);
1894 box.SetFillColor(color);
1895 box.DrawBox(xlow, ylow, xup, yup);
1896 box.SetFillStyle(0);
1897 box.SetLineColor(1);
1898 box.DrawBox(xlow, ylow, xup, yup);
1899 if (color == 1) text.SetTextColor(0);
1900 else text.SetTextColor(1);
1901 text.DrawText(0.5*(xlow+xup), 0.5*(ylow+yup), TString::Format("%d",color).Data());
1902 }
1903 }
1904}
1905
1906////////////////////////////////////////////////////////////////////////////////
1907/// Execute action corresponding to one event.
1908///
1909/// This member function is called when a TPad object is clicked.
1910///
1911/// If the mouse is clicked in one of the 4 corners of the pad (pA,pB,pC,pD)
1912/// the pad is resized with the rubber rectangle.
1913///
1914/// If the mouse is clicked inside the pad, the pad is moved.
1915///
1916/// If the mouse is clicked on the 4 edges (pL,pR,pTop,pBot), the pad is scaled
1917/// parallel to this edge.
1918///
1919/// \image html gpad_pad4.png
1920///
1921/// Note that this function duplicates on purpose the functionality
1922/// already implemented in TBox::ExecuteEvent.
1923/// If somebody modifies this function, may be similar changes should also
1924/// be applied to TBox::ExecuteEvent.
1925
1927{
1928 const Int_t kMaxDiff = 5;
1929 const Int_t kMinSize = 20;
1930 static Int_t pxorg, pyorg;
1931 static Int_t px1, px2, py1, py2, pxl, pyl, pxt, pyt, pxold, pyold;
1932 static Int_t px1p, px2p, py1p, py2p, pxlp, pylp, pxtp, pytp;
1933 static Bool_t pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE;
1934 Int_t wx, wy;
1938
1939 if (!IsEditable() && event != kMouseEnter) return;
1940 TVirtualPad *parent = GetMother();
1941 if (!parent->IsEditable()) return;
1942
1943 HideToolTip(event);
1944
1945 if (fXlowNDC < 0 && event != kButton1Down) return;
1946 if (fYlowNDC < 0 && event != kButton1Down) return;
1947
1948 // keep old mouse position
1949 if (event == kButton1Down) {
1950 pxorg = px;
1951 pyorg = py;
1952 }
1953
1954 Int_t newcode = gROOT->GetEditorMode();
1955 if (newcode)
1956 pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE;
1957 switch (newcode) {
1958 case kPad:
1959 TCreatePrimitives::Pad(event,px,py,0);
1960 break;
1961 case kMarker:
1962 case kText:
1963 TCreatePrimitives::Text(event,px,py,newcode);
1964 break;
1965 case kLine:
1966 TCreatePrimitives::Line(event,px,py,kLine);
1967 break;
1968 case kArrow:
1969 TCreatePrimitives::Line(event,px,py,kArrow);
1970 break;
1971 case kCurlyLine:
1973 break;
1974 case kCurlyArc:
1976 break;
1977 case kPolyLine:
1979 break;
1980 case kCutG:
1982 break;
1983 case kArc:
1984 TCreatePrimitives::Ellipse(event,px,py,kArc);
1985 break;
1986 case kEllipse:
1988 break;
1989 case kButton:
1990 case kPave:
1991 case kPaveLabel:
1992 case kPaveText:
1993 case kPavesText:
1994 case kDiamond:
1995 TCreatePrimitives::Pave(event,px,py,newcode);
1996 return;
1997 default:
1998 break;
1999 }
2000 if (newcode) return;
2001
2002 switch (event) {
2003
2004 case kMouseEnter:
2005 if (fTip)
2007 break;
2008
2009 case kArrowKeyPress:
2010 case kButton1Down:
2011
2014
2015 GetPainter()->SetLineColor(-1);
2016 TAttLine::Modify(); //Change line attributes only if necessary
2017 if (GetFillColor())
2019 else
2022
2023 // No break !!!
2024
2025 case kMouseMotion:
2026
2027 px1 = XtoAbsPixel(fX1);
2028 py1 = YtoAbsPixel(fY1);
2029 px2 = XtoAbsPixel(fX2);
2030 py2 = YtoAbsPixel(fY2);
2031
2032 if (px1 < px2) {
2033 pxl = px1;
2034 pxt = px2;
2035 } else {
2036 pxl = px2;
2037 pxt = px1;
2038 }
2039 if (py1 < py2) {
2040 pyl = py1;
2041 pyt = py2;
2042 } else {
2043 pyl = py2;
2044 pyt = py1;
2045 }
2046
2047 px1p = parent->XtoAbsPixel(parent->GetX1()) + parent->GetBorderSize();
2048 py1p = parent->YtoAbsPixel(parent->GetY1()) - parent->GetBorderSize();
2049 px2p = parent->XtoAbsPixel(parent->GetX2()) - parent->GetBorderSize();
2050 py2p = parent->YtoAbsPixel(parent->GetY2()) + parent->GetBorderSize();
2051
2052 if (px1p < px2p) {
2053 pxlp = px1p;
2054 pxtp = px2p;
2055 } else {
2056 pxlp = px2p;
2057 pxtp = px1p;
2058 }
2059 if (py1p < py2p) {
2060 pylp = py1p;
2061 pytp = py2p;
2062 } else {
2063 pylp = py2p;
2064 pytp = py1p;
2065 }
2066
2067 pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE;
2068
2069 // case pA
2070 if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) {
2071 pxold = pxl; pyold = pyl; pA = kTRUE;
2073 }
2074 // case pB
2075 if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) {
2076 pxold = pxt; pyold = pyl; pB = kTRUE;
2078 }
2079 // case pC
2080 if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) {
2081 pxold = pxt; pyold = pyt; pC = kTRUE;
2083 }
2084 // case pD
2085 if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) {
2086 pxold = pxl; pyold = pyt; pD = kTRUE;
2088 }
2089
2090 if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
2091 TMath::Abs(py - pyl) < kMaxDiff) { // top edge
2092 pxold = pxl; pyold = pyl; pTop = kTRUE;
2094 }
2095
2096 if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
2097 TMath::Abs(py - pyt) < kMaxDiff) { // bottom edge
2098 pxold = pxt; pyold = pyt; pBot = kTRUE;
2100 }
2101
2102 if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) &&
2103 TMath::Abs(px - pxl) < kMaxDiff) { // left edge
2104 pxold = pxl; pyold = pyl; pL = kTRUE;
2106 }
2107
2108 if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) &&
2109 TMath::Abs(px - pxt) < kMaxDiff) { // right edge
2110 pxold = pxt; pyold = pyt; pR = kTRUE;
2112 }
2113
2114 if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
2115 (py > pyl+kMaxDiff && py < pyt-kMaxDiff)) { // inside box
2116 pxold = px; pyold = py; pINSIDE = kTRUE;
2117 if (event == kButton1Down)
2119 else
2121 }
2122
2123 fResizing = kFALSE;
2124 if (pA || pB || pC || pD || pTop || pL || pR || pBot)
2125 fResizing = kTRUE;
2126
2127 if (!pA && !pB && !pC && !pD && !pTop && !pL && !pR && !pBot && !pINSIDE)
2129
2130 break;
2131
2132 case kArrowKeyRelease:
2133 case kButton1Motion:
2134
2135 if (TestBit(kCannotMove)) break;
2136 wx = wy = 0;
2137
2138 if (pA) {
2140 if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; }
2141 if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; }
2142 if (px < pxlp) { px = pxlp; wx = px; }
2143 if (py < pylp) { py = pylp; wy = py; }
2144 if (fixedr) {
2145 Double_t dy = Double_t(TMath::Abs(pxt-px))/parent->UtoPixel(1.) /
2147 Int_t npy2 = pyt - TMath::Abs(parent->VtoAbsPixel(dy) -
2148 parent->VtoAbsPixel(0));
2149 if (npy2 < pylp) {
2150 px = pxold;
2151 py = pyold;
2152 } else
2153 py = npy2;
2154
2155 wx = wy = 0;
2156 }
2157 if (!ropaque) gVirtualX->DrawBox(px, pyt, pxt, py, TVirtualX::kHollow);
2158 }
2159 if (pB) {
2160 if (!ropaque) gVirtualX->DrawBox(pxl , pyt, pxold, pyold, TVirtualX::kHollow);
2161 if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; }
2162 if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; }
2163 if (px > pxtp) { px = pxtp; wx = px; }
2164 if (py < pylp) { py = pylp; wy = py; }
2165 if (fixedr) {
2166 Double_t dy = Double_t(TMath::Abs(pxl-px))/parent->UtoPixel(1.) /
2168 Int_t npy2 = pyt - TMath::Abs(parent->VtoAbsPixel(dy) -
2169 parent->VtoAbsPixel(0));
2170 if (npy2 < pylp) {
2171 px = pxold;
2172 py = pyold;
2173 } else
2174 py = npy2;
2175
2176 wx = wy = 0;
2177 }
2178 if (!ropaque) gVirtualX->DrawBox(pxl , pyt, px , py, TVirtualX::kHollow);
2179 }
2180 if (pC) {
2181 if (!ropaque) gVirtualX->DrawBox(pxl , pyl, pxold, pyold, TVirtualX::kHollow);
2182 if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; }
2183 if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; }
2184 if (px > pxtp) { px = pxtp; wx = px; }
2185 if (py > pytp) { py = pytp; wy = py; }
2186 if (fixedr) {
2187 Double_t dy = Double_t(TMath::Abs(pxl-px))/parent->UtoPixel(1.) /
2189 Int_t npy2 = pyl + TMath::Abs(parent->VtoAbsPixel(dy) -
2190 parent->VtoAbsPixel(0));
2191 if (npy2 > pytp) {
2192 px = pxold;
2193 py = pyold;
2194 } else
2195 py = npy2;
2196
2197 wx = wy = 0;
2198 }
2199 if (!ropaque) gVirtualX->DrawBox(pxl, pyl, px, py, TVirtualX::kHollow);
2200 }
2201 if (pD) {
2203 if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; }
2204 if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; }
2205 if (px < pxlp) { px = pxlp; wx = px; }
2206 if (py > pytp) { py = pytp; wy = py; }
2207 if (fixedr) {
2208 Double_t dy = Double_t(TMath::Abs(pxt-px))/parent->UtoPixel(1.) /
2210 Int_t npy2 = pyl + TMath::Abs(parent->VtoAbsPixel(dy) -
2211 parent->VtoAbsPixel(0));
2212 if (npy2 > pytp) {
2213 px = pxold;
2214 py = pyold;
2215 } else
2216 py = npy2;
2217
2218 wx = wy = 0;
2219 }
2220 if (!ropaque) gVirtualX->DrawBox(px, py, pxt, pyl, TVirtualX::kHollow);
2221 }
2222 if (pTop) {
2223 if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
2224 py2 += py - pyold;
2225 if (py2 > py1-kMinSize) { py2 = py1-kMinSize; wy = py2; }
2226 if (py2 < py2p) { py2 = py2p; wy = py2; }
2227 if (fixedr) {
2228 Double_t dx = Double_t(TMath::Abs(py2-py1))/parent->VtoPixel(0) *
2230 Int_t npx2 = px1 + parent->UtoPixel(dx);
2231 if (npx2 > px2p)
2232 py2 -= py - pyold;
2233 else
2234 px2 = npx2;
2235 }
2236 if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
2237 }
2238 if (pBot) {
2239 if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
2240 py1 += py - pyold;
2241 if (py1 < py2+kMinSize) { py1 = py2+kMinSize; wy = py1; }
2242 if (py1 > py1p) { py1 = py1p; wy = py1; }
2243 if (fixedr) {
2244 Double_t dx = Double_t(TMath::Abs(py2-py1))/parent->VtoPixel(0) *
2246 Int_t npx2 = px1 + parent->UtoPixel(dx);
2247 if (npx2 > px2p)
2248 py1 -= py - pyold;
2249 else
2250 px2 = npx2;
2251 }
2252 if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
2253 }
2254 if (pL) {
2255 if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
2256 px1 += px - pxold;
2257 if (px1 > px2-kMinSize) { px1 = px2-kMinSize; wx = px1; }
2258 if (px1 < px1p) { px1 = px1p; wx = px1; }
2259 if (fixedr) {
2260 Double_t dy = Double_t(TMath::Abs(px2-px1))/parent->UtoPixel(1.) /
2262 Int_t npy2 = py1 - TMath::Abs(parent->VtoAbsPixel(dy) -
2263 parent->VtoAbsPixel(0));
2264 if (npy2 < py2p)
2265 px1 -= px - pxold;
2266 else
2267 py2 = npy2;
2268 }
2269 if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
2270 }
2271 if (pR) {
2272 if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
2273 px2 += px - pxold;
2274 if (px2 < px1+kMinSize) { px2 = px1+kMinSize; wx = px2; }
2275 if (px2 > px2p) { px2 = px2p; wx = px2; }
2276 if (fixedr) {
2277 Double_t dy = Double_t(TMath::Abs(px2-px1))/parent->UtoPixel(1.) /
2279 Int_t npy2 = py1 - TMath::Abs(parent->VtoAbsPixel(dy) -
2280 parent->VtoAbsPixel(0));
2281 if (npy2 < py2p)
2282 px2 -= px - pxold;
2283 else
2284 py2 = npy2;
2285 }
2286 if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
2287 }
2288 if (pINSIDE) {
2289 if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); // draw the old box
2290 Int_t dx = px - pxold;
2291 Int_t dy = py - pyold;
2292 px1 += dx; py1 += dy; px2 += dx; py2 += dy;
2293 if (px1 < px1p) { dx = px1p - px1; px1 += dx; px2 += dx; wx = px+dx; }
2294 if (px2 > px2p) { dx = px2 - px2p; px1 -= dx; px2 -= dx; wx = px-dx; }
2295 if (py1 > py1p) { dy = py1 - py1p; py1 -= dy; py2 -= dy; wy = py-dy; }
2296 if (py2 < py2p) { dy = py2p - py2; py1 += dy; py2 += dy; wy = py+dy; }
2297 if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); // draw the new box
2298 }
2299
2300 if (wx || wy) {
2301 if (wx) px = wx;
2302 if (wy) py = wy;
2303 gVirtualX->Warp(px, py);
2304 }
2305
2306 pxold = px;
2307 pyold = py;
2308
2309 Double_t x1, y1, x2, y2;
2310 x1 = x2 = y1 = y2 = 0;
2311
2312 if ((!fResizing && opaque) || (fResizing && ropaque)) {
2313 if (pA) {
2314 x1 = AbsPixeltoX(pxold);
2315 y1 = AbsPixeltoY(pyt);
2316 x2 = AbsPixeltoX(pxt);
2317 y2 = AbsPixeltoY(pyold);
2318 }
2319 if (pB) {
2320 x1 = AbsPixeltoX(pxl);
2321 y1 = AbsPixeltoY(pyt);
2322 x2 = AbsPixeltoX(pxold);
2323 y2 = AbsPixeltoY(pyold);
2324 }
2325 if (pC) {
2326 x1 = AbsPixeltoX(pxl);
2327 y1 = AbsPixeltoY(pyold);
2328 x2 = AbsPixeltoX(pxold);
2329 y2 = AbsPixeltoY(pyl);
2330 }
2331 if (pD) {
2332 x1 = AbsPixeltoX(pxold);
2333 y1 = AbsPixeltoY(pyold);
2334 x2 = AbsPixeltoX(pxt);
2335 y2 = AbsPixeltoY(pyl);
2336 }
2337 if (pTop || pBot || pL || pR || pINSIDE) {
2338 x1 = AbsPixeltoX(px1);
2339 y1 = AbsPixeltoY(py1);
2340 x2 = AbsPixeltoX(px2);
2341 y2 = AbsPixeltoY(py2);
2342 }
2343
2344 if (px != pxorg || py != pyorg) {
2345
2346 // Get parent corners pixels coordinates
2347 Int_t parentpx1 = fMother->XtoAbsPixel(parent->GetX1());
2348 Int_t parentpx2 = fMother->XtoAbsPixel(parent->GetX2());
2349 Int_t parentpy1 = fMother->YtoAbsPixel(parent->GetY1());
2350 Int_t parentpy2 = fMother->YtoAbsPixel(parent->GetY2());
2351
2352 // Get pad new corners pixels coordinates
2357
2358 // Compute new pad positions in the NDC space of parent
2363 }
2364
2365 // Reset pad parameters and recompute conversion coefficients
2366 ResizePad();
2367
2368 if (pINSIDE) gPad->ShowGuidelines(this, event);
2369 if (pTop) gPad->ShowGuidelines(this, event, 't', true);
2370 if (pBot) gPad->ShowGuidelines(this, event, 'b', true);
2371 if (pL) gPad->ShowGuidelines(this, event, 'l', true);
2372 if (pR) gPad->ShowGuidelines(this, event, 'r', true);
2373 if (pA) gPad->ShowGuidelines(this, event, '1', true);
2374 if (pB) gPad->ShowGuidelines(this, event, '2', true);
2375 if (pC) gPad->ShowGuidelines(this, event, '3', true);
2376 if (pD) gPad->ShowGuidelines(this, event, '4', true);
2377
2378 Modified(kTRUE);
2379 }
2380
2381 break;
2382
2383 case kButton1Up:
2384
2385 if (gROOT->IsEscaped()) {
2386 gROOT->SetEscape(kFALSE);
2387 break;
2388 }
2389
2390 if (opaque||ropaque) {
2391 ShowGuidelines(this, event);
2392 } else {
2393 x1 = x2 = y1 = y2 = 0;
2394
2395 if (pA) {
2396 x1 = AbsPixeltoX(pxold);
2397 y1 = AbsPixeltoY(pyt);
2398 x2 = AbsPixeltoX(pxt);
2399 y2 = AbsPixeltoY(pyold);
2400 }
2401 if (pB) {
2402 x1 = AbsPixeltoX(pxl);
2403 y1 = AbsPixeltoY(pyt);
2404 x2 = AbsPixeltoX(pxold);
2405 y2 = AbsPixeltoY(pyold);
2406 }
2407 if (pC) {
2408 x1 = AbsPixeltoX(pxl);
2409 y1 = AbsPixeltoY(pyold);
2410 x2 = AbsPixeltoX(pxold);
2411 y2 = AbsPixeltoY(pyl);
2412 }
2413 if (pD) {
2414 x1 = AbsPixeltoX(pxold);
2415 y1 = AbsPixeltoY(pyold);
2416 x2 = AbsPixeltoX(pxt);
2417 y2 = AbsPixeltoY(pyl);
2418 }
2419 if (pTop || pBot || pL || pR || pINSIDE) {
2420 x1 = AbsPixeltoX(px1);
2421 y1 = AbsPixeltoY(py1);
2422 x2 = AbsPixeltoX(px2);
2423 y2 = AbsPixeltoY(py2);
2424 }
2425
2426 if (pA || pB || pC || pD || pTop || pL || pR || pBot)
2427 Modified(kTRUE);
2428
2429 gVirtualX->SetLineColor(-1);
2430 gVirtualX->SetLineWidth(-1);
2431
2432 if (px != pxorg || py != pyorg) {
2433
2434 // Get parent corners pixels coordinates
2435 Int_t parentpx1 = fMother->XtoAbsPixel(parent->GetX1());
2436 Int_t parentpx2 = fMother->XtoAbsPixel(parent->GetX2());
2437 Int_t parentpy1 = fMother->YtoAbsPixel(parent->GetY1());
2438 Int_t parentpy2 = fMother->YtoAbsPixel(parent->GetY2());
2439
2440 // Get pad new corners pixels coordinates
2445
2446 // Compute new pad positions in the NDC space of parent
2451 }
2452
2453 // Reset pad parameters and recompute conversion coefficients
2454 ResizePad();
2455
2456
2457 // emit signal
2458 RangeChanged();
2459 }
2460
2461 break;
2462
2463 case kButton1Locate:
2464
2465 ExecuteEvent(kButton1Down, px, py);
2466
2467 while (true) {
2468 px = py = 0;
2469 event = gVirtualX->RequestLocator(1, 1, px, py);
2470
2472
2473 if (event != -1) { // button is released
2474 ExecuteEvent(kButton1Up, px, py);
2475 return;
2476 }
2477 }
2478
2479 case kButton2Down:
2480
2481 Pop();
2482 break;
2483
2484 }
2485}
2486
2487////////////////////////////////////////////////////////////////////////////////
2488/// Execute action corresponding to one event for a TAxis object
2489/// (called by TAxis::ExecuteEvent.)
2490/// This member function is called when an axis is clicked with the locator
2491///
2492/// The axis range is set between the position where the mouse is pressed
2493/// and the position where it is released.
2494///
2495/// If the mouse position is outside the current axis range when it is released
2496/// the axis is unzoomed with the corresponding proportions.
2497///
2498/// Note that the mouse does not need to be in the pad or even canvas
2499/// when it is released.
2500
2502{
2503 if (!IsEditable()) return;
2504 if (!axis) return;
2506
2507 TView *view = GetView();
2508 static Int_t axisNumber;
2509 static Double_t ratio1, ratio2;
2510 static Int_t px1old, py1old, px2old, py2old;
2511 Int_t nbd, inc, bin1, bin2, first, last;
2512 Double_t temp, xmin,xmax;
2513 Bool_t opaque = gPad->OpaqueMoving();
2514 bool resetAxisRange = false;
2515 static std::unique_ptr<TBox> zoombox;
2516 Double_t zbx1=0,zbx2=0,zby1=0,zby2=0;
2517
2518 // The CONT4 option, used to paint TH2, is a special case; it uses a 3D
2519 // drawing technique to paint a 2D plot.
2520 TString opt = axis->GetParent()->GetDrawOption();
2521 opt.ToLower();
2523 if (strstr(opt,"cont4")) {
2524 view = nullptr;
2525 kCont4 = kTRUE;
2526 }
2527
2528 switch (event) {
2529
2530 case kButton1Down:
2531 axisNumber = 1;
2532 if (!strcmp(axis->GetName(),"xaxis")) {
2533 axisNumber = 1;
2534 if (!IsVertical()) axisNumber = 2;
2535 }
2536 if (!strcmp(axis->GetName(),"yaxis")) {
2537 axisNumber = 2;
2538 if (!IsVertical()) axisNumber = 1;
2539 }
2540 if (!strcmp(axis->GetName(),"zaxis")) {
2541 axisNumber = 3;
2542 }
2543 if (view) {
2544 view->GetDistancetoAxis(axisNumber, px, py, ratio1);
2545 } else {
2546 if (axisNumber == 1) {
2547 ratio1 = (AbsPixeltoX(px) - GetUxmin())/(GetUxmax() - GetUxmin());
2550 px2old = px1old;
2552 } else if (axisNumber == 2) {
2553 ratio1 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
2557 py2old = py1old;
2558 } else {
2559 ratio1 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
2563 py2old = py1old;
2564 }
2565 if (!opaque) {
2567 } else {
2568 if (axisNumber == 1) {
2571 zby1 = GetUymin();
2572 zby2 = GetUymax();
2573 } else if (axisNumber == 2) {
2574 zbx1 = GetUxmin();
2575 zbx2 = GetUxmax();
2578 }
2579 if (GetLogx()) {
2580 zbx1 = TMath::Power(10,zbx1);
2581 zbx2 = TMath::Power(10,zbx2);
2582 }
2583 if (GetLogy()) {
2584 zby1 = TMath::Power(10,zby1);
2585 zby2 = TMath::Power(10,zby2);
2586 }
2587 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
2588 Int_t ci = TColor::GetColor("#7d7dff");
2589 TColor *zoomcolor = gROOT->GetColor(ci);
2590 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
2591 else zoomcolor->SetAlpha(0.5);
2592 zoombox->SetFillColor(ci);
2593 zoombox->Draw();
2594 gPad->Modified();
2595 gPad->Update();
2596 }
2597 }
2598 if (!opaque) gVirtualX->SetLineColor(-1);
2599 // No break !!!
2600
2601 case kButton1Motion:
2602 if (view) {
2603 view->GetDistancetoAxis(axisNumber, px, py, ratio2);
2604 } else {
2606 if (axisNumber == 1) {
2607 ratio2 = (AbsPixeltoX(px) - GetUxmin())/(GetUxmax() - GetUxmin());
2609 } else {
2610 ratio2 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
2612 }
2613 if (!opaque) {
2615 } else {
2616 if (axisNumber == 1) {
2619 zby1 = GetUymin();
2620 zby2 = GetUymax();
2621 } else if (axisNumber == 2) {
2622 zbx1 = GetUxmin();
2623 zbx2 = GetUxmax();
2626 }
2627 if (GetLogx()) {
2628 zbx1 = TMath::Power(10,zbx1);
2629 zbx2 = TMath::Power(10,zbx2);
2630 }
2631 if (GetLogy()) {
2632 zby1 = TMath::Power(10,zby1);
2633 zby2 = TMath::Power(10,zby2);
2634 }
2635 if (zoombox) {
2636 zoombox->SetX1(zbx1);
2637 zoombox->SetY1(zby1);
2638 zoombox->SetX2(zbx2);
2639 zoombox->SetY2(zby2);
2640 }
2641 gPad->Modified();
2642 gPad->Update();
2643 }
2644 }
2645 break;
2646
2647 case kWheelUp:
2648 nbd = (axis->GetLast()-axis->GetFirst());
2649 inc = TMath::Max(nbd/100,1);
2650 bin1 = axis->GetFirst()+inc;
2651 bin2 = axis->GetLast()-inc;
2652 bin1 = TMath::Max(bin1, 1);
2653 bin2 = TMath::Min(bin2, axis->GetNbins());
2654 if (bin2>bin1) {
2655 axis->SetRange(bin1,bin2);
2656 gPad->Modified();
2657 gPad->Update();
2658 }
2659 break;
2660
2661 case kWheelDown:
2662 nbd = (axis->GetLast()-axis->GetFirst());
2663 inc = TMath::Max(nbd/100,1);
2664 bin1 = axis->GetFirst()-inc;
2665 bin2 = axis->GetLast()+inc;
2666 bin1 = TMath::Max(bin1, 1);
2667 bin2 = TMath::Min(bin2, axis->GetNbins());
2668 resetAxisRange = (bin1 == 1 && axis->GetFirst() == 1 && bin2 == axis->GetNbins() && axis->GetLast() == axis->GetNbins());
2669 if (bin2>bin1) {
2670 axis->SetRange(bin1,bin2);
2671 }
2673 if (bin2>bin1) {
2674 gPad->Modified();
2675 gPad->Update();
2676 }
2677 break;
2678
2679 case kButton1Up:
2680 if (gROOT->IsEscaped()) {
2681 gROOT->SetEscape(kFALSE);
2682 if (opaque && zoombox)
2683 zoombox.reset();
2684 break;
2685 }
2686
2687 if (view) {
2688 view->GetDistancetoAxis(axisNumber, px, py, ratio2);
2689 if (ratio1 > ratio2) {
2690 temp = ratio1;
2691 ratio1 = ratio2;
2692 ratio2 = temp;
2693 }
2694 if (ratio2 - ratio1 > 0.05) {
2695 TH1 *hobj = (TH1*)axis->GetParent();
2696 if (axisNumber == 3 && hobj && hobj->GetDimension() != 3) {
2697 Float_t zmin = hobj->GetMinimum();
2698 Float_t zmax = hobj->GetMaximum();
2699 if(GetLogz()){
2700 if (zmin <= 0 && zmax > 0) zmin = TMath::Min((Double_t)1,
2701 (Double_t)0.001*zmax);
2702 zmin = TMath::Log10(zmin);
2703 zmax = TMath::Log10(zmax);
2704 }
2705 Float_t newmin = zmin + (zmax-zmin)*ratio1;
2706 Float_t newmax = zmin + (zmax-zmin)*ratio2;
2707 if (newmin < zmin) newmin = hobj->GetBinContent(hobj->GetMinimumBin());
2708 if (newmax > zmax) newmax = hobj->GetBinContent(hobj->GetMaximumBin());
2709 if (GetLogz()){
2710 newmin = TMath::Exp(2.302585092994*newmin);
2711 newmax = TMath::Exp(2.302585092994*newmax);
2712 }
2713 hobj->SetMinimum(newmin);
2714 hobj->SetMaximum(newmax);
2715 hobj->SetBit(TH1::kIsZoomed);
2716 } else {
2717 first = axis->GetFirst();
2718 last = axis->GetLast();
2719 bin1 = first + Int_t((last-first+1)*ratio1);
2720 bin2 = first + Int_t((last-first+1)*ratio2);
2721 bin1 = TMath::Max(bin1, 1);
2722 bin2 = TMath::Min(bin2, axis->GetNbins());
2723 axis->SetRange(bin1, bin2);
2724 }
2725 delete view;
2726 SetView(nullptr);
2727 Modified(kTRUE);
2728 }
2729 } else {
2730 if (axisNumber == 1) {
2731 ratio2 = (AbsPixeltoX(px) - GetUxmin())/(GetUxmax() - GetUxmin());
2732 xmin = GetUxmin() +ratio1*(GetUxmax() - GetUxmin());
2733 xmax = GetUxmin() +ratio2*(GetUxmax() - GetUxmin());
2734 if (GetLogx() && !kCont4) {
2735 xmin = PadtoX(xmin);
2736 xmax = PadtoX(xmax);
2737 }
2738 } else if (axisNumber == 2) {
2739 ratio2 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
2740 xmin = GetUymin() +ratio1*(GetUymax() - GetUymin());
2741 xmax = GetUymin() +ratio2*(GetUymax() - GetUymin());
2742 if (GetLogy() && !kCont4) {
2743 xmin = PadtoY(xmin);
2744 xmax = PadtoY(xmax);
2745 }
2746 } else {
2747 ratio2 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
2748 xmin = ratio1;
2749 xmax = ratio2;
2750 }
2751 if (xmin > xmax) {
2752 temp = xmin;
2753 xmin = xmax;
2754 xmax = temp;
2755 temp = ratio1;
2756 ratio1 = ratio2;
2757 ratio2 = temp;
2758 }
2759
2760 // xmin and xmax need to be adjusted in case of CONT4.
2761 if (kCont4) {
2762 Double_t low = axis->GetBinLowEdge(axis->GetFirst());
2763 Double_t up = axis->GetBinUpEdge(axis->GetLast());
2764 Double_t xmi = GetUxmin();
2765 Double_t xma = GetUxmax();
2766 xmin = ((xmin-xmi)/(xma-xmi))*(up-low)+low;
2767 xmax = ((xmax-xmi)/(xma-xmi))*(up-low)+low;
2768 }
2769
2770 if (!strcmp(axis->GetName(),"xaxis")) axisNumber = 1;
2771 if (!strcmp(axis->GetName(),"yaxis")) axisNumber = 2;
2772 if (ratio2 - ratio1 > 0.05) {
2773 //update object owning this axis
2774 TH1 *hobj1 = (TH1*)axis->GetParent();
2775 bin1 = axis->FindFixBin(xmin);
2776 bin2 = axis->FindFixBin(xmax);
2777 bin1 = TMath::Max(bin1, 1);
2778 bin2 = TMath::Min(bin2, axis->GetNbins());
2779 if (axisNumber == 1) axis->SetRange(bin1,bin2);
2780 if (axisNumber == 2 && hobj1) {
2781 if (hobj1->GetDimension() == 1) {
2782 if (hobj1->GetNormFactor() != 0) {
2783 Double_t norm = hobj1->GetSumOfWeights()/hobj1->GetNormFactor();
2784 xmin *= norm;
2785 xmax *= norm;
2786 }
2787 hobj1->SetMinimum(xmin);
2788 hobj1->SetMaximum(xmax);
2789 hobj1->SetBit(TH1::kIsZoomed);
2790 } else {
2791 axis->SetRange(bin1,bin2);
2792 }
2793 }
2794 //update all histograms in the pad
2795 TIter next(GetListOfPrimitives());
2796 TObject *obj;
2797 while ((obj= next())) {
2798 if (!obj->InheritsFrom(TH1::Class())) continue;
2799 TH1 *hobj = (TH1*)obj;
2800 if (hobj == hobj1) continue;
2801 bin1 = hobj->GetXaxis()->FindFixBin(xmin);
2802 bin2 = hobj->GetXaxis()->FindFixBin(xmax);
2803 if (axisNumber == 1) {
2804 hobj->GetXaxis()->SetRange(bin1,bin2);
2805 } else if (axisNumber == 2) {
2806 if (hobj->GetDimension() == 1) {
2809 if (hobj->GetNormFactor() != 0) {
2810 Double_t norm = hobj->GetSumOfWeights()/hobj->GetNormFactor();
2811 xxmin *= norm;
2812 xxmax *= norm;
2813 }
2814 hobj->SetMinimum(xxmin);
2815 hobj->SetMaximum(xxmax);
2816 hobj->SetBit(TH1::kIsZoomed);
2817 } else {
2818 bin1 = hobj->GetYaxis()->FindFixBin(xmin);
2819 bin2 = hobj->GetYaxis()->FindFixBin(xmax);
2820 hobj->GetYaxis()->SetRange(bin1,bin2);
2821 }
2822 }
2823 }
2824 Modified(kTRUE);
2825 }
2826 }
2827 if (!opaque) {
2828 gVirtualX->SetLineColor(-1);
2829 } else {
2830 if (zoombox) {
2831 zoombox.reset();
2832 gPad->Modified();
2833 gPad->Update();
2834 }
2835 }
2836 break;
2837 }
2838}
2839
2840////////////////////////////////////////////////////////////////////////////////
2841/// Search if object named name is inside this pad or in pads inside this pad.
2842///
2843/// In case name is in several sub-pads the first one is returned.
2844
2845TObject *TPad::FindObject(const char *name) const
2846{
2847 if (!fPrimitives) return nullptr;
2849 if (found) return found;
2850 TIter next(GetListOfPrimitives());
2851 while (auto cur = next()) {
2852 if (cur->InheritsFrom(TPad::Class())) {
2853 found = ((TPad*)cur)->FindObject(name);
2854 if (found) return found;
2855 }
2856 }
2857 return nullptr;
2858}
2859
2860////////////////////////////////////////////////////////////////////////////////
2861/// Search if obj is in pad or in pads inside this pad.
2862///
2863/// In case obj is in several sub-pads the first one is returned.
2864
2866{
2867 if (!fPrimitives) return nullptr;
2868 TObject *found = fPrimitives->FindObject(obj);
2869 if (found) return found;
2870 TIter next(GetListOfPrimitives());
2871 while (auto cur = next()) {
2872 if (cur->InheritsFrom(TPad::Class())) {
2873 found = ((TPad*)cur)->FindObject(obj);
2874 if (found) return found;
2875 }
2876 }
2877 return nullptr;
2878}
2879
2880////////////////////////////////////////////////////////////////////////////////
2881/// Get canvas identifier.
2882
2884{
2885 return fCanvas ? fCanvas->GetCanvasID() : -1;
2886}
2887
2888////////////////////////////////////////////////////////////////////////////////
2889/// Get canvas implementation pointer if any
2890
2892{
2893 return fCanvas ? fCanvas->GetCanvasImp() : nullptr;
2894}
2895
2896////////////////////////////////////////////////////////////////////////////////
2897/// Get Event.
2898
2900{
2901 return fCanvas ? fCanvas->GetEvent() : 0;
2902}
2903
2904////////////////////////////////////////////////////////////////////////////////
2905/// Get X event.
2906
2908{
2909 return fCanvas ? fCanvas->GetEventX() : 0;
2910}
2911
2912////////////////////////////////////////////////////////////////////////////////
2913/// Get Y event.
2914
2916{
2917 return fCanvas ? fCanvas->GetEventY() : 0;
2918}
2919
2920////////////////////////////////////////////////////////////////////////////////
2921/// Get virtual canvas.
2922
2924{
2925 return fCanvas ? (TVirtualPad*) fCanvas : nullptr;
2926}
2927
2928////////////////////////////////////////////////////////////////////////////////
2929/// Get highlight color.
2930
2932{
2933 return fCanvas ? fCanvas->GetHighLightColor() : 0;
2934}
2935
2936////////////////////////////////////////////////////////////////////////////////
2937/// Static function (see also TPad::SetMaxPickDistance)
2938
2943
2944////////////////////////////////////////////////////////////////////////////////
2945/// Get selected.
2946
2948{
2949 if (fCanvas == this) return nullptr;
2950 return fCanvas ? fCanvas->GetSelected() : nullptr;
2951}
2952
2953////////////////////////////////////////////////////////////////////////////////
2954/// Get selected pad.
2955
2957{
2958 if (fCanvas == this) return nullptr;
2959 return fCanvas ? fCanvas->GetSelectedPad() : nullptr;
2960}
2961
2962////////////////////////////////////////////////////////////////////////////////
2963/// Get save pad.
2964
2966{
2967 if (fCanvas == this) return nullptr;
2968 return fCanvas ? fCanvas->GetPadSave() : nullptr;
2969}
2970
2971////////////////////////////////////////////////////////////////////////////////
2972/// Get Wh.
2973
2975{
2976 return fCanvas ? fCanvas->GetWh() : 0;
2977}
2978
2979////////////////////////////////////////////////////////////////////////////////
2980/// Get Ww.
2981
2983{
2984 return fCanvas ? fCanvas->GetWw() : 0;
2985}
2986
2987////////////////////////////////////////////////////////////////////////////////
2988/// Hide tool tip depending on the event type. Typically tool tips
2989/// are hidden when event is not a kMouseEnter and not a kMouseMotion
2990/// event.
2991
2993{
2994 if (event != kMouseEnter && event != kMouseMotion && fTip)
2995 gPad->CloseToolTip(fTip);
2996}
2997
2998////////////////////////////////////////////////////////////////////////////////
2999/// Is pad in batch mode ?
3000
3002{
3003 return fCanvas ? fCanvas->IsBatch() : kFALSE;
3004}
3005
3006////////////////////////////////////////////////////////////////////////////////
3007/// Is pad retained ?
3008
3010{
3011 return fCanvas ? fCanvas->IsRetained() : kFALSE;
3012}
3013
3014////////////////////////////////////////////////////////////////////////////////
3015/// Is web ?
3017{
3018 return fCanvas ? fCanvas->IsWeb() : kFALSE;
3019}
3020
3021////////////////////////////////////////////////////////////////////////////////
3022/// Is pad moving in opaque mode ?
3023
3025{
3026 return fCanvas ? fCanvas->OpaqueMoving() : kFALSE;
3027}
3028
3029////////////////////////////////////////////////////////////////////////////////
3030/// Is pad resizing in opaque mode ?
3031
3033{
3034 return fCanvas ? fCanvas->OpaqueResizing() : kFALSE;
3035}
3036
3037////////////////////////////////////////////////////////////////////////////////
3038/// Set pad in batch mode.
3039
3041{
3043}
3044
3045////////////////////////////////////////////////////////////////////////////////
3046/// Set canvas size.
3047
3049{
3050 if (fCanvas) fCanvas->SetCanvasSize(ww,wh);
3051}
3052
3053////////////////////////////////////////////////////////////////////////////////
3054/// Set cursor type.
3055
3060
3061////////////////////////////////////////////////////////////////////////////////
3062/// Set double buffer mode ON or OFF.
3063
3068
3069////////////////////////////////////////////////////////////////////////////////
3070/// Set selected.
3071
3073{
3074 if (fCanvas) fCanvas->SetSelected(obj);
3075}
3076
3077////////////////////////////////////////////////////////////////////////////////
3078/// Update pad.
3079
3081{
3082 if (fCanvas) fCanvas->Update();
3083}
3084
3085////////////////////////////////////////////////////////////////////////////////
3086/// Asynchronous pad update.
3087/// In case of web-based canvas triggers update of the canvas on the client side,
3088/// but does not wait that real update is completed. Avoids blocking of caller thread.
3089/// Have to be used if called from other web-based widget to avoid logical dead-locks.
3090/// In case of normal canvas just canvas->Update() is performed.
3091
3093{
3094 if (fCanvas) fCanvas->UpdateAsync();
3095}
3096
3097////////////////////////////////////////////////////////////////////////////////
3098/// Get frame.
3099
3101{
3102 if (!fPrimitives) fPrimitives = new TList;
3104 if (!frame) frame = (TFrame*)GetListOfPrimitives()->FindObject("TFrame");
3105 fFrame = frame;
3106 if (!fFrame) {
3107 if (!frame) fFrame = new TFrame(0,0,1,1);
3117 } else {
3118 // Preexisting and now assigned to fFrame, let's make sure it is not
3119 // deleted twice (the bit might have been set in TPad::Streamer)
3121 }
3122 return fFrame;
3123}
3124
3125////////////////////////////////////////////////////////////////////////////////
3126/// Get primitive.
3127
3129{
3130 if (!fPrimitives) return nullptr;
3131 TIter next(fPrimitives);
3132 TObject *found, *obj;
3133 while ((obj=next())) {
3134 if (!strcmp(name, obj->GetName())) return obj;
3135 if (obj->InheritsFrom(TPad::Class())) continue;
3136 found = obj->FindObject(name);
3137 if (found) return found;
3138 }
3139 return nullptr;
3140}
3141
3142////////////////////////////////////////////////////////////////////////////////
3143/// Get a pointer to subpadnumber of this pad.
3144
3146{
3147 if (!subpadnumber) {
3148 return (TVirtualPad*)this;
3149 }
3150
3151 TObject *obj;
3152 if (!fPrimitives) return nullptr;
3153 TIter next(GetListOfPrimitives());
3154 while ((obj = next())) {
3155 if (obj->InheritsFrom(TVirtualPad::Class())) {
3156 TVirtualPad *pad = (TVirtualPad*)obj;
3157 if (pad->GetNumber() == subpadnumber) return pad;
3158 }
3159 }
3160 return nullptr;
3161}
3162
3163////////////////////////////////////////////////////////////////////////////////
3164/// Return lower and upper bounds of the pad in NDC coordinates.
3165
3166void TPad::GetPadPar(Double_t &xlow, Double_t &ylow, Double_t &xup, Double_t &yup)
3167{
3168 xlow = fXlowNDC;
3169 ylow = fYlowNDC;
3170 xup = fXlowNDC+fWNDC;
3171 yup = fYlowNDC+fHNDC;
3172}
3173
3174////////////////////////////////////////////////////////////////////////////////
3175/// Return pad world coordinates range.
3176
3178{
3179 x1 = fX1;
3180 y1 = fY1;
3181 x2 = fX2;
3182 y2 = fY2;
3183}
3184
3185////////////////////////////////////////////////////////////////////////////////
3186/// Return pad axis coordinates range.
3187
3189{
3190 xmin = fUxmin;
3191 ymin = fUymin;
3192 xmax = fUxmax;
3193 ymax = fUymax;
3194}
3195
3196////////////////////////////////////////////////////////////////////////////////
3197/// Highlight pad.
3198/// do not highlight when printing on Postscript
3199
3201{
3202 if (gVirtualPS && gVirtualPS->TestBit(kPrintingPS)) return;
3203
3204 if (color <= 0) return;
3205
3207
3208 // We do not want to have active(executable) buttons, etc highlighted
3209 // in this manner, unless we want to edit'em
3211 //When doing a DrawClone from the GUI you would do
3212 // - select an empty pad -
3213 // - right click on object -
3214 // - select DrawClone on menu -
3215 //
3216 // Without the SetSelectedPad(); in the HighLight function, the
3217 // above instruction lead to the clone to be drawn in the
3218 // same canvas as the original object. This is because the
3219 // 'right clicking' (via TCanvas::HandleInput) changes gPad
3220 // momentarily such that when DrawClone is called, it is
3221 // not the right value (for DrawClone). Should be FIXED.
3222 gROOT->SetSelectedPad(this);
3223 if (GetBorderMode()>0) {
3224 if (set) PaintBorder(-color, kFALSE);
3226 }
3227 }
3228
3230}
3231
3232////////////////////////////////////////////////////////////////////////////////
3233/// List all primitives in pad.
3234
3236{
3238 std::cout <<IsA()->GetName()<<" fXlowNDC=" <<fXlowNDC<<" fYlowNDC="<<fYlowNDC<<" fWNDC="<<GetWNDC()<<" fHNDC="<<GetHNDC()
3239 <<" Name= "<<GetName()<<" Title= "<<GetTitle()<<" Option="<<option<<std::endl;
3241 if (!fPrimitives) return;
3244}
3245
3246////////////////////////////////////////////////////////////////////////////////
3247/// Increment (i==1) or set (i>1) the number of autocolor in the pad.
3248
3250{
3251 if (opt.Index("pfc")>=0 || opt.Index("plc")>=0 || opt.Index("pmc")>=0) {
3252 if (i==1) fNumPaletteColor++;
3253 else fNumPaletteColor = i;
3254 return fNumPaletteColor;
3255 } else {
3256 return 0;
3257 }
3258}
3259
3260////////////////////////////////////////////////////////////////////////////////
3261/// Get the next autocolor in the pad.
3262
3264{
3265 Int_t i = 0;
3266 Int_t ncolors = gStyle->GetNumberOfColors();
3267 if (fNumPaletteColor>1) {
3268 i = fNextPaletteColor*(ncolors/(fNumPaletteColor-1));
3269 if (i>=ncolors) i = ncolors-1;
3270 }
3273 return gStyle->GetColorPalette(i);
3274}
3275
3276////////////////////////////////////////////////////////////////////////////////
3277/// Initialise the grid used to find empty space when adding a box (Legend) in a pad
3278
3280{
3281 Int_t const cellSize = 10; // Size of an individual grid cell in pixels.
3282
3283 fCGnx = GetWw()/cellSize;
3284 fCGny = GetWh()/cellSize;
3285
3286 // Initialise the collide grid
3287 fCollideGrid.resize(fCGnx*fCGny);
3288 for (int i = 0; i < fCGnx; i++)
3289 for (int j = 0; j < fCGny; j++)
3290 fCollideGrid[i + j * fCGnx] = kTRUE;
3291
3292 // Fill the collide grid
3293 TIter iter(GetListOfPrimitives());
3294
3295 while(auto o = iter()) {
3296 if (o == oi)
3297 continue;
3298 if (o->InheritsFrom(TFrame::Class()))
3300 else if (o->InheritsFrom(TBox::Class()))
3302 else if (o->InheritsFrom(TH1::Class()))
3304 else if (o->InheritsFrom(TGraph::Class()))
3306 else if (o->InheritsFrom(TMultiGraph::Class())) {
3307 TIter nextgraph(((TMultiGraph *)o)->GetListOfGraphs());
3308 while (auto og = nextgraph())
3310 } else if (o->InheritsFrom(THStack::Class())) {
3311 TIter nexthist(((THStack *)o)->GetHists());
3312 while (auto oh = nexthist()) {
3313 if (oh->InheritsFrom(TH1::Class()))
3315 }
3316 }
3317 }
3318}
3319
3320////////////////////////////////////////////////////////////////////////////////
3321/// Check if a box of size w and h collide some primitives in the pad at
3322/// position i,j
3323
3325{
3326 for (int r = i; r < w + i; r++) {
3327 for (int c = j; c < h + j; c++) {
3328 if (!fCollideGrid[r + c * fCGnx])
3329 return kTRUE;
3330 }
3331 }
3332 return kFALSE;
3333}
3334
3335////////////////////////////////////////////////////////////////////////////////
3336/// Place a box in NDC space
3337///
3338/// \return `true` if the box could be placed, `false` if not.
3339///
3340/// \param[in] o pointer to the box to be placed
3341/// \param[in] w box width to be placed
3342/// \param[in] h box height to be placed
3343/// \param[out] xl x position of the bottom left corner of the placed box
3344/// \param[out] yb y position of the bottom left corner of the placed box
3345/// \param[in] option l=left, r=right, t=top, b=bottom, w=within margins. Order determines
3346/// priority for placement. Default is "lb" (prioritises horizontal over vertical)
3347
3349{
3350 FillCollideGrid(o);
3351
3352 Int_t iw = (int)(fCGnx*w);
3353 Int_t ih = (int)(fCGny*h);
3354
3355 Int_t nxbeg = 0;
3356 Int_t nybeg = 0;
3357 Int_t nxend = fCGnx-iw-1;
3358 Int_t nyend = fCGny-ih-1;
3359 Int_t dx = 1;
3360 Int_t dy = 1;
3361
3362 bool isFirstVertical = false;
3363 bool isFirstHorizontal = false;
3364
3365 for (std::size_t i = 0; option[i] != '\0'; ++i) {
3366 char letter = std::tolower(option[i]);
3367 if (letter == 'w') {
3372 } else if (letter == 't' || letter == 'b') {
3374 // go from top to bottom instead of bottom to top
3375 dy = letter == 't' ? -1 : 1;
3376 } else if (letter == 'l' || letter == 'r') {
3378 // go from right to left instead of left to right
3379 dx = letter == 'r' ? -1 : 1;
3380 }
3381 }
3382
3383 if(dx < 0) std::swap(nxbeg, nxend);
3384 if(dy < 0) std::swap(nybeg, nyend);
3385
3386 auto attemptPlacement = [&](Int_t i, Int_t j) {
3387 if (Collide(i, j, iw, ih)) {
3388 return false;
3389 } else {
3390 xl = (Double_t)(i) / (Double_t)(fCGnx);
3391 yb = (Double_t)(j) / (Double_t)(fCGny);
3392 return true;
3393 }
3394 };
3395
3396 if(!isFirstVertical) {
3397 for (Int_t i = nxbeg; i != nxend; i += dx) {
3398 for (Int_t j = nybeg; j != nyend; j += dy) {
3399 if (attemptPlacement(i, j)) return true;
3400 }
3401 }
3402 } else {
3403 // prioritizing vertical over horizontal
3404 for (Int_t j = nybeg; j != nyend; j += dy) {
3405 for (Int_t i = nxbeg; i != nxend; i += dx) {
3406 if (attemptPlacement(i, j)) return true;
3407 }
3408 }
3409 }
3410
3411 return kFALSE;
3412}
3413
3414#define NotFree(i, j) fCollideGrid[TMath::Max(TMath::Min(i+j*fCGnx,fCGnx*fCGny),0)] = kFALSE;
3415
3416////////////////////////////////////////////////////////////////////////////////
3417/// Mark as "not free" the cells along a line.
3418
3420{
3421 NotFree(x1, y1);
3422 NotFree(x2, y2);
3423 Int_t i, j, xt, yt;
3424
3425 // horizontal lines
3426 if (y1==y2) {
3427 for (i=x1+1; i<x2; i++) NotFree(i,y1);
3428 return;
3429 }
3430
3431 // vertical lines
3432 if (x1==x2) {
3433 for (i=y1+1; i<y2; i++) NotFree(x1,i);
3434 return;
3435 }
3436
3437 // other lines
3438 if (TMath::Abs(x2-x1)>TMath::Abs(y2-y1)) {
3439 if (x1>x2) {
3440 xt = x1; x1 = x2; x2 = xt;
3441 yt = y1; y1 = y2; y2 = yt;
3442 }
3443 for (i=x1+1; i<x2; i++) {
3444 j = (Int_t)((Double_t)(y2-y1)*(Double_t)((i-x1)/(Double_t)(x2-x1))+y1);
3445 NotFree(i,j);
3446 NotFree(i,(j+1));
3447 }
3448 } else {
3449 if (y1>y2) {
3450 yt = y1; y1 = y2; y2 = yt;
3451 xt = x1; x1 = x2; x2 = xt;
3452 }
3453 for (j=y1+1; j<y2; j++) {
3454 i = (Int_t)((Double_t)(x2-x1)*(Double_t)((j-y1)/(Double_t)(y2-y1))+x1);
3455 NotFree(i,j);
3456 NotFree((i+1),j);
3457 }
3458 }
3459}
3460
3461////////////////////////////////////////////////////////////////////////////////
3463{
3464 TBox *b = (TBox *)o;
3465 if (fCGnx==0||fCGny==0) return;
3466 Double_t xs = (fX2-fX1)/fCGnx;
3467 Double_t ys = (fY2-fY1)/fCGny;
3468
3469 Int_t x1 = (Int_t)((b->GetX1()-fX1)/xs);
3470 Int_t x2 = (Int_t)((b->GetX2()-fX1)/xs);
3471 Int_t y1 = (Int_t)((b->GetY1()-fY1)/ys);
3472 Int_t y2 = (Int_t)((b->GetY2()-fY1)/ys);
3473 for (int i = x1; i<=x2; i++) {
3474 for (int j = y1; j<=y2; j++) NotFree(i, j);
3475 }
3476}
3477
3478////////////////////////////////////////////////////////////////////////////////
3480{
3481 TFrame *f = (TFrame *)o;
3482 if (fCGnx==0||fCGny==0) return;
3483 Double_t xs = (fX2-fX1)/fCGnx;
3484 Double_t ys = (fY2-fY1)/fCGny;
3485
3486 Int_t x1 = (Int_t)((f->GetX1()-fX1)/xs);
3487 Int_t x2 = (Int_t)((f->GetX2()-fX1)/xs);
3488 Int_t y1 = (Int_t)((f->GetY1()-fY1)/ys);
3489 Int_t y2 = (Int_t)((f->GetY2()-fY1)/ys);
3490 Int_t i;
3491
3492 for (i = x1; i<=x2; i++) {
3493 NotFree(i, y1);
3494 NotFree(i, (y1-1));
3495 NotFree(i, (y1-2));
3496 }
3497 for (i = y1; i<=y2; i++) {
3498 NotFree(x1, i);
3499 NotFree((x1-1), i);
3500 NotFree((x1-2), i);
3501 }
3502}
3503
3504////////////////////////////////////////////////////////////////////////////////
3506{
3507 TGraph *g = (TGraph *)o;
3508 if (fCGnx==0||fCGny==0) return;
3509 Double_t xs = (fX2-fX1)/fCGnx;
3510 Double_t ys = (fY2-fY1)/fCGny;
3511
3512 Int_t n = g->GetN();
3513 Int_t s = TMath::Max(n/10,1);
3514 Double_t x1, x2, y1, y2;
3515 for (Int_t i=s; i<n; i=i+s) {
3516 g->GetPoint(TMath::Max(0,i-s),x1,y1);
3517 g->GetPoint(i ,x2,y2);
3518 if (fLogx) {
3519 if (x1 > 0) x1 = TMath::Log10(x1);
3520 else x1 = fUxmin;
3521 if (x2 > 0) x2 = TMath::Log10(x2);
3522 else x2 = fUxmin;
3523 }
3524 if (fLogy) {
3525 if (y1 > 0) y1 = TMath::Log10(y1);
3526 else y1 = fUymin;
3527 if (y2 > 0) y2 = TMath::Log10(y2);
3528 else y2 = fUymin;
3529 }
3530 LineNotFree((int)((x1-fX1)/xs), (int)((x2-fX1)/xs),
3531 (int)((y1-fY1)/ys), (int)((y2-fY1)/ys));
3532 }
3533}
3534
3535////////////////////////////////////////////////////////////////////////////////
3537{
3538 TH1 *h = (TH1 *)o;
3539 if (fCGnx==0||fCGny==0) return;
3540 if (o->InheritsFrom(TH2::Class())) return;
3541 if (o->InheritsFrom(TH3::Class())) return;
3542
3543 TString name = h->GetName();
3544 if (name.Index("hframe") >= 0) return;
3545
3546 Double_t xs = (fX2-fX1)/fCGnx;
3547 Double_t ys = (fY2-fY1)/fCGny;
3548
3549 bool haserrors = false;
3550 TString drawOption = h->GetDrawOption();
3551 drawOption.ToLower();
3552 drawOption.ReplaceAll("same","");
3553
3554 if (drawOption.Index("hist") < 0) {
3555 if (drawOption.Index("e") >= 0) haserrors = true;
3556 }
3557
3558 Int_t nx = h->GetNbinsX();
3559 Int_t x1, y1, y2;
3560 Int_t i, j;
3561 Double_t x1l, y1l, y2l;
3562
3563 for (i = 1; i<nx; i++) {
3564 if (haserrors) {
3565 x1l = h->GetBinCenter(i);
3566 if (fLogx) {
3567 if (x1l > 0) x1l = TMath::Log10(x1l);
3568 else x1l = fUxmin;
3569 }
3570 x1 = (Int_t)((x1l-fX1)/xs);
3571 y1l = h->GetBinContent(i)-h->GetBinErrorLow(i);
3572 if (fLogy) {
3573 if (y1l > 0) y1l = TMath::Log10(y1l);
3574 else y1l = fUymin;
3575 }
3576 y1 = (Int_t)((y1l-fY1)/ys);
3577 y2l = h->GetBinContent(i)+h->GetBinErrorUp(i);
3578 if (fLogy) {
3579 if (y2l > 0) y2l = TMath::Log10(y2l);
3580 else y2l = fUymin;
3581 }
3582 y2 = (Int_t)((y2l-fY1)/ys);
3583 for (j=y1; j<y2; j++) {
3584 NotFree(x1, j);
3585 }
3586 }
3587 x1l = h->GetBinLowEdge(i);
3588 if (fLogx) {
3589 if (x1l > 0) x1l = TMath::Log10(x1l);
3590 else x1l = fUxmin;
3591 }
3592 x1 = (Int_t)((x1l-fX1)/xs);
3593 y1l = h->GetBinContent(i);
3594 if (fLogy) {
3595 if (y1l > 0) y1l = TMath::Log10(y1l);
3596 else y1l = fUymin;
3597 }
3598 y1 = (Int_t)((y1l-fY1)/ys);
3599 NotFree(x1, y1);
3600 x1l = h->GetBinLowEdge(i)+h->GetBinWidth(i);
3601 if (fLogx) {
3602 if (x1l > 0) x1l = TMath::Log10(x1l);
3603 else x1l = fUxmin;
3604 }
3605 x1 = (int)((x1l-fX1)/xs);
3606 NotFree(x1, y1);
3607 }
3608
3609 // Extra objects in the list of function
3610 TPaveStats *ps = (TPaveStats*)h->GetListOfFunctions()->FindObject("stats");
3611 if (ps) FillCollideGridTBox(ps);
3612}
3613
3614////////////////////////////////////////////////////////////////////////////////
3615/// This method draws the collide grid on top of the canvas. This is used for
3616/// debugging only. At some point it will be removed.
3617
3619{
3620 if (fCGnx==0||fCGny==0) return;
3621
3622 TContext ctxt(this, kTRUE);
3623
3624 TBox box;
3625 box.SetFillColorAlpha(kRed,0.5);
3626
3627 Double_t xs = (fX2-fX1)/fCGnx;
3628 Double_t ys = (fY2-fY1)/fCGny;
3629
3630 Double_t X1L, X2L, Y1L, Y2L;
3631 Double_t t = 0.15;
3632 Double_t Y1, Y2;
3633 Double_t X1 = fX1;
3634 Double_t X2 = X1+xs;
3635
3636 for (int i = 0; i<fCGnx; i++) {
3637 Y1 = fY1;
3638 Y2 = Y1+ys;
3639 for (int j = 0; j<fCGny; j++) {
3640 if (GetLogx()) {
3641 X1L = TMath::Power(10,X1);
3642 X2L = TMath::Power(10,X2);
3643 } else {
3644 X1L = X1;
3645 X2L = X2;
3646 }
3647 if (GetLogy()) {
3648 Y1L = TMath::Power(10,Y1);
3649 Y2L = TMath::Power(10,Y2);
3650 } else {
3651 Y1L = Y1;
3652 Y2L = Y2;
3653 }
3654 if (!fCollideGrid[i + j*fCGnx]) {
3655 box.SetFillColorAlpha(kBlack,t);
3656 box.DrawBox(X1L, Y1L, X2L, Y2L);
3657 } else {
3658 box.SetFillColorAlpha(kRed,t);
3659 box.DrawBox(X1L, Y1L, X2L, Y2L);
3660 }
3661 Y1 = Y2;
3662 Y2 = Y1+ys;
3663 if (t==0.15) t = 0.1;
3664 else t = 0.15;
3665 }
3666 X1 = X2;
3667 X2 = X1+xs;
3668 }
3669}
3670
3671////////////////////////////////////////////////////////////////////////////////
3672/// Short cut to call Modified() and Update() in a single call.
3673/// On Mac with Cocoa, it performs an additional ProcessEvents().
3674
3676{
3677 Modified();
3678 Update();
3679#ifdef R__HAS_COCOA
3681#endif
3682}
3683
3684////////////////////////////////////////////////////////////////////////////////
3685/// Convert x from pad to X.
3686
3688{
3689 if (fLogx && x < 50) return Double_t(TMath::Exp(2.302585092994*x));
3690 return x;
3691}
3692
3693////////////////////////////////////////////////////////////////////////////////
3694/// Convert y from pad to Y.
3695
3697{
3698 if (fLogy && y < 50) return Double_t(TMath::Exp(2.302585092994*y));
3699 return y;
3700}
3701
3702////////////////////////////////////////////////////////////////////////////////
3703/// Convert x from X to pad.
3704
3706{
3707 if (fLogx) {
3708 if (x > 0) x = TMath::Log10(x);
3709 else x = fUxmin;
3710 }
3711 return x;
3712}
3713
3714////////////////////////////////////////////////////////////////////////////////
3715/// Convert y from Y to pad.
3716
3718{
3719 if (fLogy) {
3720 if (y > 0) y = TMath::Log10(y);
3721 else y = fUymin;
3722 }
3723 return y;
3724}
3725
3726////////////////////////////////////////////////////////////////////////////////
3727/// Paint all primitives in pad.
3728
3729void TPad::Paint(Option_t * /*option*/)
3730{
3731 if (!fPrimitives)
3732 fPrimitives = new TList;
3734 fViewer3D->PadPaint(this);
3736 if (GetGLDevice()!=-1 && gVirtualPS) {
3737 TContext ctxt(this, kFALSE);
3738 if (gGLManager) gGLManager->PrintViewer(GetViewer3D());
3739 }
3740 return;
3741 }
3742
3744
3746 fPadPaint = 1;
3747
3748 {
3749 TContext ctxt(this, kTRUE);
3750
3752 PaintDate();
3753
3754 auto lnk = GetListOfPrimitives()->FirstLink();
3755
3756 while (lnk) {
3757 TObject *obj = lnk->GetObject();
3758
3759 // Create a pad 3D viewer if none exists and we encounter a 3D shape
3760 if (!fViewer3D && obj->InheritsFrom(TAtt3D::Class())) {
3761 GetViewer3D("pad");
3762 }
3763
3764 // Open a 3D scene if required
3765 if (fViewer3D && !fViewer3D->BuildingScene()) {
3768 }
3769
3770 obj->Paint(lnk->GetOption());
3771 lnk = lnk->Next();
3772 }
3773 }
3774
3775 fPadPaint = 0;
3777
3778 // Close the 3D scene if we opened it. This must be done after modified
3779 // flag is cleared, as some viewers will invoke another paint by marking pad modified again
3780 if (began3DScene) {
3782 }
3783}
3784
3785////////////////////////////////////////////////////////////////////////////////
3786/// Paint the pad border.
3787/// Draw first a box as a normal filled box
3788
3790{
3791 if (color >= 0) {
3792 TAttLine::Modify(); //Change line attributes only if necessary
3793 TAttFill::Modify(); //Change fill area attributes only if necessary
3794
3795 //With Cocoa we have a transparency. But we also have
3796 //pixmaps, and if you just paint a new content over the old one
3797 //with alpha < 1., you'll be able to see the old content.
3798 if (!gROOT->IsBatch() && gVirtualX->InheritsFrom("TGCocoa") && GetPainter())
3800
3802 }
3803 if (color < 0) color = -color;
3804 // then paint 3d frame (depending on bordermode)
3805 if (IsTransparent()) return;
3806 // Paint a 3D frame around the pad.
3807
3808 if (fBorderMode == 0) return;
3810 if (bordersize <= 0) bordersize = 2;
3811
3812 const Double_t realBsX = bordersize / (GetAbsWNDC() * GetWw()) * (fX2 - fX1);
3813 const Double_t realBsY = bordersize / (GetAbsHNDC() * GetWh()) * (fY2 - fY1);
3814
3815 Short_t px1,py1,px2,py2;
3816 Double_t xl, xt, yl, yt;
3817
3818 // GetColorDark() and GetColorBright() use GetFillColor()
3820 SetFillColor(color);
3822 Color_t light = 0, dark = 0;
3823 if (color != 0) {
3825 dark = TColor::GetColorDark(color);
3826 }
3827
3828 // Compute real left bottom & top right of the box in pixels
3829 px1 = XtoPixel(fX1); py1 = YtoPixel(fY1);
3830 px2 = XtoPixel(fX2); py2 = YtoPixel(fY2);
3831 if (px1 < px2) {xl = fX1; xt = fX2; }
3832 else {xl = fX2; xt = fX1;}
3833 if (py1 > py2) {yl = fY1; yt = fY2;}
3834 else {yl = fY2; yt = fY1;}
3835
3836 Double_t frameXs[7] = {}, frameYs[7] = {};
3837
3838 if (!IsBatch() && GetPainter()) {
3839 // Draw top&left part of the box
3840 frameXs[0] = xl; frameYs[0] = yl;
3841 frameXs[1] = xl + realBsX; frameYs[1] = yl + realBsY;
3842 frameXs[2] = frameXs[1]; frameYs[2] = yt - realBsY;
3843 frameXs[3] = xt - realBsX; frameYs[3] = frameYs[2];
3844 frameXs[4] = xt; frameYs[4] = yt;
3845 frameXs[5] = xl; frameYs[5] = yt;
3846 frameXs[6] = xl; frameYs[6] = yl;
3847
3848 if (fBorderMode == -1) GetPainter()->SetFillColor(dark);
3849 else GetPainter()->SetFillColor(light);
3851
3852 // Draw bottom&right part of the box
3853 frameXs[0] = xl; frameYs[0] = yl;
3854 frameXs[1] = xl + realBsX; frameYs[1] = yl + realBsY;
3855 frameXs[2] = xt - realBsX; frameYs[2] = frameYs[1];
3856 frameXs[3] = frameXs[2]; frameYs[3] = yt - realBsY;
3857 frameXs[4] = xt; frameYs[4] = yt;
3858 frameXs[5] = xt; frameYs[5] = yl;
3859 frameXs[6] = xl; frameYs[6] = yl;
3860
3862 else GetPainter()->SetFillColor(dark);
3864
3865 // If this pad is a button, highlight it
3866 if (InheritsFrom(TButton::Class()) && fBorderMode == -1) {
3867 if (TestBit(kFraming)) { // bit set in TButton::SetFraming
3868 if (GetFillColor() != 2) GetPainter()->SetLineColor(2);
3869 else GetPainter()->SetLineColor(4);
3871 }
3872 }
3873 GetPainter()->SetFillColor(-1);
3875 }
3876
3877 if (!tops) return;
3878
3880}
3881
3882////////////////////////////////////////////////////////////////////////////////
3883/// Paint a frame border with Postscript.
3884
3890
3891////////////////////////////////////////////////////////////////////////////////
3892/// Paint the current date and time if the option `Date` is set on via `gStyle->SetOptDate()`
3893/// Paint the current file name if the option `File` is set on via `gStyle->SetOptFile()`
3894
3896{
3897 if (fCanvas == this) {
3898 if (gStyle->GetOptDate()) {
3899 TDatime dt;
3900 const char *dates;
3901 char iso[16];
3902 if (gStyle->GetOptDate() < 10) {
3903 //by default use format like "Wed Sep 25 17:10:35 2002"
3904 dates = dt.AsString();
3905 } else if (gStyle->GetOptDate() < 20) {
3906 //use ISO format like 2002-09-25
3907 strlcpy(iso,dt.AsSQLString(),16);
3908 dates = iso;
3909 } else {
3910 //use ISO format like 2002-09-25 17:10:35
3911 dates = dt.AsSQLString();
3912 }
3914 tdate.SetTextSize( gStyle->GetAttDate()->GetTextSize());
3915 tdate.SetTextFont( gStyle->GetAttDate()->GetTextFont());
3916 tdate.SetTextColor(gStyle->GetAttDate()->GetTextColor());
3917 tdate.SetTextAlign(gStyle->GetAttDate()->GetTextAlign());
3918 tdate.SetTextAngle(gStyle->GetAttDate()->GetTextAngle());
3919 tdate.SetNDC();
3920 tdate.Paint();
3921 }
3922 if (gStyle->GetOptFile() && gFile) {
3923 TText tfile(1. - gStyle->GetDateX(),gStyle->GetDateY(),gFile->GetName());
3927 tfile.SetTextAlign(31);
3929 tfile.SetNDC();
3930 tfile.Paint();
3931 }
3932 }
3933}
3934
3935////////////////////////////////////////////////////////////////////////////////
3936/// Paint histogram/graph frame.
3937
3939{
3940 if (!fPrimitives) fPrimitives = new TList;
3942 TFrame *frame = GetFrame();
3943 frame->SetX1(xmin);
3944 frame->SetX2(xmax);
3945 frame->SetY1(ymin);
3946 frame->SetY2(ymax);
3947 if (!glist->FindObject(fFrame)) {
3948 glist->AddFirst(frame);
3950 }
3951 frame->Paint();
3952}
3953
3954////////////////////////////////////////////////////////////////////////////////
3955/// Traverse pad hierarchy and (re)paint only modified pads.
3956
3958{
3960 if (IsModified()) {
3961 fViewer3D->PadPaint(this);
3963 }
3965 auto lnk = pList ? pList->FirstLink() : nullptr;
3966 while (lnk) {
3967 auto obj = lnk->GetObject();
3968 if (obj->InheritsFrom(TPad::Class()))
3969 ((TPad*)obj)->PaintModified();
3970 lnk = lnk->Next();
3971 }
3972 return;
3973 }
3974
3976
3978 if (gVirtualPS) {
3980 gVirtualPS = nullptr;
3981 }
3982
3984 fPadPaint = 1;
3985 {
3986 TContext ctxt(this, kTRUE);
3987 if (IsModified() || IsTransparent()) {
3988 if ((fFillStyle < 3026) && (fFillStyle > 3000)) {
3989 if (!gPad->IsBatch() && GetPainter()) GetPainter()->ClearDrawable();
3990 }
3992 }
3993
3994 PaintDate();
3995
3997 auto lnk = pList ? pList->FirstLink() : nullptr;
3998
3999 while (lnk) {
4000 TObject *obj = lnk->GetObject();
4001 if (obj->InheritsFrom(TPad::Class())) {
4002 ((TPad*)obj)->PaintModified();
4003 } else if (IsModified() || IsTransparent()) {
4004
4005 // Create a pad 3D viewer if none exists and we encounter a
4006 // 3D shape
4007 if (!fViewer3D && obj->InheritsFrom(TAtt3D::Class())) {
4008 GetViewer3D("pad");
4009 }
4010
4011 // Open a 3D scene if required
4012 if (fViewer3D && !fViewer3D->BuildingScene()) {
4015 }
4016
4017 obj->Paint(lnk->GetOption());
4018 }
4019 lnk = lnk->Next();
4020 }
4021 }
4022
4023 fPadPaint = 0;
4025
4026 // This must be done after modified flag is cleared, as some
4027 // viewers will invoke another paint by marking pad modified again
4028 if (began3DScene) {
4030 }
4031
4033}
4034
4035////////////////////////////////////////////////////////////////////////////////
4036/// Paint box in CurrentPad World coordinates.
4037///
4038/// - if option[0] = 's' the box is forced to be paint with style=0
4039/// - if option[0] = 'l' the box contour is drawn
4040
4042{
4043 if (!gPad->IsBatch() && GetPainter()) {
4045 Int_t style = style0;
4046 if (option[0] == 's') {
4048 style = 0;
4049 }
4050 if (style) {
4051 if (style > 3000 && style < 4000) {
4052 if (style < 3026) {
4053 // draw stipples with fFillColor foreground
4055 }
4056
4057 if (style >= 3100 && style < 4000) {
4058 Double_t xb[4], yb[4];
4059 xb[0] = x1; xb[1] = x1; xb[2] = x2; xb[3] = x2;
4060 yb[0] = y1; yb[1] = y2; yb[2] = y2; yb[3] = y1;
4062 return;
4063 }
4064 //special case for TAttFillCanvas
4065 if (GetPainter()->GetFillColor() == 10) {
4068 GetPainter()->SetFillColor(10);
4069 }
4070 } else if (style >= 4000 && style <= 4100) {
4071 // For style >=4000 we make the window transparent.
4072 // From 4000 to 4100 the window is 100% transparent to 100% opaque
4073
4074 //ignore this style option when this is the canvas itself
4075 if (this == fMother) {
4076 //It's clear, that virtual X checks a style (4000) and will render a hollow rect!
4078 if (gVirtualX->InheritsFrom("TGCocoa"))
4079 GetPainter()->SetFillStyle(1000);
4081 if (gVirtualX->InheritsFrom("TGCocoa"))
4083 } else {
4084 //draw background by blitting all bottom pads
4085 int px, py;
4086 XYtoAbsPixel(fX1, fY2, px, py);
4087
4088 if (fMother) {
4090 CopyBackgroundPixmaps(fMother, this, px, py);
4091 }
4092
4093 GetPainter()->SetOpacity(style - 4000);
4094 }
4095 } else if (style >= 1000 && style <= 1999) {
4097 } else {
4099 }
4101 } else {
4103 if (option[0] == 's') GetPainter()->SetFillStyle(style0);
4104 }
4105 }
4106
4107 if (gVirtualPS) {
4109 if (option[0] == 's') {
4111 } else {
4112 if (style0 >= 3100 && style0 < 4000) {
4113 Double_t xb[4], yb[4];
4114 xb[0] = x1; xb[1] = x1; xb[2] = x2; xb[3] = x2;
4115 yb[0] = y1; yb[1] = y2; yb[2] = y2; yb[3] = y1;
4117 return;
4118 }
4119 }
4120 gVirtualPS->DrawBox(x1, y1, x2, y2);
4121 if (option[0] == 'l') {
4123 gVirtualPS->DrawBox(x1, y1, x2, y2);
4124 }
4125 if (option[0] == 's' || option[0] == 'l') gVirtualPS->SetFillStyle(style0);
4126 }
4127
4128 Modified();
4129}
4130
4131////////////////////////////////////////////////////////////////////////////////
4132/// Copy pixmaps of pads laying below pad "stop" into pad "stop". This
4133/// gives the effect of pad "stop" being transparent.
4134
4136{
4137 if (!start) return;
4138 TObject *obj;
4139 if (!fPrimitives) fPrimitives = new TList;
4140 TIter next(start->GetListOfPrimitives());
4141 while ((obj = next())) {
4142 if (obj->InheritsFrom(TPad::Class())) {
4143 if (obj == stop) break;
4144 ((TPad*)obj)->CopyBackgroundPixmap(x, y);
4145 ((TPad*)obj)->CopyBackgroundPixmaps((TPad*)obj, stop, x, y);
4146 }
4147 }
4148}
4149
4150////////////////////////////////////////////////////////////////////////////////
4151/// Copy pixmap of this pad as background of the current pad.
4152
4154{
4155 int px, py;
4156 XYtoAbsPixel(fX1, fY2, px, py);
4157 if (GetPainter()) GetPainter()->CopyDrawable(GetPixmapID(), px-x, py-y);
4158}
4159
4160////////////////////////////////////////////////////////////////////////////////
4161
4163{
4164 Warning("TPad::PaintFillArea", "Float_t signature is obsolete. Use Double_t signature.");
4165}
4166
4167////////////////////////////////////////////////////////////////////////////////
4168/// Paint fill area in CurrentPad World coordinates.
4169
4171{
4172 if (nn <3) return;
4173 Int_t n=0;
4177 } else {
4178 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4179 }
4180
4181 Int_t nc = 2*nn+1;
4182 std::vector<Double_t> x(nc, 0.);
4183 std::vector<Double_t> y(nc, 0.);
4184
4185 n = ClipPolygon(nn, xx, yy, nc, &x.front(), &y.front(),xmin,ymin,xmax,ymax);
4186 if (!n)
4187 return;
4188
4189 // Paint the fill area with hatches
4191 if (gPad->IsBatch() && GetPainter() && gVirtualPS) fillstyle = gVirtualPS->GetFillStyle();
4192 if (fillstyle >= 3100 && fillstyle < 4000) {
4193 PaintFillAreaHatches(nn, &x.front(), &y.front(), fillstyle);
4194 return;
4195 }
4196
4197 if (!gPad->IsBatch() && GetPainter())
4198 // invoke the graphics subsystem
4199 GetPainter()->DrawFillArea(n, &x.front(), &y.front());
4200
4201 if (gVirtualPS)
4202 gVirtualPS->DrawPS(-n, &x.front(), &y.front());
4203
4204 Modified();
4205}
4206
4207////////////////////////////////////////////////////////////////////////////////
4208/// Paint fill area in CurrentPad NDC coordinates.
4209
4211{
4212 std::vector<Double_t> xw(n), yw(n);
4213 for (int i=0; i<n; i++) {
4214 xw[i] = fX1 + x[i]*(fX2 - fX1);
4215 yw[i] = fY1 + y[i]*(fY2 - fY1);
4216 }
4217 PaintFillArea(n, xw.data(), yw.data(), option);
4218}
4219
4220////////////////////////////////////////////////////////////////////////////////
4221/// This function paints hatched fill area according to the FillStyle value
4222/// The convention for the Hatch is the following:
4223///
4224/// `FillStyle = 3ijk`
4225///
4226/// - i (1-9) : specify the space between each hatch
4227/// 1 = minimum 9 = maximum
4228/// the final spacing is i*GetHatchesSpacing(). The hatches spacing
4229/// is set by SetHatchesSpacing()
4230/// - j (0-9) : specify angle between 0 and 90 degrees
4231/// * 0 = 0
4232/// * 1 = 10
4233/// * 2 = 20
4234/// * 3 = 30
4235/// * 4 = 45
4236/// * 5 = Not drawn
4237/// * 6 = 60
4238/// * 7 = 70
4239/// * 8 = 80
4240/// * 9 = 90
4241/// - k (0-9) : specify angle between 90 and 180 degrees
4242/// * 0 = 180
4243/// * 1 = 170
4244/// * 2 = 160
4245/// * 3 = 150
4246/// * 4 = 135
4247/// * 5 = Not drawn
4248/// * 6 = 120
4249/// * 7 = 110
4250/// * 8 = 100
4251/// * 9 = 90
4252
4254{
4255 static Double_t ang1[10] = { 0., 10., 20., 30., 45.,5., 60., 70., 80., 89.99};
4256 static Double_t ang2[10] = {180.,170.,160.,150.,135.,5.,120.,110.,100., 89.99};
4257
4258 Int_t fasi = FillStyle % 1000;
4259 Int_t idSPA = fasi / 100;
4260 Int_t iAng2 = (fasi - 100 * idSPA) / 10;
4261 Int_t iAng1 = fasi % 10;
4262 Double_t dy = 0.003 * idSPA * gStyle->GetHatchesSpacing();
4264 Int_t lss = 0, lss2 = 0, lcs = 0, lcs2 = 0;
4265
4266 // Save the current line attributes and change to draw hatches
4267 if (!gPad->IsBatch() && GetPainter()) {
4274 }
4275 if (gVirtualPS) {
4282 }
4283
4284 // Draw the hatches
4285 if (ang1[iAng1] != 5.) PaintHatches(dy, ang1[iAng1], nn, xx, yy);
4286 if (ang2[iAng2] != 5.) PaintHatches(dy, ang2[iAng2], nn, xx, yy);
4287
4288 // Restore the line attributes
4289 if (!gPad->IsBatch() && GetPainter()) {
4293 }
4294 if (gVirtualPS) {
4298 }
4299}
4300
4301////////////////////////////////////////////////////////////////////////////////
4302/// This routine draw hatches inclined with the
4303/// angle "angle" and spaced of "dy" in normalized device
4304/// coordinates in the surface defined by n,xx,yy.
4305
4308{
4309 Int_t i, i1, i2, nbi, m, inv;
4311 const Double_t angr = TMath::Pi()*(180.-angle)/180.;
4312 const Double_t epsil = 0.0001;
4313 const Int_t maxnbi = 100;
4314 Double_t xli[maxnbi], xlh[2], ylh[2], xt1, xt2, yt1, yt2;
4315 Double_t ll, x, y, x1, x2, y1, y2, a, b, xi, xip, xin, yi, yip;
4316
4317 Double_t rwxmin = gPad->GetX1();
4318 Double_t rwxmax = gPad->GetX2();
4319 Double_t rwymin = gPad->GetY1();
4320 Double_t rwymax = gPad->GetY2();
4321 ratiox = 1./(rwxmax-rwxmin);
4322 ratioy = 1./(rwymax-rwymin);
4323
4326 if (TMath::Abs(cosa) <= epsil) cosa=0.;
4327 if (TMath::Abs(sina) <= epsil) sina=0.;
4328 sinb = -sina;
4329 cosb = cosa;
4330
4331 // Values needed to compute the hatches in TRUE normalized space (NDC)
4332 Int_t iw = (Int_t)gPad->GetWw();
4333 Int_t ih = (Int_t)gPad->GetWh();
4335 gPad->GetPadPar(x1p,y1p,x2p,y2p);
4336 iw = (Int_t)(iw*x2p)-(Int_t)(iw*x1p);
4337 ih = (Int_t)(ih*y2p)-(Int_t)(ih*y1p);
4340
4341 // Search ymin and ymax
4342 ymin = 1.;
4343 ymax = 0.;
4344 for (i=1; i<=nn; i++) {
4345 x = wndc*ratiox*(xx[i-1]-rwxmin);
4346 y = hndc*ratioy*(yy[i-1]-rwymin);
4347 yrot = sina*x+cosa*y;
4348 if (yrot > ymax) ymax = yrot;
4349 if (yrot < ymin) ymin = yrot;
4350 }
4351
4352 Int_t yindx = (Int_t) (ymax/dy);
4353
4354 while (dy * yindx >= ymin) {
4355 ycur = dy * yindx--;
4356 nbi = 0;
4357 for (i=2; i<=nn+1; i++) {
4358 i2 = i;
4359 i1 = i-1;
4360 if (i == nn+1) i2=1;
4361 x1 = wndc*ratiox*(xx[i1-1]-rwxmin);
4362 y1 = hndc*ratioy*(yy[i1-1]-rwymin);
4363 x2 = wndc*ratiox*(xx[i2-1]-rwxmin);
4364 y2 = hndc*ratioy*(yy[i2-1]-rwymin);
4365 xt1 = cosa*x1-sina*y1;
4366 yt1 = sina*x1+cosa*y1;
4367 xt2 = cosa*x2-sina*y2;
4368 yt2 = sina*x2+cosa*y2;
4369
4370 // Line segment parallel to oy
4371 if (xt1 == xt2) {
4372 if (yt1 < yt2) {
4373 yi = yt1;
4374 yip = yt2;
4375 } else {
4376 yi = yt2;
4377 yip = yt1;
4378 }
4379 if ((yi <= ycur) && (ycur < yip)) {
4380 nbi++;
4381 if (nbi >= maxnbi) return;
4382 xli[nbi-1] = xt1;
4383 }
4384 continue;
4385 }
4386
4387 // Line segment parallel to ox
4388 if (yt1 == yt2) {
4389 if (yt1 == ycur) {
4390 nbi++;
4391 if (nbi >= maxnbi) return;
4392 xli[nbi-1] = xt1;
4393 nbi++;
4394 if (nbi >= maxnbi) return;
4395 xli[nbi-1] = xt2;
4396 }
4397 continue;
4398 }
4399
4400 // Other line segment
4401 a = (yt1-yt2)/(xt1-xt2);
4402 b = (yt2*xt1-xt2*yt1)/(xt1-xt2);
4403 if (xt1 < xt2) {
4404 xi = xt1;
4405 xip = xt2;
4406 } else {
4407 xi = xt2;
4408 xip = xt1;
4409 }
4410 xin = (ycur-b)/a;
4411 if ((xi <= xin) && (xin < xip) &&
4412 (TMath::Min(yt1,yt2) <= ycur) &&
4413 (ycur < TMath::Max(yt1,yt2))) {
4414 nbi++;
4415 if (nbi >= maxnbi) return;
4416 xli[nbi-1] = xin;
4417 }
4418 }
4419
4420 // Sorting of the x coordinates intersections
4421 inv = 0;
4422 m = nbi-1;
4423L30:
4424 for (i=1; i<=m; i++) {
4425 if (xli[i] < xli[i-1]) {
4426 inv++;
4427 ll = xli[i-1];
4428 xli[i-1] = xli[i];
4429 xli[i] = ll;
4430 }
4431 }
4432 m--;
4433 if (inv == 0) goto L50;
4434 inv = 0;
4435 goto L30;
4436
4437 // Draw the hatches
4438L50:
4439 if (nbi%2 != 0) continue;
4440
4441 for (i=1; i<=nbi; i=i+2) {
4442 // Rotate back the hatches
4443 xlh[0] = cosb*xli[i-1]-sinb*ycur;
4444 ylh[0] = sinb*xli[i-1]+cosb*ycur;
4445 xlh[1] = cosb*xli[i] -sinb*ycur;
4446 ylh[1] = sinb*xli[i] +cosb*ycur;
4447 // Convert hatches' positions from true NDC to WC
4448 xlh[0] = (xlh[0]/wndc)*(rwxmax-rwxmin)+rwxmin;
4449 ylh[0] = (ylh[0]/hndc)*(rwymax-rwymin)+rwymin;
4450 xlh[1] = (xlh[1]/wndc)*(rwxmax-rwxmin)+rwxmin;
4451 ylh[1] = (ylh[1]/hndc)*(rwymax-rwymin)+rwymin;
4452 gPad->PaintLine(xlh[0], ylh[0], xlh[1], ylh[1]);
4453 }
4454 }
4455}
4456
4457////////////////////////////////////////////////////////////////////////////////
4458/// Paint line in CurrentPad World coordinates.
4459
4461{
4462 Double_t x[2] = {x1, x2}, y[2] = {y1, y2};
4463
4464 //If line is totally clipped, return
4466 if (Clip(x,y,fUxmin,fUymin,fUxmax,fUymax) == 2) return;
4467 } else {
4468 if (Clip(x,y,fX1,fY1,fX2,fY2) == 2) return;
4469 }
4470
4471 if (!gPad->IsBatch() && GetPainter())
4472 GetPainter()->DrawLine(x[0], y[0], x[1], y[1]);
4473
4474 if (gVirtualPS)
4475 gVirtualPS->DrawPS(2, x, y);
4476
4477 Modified();
4478}
4479
4480////////////////////////////////////////////////////////////////////////////////
4481/// Paint line in normalized coordinates.
4482
4484{
4485 static Double_t xw[2], yw[2];
4486 if (!gPad->IsBatch() && GetPainter())
4488
4489 if (gVirtualPS) {
4490 xw[0] = fX1 + u1*(fX2 - fX1);
4491 xw[1] = fX1 + u2*(fX2 - fX1);
4492 yw[0] = fY1 + v1*(fY2 - fY1);
4493 yw[1] = fY1 + v2*(fY2 - fY1);
4494 gVirtualPS->DrawPS(2, xw, yw);
4495 }
4496
4497 Modified();
4498}
4499
4500////////////////////////////////////////////////////////////////////////////////
4501/// Paint 3-D line in the CurrentPad.
4502
4504{
4505 if (!fView) return;
4506
4507 // convert from 3-D to 2-D pad coordinate system
4508 Double_t xpad[6];
4509 Double_t temp[3];
4510 Int_t i;
4511 for (i=0;i<3;i++) temp[i] = p1[i];
4512 fView->WCtoNDC(temp, &xpad[0]);
4513 for (i=0;i<3;i++) temp[i] = p2[i];
4514 fView->WCtoNDC(temp, &xpad[3]);
4515 PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
4516}
4517
4518////////////////////////////////////////////////////////////////////////////////
4519/// Paint 3-D line in the CurrentPad.
4520
4522{
4523 if (!fView) return;
4524
4525 // convert from 3-D to 2-D pad coordinate system
4526 Double_t xpad[6];
4527 Double_t temp[3];
4528 Int_t i;
4529 for (i=0;i<3;i++) temp[i] = p1[i];
4530 fView->WCtoNDC(temp, &xpad[0]);
4531 for (i=0;i<3;i++) temp[i] = p2[i];
4532 fView->WCtoNDC(temp, &xpad[3]);
4533 PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
4534}
4535
4536////////////////////////////////////////////////////////////////////////////////
4537/// Paint 3-D marker in the CurrentPad.
4538
4540{
4541 if (!fView) return;
4542
4543 Double_t rmin[3], rmax[3];
4545
4546 // convert from 3-D to 2-D pad coordinate system
4547 Double_t xpad[3];
4548 Double_t temp[3];
4549 temp[0] = x;
4550 temp[1] = y;
4551 temp[2] = z;
4552 if (x<rmin[0] || x>rmax[0]) return;
4553 if (y<rmin[1] || y>rmax[1]) return;
4554 if (z<rmin[2] || z>rmax[2]) return;
4555 fView->WCtoNDC(temp, &xpad[0]);
4556 PaintPolyMarker(1, &xpad[0], &xpad[1]);
4557}
4558
4559////////////////////////////////////////////////////////////////////////////////
4560/// Paint polyline in CurrentPad World coordinates.
4561
4563{
4564 if (n < 2) return;
4565
4569 } else {
4570 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4571 }
4572 Int_t i, i1=-1,np=1;
4573 for (i=0; i<n-1; i++) {
4574 Double_t x1=x[i];
4575 Double_t y1=y[i];
4576 Double_t x2=x[i+1];
4577 Double_t y2=y[i+1];
4578 Int_t iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4579 if (iclip == 2) {
4580 i1 = -1;
4581 continue;
4582 }
4583 np++;
4584 if (i1 < 0) i1 = i;
4585 if (iclip == 0 && i < n-2) continue;
4586 if (!gPad->IsBatch() && GetPainter())
4587 GetPainter()->DrawPolyLine(np, &x[i1], &y[i1]);
4588 if (gVirtualPS) {
4589 gVirtualPS->DrawPS(np, &x[i1], &y[i1]);
4590 }
4591 if (iclip) {
4592 x[i] = x1;
4593 y[i] = y1;
4594 x[i+1] = x2;
4595 y[i+1] = y2;
4596 }
4597 i1 = -1;
4598 np = 1;
4599 }
4600
4601 Modified();
4602}
4603
4604////////////////////////////////////////////////////////////////////////////////
4605/// Paint polyline in CurrentPad World coordinates.
4606///
4607/// If option[0] == 'C' no clipping
4608
4610{
4611 if (n < 2) return;
4612
4617 } else {
4618 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4619 if (option && (option[0] == 'C')) mustClip = kFALSE;
4620 }
4621
4622 Int_t i, i1=-1, np=1, iclip=0;
4623
4624 for (i=0; i < n-1; i++) {
4625 Double_t x1=x[i];
4626 Double_t y1=y[i];
4627 Double_t x2=x[i+1];
4628 Double_t y2=y[i+1];
4629 if (mustClip) {
4630 iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4631 if (iclip == 2) {
4632 i1 = -1;
4633 continue;
4634 }
4635 }
4636 np++;
4637 if (i1 < 0) i1 = i;
4638 if (iclip == 0 && i < n-2) continue;
4639 if (!gPad->IsBatch() && GetPainter())
4640 GetPainter()->DrawPolyLine(np, &x[i1], &y[i1]);
4641 if (gVirtualPS) {
4642 gVirtualPS->DrawPS(np, &x[i1], &y[i1]);
4643 }
4644 if (iclip) {
4645 x[i] = x1;
4646 y[i] = y1;
4647 x[i+1] = x2;
4648 y[i+1] = y2;
4649 }
4650 i1 = -1;
4651 np = 1;
4652 }
4653
4654 Modified();
4655}
4656
4657////////////////////////////////////////////////////////////////////////////////
4658/// Paint polyline in CurrentPad NDC coordinates.
4659
4661{
4662 if (n <=0) return;
4663
4664 if (!gPad->IsBatch() && GetPainter())
4666
4667 if (gVirtualPS) {
4668 std::vector<Double_t> xw(n), yw(n);
4669 for (Int_t i=0; i<n; i++) {
4670 xw[i] = fX1 + x[i]*(fX2 - fX1);
4671 yw[i] = fY1 + y[i]*(fY2 - fY1);
4672 }
4673 gVirtualPS->DrawPS(n, xw.data(), yw.data());
4674 }
4675 Modified();
4676}
4677
4678////////////////////////////////////////////////////////////////////////////////
4679/// Paint 3-D polyline in the CurrentPad.
4680
4682{
4683 if (!fView) return;
4684
4685 // Loop on each individual line
4686 for (Int_t i = 1; i < n; i++)
4687 PaintLine3D(&p[3*i-3], &p[3*i]);
4688
4689 Modified();
4690}
4691
4692////////////////////////////////////////////////////////////////////////////////
4693/// Paint polymarker in CurrentPad World coordinates.
4694
4696{
4697 Int_t n = TMath::Abs(nn);
4699 if (nn > 0 || TestBit(TGraph::kClipFrame)) {
4701 } else {
4702 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4703 }
4704 Int_t i,i1=-1,np=0;
4705 for (i=0; i<n; i++) {
4706 if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
4707 np++;
4708 if (i1 < 0) i1 = i;
4709 if (i < n-1) continue;
4710 }
4711 if (np == 0) continue;
4712 if (!gPad->IsBatch() && GetPainter())
4713 GetPainter()->DrawPolyMarker(np, &x[i1], &y[i1]);
4714 if (gVirtualPS) {
4716 }
4717 i1 = -1;
4718 np = 0;
4719 }
4720 Modified();
4721}
4722
4723////////////////////////////////////////////////////////////////////////////////
4724/// Paint polymarker in CurrentPad World coordinates.
4725
4727{
4728 Int_t n = TMath::Abs(nn);
4730 if (nn > 0 || TestBit(TGraph::kClipFrame)) {
4732 } else {
4733 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4734 }
4735 Int_t i,i1=-1,np=0;
4736 for (i=0; i<n; i++) {
4737 if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
4738 np++;
4739 if (i1 < 0) i1 = i;
4740 if (i < n-1) continue;
4741 }
4742 if (np == 0) continue;
4743 if (!gPad->IsBatch() && GetPainter())
4744 GetPainter()->DrawPolyMarker(np, &x[i1], &y[i1]);
4745 if (gVirtualPS) {
4747 }
4748 i1 = -1;
4749 np = 0;
4750 }
4751 Modified();
4752}
4753
4754////////////////////////////////////////////////////////////////////////////////
4755/// Paint N individual segments
4756/// Provided arrays should have 2*n elements
4757/// IMPORTANT! Provided arrays can be modified after function call!
4758
4760{
4761 if (n < 1)
4762 return;
4763
4768 } else {
4769 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4770 if (option && *option == 'C') mustClip = kFALSE;
4771 }
4772
4773 if (!mustClip)
4774 isAny = kTRUE;
4775 else {
4776 for (Int_t i = 0; i < 2*n; i+=2) {
4777 Int_t iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4778 if (iclip == 2)
4779 x[i] = y[i] = x[i+1] = y[i+1] = 0;
4780 else
4781 isAny = kTRUE;
4782 }
4783 }
4784
4785 if (isAny && !gPad->IsBatch() && GetPainter())
4786 GetPainter()->DrawSegments(n, x, y);
4787
4788 if (isAny && gVirtualPS)
4790
4791 Modified();
4792}
4793
4794
4795////////////////////////////////////////////////////////////////////////////////
4796/// Paint N individual segments in NDC coordinates
4797/// Provided arrays should have 2*n elements
4798/// IMPORTANT! Provided arrays can be modified after function call!
4799
4801{
4802 if (!gPad->IsBatch() && GetPainter())
4804
4805 if (gVirtualPS) {
4806 // recalculate values into normal coordiantes
4807 for (Int_t i = 0; i < 2*n; i++) {
4808 u[i] = fX1 + u[i]*(fX2 - fX1);
4809 v[i] = fY1 + v[i]*(fY2 - fY1);
4810 }
4812 }
4813
4814 Modified();
4815}
4816
4817
4818////////////////////////////////////////////////////////////////////////////////
4819/// Paint text in CurrentPad World coordinates.
4820
4822{
4823 Modified();
4824
4825 if (!gPad->IsBatch() && GetPainter())
4827
4828 if (gVirtualPS) gVirtualPS->Text(x, y, text);
4829}
4830
4831////////////////////////////////////////////////////////////////////////////////
4832/// Paint text in CurrentPad World coordinates.
4833
4834void TPad::PaintText(Double_t x, Double_t y, const wchar_t *text)
4835{
4836 Modified();
4837
4838 if (!gPad->IsBatch() && GetPainter())
4840
4841 if (gVirtualPS) gVirtualPS->Text(x, y, text);
4842}
4843
4844////////////////////////////////////////////////////////////////////////////////
4845/// Paint text with URL in CurrentPad World coordinates.
4846
4847void TPad::PaintTextUrl(Double_t x, Double_t y, const char *text, const char *url)
4848{
4849 Modified();
4850
4851 if (!gPad->IsBatch() && GetPainter())
4853
4855}
4856
4857
4858////////////////////////////////////////////////////////////////////////////////
4859/// Paint text in CurrentPad NDC coordinates.
4860
4862{
4863 Modified();
4864
4865 if (!gPad->IsBatch() && GetPainter())
4867
4868 if (gVirtualPS) {
4869 Double_t x = fX1 + u*(fX2 - fX1);
4870 Double_t y = fY1 + v*(fY2 - fY1);
4871 gVirtualPS->Text(x, y, text);
4872 }
4873}
4874
4875////////////////////////////////////////////////////////////////////////////////
4876/// Paint text in CurrentPad NDC coordinates.
4877
4879{
4880 Modified();
4881
4882 if (!gPad->IsBatch() && GetPainter())
4884
4885 if (gVirtualPS) {
4886 Double_t x = fX1 + u*(fX2 - fX1);
4887 Double_t y = fY1 + v*(fY2 - fY1);
4888 gVirtualPS->Text(x, y, text);
4889 }
4890}
4891
4892////////////////////////////////////////////////////////////////////////////////
4893/// Search for an object at pixel position px,py.
4894///
4895/// Check if point is in this pad.
4896///
4897/// If yes, check if it is in one of the sub-pads
4898///
4899/// If found in the pad, compute closest distance of approach
4900/// to each primitive.
4901///
4902/// If one distance of approach is found to be within the limit Distancemaximum
4903/// the corresponding primitive is selected and the routine returns.
4904
4906{
4907 //the two following statements are necessary under NT (multithreaded)
4908 //when a TCanvas object is being created and a thread calling TPad::Pick
4909 //before the TPad constructor has completed in the other thread
4910 if (!gPad) return nullptr; //Andy Haas
4911 if (!GetListOfPrimitives()) return nullptr; //Andy Haas
4912
4913 Int_t dist;
4914 // Search if point is in pad itself
4915 Double_t x = AbsPixeltoX(px);
4916 Double_t y = AbsPixeltoY(py);
4917 if (this != gPad->GetCanvas()) {
4918 if (!((x >= fX1 && x <= fX2) && (y >= fY1 && y <= fY2))) return nullptr;
4919 }
4920
4921 // search for a primitive in this pad or its sub-pads
4922 static TObjOptLink dummyLink(nullptr,""); //place holder for when no link available
4923
4924 TContext ctxt(this, kFALSE); // since no drawing will be done, don't use cd() for efficiency reasons
4925
4926 TPad *pick = nullptr;
4927 TPad *picked = this;
4928 pickobj = nullptr;
4930 dummyLink.SetObject(this);
4931 pickobj = &dummyLink;
4932 }
4933
4934 // Loop backwards over the list of primitives. The first non-pad primitive
4935 // found is the selected one. However, we have to keep going down the
4936 // list to see if there is maybe a pad overlaying the primitive. In that
4937 // case look into the pad for a possible primitive. Once a pad has been
4938 // found we can terminate the loop.
4939 Bool_t gotPrim = kFALSE; // true if found a non pad primitive
4941
4942 //We can have 3d stuff in pad. If canvas prefers to draw
4943 //such stuff with OpenGL, the selection of 3d objects is
4944 //a gl viewer business so, in first cycle we do not
4945 //call DistancetoPrimitive for TAtt3D descendants.
4946 //In case of gl we first try to select 2d object first.
4947
4948 while (lnk) {
4949 TObject *obj = lnk->GetObject();
4950
4951 //If canvas prefers GL, all 3d objects must be drawn/selected by
4952 //gl viewer
4953 if (obj->InheritsFrom(TAtt3D::Class()) && fEmbeddedGL) {
4954 lnk = lnk->Prev();
4955 continue;
4956 }
4957
4958 fPadPointer = obj;
4959 if (obj->InheritsFrom(TPad::Class())) {
4960 pick = ((TPad*)obj)->Pick(px, py, pickobj);
4961 if (pick) {
4962 picked = pick;
4963 break;
4964 }
4965 } else if (!gROOT->GetEditorMode()) {
4966 if (!gotPrim) {
4967 if (!obj->TestBit(kCannotPick)) {
4968 dist = obj->DistancetoPrimitive(px, py);
4969 if (dist < fgMaxPickDistance) {
4970 pickobj = lnk;
4971 gotPrim = kTRUE;
4972 if (dist == 0) break;
4973 }
4974 }
4975 }
4976 }
4977
4978 lnk = lnk->Prev();
4979 }
4980
4981 //if no primitive found, check if we have a TView
4982 //if yes, return the view except if you are in the lower or upper X range
4983 //of the pad.
4984 //In case canvas prefers gl, fView existence
4985 //automatically means viewer3d existence. (?)
4986
4987 if (fView && !gotPrim) {
4988 Double_t dx = 0.05*(fUxmax-fUxmin);
4989 if ((x > fUxmin + dx) && (x < fUxmax-dx)) {
4990
4991 if (fEmbeddedGL) {
4992 //No 2d stuff was selected, but we have gl-viewer. Let it select an object in
4993 //scene (or select itself). In any case it'll internally call
4994 //gPad->SetSelected(ptr) as, for example, hist painter does.
4995 py -= Int_t((1 - GetHNDC() - GetYlowNDC()) * GetWh());
4996 px -= Int_t(GetXlowNDC() * GetWw());
4998 }
4999 else
5000 dummyLink.SetObject(fView);
5001 }
5002 }
5003
5004 if (picked->InheritsFrom(TButton::Class())) {
5006 if (!button->IsEditable()) pickobj = nullptr;
5007 }
5008
5009 if (TestBit(kCannotPick)) {
5010
5011 if (picked == this) {
5012 // cannot pick pad itself!
5013 picked = nullptr;
5014 }
5015
5016 }
5017
5018 return picked;
5019}
5020
5021////////////////////////////////////////////////////////////////////////////////
5022/// Pop pad to the top of the stack.
5023
5025{
5027 return;
5028 if (!fPrimitives)
5029 fPrimitives = new TList;
5030 if (this == fMother->GetListOfPrimitives()->Last())
5031 return;
5032
5034 while (auto obj = next())
5035 if (obj == this) {
5036 TString opt = next.GetOption();
5037 fMother->Remove(this, kFALSE); // do not issue modified
5038 fMother->Add(this, opt.Data());
5039 return;
5040 }
5041}
5042
5043////////////////////////////////////////////////////////////////////////////////
5044/// This method is equivalent to `SaveAs("filename")`. See TPad::SaveAs for details.
5045
5046void TPad::Print(const char *filename) const
5047{
5048 ((TPad*)this)->SaveAs(filename);
5049}
5050
5051////////////////////////////////////////////////////////////////////////////////
5052/// Auxiliary function. Returns kTRUE if list contains an object inherited
5053/// from TImage
5054
5056{
5057 TIter next(li);
5058
5059 while (auto obj = next()) {
5060 if (obj->InheritsFrom(TImage::Class())) {
5061 return kTRUE;
5062 } else if (obj->InheritsFrom(TPad::Class())) {
5063 if (ContainsTImage(((TPad*)obj)->GetListOfPrimitives())) {
5064 return kTRUE;
5065 }
5066 }
5067 }
5068 return kFALSE;
5069}
5070
5071////////////////////////////////////////////////////////////////////////////////
5072/// Save Canvas contents in a file in one of various formats.
5073///
5074/// \anchor TPadPrint
5075/// option can be:
5076///
5077/// - `ps`: a Postscript file is produced (default). [See special cases](\ref TPadPrintPS).
5078/// - `Portrait`: Postscript file is produced (Portrait)
5079/// - `Landscape`: Postscript file is produced (Landscape)
5080/// - `eps`: an Encapsulated Postscript file is produced
5081/// - `Preview`: an [Encapsulated Postscript file with preview](\ref TPadPrintPreview) is produced.
5082/// - `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.
5083/// - `Title:`: The character string after `Title:` becomes a table
5084/// of content entry (for PDF files).
5085/// - `EmbedFonts`: a [PDF file with embedded fonts](\ref TPadPrintEmbedFonts) is generated.
5086/// - `svg`: a SVG file is produced
5087/// - `tex`: a TeX file is produced
5088/// - `Standalone`: a [standalone TeX file](\ref TPadPrintStandalone) is produced.
5089/// - `gif`: a GIF file is produced
5090/// - `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
5091/// - `xpm`: a XPM file is produced
5092/// - `png`: a PNG file is produced
5093/// - `jpg`: a JPEG file is produced. NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
5094/// - `tiff`: a TIFF file is produced
5095/// - `cxx`: a C++ macro file is produced
5096/// - `xml`: a XML file
5097/// - `json`: a JSON file
5098/// - `root`: a ROOT binary file
5099///
5100/// `filename` = 0 - filename is defined by `GetName` and its
5101/// extension is defined with the option
5102///
5103/// When Postscript output is selected (`ps`, `eps`), the canvas is saved
5104/// to `filename.ps` or `filename.eps`. The aspect ratio of the canvas is preserved
5105/// on the Postscript file. When the "ps" option is selected, the Postscript
5106/// page will be landscape format if the canvas is in landscape format, otherwise
5107/// portrait format is selected.
5108///
5109/// The physical size of the Postscript page is the one selected in the
5110/// current style. This size can be modified via TStyle::SetPaperSize.
5111///
5112/// Examples:
5113/// ~~~ {.cpp}
5114/// gStyle->SetPaperSize(TStyle::kA4); //default
5115/// gStyle->SetPaperSize(TStyle::kUSLetter);
5116/// ~~~
5117/// where TStyle::kA4 and TStyle::kUSLetter are defined in the enum
5118/// EPaperSize in TStyle.h
5119///
5120/// An alternative is to call:
5121/// ~~~ {.cpp}
5122/// gStyle->SetPaperSize(20,26); same as kA4
5123/// or gStyle->SetPaperSize(20,24); same as kUSLetter
5124/// ~~~
5125/// The above numbers take into account some margins and are in centimeters.
5126///
5127/// \anchor TPadPrintPreview
5128/// ### The "Preview" option
5129///
5130/// The "Preview" option allows to generate a preview (in the TIFF format) within
5131/// the Encapsulated Postscript file. This preview can be used by programs like
5132/// MSWord to visualize the picture on screen. The "Preview" option relies on the
5133/// ["epstool" command](http://www.cs.wisc.edu/~ghost/gsview/epstool.htm).
5134///
5135/// Example:
5136/// ~~~ {.cpp}
5137/// canvas->Print("example.eps","Preview");
5138/// ~~~
5139///
5140/// \anchor TPadPrintEmbedFonts
5141/// ### The "EmbedFonts" option
5142///
5143/// The "EmbedFonts" option allows to embed the fonts used in a PDF file inside
5144/// that file. This option relies on the ["gs" command](https://ghostscript.com).
5145///
5146/// Example:
5147/// ~~~ {.cpp}
5148/// canvas->Print("example.pdf","EmbedFonts");
5149/// ~~~
5150///
5151/// \anchor TPadPrintStandalone
5152/// ### The "Standalone" option
5153/// The "Standalone" option allows to generate a TeX file ready to be processed by
5154/// tools like `pdflatex`.
5155///
5156/// Example:
5157/// ~~~ {.cpp}
5158/// canvas->Print("example.tex","Standalone");
5159/// ~~~
5160///
5161/// \anchor TPadPrintPS
5162/// ### Writing several canvases to the same Postscript or PDF file:
5163///
5164/// - if the Postscript or PDF file name finishes with "(", the file is not closed
5165/// - if the Postscript or PDF file name finishes with ")" and the file has been opened
5166/// with "(", the file is closed.
5167///
5168/// Example:
5169/// ~~~ {.cpp}
5170/// {
5171/// TCanvas c1("c1");
5172/// h1.Draw();
5173/// c1.Print("c1.ps("); //write canvas and keep the ps file open
5174/// h2.Draw();
5175/// c1.Print("c1.ps"); canvas is added to "c1.ps"
5176/// h3.Draw();
5177/// c1.Print("c1.ps)"); canvas is added to "c1.ps" and ps file is closed
5178/// }
5179/// ~~~
5180/// In the previous example replacing "ps" by "pdf" will create a multi-pages PDF file.
5181///
5182/// Note that the following sequence writes the canvas to "c1.ps" and closes the ps file.:
5183/// ~~~ {.cpp}
5184/// TCanvas c1("c1");
5185/// h1.Draw();
5186/// c1.Print("c1.ps");
5187/// ~~~
5188/// The `TCanvas::Print("file.ps(")` mechanism is very useful, but it can be
5189/// a little inconvenient to have the action of opening/closing a file
5190/// being atomic with printing a page. Particularly if pages are being
5191/// generated in some loop one needs to detect the special cases of first
5192/// and last page and then munge the argument to Print() accordingly.
5193///
5194/// The "[" and "]" can be used instead of "(" and ")" to open / close without
5195/// actual printing.
5196///
5197/// Example:
5198/// ~~~ {.cpp}
5199/// c1.Print("file.ps["); // No actual print, just open file.ps
5200/// for (int i=0; i<10; ++i) {
5201/// // fill canvas for context i
5202/// // ...
5203///
5204/// c1.Print("file.ps"); // actually print canvas to file
5205/// }// end loop
5206/// c1.Print("file.ps]"); // No actual print, just close.
5207/// ~~~
5208/// As before, the same macro is valid for PDF files.
5209///
5210/// It is possible to print a canvas into an animated GIF file by specifying the
5211/// file name as "myfile.gif+" or "myfile.gif+NN", where NN*10ms is delay
5212/// between the subimages' display. If NN is omitted the delay between
5213/// subimages is zero. Each picture is added in the animation thanks to a loop
5214/// similar to the following one:
5215/// ~~~ {.cpp}
5216/// for (int i=0; i<10; ++i) {
5217/// // fill canvas for context i
5218/// // ...
5219///
5220/// c1.Print("file.gif+5"); // print canvas to GIF file with 50ms delays
5221/// }// end loop
5222/// ~~~
5223/// The delay between each frame must be specified in each Print() statement.
5224/// If the file "myfile.gif" already exists, the new frame are appended at
5225/// the end of the file. To avoid this, delete it first with `gSystem->Unlink(myfile.gif);`
5226/// If you want the gif file to repeat or loop forever, check TASImage::WriteImage documentation
5227
5229{
5230 if (!GetCanvas())
5231 return;
5232
5234
5235 // "[" and "]" are special characters for ExpandPathName. When they are at the end
5236 // of the file name (see help) they must be removed before doing ExpandPathName.
5237 if (fs1.EndsWith("[")) {
5238 fs1.Replace((fs1.Length()-1),1," ");
5240 fs1.Replace((fs1.Length()-1),1,"[");
5241 } else if (fs1.EndsWith("]")) {
5242 fs1.Replace((fs1.Length()-1),1," ");
5244 fs1.Replace((fs1.Length()-1),1,"]");
5245 } else {
5247 }
5248
5249 // Set the default option as "Postscript" (Should be a data member of TPad)
5250 const char *opt_default = "ps";
5251
5252 TString opt = !option ? opt_default : option;
5254
5255 Bool_t title = kFALSE;
5256 if (strstr(opt,"Title:")) title = kTRUE;
5257
5258 if (!fs1.Length()) {
5259 psname = GetName();
5260 psname += opt;
5261 } else {
5262 psname = fs1;
5263 }
5264
5265 // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
5266 if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
5267 psname = GetName();
5268 psname.Append(fs1);
5269 psname.Prepend("/");
5270 psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
5271 }
5272
5273 // Save pad/canvas in alternative formats
5275 if (!title && strstr(opt, "gif+")) {
5277 image = kTRUE;
5278 } else if (!title && strstr(opt, "gif")) {
5280 image = kTRUE;
5281 } else if (!title && strstr(opt, "png")) {
5283 image = kTRUE;
5284 } else if (!title && strstr(opt, "jpg")) {
5286 image = kTRUE;
5287 } else if (!title && strstr(opt, "tiff")) {
5289 image = kTRUE;
5290 } else if (!title && strstr(opt, "xpm")) {
5292 image = kTRUE;
5293 } else if (!title && strstr(opt, "bmp")) {
5295 image = kTRUE;
5296 }
5297
5298 if (GetCanvas()->IsWeb() && GetPainter() &&
5299 (strstr(opt,"svg") || strstr(opt,"pdf") || (gtype == TImage::kJpeg) || (gtype == TImage::kPng))) {
5300 GetPainter()->SaveImage(this, psname.Data(), gtype);
5301 return;
5302 }
5303
5304 if (!GetCanvas()->IsBatch() && GetPainter())
5306
5307
5308 if (!gROOT->IsBatch() && image) {
5310 Int_t wid = (this == GetCanvas()) ? GetCanvas()->GetCanvasID() : GetPixmapID();
5311 Color_t hc = gPad->GetCanvas()->GetHighLightColor();
5312 gPad->GetCanvas()->SetHighLightColor(-1);
5313 gPad->Modified();
5314 gPad->Update();
5315 if (GetPainter()){
5317 GetPainter()->SaveImage(this, psname.Data(), gtype);
5318 }
5319 if (!gSystem->AccessPathName(psname.Data())) {
5320 Info("Print", "GIF file %s has been created", psname.Data());
5321 }
5322 gPad->GetCanvas()->SetHighLightColor(hc);
5323 return;
5324 }
5325 if (gtype != TImage::kUnknown) {
5326 Color_t hc = gPad->GetCanvas()->GetHighLightColor();
5327 gPad->GetCanvas()->SetHighLightColor(-1);
5328 gPad->Modified();
5329 gPad->Update();
5330 gVirtualX->Update(1);
5331 gSystem->Sleep(30); // synchronize
5332 if (GetPainter()) GetPainter()->SaveImage(this, psname, gtype);
5333 if (!gSystem->AccessPathName(psname)) {
5334 Info("Print", "file %s has been created", psname.Data());
5335 }
5336 gPad->GetCanvas()->SetHighLightColor(hc);
5337 } else {
5338 Warning("Print", "Unsupported image format %s", psname.Data());
5339 }
5340 return;
5341 }
5342
5343 //==============Save pad/canvas as a C++ script==============================
5344 if (!title && strstr(opt,"cxx")) {
5345 GetCanvas()->SaveSource(psname, "");
5346 return;
5347 }
5348
5349 //==============Save pad/canvas as a root file===============================
5350 if (!title && strstr(opt,"root")) {
5351 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5352 return;
5353 }
5354
5355 //==============Save pad/canvas as a XML file================================
5356 if (!title && strstr(opt,"xml")) {
5357 // Plugin XML driver
5358 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5359 return;
5360 }
5361
5362 //==============Save pad/canvas as a JSON file================================
5363 if (!title && strstr(opt,"json")) {
5364 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5365 return;
5366 }
5367
5368 //==============Save pad/canvas as a SVG file================================
5369 if (!title && strstr(opt,"svg")) {
5370 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5371
5373 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5374 noScreen = kTRUE;
5376 }
5377
5378 TContext ctxt(this, kTRUE);
5379
5380 if (!gVirtualPS) {
5381 // Plugin Postscript/SVG driver
5382 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "svg")) {
5383 if (h->LoadPlugin() == -1)
5384 return;
5385 h->ExecPlugin(0);
5386 }
5387 }
5388
5389 // Create a new SVG file
5390 if (gVirtualPS) {
5395 }
5396 Paint();
5397 if (noScreen)
5399
5401 Info("Print", "SVG file %s has been created", psname.Data());
5402
5403 delete gVirtualPS;
5404 gVirtualPS = nullptr;
5405
5406 return;
5407 }
5408
5409 //==============Save pad/canvas as a TeX file================================
5410 if (!title && (strstr(opt,"tex") || strstr(opt,"Standalone"))) {
5411 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5412
5414 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5415 noScreen = kTRUE;
5417 }
5418
5419 TContext ctxt(this, kTRUE);
5420
5421 if (!gVirtualPS) {
5422 // Plugin Postscript/SVG driver
5423 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "tex")) {
5424 if (h->LoadPlugin() == -1)
5425 return;
5426 h->ExecPlugin(0);
5427 }
5428 }
5429
5431 if (strstr(opt,"Standalone")) standalone = kTRUE;
5432
5433 // Create a new TeX file
5434 if (gVirtualPS) {
5436 if (standalone) gVirtualPS->SetTitle("Standalone");
5440 }
5441 Paint();
5443
5444 if (!gSystem->AccessPathName(psname)) {
5445 if (standalone) {
5446 Info("Print", "Standalone TeX file %s has been created", psname.Data());
5447 } else{
5448 Info("Print", "TeX file %s has been created", psname.Data());
5449 }
5450 }
5451
5452 delete gVirtualPS;
5453 gVirtualPS = nullptr;
5454
5455 return;
5456 }
5457
5458 //==============Save pad/canvas as a Postscript file=========================
5459
5460 // in case we read directly from a Root file and the canvas
5461 // is not on the screen, set batch mode
5462
5465 if (!image) {
5466 // The parenthesis mechanism is only valid for PS and PDF files.
5467 copen = psname.EndsWith("("); if (copen) psname[psname.Length()-1] = 0;
5468 cclose = psname.EndsWith(")"); if (cclose) psname[psname.Length()-1] = 0;
5469 copenb = psname.EndsWith("["); if (copenb) psname[psname.Length()-1] = 0;
5470 ccloseb = psname.EndsWith("]"); if (ccloseb) psname[psname.Length()-1] = 0;
5471 }
5472 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5474 if (copen || copenb) mustClose = kFALSE;
5475 if (cclose || ccloseb) mustClose = kTRUE;
5476
5478 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5479 noScreen = kTRUE;
5481 }
5482 Int_t pstype = 111;
5485 Double_t ratio = ycanvas/xcanvas;
5486 if (ratio < 1) pstype = 112;
5487 if (strstr(opt,"Portrait")) pstype = 111;
5488 if (strstr(opt,"Landscape")) pstype = 112;
5489 if (strstr(opt,"eps")) pstype = 113;
5490 if (strstr(opt,"Preview")) pstype = 113;
5491
5492 TContext ctxt(this, kTRUE);
5494
5495 if (!gVirtualPS || mustOpen) {
5496
5497 const char *pluginName = "ps"; // Plugin Postscript driver
5498 if (strstr(opt,"pdf") || title || strstr(opt,"EmbedFonts"))
5499 pluginName = "pdf";
5500 else if (image)
5501 pluginName = "image"; // Plugin TImageDump driver
5502
5503 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", pluginName)) {
5504 if (h->LoadPlugin() == -1)
5505 return;
5506 h->ExecPlugin(0);
5507 }
5508
5509 // Create a new Postscript, PDF or image file
5510 if (gVirtualPS)
5512 const Ssiz_t titlePos = opt.Index("Title:");
5513 if (titlePos != kNPOS) {
5514 if (gVirtualPS)
5515 gVirtualPS->SetTitle(opt.Data()+titlePos+6);
5516 opt.Replace(titlePos,opt.Length(),"pdf");
5517 }
5518 if (gVirtualPS)
5520 if (gVirtualPS)
5522 if (!copenb) {
5523 if (!strstr(opt,"pdf") || image) {
5525 }
5526 Paint();
5527 }
5529
5530 if (mustClose) {
5531 gROOT->GetListOfSpecials()->Remove(gVirtualPS);
5532 delete gVirtualPS;
5533 gVirtualPS = psave;
5534 } else {
5535 gROOT->GetListOfSpecials()->Add(gVirtualPS);
5536 gVirtualPS = nullptr;
5537 }
5538
5539 if (!gSystem->AccessPathName(psname)) {
5540 if (!copen) Info("Print", "%s file %s has been created", opt.Data(), psname.Data());
5541 else Info("Print", "%s file %s has been created using the current canvas", opt.Data(), psname.Data());
5542 }
5543 } else {
5544 // Append to existing Postscript, PDF or GIF file
5545 if (!ccloseb) {
5547 Paint();
5548 }
5549 const Ssiz_t titlePos = opt.Index("Title:");
5550 if (titlePos != kNPOS) {
5551 gVirtualPS->SetTitle(opt.Data()+titlePos+6);
5552 opt.Replace(titlePos,opt.Length(),"pdf");
5553 } else if (!ccloseb) {
5554 gVirtualPS->SetTitle("PDF");
5555 }
5556 if (mustClose) {
5557 if (cclose) Info("Print", "Current canvas added to %s file %s and file closed", opt.Data(), psname.Data());
5558 else Info("Print", "%s file %s has been closed", opt.Data(), psname.Data());
5559 gROOT->GetListOfSpecials()->Remove(gVirtualPS);
5560 delete gVirtualPS;
5561 gVirtualPS = nullptr;
5562 } else {
5563 Info("Print", "Current canvas added to %s file %s", opt.Data(), psname.Data());
5564 gVirtualPS = nullptr;
5565 }
5566 }
5567
5568 if (strstr(opt,"Preview"))
5569 gSystem->Exec(TString::Format("epstool --quiet -t6p %s %s", psname.Data(), psname.Data()).Data());
5570 if (strstr(opt,"EmbedFonts")) {
5571 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",
5572 psname.Data()).Data());
5573 gSystem->Rename("pdf_temp.pdf", psname.Data());
5574 }
5575
5576}
5577
5578////////////////////////////////////////////////////////////////////////////////
5579/// Set world coordinate system for the pad.
5580/// Emits signal "RangeChanged()", in the slot get the range
5581/// via GetRange().
5582
5584{
5585 if ((x1 >= x2) || (y1 >= y2)) {
5586 Error("Range", "illegal world coordinates range: x1=%f, y1=%f, x2=%f, y2=%f",x1,y1,x2,y2);
5587 return;
5588 }
5589
5590 fUxmin = x1;
5591 fUxmax = x2;
5592 fUymin = y1;
5593 fUymax = y2;
5594
5595 if (fX1 == x1 && fY1 == y1 && fX2 == x2 && fY2 == y2) return;
5596
5597 fX1 = x1;
5598 fY1 = y1;
5599 fX2 = x2;
5600 fY2 = y2;
5601
5602 // compute pad conversion coefficients
5603 ResizePad();
5604
5605 if (gPad == this && GetPainter())
5607
5608 // emit signal
5609 RangeChanged();
5610}
5611
5612////////////////////////////////////////////////////////////////////////////////
5613/// Set axis coordinate system for the pad.
5614/// The axis coordinate system is a subset of the world coordinate system
5615/// xmin,ymin is the origin of the current coordinate system,
5616/// xmax is the end of the X axis, ymax is the end of the Y axis.
5617/// By default a margin of 10 per cent is left on all sides of the pad
5618/// Emits signal "RangeAxisChanged()", in the slot get the axis range
5619/// via GetRangeAxis().
5620
5622{
5623 if ((xmin >= xmax) || (ymin >= ymax)) {
5624 Error("RangeAxis", "illegal axis coordinates range: xmin=%f, ymin=%f, xmax=%f, ymax=%f",
5625 xmin, ymin, xmax, ymax);
5626 return;
5627 }
5628
5629 fUxmin = xmin;
5630 fUymin = ymin;
5631 fUxmax = xmax;
5632 fUymax = ymax;
5633
5634 // emit signal
5636}
5637
5638////////////////////////////////////////////////////////////////////////////////
5639/// Recursively remove object from a pad and its sub-pads.
5640
5642{
5643 if (fCanvas) {
5644 if (obj == fCanvas->GetSelected()) fCanvas->SetSelected(nullptr);
5645 if (obj == fCanvas->GetClickSelected()) fCanvas->SetClickSelected(nullptr);
5646 }
5647 if (obj == fView) fView = nullptr;
5648 if (!fPrimitives) return;
5651 if (nold != fPrimitives->GetSize()) fModified = kTRUE;
5652}
5653
5654////////////////////////////////////////////////////////////////////////////////
5655/// Remove object from list of primitives
5656/// When \par modified set to kTRUE (default) pad will be marked as modified - if object really removed
5657/// Returns result of GetListOfPrimitives()->Remove(obj) or nullptr if list of primitives not exists
5658
5660{
5661 TObject *res = nullptr;
5662 if (fPrimitives)
5663 res = fPrimitives->Remove(obj);
5664 if (res && modified)
5665 Modified();
5666 return res;
5667}
5668
5669////////////////////////////////////////////////////////////////////////////////
5670/// Redraw the frame axis.
5671///
5672/// Redrawing axis may be necessary in case of superimposed histograms
5673/// when one or more histograms have a fill color.
5674///
5675/// Instead of calling this function, it may be more convenient
5676/// to call directly `h1->Draw("sameaxis")` where h1 is the pointer
5677/// to the first histogram drawn in the pad.
5678///
5679/// By default, if the pad has the options gridx or/and gridy activated,
5680/// the grid is not drawn by this function.
5681///
5682/// If option="g" is specified, this will force the drawing of the grid
5683/// on top of the picture
5684///
5685/// To redraw the axis tick marks do:
5686/// ~~~ {.cpp}
5687/// gPad->RedrawAxis();
5688/// ~~~
5689/// To redraw the axis grid do:
5690/// ~~~ {.cpp}
5691/// gPad->RedrawAxis("G");
5692/// ~~~
5693/// To redraw the axis tick marks and the axis grid do:
5694/// ~~~ {.cpp}
5695/// gPad->RedrawAxis();
5696/// gPad->RedrawAxis("G");
5697/// ~~~
5698///
5699/// If option="f" is specified, this will force the drawing of the frame
5700/// around the plot.
5701
5703{
5704 TString opt = option;
5705 opt.ToLower();
5706
5707 TContext ctxt(this, kTRUE);
5708
5709 TH1 *hobj = nullptr;
5710
5711 // Get the first histogram drawing the axis in the list of primitives
5712 if (!fPrimitives) fPrimitives = new TList;
5713 TIter next(fPrimitives);
5714 TObject *obj;
5715 while ((obj = next())) {
5716 if (obj->InheritsFrom(TH1::Class())) {
5717 hobj = (TH1*)obj;
5718 break;
5719 }
5720 if (obj->InheritsFrom(TMultiGraph::Class())) {
5721 TMultiGraph *mg = (TMultiGraph*)obj;
5722 if (mg) hobj = mg->GetHistogram();
5723 break;
5724 }
5725 if (obj->InheritsFrom(TGraph::Class())) {
5726 TGraph *g = (TGraph*)obj;
5727 if (g) hobj = g->GetHistogram();
5728 break;
5729 }
5730 if (obj->InheritsFrom(THStack::Class())) {
5731 THStack *hs = (THStack*)obj;
5732 if (hs) hobj = hs->GetHistogram();
5733 break;
5734 }
5735 }
5736
5737 if (hobj) {
5738 if (opt.Contains("g")) hobj->DrawCopy("sameaxig");
5739 else hobj->DrawCopy("sameaxis");
5740 }
5741
5742 if (opt.Contains("f")) {
5743 auto b = new TBox(gPad->GetUxmin(), gPad->GetUymin(),
5744 gPad->GetUxmax(), gPad->GetUymax());
5745 b->SetFillStyle(0);
5746 b->SetLineStyle(gPad->GetFrameLineStyle());
5747 b->SetLineWidth(gPad->GetFrameLineWidth());
5748 b->SetLineColor(gPad->GetFrameLineColor());
5749 b->Draw();
5750 }
5751}
5752
5753////////////////////////////////////////////////////////////////////////////////
5754/// Compute pad conversion coefficients.
5755///
5756/// ### Conversion from x to px
5757///
5758/// \f[\frac{x-xmin}{xrange} = \frac{px-pxlow}{pxrange}\f]
5759/// with:
5760/// \f[ xrange = xmax-xmin \f]
5761/// \f[ pxrange = pxmax-pxmin \f]
5762///
5763/// \f[
5764/// \Rightarrow px = \frac{pxrange(x-xmin)}{xrange} + pxlow = fXtoPixelk + fXtoPixel \times x
5765/// \f]
5766///
5767/// \f[
5768/// \Rightarrow fXtoPixelk = pxlow - pxrange \frac{xmin}{xrange}
5769/// \f]
5770/// \f[
5771/// fXtoPixel = \frac{pxrange}{xrange}
5772/// \f]
5773/// where:
5774/// \f[
5775/// pxlow = fAbsXlowNDC \times fCw
5776/// \f]
5777/// \f[
5778/// pxrange = fAbsWNDC \times fCw
5779/// \f]
5780///
5781/// ### Conversion from y to py
5782///
5783/// \f[\frac{y-ymin}{yrange} = \frac{py-pylow}{pyrange}\f]
5784/// with:
5785/// \f[ yrange = ymax-ymin \f]
5786/// \f[ pyrange = pymax-pymin \f]
5787///
5788/// \f[
5789/// \Rightarrow py = \frac{pyrange(y-xmin)}{yrange} + pylow = fYtoPixelk + fYtoPixel \times y
5790/// \f]
5791///
5792/// \f[
5793/// \Rightarrow fYtoPixelk = pylow - pyrange \frac{ymin}{yrange}
5794/// \f]
5795/// \f[
5796/// fYtoPixel = \frac{pyrange}{yrange}
5797/// \f]
5798/// where:
5799/// \f[
5800/// pylow = fAbsYlowNDC \times fCh
5801/// \f]
5802/// \f[
5803/// pyrange = fAbsHNDC \times fCh
5804/// \f]
5805///
5806/// ### Conversion from px to x
5807///
5808/// \f[
5809/// \Rightarrow x = \frac{xrange(px-pxlow)}{pxrange}+ xmin = fPixeltoXk + fPixeltoX \times px
5810/// \f]
5811///
5812/// \f[
5813/// \Rightarrow fPixeltoXk = xmin - pxlow \times\frac{xrange}{pxrange}
5814/// \f]
5815/// \f[
5816/// fPixeltoX = \frac{xrange}{pxrange}
5817/// \f]
5818///
5819/// ### Conversion from py to y
5820///
5821/// \f[
5822/// \Rightarrow y = \frac{yrange(py-pylow)}{pyrange}+ ymin = fPixeltoYk + fPixeltoY \times py
5823/// \f]
5824///
5825/// \f[
5826/// \Rightarrow fPixeltoYk = ymin - pylow \times\frac{yrange}{pyrange}
5827/// \f]
5828/// \f[
5829/// fPixeltoY = \frac{yrange}{pyrange}
5830/// \f]
5831///
5832/// ### Computation of the coefficients in case of LOG scales
5833///
5834/// #### Conversion from pixel coordinates to world coordinates
5835///
5836/// \f[
5837/// u = \frac{Log(x) - Log(xmin)}{Log(xmax) - Log(xmin)} = \frac{Log(x/xmin)}{Log(xmax/xmin)} = \frac{px - pxlow}{pxrange}
5838/// \f]
5839///
5840/// \f[ \Rightarrow Log(\frac{x}{xmin}) = u \times Log(\frac{xmax}{xmin}) \f]
5841/// \f[ x = xmin \times e^{(u \times Log(\frac{xmax}{xmin})} \f]
5842/// Let:
5843/// \f[ alfa = \frac{Log(\frac{xmax}{xmin})}{fAbsWNDC} \f]
5844///
5845/// \f[ x = xmin \times e^{(-alfa \times pxlow)} + e^{(alfa \times px)} \f]
5846/// \f[ x = fPixeltoXk \times e^{(fPixeltoX \times px)} \f]
5847/// \f[ ==> fPixeltoXk = xmin \times e^{(-alfa*pxlow)} \f]
5848/// \f[ fPixeltoX = alfa \f]
5849///
5850/// \f[
5851/// v = \frac{Log(y) - Log(ymin)}{Log(ymax) - Log(ymin)} = \frac{Log(y/ymin)}{Log(ymax/ymin)} = \frac{py - pylow}{pyrange}
5852/// \f]
5853/// Let:
5854/// \f[ beta = Log(\frac{ymax}{ymin}) \f]
5855/// \f[ Log(\frac{y}{ymin}) = beta \times pylow - beta \times py \f]
5856/// \f[ \frac{y}{ymin} = e^{(beta \times pylow - beta \times py)} \f]
5857/// \f[ y = ymin \times e^{(beta \times pylow)} \times e^{(-beta \times py)}\f]
5858/// \f[ \Rightarrow y = fPixeltoYk \times e^{(fPixeltoY \times py)} \f]
5859/// \f[ fPixeltoYk = ymin \times e^{(beta \times pylow)} \f]
5860/// \f[ fPixeltoY = -beta \f]
5861///
5862/// #### Conversion from World coordinates to pixel coordinates
5863///
5864/// \f[ px = pxlow + u*pxrange \f]
5865/// \f[ = pxlow + Log(x/xmin)/alfa \f]
5866/// \f[ = pxlow -Log(xmin)/alfa + Log(x)/alfa \f]
5867/// \f[ = fXtoPixelk + fXtoPixel*Log(x) \f]
5868/// \f[ \Rightarrow fXtoPixelk = pxlow -Log(xmin)/alfa \f]
5869/// \f[ \Rightarrow fXtoPixel = 1/alfa \f]
5870///
5871/// \f[ py = pylow - Log(y/ymin)/beta \f]
5872/// \f[ = fYtoPixelk + fYtoPixel*Log(y) \f]
5873/// \f[ \Rightarrow fYtoPixelk = pylow - Log(ymin)/beta \f]
5874/// \f[ fYtoPixel = 1/beta \f]
5875
5877{
5878
5879 if (!gPad) {
5880 Error("ResizePad", "Cannot resize pad. No current pad available.");
5881 return;
5882 }
5883 if (gPad->GetWw()==0.0||gPad->GetWh()==0.0) {
5884 Warning("ResizePad", "gPad has at least one zero dimension.");
5885 return;
5886 }
5887 if (fX1==fX2||fY1==fY2) {
5888 Warning("ResizePad", "The pad has at least one zero dimension.");
5889 return;
5890 }
5891 // Recompute subpad positions in case pad has been moved/resized
5892 TPad *parent = fMother;
5893 if (this == gPad->GetCanvas()) {
5896 fAbsWNDC = fWNDC;
5897 fAbsHNDC = fHNDC;
5898 }
5899 else {
5900 if (parent->GetAbsHNDC()==0.0||parent->GetAbsWNDC()==0.0||fHNDC==0.0||fWNDC==0.0) {
5901 Warning("ResizePad", "The parent pad has at least one zero dimension.");
5902 return;
5903 }
5904 fAbsXlowNDC = fXlowNDC*parent->GetAbsWNDC() + parent->GetAbsXlowNDC();
5905 fAbsYlowNDC = fYlowNDC*parent->GetAbsHNDC() + parent->GetAbsYlowNDC();
5906 fAbsWNDC = fWNDC*parent->GetAbsWNDC();
5907 fAbsHNDC = fHNDC*parent->GetAbsHNDC();
5908 }
5909
5910 Double_t ww = (Double_t)gPad->GetWw();
5911 Double_t wh = (Double_t)gPad->GetWh();
5916
5917 // Linear X axis
5918 Double_t rounding = 0.; // was used before to adjust somehow wrong int trunctation by coordiantes transformation
5919 Double_t xrange = fX2 - fX1;
5920 fXtoAbsPixelk = rounding + pxlow - pxrange*fX1/xrange; //origin at left
5924 fPixeltoXk = fX1;
5926 // Linear Y axis
5927 Double_t yrange = fY2 - fY1;
5928 fYtoAbsPixelk = rounding + pylow - pyrange*fY1/yrange; //origin at top
5932 fPixeltoYk = fY1;
5934
5935 // Coefficients to convert from pad NDC coordinates to pixel coordinates
5936
5943
5944 // Coefficients to convert from canvas pixels to pad world coordinates
5945
5946 // Resize all sub-pads
5947 TObject *obj;
5948 if (!fPrimitives) fPrimitives = new TList;
5949 TIter next(GetListOfPrimitives());
5950 while ((obj = next())) {
5951 if (obj->InheritsFrom(TPad::Class()))
5952 ((TPad*)obj)->ResizePad(option);
5953 }
5954
5955 // Reset all current sizes
5956 if (gPad->IsBatch())
5957 fPixmapID = 0;
5958 else {
5959 if (GetPainter()){
5960 GetPainter()->SetLineWidth(-1);
5961 GetPainter()->SetTextSize(-1);
5962 }
5963 // create or re-create off-screen pixmap
5964 if (fPixmapID) {
5965 int w = TMath::Abs(XtoPixel(fX2) - XtoPixel(fX1));
5966 int h = TMath::Abs(YtoPixel(fY2) - YtoPixel(fY1));
5967 //protection in case of wrong pad parameters.
5968 //without this protection, the OpenPixmap or ResizePixmap crashes with
5969 //the message "Error in <RootX11ErrorHandler>: BadValue (integer parameter out of range for operation)"
5970 //resulting in a frozen xterm
5971 if ( !(TMath::Finite(fX1)) || !(TMath::Finite(fX2))
5972 || !(TMath::Finite(fY1)) || !(TMath::Finite(fY2))
5973 || (TMath::IsNaN(fX1)) || (TMath::IsNaN(fX2))
5974 || (TMath::IsNaN(fY1)) || (TMath::IsNaN(fY2)))
5975 Warning("ResizePad", "Inf/NaN propagated to the pad. Check drawn objects.");
5976 if (w <= 0 || w > 10000) {
5977 Warning("ResizePad", "%s width changed from %d to %d\n",GetName(),w,10);
5978 w = 10;
5979 }
5980 if (h <= 0 || h > 10000) {
5981 Warning("ResizePad", "%s height changed from %d to %d\n",GetName(),h,10);
5982 h = 10;
5983 }
5984 if (fPixmapID == -1) { // this case is handled via the ctor
5986 } else {
5987 if (gVirtualX) {
5988 if (gVirtualX->ResizePixmap(fPixmapID, w, h)) {
5989 Resized();
5990 Modified(kTRUE);
5991 }
5992 }
5993 }
5994 }
5995 }
5996 if (fView) {
5997 if (gPad == this) {
5998 fView->ResizePad();
5999 } else {
6000 TContext ctxt(this, kTRUE);
6001 fView->ResizePad();
6002 }
6003 }
6004}
6005
6006////////////////////////////////////////////////////////////////////////////////
6007/// Save the pad content in a file.
6008///
6009/// The file's format used to save the pad is determined by the `filename` extension:
6010///
6011/// - if `filename` is empty, the file produced is `padname.ps`
6012/// - if `filename` starts with a dot, the padname is added in front
6013/// - if `filename` ends with `.ps`, a Postscript file is produced
6014/// - if `filename` ends with `.eps`, an Encapsulated Postscript file is produced
6015/// - 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.
6016/// - if `filename` ends with `.svg`, a SVG file is produced
6017/// - if `filename` ends with `.tex`, a TeX file is produced
6018/// - if `filename` ends with `.gif`, a GIF file is produced
6019/// - 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
6020/// - if `filename` ends with `.xpm`, a XPM file is produced
6021/// - if `filename` ends with `.png`, a PNG file is produced
6022/// - if `filename` ends with `.bmp`, a BMP file is produced
6023/// - if `filename` ends with `.jpg` or `.jpeg` a JPEG file is produced NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
6024/// - if `filename` ends with `.tiff`, a TIFF file is produced
6025/// - if `filename` ends with `.C`, `.cxx`,`.cpp` or `.cc`, a C++ macro file is produced
6026/// - if `filename` ends with `.root`, a Root file is produced
6027/// - if `filename` ends with `.xml`, a XML file is produced
6028/// - if `filename` ends with `.json`, a JSON file is produced
6029///
6030/// \remarks
6031/// - The parameter `option` is not used.
6032/// - This method calls [TPad::Print(const char *filename, Option_t *option)](\ref TPadPrint)
6033/// the value of `option` is determined by the `filename` extension.
6034/// - Postscript and PDF formats allow to have [several pictures in one file](\ref TPadPrintPS).
6035
6036void TPad::SaveAs(const char *filename, Option_t * /*option*/) const
6037{
6040
6041 if (!lenfil) { psname = GetName(); psname.Append(".ps"); }
6042 else psname = filename;
6043
6044 // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
6045 if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
6046 psname = GetName();
6047 psname.Append(filename);
6048 psname.Prepend("/");
6049 psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
6050 }
6051
6052 if (psname.EndsWith(".gif"))
6053 ((TPad*)this)->Print(psname,"gif");
6054 else if (psname.Contains(".gif+"))
6055 ((TPad*)this)->Print(psname,"gif+");
6056 else if (psname.EndsWith(".C") || psname.EndsWith(".cxx") || psname.EndsWith(".cpp") || psname.EndsWith(".cc"))
6057 ((TPad*)this)->Print(psname,"cxx");
6058 else if (psname.EndsWith(".root"))
6059 ((TPad*)this)->Print(psname,"root");
6060 else if (psname.EndsWith(".xml"))
6061 ((TPad*)this)->Print(psname,"xml");
6062 else if (psname.EndsWith(".json"))
6063 ((TPad*)this)->Print(psname,"json");
6064 else if (psname.EndsWith(".eps"))
6065 ((TPad*)this)->Print(psname,"eps");
6066 else if (psname.EndsWith(".pdf"))
6067 ((TPad*)this)->Print(psname,"pdf");
6068 else if (psname.EndsWith(".pdf["))
6069 ((TPad*)this)->Print(psname,"pdf");
6070 else if (psname.EndsWith(".pdf]"))
6071 ((TPad*)this)->Print(psname,"pdf");
6072 else if (psname.EndsWith(".pdf("))
6073 ((TPad*)this)->Print(psname,"pdf");
6074 else if (psname.EndsWith(".pdf)"))
6075 ((TPad*)this)->Print(psname,"pdf");
6076 else if (psname.EndsWith(".svg"))
6077 ((TPad*)this)->Print(psname,"svg");
6078 else if (psname.EndsWith(".tex"))
6079 ((TPad*)this)->Print(psname,"tex");
6080 else if (psname.EndsWith(".xpm"))
6081 ((TPad*)this)->Print(psname,"xpm");
6082 else if (psname.EndsWith(".png"))
6083 ((TPad*)this)->Print(psname,"png");
6084 else if (psname.EndsWith(".jpg"))
6085 ((TPad*)this)->Print(psname,"jpg");
6086 else if (psname.EndsWith(".jpeg"))
6087 ((TPad*)this)->Print(psname,"jpg");
6088 else if (psname.EndsWith(".bmp"))
6089 ((TPad*)this)->Print(psname,"bmp");
6090 else if (psname.EndsWith(".tiff"))
6091 ((TPad*)this)->Print(psname,"tiff");
6092 else
6093 ((TPad*)this)->Print(psname,"ps");
6094}
6095
6096////////////////////////////////////////////////////////////////////////////////
6097/// Save primitives in this pad on the C++ source file out.
6098
6099void TPad::SavePrimitive(std::ostream &out, Option_t * option /*= ""*/)
6100{
6101 TContext ctxt(this, kFALSE); // not interactive
6102
6104
6105 // check for space in the pad name
6106 auto p = padName.Index(" ");
6107 if (p != kNPOS)
6108 padName.Resize(p);
6109
6110 TString opt = option;
6111 if (!opt.Contains("toplevel")) {
6112 static Int_t pcounter = 0;
6113 padName += TString::Format("__%d", pcounter++);
6114 padName = gInterpreter->MapCppName(padName);
6115 }
6116
6117 const char *pname = padName.Data();
6118 const char *cname = padName.Data();
6119
6120 if (padName.Length() == 0) {
6121 pname = "unnamed";
6122 if (this == gPad->GetCanvas())
6123 cname = "c1";
6124 else
6125 cname = "pad";
6126 }
6127
6128 // Write pad parameters
6129 if (this != gPad->GetCanvas()) {
6130 out << " \n";
6131 out << "// ------------>Primitives in pad: " << GetName() << "\n";
6132 out << " TPad *" << cname << " = new TPad(\"" << GetName() << "\", \""
6133 << TString(GetTitle()).ReplaceSpecialCppChars() << "\", " << fXlowNDC << ", " << fYlowNDC << ", "
6134 << fXlowNDC + fWNDC << ", " << fYlowNDC + fHNDC << ");\n";
6135 out << " " << cname << "->Draw();\n";
6136 out << " " << cname << "->cd();\n";
6137 }
6138 out << " " << cname << "->Range(" << fX1 << "," << fY1 << "," << fX2 << "," << fY2 << ");\n";
6139 TView *view = GetView();
6140 if (view) {
6141 Double_t rmin[3], rmax[3];
6142 view->GetRange(rmin, rmax);
6143 out << " TView::CreateView(1)->SetRange(" << rmin[0] << ", " << rmin[1] << ", " << rmin[2] << ", " << rmax[0]
6144 << ", " << rmax[1] << ", " << rmax[2] << ");\n";
6145 }
6146
6147 SaveFillAttributes(out, cname, -1, -1);
6148
6149 if (GetBorderMode() != 1)
6150 out << " " << cname << "->SetBorderMode(" << GetBorderMode() << ");\n";
6151 if (GetBorderSize() != 4)
6152 out << " " << cname << "->SetBorderSize(" << GetBorderSize() << ");\n";
6153 if (GetLogx())
6154 out << " " << cname << "->SetLogx();\n";
6155 if (GetLogy())
6156 out << " " << cname << "->SetLogy();\n";
6157 if (GetLogz())
6158 out << " " << cname << "->SetLogz();\n";
6159 if (GetGridx())
6160 out << " " << cname << "->SetGridx();\n";
6161 if (GetGridy())
6162 out << " " << cname << "->SetGridy();\n";
6163 if (GetTickx())
6164 out << " " << cname << "->SetTickx(" << GetTickx() << ");\n";
6165 if (GetTicky())
6166 out << " " << cname << "->SetTicky(" << GetTicky() << ");\n";
6167 if (GetTheta() != 30)
6168 out << " " << cname << "->SetTheta(" << GetTheta() << ");\n";
6169 if (GetPhi() != 30)
6170 out << " " << cname << "->SetPhi(" << GetPhi() << ");\n";
6171 if (TMath::Abs(fLeftMargin - 0.1) > 0.01)
6172 out << " " << cname << "->SetLeftMargin(" << GetLeftMargin() << ");\n";
6173 if (TMath::Abs(fRightMargin - 0.1) > 0.01)
6174 out << " " << cname << "->SetRightMargin(" << GetRightMargin() << ");\n";
6175 if (TMath::Abs(fTopMargin - 0.1) > 0.01)
6176 out << " " << cname << "->SetTopMargin(" << GetTopMargin() << ");\n";
6177 if (TMath::Abs(fBottomMargin - 0.1) > 0.01)
6178 out << " " << cname << "->SetBottomMargin(" << GetBottomMargin() << ");\n";
6179
6181 out << " " << cname << "->SetFrameFillColor(" << TColor::SavePrimitiveColor(GetFrameFillColor()) << ");\n";
6182 if (GetFrameFillStyle() != 1001)
6183 out << " " << cname << "->SetFrameFillStyle(" << GetFrameFillStyle() << ");\n";
6184 if (GetFrameLineStyle() != 1)
6185 out << " " << cname << "->SetFrameLineStyle(" << GetFrameLineStyle() << ");\n";
6186 if (GetFrameLineColor() != 1)
6187 out << " " << cname << "->SetFrameLineColor(" << TColor::SavePrimitiveColor(GetFrameLineColor()) << ");\n";
6188 if (GetFrameLineWidth() != 1)
6189 out << " " << cname << "->SetFrameLineWidth(" << GetFrameLineWidth() << ");\n";
6190 if (GetFrameBorderMode() != 0)
6191 out << " " << cname << "->SetFrameBorderMode(" << GetFrameBorderMode() << ");\n";
6192 if (GetFrameBorderSize() != 1)
6193 out << " " << cname << "->SetFrameBorderSize(" << GetFrameBorderSize() << ");\n";
6194
6195 TFrame *frame = fFrame;
6196 if (!frame)
6197 frame = (TFrame *)GetPrimitive("TFrame");
6198 if (frame) {
6199 if (frame->GetFillColor() != GetFillColor())
6200 out << " " << cname << "->SetFrameFillColor(" << TColor::SavePrimitiveColor(frame->GetFillColor()) << ");\n";
6201 if (frame->GetFillStyle() != 1001)
6202 out << " " << cname << "->SetFrameFillStyle(" << frame->GetFillStyle() << ");\n";
6203 if (frame->GetLineStyle() != 1)
6204 out << " " << cname << "->SetFrameLineStyle(" << frame->GetLineStyle() << ");\n";
6205 if (frame->GetLineColor() != 1)
6206 out << " " << cname << "->SetFrameLineColor(" << TColor::SavePrimitiveColor(frame->GetLineColor()) << ");\n";
6207 if (frame->GetLineWidth() != 1)
6208 out << " " << cname << "->SetFrameLineWidth(" << frame->GetLineWidth() << ");\n";
6209 if (frame->GetBorderMode() != 0)
6210 out << " " << cname << "->SetFrameBorderMode(" << frame->GetBorderMode() << ");\n";
6211 if (frame->GetBorderSize() != 1)
6212 out << " " << cname << "->SetFrameBorderSize(" << frame->GetBorderSize() << ");\n";
6213 }
6214
6215 TIter next(GetListOfPrimitives());
6216
6217 while (auto obj = next()) {
6218 obj->SavePrimitive(out, (Option_t *)next.GetOption());
6219 if (obj->InheritsFrom(TPad::Class())) {
6220 if (opt.Contains("toplevel"))
6221 out << " " << pname << "->cd();\n";
6222 else
6223 out << " " << cname << "->cd();\n";
6224 }
6225 }
6226 out << " " << cname << "->Modified();\n";
6227}
6228
6229////////////////////////////////////////////////////////////////////////////////
6230/// Fix pad aspect ratio to current value if fixed is true.
6231
6233{
6234 if (fixed) {
6235 if (!fFixedAspectRatio) {
6236 if (fHNDC != 0.)
6238 else {
6239 Error("SetAspectRatio", "cannot fix aspect ratio, height of pad is 0");
6240 return;
6241 }
6243 }
6244 } else {
6246 fAspectRatio = 0;
6247 }
6248}
6249
6250////////////////////////////////////////////////////////////////////////////////
6251/// Set pad editable yes/no
6252/// If a pad is not editable:
6253/// - one cannot modify the pad and its objects via the mouse.
6254/// - one cannot add new objects to the pad
6255
6257{
6258 fEditable = mode;
6259
6260 TObject *obj;
6261 if (!fPrimitives) fPrimitives = new TList;
6262 TIter next(GetListOfPrimitives());
6263 while ((obj = next())) {
6264 if (obj->InheritsFrom(TPad::Class())) {
6265 TPad *pad = (TPad*)obj;
6266 pad->SetEditable(mode);
6267 }
6268 }
6269}
6270
6271////////////////////////////////////////////////////////////////////////////////
6272/// Override TAttFill::FillStyle for TPad because we want to handle style=0
6273/// as style 4000.
6274
6276{
6277 if (fstyle == 0) fstyle = 4000;
6279}
6280
6281////////////////////////////////////////////////////////////////////////////////
6282/// Set Lin/Log scale for X
6283/// - value = 0 X scale will be linear
6284/// - value = 1 X scale will be logarithmic (base 10)
6285/// - value > 1 reserved for possible support of base e or other
6286
6288{
6289 fLogx = value;
6290 delete fView; fView = nullptr;
6291 Modified();
6293}
6294
6295////////////////////////////////////////////////////////////////////////////////
6296/// Set Lin/Log scale for Y
6297/// - value = 0 Y scale will be linear
6298/// - value = 1 Y scale will be logarithmic (base 10)
6299/// - value > 1 reserved for possible support of base e or other
6300
6302{
6303 fLogy = value;
6304 delete fView; fView = nullptr;
6305 Modified();
6307}
6308
6309////////////////////////////////////////////////////////////////////////////////
6310/// Set Lin/Log scale for Z
6311
6313{
6314 fLogz = value;
6315 delete fView; fView = nullptr;
6316 Modified();
6318}
6319
6320////////////////////////////////////////////////////////////////////////////////
6321/// Set canvas range for pad and resize the pad. If the aspect ratio
6322/// was fixed before the call it will be un-fixed.
6323
6325{
6326 // Reorder points to make sure xlow,ylow is bottom left point and
6327 // xup,yup is top right point.
6328 if (xup < xlow) {
6329 Double_t x = xlow;
6330 xlow = xup;
6331 xup = x;
6332 }
6333 if (yup < ylow) {
6334 Double_t y = ylow;
6335 ylow = yup;
6336 yup = y;
6337 }
6338
6339 // Check if the new pad position is valid.
6340 if ((xlow < 0) || (xlow > 1) || (ylow < 0) || (ylow > 1)) {
6341 Error("TPad", "illegal bottom left position: x=%f, y=%f", xlow, ylow);
6342 return;
6343 }
6344 if ((xup < 0) || (xup > 1) || (yup < 0) || (yup > 1)) {
6345 Error("TPad", "illegal top right position: x=%f, y=%f", xup, yup);
6346 return;
6347 }
6348 if (xup-xlow <= 0) {
6349 Error("TPad", "illegal width: %f", xup-xlow);
6350 return;
6351 }
6352 if (yup-ylow <= 0) {
6353 Error("TPad", "illegal height: %f", yup-ylow);
6354 return;
6355 }
6356
6357 fXlowNDC = xlow;
6358 fYlowNDC = ylow;
6359 fXUpNDC = xup;
6360 fYUpNDC = yup;
6361 fWNDC = xup - xlow;
6362 fHNDC = yup - ylow;
6363
6365
6366 ResizePad();
6367}
6368
6369////////////////////////////////////////////////////////////////////////////////
6370/// Set all pad parameters.
6371
6372void TPad::SetPad(const char *name, const char *title,
6373 Double_t xlow, Double_t ylow, Double_t xup, Double_t yup,
6375{
6376 fName = name;
6377 fTitle = title;
6378 SetFillStyle(1001);
6383 if (color >= 0) SetFillColor(color);
6386 else fBorderSize = bordersize;
6388 else fBorderMode = bordermode;
6389
6390 SetPad(xlow, ylow, xup, yup);
6391}
6392
6393////////////////////////////////////////////////////////////////////////////////
6394/// Set the current TView. Delete previous view if view=0
6395
6397{
6398 if (!view) delete fView;
6399 fView = view;
6400}
6401
6402////////////////////////////////////////////////////////////////////////////////
6403/// Set postscript fill area attributes.
6404
6406{
6407 if (gVirtualPS) {
6408 gVirtualPS->SetFillColor(color);
6410 }
6411}
6412
6413////////////////////////////////////////////////////////////////////////////////
6414/// Set postscript line attributes.
6415
6424
6425////////////////////////////////////////////////////////////////////////////////
6426/// Set postscript marker attributes.
6427
6436
6437////////////////////////////////////////////////////////////////////////////////
6438/// Set postscript text attributes.
6439
6441{
6442 if (gVirtualPS) {
6443 gVirtualPS->SetTextAlign(align);
6445 gVirtualPS->SetTextColor(color);
6446 gVirtualPS->SetTextFont(font);
6447 if (font%10 > 2) {
6448 Float_t wh = (Float_t)gPad->XtoPixel(gPad->GetX2());
6449 Float_t hh = (Float_t)gPad->YtoPixel(gPad->GetY1());
6450 Float_t dy;
6451 if (wh < hh) {
6453 tsize = dy/(fX2-fX1);
6454 } else {
6456 tsize = dy/(fY2-fY1);
6457 }
6458 }
6460 }
6461}
6462
6463////////////////////////////////////////////////////////////////////////////////
6464/// Draw Arrows to indicated equal distances of Objects with given BBoxes.
6465/// Used by ShowGuidelines
6466
6468{
6469 Int_t lineColor = TColor::GetColor(239, 202, 0);
6470 Int_t x1,x2,y1,y2;
6471 x1 = x2 = y1 = y2 = 0;
6472 if (mode == 'x') {
6473 if (aBBox.fX<bBBox.fX) {
6474 x1 = aBBox.fX+aBBox.fWidth;
6475 x2 = bBBox.fX;
6476 }
6477 else {
6478 x1 = bBBox.fX+bBBox.fWidth;
6479 x2 = aBBox.fX;
6480 }
6481
6482 if ((aBBox.fY > bBBox.fY) && (aBBox.fY + aBBox.fHeight < bBBox.fY + bBBox.fHeight))
6483 y1 = y2 = aBBox.fY + TMath::Nint(0.5*(Double_t)(aBBox.fHeight))+1;
6484 else if ((bBBox.fY > aBBox.fY) && (bBBox.fY + bBBox.fHeight < aBBox.fY + aBBox.fHeight))
6485 y1 = y2 = bBBox.fY + TMath::Nint(0.5*(Double_t)(bBBox.fHeight))+1;
6486 else if (aBBox.fY>bBBox.fY) y1 = y2 = aBBox.fY-TMath::Nint(0.5*(Double_t)(aBBox.fY-(bBBox.fY+bBBox.fHeight)));
6487 else y1 = y2 = bBBox.fY-TMath::Nint(0.5*(Double_t)(bBBox.fY-(aBBox.fY+aBBox.fHeight)));
6488 }
6489 else if (mode == 'y') {
6490 if (aBBox.fY<bBBox.fY) {
6491 y1 = aBBox.fY+aBBox.fHeight;
6492 y2 = bBBox.fY;
6493 }
6494 else {
6495 y1 = bBBox.fY+bBBox.fHeight;
6496 y2 = aBBox.fY;
6497 }
6498 if ((aBBox.fX > bBBox.fX) && (aBBox.fX + aBBox.fWidth < bBBox.fX + bBBox.fWidth))
6499 x1 = x2 = aBBox.fX + TMath::Nint(0.5*(Double_t)(aBBox.fWidth))+1;
6500 else if ((bBBox.fX > aBBox.fX) && (bBBox.fX + bBBox.fWidth < aBBox.fX + aBBox.fWidth))
6501 x1 = x2 = bBBox.fX + TMath::Nint(0.5*(Double_t)(bBBox.fWidth))+1;
6502 else if (aBBox.fX>bBBox.fX) x1 = x2 = aBBox.fX+TMath::Nint(0.5*(Double_t)(bBBox.fX+bBBox.fWidth-aBBox.fX));
6503 else x1 = x2 = bBBox.fX+TMath::Nint(0.5*(Double_t)(aBBox.fX+aBBox.fWidth-bBBox.fX));
6504 }
6505
6506 TArrow *A = new TArrow(gPad->PixeltoX(x1), gPad->PixeltoY(y1-gPad->VtoPixel(0)), gPad->PixeltoX(x2), gPad->PixeltoY(y2-gPad->VtoPixel(0)), 0.01, "<|>");
6507 A->SetBit(kCanDelete);
6509 A->SetLineWidth(1);
6511 A->Draw();
6512
6513 return;
6514}
6515
6516////////////////////////////////////////////////////////////////////////////////
6517/// struct used by ShowGuidelines to store the distance Field between objects
6518/// in the canvas.
6519
6520struct dField {
6524 char fdir;
6525
6526
6528 : fa(nullptr), fb(nullptr), fdist(0), fdir(' ')
6529 {}
6530
6532 : fa(a), fb(b), fdist(dist), fdir(direction)
6533 {}
6534};
6535
6536////////////////////////////////////////////////////////////////////////////////
6537/// Shows lines to indicate if a TAttBBox2D object is aligned to
6538/// the center or to another object, shows distance arrows if two
6539/// objects on screen have the same distance to another object
6540/// Call from primitive in Execute Event, in ButtonMotion after
6541/// the new coordinates have been set, to 'stick'
6542/// once when button is up to delete lines
6543///
6544/// modes: t (Top), b (bottom), l (left), r (right), i (inside)
6545/// in resize modes (t,b,l,r) only size arrows are sticky
6546///
6547/// in mode, the function gets the point on the element that is clicked to
6548/// move (i) or resize (all others). The expected values are:
6549/// \image html gpad_pad5.png
6550
6551void TPad::ShowGuidelines(TObject *object, const Int_t event, const char mode, const bool cling )
6552{
6553 // When the object is moved with arrow or when the ShowGuideLines flag
6554 // is off we do show guide lines.
6555 if ((event == kArrowKeyRelease) || (event == kArrowKeyPress) ||
6556 !gEnv->GetValue("Canvas.ShowGuideLines", 0)) return;
6557
6558 std::vector<dField> curDist;
6559 std::vector<dField> otherDist;
6560 Int_t pMX, pMY;
6561 Double_t MX, MY;
6563 TList *prims;
6564 UInt_t n;
6566 aBBox = bBBox = Rectangle_t();
6567 TLine *L;
6568 TArrow *A;
6569 Int_t dSizeArrow = 12; // distance of arrows indicating same size from BBox in px
6570 Bool_t movedX, movedY; // make sure the current object is moved just once
6571 movedX = movedY = false;
6572 Bool_t resize = false; // indicates resize mode
6573 Bool_t log = gPad->GetLogx() || gPad->GetLogy();
6574 if (mode != 'i') resize = true;
6575
6576 TPad *is_pad = dynamic_cast<TPad *>( object );
6577
6579
6580 if (is_pad && is_pad->GetMother())
6581 is_pad->GetMother()->cd();
6582
6583 static TPad *tmpGuideLinePad = nullptr;
6584
6585 //delete all existing Guidelines and create new invisible pad
6586 if (tmpGuideLinePad) {
6587 ctxt.PadDeleted(tmpGuideLinePad);
6588 auto guidePadClicked = (object == tmpGuideLinePad); // in case of funny button click combination.
6589 tmpGuideLinePad->Delete();
6590 tmpGuideLinePad = nullptr;
6591 if (guidePadClicked) return;
6592 }
6593
6594 // Get Primitives
6595 prims = gPad->GetListOfPrimitives();
6596 n = TMath::Min(15,prims->GetSize());
6597 Int_t lineColor = TColor::GetColor(239, 202, 0);
6598
6599 TAttBBox2D *cur = dynamic_cast<TAttBBox2D *>( object );
6600 if (cur) {
6601 //create invisible TPad above gPad
6602 if (!tmpGuideLinePad){
6603 tmpGuideLinePad = new TPad("tmpGuideLinePad", "tmpGuideLinePad", 0, 0, 1, 1);
6604 Double_t x1, y1, x2, y2;
6605 gPad->GetRange(x1, y1, x2, y2);
6606 tmpGuideLinePad->Range(x1, y1, x2, y2);
6607 tmpGuideLinePad->SetFillStyle(0);
6608 tmpGuideLinePad->SetFillColor(0);
6609 tmpGuideLinePad->Draw();
6610 tmpGuideLinePad->cd();
6611 gPad->GetRange(x1, y1, x2, y2);
6612 }
6613 if (cling && !log) threshold = 7;
6614 else threshold = 1;
6615
6616 Rectangle_t BBox = cur->GetBBox();
6617 TPoint center = cur->GetBBoxCenter();
6618
6619 otherDist.clear();
6620 curDist.clear();
6621
6622 switch (event) {
6623
6624 case kButton1Down:
6625 case kButton1Motion:
6626 MX = gPad->GetX1() + 0.5 * (gPad->GetX2()-gPad->GetX1());
6627 MY = gPad->GetY1() + 0.5 * (gPad->GetY2()-gPad->GetY1());
6628 pMX = gPad->XtoPixel(MX);
6629 pMY = gPad->YtoPixel(MY);
6630 // Middlelines
6631 if (TMath::Abs(pMX-center.GetX())<threshold) {
6632 if (cling && (!resize)) {
6633 cur->SetBBoxCenterX(pMX);
6634 center = cur->GetBBoxCenter();
6635 BBox = cur->GetBBox();
6636 center = cur->GetBBoxCenter();
6637 }
6638 L = new TLine(MX, gPad->GetY1(), MX, gPad->GetY2());
6639 L->SetBit(kCanDelete);
6640 L->SetLineColor(lineColor);
6641 L->Draw();
6642 }
6643 if (TMath::Abs(pMY-center.GetY())<threshold) {
6644 if (cling && (!resize)) {
6645 cur->SetBBoxCenterY(pMY);
6646 center = cur->GetBBoxCenter();
6647 BBox = cur->GetBBox();
6648 center = cur->GetBBoxCenter();
6649 }
6650 L = new TLine(gPad->GetX1(), MY, gPad->GetX2(), MY);
6651 L->SetBit(kCanDelete);
6652 L->SetLineColor(lineColor);
6653 L->Draw();
6654 }
6655 // Alignment to other objects
6656 for (UInt_t i = 0; i<n; i++) {
6657 TAttBBox2D *other = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6658 if (other) {
6659 if (other != cur) {
6660 TPoint centerOther = other->GetBBoxCenter();
6661 if (TMath::Abs(center.GetX()-centerOther.GetX())<threshold) {
6662 if (cling && (!resize)) {
6663 cur->SetBBoxCenterX(centerOther.GetX());
6664 BBox = cur->GetBBox();
6665 center = cur->GetBBoxCenter();
6666 }
6667 L = new TLine(gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(center.GetY()-gPad->VtoPixel(0)),
6668 gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)));
6669 L->SetLineColor(lineColor);
6670 L->Draw();
6671 L->SetBit(kCanDelete);
6672 }
6673 if (TMath::Abs(center.GetY()-centerOther.GetY())<threshold) {
6674 if (cling && (!resize)) {
6675 cur->SetBBoxCenterY(centerOther.GetY());
6676 BBox = cur->GetBBox();
6677 center = cur->GetBBoxCenter();
6678 }
6679 L = new TLine(gPad->PixeltoX(center.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)),
6680 gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)));
6681 L->SetBit(kCanDelete);
6682 L->SetLineColor(lineColor);
6683 L->Draw();
6684 }
6685 }
6686 }
6687 }
6688 // Get Distances between objects
6689 for (UInt_t i = 0; i<n; i++) {
6690 TAttBBox2D *a = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6691 if (a) {
6692 aBBox = a->GetBBox();
6693 for (UInt_t j = i+1; j<n; j++) {
6694 TAttBBox2D *b = dynamic_cast<TAttBBox2D *>( prims->At(j) );
6695 if (b) {
6696 bBBox = b->GetBBox();
6697
6698 //only when bounding boxes overlap in x or y direction
6699 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
6700 if ((aBBox.fY+aBBox.fHeight<bBBox.fY)||(bBBox.fY+bBBox.fHeight<aBBox.fY)) {//No overlap in Y-direction required
6701 dField abDist = dField();
6702 if (aBBox.fY>bBBox.fY) abDist = dField(a, b, TMath::Abs(aBBox.fY-(bBBox.fY+bBBox.fHeight)), 'y');
6703 else abDist = dField(a, b, TMath::Abs(bBBox.fY-(aBBox.fY+aBBox.fHeight)), 'y');
6704 if ((b != cur)&&(a != cur)) otherDist.push_back(abDist);
6705 else curDist.push_back(abDist);
6706 }
6707 } 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
6708 if ((aBBox.fX+aBBox.fWidth<bBBox.fX)||(bBBox.fX+bBBox.fWidth<aBBox.fX)) {//No overlap in x-direction required
6709 dField abDist = dField();
6710 if (aBBox.fX>bBBox.fX) abDist = dField(a, b, TMath::Abs(aBBox.fX-(bBBox.fX+bBBox.fWidth)), 'x');
6711 else abDist = dField(a, b, TMath::Abs(bBBox.fX-(aBBox.fX+aBBox.fWidth)), 'x');
6712 if ((b != cur)&&(a != cur)) otherDist.push_back(abDist);
6713 else curDist.push_back(abDist);
6714 }
6715 }
6716 }
6717 }
6718 }
6719 }
6720 // Show equal distances
6721 for (UInt_t i = 0; i<curDist.size(); i++) {
6722 for (UInt_t j = 0; j<otherDist.size(); j++) {
6723 if ((curDist[i].fdir == otherDist[j].fdir) && (otherDist[j].fdir=='x') && (TMath::Abs(curDist[i].fdist-otherDist[j].fdist)<threshold)) {
6724 if (cling && (!movedX) && (!resize)) {
6725 if ((cur->GetBBoxCenter().fX < curDist[i].fb->GetBBoxCenter().fX)||(cur->GetBBoxCenter().fX < curDist[i].fa->GetBBoxCenter().fX))
6726 cur->SetBBoxCenterX(cur->GetBBoxCenter().fX - otherDist[j].fdist + curDist[i].fdist);
6727 else cur->SetBBoxCenterX(cur->GetBBoxCenter().fX + otherDist[j].fdist - curDist[i].fdist);
6728 movedX = true;
6729 }
6730 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'x');
6731 DrawDist(otherDist[j].fa->GetBBox(), otherDist[j].fb->GetBBox(), 'x');
6732 }
6733 if ((curDist[i].fdir == otherDist[j].fdir) && (otherDist[j].fdir=='y') && (TMath::Abs(curDist[i].fdist-otherDist[j].fdist)<threshold)) {
6734 if (cling && (!movedY) && (!resize)) {
6735 if ((cur->GetBBoxCenter().fY < curDist[i].fb->GetBBoxCenter().fY)||(cur->GetBBoxCenter().fY < curDist[i].fa->GetBBoxCenter().fY))
6736 cur->SetBBoxCenterY(cur->GetBBoxCenter().fY - otherDist[j].fdist + curDist[i].fdist);
6737 else cur->SetBBoxCenterY(cur->GetBBoxCenter().fY + otherDist[j].fdist - curDist[i].fdist);
6738 movedY = true;
6739 }
6740 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'y');
6741 DrawDist(otherDist[j].fa->GetBBox(), otherDist[j].fb->GetBBox(), 'y');
6742 }
6743 }
6744 for (UInt_t j = i; j<curDist.size(); j++) {
6745 if (i!=j) {
6746 if ((curDist[i].fdir == curDist[j].fdir) && (curDist[j].fdir=='x') && (TMath::Abs(curDist[i].fdist-curDist[j].fdist)<threshold)) {
6747 if (cling && (!movedX) && (!resize)) {
6748 if ((cur->GetBBoxCenter().fX < curDist[i].fb->GetBBoxCenter().fX)||(cur->GetBBoxCenter().fX < curDist[i].fa->GetBBoxCenter().fX))
6749 cur->SetBBoxCenterX(cur->GetBBoxCenter().fX - floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6750 else cur->SetBBoxCenterX(cur->GetBBoxCenter().fX + floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6751 }
6752 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'x');
6753 DrawDist(curDist[j].fa->GetBBox(), curDist[j].fb->GetBBox(), 'x');
6754 }
6755
6756 if ((curDist[i].fdir == curDist[j].fdir) && (curDist[j].fdir=='y') && (TMath::Abs(curDist[i].fdist-curDist[j].fdist)<threshold)) {
6757 if (cling && (!movedY) && (!resize)) {
6758 if ((cur->GetBBoxCenter().fY < curDist[i].fb->GetBBoxCenter().fY)||(cur->GetBBoxCenter().fY < curDist[i].fa->GetBBoxCenter().fY))
6759 cur->SetBBoxCenterY(cur->GetBBoxCenter().fY - floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6760 else cur->SetBBoxCenterY(cur->GetBBoxCenter().fY + floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6761 }
6762 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'y');
6763 DrawDist(curDist[j].fa->GetBBox(), curDist[j].fb->GetBBox(), 'y');
6764 }
6765 }
6766 }
6767 }
6768 if (resize) {
6769 // Show equal Sizes
6770 for (UInt_t i = 0; i<n; i++) {
6771 TAttBBox2D *a = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6772 if (a && (cur != a)) {
6773 aBBox = a->GetBBox();
6774
6775 if ((TMath::Abs(aBBox.fWidth - BBox.fWidth)<threshold) && (mode != 't') && (mode != 'b')) {
6776 if (cling) {
6777 if (mode == 'l') cur->SetBBoxX1(BBox.fX + BBox.fWidth - aBBox.fWidth);
6778 if (mode == 'r') cur->SetBBoxX2(BBox.fX + aBBox.fWidth);
6779 if ((mode == '1')||(mode == '4')) cur->SetBBoxX1(BBox.fX + BBox.fWidth - aBBox.fWidth);
6780 if ((mode == '2')||(mode == '3')) cur->SetBBoxX2(BBox.fX + aBBox.fWidth);
6781 BBox = cur->GetBBox();
6782 }
6783
6784 A = new TArrow(gPad->PixeltoX(aBBox.fX), gPad->PixeltoY(aBBox.fY-dSizeArrow-gPad->VtoPixel(0)),
6785 gPad->PixeltoX(aBBox.fX+aBBox.fWidth), gPad->PixeltoY(aBBox.fY-dSizeArrow-gPad->VtoPixel(0)), 0.01, "<|>");
6786 A->SetBit(kCanDelete);
6789 A->Draw();
6790
6791 A = new TArrow(gPad->PixeltoX(BBox.fX), gPad->PixeltoY(BBox.fY-dSizeArrow-gPad->VtoPixel(0)),
6792 gPad->PixeltoX(BBox.fX+BBox.fWidth), gPad->PixeltoY(BBox.fY-dSizeArrow-gPad->VtoPixel(0)), 0.01, "<|>");
6793 A->SetBit(kCanDelete);
6796 A->Draw();
6797 }
6798 if ((TMath::Abs(aBBox.fHeight - BBox.fHeight)<threshold) && (mode != 'r') && (mode != 'l')) {
6799 if (cling) {
6800 if (mode == 't') cur->SetBBoxY1(BBox.fY + BBox.fHeight - aBBox.fHeight);
6801 if (mode == 'b') cur->SetBBoxY2(BBox.fY + aBBox.fHeight);
6802 if ((mode == '1')||(mode == '2')) cur->SetBBoxY1(BBox.fY + BBox.fHeight - aBBox.fHeight);
6803 if ((mode == '3')||(mode == '4')) cur->SetBBoxY2(BBox.fY + aBBox.fHeight);
6804 BBox = cur->GetBBox();
6805 }
6806 A = new TArrow(gPad->PixeltoX(aBBox.fX-dSizeArrow), gPad->PixeltoY(aBBox.fY-gPad->VtoPixel(0)),
6807 gPad->PixeltoX(aBBox.fX-dSizeArrow), gPad->PixeltoY(aBBox.fY+aBBox.fHeight-gPad->VtoPixel(0)), 0.01, "<|>");
6808 A->SetBit(kCanDelete);
6811 A->Draw();
6812
6813 A = new TArrow(gPad->PixeltoX(BBox.fX-dSizeArrow), gPad->PixeltoY(BBox.fY-gPad->VtoPixel(0)),
6814 gPad->PixeltoX(BBox.fX-dSizeArrow), gPad->PixeltoY(BBox.fY+BBox.fHeight-gPad->VtoPixel(0)), 0.01, "<|>");
6815 A->SetBit(kCanDelete);
6818 A->Draw();
6819 }
6820 }
6821 }
6822 }
6823
6824 break;
6825
6826 case kButton1Up:
6827 if (tmpGuideLinePad) {
6828 // All the arrows and lines in that pad are also deleted because
6829 // they all have the bit kCanDelete on.
6830 tmpGuideLinePad->Delete();
6831 tmpGuideLinePad = nullptr;
6832 }
6833 break;
6834 }
6835 }
6836
6837 gPad->Modified(kTRUE);
6838}
6839
6840////////////////////////////////////////////////////////////////////////////////
6841/// Return kTRUE if the crosshair has been activated (via SetCrosshair).
6842
6844{
6845 return (Bool_t)GetCrosshair();
6846}
6847
6848////////////////////////////////////////////////////////////////////////////////
6849/// Return the crosshair type (from the mother canvas)
6850/// crosshair type = 0 means no crosshair.
6851
6853{
6854 if (this == (TPad*)fCanvas)
6855 return fCrosshair;
6856 return fCanvas ? fCanvas->GetCrosshair() : 0;
6857}
6858
6859////////////////////////////////////////////////////////////////////////////////
6860/// Set crosshair active/inactive.
6861/// - If crhair != 0, a crosshair will be drawn in the pad and its sub-pads.
6862/// - If the canvas crhair = 1 , the crosshair spans the full canvas.
6863/// - If the canvas crhair > 1 , the crosshair spans only the pad.
6864
6866{
6867 if (!fCanvas) return;
6869 fCrosshairPos = 0;
6870
6871 if (this != (TPad*)fCanvas) fCanvas->SetCrosshair(crhair);
6872}
6873
6874////////////////////////////////////////////////////////////////////////////////
6875/// static function to set the maximum Pick Distance fgMaxPickDistance
6876/// This parameter is used in TPad::Pick to select an object if
6877/// its DistancetoPrimitive returns a value < fgMaxPickDistance
6878/// The default value is 5 pixels. Setting a smaller value will make
6879/// picking more precise but also more difficult
6880
6885
6886////////////////////////////////////////////////////////////////////////////////
6887/// Set tool tip text associated with this pad. The delay is in
6888/// milliseconds (minimum 250). To remove tool tip call method with
6889/// text = 0.
6890
6892{
6893 if (fTip) {
6895 fTip = nullptr;
6896 }
6897
6898 if (text && strlen(text))
6899 fTip = CreateToolTip((TBox*)nullptr, text, delayms);
6900}
6901
6902////////////////////////////////////////////////////////////////////////////////
6903/// Set pad vertical (default) or horizontal
6904
6906{
6907 if (vert) ResetBit(kHori);
6908 else SetBit(kHori);
6909}
6910
6911////////////////////////////////////////////////////////////////////////////////
6912/// Stream a class object.
6913
6915{
6916 UInt_t R__s, R__c;
6919 TObject *obj;
6920 if (b.IsReading()) {
6921 Version_t v = b.ReadVersion(&R__s, &R__c);
6922 if (v > 5) {
6923 if (!gPad)
6924 gPad = new TCanvas(GetName());
6925 fMother = (TPad*)gPad;
6927 TContext ctxt(this, kFALSE);
6928 fPixmapID = -1; // -1 means pixmap will be created by ResizePad()
6929 gReadLevel++;
6930 gROOT->SetReadingObject(kTRUE);
6931
6932 b.ReadClassBuffer(TPad::Class(), this, v, R__s, R__c);
6933
6934 //Set the kCanDelete bit in all objects in the pad such that when the pad
6935 //is deleted all objects in the pad are deleted too.
6936 //Also set must cleanup bit which normally set for all primitives add to pad,
6937 // but may be reset in IO like TH1::Streamer does
6938 TIter next(fPrimitives);
6939 while ((obj = next())) {
6940 obj->SetBit(kCanDelete);
6941 obj->SetBit(kMustCleanup);
6942 }
6943
6944 fModified = kTRUE;
6945 fPadPointer = nullptr;
6946 gReadLevel--;
6947 if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
6948 gROOT->SetReadingObject(kFALSE);
6949 return;
6950 }
6951
6952 //====process old versions before automatic schema evolution
6953 if (v < 5) { //old TPad in single precision
6954 if (v < 3) { //old TPad derived from TWbox
6955 b.ReadVersion(); // TVirtualPad::Streamer(b)
6956 b.ReadVersion(); // TWbox::Streamer(b)
6957 b.ReadVersion(); // TBox::Streamer(b)
6961 b >> single; fX1 = single;
6962 b >> single; fY1 = single;
6963 b >> single; fX2 = single;
6964 b >> single; fY2 = single;
6965 b >> fBorderSize;
6966 b >> fBorderMode;
6968 } else { //new TPad
6971 b >> single; fX1 = single;
6972 b >> single; fY1 = single;
6973 b >> single; fX2 = single;
6974 b >> single; fY2 = single;
6975 b >> fBorderSize;
6976 b >> fBorderMode;
6977 }
6978 b >> fLogx;
6979 b >> fLogy;
6980 b >> fLogz;
6982 b >> single; fXtoPixelk = single;
6983 b >> single; fXtoPixel = single;
6985 b >> single; fYtoPixelk = single;
6986 b >> single; fYtoPixel = single;
6988 b >> single; fUtoPixelk = single;
6989 b >> single; fUtoPixel = single;
6991 b >> single; fVtoPixelk = single;
6992 b >> single; fVtoPixel = single;
6994 b >> single; fPixeltoXk = single;
6995 b >> single; fPixeltoX = single;
6997 b >> single; fPixeltoYk = single;
6998 b >> single; fPixeltoY = single;
6999 b >> single; fXlowNDC = single;
7000 b >> single; fYlowNDC = single;
7001 b >> single; fWNDC = single;
7002 b >> single; fHNDC = single;
7003 b >> single; fAbsXlowNDC = single;
7004 b >> single; fAbsYlowNDC = single;
7005 b >> single; fAbsWNDC = single;
7006 b >> single; fAbsHNDC = single;
7007 b >> single; fUxmin = single;
7008 b >> single; fUymin = single;
7009 b >> single; fUxmax = single;
7010 b >> single; fUymax = single;
7011 } else {
7014 b >> fX1;
7015 b >> fY1;
7016 b >> fX2;
7017 b >> fY2;
7018 b >> fBorderSize;
7019 b >> fBorderMode;
7020 b >> fLogx;
7021 b >> fLogy;
7022 b >> fLogz;
7023 b >> fXtoAbsPixelk;
7024 b >> fXtoPixelk;
7025 b >> fXtoPixel;
7026 b >> fYtoAbsPixelk;
7027 b >> fYtoPixelk;
7028 b >> fYtoPixel;
7029 b >> fUtoAbsPixelk;
7030 b >> fUtoPixelk;
7031 b >> fUtoPixel;
7032 b >> fVtoAbsPixelk;
7033 b >> fVtoPixelk;
7034 b >> fVtoPixel;
7035 b >> fAbsPixeltoXk;
7036 b >> fPixeltoXk;
7037 b >> fPixeltoX;
7038 b >> fAbsPixeltoYk;
7039 b >> fPixeltoYk;
7040 b >> fPixeltoY;
7041 b >> fXlowNDC;
7042 b >> fYlowNDC;
7043 b >> fWNDC;
7044 b >> fHNDC;
7045 b >> fAbsXlowNDC;
7046 b >> fAbsYlowNDC;
7047 b >> fAbsWNDC;
7048 b >> fAbsHNDC;
7049 b >> fUxmin;
7050 b >> fUymin;
7051 b >> fUxmax;
7052 b >> fUymax;
7053 }
7054
7055 if (!gPad)
7056 gPad = new TCanvas(GetName());
7057 if (gReadLevel == 0)
7059 else
7060 fMother = (TPad *)gPad;
7061 if (!fMother)
7062 fMother = (TPad *)gPad;
7063 if (fMother)
7065 gPad = fMother;
7066 fPixmapID = -1; // -1 means pixmap will be created by ResizePad()
7067 //-------------------------
7068 // read objects and their drawing options
7069 // b >> fPrimitives;
7070 gReadLevel++;
7071 gROOT->SetReadingObject(kTRUE);
7072 fPrimitives = new TList;
7073 b >> nobjects;
7074 if (nobjects > 0) {
7075 TContext ctxt(this, kFALSE);
7076 char drawoption[64];
7077 for (Int_t i = 0; i < nobjects; i++) {
7078 b >> obj;
7079 b >> nch;
7080 b.ReadFastArray(drawoption,nch);
7082 gPad = this; // gPad may be modified in b >> obj if obj is a pad
7083 }
7084 }
7085 gReadLevel--;
7086 gROOT->SetReadingObject(kFALSE);
7087 //////////////////////////////////////////////////////////////////////////
7088
7089 if (v > 3) {
7090 b >> fExecs;
7091 }
7092 fName.Streamer(b);
7093 fTitle.Streamer(b);
7094 b >> fPadPaint;
7095 fModified = kTRUE;
7096 b >> fGridx;
7097 b >> fGridy;
7098 b >> fFrame;
7099 b >> fView;
7100 if (v < 5) {
7101 b >> single; fTheta = single;
7102 b >> single; fPhi = single;
7103 } else {
7104 b >> fTheta;
7105 b >> fPhi;
7106 }
7107 fPadPointer = nullptr;
7108 b >> fNumber;
7109 b >> fAbsCoord;
7110 if (v > 1) {
7111 b >> fTickx;
7112 b >> fTicky;
7113 } else {
7114 fTickx = fTicky = 0;
7115 }
7116 if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
7117 b.CheckByteCount(R__s, R__c, TPad::IsA());
7118 //====end of old versions
7119
7120 } else {
7121 b.WriteClassBuffer(TPad::Class(),this);
7122 }
7123}
7124
7125////////////////////////////////////////////////////////////////////////////////
7126/// Force a copy of current style for all objects in pad.
7127
7129{
7130 if (gStyle->IsReading()) {
7142 fLogx = gStyle->GetOptLogx();
7143 fLogy = gStyle->GetOptLogy();
7144 fLogz = gStyle->GetOptLogz();
7145 } else {
7160 }
7161
7162 if (!fPrimitives) fPrimitives = new TList;
7163 TIter next(GetListOfPrimitives());
7164 TObject *obj;
7165
7166 while ((obj = next())) {
7167 obj->UseCurrentStyle();
7168 }
7169
7170 TPaveText *title = (TPaveText*)FindObject("title");
7171 if (title) {
7172 if (gStyle->IsReading()) {
7174 title->SetTextFont(gStyle->GetTitleFont(""));
7177 if (!gStyle->GetOptTitle()) delete title;
7178 } else {
7180 gStyle->SetTitleFont(title->GetTextFont());
7183 }
7184 }
7186
7187 if (gStyle->IsReading()) Modified();
7188}
7189
7190////////////////////////////////////////////////////////////////////////////////
7191/// Loop and sleep until a primitive with name=pname is found in the pad.
7192///
7193/// If emode is given, the editor is automatically set to emode, ie
7194/// it is not required to have the editor control bar.
7195///
7196/// The possible values for emode are:
7197/// - emode = "" (default). User will select the mode via the editor bar
7198/// - emode = "Arc", "Line", "Arrow", "Button", "Diamond", "Ellipse",
7199/// - emode = "Pad","pave", "PaveLabel","PaveText", "PavesText",
7200/// - emode = "PolyLine", "CurlyLine", "CurlyArc", "Text", "Marker", "CutG"
7201///
7202/// If emode is specified and it is not valid, "PolyLine" is assumed. If emode
7203/// is not specified or ="", an attempt is to use pname[1...]
7204///
7205/// for example if pname="TArc", emode="Arc" will be assumed.
7206/// When this function is called within a macro, the macro execution
7207/// is suspended until a primitive corresponding to the arguments
7208/// is found in the pad.
7209///
7210/// If CRTL/C is typed in the pad, the function returns 0.
7211///
7212/// While this function is executing, one can use the mouse, interact
7213/// with the graphics pads, use the Inspector, Browser, TreeViewer, etc.
7214///
7215/// Examples:
7216/// ~~~ {.cpp}
7217/// c1.WaitPrimitive(); // Return the first created primitive
7218/// // whatever it is.
7219/// // If a double-click with the mouse is executed
7220/// // in the pad or any key pressed, the function
7221/// // returns 0.
7222/// c1.WaitPrimitive("ggg"); // Set the editor in mode "PolyLine/Graph"
7223/// // Create a polyline, then using the context
7224/// // menu item "SetName", change the name
7225/// // of the created TGraph to "ggg"
7226/// c1.WaitPrimitive("TArc");// Set the editor in mode "Arc". Returns
7227/// // as soon as a TArc object is created.
7228/// c1.WaitPrimitive("lat","Text"); // Set the editor in Text/Latex mode.
7229/// // Create a text object, then Set its name to "lat"
7230/// ~~~
7231/// The following macro waits for 10 primitives of any type to be created.
7232///
7233/// ~~~ {.cpp}
7234///{
7235/// TCanvas c1("c1");
7236/// TObject *obj;
7237/// for (Int_t i=0;i<10;i++) {
7238/// obj = gPad->WaitPrimitive();
7239/// if (!obj) break;
7240/// printf("Loop i=%d, found objIsA=%s, name=%s\n",
7241/// i,obj->ClassName(),obj->GetName());
7242/// }
7243///}
7244/// ~~~
7245///
7246/// If ROOT runs in batch mode a call to this method does nothing.
7247
7248TObject *TPad::WaitPrimitive(const char *pname, const char *emode)
7249{
7250 if (!gPad || IsWeb())
7251 return nullptr;
7252
7253 if (emode && strlen(emode)) gROOT->SetEditorMode(emode);
7254 if (gROOT->GetEditorMode() == 0 && pname && strlen(pname) > 2) gROOT->SetEditorMode(&pname[1]);
7255
7256 if (!fPrimitives) fPrimitives = new TList;
7258 TObject *oldlast = gPad->GetListOfPrimitives() ? gPad->GetListOfPrimitives()->Last() : nullptr;
7259 TObject *obj = nullptr;
7261 Bool_t hasname = pname && (strlen(pname) > 0);
7262 if ((!pname || !pname[0]) && (!emode || !emode[0])) testlast = kTRUE;
7263 if (testlast) gROOT->SetEditorMode();
7264 while (!gSystem->ProcessEvents() && gROOT->GetSelectedPad() && gPad) {
7265 if (gROOT->GetEditorMode() == 0) {
7266 if (hasname) {
7267 obj = FindObject(pname);
7268 if (obj) return obj;
7269 }
7270 if (testlast) {
7271 if (!gPad->GetListOfPrimitives()) return nullptr;
7272 obj = gPad->GetListOfPrimitives()->Last();
7273 if (obj != oldlast) return obj;
7274 Int_t event = GetEvent();
7275 if (event == kButton1Double || event == kKeyPress) {
7276 //the following statement is required against other loop executions
7277 //before returning
7278 fCanvas->HandleInput((EEventType)-1,0,0);
7279 return nullptr;
7280 }
7281 }
7282 }
7283 gSystem->Sleep(10);
7284 }
7285
7286 return nullptr;
7287}
7288
7289////////////////////////////////////////////////////////////////////////////////
7290/// Create a tool tip and return its pointer.
7291
7293{
7294 if (gPad->IsBatch()) return nullptr;
7295 return (TObject*)gROOT->ProcessLineFast(TString::Format("new TGToolTip((TBox*)0x%zx,\"%s\",%d)",
7296 (size_t)box,text,(Int_t)delayms).Data());
7297}
7298
7299////////////////////////////////////////////////////////////////////////////////
7300/// Delete tool tip object.
7301
7303{
7304 // delete tip;
7305 if (!tip) return;
7306 gROOT->ProcessLineFast(TString::Format("delete (TGToolTip*)0x%zx", (size_t)tip).Data());
7307}
7308
7309////////////////////////////////////////////////////////////////////////////////
7310/// Reset tool tip, i.e. within time specified in CreateToolTip the
7311/// tool tip will pop up.
7312
7314{
7315 if (!tip) return;
7316 // tip->Reset(this);
7317 gROOT->ProcessLineFast(TString::Format("((TGToolTip*)0x%zx)->Reset((TPad*)0x%zx)",
7318 (size_t)tip,(size_t)this).Data());
7319}
7320
7321////////////////////////////////////////////////////////////////////////////////
7322/// Hide tool tip.
7323
7325{
7326 if (!tip) return;
7327 // tip->Hide();
7328 gROOT->ProcessLineFast(TString::Format("((TGToolTip*)0x%zx)->Hide()", (size_t)tip).Data());
7329}
7330
7331////////////////////////////////////////////////////////////////////////////////
7332/// Deprecated: use TPad::GetViewer3D() instead
7333
7335{
7336 ::Info("TPad::x3d()", "This function is deprecated. Use %s->GetViewer3D(\"x3d\") instead",this->GetName());
7337
7338 // Default on GetViewer3D is pad - for x3d it was x3d...
7339 if (!type || !type[0]) {
7340 type = "x3d";
7341 }
7343}
7344
7345////////////////////////////////////////////////////////////////////////////////
7346/// Create/obtain handle to 3D viewer. Valid types are:
7347/// - 'pad' - pad drawing via TViewer3DPad
7348/// any others registered with plugin manager supporting TVirtualViewer3D
7349/// If an invalid/null type is requested then the current viewer is returned
7350/// (if any), otherwise a default 'pad' type is returned
7351
7353{
7355
7356 if ((!type || !*type || (strstr(type, "gl") && !strstr(type, "ogl"))) && (!fCanvas || !fCanvas->UseGL()))
7357 type = "pad";
7358
7359 if (type && *type) {
7360 if (gPluginMgr->FindHandler("TVirtualViewer3D", type))
7361 validType = kTRUE;
7362 }
7363
7364 // Invalid/null type requested?
7365 if (!validType) {
7366 // Return current viewer if there is one
7367 if (fViewer3D)
7368 return fViewer3D;
7369 // otherwise default to the pad
7370 else
7371 type = "pad";
7372 }
7373
7374 // Ensure we can create the new viewer before removing any existing one
7375 TVirtualViewer3D *newViewer = nullptr;
7376
7378
7379 // External viewers need to be created via plugin manager via interface...
7380 if (!strstr(type,"pad")) {
7382
7383 if (!newViewer) {
7384 Warning("GetViewer3D", "Cannot create 3D viewer of type: %s", type);
7385 // Return the existing viewer
7386 return fViewer3D;
7387 }
7388
7389 if (strstr(type, "gl") && !strstr(type, "ogl")) {
7392 Modified();
7393 } else {
7395 }
7396
7397 } else {
7398 newViewer = new TViewer3DPad(*this);
7399 }
7400
7401 // If we had a previous viewer destroy it now
7402 // In this case we do take responsibility for destroying viewer
7403 // c.f. ReleaseViewer3D
7404 delete fViewer3D;
7405
7406 // Set and return new viewer
7408
7409 // Ensure any new external viewer is painted
7410 // For internal TViewer3DPad type we assume this is being
7411 // create on demand due to a paint - so this is not required
7412 if (createdExternal) {
7413 Modified();
7414 Update();
7415 }
7416
7417 return fViewer3D;
7418}
7419
7420////////////////////////////////////////////////////////////////////////////////
7421/// Release current (external) viewer
7422
7424{
7425 fViewer3D = nullptr;
7426
7427 // We would like to ensure the pad is repainted
7428 // when external viewer is closed down. However
7429 // a modify/paint call here will repaint the pad
7430 // before the external viewer window actually closes.
7431 // So the pad would have to be redraw twice over.
7432 // Currently we just have to live with the pad staying blank
7433 // any click in pad will refresh.
7434}
7435
7436////////////////////////////////////////////////////////////////////////////////
7437/// Get GL device.
7438
7440{
7441 return fGLDevice;
7442}
7443
7444////////////////////////////////////////////////////////////////////////////////
7445/// Emit RecordPave() signal.
7446
7448{
7449 Emit("RecordPave(const TObject*)", (Longptr_t)obj);
7450}
7451
7452////////////////////////////////////////////////////////////////////////////////
7453/// Emit RecordLatex() signal.
7454
7456{
7457 Emit("RecordLatex(const TObject*)", (Longptr_t)obj);
7458}
7459
7460////////////////////////////////////////////////////////////////////////////////
7461/// Get pad painter from TCanvas.
7462
7464{
7465 if (!fCanvas) return nullptr;
7466 return fCanvas->GetCanvasPainter();
7467}
7468
7469////////////////////////////////////////////////////////////////////////////////
7470/// Return the bounding Box of the Pad
7471
7473{
7474 Rectangle_t BBox{0, 0, 0, 0};
7475 if (gPad) {
7476 BBox.fX = gPad->XtoPixel(fXlowNDC * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1());
7477 BBox.fY = gPad->YtoPixel((fYlowNDC + fHNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1());
7478 BBox.fWidth = gPad->XtoPixel((fXlowNDC + fWNDC) * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1()) -
7479 gPad->XtoPixel(fXlowNDC * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1());
7480 BBox.fHeight = gPad->YtoPixel((fYlowNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1()) -
7481 gPad->YtoPixel((fYlowNDC + fHNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1());
7482 }
7483 return BBox;
7484}
7485
7486////////////////////////////////////////////////////////////////////////////////
7487/// Return the center of the Pad as TPoint in pixels
7488
7490{
7491 TPoint p(0, 0);
7492 if (gPad) {
7493 Double_t x = ((fXlowNDC + 0.5 * fWNDC) * (gPad->GetX2() - gPad->GetX1())) + gPad->GetX1();
7494 Double_t y = ((fYlowNDC + 0.5 * fHNDC) * (gPad->GetY2() - gPad->GetY1())) + gPad->GetY1();
7495 p.SetX(gPad->XtoPixel(x));
7496 p.SetY(gPad->YtoPixel(y));
7497 }
7498 return p;
7499}
7500
7501////////////////////////////////////////////////////////////////////////////////
7502/// Set center of the Pad
7503
7505{
7506 if (!gPad)
7507 return;
7508 fXlowNDC = (gPad->PixeltoX(p.GetX()) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1()) - 0.5 * fWNDC;
7509 fYlowNDC =
7510 (gPad->PixeltoY(p.GetY() - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - 0.5 * fHNDC;
7511 ResizePad();
7512}
7513
7514////////////////////////////////////////////////////////////////////////////////
7515/// Set X coordinate of the center of the Pad
7516
7518{
7519 if (!gPad)
7520 return;
7521 fXlowNDC = (gPad->PixeltoX(x) - gPad->GetX1())/(gPad->GetX2()-gPad->GetX1())-0.5*fWNDC;
7522 ResizePad();
7523}
7524
7525////////////////////////////////////////////////////////////////////////////////
7526/// Set Y coordinate of the center of the Pad
7527
7529{
7530 if (!gPad)
7531 return;
7532 fYlowNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - 0.5 * fHNDC;
7533 ResizePad();
7534}
7535
7536////////////////////////////////////////////////////////////////////////////////
7537/// Set lefthandside of BoundingBox to a value
7538/// (resize in x direction on left)
7539
7541{
7542 if (!gPad)
7543 return;
7544 fXlowNDC = (gPad->PixeltoX(x) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1());
7546 ResizePad();
7547}
7548
7549////////////////////////////////////////////////////////////////////////////////
7550/// Set right hand side of BoundingBox to a value
7551/// (resize in x direction on right)
7552
7554{
7555 if (!gPad)
7556 return;
7557 fWNDC = (gPad->PixeltoX(x) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1()) - fXlowNDC;
7558 ResizePad();
7559}
7560
7561////////////////////////////////////////////////////////////////////////////////
7562/// Set top of BoundingBox to a value (resize in y direction on top)
7563
7565{
7566 if (!gPad)
7567 return;
7568 fHNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - fYlowNDC;
7569 ResizePad();
7570}
7571
7572////////////////////////////////////////////////////////////////////////////////
7573/// Set bottom of BoundingBox to a value
7574/// (resize in y direction on bottom)
7575
7577{
7578 if (!gPad)
7579 return;
7580 fYlowNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1());
7582 ResizePad();
7583}
7584
7585////////////////////////////////////////////////////////////////////////////////
7586/// Mark pad modified
7587/// Will be repainted when TCanvas::Update() will be called next time
7588
7590{
7591 if (!fModified && flag) Emit("Modified()");
7592 fModified = flag;
7593}
7594
7595////////////////////////////////////////////////////////////////////////////////
7596/// Convert absolute pixel into X/Y coordinates
7597
7603
7604
7605////////////////////////////////////////////////////////////////////////////////
7606/// Convert pixel to X coordinate
7607
7609{
7610 if (fAbsCoord) return fAbsPixeltoXk + px*fPixeltoX;
7611 else return fPixeltoXk + px*fPixeltoX;
7612}
7613
7614////////////////////////////////////////////////////////////////////////////////
7615/// Convert pixel to Y coordinate
7616
7618{
7619 if (fAbsCoord) return fAbsPixeltoYk + py*fPixeltoY;
7620 else return fPixeltoYk + py*fPixeltoY;
7621}
7622
7623////////////////////////////////////////////////////////////////////////////////
7624/// Convert pixel to X/Y coordinates
7625
7631
7632////////////////////////////////////////////////////////////////////////////////
7633/// Convert X/Y into absolute pixel coordinates - integer
7634
7640
7641////////////////////////////////////////////////////////////////////////////////
7642/// Check value for valid range for pixel values
7643
7645{
7646 return v < -kMaxPixel ? -kMaxPixel : (v > kMaxPixel ? kMaxPixel : v);
7647}
7648
7649////////////////////////////////////////////////////////////////////////////////
7650/// Convert X/Y into absolute pixel coordinates - doble
7651/// Introduced to avoid pixel rounding problems
7652
7658
7659////////////////////////////////////////////////////////////////////////////////
7660/// Convert X/Y into pixel coordinates - integer
7661
7663{
7664 xpixel = XtoPixel(x);
7665 ypixel = YtoPixel(y);
7666}
7667
7668////////////////////////////////////////////////////////////////////////////////
7669/// Convert X/Y into pixel coordinates - double
7670
7676
7677////////////////////////////////////////////////////////////////////////////////
7678/// Convert X NDC to pixel
7679
7684
7685////////////////////////////////////////////////////////////////////////////////
7686/// Convert Y NDC to pixel
7687
7692
7693////////////////////////////////////////////////////////////////////////////////
7694/// Convert X NDC to absolute pixel
7695
7700
7701////////////////////////////////////////////////////////////////////////////////
7702/// Convert Y NDC to absolute pixel
7703
7708
7709////////////////////////////////////////////////////////////////////////////////
7710/// Convert X coordinate to absolute pixel
7711
7716
7717////////////////////////////////////////////////////////////////////////////////
7718/// Convert X coordinate to pixel
7719
7724
7725////////////////////////////////////////////////////////////////////////////////
7726/// Convert Y coordinate to absolute pixel
7727
7732
7733////////////////////////////////////////////////////////////////////////////////
7734/// Convert a vertical distance [y1,y2] to pixel
7735
7737{
7738 double h1 = fYtoAbsPixelk + y1 * fYtoPixel;
7739 double h2 = fYtoAbsPixelk + y2 * fYtoPixel;
7740 return TMath::Nint(pixel_boundary(std::abs(h1 - h2)));
7741}
7742
7743////////////////////////////////////////////////////////////////////////////////
7744/// Convert a horizontal distance [x1,x2] to pixel
7745
7747{
7748 double w1 = fXtoAbsPixelk + x1 * fXtoPixel;
7749 double w2 = fXtoAbsPixelk + x2 * fXtoPixel;
7750 return TMath::Nint(pixel_boundary(std::abs(w1 - w2)));
7751}
7752
7753
7754////////////////////////////////////////////////////////////////////////////////
7755/// Convert Y coordinate to pixel
7756
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:531
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
short Style_t
Style number (short)
Definition RtypesCore.h:96
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Color_t
Color number (short)
Definition RtypesCore.h:99
float Size_t
Attribute size (float)
Definition RtypesCore.h:103
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:89
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
short Width_t
Line width (short)
Definition RtypesCore.h:98
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
@ kRed
Definition Rtypes.h:67
@ kBlack
Definition Rtypes.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gDirectory
Definition TDirectory.h:385
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
#define gFile
Definition TFile.h:439
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t cursor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t SetFillStyle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char cname
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void SetCursor
Option_t Option_t SetFillColor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Option_t Option_t style
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t button
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
char name[80]
Definition TGX11.cxx:110
const Int_t kMAXLEVELS
Definition TGeometry.h:27
float xmin
float ymin
float xmax
float ymax
#define gInterpreter
Double_t pixel_boundary(Double_t v)
Check value for valid range for pixel values.
Definition TPad.cxx:7644
static Int_t gReadLevel
Definition TPad.cxx:66
static Bool_t ContainsTImage(TList *li)
Auxiliary function.
Definition TPad.cxx:5055
#define NotFree(i, j)
Definition TPad.cxx:3414
R__EXTERN TPluginManager * gPluginMgr
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:414
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
#define gGLManager
Definition TVirtualGL.h:159
#define R__LOCKGUARD(mutex)
R__EXTERN TVirtualPS * gVirtualPS
Definition TVirtualPS.h:84
#define gPad
R__EXTERN Int_t(* gThreadXAR)(const char *xact, Int_t nb, void **ar, Int_t *iret)
#define gVirtualX
Definition TVirtualX.h:338
#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:522
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:422
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
Int_t GetNbins() const
Definition TAxis.h:127
virtual TObject * GetParent() const
Definition TAxis.h:130
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:1061
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
Each class (see TClass) has a linked list of its base class(es).
Definition TBaseClass.h:33
TClass * GetClassPointer(Bool_t load=kTRUE)
Get pointer to the base class TClass.
Create a Box.
Definition TBox.h:22
virtual void SetY2(Double_t y2)
Definition TBox.h:65
static TClass * Class()
virtual void SetX1(Double_t x1)
Definition TBox.h:62
virtual void SetX2(Double_t x2)
Definition TBox.h:63
virtual void SetY1(Double_t y1)
Definition TBox.h:64
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
Buffer base class used for serializing objects.
Definition TBuffer.h:43
A TButton object is a user interface object.
Definition TButton.h:18
static TClass * Class()
ABC describing GUI independent main window (with menubar, scrollbars and a drawing area).
Definition TCanvasImp.h:30
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:503
TExec is a utility class that can be used to execute a C++ command when some event happens in a pad.
Definition TExec.h:26
Define a Frame.
Definition TFrame.h:19
static TClass * Class()
void Paint(Option_t *option="") override
Paint this wbox with its current attributes.
Definition TFrame.cxx:127
void UseCurrentStyle() override
Replace current frame attributes by current style.
Definition TFrame.cxx:157
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
static TClass * Class()
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
@ kIsZoomed
Bit set when zooming on Y axis.
Definition TH1.h:407
static TClass * Class()
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
EImageFileTypes
Definition TImage.h:36
@ kBmp
Definition TImage.h:45
@ kPng
Definition TImage.h:40
@ kJpeg
Definition TImage.h:41
@ kXpm
Definition TImage.h:37
@ kAnimGif
Definition TImage.h:55
@ kUnknown
Definition TImage.h:54
@ kTiff
Definition TImage.h:49
@ kGif
Definition TImage.h:48
static TClass * Class()
Option_t * GetOption() const
This class displays a legend box (TPaveText) containing several legend entries.
Definition TLegend.h:23
Use the TLine constructor to create a simple line.
Definition TLine.h:22
Iterator of linked list.
Definition TList.h:196
Option_t * GetOption() const override
Returns the object option stored in the list.
Definition TList.cxx:1274
A doubly linked list.
Definition TList.h:38
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition TList.cxx:532
virtual TObjLink * LastLink() const
Definition TList.h:110
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void RecursiveRemove(TObject *obj) override
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition TList.cxx:894
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
void AddLast(TObject *obj) override
Add object at the end of the list.
Definition TList.cxx:149
TObject * Last() const override
Return the last object in the list. Returns 0 when list is empty.
Definition TList.cxx:823
virtual TObjLink * FirstLink() const
Definition TList.h:107
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
Each ROOT class (see TClass) has a linked list of methods.
Definition TMethod.h:38
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TH1F * GetHistogram()
Returns a pointer to the histogram used to draw the axis.
static TClass * Class()
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
static TClass * Class()
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:149
Mother of all ROOT objects.
Definition TObject.h:42
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Computes distance from point (px,py) to the object.
Definition TObject.cxx:284
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:458
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:990
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:903
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1075
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:422
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:882
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:544
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1089
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:502
void MakeZombie()
Definition TObject.h:55
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:626
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:75
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:70
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:72
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1063
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:3024
void PaintTextNDC(Double_t u, Double_t v, const char *text) override
Paint text in CurrentPad NDC coordinates.
Definition TPad.cxx:4861
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:2992
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:6428
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:1481
void AbsCoordinates(Bool_t set) override
Definition TPad.h:167
static TClass * Class()
Bool_t IsBatch() const override
Is pad in batch mode ?
Definition TPad.cxx:3001
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:3263
Int_t VtoPixel(Double_t v) const override
Convert Y NDC to pixel.
Definition TPad.cxx:7688
void PaintBorder(Color_t color, Bool_t tops)
Paint the pad border.
Definition TPad.cxx:3789
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:3279
void SetView(TView *view=nullptr) override
Set the current TView. Delete previous view if view=0.
Definition TPad.cxx:6396
TVirtualViewer3D * GetViewer3D(Option_t *type="") override
Create/obtain handle to 3D viewer.
Definition TPad.cxx:7352
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:4306
void PaintLine3D(Float_t *p1, Float_t *p2) override
Paint 3-D line in the CurrentPad.
Definition TPad.cxx:4503
static Int_t fgMaxPickDistance
Maximum Pick Distance.
Definition TPad.h:115
void ResizePad(Option_t *option="") override
Compute pad conversion coefficients.
Definition TPad.cxx:5876
void PaintMarker3D(Double_t x, Double_t y, Double_t z) override
Paint 3-D marker in the CurrentPad.
Definition TPad.cxx:4539
void PaintPolyMarker(Int_t n, Float_t *x, Float_t *y, Option_t *option="") override
Paint polymarker in CurrentPad World coordinates.
Definition TPad.cxx:4695
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:7455
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:4135
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:1287
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save primitives in this pad on the C++ source file out.
Definition TPad.cxx:6099
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:3696
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:7564
Int_t fTicky
Set to 1 if tick marks along Y.
Definition TPad.h:90
Int_t GetPixmapID() const override
Definition TPad.h:267
Bool_t GetGridx() const override
Definition TPad.h:236
Double_t fX2
X of upper X coordinate.
Definition TPad.h:38
Bool_t PlaceBox(TObject *o, Double_t w, Double_t h, Double_t &xl, Double_t &yb, Option_t *option="lb") override
Place a box in NDC space.
Definition TPad.cxx:3348
void SetLogz(Int_t value=1) override
Set Lin/Log scale for Z.
Definition TPad.cxx:6312
Bool_t fEmbeddedGL
!
Definition TPad.h:87
Int_t UtoAbsPixel(Double_t u) const override
Convert X NDC to absolute pixel.
Definition TPad.cxx:7696
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:7720
void SetAttFillPS(Color_t color, Style_t style) override
Set postscript fill area attributes.
Definition TPad.cxx:6405
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:7528
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:4153
~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:7302
void Close(Option_t *option="") override
Delete all primitives in pad and pad itself.
Definition TPad.cxx:1079
void AbsPixeltoXY(Double_t xpixel, Double_t ypixel, Double_t &x, Double_t &y) override
Convert absolute pixel into X/Y coordinates.
Definition TPad.cxx:7598
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:5659
UInt_t GetWw() const override
Get Ww.
Definition TPad.cxx:2982
void PaintModified() override
Traverse pad hierarchy and (re)paint only modified pads.
Definition TPad.cxx:3957
void SetEditable(Bool_t mode=kTRUE) override
Set pad editable yes/no If a pad is not editable:
Definition TPad.cxx:6256
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:3895
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:6881
void PixeltoXY(Double_t xpixel, Double_t ypixel, Double_t &x, Double_t &y) override
Convert pixel to X/Y coordinates.
Definition TPad.cxx:7626
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:7553
void SetBBoxX1(const Int_t x) override
Set lefthandside of BoundingBox to a value (resize in x direction on left)
Definition TPad.cxx:7540
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:6275
Double_t AbsPixeltoY(Double_t py) override
Definition TPad.h:169
TH1F * DrawFrame(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, const char *title="") override
Draw an empty pad frame with X and Y axis.
Definition TPad.cxx:1818
Double_t fVtoPixel
ypixel = fVtoPixelk + fVtoPixel*vndc
Definition TPad.h:53
TCanvasImp * GetCanvasImp() const override
Get canvas implementation pointer if any.
Definition TPad.cxx:2891
Int_t GetEvent() const override
Get Event.
Definition TPad.cxx:2899
Double_t PadtoX(Double_t x) const override
Convert x from pad to X.
Definition TPad.cxx:3687
virtual void DrawCrosshair()
Function called to draw a crosshair in the canvas.
Definition TPad.cxx:1745
Double_t YtoPad(Double_t y) const override
Convert y from Y to pad.
Definition TPad.cxx:3717
virtual void RangeChanged()
Definition TPad.h:321
Double_t fUymin
Minimum value on the Y axis.
Definition TPad.h:75
void SetPad(const char *name, const char *title, Double_t xlow, Double_t ylow, Double_t xup, Double_t yup, Color_t color=35, Short_t bordersize=5, Short_t bordermode=-1) override
Set all pad parameters.
Definition TPad.cxx:6372
void SetCursor(ECursor cursor) override
Set cursor type.
Definition TPad.cxx:3056
Int_t GetCanvasID() const override
Get canvas identifier.
Definition TPad.cxx:2883
Int_t fLogz
(=0 if Z linear scale, =1 if log scale)
Definition TPad.h:93
Int_t HtoAbsPixel(Double_t y1, Double_t y2) const override
Convert a vertical distance [y1,y2] to pixel.
Definition TPad.cxx:7736
void XYtoPixel(Double_t x, Double_t y, Int_t &xpixel, Int_t &ypixel) const override
Convert X/Y into pixel coordinates - integer.
Definition TPad.cxx:7662
Double_t fYtoPixelk
Conversion coefficient for Y World to pixel.
Definition TPad.h:45
void UpdateAsync() override
Asynchronous pad update.
Definition TPad.cxx:3092
TPad()
Pad default constructor.
Definition TPad.cxx:130
void UseCurrentStyle() override
Force a copy of current style for all objects in pad.
Definition TPad.cxx:7128
static Int_t GetMaxPickDistance()
Static function (see also TPad::SetMaxPickDistance)
Definition TPad.cxx:2939
Int_t VtoAbsPixel(Double_t v) const override
Convert Y NDC to absolute pixel.
Definition TPad.cxx:7704
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:5583
Double_t fUtoPixelk
Conversion coefficient for U NDC to pixel.
Definition TPad.h:49
void XYtoAbsPixel(Double_t x, Double_t y, Int_t &xpixel, Int_t &ypixel) const override
Convert X/Y into absolute pixel coordinates - integer.
Definition TPad.cxx:7635
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:2915
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:7248
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:6440
Bool_t fModified
Set to true when pad is modified.
Definition TPad.h:99
Double_t PixeltoY(Double_t py) override
Convert pixel to Y coordinate.
Definition TPad.cxx:7617
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:4905
void Update() override
Update pad.
Definition TPad.cxx:3080
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:4210
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:7757
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:4460
Int_t GetGLDevice() override
Get GL device.
Definition TPad.cxx:7439
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:7447
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:3885
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:6301
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:2501
void HighLight(Color_t col=kRed, Bool_t set=kTRUE) override
Highlight pad.
Definition TPad.cxx:3200
Double_t AbsPixeltoX(Double_t px) override
Definition TPad.h:168
void SetBatch(Bool_t batch=kTRUE) override
Set pad in batch mode.
Definition TPad.cxx:3040
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:7334
Bool_t HasCrosshair() const override
Return kTRUE if the crosshair has been activated (via SetCrosshair).
Definition TPad.cxx:6843
Bool_t IsRetained() const override
Is pad retained ?
Definition TPad.cxx:3009
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:3324
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:4162
void Modified(Bool_t flag=true) override
Mark pad modified Will be repainted when TCanvas::Update() will be called next time.
Definition TPad.cxx:7589
void RecursiveRemove(TObject *obj) override
Recursively remove object from a pad and its sub-pads.
Definition TPad.cxx:5641
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:1386
Bool_t HasFixedAspectRatio() const override
Definition TPad.h:271
void CloseToolTip(TObject *tip) override
Hide tool tip.
Definition TPad.cxx:7324
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:6891
void PaintPolyLine(Int_t n, Float_t *x, Float_t *y, Option_t *option="") override
Paint polyline in CurrentPad World coordinates.
Definition TPad.cxx:4562
Int_t WtoAbsPixel(Double_t x1, Double_t x2) const override
Convert a horizontal distance [x1,x2] to pixel.
Definition TPad.cxx:7746
void ls(Option_t *option="") const override
List all primitives in pad.
Definition TPad.cxx:3235
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:3675
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:2965
void SetAttLinePS(Color_t color, Style_t style, Width_t lwidth) override
Set postscript line attributes.
Definition TPad.cxx:6416
TClass * IsA() const override
Definition TPad.h:428
virtual void Resized()
Definition TPad.h:328
TVirtualPad * GetVirtCanvas() const override
Get virtual canvas.
Definition TPad.cxx:2923
void DeleteExec(const char *name) override
Remove TExec name from the list of Execs.
Definition TPad.cxx:1167
void PaintSegments(Int_t n, Double_t *x, Double_t *y, Option_t *option="") override
Paint N individual segments Provided arrays should have 2*n elements IMPORTANT! Provided arrays can b...
Definition TPad.cxx:4759
void Streamer(TBuffer &) override
Stream a class object.
Definition TPad.cxx:6914
void PaintSegmentsNDC(Int_t n, Double_t *u, Double_t *v) override
Paint N individual segments in NDC coordinates Provided arrays should have 2*n elements IMPORTANT!...
Definition TPad.cxx:4800
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:7680
TPoint GetBBoxCenter() override
Return the center of the Pad as TPoint in pixels.
Definition TPad.cxx:7489
void FillCollideGridTFrame(TObject *o)
Definition TPad.cxx:3479
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:3419
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:1926
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:3048
Int_t GetLogz() const override
Definition TPad.h:259
virtual void AutoExec()
Execute the list of Execs when a pad event occurs.
Definition TPad.cxx: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:3505
void SetFixedAspectRatio(Bool_t fixed=kTRUE) override
Fix pad aspect ratio to current value if fixed is true.
Definition TPad.cxx:6232
Short_t GetBorderSize() const override
Definition TPad.h:201
void RedrawAxis(Option_t *option="") override
Redraw the frame axis.
Definition TPad.cxx:5702
void DrawDist(Rectangle_t aBBox, Rectangle_t bBBox, char mode)
Draw Arrows to indicated equal distances of Objects with given BBoxes.
Definition TPad.cxx:6467
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:7728
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:4253
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:5621
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:7313
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:2974
TCanvas * GetCanvas() const override
Definition TPad.h:263
Short_t fBorderSize
pad bordersize in pixels
Definition TPad.h:97
void Add(TObject *obj, Option_t *opt="", Bool_t modified=kTRUE) override
Add an object to list of primitives with specified draw option When.
Definition TPad.cxx: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:7472
void Paint(Option_t *option="") override
Paint all primitives in pad.
Definition TPad.cxx:3729
void FillCollideGridTBox(TObject *o)
Definition TPad.cxx:3462
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:3618
TString fName
Pad name.
Definition TPad.h:109
void SetVertical(Bool_t vert=kTRUE) override
Set pad vertical (default) or horizontal.
Definition TPad.cxx:6905
void FillCollideGridTH1(TObject *o)
Definition TPad.cxx:3536
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:3166
void PaintText(Double_t x, Double_t y, const char *text) override
Paint text in CurrentPad World coordinates.
Definition TPad.cxx:4821
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:1863
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:6036
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:2845
Color_t GetHighLightColor() const override
Get highlight color.
Definition TPad.cxx:2931
Bool_t OpaqueResizing() const override
Is pad resizing in opaque mode ?
Definition TPad.cxx:3032
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:4483
void Print(const char *filename="") const override
This method is equivalent to SaveAs("filename"). See TPad::SaveAs for details.
Definition TPad.cxx:5046
Int_t GetEventX() const override
Get X event.
Definition TPad.cxx:2907
TFrame * GetFrame() override
Get frame.
Definition TPad.cxx:3100
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:7463
void Draw(Option_t *option="") override
Draw Pad in Current pad (re-parent pad if necessary).
Definition TPad.cxx:1504
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:6551
Int_t GetCrosshair() const
Return the crosshair type (from the mother canvas) crosshair type = 0 means no crosshair.
Definition TPad.cxx:6852
void GetRangeAxis(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) override
Return pad axis coordinates range.
Definition TPad.cxx:3188
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:4041
void DrawClassObject(const TObject *obj, Option_t *option="") override
Draw class inheritance tree of the class to which obj belongs.
Definition TPad.cxx:1543
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:3128
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:7504
Bool_t IsWeb() const override
Is web ?
Definition TPad.cxx:3016
void SetSelected(TObject *obj) override
Set selected.
Definition TPad.cxx:3072
TObject * GetSelected() const override
Get selected.
Definition TPad.cxx:2947
void GetRange(Double_t &x1, Double_t &y1, Double_t &x2, Double_t &y2) override
Return pad world coordinates range.
Definition TPad.cxx:3177
Double_t PixeltoX(Double_t px) override
Convert pixel to X coordinate.
Definition TPad.cxx:7608
void PaintPolyLineNDC(Int_t n, Double_t *x, Double_t *y, Option_t *option="") override
Paint polyline in CurrentPad NDC coordinates.
Definition TPad.cxx:4660
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:3249
void PaintPadFrame(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax) override
Paint histogram/graph frame.
Definition TPad.cxx:3938
Double_t GetAbsYlowNDC() const override
Definition TPad.h:222
Double_t fUxmax
Maximum value on the X axis.
Definition TPad.h:76
void AddFirst(TObject *obj, Option_t *opt="", Bool_t modified=kTRUE) override
Add an object as first in list of primitives with specified draw option When.
Definition TPad.cxx:437
Double_t fY2
Y of upper Y coordinate.
Definition TPad.h:39
void PaintTextUrl(Double_t x, Double_t y, const char *text, const char *url) override
Paint text with URL in CurrentPad World coordinates.
Definition TPad.cxx:4847
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:2956
void PaintPolyLine3D(Int_t n, Double_t *p) override
Paint 3-D polyline in the CurrentPad.
Definition TPad.cxx:4681
TVirtualPad * GetPad(Int_t subpadnumber) const override
Get a pointer to subpadnumber of this pad.
Definition TPad.cxx:3145
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:6287
void ReleaseViewer3D(Option_t *type="") override
Release current (external) viewer.
Definition TPad.cxx:7423
void SetCrosshair(Int_t crhair=1) override
Set crosshair active/inactive.
Definition TPad.cxx:6865
void SetDoubleBuffer(Int_t mode=1) override
Set double buffer mode ON or OFF.
Definition TPad.cxx:3064
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:7517
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:7292
@ 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:5024
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:7712
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:7576
Double_t XtoPad(Double_t x) const override
Convert x from X to pad.
Definition TPad.cxx:3705
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:2894
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:2902
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2751
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
TString & ReplaceSpecialCppChars()
Find special characters which are typically used in printf() calls and replace them by appropriate es...
Definition TString.cxx:1121
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:703
const char * Data() const
Definition TString.h:384
virtual void Streamer(TBuffer &)
Stream a string object.
Definition TString.cxx:1418
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2384
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2362
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:660
Int_t GetOptLogy() const
Definition TStyle.h:250
void SetPadBorderMode(Int_t mode=1)
Definition TStyle.h:361
void SetPadTopMargin(Float_t margin=0.1)
Definition TStyle.h:363
void SetOptLogx(Int_t logx=1)
Definition TStyle.h:333
void SetPadBottomMargin(Float_t margin=0.1)
Definition TStyle.h:362
Int_t GetOptTitle() const
Definition TStyle.h:248
Int_t GetPadTickX() const
Definition TStyle.h:219
Bool_t IsReading() const
Definition TStyle.h:300
Color_t GetPadColor() const
Definition TStyle.h:210
void SetPadRightMargin(Float_t margin=0.1)
Definition TStyle.h:365
void SetTitleFont(Style_t font=62, Option_t *axis="X")
Definition TStyle.cxx:1776
Float_t GetPadRightMargin() const
Definition TStyle.h:216
void SetTitleBorderSize(Width_t size=2)
Definition TStyle.h:412
Float_t GetDateX() const
Definition TStyle.h:199
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1217
void SetPadTickY(Int_t ticky)
Definition TStyle.h:369
Color_t GetTitleFillColor() const
Definition TStyle.h:273
void SetPadTickX(Int_t tickx)
Definition TStyle.h:368
Int_t GetOptDate() const
Definition TStyle.h:244
Bool_t GetPadGridY() const
Definition TStyle.h:218
void SetPadGridX(Bool_t gridx)
Definition TStyle.h:366
void SetTitleTextColor(Color_t color=1)
Definition TStyle.h:409
Float_t GetPadLeftMargin() const
Definition TStyle.h:215
Double_t GetHatchesSpacing() const
Definition TStyle.h:203
Bool_t GetPadGridX() const
Definition TStyle.h:217
void SetPadLeftMargin(Float_t margin=0.1)
Definition TStyle.h:364
void SetPadGridY(Bool_t gridy)
Definition TStyle.h:367
void SetOptLogy(Int_t logy=1)
Definition TStyle.h:334
Int_t GetOptFile() const
Definition TStyle.h:245
TAttText * GetAttDate()
Definition TStyle.h:170
Int_t GetPadTickY() const
Definition TStyle.h:220
Width_t GetPadBorderSize() const
Definition TStyle.h:211
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
void SetTitleFillColor(Color_t color=1)
Definition TStyle.h:408
Float_t GetPadBottomMargin() const
Definition TStyle.h:213
void SetOptLogz(Int_t logz=1)
Definition TStyle.h:335
void SetPadColor(Color_t color=19)
Definition TStyle.h:359
Color_t GetTitleTextColor() const
Definition TStyle.h:274
Int_t GetOptLogx() const
Definition TStyle.h:249
Float_t GetDateY() const
Definition TStyle.h:200
Int_t GetPadBorderMode() const
Definition TStyle.h:212
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1176
Int_t GetOptLogz() const
Definition TStyle.h:251
void SetPadBorderSize(Width_t size=1)
Definition TStyle.h:360
Int_t GetHatchesLineWidth() const
Definition TStyle.h:202
Float_t GetPadTopMargin() const
Definition TStyle.h:214
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1285
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition TSystem.cxx:651
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1307
virtual int Rename(const char *from, const char *to)
Rename a file.
Definition TSystem.cxx:1361
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:435
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:414
Base class for several text objects.
Definition TText.h:22
void Paint(Option_t *option="") override
Paint this text with its current attributes.
Definition TText.cxx:686
virtual void SetNDC(Bool_t isNDC=kTRUE)
Set NDC mode on if isNDC = kTRUE, off otherwise.
Definition TText.cxx:816
See TView3D.
Definition TView.h:25
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual void ResizePad()=0
virtual void GetRange(Float_t *min, Float_t *max)=0
Provides 3D viewer interface (TVirtualViewer3D) support on a pad.
TVirtualPS is an abstract interface to Postscript, PDF, SVG.
Definition TVirtualPS.h:30
virtual void 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 DrawSegments(Int_t n, Double_t *xw, Double_t *yw)
Print N segments.
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
virtual void TextUrl(Double_t x, Double_t y, const char *string, const char *url)=0
To make it possible to use GL for 2D graphic in a TPad/TCanvas.
virtual void DrawSegmentsNDC(Int_t n, const Double_t *u, const Double_t *v)
Draw N segments in NDC coordinates on the pad Exclude segments where both points match.
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 DrawSegments(Int_t n, const Double_t *x, const Double_t *y)
Draw N segments on the pad Exclude segments where both points match.
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
TH1F * h1
Definition legend1.C:5
leg
Definition legend1.C:34
R__ALWAYS_INLINE bool HasBeenDeleted(const TObject *obj)
Check if the TObject's memory has been deleted.
Definition TObject.h:407
void CallRecursiveRemoveIfNeeded(TObject &obj)
call RecursiveRemove for obj if gROOT is valid and obj.TestBit(kMustCleanup) is true.
Definition TROOT.h:403
Bool_t IsNaN(Double_t x)
Definition TMath.h:903
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:704
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t Exp(Double_t x)
Returns the base-e exponential function of x, which is e raised to the power x.
Definition TMath.h:720
Double_t Floor(Double_t x)
Rounds x downward, returning the largest integral value that is not greater than x.
Definition TMath.h:691
Double_t Ceil(Double_t x)
Rounds x upward, returning the smallest integral value that is not less than x.
Definition TMath.h:679
Int_t Finite(Double_t x)
Check if it is finite with a mask in order to be consistent in presence of fast math.
Definition TMath.h:781
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:767
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:732
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:605
constexpr Double_t Pi()
Definition TMath.h:40
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:773
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
void inv(rsa_NUMBER *, rsa_NUMBER *, rsa_NUMBER *)
Definition rsaaux.cxx:949
Rectangle structure (maps to the X11 XRectangle structure)
Definition GuiTypes.h: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:6520
TAttBBox2D * fb
Definition TPad.cxx:6522
dField()
Definition TPad.cxx:6527
char fdir
Definition TPad.cxx:6524
dField(TAttBBox2D *a, TAttBBox2D *b, Int_t dist, char direction)
Definition TPad.cxx:6531
TAttBBox2D * fa
Definition TPad.cxx:6521
Int_t fdist
Definition TPad.cxx:6523
TMarker m
Definition textangle.C:8