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