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