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