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