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 "TVirtualX.h"
34#include "TVirtualViewer3D.h"
35#include "TView.h"
36#include "TPoint.h"
37#include "TGraph.h"
38#include "TMultiGraph.h"
39#include "THStack.h"
40#include "TPaveText.h"
41#include "TPaveStats.h"
42#include "TGroupButton.h"
43#include "TBrowser.h"
44#include "TVirtualGL.h"
45#include "TString.h"
46#include "TDataMember.h"
47#include "TMethod.h"
48#include "TDataType.h"
49#include "TFrame.h"
50#include "TWbox.h"
51#include "TExec.h"
52#include "TDatime.h"
53#include "TColor.h"
54#include "TCanvas.h"
55#include "TCanvasImp.h"
56#include "TPluginManager.h"
57#include "TEnv.h"
58#include "TImage.h"
59#include "TViewer3DPad.h"
60#include "TCreatePrimitives.h"
61#include "TLegend.h"
62#include "TAtt3D.h"
63#include "TVirtualPadPainter.h"
64#include "strlcpy.h"
65#include "snprintf.h"
66
67#include "TVirtualMutex.h"
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 subpoads", 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) {
1860 Double_t dx = (xmaxl-xminl)/nbins;
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
1963 HideToolTip(event);
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:
1973 TCreatePrimitives::Pad(event,px,py,0);
1974 break;
1975 case kMarker:
1976 case kText:
1977 TCreatePrimitives::Text(event,px,py,newcode);
1978 break;
1979 case kLine:
1980 TCreatePrimitives::Line(event,px,py,kLine);
1981 break;
1982 case kArrow:
1983 TCreatePrimitives::Line(event,px,py,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:
1998 TCreatePrimitives::Ellipse(event,px,py,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:
2009 TCreatePrimitives::Pave(event,px,py,newcode);
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 trnasformation 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 trnasformation 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 if (opt.Index("pfc")>=0 || opt.Index("plc")>=0 || opt.Index("pmc")>=0) {
3135 if (i==1) fNumPaletteColor++;
3136 else fNumPaletteColor = i;
3137 return fNumPaletteColor;
3138 } else {
3139 return 0;
3140 }
3141}
3142
3143////////////////////////////////////////////////////////////////////////////////
3144/// Get the next autocolor in the pad.
3145
3147{
3148 Int_t i = 0;
3150 if (fNumPaletteColor>1) {
3152 if (i>=ncolors) i = ncolors-1;
3153 }
3156 return gStyle->GetColorPalette(i);
3157}
3158
3159////////////////////////////////////////////////////////////////////////////////
3160/// Initialise the grid used to find empty space when adding a box (Legend) in a pad
3161
3163{
3164 Int_t const cellSize = 10; // Size of an individual grid cell in pixels.
3165
3166 fCGnx = GetWw()/cellSize;
3167 fCGny = GetWh()/cellSize;
3168
3169 // Initialise the collide grid
3170 fCollideGrid.resize(fCGnx*fCGny);
3171 for (int i = 0; i < fCGnx; i++)
3172 for (int j = 0; j < fCGny; j++)
3173 fCollideGrid[i + j * fCGnx] = kTRUE;
3174
3175 // Fill the collide grid
3176 TIter iter(GetListOfPrimitives());
3177
3178 while(auto o = iter()) {
3179 if (o == oi)
3180 continue;
3181 if (o->InheritsFrom(TFrame::Class()))
3183 else if (o->InheritsFrom(TBox::Class()))
3185 else if (o->InheritsFrom(TH1::Class()))
3187 else if (o->InheritsFrom(TGraph::Class()))
3189 else if (o->InheritsFrom(TMultiGraph::Class())) {
3190 TIter nextgraph(((TMultiGraph *)o)->GetListOfGraphs());
3191 while (auto og = nextgraph())
3193 } else if (o->InheritsFrom(THStack::Class())) {
3194 TIter nexthist(((THStack *)o)->GetHists());
3195 while (auto oh = nexthist()) {
3196 if (oh->InheritsFrom(TH1::Class()))
3198 }
3199 }
3200 }
3201}
3202
3203////////////////////////////////////////////////////////////////////////////////
3204/// Check if a box of size w and h collide some primitives in the pad at
3205/// position i,j
3206
3208{
3209 for (int r = i; r < w + i; r++) {
3210 for (int c = j; c < h + j; c++) {
3211 if (!fCollideGrid[r + c * fCGnx])
3212 return kTRUE;
3213 }
3214 }
3215 return kFALSE;
3216}
3217
3218////////////////////////////////////////////////////////////////////////////////
3219/// Place a box in NDC space
3220///
3221/// \return `true` if the box could be placed, `false` if not.
3222///
3223/// \param[in] o pointer to the box to be placed
3224/// \param[in] w box width to be placed
3225/// \param[in] h box height to be placed
3226/// \param[out] xl x position of the bottom left corner of the placed box
3227/// \param[out] yb y position of the bottom left corner of the placed box
3228/// \param[in] option l=left, r=right, t=top, b=bottom, w=within margins. Order determines
3229/// priority for placement. Default is "lb" (prioritises horizontal over vertical)
3230
3232{
3233 FillCollideGrid(o);
3234
3235 Int_t iw = (int)(fCGnx*w);
3236 Int_t ih = (int)(fCGny*h);
3237
3238 Int_t nxbeg = 0;
3239 Int_t nybeg = 0;
3240 Int_t nxend = fCGnx-iw-1;
3241 Int_t nyend = fCGny-ih-1;
3242 Int_t dx = 1;
3243 Int_t dy = 1;
3244
3245 bool isFirstVertical = false;
3246 bool isFirstHorizontal = false;
3247
3248 for (std::size_t i = 0; option[i] != '\0'; ++i) {
3249 char letter = std::tolower(option[i]);
3250 if (letter == 'w') {
3255 } else if (letter == 't' || letter == 'b') {
3257 // go from top to bottom instead of bottom to top
3258 dy = letter == 't' ? -1 : 1;
3259 } else if (letter == 'l' || letter == 'r') {
3261 // go from right to left instead of left to right
3262 dx = letter == 'r' ? -1 : 1;
3263 }
3264 }
3265
3266 if(dx < 0) std::swap(nxbeg, nxend);
3267 if(dy < 0) std::swap(nybeg, nyend);
3268
3269 auto attemptPlacement = [&](Int_t i, Int_t j) {
3270 if (Collide(i, j, iw, ih)) {
3271 return false;
3272 } else {
3273 xl = (Double_t)(i) / (Double_t)(fCGnx);
3274 yb = (Double_t)(j) / (Double_t)(fCGny);
3275 return true;
3276 }
3277 };
3278
3279 if(!isFirstVertical) {
3280 for (Int_t i = nxbeg; i != nxend; i += dx) {
3281 for (Int_t j = nybeg; j != nyend; j += dy) {
3282 if (attemptPlacement(i, j)) return true;
3283 }
3284 }
3285 } else {
3286 // prioritizing vertical over horizontal
3287 for (Int_t j = nybeg; j != nyend; j += dy) {
3288 for (Int_t i = nxbeg; i != nxend; i += dx) {
3289 if (attemptPlacement(i, j)) return true;
3290 }
3291 }
3292 }
3293
3294 return kFALSE;
3295}
3296
3297#define NotFree(i, j) fCollideGrid[TMath::Max(TMath::Min(i+j*fCGnx,fCGnx*fCGny),0)] = kFALSE;
3298
3299////////////////////////////////////////////////////////////////////////////////
3300/// Mark as "not free" the cells along a line.
3301
3303{
3304 NotFree(x1, y1);
3305 NotFree(x2, y2);
3306 Int_t i, j, xt, yt;
3307
3308 // horizontal lines
3309 if (y1==y2) {
3310 for (i=x1+1; i<x2; i++) NotFree(i,y1);
3311 return;
3312 }
3313
3314 // vertical lines
3315 if (x1==x2) {
3316 for (i=y1+1; i<y2; i++) NotFree(x1,i);
3317 return;
3318 }
3319
3320 // other lines
3321 if (TMath::Abs(x2-x1)>TMath::Abs(y2-y1)) {
3322 if (x1>x2) {
3323 xt = x1; x1 = x2; x2 = xt;
3324 yt = y1; y1 = y2; y2 = yt;
3325 }
3326 for (i=x1+1; i<x2; i++) {
3327 j = (Int_t)((Double_t)(y2-y1)*(Double_t)((i-x1)/(Double_t)(x2-x1))+y1);
3328 NotFree(i,j);
3329 NotFree(i,(j+1));
3330 }
3331 } else {
3332 if (y1>y2) {
3333 yt = y1; y1 = y2; y2 = yt;
3334 xt = x1; x1 = x2; x2 = xt;
3335 }
3336 for (j=y1+1; j<y2; j++) {
3337 i = (Int_t)((Double_t)(x2-x1)*(Double_t)((j-y1)/(Double_t)(y2-y1))+x1);
3338 NotFree(i,j);
3339 NotFree((i+1),j);
3340 }
3341 }
3342}
3343
3344////////////////////////////////////////////////////////////////////////////////
3346{
3347 TBox *b = (TBox *)o;
3348 if (fCGnx==0||fCGny==0) return;
3349 Double_t xs = (fX2-fX1)/fCGnx;
3350 Double_t ys = (fY2-fY1)/fCGny;
3351
3352 Int_t x1 = (Int_t)((b->GetX1()-fX1)/xs);
3353 Int_t x2 = (Int_t)((b->GetX2()-fX1)/xs);
3354 Int_t y1 = (Int_t)((b->GetY1()-fY1)/ys);
3355 Int_t y2 = (Int_t)((b->GetY2()-fY1)/ys);
3356 for (int i = x1; i<=x2; i++) {
3357 for (int j = y1; j<=y2; j++) NotFree(i, j);
3358 }
3359}
3360
3361////////////////////////////////////////////////////////////////////////////////
3363{
3364 TFrame *f = (TFrame *)o;
3365 if (fCGnx==0||fCGny==0) return;
3366 Double_t xs = (fX2-fX1)/fCGnx;
3367 Double_t ys = (fY2-fY1)/fCGny;
3368
3369 Int_t x1 = (Int_t)((f->GetX1()-fX1)/xs);
3370 Int_t x2 = (Int_t)((f->GetX2()-fX1)/xs);
3371 Int_t y1 = (Int_t)((f->GetY1()-fY1)/ys);
3372 Int_t y2 = (Int_t)((f->GetY2()-fY1)/ys);
3373 Int_t i;
3374
3375 for (i = x1; i<=x2; i++) {
3376 NotFree(i, y1);
3377 NotFree(i, (y1-1));
3378 NotFree(i, (y1-2));
3379 }
3380 for (i = y1; i<=y2; i++) {
3381 NotFree(x1, i);
3382 NotFree((x1-1), i);
3383 NotFree((x1-2), i);
3384 }
3385}
3386
3387////////////////////////////////////////////////////////////////////////////////
3389{
3390 TGraph *g = (TGraph *)o;
3391 if (fCGnx==0||fCGny==0) return;
3392 Double_t xs = (fX2-fX1)/fCGnx;
3393 Double_t ys = (fY2-fY1)/fCGny;
3394
3395 Int_t n = g->GetN();
3396 Int_t s = TMath::Max(n/10,1);
3397 Double_t x1, x2, y1, y2;
3398 for (Int_t i=s; i<n; i=i+s) {
3399 g->GetPoint(TMath::Max(0,i-s),x1,y1);
3400 g->GetPoint(i ,x2,y2);
3401 if (fLogx) {
3402 if (x1 > 0) x1 = TMath::Log10(x1);
3403 else x1 = fUxmin;
3404 if (x2 > 0) x2 = TMath::Log10(x2);
3405 else x2 = fUxmin;
3406 }
3407 if (fLogy) {
3408 if (y1 > 0) y1 = TMath::Log10(y1);
3409 else y1 = fUymin;
3410 if (y2 > 0) y2 = TMath::Log10(y2);
3411 else y2 = fUymin;
3412 }
3413 LineNotFree((int)((x1-fX1)/xs), (int)((x2-fX1)/xs),
3414 (int)((y1-fY1)/ys), (int)((y2-fY1)/ys));
3415 }
3416}
3417
3418////////////////////////////////////////////////////////////////////////////////
3420{
3421 TH1 *h = (TH1 *)o;
3422 if (fCGnx==0||fCGny==0) return;
3423 if (o->InheritsFrom(TH2::Class())) return;
3424 if (o->InheritsFrom(TH3::Class())) return;
3425
3426 TString name = h->GetName();
3427 if (name.Index("hframe") >= 0) return;
3428
3429 Double_t xs = (fX2-fX1)/fCGnx;
3430 Double_t ys = (fY2-fY1)/fCGny;
3431
3432 bool haserrors = false;
3433 TString drawOption = h->GetDrawOption();
3434 drawOption.ToLower();
3435 drawOption.ReplaceAll("same","");
3436
3437 if (drawOption.Index("hist") < 0) {
3438 if (drawOption.Index("e") >= 0) haserrors = true;
3439 }
3440
3441 Int_t nx = h->GetNbinsX();
3442 Int_t x1, y1, y2;
3443 Int_t i, j;
3444 Double_t x1l, y1l, y2l;
3445
3446 for (i = 1; i<nx; i++) {
3447 if (haserrors) {
3448 x1l = h->GetBinCenter(i);
3449 if (fLogx) {
3450 if (x1l > 0) x1l = TMath::Log10(x1l);
3451 else x1l = fUxmin;
3452 }
3453 x1 = (Int_t)((x1l-fX1)/xs);
3454 y1l = h->GetBinContent(i)-h->GetBinErrorLow(i);
3455 if (fLogy) {
3456 if (y1l > 0) y1l = TMath::Log10(y1l);
3457 else y1l = fUymin;
3458 }
3459 y1 = (Int_t)((y1l-fY1)/ys);
3460 y2l = h->GetBinContent(i)+h->GetBinErrorUp(i);
3461 if (fLogy) {
3462 if (y2l > 0) y2l = TMath::Log10(y2l);
3463 else y2l = fUymin;
3464 }
3465 y2 = (Int_t)((y2l-fY1)/ys);
3466 for (j=y1; j<y2; j++) {
3467 NotFree(x1, j);
3468 }
3469 }
3470 x1l = h->GetBinLowEdge(i);
3471 if (fLogx) {
3472 if (x1l > 0) x1l = TMath::Log10(x1l);
3473 else x1l = fUxmin;
3474 }
3475 x1 = (Int_t)((x1l-fX1)/xs);
3476 y1l = h->GetBinContent(i);
3477 if (fLogy) {
3478 if (y1l > 0) y1l = TMath::Log10(y1l);
3479 else y1l = fUymin;
3480 }
3481 y1 = (Int_t)((y1l-fY1)/ys);
3482 NotFree(x1, y1);
3483 x1l = h->GetBinLowEdge(i)+h->GetBinWidth(i);
3484 if (fLogx) {
3485 if (x1l > 0) x1l = TMath::Log10(x1l);
3486 else x1l = fUxmin;
3487 }
3488 x1 = (int)((x1l-fX1)/xs);
3489 NotFree(x1, y1);
3490 }
3491
3492 // Extra objects in the list of function
3493 TPaveStats *ps = (TPaveStats*)h->GetListOfFunctions()->FindObject("stats");
3494 if (ps) FillCollideGridTBox(ps);
3495}
3496
3497////////////////////////////////////////////////////////////////////////////////
3498/// This method draws the collide grid on top of the canvas. This is used for
3499/// debugging only. At some point it will be removed.
3500
3502{
3503 if (fCGnx==0||fCGny==0) return;
3504
3505 TContext ctxt(this, kTRUE);
3506
3507 TBox box;
3508 box.SetFillColorAlpha(kRed,0.5);
3509
3510 Double_t xs = (fX2-fX1)/fCGnx;
3511 Double_t ys = (fY2-fY1)/fCGny;
3512
3513 Double_t X1L, X2L, Y1L, Y2L;
3514 Double_t t = 0.15;
3515 Double_t Y1, Y2;
3516 Double_t X1 = fX1;
3517 Double_t X2 = X1+xs;
3518
3519 for (int i = 0; i<fCGnx; i++) {
3520 Y1 = fY1;
3521 Y2 = Y1+ys;
3522 for (int j = 0; j<fCGny; j++) {
3523 if (GetLogx()) {
3524 X1L = TMath::Power(10,X1);
3525 X2L = TMath::Power(10,X2);
3526 } else {
3527 X1L = X1;
3528 X2L = X2;
3529 }
3530 if (GetLogy()) {
3531 Y1L = TMath::Power(10,Y1);
3532 Y2L = TMath::Power(10,Y2);
3533 } else {
3534 Y1L = Y1;
3535 Y2L = Y2;
3536 }
3537 if (!fCollideGrid[i + j*fCGnx]) {
3538 box.SetFillColorAlpha(kBlack,t);
3539 box.DrawBox(X1L, Y1L, X2L, Y2L);
3540 } else {
3541 box.SetFillColorAlpha(kRed,t);
3542 box.DrawBox(X1L, Y1L, X2L, Y2L);
3543 }
3544 Y1 = Y2;
3545 Y2 = Y1+ys;
3546 if (t==0.15) t = 0.1;
3547 else t = 0.15;
3548 }
3549 X1 = X2;
3550 X2 = X1+xs;
3551 }
3552}
3553
3554////////////////////////////////////////////////////////////////////////////////
3555/// Short cut to call Modified() and Update() in a single call.
3556/// On Mac with Cocoa, it performs an additional ProcessEvents().
3557
3559{
3560 Modified();
3561 Update();
3562#ifdef R__HAS_COCOA
3564#endif
3565}
3566
3567////////////////////////////////////////////////////////////////////////////////
3568/// Convert x from pad to X.
3569
3571{
3572 if (fLogx && x < 50) return Double_t(TMath::Exp(2.302585092994*x));
3573 return x;
3574}
3575
3576////////////////////////////////////////////////////////////////////////////////
3577/// Convert y from pad to Y.
3578
3580{
3581 if (fLogy && y < 50) return Double_t(TMath::Exp(2.302585092994*y));
3582 return y;
3583}
3584
3585////////////////////////////////////////////////////////////////////////////////
3586/// Convert x from X to pad.
3587
3589{
3590 if (fLogx) {
3591 if (x > 0) x = TMath::Log10(x);
3592 else x = fUxmin;
3593 }
3594 return x;
3595}
3596
3597////////////////////////////////////////////////////////////////////////////////
3598/// Convert y from Y to pad.
3599
3601{
3602 if (fLogy) {
3603 if (y > 0) y = TMath::Log10(y);
3604 else y = fUymin;
3605 }
3606 return y;
3607}
3608
3609////////////////////////////////////////////////////////////////////////////////
3610/// Paint all primitives in pad.
3611
3612void TPad::Paint(Option_t * /*option*/)
3613{
3614 if (!fPrimitives)
3615 fPrimitives = new TList;
3617 fViewer3D->PadPaint(this);
3619 if (GetGLDevice()!=-1 && gVirtualPS) {
3620 TContext ctxt(this, kFALSE);
3621 if (gGLManager) gGLManager->PrintViewer(GetViewer3D());
3622 }
3623 return;
3624 }
3625
3626 TVirtualPadPainter *oldpp = nullptr;
3628
3629 if (fCanvas) {
3630 // check if special PS painter should be assigned to TCanvas
3633 }
3634
3636 fPadPaint = 1;
3637
3638 {
3639 TContext ctxt(this, kTRUE);
3640
3642 PaintDate();
3643
3644 auto lnk = GetListOfPrimitives()->FirstLink();
3645
3646 while (lnk) {
3647 TObject *obj = lnk->GetObject();
3648
3649 // Create a pad 3D viewer if none exists and we encounter a 3D shape
3650 if (!fViewer3D && obj->InheritsFrom(TAtt3D::Class())) {
3651 GetViewer3D("pad");
3652 }
3653
3654 // Open a 3D scene if required
3655 if (fViewer3D && !fViewer3D->BuildingScene()) {
3658 }
3659
3660 obj->Paint(lnk->GetOption());
3661 lnk = lnk->Next();
3662 }
3663
3664 if (fCanvas && (fCanvas->fHilightPadBorder == this)) {
3665 auto col = GetHighLightColor();
3666 if (col > 0) PaintBorder(-col, kTRUE);
3667 }
3668 }
3669
3670 fPadPaint = 0;
3672
3673 if (replace_pp && fCanvas)
3675
3676 // Close the 3D scene if we opened it. This must be done after modified
3677 // flag is cleared, as some viewers will invoke another paint by marking pad modified again
3678 if (began3DScene) {
3680 }
3681}
3682
3683////////////////////////////////////////////////////////////////////////////////
3684/// Paint the pad border.
3685/// Draw first a box as a normal filled box
3686
3687void TPad::PaintBorder(Color_t color, Bool_t /* tops */)
3688{
3689 auto pp = GetPainter();
3690 if (!pp)
3691 return;
3692
3693 pp->OnPad(this);
3694
3695 if (color >= 0) {
3696
3698
3700 if (!IsBatch() && (pp->IsCocoa() || (pp->IsNative() && (style > 3000) && (style < 3026))))
3701 pp->ClearDrawable();
3702
3703 // special only for transparent pads in plain X11;
3704 // Cocoa, GL, Web and PS implement transparency different
3705 if ((style >= 4000) && (style <= 4100) && pp->IsNative() && !pp->IsCocoa() && !pp->GetPS() && !(fCanvas && fCanvas->UseGL()) && !IsWeb() && !IsBatch()) {
3706 if (this == fMother) {
3707 style = 1001;
3708 } else {
3709 // copy all pixmaps
3711 Int_t px, py;
3712 XYtoAbsPixel(GetX1(), GetY2(), px, py);
3713 if (fMother)
3714 fMother->CopyBackgroundPixmaps(this, px, py);
3715 pp->SetAttFill({color, 1001}); // use fill color producing opacity
3716 pp->SetOpacity(style - 4000);
3717 }
3718 } else if ((style >= 4000) && (style <= 4100) && pp->IsCocoa() && (this == fMother))
3719 style = 1001;
3720 else if ((color == 10) && (style > 3000) && (style < 3100))
3721 color = 1;
3722
3723 if (do_paint_box) {
3724 pp->SetAttFill({color, style});
3725 pp->SetAttLine(*this);
3726 PaintBox(fX1, fY1, fX2, fY2);
3727 }
3728 } else
3729 color = -color;
3730
3731 if (IsTransparent() || (fBorderMode == 0))
3732 return;
3733
3734 // then paint 3d frame (depending on bordermode)
3735 // Paint a 3D frame around the pad.
3736
3737 TWbox box;
3738 box.SetFillColor(color);
3739 box.SetFillStyle(GetFillStyle());
3741
3742 box.PaintBorderOn(this, fX1, fY1, fX2, fY2,
3745}
3746
3747////////////////////////////////////////////////////////////////////////////////
3748/// Paint a frame border with Postscript - no longer used
3749
3755
3756////////////////////////////////////////////////////////////////////////////////
3757/// Paint the current date and time if the option `Date` is set on via `gStyle->SetOptDate()`
3758/// Paint the current file name if the option `File` is set on via `gStyle->SetOptFile()`
3759
3761{
3762 if (fCanvas == this) {
3763 if (gStyle->GetOptDate()) {
3764 TDatime dt;
3765 const char *dates;
3766 char iso[16];
3767 if (gStyle->GetOptDate() < 10) {
3768 //by default use format like "Wed Sep 25 17:10:35 2002"
3769 dates = dt.AsString();
3770 } else if (gStyle->GetOptDate() < 20) {
3771 //use ISO format like 2002-09-25
3772 strlcpy(iso,dt.AsSQLString(),16);
3773 dates = iso;
3774 } else {
3775 //use ISO format like 2002-09-25 17:10:35
3776 dates = dt.AsSQLString();
3777 }
3779 tdate.SetTextSize( gStyle->GetAttDate()->GetTextSize());
3780 tdate.SetTextFont( gStyle->GetAttDate()->GetTextFont());
3781 tdate.SetTextColor(gStyle->GetAttDate()->GetTextColor());
3782 tdate.SetTextAlign(gStyle->GetAttDate()->GetTextAlign());
3783 tdate.SetTextAngle(gStyle->GetAttDate()->GetTextAngle());
3784 tdate.SetNDC();
3785 tdate.Paint();
3786 }
3787 if (gStyle->GetOptFile() && gFile) {
3788 TText tfile(1. - gStyle->GetDateX(),gStyle->GetDateY(),gFile->GetName());
3792 tfile.SetTextAlign(31);
3794 tfile.SetNDC();
3795 tfile.Paint();
3796 }
3797 }
3798}
3799
3800////////////////////////////////////////////////////////////////////////////////
3801/// Paint histogram/graph frame.
3802
3804{
3805 if (!fPrimitives) fPrimitives = new TList;
3807 TFrame *frame = GetFrame();
3808 frame->SetX1(xmin);
3809 frame->SetX2(xmax);
3810 frame->SetY1(ymin);
3811 frame->SetY2(ymax);
3812 if (!glist->FindObject(fFrame)) {
3813 glist->AddFirst(frame);
3815 }
3816 frame->Paint();
3817}
3818
3819////////////////////////////////////////////////////////////////////////////////
3820/// Traverse pad hierarchy and (re)paint only modified pads.
3821
3823{
3825 if (IsModified()) {
3826 fViewer3D->PadPaint(this);
3828 }
3830 auto lnk = pList ? pList->FirstLink() : nullptr;
3831 while (lnk) {
3832 auto obj = lnk->GetObject();
3833 if (obj->InheritsFrom(TPad::Class()))
3834 ((TPad*)obj)->PaintModified();
3835 lnk = lnk->Next();
3836 }
3837 return;
3838 }
3839
3842 gVirtualPS = nullptr;
3843
3844 TVirtualPadPainter *oldpp = nullptr;
3846
3847 if (fCanvas) {
3848 // check if special PS painter should be assigned to TCanvas
3851 }
3852
3854 fPadPaint = 1;
3855 {
3856 TContext ctxt(this, kTRUE);
3857 if (IsModified() || IsTransparent())
3859
3860 PaintDate();
3861
3863 auto lnk = pList ? pList->FirstLink() : nullptr;
3864
3865 while (lnk) {
3866 TObject *obj = lnk->GetObject();
3867 if (obj->InheritsFrom(TPad::Class())) {
3868 ((TPad*)obj)->PaintModified();
3869 } else if (IsModified() || IsTransparent()) {
3870
3871 // Create a pad 3D viewer if none exists and we encounter a
3872 // 3D shape
3873 if (!fViewer3D && obj->InheritsFrom(TAtt3D::Class())) {
3874 GetViewer3D("pad");
3875 }
3876
3877 // Open a 3D scene if required
3878 if (fViewer3D && !fViewer3D->BuildingScene()) {
3881 }
3882
3883 obj->Paint(lnk->GetOption());
3884 }
3885 lnk = lnk->Next();
3886 }
3887 }
3888
3889 fPadPaint = 0;
3891
3892 // This must be done after modified flag is cleared, as some
3893 // viewers will invoke another paint by marking pad modified again
3894 if (began3DScene && fViewer3D)
3896
3897 if (replace_pp && fCanvas)
3899
3901}
3902
3903////////////////////////////////////////////////////////////////////////////////
3904/// Paint box in CurrentPad World coordinates.
3905///
3906/// - if option[0] = 's' the box is forced to be paint with style=0
3907/// - if option[0] = 'l' the box contour is drawn
3908
3910{
3911 auto pp = GetPainter();
3912 if (!pp)
3913 return;
3914
3915 pp->OnPad(this);
3916
3917 Style_t style = pp->GetAttFill().GetFillStyle();
3919 if (option && *option == 's')
3921 else if (option && *option == 'l')
3923
3924 if (style >= 3100 && style < 4000) {
3925 Double_t xb[4] = {x1, x1, x2, x2};
3926 Double_t yb[4] = {y1, y2, y2, y1};
3928 } else if (style >= 0 && style < 1000) {
3930 } else if (style >= 1000 && style < 2000) {
3931 draw_fill = kTRUE;
3932 } else if (style > 3000 && style < 3100) {
3933 draw_fill = style < 3026;
3934 } else if (style >= 4000 && style <= 4100) {
3935 // transparency styles, supported now by all painters
3936 draw_fill = style > 4000;
3937 } else if (style > 0)
3939
3940 if (draw_fill && !skip_fill)
3941 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
3942
3943 if (draw_border)
3944 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow);
3945
3946 Modified();
3947}
3948
3949////////////////////////////////////////////////////////////////////////////////
3950/// Copy pixmaps of pads laying below pad "stop" into pad "stop". This
3951/// gives the effect of pad "stop" being transparent.
3952
3954{
3955 Int_t px, py;
3956 XYtoAbsPixel(GetX1(), GetY2(), px, py);
3957 /// Copy pixmap of this pad as background of the current pad.
3958 if (auto pp = GetPainter())
3959 pp->CopyDrawable(GetPixmapID(), px - x, py - y);
3960
3961 TIter next(GetListOfPrimitives());
3962 while (auto obj = next()) {
3963 if (obj == stop)
3964 break;
3965 if (auto pad = dynamic_cast<TPad *>(obj))
3966 pad->CopyBackgroundPixmaps(stop, x, y);
3967 }
3968}
3969
3970////////////////////////////////////////////////////////////////////////////////
3971
3973{
3974 Warning("TPad::PaintFillArea", "Float_t signature is obsolete. Use Double_t signature.");
3975}
3976
3977////////////////////////////////////////////////////////////////////////////////
3978/// Paint fill area in CurrentPad World coordinates.
3979
3981{
3982 if (nn < 3)
3983 return;
3987 } else {
3988 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
3989 }
3990
3991 Int_t nc = 2*nn+1;
3992 std::vector<Double_t> x(nc, 0.);
3993 std::vector<Double_t> y(nc, 0.);
3994
3995 Int_t n = ClipPolygon(nn, xx, yy, nc, x.data(), y.data(), xmin, ymin, xmax, ymax);
3996 if (!n)
3997 return;
3998
3999 auto pp = GetPainter();
4000 if (!pp)
4001 return;
4002
4003 pp->OnPad(this);
4004
4005 // Paint the fill area with hatches
4006 Int_t fillstyle = pp->GetFillStyle();
4007 if (fillstyle >= 3100 && fillstyle < 4000)
4008 PaintFillAreaHatches(nn, x.data(), y.data(), fillstyle);
4009 else
4010 pp->DrawFillArea(n, x.data(), y.data());
4011
4012 Modified();
4013}
4014
4015////////////////////////////////////////////////////////////////////////////////
4016/// Paint fill area in CurrentPad NDC coordinates.
4017
4019{
4020 std::vector<Double_t> xw(n), yw(n);
4021 for (int i=0; i<n; i++) {
4022 xw[i] = fX1 + x[i]*(fX2 - fX1);
4023 yw[i] = fY1 + y[i]*(fY2 - fY1);
4024 }
4025 PaintFillArea(n, xw.data(), yw.data(), option);
4026}
4027
4028////////////////////////////////////////////////////////////////////////////////
4029/// This function paints hatched fill area according to the FillStyle value
4030/// The convention for the Hatch is the following:
4031///
4032/// `FillStyle = 3ijk`
4033///
4034/// - i (1-9) : specify the space between each hatch
4035/// 1 = minimum 9 = maximum
4036/// the final spacing is i*GetHatchesSpacing(). The hatches spacing
4037/// is set by SetHatchesSpacing()
4038/// - j (0-9) : specify angle between 0 and 90 degrees
4039/// * 0 = 0
4040/// * 1 = 10
4041/// * 2 = 20
4042/// * 3 = 30
4043/// * 4 = 45
4044/// * 5 = Not drawn
4045/// * 6 = 60
4046/// * 7 = 70
4047/// * 8 = 80
4048/// * 9 = 90
4049/// - k (0-9) : specify angle between 90 and 180 degrees
4050/// * 0 = 180
4051/// * 1 = 170
4052/// * 2 = 160
4053/// * 3 = 150
4054/// * 4 = 135
4055/// * 5 = Not drawn
4056/// * 6 = 120
4057/// * 7 = 110
4058/// * 8 = 100
4059/// * 9 = 90
4060
4062{
4063 static Double_t ang1[10] = { 0., 10., 20., 30., 45.,5., 60., 70., 80., 89.99};
4064 static Double_t ang2[10] = {180.,170.,160.,150.,135.,5.,120.,110.,100., 89.99};
4065
4066 Int_t fasi = FillStyle % 1000;
4067 Int_t idSPA = fasi / 100;
4068 Int_t iAng2 = (fasi - 100 * idSPA) / 10;
4069 Int_t iAng1 = fasi % 10;
4070 Double_t dy = 0.003 * idSPA * gStyle->GetHatchesSpacing();
4072 auto pp = GetPainter();
4073 if (!pp)
4074 return;
4075
4076 // Save the current line attributes and change to draw hatches
4077 TAttLine saveatt = pp->GetAttLine();
4078
4079 pp->SetAttLine({ pp->GetAttFill().GetFillColor(), 1, lw });
4080
4081 // Draw the hatches
4082 if (ang1[iAng1] != 5.)
4084 if (ang2[iAng2] != 5.)
4086
4087 pp->SetAttLine(saveatt);
4088}
4089
4090////////////////////////////////////////////////////////////////////////////////
4091/// This routine draw hatches inclined with the
4092/// angle "angle" and spaced of "dy" in normalized device
4093/// coordinates in the surface defined by n,xx,yy.
4094
4097{
4098 Int_t i, i1, i2, nbi;
4100 const Double_t angr = TMath::Pi()*(180.-angle)/180.;
4101 const Double_t epsil = 0.0001;
4102
4103 std::vector<Double_t> xli;
4104 std::vector<Double_t> yli;
4105
4106 Double_t xt1, xt2, yt1, yt2;
4107 Double_t x, y, x1, x2, y1, y2, a, b, xi, xip, xin, yi, yip;
4108
4109 Double_t rwxmin = gPad->GetX1();
4110 Double_t rwxmax = gPad->GetX2();
4111 Double_t rwymin = gPad->GetY1();
4112 Double_t rwymax = gPad->GetY2();
4113 ratiox = 1./(rwxmax-rwxmin);
4114 ratioy = 1./(rwymax-rwymin);
4115
4118 if (TMath::Abs(cosa) <= epsil) cosa=0.;
4119 if (TMath::Abs(sina) <= epsil) sina=0.;
4120 sinb = -sina;
4121 cosb = cosa;
4122
4123 // Values needed to compute the hatches in TRUE normalized space (NDC)
4124 Int_t iw = (Int_t)gPad->GetWw();
4125 Int_t ih = (Int_t)gPad->GetWh();
4127 gPad->GetPadPar(x1p,y1p,x2p,y2p);
4128 iw = (Int_t)(iw*x2p)-(Int_t)(iw*x1p);
4129 ih = (Int_t)(ih*y2p)-(Int_t)(ih*y1p);
4132
4133 // Search ymin and ymax
4134 ymin = 1.;
4135 ymax = 0.;
4136 for (i=1; i<=nn; i++) {
4137 x = wndc*ratiox*(xx[i-1]-rwxmin);
4138 y = hndc*ratioy*(yy[i-1]-rwymin);
4139 yrot = sina*x+cosa*y;
4140 if (yrot > ymax) ymax = yrot;
4141 if (yrot < ymin) ymin = yrot;
4142 }
4143
4144 Int_t yindx = (Int_t) (ymax/dy);
4145
4146 while (dy * yindx >= ymin) {
4147 ycur = dy * yindx--;
4148 nbi = 0;
4149
4150 xli.clear();
4151 yli.clear();
4152
4153 for (i=2; i<=nn+1; i++) {
4154 i2 = i;
4155 i1 = i-1;
4156 if (i == nn+1) i2=1;
4157
4158 x1 = wndc*ratiox*(xx[i1-1]-rwxmin);
4159 y1 = hndc*ratioy*(yy[i1-1]-rwymin);
4160 x2 = wndc*ratiox*(xx[i2-1]-rwxmin);
4161 y2 = hndc*ratioy*(yy[i2-1]-rwymin);
4162
4163 xt1 = cosa*x1-sina*y1;
4164 yt1 = sina*x1+cosa*y1;
4165 xt2 = cosa*x2-sina*y2;
4166 yt2 = sina*x2+cosa*y2;
4167
4168 // Line segment parallel to oy
4169 if (xt1 == xt2) {
4170 if (yt1 < yt2) {
4171 yi = yt1;
4172 yip = yt2;
4173 } else {
4174 yi = yt2;
4175 yip = yt1;
4176 }
4177 if ((yi <= ycur) && (ycur < yip)) {
4178 nbi++;
4179 xli.push_back(xt1);
4180 }
4181 continue;
4182 }
4183
4184 // Line segment parallel to ox
4185 if (yt1 == yt2) {
4186 if (yt1 == ycur) {
4187 nbi++;
4188 xli.push_back(xt1);
4189 nbi++;
4190 xli.push_back(xt2);
4191 }
4192 continue;
4193 }
4194
4195 // Other line segment
4196 a = (yt1-yt2)/(xt1-xt2);
4197 b = (yt2*xt1-xt2*yt1)/(xt1-xt2);
4198
4199 if (xt1 < xt2) {
4200 xi = xt1;
4201 xip = xt2;
4202 } else {
4203 xi = xt2;
4204 xip = xt1;
4205 }
4206
4207 xin = (ycur-b)/a;
4208
4209 if ((xi <= xin) && (xin < xip) &&
4210 (TMath::Min(yt1,yt2) <= ycur) &&
4211 (ycur < TMath::Max(yt1,yt2))) {
4212 nbi++;
4213 xli.push_back(xin);
4214 }
4215 }
4216
4217 // Sorting of the x coordinates intersections
4218 std::sort(xli.begin(), xli.end());
4219
4220 // Draw the hatches
4221 if ((nbi%2 != 0) || (nbi == 0))
4222 continue;
4223
4224 for (i=0; i<nbi; ++i) {
4225 // Rotate back the hatches - first calculate y coordinate
4226 Double_t ytmp = sinb*xli[i] + cosb*ycur;
4227 xli[i] = cosb*xli[i] - sinb*ycur;
4228 // Convert hatches' positions from true NDC to WC to handle cliping
4229 xli[i] = (xli[i]/wndc)*(rwxmax-rwxmin)+rwxmin;
4231 yli.push_back(ytmp);
4232 }
4233
4234 gPad->PaintSegments(nbi/2, xli.data(), yli.data());
4235 }
4236}
4237
4238////////////////////////////////////////////////////////////////////////////////
4239/// Paint line in CurrentPad World coordinates.
4240
4242{
4243 Double_t x[2] = {x1, x2}, y[2] = {y1, y2};
4244
4245 //If line is totally clipped, return
4247 if (Clip(x,y,fUxmin,fUymin,fUxmax,fUymax) == 2) return;
4248 } else {
4249 if (Clip(x,y,fX1,fY1,fX2,fY2) == 2) return;
4250 }
4251
4252 if (auto pp = GetPainter()) {
4253 pp->OnPad(this);
4254 pp->DrawLine(x[0], y[0], x[1], y[1]);
4255 }
4256
4257 Modified();
4258}
4259
4260////////////////////////////////////////////////////////////////////////////////
4261/// Paint line in normalized coordinates.
4262
4264{
4265 if (auto pp = GetPainter()) {
4266 pp->OnPad(this);
4267 pp->DrawLineNDC(u1, v1, u2, v2);
4268 }
4269
4270 Modified();
4271}
4272
4273////////////////////////////////////////////////////////////////////////////////
4274/// Paint 3-D line in the CurrentPad.
4275
4277{
4278 if (!fView) return;
4279
4280 // convert from 3-D to 2-D pad coordinate system
4281 Double_t xpad[6];
4282 Double_t temp[3];
4283 Int_t i;
4284 for (i=0;i<3;i++) temp[i] = p1[i];
4285 fView->WCtoNDC(temp, &xpad[0]);
4286 for (i=0;i<3;i++) temp[i] = p2[i];
4287 fView->WCtoNDC(temp, &xpad[3]);
4288 PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
4289}
4290
4291////////////////////////////////////////////////////////////////////////////////
4292/// Paint 3-D line in the CurrentPad.
4293
4295{
4296 if (!fView) return;
4297
4298 // convert from 3-D to 2-D pad coordinate system
4299 Double_t xpad[6];
4300 Double_t temp[3];
4301 Int_t i;
4302 for (i=0;i<3;i++) temp[i] = p1[i];
4303 fView->WCtoNDC(temp, &xpad[0]);
4304 for (i=0;i<3;i++) temp[i] = p2[i];
4305 fView->WCtoNDC(temp, &xpad[3]);
4306 PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
4307}
4308
4309////////////////////////////////////////////////////////////////////////////////
4310/// Paint 3-D marker in the CurrentPad.
4311
4313{
4314 if (!fView) return;
4315
4316 Double_t rmin[3], rmax[3];
4318
4319 // convert from 3-D to 2-D pad coordinate system
4320 Double_t xpad[3];
4321 Double_t temp[3];
4322 temp[0] = x;
4323 temp[1] = y;
4324 temp[2] = z;
4325 if (x<rmin[0] || x>rmax[0]) return;
4326 if (y<rmin[1] || y>rmax[1]) return;
4327 if (z<rmin[2] || z>rmax[2]) return;
4328 fView->WCtoNDC(temp, &xpad[0]);
4329 PaintPolyMarker(1, &xpad[0], &xpad[1]);
4330}
4331
4332////////////////////////////////////////////////////////////////////////////////
4333/// Paint polyline in CurrentPad World coordinates.
4334
4336{
4337 if (n < 2) return;
4338
4342 } else {
4343 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4344 }
4345 Int_t i, i1=-1,np=1;
4346 for (i=0; i<n-1; i++) {
4347 Double_t x1=x[i];
4348 Double_t y1=y[i];
4349 Double_t x2=x[i+1];
4350 Double_t y2=y[i+1];
4351 Int_t iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4352 if (iclip == 2) {
4353 i1 = -1;
4354 continue;
4355 }
4356 np++;
4357 if (i1 < 0)
4358 i1 = i;
4359 if (iclip == 0 && i < n-2)
4360 continue;
4361 if (auto pp = GetPainter()) {
4362 pp->OnPad(this);
4363 pp->DrawPolyLine(np, &x[i1], &y[i1]);
4364 }
4365 if (iclip) {
4366 x[i] = x1;
4367 y[i] = y1;
4368 x[i+1] = x2;
4369 y[i+1] = y2;
4370 }
4371 i1 = -1;
4372 np = 1;
4373 }
4374
4375 Modified();
4376}
4377
4378////////////////////////////////////////////////////////////////////////////////
4379/// Paint polyline in CurrentPad World coordinates.
4380///
4381/// If option[0] == 'C' no clipping
4382
4384{
4385 if (n < 2) return;
4386
4391 } else {
4392 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4393 if (option && (option[0] == 'C')) mustClip = kFALSE;
4394 }
4395
4396 Int_t i, i1=-1, np = 1, iclip = 0;
4397
4398 for (i=0; i < n-1; i++) {
4399 Double_t x1 = x[i];
4400 Double_t y1 = y[i];
4401 Double_t x2 = x[i+1];
4402 Double_t y2 = y[i+1];
4403 if (mustClip) {
4404 iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4405 if (iclip == 2) {
4406 i1 = -1;
4407 continue;
4408 }
4409 }
4410 np++;
4411 if (i1 < 0)
4412 i1 = i;
4413 if (iclip == 0 && i < n-2)
4414 continue;
4415 if (auto pp = GetPainter()) {
4416 pp->OnPad(this);
4417 pp->DrawPolyLine(np, &x[i1], &y[i1]);
4418 }
4419 if (iclip) {
4420 x[i] = x1;
4421 y[i] = y1;
4422 x[i+1] = x2;
4423 y[i+1] = y2;
4424 }
4425 i1 = -1;
4426 np = 1;
4427 }
4428
4429 Modified();
4430}
4431
4432////////////////////////////////////////////////////////////////////////////////
4433/// Paint polyline in CurrentPad NDC coordinates.
4434
4436{
4437 if (n <= 0)
4438 return;
4439
4440 if (auto pp = GetPainter()) {
4441 pp->OnPad(this);
4442 pp->DrawPolyLineNDC(n, x, y);
4443 }
4444
4445 Modified();
4446}
4447
4448////////////////////////////////////////////////////////////////////////////////
4449/// Paint 3-D polyline in the CurrentPad.
4450
4452{
4453 if (!fView) return;
4454
4455 // Loop on each individual line
4456 for (Int_t i = 1; i < n; i++)
4457 PaintLine3D(&p[3*i-3], &p[3*i]);
4458
4459 Modified();
4460}
4461
4462////////////////////////////////////////////////////////////////////////////////
4463/// Paint polymarker in CurrentPad World coordinates.
4464
4466{
4467 Int_t n = TMath::Abs(nn);
4469 if (nn > 0 || TestBit(TGraph::kClipFrame)) {
4471 } else {
4472 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4473 }
4474 Int_t i,i1=-1,np=0;
4475 for (i=0; i<n; i++) {
4476 if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
4477 np++;
4478 if (i1 < 0) i1 = i;
4479 if (i < n-1) continue;
4480 }
4481 if (np == 0)
4482 continue;
4483 if (auto pp = GetPainter()) {
4484 pp->OnPad(this);
4485 pp->DrawPolyMarker(np, &x[i1], &y[i1]);
4486 }
4487 i1 = -1;
4488 np = 0;
4489 }
4490 Modified();
4491}
4492
4493////////////////////////////////////////////////////////////////////////////////
4494/// Paint polymarker in CurrentPad World coordinates.
4495
4497{
4498 Int_t n = TMath::Abs(nn);
4500 if (nn > 0 || TestBit(TGraph::kClipFrame)) {
4502 } else {
4503 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4504 }
4505 Int_t i,i1=-1,np=0;
4506 for (i=0; i<n; i++) {
4507 if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
4508 np++;
4509 if (i1 < 0) i1 = i;
4510 if (i < n-1) continue;
4511 }
4512 if (np == 0)
4513 continue;
4514 if (auto pp = GetPainter()) {
4515 pp->OnPad(this);
4516 pp->DrawPolyMarker(np, &x[i1], &y[i1]);
4517 }
4518 i1 = -1;
4519 np = 0;
4520 }
4521 Modified();
4522}
4523
4524////////////////////////////////////////////////////////////////////////////////
4525/// Paint N individual segments
4526/// Provided arrays should have 2*n elements
4527/// IMPORTANT! Provided arrays can be modified after function call!
4528
4530{
4531 if (n < 1)
4532 return;
4533
4538 } else {
4539 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4540 if (option && *option == 'C') mustClip = kFALSE;
4541 }
4542
4543 if (!mustClip)
4544 isAny = kTRUE;
4545 else {
4546 for (Int_t i = 0; i < 2*n; i+=2) {
4547 Int_t iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4548 if (iclip == 2)
4549 x[i] = y[i] = x[i+1] = y[i+1] = 0;
4550 else
4551 isAny = kTRUE;
4552 }
4553 }
4554
4555 if (isAny)
4556 if (auto pp = GetPainter()) {
4557 pp->OnPad(this);
4558 pp->DrawSegments(n, x, y);
4559 }
4560
4561 Modified();
4562}
4563
4564
4565////////////////////////////////////////////////////////////////////////////////
4566/// Paint N individual segments in NDC coordinates
4567/// Provided arrays should have 2*n elements
4568/// IMPORTANT! Provided arrays can be modified after function call!
4569
4571{
4572 if (auto pp = GetPainter()) {
4573 pp->OnPad(this);
4574 pp->DrawSegmentsNDC(n, u, v);
4575 }
4576
4577 Modified();
4578}
4579
4580
4581////////////////////////////////////////////////////////////////////////////////
4582/// Paint text in CurrentPad World coordinates.
4583
4585{
4586 Modified();
4587
4588 if (auto pp = GetPainter()) {
4589 pp->OnPad(this);
4590 pp->DrawText(x, y, text, TVirtualPadPainter::kClear);
4591 }
4592}
4593
4594////////////////////////////////////////////////////////////////////////////////
4595/// Paint text in CurrentPad World coordinates.
4596
4597void TPad::PaintText(Double_t x, Double_t y, const wchar_t *text)
4598{
4599 Modified();
4600
4601 if (auto pp = GetPainter()) {
4602 pp->OnPad(this);
4603 pp->DrawText(x, y, text, TVirtualPadPainter::kClear);
4604 }
4605}
4606
4607////////////////////////////////////////////////////////////////////////////////
4608/// Paint text with URL in CurrentPad World coordinates.
4609
4610void TPad::PaintTextUrl(Double_t x, Double_t y, const char *text, const char *url)
4611{
4612 Modified();
4613
4614 if (auto pp = GetPainter()) {
4615 pp->OnPad(this);
4616 pp->DrawTextUrl(x, y, text, url);
4617 }
4618}
4619
4620////////////////////////////////////////////////////////////////////////////////
4621/// Paint text in CurrentPad NDC coordinates.
4622
4624{
4625 Modified();
4626
4627 if (auto pp = GetPainter()) {
4628 pp->OnPad(this);
4629 pp->DrawTextNDC(u, v, text, TVirtualPadPainter::kClear);
4630 }
4631}
4632
4633////////////////////////////////////////////////////////////////////////////////
4634/// Paint text in CurrentPad NDC coordinates.
4635
4637{
4638 Modified();
4639
4640 if (auto pp = GetPainter()) {
4641 pp->OnPad(this);
4642 pp->DrawTextNDC(u, v, text, TVirtualPadPainter::kClear);
4643 }
4644}
4645
4646////////////////////////////////////////////////////////////////////////////////
4647/// Search for an object at pixel position px,py.
4648///
4649/// Check if point is in this pad.
4650///
4651/// If yes, check if it is in one of the sub-pads
4652///
4653/// If found in the pad, compute closest distance of approach
4654/// to each primitive.
4655///
4656/// If one distance of approach is found to be within the limit Distancemaximum
4657/// the corresponding primitive is selected and the routine returns.
4658
4660{
4661 //the two following statements are necessary under NT (multithreaded)
4662 //when a TCanvas object is being created and a thread calling TPad::Pick
4663 //before the TPad constructor has completed in the other thread
4664 if (!gPad) return nullptr; //Andy Haas
4665 if (!GetListOfPrimitives()) return nullptr; //Andy Haas
4666
4667 Int_t dist;
4668 // Search if point is in pad itself
4669 Double_t x = AbsPixeltoX(px);
4670 Double_t y = AbsPixeltoY(py);
4671 if (this != gPad->GetCanvas()) {
4672 if (!((x >= fX1 && x <= fX2) && (y >= fY1 && y <= fY2))) return nullptr;
4673 }
4674
4675 // search for a primitive in this pad or its sub-pads
4676 static TObjOptLink dummyLink(nullptr,""); //place holder for when no link available
4677
4678 TContext ctxt(this, kFALSE); // since no drawing will be done, don't use cd() for efficiency reasons
4679
4680 TPad *pick = nullptr;
4681 TPad *picked = this;
4682 pickobj = nullptr;
4684 dummyLink.SetObject(this);
4685 pickobj = &dummyLink;
4686 }
4687
4688 // Loop backwards over the list of primitives. The first non-pad primitive
4689 // found is the selected one. However, we have to keep going down the
4690 // list to see if there is maybe a pad overlaying the primitive. In that
4691 // case look into the pad for a possible primitive. Once a pad has been
4692 // found we can terminate the loop.
4693 Bool_t gotPrim = kFALSE; // true if found a non pad primitive
4695
4696 //We can have 3d stuff in pad. If canvas prefers to draw
4697 //such stuff with OpenGL, the selection of 3d objects is
4698 //a gl viewer business so, in first cycle we do not
4699 //call DistancetoPrimitive for TAtt3D descendants.
4700 //In case of gl we first try to select 2d object first.
4701
4702 while (lnk) {
4703 TObject *obj = lnk->GetObject();
4704
4705 //If canvas prefers GL, all 3d objects must be drawn/selected by
4706 //gl viewer
4707 if (obj->InheritsFrom(TAtt3D::Class()) && fEmbeddedGL) {
4708 lnk = lnk->Prev();
4709 continue;
4710 }
4711
4712 fPadPointer = obj;
4713 if (obj->InheritsFrom(TPad::Class())) {
4714 pick = ((TPad*)obj)->Pick(px, py, pickobj);
4715 if (pick) {
4716 picked = pick;
4717 break;
4718 }
4719 } else if (!gROOT->GetEditorMode()) {
4720 if (!gotPrim) {
4721 if (!obj->TestBit(kCannotPick)) {
4722 dist = obj->DistancetoPrimitive(px, py);
4723 if (dist < fgMaxPickDistance) {
4724 pickobj = lnk;
4725 gotPrim = kTRUE;
4726 if (dist == 0) break;
4727 }
4728 }
4729 }
4730 }
4731
4732 lnk = lnk->Prev();
4733 }
4734
4735 //if no primitive found, check if we have a TView
4736 //if yes, return the view except if you are in the lower or upper X range
4737 //of the pad.
4738 //In case canvas prefers gl, fView existence
4739 //automatically means viewer3d existence. (?)
4740
4741 if (fView && !gotPrim) {
4742 Double_t dx = 0.05*(fUxmax-fUxmin);
4743 if ((x > fUxmin + dx) && (x < fUxmax-dx)) {
4744
4745 if (fEmbeddedGL) {
4746 //No 2d stuff was selected, but we have gl-viewer. Let it select an object in
4747 //scene (or select itself). In any case it'll internally call
4748 //gPad->SetSelected(ptr) as, for example, hist painter does.
4749 py -= Int_t((1 - GetHNDC() - GetYlowNDC()) * GetWh());
4750 px -= Int_t(GetXlowNDC() * GetWw());
4752 }
4753 else
4754 dummyLink.SetObject(fView);
4755 }
4756 }
4757
4758 if (picked->InheritsFrom(TButton::Class())) {
4760 if (!button->IsEditable()) pickobj = nullptr;
4761 }
4762
4763 if (TestBit(kCannotPick)) {
4764
4765 if (picked == this) {
4766 // cannot pick pad itself!
4767 picked = nullptr;
4768 }
4769
4770 }
4771
4772 return picked;
4773}
4774
4775////////////////////////////////////////////////////////////////////////////////
4776/// Pop pad to the top of the stack.
4777
4779{
4781 return;
4782 if (!fPrimitives)
4783 fPrimitives = new TList;
4784 if (this == fMother->GetListOfPrimitives()->Last())
4785 return;
4786
4788 while (auto obj = next())
4789 if (obj == this) {
4790 TString opt = next.GetOption();
4791 fMother->Remove(this, kFALSE); // do not issue modified
4792 fMother->Add(this, opt.Data());
4793 return;
4794 }
4795}
4796
4797////////////////////////////////////////////////////////////////////////////////
4798/// This method is equivalent to `SaveAs("filename")`. See TPad::SaveAs for details.
4799
4800void TPad::Print(const char *filename) const
4801{
4802 ((TPad*)this)->SaveAs(filename);
4803}
4804
4805////////////////////////////////////////////////////////////////////////////////
4806/// Auxiliary function. Returns kTRUE if list contains an object inherited
4807/// from TImage
4808
4810{
4811 TIter next(li);
4812
4813 while (auto obj = next()) {
4814 if (obj->InheritsFrom(TImage::Class())) {
4815 return kTRUE;
4816 } else if (obj->InheritsFrom(TPad::Class())) {
4817 if (ContainsTImage(((TPad*)obj)->GetListOfPrimitives())) {
4818 return kTRUE;
4819 }
4820 }
4821 }
4822 return kFALSE;
4823}
4824
4825////////////////////////////////////////////////////////////////////////////////
4826/// Save Canvas contents in a file in one of various formats.
4827///
4828/// \anchor TPadPrint
4829/// option can be:
4830///
4831/// - `ps`: a Postscript file is produced (default). [See special cases](\ref TPadPrintPS).
4832/// - `Portrait`: Postscript file is produced (Portrait)
4833/// - `Landscape`: Postscript file is produced (Landscape)
4834/// - `eps`: an Encapsulated Postscript file is produced
4835/// - `Preview`: an [Encapsulated Postscript file with preview](\ref TPadPrintPreview) is produced.
4836/// - `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.
4837/// - `Title:`: The character string after `Title:` becomes a table
4838/// of content entry (for PDF files).
4839/// - `EmbedFonts`: a [PDF file with embedded fonts](\ref TPadPrintEmbedFonts) is generated.
4840/// - `svg`: a SVG file is produced
4841/// - `tex`: a TeX file is produced
4842/// - `Standalone`: a [standalone TeX file](\ref TPadPrintStandalone) is produced.
4843/// - `gif`: a GIF file is produced
4844/// - `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
4845/// - `xpm`: a XPM file is produced
4846/// - `png`: a PNG file is produced
4847/// - `jpg`: a JPEG file is produced. NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
4848/// - `tiff`: a TIFF file is produced
4849/// - `cxx`: a C++ macro file is produced
4850/// - `xml`: a XML file
4851/// - `json`: a JSON file
4852/// - `root`: a ROOT binary file
4853///
4854/// `filename` = 0 - filename is defined by `GetName` and its
4855/// extension is defined with the option
4856///
4857/// When Postscript output is selected (`ps`, `eps`), the canvas is saved
4858/// to `filename.ps` or `filename.eps`. The aspect ratio of the canvas is preserved
4859/// on the Postscript file. When the "ps" option is selected, the Postscript
4860/// page will be landscape format if the canvas is in landscape format, otherwise
4861/// portrait format is selected.
4862///
4863/// The physical size of the Postscript page is the one selected in the
4864/// current style. This size can be modified via TStyle::SetPaperSize.
4865///
4866/// Examples:
4867/// ~~~ {.cpp}
4868/// gStyle->SetPaperSize(TStyle::kA4); //default
4869/// gStyle->SetPaperSize(TStyle::kUSLetter);
4870/// ~~~
4871/// where TStyle::kA4 and TStyle::kUSLetter are defined in the enum
4872/// EPaperSize in TStyle.h
4873///
4874/// An alternative is to call:
4875/// ~~~ {.cpp}
4876/// gStyle->SetPaperSize(20,26); same as kA4
4877/// or gStyle->SetPaperSize(20,24); same as kUSLetter
4878/// ~~~
4879/// The above numbers take into account some margins and are in centimeters.
4880///
4881/// \anchor TPadPrintPreview
4882/// ### The "Preview" option
4883///
4884/// The "Preview" option allows to generate a preview (in the TIFF format) within
4885/// the Encapsulated Postscript file. This preview can be used by programs like
4886/// MSWord to visualize the picture on screen. The "Preview" option relies on the
4887/// ["epstool" command](http://www.cs.wisc.edu/~ghost/gsview/epstool.htm).
4888///
4889/// Example:
4890/// ~~~ {.cpp}
4891/// canvas->Print("example.eps","Preview");
4892/// ~~~
4893///
4894/// \anchor TPadPrintEmbedFonts
4895/// ### The "EmbedFonts" option
4896///
4897/// The "EmbedFonts" option allows to embed the fonts used in a PDF file inside
4898/// that file. This option relies on the ["gs" command](https://ghostscript.com).
4899///
4900/// Example:
4901/// ~~~ {.cpp}
4902/// canvas->Print("example.pdf","EmbedFonts");
4903/// ~~~
4904///
4905/// \anchor TPadPrintStandalone
4906/// ### The "Standalone" option
4907/// The "Standalone" option allows to generate a TeX file ready to be processed by
4908/// tools like `pdflatex`.
4909///
4910/// Example:
4911/// ~~~ {.cpp}
4912/// canvas->Print("example.tex","Standalone");
4913/// ~~~
4914///
4915/// \anchor TPadPrintPS
4916/// ### Writing several canvases to the same Postscript or PDF file:
4917///
4918/// - if the Postscript or PDF file name finishes with "(", the file is not closed
4919/// - if the Postscript or PDF file name finishes with ")" and the file has been opened
4920/// with "(", the file is closed.
4921///
4922/// Example:
4923/// ~~~ {.cpp}
4924/// {
4925/// TCanvas c1("c1");
4926/// h1.Draw();
4927/// c1.Print("c1.ps("); //write canvas and keep the ps file open
4928/// h2.Draw();
4929/// c1.Print("c1.ps"); canvas is added to "c1.ps"
4930/// h3.Draw();
4931/// c1.Print("c1.ps)"); canvas is added to "c1.ps" and ps file is closed
4932/// }
4933/// ~~~
4934/// In the previous example replacing "ps" by "pdf" will create a multi-pages PDF file.
4935///
4936/// Note that the following sequence writes the canvas to "c1.ps" and closes the ps file.:
4937/// ~~~ {.cpp}
4938/// TCanvas c1("c1");
4939/// h1.Draw();
4940/// c1.Print("c1.ps");
4941/// ~~~
4942/// The `TCanvas::Print("file.ps(")` mechanism is very useful, but it can be
4943/// a little inconvenient to have the action of opening/closing a file
4944/// being atomic with printing a page. Particularly if pages are being
4945/// generated in some loop one needs to detect the special cases of first
4946/// and last page and then munge the argument to Print() accordingly.
4947///
4948/// The "[" and "]" can be used instead of "(" and ")" to open / close without
4949/// actual printing.
4950///
4951/// Example:
4952/// ~~~ {.cpp}
4953/// c1.Print("file.ps["); // No actual print, just open file.ps
4954/// for (int i=0; i<10; ++i) {
4955/// // fill canvas for context i
4956/// // ...
4957///
4958/// c1.Print("file.ps"); // actually print canvas to file
4959/// }// end loop
4960/// c1.Print("file.ps]"); // No actual print, just close.
4961/// ~~~
4962/// As before, the same macro is valid for PDF files.
4963///
4964/// It is possible to print a canvas into an animated GIF file by specifying the
4965/// file name as "myfile.gif+" or "myfile.gif+NN", where NN*10ms is delay
4966/// between the subimages' display. If NN is omitted the delay between
4967/// subimages is zero. Each picture is added in the animation thanks to a loop
4968/// similar to the following one:
4969/// ~~~ {.cpp}
4970/// for (int i=0; i<10; ++i) {
4971/// // fill canvas for context i
4972/// // ...
4973///
4974/// c1.Print("file.gif+5"); // print canvas to GIF file with 50ms delays
4975/// }// end loop
4976/// ~~~
4977/// The delay between each frame must be specified in each Print() statement.
4978/// If the file "myfile.gif" already exists, the new frame are appended at
4979/// the end of the file. To avoid this, delete it first with `gSystem->Unlink(myfile.gif);`
4980/// If you want the gif file to repeat or loop forever, check TASImage::WriteImage documentation
4981
4983{
4984 if (!GetCanvas())
4985 return;
4986
4988
4989 // "[" and "]" are special characters for ExpandPathName. When they are at the end
4990 // of the file name (see help) they must be removed before doing ExpandPathName.
4991 if (fs1.EndsWith("[")) {
4992 fs1.Replace((fs1.Length()-1),1," ");
4994 fs1.Replace((fs1.Length()-1),1,"[");
4995 } else if (fs1.EndsWith("]")) {
4996 fs1.Replace((fs1.Length()-1),1," ");
4998 fs1.Replace((fs1.Length()-1),1,"]");
4999 } else {
5001 }
5002
5003 // Set the default option as "Postscript" (Should be a data member of TPad)
5004 const char *opt_default = "ps";
5005
5006 TString opt = !option ? opt_default : option;
5008
5009 Bool_t title = kFALSE;
5010 if (strstr(opt,"Title:")) title = kTRUE;
5011
5012 if (!fs1.Length()) {
5013 psname = GetName();
5014 psname += opt;
5015 } else {
5016 psname = fs1;
5017 }
5018
5019 // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
5020 if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
5021 psname = GetName();
5022 psname.Append(fs1);
5023 psname.Prepend("/");
5024 psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
5025 }
5026
5027 // Save pad/canvas in alternative formats
5029 if (!title && strstr(opt, "gif+")) {
5031 image = kTRUE;
5032 } else if (!title && strstr(opt, "gif")) {
5034 image = kTRUE;
5035 } else if (!title && strstr(opt, "png")) {
5037 image = kTRUE;
5038 } else if (!title && strstr(opt, "jpg")) {
5040 image = kTRUE;
5041 } else if (!title && strstr(opt, "tiff")) {
5043 image = kTRUE;
5044 } else if (!title && strstr(opt, "xpm")) {
5046 image = kTRUE;
5047 } else if (!title && strstr(opt, "bmp")) {
5049 image = kTRUE;
5050 }
5051
5052 if (GetCanvas()->IsWeb() && GetPainter() &&
5053 (strstr(opt,"svg") || strstr(opt,"pdf") || (gtype == TImage::kJpeg) || (gtype == TImage::kPng))) {
5054 GetPainter()->SaveImage(this, psname.Data(), gtype);
5055 return;
5056 }
5057
5058 if (!GetCanvas()->IsBatch() && GetPainter())
5060
5061
5062 if (!gROOT->IsBatch() && image) {
5064 Int_t wid = (this == GetCanvas()) ? GetCanvas()->GetCanvasID() : GetPixmapID();
5065 Color_t hc = gPad->GetCanvas()->GetHighLightColor();
5066 gPad->GetCanvas()->SetHighLightColor(-1);
5067 gPad->Modified();
5068 gPad->Update();
5069 if (GetPainter()) {
5071 GetPainter()->SaveImage(this, psname.Data(), gtype);
5072 }
5073 if (!gSystem->AccessPathName(psname.Data())) {
5074 Info("Print", "GIF file %s has been created", psname.Data());
5075 }
5076 gPad->GetCanvas()->SetHighLightColor(hc);
5077 return;
5078 }
5079 if (gtype != TImage::kUnknown) {
5080 Color_t hc = gPad->GetCanvas()->GetHighLightColor();
5081 gPad->GetCanvas()->SetHighLightColor(-1);
5082 gPad->Modified();
5083 gPad->Update();
5084 gPad->GetCanvasImp()->UpdateDisplay(1, kTRUE);
5085 if (GetPainter())
5086 GetPainter()->SaveImage(this, psname, gtype);
5087 if (!gSystem->AccessPathName(psname)) {
5088 Info("Print", "file %s has been created", psname.Data());
5089 }
5090 gPad->GetCanvas()->SetHighLightColor(hc);
5091 } else {
5092 Warning("Print", "Unsupported image format %s", psname.Data());
5093 }
5094 return;
5095 }
5096
5097 //==============Save pad/canvas as a C++ script==============================
5098 if (!title && strstr(opt,"cxx")) {
5099 GetCanvas()->SaveSource(psname, "");
5100 return;
5101 }
5102
5103 //==============Save pad/canvas as a root file===============================
5104 if (!title && strstr(opt,"root")) {
5105 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5106 return;
5107 }
5108
5109 //==============Save pad/canvas as a XML file================================
5110 if (!title && strstr(opt,"xml")) {
5111 // Plugin XML driver
5112 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5113 return;
5114 }
5115
5116 //==============Save pad/canvas as a JSON file================================
5117 if (!title && strstr(opt,"json")) {
5118 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5119 return;
5120 }
5121
5122 //==============Save pad/canvas as a SVG file================================
5123 if (!title && strstr(opt,"svg")) {
5124 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5125
5127 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5128 noScreen = kTRUE;
5130 }
5131
5132 TContext ctxt(this, kTRUE);
5133
5134 if (!gVirtualPS) {
5135 // Plugin Postscript/SVG driver
5136 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "svg")) {
5137 if (h->LoadPlugin() == -1)
5138 return;
5139 h->ExecPlugin(0);
5140 }
5141 }
5142
5143 // Create a new SVG file
5144 if (gVirtualPS) {
5149 }
5150
5151 Paint();
5152 if (noScreen)
5154 if (wasModified && !IsBatch())
5155 Modified(kTRUE);
5156
5158 Info("Print", "SVG file %s has been created", psname.Data());
5159
5160 delete gVirtualPS;
5161 gVirtualPS = nullptr;
5162
5163 return;
5164 }
5165
5166 //==============Save pad/canvas as a TeX file================================
5167 if (!title && (strstr(opt,"tex") || strstr(opt,"Standalone"))) {
5168 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5169
5171 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5172 noScreen = kTRUE;
5174 }
5175
5176 TContext ctxt(this, kTRUE);
5177
5178 if (!gVirtualPS) {
5179 // Plugin Postscript/SVG driver
5180 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "tex")) {
5181 if (h->LoadPlugin() == -1)
5182 return;
5183 h->ExecPlugin(0);
5184 }
5185 }
5186
5188 if (strstr(opt,"Standalone")) standalone = kTRUE;
5189
5190 // Create a new TeX file
5191 if (gVirtualPS) {
5193 if (standalone) gVirtualPS->SetTitle("Standalone");
5197 }
5198 Paint();
5199 if (noScreen)
5201 if (wasModified && !IsBatch())
5202 Modified(kTRUE);
5203
5204 if (!gSystem->AccessPathName(psname)) {
5205 if (standalone) {
5206 Info("Print", "Standalone TeX file %s has been created", psname.Data());
5207 } else{
5208 Info("Print", "TeX file %s has been created", psname.Data());
5209 }
5210 }
5211
5212 delete gVirtualPS;
5213 gVirtualPS = nullptr;
5214
5215 return;
5216 }
5217
5218 //==============Save pad/canvas as a Postscript file=========================
5219
5220 // in case we read directly from a Root file and the canvas
5221 // is not on the screen, set batch mode
5222
5225 if (!image) {
5226 // The parenthesis mechanism is only valid for PS and PDF files.
5227 copen = psname.EndsWith("("); if (copen) psname[psname.Length()-1] = 0;
5228 cclose = psname.EndsWith(")"); if (cclose) psname[psname.Length()-1] = 0;
5229 copenb = psname.EndsWith("["); if (copenb) psname[psname.Length()-1] = 0;
5230 ccloseb = psname.EndsWith("]"); if (ccloseb) psname[psname.Length()-1] = 0;
5231 }
5232 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5234 if (copen || copenb) mustClose = kFALSE;
5235 if (cclose || ccloseb) mustClose = kTRUE;
5236
5238 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5239 noScreen = kTRUE;
5241 }
5242 Int_t pstype = 111;
5245 Double_t ratio = ycanvas/xcanvas;
5246 if (ratio < 1) pstype = 112;
5247 if (strstr(opt,"Portrait")) pstype = 111;
5248 if (strstr(opt,"Landscape")) pstype = 112;
5249 if (strstr(opt,"eps")) pstype = 113;
5250 if (strstr(opt,"Preview")) pstype = 113;
5251
5252 TContext ctxt(this, kTRUE);
5254
5255 if (!gVirtualPS || mustOpen) {
5256
5257 const char *pluginName = "ps"; // Plugin Postscript driver
5258 if (strstr(opt,"pdf") || title || strstr(opt,"EmbedFonts"))
5259 pluginName = "pdf";
5260 else if (image)
5261 pluginName = "image"; // Plugin TImageDump driver
5262
5263 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", pluginName)) {
5264 if (h->LoadPlugin() == -1)
5265 return;
5266 h->ExecPlugin(0);
5267 }
5268
5269 // Create a new Postscript, PDF or image file
5270 if (gVirtualPS)
5272 const Ssiz_t titlePos = opt.Index("Title:");
5273 if (titlePos != kNPOS) {
5274 if (gVirtualPS)
5275 gVirtualPS->SetTitle(opt.Data()+titlePos+6);
5276 opt.Replace(titlePos,opt.Length(),"pdf");
5277 }
5278 if (gVirtualPS)
5280 if (gVirtualPS)
5282 if (!copenb) {
5283 if (!strstr(opt,"pdf") || image) {
5285 }
5286 Paint();
5287 }
5289
5290 if (mustClose) {
5291 gROOT->GetListOfSpecials()->Remove(gVirtualPS);
5292 delete gVirtualPS;
5293 gVirtualPS = psave;
5294 } else {
5295 gROOT->GetListOfSpecials()->Add(gVirtualPS);
5296 gVirtualPS = nullptr;
5297 }
5298
5299 if (!gSystem->AccessPathName(psname)) {
5300 if (!copen) Info("Print", "%s file %s has been created", opt.Data(), psname.Data());
5301 else Info("Print", "%s file %s has been created using the current canvas", opt.Data(), psname.Data());
5302 }
5303 } else {
5304 // Append to existing Postscript, PDF or GIF file
5305 if (!ccloseb) {
5307 Paint();
5308 }
5309 const Ssiz_t titlePos = opt.Index("Title:");
5310 if (titlePos != kNPOS) {
5311 gVirtualPS->SetTitle(opt.Data()+titlePos+6);
5312 opt.Replace(titlePos,opt.Length(),"pdf");
5313 } else if (!ccloseb) {
5314 gVirtualPS->SetTitle("PDF");
5315 }
5316 if (mustClose) {
5317 if (cclose) Info("Print", "Current canvas added to %s file %s and file closed", opt.Data(), psname.Data());
5318 else Info("Print", "%s file %s has been closed", opt.Data(), psname.Data());
5319 gROOT->GetListOfSpecials()->Remove(gVirtualPS);
5320 delete gVirtualPS;
5321 gVirtualPS = nullptr;
5322 } else {
5323 Info("Print", "Current canvas added to %s file %s", opt.Data(), psname.Data());
5324 gVirtualPS = nullptr;
5325 }
5326 }
5327
5328 if (wasModified && !IsBatch())
5329 Modified(kTRUE);
5330
5331 if (strstr(opt,"Preview"))
5332 gSystem->Exec(TString::Format("epstool --quiet -t6p %s %s", psname.Data(), psname.Data()).Data());
5333 if (strstr(opt,"EmbedFonts")) {
5334 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",
5335 psname.Data()).Data());
5336 gSystem->Rename("pdf_temp.pdf", psname.Data());
5337 }
5338
5339}
5340
5341////////////////////////////////////////////////////////////////////////////////
5342/// Set world coordinate system for the pad.
5343/// Emits signal "RangeChanged()", in the slot get the range
5344/// via GetRange().
5345
5347{
5348 if ((x1 >= x2) || (y1 >= y2)) {
5349 Error("Range", "illegal world coordinates range: x1=%f, y1=%f, x2=%f, y2=%f",x1,y1,x2,y2);
5350 return;
5351 }
5352
5353 fUxmin = x1;
5354 fUxmax = x2;
5355 fUymin = y1;
5356 fUymax = y2;
5357
5358 if (fX1 == x1 && fY1 == y1 && fX2 == x2 && fY2 == y2) return;
5359
5360 fX1 = x1;
5361 fY1 = y1;
5362 fX2 = x2;
5363 fY2 = y2;
5364
5365 // compute pad conversion coefficients
5366 ResizePad();
5367
5368 if (gPad == this && GetPainter())
5370
5371 // emit signal
5372 RangeChanged();
5373}
5374
5375////////////////////////////////////////////////////////////////////////////////
5376/// Set axis coordinate system for the pad.
5377/// The axis coordinate system is a subset of the world coordinate system
5378/// xmin,ymin is the origin of the current coordinate system,
5379/// xmax is the end of the X axis, ymax is the end of the Y axis.
5380/// By default a margin of 10 per cent is left on all sides of the pad
5381/// Emits signal "RangeAxisChanged()", in the slot get the axis range
5382/// via GetRangeAxis().
5383
5385{
5386 if ((xmin >= xmax) || (ymin >= ymax)) {
5387 Error("RangeAxis", "illegal axis coordinates range: xmin=%f, ymin=%f, xmax=%f, ymax=%f",
5388 xmin, ymin, xmax, ymax);
5389 return;
5390 }
5391
5392 fUxmin = xmin;
5393 fUymin = ymin;
5394 fUxmax = xmax;
5395 fUymax = ymax;
5396
5397 // emit signal
5399}
5400
5401////////////////////////////////////////////////////////////////////////////////
5402/// Recursively remove object from a pad and its sub-pads.
5403
5405{
5406 if (fCanvas) {
5407 if (obj == fCanvas->GetSelected()) fCanvas->SetSelected(nullptr);
5408 if (obj == fCanvas->GetClickSelected()) fCanvas->SetClickSelected(nullptr);
5409 }
5410 if (obj == fView) fView = nullptr;
5411 if (!fPrimitives) return;
5414 if (nold != fPrimitives->GetSize()) fModified = kTRUE;
5415}
5416
5417////////////////////////////////////////////////////////////////////////////////
5418/// Remove object from list of primitives
5419/// When \par modified set to kTRUE (default) pad will be marked as modified - if object really removed
5420/// Returns result of GetListOfPrimitives()->Remove(obj) or nullptr if list of primitives not exists
5421
5423{
5424 TObject *res = nullptr;
5425 if (fPrimitives)
5426 res = fPrimitives->Remove(obj);
5427 if (res && modified)
5428 Modified();
5429 return res;
5430}
5431
5432////////////////////////////////////////////////////////////////////////////////
5433/// Redraw the frame axis.
5434///
5435/// Redrawing axis may be necessary in case of superimposed histograms
5436/// when one or more histograms have a fill color.
5437///
5438/// Instead of calling this function, it may be more convenient
5439/// to call directly `h1->Draw("sameaxis")` where h1 is the pointer
5440/// to the first histogram drawn in the pad.
5441///
5442/// By default, if the pad has the options gridx or/and gridy activated,
5443/// the grid is not drawn by this function.
5444///
5445/// If option="g" is specified, this will force the drawing of the grid
5446/// on top of the picture
5447///
5448/// To redraw the axis tick marks do:
5449/// ~~~ {.cpp}
5450/// gPad->RedrawAxis();
5451/// ~~~
5452/// To redraw the axis grid do:
5453/// ~~~ {.cpp}
5454/// gPad->RedrawAxis("G");
5455/// ~~~
5456/// To redraw the axis tick marks and the axis grid do:
5457/// ~~~ {.cpp}
5458/// gPad->RedrawAxis();
5459/// gPad->RedrawAxis("G");
5460/// ~~~
5461///
5462/// If option="f" is specified, this will force the drawing of the frame
5463/// around the plot.
5464
5466{
5467 TString opt = option;
5468 opt.ToLower();
5469
5470 TContext ctxt(this, kTRUE);
5471
5472 TH1 *hobj = nullptr;
5473
5474 // Get the first histogram drawing the axis in the list of primitives
5475 if (!fPrimitives) fPrimitives = new TList;
5476 TIter next(fPrimitives);
5477 TObject *obj;
5478 while ((obj = next())) {
5479 if (obj->InheritsFrom(TH1::Class())) {
5480 hobj = (TH1*)obj;
5481 break;
5482 }
5483 if (obj->InheritsFrom(TMultiGraph::Class())) {
5484 TMultiGraph *mg = (TMultiGraph*)obj;
5485 if (mg) hobj = mg->GetHistogram();
5486 break;
5487 }
5488 if (obj->InheritsFrom(TGraph::Class())) {
5489 TGraph *g = (TGraph*)obj;
5490 if (g) hobj = g->GetHistogram();
5491 break;
5492 }
5493 if (obj->InheritsFrom(THStack::Class())) {
5494 THStack *hs = (THStack*)obj;
5495 if (hs) hobj = hs->GetHistogram();
5496 break;
5497 }
5498 }
5499
5500 if (hobj) {
5501 if (opt.Contains("g")) hobj->DrawCopy("sameaxig");
5502 else hobj->DrawCopy("sameaxis");
5503 }
5504
5505 if (opt.Contains("f")) {
5506 auto b = new TBox(gPad->GetUxmin(), gPad->GetUymin(),
5507 gPad->GetUxmax(), gPad->GetUymax());
5508 b->SetFillStyle(0);
5509 b->SetLineStyle(gPad->GetFrameLineStyle());
5510 b->SetLineWidth(gPad->GetFrameLineWidth());
5511 b->SetLineColor(gPad->GetFrameLineColor());
5512 b->Draw();
5513 }
5514}
5515
5516////////////////////////////////////////////////////////////////////////////////
5517/// Compute pad conversion coefficients.
5518///
5519/// ### Conversion from x to px
5520///
5521/// \f[\frac{x-xmin}{xrange} = \frac{px-pxlow}{pxrange}\f]
5522/// with:
5523/// \f[ xrange = xmax-xmin \f]
5524/// \f[ pxrange = pxmax-pxmin \f]
5525///
5526/// \f[
5527/// \Rightarrow px = \frac{pxrange(x-xmin)}{xrange} + pxlow = fXtoPixelk + fXtoPixel \times x
5528/// \f]
5529///
5530/// \f[
5531/// \Rightarrow fXtoPixelk = pxlow - pxrange \frac{xmin}{xrange}
5532/// \f]
5533/// \f[
5534/// fXtoPixel = \frac{pxrange}{xrange}
5535/// \f]
5536/// where:
5537/// \f[
5538/// pxlow = fAbsXlowNDC \times fCw
5539/// \f]
5540/// \f[
5541/// pxrange = fAbsWNDC \times fCw
5542/// \f]
5543///
5544/// ### Conversion from y to py
5545///
5546/// \f[\frac{y-ymin}{yrange} = \frac{py-pylow}{pyrange}\f]
5547/// with:
5548/// \f[ yrange = ymax-ymin \f]
5549/// \f[ pyrange = pymax-pymin \f]
5550///
5551/// \f[
5552/// \Rightarrow py = \frac{pyrange(y-xmin)}{yrange} + pylow = fYtoPixelk + fYtoPixel \times y
5553/// \f]
5554///
5555/// \f[
5556/// \Rightarrow fYtoPixelk = pylow - pyrange \frac{ymin}{yrange}
5557/// \f]
5558/// \f[
5559/// fYtoPixel = \frac{pyrange}{yrange}
5560/// \f]
5561/// where:
5562/// \f[
5563/// pylow = fAbsYlowNDC \times fCh
5564/// \f]
5565/// \f[
5566/// pyrange = fAbsHNDC \times fCh
5567/// \f]
5568///
5569/// ### Conversion from px to x
5570///
5571/// \f[
5572/// \Rightarrow x = \frac{xrange(px-pxlow)}{pxrange}+ xmin = fPixeltoXk + fPixeltoX \times px
5573/// \f]
5574///
5575/// \f[
5576/// \Rightarrow fPixeltoXk = xmin - pxlow \times\frac{xrange}{pxrange}
5577/// \f]
5578/// \f[
5579/// fPixeltoX = \frac{xrange}{pxrange}
5580/// \f]
5581///
5582/// ### Conversion from py to y
5583///
5584/// \f[
5585/// \Rightarrow y = \frac{yrange(py-pylow)}{pyrange}+ ymin = fPixeltoYk + fPixeltoY \times py
5586/// \f]
5587///
5588/// \f[
5589/// \Rightarrow fPixeltoYk = ymin - pylow \times\frac{yrange}{pyrange}
5590/// \f]
5591/// \f[
5592/// fPixeltoY = \frac{yrange}{pyrange}
5593/// \f]
5594///
5595/// ### Computation of the coefficients in case of LOG scales
5596///
5597/// #### Conversion from pixel coordinates to world coordinates
5598///
5599/// \f[
5600/// u = \frac{Log(x) - Log(xmin)}{Log(xmax) - Log(xmin)} = \frac{Log(x/xmin)}{Log(xmax/xmin)} = \frac{px - pxlow}{pxrange}
5601/// \f]
5602///
5603/// \f[ \Rightarrow Log(\frac{x}{xmin}) = u \times Log(\frac{xmax}{xmin}) \f]
5604/// \f[ x = xmin \times e^{(u \times Log(\frac{xmax}{xmin})} \f]
5605/// Let:
5606/// \f[ alfa = \frac{Log(\frac{xmax}{xmin})}{fAbsWNDC} \f]
5607///
5608/// \f[ x = xmin \times e^{(-alfa \times pxlow)} + e^{(alfa \times px)} \f]
5609/// \f[ x = fPixeltoXk \times e^{(fPixeltoX \times px)} \f]
5610/// \f[ ==> fPixeltoXk = xmin \times e^{(-alfa*pxlow)} \f]
5611/// \f[ fPixeltoX = alfa \f]
5612///
5613/// \f[
5614/// v = \frac{Log(y) - Log(ymin)}{Log(ymax) - Log(ymin)} = \frac{Log(y/ymin)}{Log(ymax/ymin)} = \frac{py - pylow}{pyrange}
5615/// \f]
5616/// Let:
5617/// \f[ beta = Log(\frac{ymax}{ymin}) \f]
5618/// \f[ Log(\frac{y}{ymin}) = beta \times pylow - beta \times py \f]
5619/// \f[ \frac{y}{ymin} = e^{(beta \times pylow - beta \times py)} \f]
5620/// \f[ y = ymin \times e^{(beta \times pylow)} \times e^{(-beta \times py)}\f]
5621/// \f[ \Rightarrow y = fPixeltoYk \times e^{(fPixeltoY \times py)} \f]
5622/// \f[ fPixeltoYk = ymin \times e^{(beta \times pylow)} \f]
5623/// \f[ fPixeltoY = -beta \f]
5624///
5625/// #### Conversion from World coordinates to pixel coordinates
5626///
5627/// \f[ px = pxlow + u*pxrange \f]
5628/// \f[ = pxlow + Log(x/xmin)/alfa \f]
5629/// \f[ = pxlow -Log(xmin)/alfa + Log(x)/alfa \f]
5630/// \f[ = fXtoPixelk + fXtoPixel*Log(x) \f]
5631/// \f[ \Rightarrow fXtoPixelk = pxlow -Log(xmin)/alfa \f]
5632/// \f[ \Rightarrow fXtoPixel = 1/alfa \f]
5633///
5634/// \f[ py = pylow - Log(y/ymin)/beta \f]
5635/// \f[ = fYtoPixelk + fYtoPixel*Log(y) \f]
5636/// \f[ \Rightarrow fYtoPixelk = pylow - Log(ymin)/beta \f]
5637/// \f[ fYtoPixel = 1/beta \f]
5638
5640{
5641
5642 if (!gPad) {
5643 Error("ResizePad", "Cannot resize pad. No current pad available.");
5644 return;
5645 }
5646 if (gPad->GetWw()==0.0||gPad->GetWh()==0.0) {
5647 Warning("ResizePad", "gPad has at least one zero dimension.");
5648 return;
5649 }
5650 if (fX1==fX2||fY1==fY2) {
5651 Warning("ResizePad", "The pad has at least one zero dimension.");
5652 return;
5653 }
5654 // Recompute subpad positions in case pad has been moved/resized
5655 TPad *parent = fMother;
5656 if (this == gPad->GetCanvas()) {
5659 fAbsWNDC = fWNDC;
5660 fAbsHNDC = fHNDC;
5661 }
5662 else {
5663 if (parent->GetAbsHNDC()==0.0||parent->GetAbsWNDC()==0.0||fHNDC==0.0||fWNDC==0.0) {
5664 Warning("ResizePad", "The parent pad has at least one zero dimension.");
5665 return;
5666 }
5667 fAbsXlowNDC = fXlowNDC*parent->GetAbsWNDC() + parent->GetAbsXlowNDC();
5668 fAbsYlowNDC = fYlowNDC*parent->GetAbsHNDC() + parent->GetAbsYlowNDC();
5669 fAbsWNDC = fWNDC*parent->GetAbsWNDC();
5670 fAbsHNDC = fHNDC*parent->GetAbsHNDC();
5671 }
5672
5673 Double_t ww = (Double_t)gPad->GetWw();
5674 Double_t wh = (Double_t)gPad->GetWh();
5679
5680 // Linear X axis
5681 Double_t rounding = 0.; // was used before to adjust somehow wrong int trunctation by coordiantes transformation
5682 Double_t xrange = fX2 - fX1;
5683 fXtoAbsPixelk = rounding + pxlow - pxrange*fX1/xrange; //origin at left
5687 fPixeltoXk = fX1;
5689 // Linear Y axis
5690 Double_t yrange = fY2 - fY1;
5691 fYtoAbsPixelk = rounding + pylow - pyrange*fY1/yrange; //origin at top
5695 fPixeltoYk = fY1;
5697
5698 // Coefficients to convert from pad NDC coordinates to pixel coordinates
5699
5706
5707 // Coefficients to convert from canvas pixels to pad world coordinates
5708
5709 // Resize all sub-pads
5710 if (!fPrimitives)
5711 fPrimitives = new TList;
5712 TIter next(GetListOfPrimitives());
5713 while (auto obj = next()) {
5714 if (obj->InheritsFrom(TPad::Class()))
5715 ((TPad *)obj)->ResizePad(option);
5716 }
5717
5718 // Reset all current sizes
5719 if (gPad->IsBatch())
5720 fPixmapID = 0;
5721 else if (auto pp = GetPainter()) {
5722 if (pp->IsNative()) {
5723 // TODO: check if this is necessary
5724 auto attl = pp->GetAttLine();
5725 attl.SetLineColor(-1);
5726 pp->SetAttLine(attl);
5727 auto attt = pp->GetAttText();
5728 attt.SetTextSize(-1);
5729 pp->OnPad(this);
5730 pp->SetAttText(attt);
5731 // create or re-create off-screen pixmap
5732 if (fPixmapID) {
5733 int w = TMath::Abs(XtoPixel(fX2) - XtoPixel(fX1));
5734 int h = TMath::Abs(YtoPixel(fY2) - YtoPixel(fY1));
5735 //protection in case of wrong pad parameters.
5736 //without this protection, the OpenPixmap or ResizePixmap crashes with
5737 //the message "Error in <RootX11ErrorHandler>: BadValue (integer parameter out of range for operation)"
5738 //resulting in a frozen xterm
5741 Warning("ResizePad", "Inf/NaN propagated to the pad. Check drawn objects.");
5742 if (w <= 0 || w > 10000) {
5743 Warning("ResizePad", "%s width changed from %d to %d\n",GetName(),w,10);
5744 w = 10;
5745 }
5746 if (h <= 0 || h > 10000) {
5747 Warning("ResizePad", "%s height changed from %d to %d\n",GetName(),h,10);
5748 h = 10;
5749 }
5750 if (fPixmapID == -1) // this case is handled via the ctor
5751 fPixmapID = pp->CreateDrawable(w, h);
5752 else if (pp->ResizeDrawable(fPixmapID, w, h)) {
5753 Resized();
5754 Modified(kTRUE);
5755 }
5756 }
5757 }
5758 }
5759 if (fView) {
5760 if (gPad == this) {
5761 fView->ResizePad();
5762 } else {
5763 TContext ctxt(this, kTRUE);
5764 fView->ResizePad();
5765 }
5766 }
5767}
5768
5769////////////////////////////////////////////////////////////////////////////////
5770/// Save the pad content in a file.
5771///
5772/// The file's format used to save the pad is determined by the `filename` extension:
5773///
5774/// - if `filename` is empty, the file produced is `padname.ps`
5775/// - if `filename` starts with a dot, the padname is added in front
5776/// - if `filename` ends with `.ps`, a Postscript file is produced
5777/// - if `filename` ends with `.eps`, an Encapsulated Postscript file is produced
5778/// - 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.
5779/// - if `filename` ends with `.svg`, a SVG file is produced
5780/// - if `filename` ends with `.tex`, a TeX file is produced
5781/// - if `filename` ends with `.gif`, a GIF file is produced
5782/// - 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
5783/// - if `filename` ends with `.xpm`, a XPM file is produced
5784/// - if `filename` ends with `.png`, a PNG file is produced
5785/// - if `filename` ends with `.bmp`, a BMP file is produced
5786/// - if `filename` ends with `.jpg` or `.jpeg` a JPEG file is produced NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
5787/// - if `filename` ends with `.tiff`, a TIFF file is produced
5788/// - if `filename` ends with `.C`, `.cxx`,`.cpp` or `.cc`, a C++ macro file is produced
5789/// - if `filename` ends with `.root`, a Root file is produced
5790/// - if `filename` ends with `.xml`, a XML file is produced
5791/// - if `filename` ends with `.json`, a JSON file is produced
5792///
5793/// \remarks
5794/// - The parameter `option` is not used.
5795/// - This method calls [TPad::Print(const char *filename, Option_t *option)](\ref TPadPrint)
5796/// the value of `option` is determined by the `filename` extension.
5797/// - Postscript and PDF formats allow to have [several pictures in one file](\ref TPadPrintPS).
5798
5799void TPad::SaveAs(const char *filename, Option_t * /*option*/) const
5800{
5803
5804 if (!lenfil) { psname = GetName(); psname.Append(".ps"); }
5805 else psname = filename;
5806
5807 // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
5808 if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
5809 psname = GetName();
5810 psname.Append(filename);
5811 psname.Prepend("/");
5812 psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
5813 }
5814
5815 if (psname.EndsWith(".gif"))
5816 ((TPad*)this)->Print(psname,"gif");
5817 else if (psname.Contains(".gif+"))
5818 ((TPad*)this)->Print(psname,"gif+");
5819 else if (psname.EndsWith(".C") || psname.EndsWith(".cxx") || psname.EndsWith(".cpp") || psname.EndsWith(".cc"))
5820 ((TPad*)this)->Print(psname,"cxx");
5821 else if (psname.EndsWith(".root"))
5822 ((TPad*)this)->Print(psname,"root");
5823 else if (psname.EndsWith(".xml"))
5824 ((TPad*)this)->Print(psname,"xml");
5825 else if (psname.EndsWith(".json"))
5826 ((TPad*)this)->Print(psname,"json");
5827 else if (psname.EndsWith(".eps"))
5828 ((TPad*)this)->Print(psname,"eps");
5829 else if (psname.EndsWith(".pdf"))
5830 ((TPad*)this)->Print(psname,"pdf");
5831 else if (psname.EndsWith(".pdf["))
5832 ((TPad*)this)->Print(psname,"pdf");
5833 else if (psname.EndsWith(".pdf]"))
5834 ((TPad*)this)->Print(psname,"pdf");
5835 else if (psname.EndsWith(".pdf("))
5836 ((TPad*)this)->Print(psname,"pdf");
5837 else if (psname.EndsWith(".pdf)"))
5838 ((TPad*)this)->Print(psname,"pdf");
5839 else if (psname.EndsWith(".svg"))
5840 ((TPad*)this)->Print(psname,"svg");
5841 else if (psname.EndsWith(".tex"))
5842 ((TPad*)this)->Print(psname,"tex");
5843 else if (psname.EndsWith(".xpm"))
5844 ((TPad*)this)->Print(psname,"xpm");
5845 else if (psname.EndsWith(".png"))
5846 ((TPad*)this)->Print(psname,"png");
5847 else if (psname.EndsWith(".jpg"))
5848 ((TPad*)this)->Print(psname,"jpg");
5849 else if (psname.EndsWith(".jpeg"))
5850 ((TPad*)this)->Print(psname,"jpg");
5851 else if (psname.EndsWith(".bmp"))
5852 ((TPad*)this)->Print(psname,"bmp");
5853 else if (psname.EndsWith(".tiff"))
5854 ((TPad*)this)->Print(psname,"tiff");
5855 else
5856 ((TPad*)this)->Print(psname,"ps");
5857}
5858
5859////////////////////////////////////////////////////////////////////////////////
5860/// Save primitives in this pad on the C++ source file out.
5861
5862void TPad::SavePrimitive(std::ostream &out, Option_t * option /*= ""*/)
5863{
5864 TContext ctxt(this, kFALSE); // not interactive
5865
5867
5868 // check for space in the pad name
5869 auto p = padName.Index(" ");
5870 if (p != kNPOS)
5871 padName.Resize(p);
5872
5873 TString opt = option;
5874 if (!opt.Contains("toplevel")) {
5875 static Int_t pcounter = 0;
5876 padName += TString::Format("__%d", pcounter++);
5877 padName = gInterpreter->MapCppName(padName);
5878 }
5879
5880 const char *pname = padName.Data();
5881 const char *cname = padName.Data();
5882
5883 if (padName.Length() == 0) {
5884 pname = "unnamed";
5885 if (this == gPad->GetCanvas())
5886 cname = "c1";
5887 else
5888 cname = "pad";
5889 }
5890
5891 // Write pad parameters
5892 if (this != gPad->GetCanvas()) {
5893 out << " \n";
5894 out << "// ------------>Primitives in pad: " << GetName() << "\n";
5895 out << " TPad *" << cname << " = new TPad(\"" << GetName() << "\", \""
5896 << TString(GetTitle()).ReplaceSpecialCppChars() << "\", " << fXlowNDC << ", " << fYlowNDC << ", "
5897 << fXlowNDC + fWNDC << ", " << fYlowNDC + fHNDC << ");\n";
5898 out << " " << cname << "->Draw();\n";
5899 out << " " << cname << "->cd();\n";
5900 }
5901 out << " " << cname << "->Range(" << fX1 << "," << fY1 << "," << fX2 << "," << fY2 << ");\n";
5902 TView *view = GetView();
5903 if (view) {
5904 Double_t rmin[3], rmax[3];
5905 view->GetRange(rmin, rmax);
5906 out << " TView::CreateView(1)->SetRange(" << rmin[0] << ", " << rmin[1] << ", " << rmin[2] << ", " << rmax[0]
5907 << ", " << rmax[1] << ", " << rmax[2] << ");\n";
5908 }
5909
5910 SaveFillAttributes(out, cname, -1, -1);
5911
5912 if (GetBorderMode() != 1)
5913 out << " " << cname << "->SetBorderMode(" << GetBorderMode() << ");\n";
5914 if (GetBorderSize() != 4)
5915 out << " " << cname << "->SetBorderSize(" << GetBorderSize() << ");\n";
5916 if (GetLogx())
5917 out << " " << cname << "->SetLogx();\n";
5918 if (GetLogy())
5919 out << " " << cname << "->SetLogy();\n";
5920 if (GetLogz())
5921 out << " " << cname << "->SetLogz();\n";
5922 if (GetGridx())
5923 out << " " << cname << "->SetGridx();\n";
5924 if (GetGridy())
5925 out << " " << cname << "->SetGridy();\n";
5926 if (GetTickx())
5927 out << " " << cname << "->SetTickx(" << GetTickx() << ");\n";
5928 if (GetTicky())
5929 out << " " << cname << "->SetTicky(" << GetTicky() << ");\n";
5930 if (GetTheta() != 30)
5931 out << " " << cname << "->SetTheta(" << GetTheta() << ");\n";
5932 if (GetPhi() != 30)
5933 out << " " << cname << "->SetPhi(" << GetPhi() << ");\n";
5934 if (TMath::Abs(fLeftMargin - 0.1) > 0.01)
5935 out << " " << cname << "->SetLeftMargin(" << GetLeftMargin() << ");\n";
5936 if (TMath::Abs(fRightMargin - 0.1) > 0.01)
5937 out << " " << cname << "->SetRightMargin(" << GetRightMargin() << ");\n";
5938 if (TMath::Abs(fTopMargin - 0.1) > 0.01)
5939 out << " " << cname << "->SetTopMargin(" << GetTopMargin() << ");\n";
5940 if (TMath::Abs(fBottomMargin - 0.1) > 0.01)
5941 out << " " << cname << "->SetBottomMargin(" << GetBottomMargin() << ");\n";
5942
5944 out << " " << cname << "->SetFrameFillColor(" << TColor::SavePrimitiveColor(GetFrameFillColor()) << ");\n";
5945 if (GetFrameFillStyle() != 1001)
5946 out << " " << cname << "->SetFrameFillStyle(" << GetFrameFillStyle() << ");\n";
5947 if (GetFrameLineStyle() != 1)
5948 out << " " << cname << "->SetFrameLineStyle(" << GetFrameLineStyle() << ");\n";
5949 if (GetFrameLineColor() != 1)
5950 out << " " << cname << "->SetFrameLineColor(" << TColor::SavePrimitiveColor(GetFrameLineColor()) << ");\n";
5951 if (GetFrameLineWidth() != 1)
5952 out << " " << cname << "->SetFrameLineWidth(" << GetFrameLineWidth() << ");\n";
5953 if (GetFrameBorderMode() != 0)
5954 out << " " << cname << "->SetFrameBorderMode(" << GetFrameBorderMode() << ");\n";
5955 if (GetFrameBorderSize() != 1)
5956 out << " " << cname << "->SetFrameBorderSize(" << GetFrameBorderSize() << ");\n";
5957
5958 TFrame *frame = fFrame;
5959 if (!frame)
5960 frame = (TFrame *)GetPrimitive("TFrame");
5961 if (frame) {
5962 if (frame->GetFillColor() != GetFillColor())
5963 out << " " << cname << "->SetFrameFillColor(" << TColor::SavePrimitiveColor(frame->GetFillColor()) << ");\n";
5964 if (frame->GetFillStyle() != 1001)
5965 out << " " << cname << "->SetFrameFillStyle(" << frame->GetFillStyle() << ");\n";
5966 if (frame->GetLineStyle() != 1)
5967 out << " " << cname << "->SetFrameLineStyle(" << frame->GetLineStyle() << ");\n";
5968 if (frame->GetLineColor() != 1)
5969 out << " " << cname << "->SetFrameLineColor(" << TColor::SavePrimitiveColor(frame->GetLineColor()) << ");\n";
5970 if (frame->GetLineWidth() != 1)
5971 out << " " << cname << "->SetFrameLineWidth(" << frame->GetLineWidth() << ");\n";
5972 if (frame->GetBorderMode() != 0)
5973 out << " " << cname << "->SetFrameBorderMode(" << frame->GetBorderMode() << ");\n";
5974 if (frame->GetBorderSize() != 1)
5975 out << " " << cname << "->SetFrameBorderSize(" << frame->GetBorderSize() << ");\n";
5976 }
5977
5978 TIter next(GetListOfPrimitives());
5979
5980 while (auto obj = next()) {
5981 obj->SavePrimitive(out, (Option_t *)next.GetOption());
5982 if (obj->InheritsFrom(TPad::Class())) {
5983 if (opt.Contains("toplevel"))
5984 out << " " << pname << "->cd();\n";
5985 else
5986 out << " " << cname << "->cd();\n";
5987 }
5988 }
5989 out << " " << cname << "->Modified();\n";
5990}
5991
5992////////////////////////////////////////////////////////////////////////////////
5993/// Fix pad aspect ratio to current value if fixed is true.
5994
5996{
5997 if (fixed) {
5998 if (!fFixedAspectRatio) {
5999 if (fHNDC != 0.)
6001 else {
6002 Error("SetAspectRatio", "cannot fix aspect ratio, height of pad is 0");
6003 return;
6004 }
6006 }
6007 } else {
6009 fAspectRatio = 0;
6010 }
6011}
6012
6013////////////////////////////////////////////////////////////////////////////////
6014/// Set pad editable yes/no
6015/// If a pad is not editable:
6016/// - one cannot modify the pad and its objects via the mouse.
6017/// - one cannot add new objects to the pad
6018
6020{
6021 fEditable = mode;
6022
6023 TObject *obj;
6024 if (!fPrimitives) fPrimitives = new TList;
6025 TIter next(GetListOfPrimitives());
6026 while ((obj = next())) {
6027 if (obj->InheritsFrom(TPad::Class())) {
6028 TPad *pad = (TPad*)obj;
6029 pad->SetEditable(mode);
6030 }
6031 }
6032}
6033
6034////////////////////////////////////////////////////////////////////////////////
6035/// Override TAttFill::FillStyle for TPad because we want to handle style=0
6036/// as style 4000.
6037
6039{
6040 if (fstyle == 0) fstyle = 4000;
6042}
6043
6044////////////////////////////////////////////////////////////////////////////////
6045/// Set Lin/Log scale for X
6046/// - value = 0 X scale will be linear
6047/// - value = 1 X scale will be logarithmic (base 10)
6048/// - value > 1 reserved for possible support of base e or other
6049
6051{
6052 fLogx = value;
6053 delete fView; fView = nullptr;
6054 Modified();
6056}
6057
6058////////////////////////////////////////////////////////////////////////////////
6059/// Set Lin/Log scale for Y
6060/// - value = 0 Y scale will be linear
6061/// - value = 1 Y scale will be logarithmic (base 10)
6062/// - value > 1 reserved for possible support of base e or other
6063
6065{
6066 fLogy = value;
6067 delete fView; fView = nullptr;
6068 Modified();
6070}
6071
6072////////////////////////////////////////////////////////////////////////////////
6073/// Set Lin/Log scale for Z
6074
6076{
6077 fLogz = value;
6078 delete fView; fView = nullptr;
6079 Modified();
6081}
6082
6083////////////////////////////////////////////////////////////////////////////////
6084/// Set canvas range for pad and resize the pad. If the aspect ratio
6085/// was fixed before the call it will be un-fixed.
6086
6088{
6089 // Reorder points to make sure xlow,ylow is bottom left point and
6090 // xup,yup is top right point.
6091 if (xup < xlow) {
6092 Double_t x = xlow;
6093 xlow = xup;
6094 xup = x;
6095 }
6096 if (yup < ylow) {
6097 Double_t y = ylow;
6098 ylow = yup;
6099 yup = y;
6100 }
6101
6102 // Check if the new pad position is valid.
6103 if ((xlow < 0) || (xlow > 1) || (ylow < 0) || (ylow > 1)) {
6104 Error("TPad", "illegal bottom left position: x=%f, y=%f", xlow, ylow);
6105 return;
6106 }
6107 if ((xup < 0) || (xup > 1) || (yup < 0) || (yup > 1)) {
6108 Error("TPad", "illegal top right position: x=%f, y=%f", xup, yup);
6109 return;
6110 }
6111 if (xup-xlow <= 0) {
6112 Error("TPad", "illegal width: %f", xup-xlow);
6113 return;
6114 }
6115 if (yup-ylow <= 0) {
6116 Error("TPad", "illegal height: %f", yup-ylow);
6117 return;
6118 }
6119
6120 fXlowNDC = xlow;
6121 fYlowNDC = ylow;
6122 fXUpNDC = xup;
6123 fYUpNDC = yup;
6124 fWNDC = xup - xlow;
6125 fHNDC = yup - ylow;
6126
6128
6129 ResizePad();
6130}
6131
6132////////////////////////////////////////////////////////////////////////////////
6133/// Set all pad parameters.
6134
6135void TPad::SetPad(const char *name, const char *title,
6136 Double_t xlow, Double_t ylow, Double_t xup, Double_t yup,
6138{
6139 fName = name;
6140 fTitle = title;
6141 SetFillStyle(1001);
6146 if (color >= 0) SetFillColor(color);
6149 else fBorderSize = bordersize;
6151 else fBorderMode = bordermode;
6152
6153 SetPad(xlow, ylow, xup, yup);
6154}
6155
6156////////////////////////////////////////////////////////////////////////////////
6157/// Set the current TView. Delete previous view if view=0
6158
6160{
6161 if (!view) delete fView;
6162 fView = view;
6163}
6164
6165////////////////////////////////////////////////////////////////////////////////
6166/// Set postscript fill area attributes.
6167///
6168/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6169
6171{
6172 if (auto pp = GetPainter())
6173 if (pp->GetPS())
6174 pp->SetAttFill({color, style});
6175}
6176
6177////////////////////////////////////////////////////////////////////////////////
6178/// Set postscript line attributes.
6179///
6180/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6181
6183{
6184 if (auto pp = GetPainter())
6185 if (pp->GetPS())
6186 pp->SetAttLine({color, style, lwidth});
6187}
6188
6189////////////////////////////////////////////////////////////////////////////////
6190/// Set postscript marker attributes.
6191///
6192/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6193
6195{
6196 if (auto pp = GetPainter())
6197 if (pp->GetPS())
6198 pp->SetAttMarker({color, style, msize});
6199}
6200
6201////////////////////////////////////////////////////////////////////////////////
6202/// Set postscript text attributes.
6203///
6204/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6205
6207{
6208 if (auto pp = GetPainter())
6209 if (pp->GetPS()) {
6210 if (font % 10 > 2) {
6213 Float_t dy;
6214 if (wh < hh) {
6216 tsize = dy/(GetX2()-GetX1());
6217 } else {
6219 tsize = dy/(GetY2()-GetY1());
6220 }
6221 }
6222 pp->OnPad(this);
6223 pp->SetAttText({align, angle, color, font, tsize});
6224 }
6225}
6226
6227////////////////////////////////////////////////////////////////////////////////
6228/// Draw Arrows to indicated equal distances of Objects with given BBoxes.
6229/// Used by ShowGuidelines
6230
6232{
6233 Int_t lineColor = TColor::GetColor(239, 202, 0);
6234 Int_t x1,x2,y1,y2;
6235 x1 = x2 = y1 = y2 = 0;
6236 if (mode == 'x') {
6237 if (aBBox.fX<bBBox.fX) {
6238 x1 = aBBox.fX+aBBox.fWidth;
6239 x2 = bBBox.fX;
6240 }
6241 else {
6242 x1 = bBBox.fX+bBBox.fWidth;
6243 x2 = aBBox.fX;
6244 }
6245
6246 if ((aBBox.fY > bBBox.fY) && (aBBox.fY + aBBox.fHeight < bBBox.fY + bBBox.fHeight))
6247 y1 = y2 = aBBox.fY + TMath::Nint(0.5*(Double_t)(aBBox.fHeight))+1;
6248 else if ((bBBox.fY > aBBox.fY) && (bBBox.fY + bBBox.fHeight < aBBox.fY + aBBox.fHeight))
6249 y1 = y2 = bBBox.fY + TMath::Nint(0.5*(Double_t)(bBBox.fHeight))+1;
6250 else if (aBBox.fY>bBBox.fY) y1 = y2 = aBBox.fY-TMath::Nint(0.5*(Double_t)(aBBox.fY-(bBBox.fY+bBBox.fHeight)));
6251 else y1 = y2 = bBBox.fY-TMath::Nint(0.5*(Double_t)(bBBox.fY-(aBBox.fY+aBBox.fHeight)));
6252 }
6253 else if (mode == 'y') {
6254 if (aBBox.fY<bBBox.fY) {
6255 y1 = aBBox.fY+aBBox.fHeight;
6256 y2 = bBBox.fY;
6257 }
6258 else {
6259 y1 = bBBox.fY+bBBox.fHeight;
6260 y2 = aBBox.fY;
6261 }
6262 if ((aBBox.fX > bBBox.fX) && (aBBox.fX + aBBox.fWidth < bBBox.fX + bBBox.fWidth))
6263 x1 = x2 = aBBox.fX + TMath::Nint(0.5*(Double_t)(aBBox.fWidth))+1;
6264 else if ((bBBox.fX > aBBox.fX) && (bBBox.fX + bBBox.fWidth < aBBox.fX + aBBox.fWidth))
6265 x1 = x2 = bBBox.fX + TMath::Nint(0.5*(Double_t)(bBBox.fWidth))+1;
6266 else if (aBBox.fX>bBBox.fX) x1 = x2 = aBBox.fX+TMath::Nint(0.5*(Double_t)(bBBox.fX+bBBox.fWidth-aBBox.fX));
6267 else x1 = x2 = bBBox.fX+TMath::Nint(0.5*(Double_t)(aBBox.fX+aBBox.fWidth-bBBox.fX));
6268 }
6269
6270 TArrow *A = new TArrow(gPad->PixeltoX(x1), gPad->PixeltoY(y1-gPad->VtoPixel(0)), gPad->PixeltoX(x2), gPad->PixeltoY(y2-gPad->VtoPixel(0)), 0.01, "<|>");
6271 A->SetBit(kCanDelete);
6273 A->SetLineWidth(1);
6275 A->Draw();
6276
6277 return;
6278}
6279
6280////////////////////////////////////////////////////////////////////////////////
6281/// struct used by ShowGuidelines to store the distance Field between objects
6282/// in the canvas.
6283
6284struct dField {
6288 char fdir;
6289
6290
6292 : fa(nullptr), fb(nullptr), fdist(0), fdir(' ')
6293 {}
6294
6296 : fa(a), fb(b), fdist(dist), fdir(direction)
6297 {}
6298};
6299
6300////////////////////////////////////////////////////////////////////////////////
6301/// Shows lines to indicate if a TAttBBox2D object is aligned to
6302/// the center or to another object, shows distance arrows if two
6303/// objects on screen have the same distance to another object
6304/// Call from primitive in Execute Event, in ButtonMotion after
6305/// the new coordinates have been set, to 'stick'
6306/// once when button is up to delete lines
6307///
6308/// modes: t (Top), b (bottom), l (left), r (right), i (inside)
6309/// in resize modes (t,b,l,r) only size arrows are sticky
6310///
6311/// in mode, the function gets the point on the element that is clicked to
6312/// move (i) or resize (all others). The expected values are:
6313/// \image html gpad_pad5.png
6314
6315void TPad::ShowGuidelines(TObject *object, const Int_t event, const char mode, const bool cling )
6316{
6317 // When the object is moved with arrow or when the ShowGuideLines flag
6318 // is off we do show guide lines.
6319 if ((event == kArrowKeyRelease) || (event == kArrowKeyPress) ||
6320 !gEnv->GetValue("Canvas.ShowGuideLines", 0)) return;
6321
6322 std::vector<dField> curDist;
6323 std::vector<dField> otherDist;
6324 Int_t pMX, pMY;
6325 Double_t MX, MY;
6327 TList *prims;
6328 UInt_t n;
6330 aBBox = bBBox = Rectangle_t();
6331 TLine *L;
6332 TArrow *A;
6333 Int_t dSizeArrow = 12; // distance of arrows indicating same size from BBox in px
6334 Bool_t movedX, movedY; // make sure the current object is moved just once
6335 movedX = movedY = false;
6336 Bool_t resize = false; // indicates resize mode
6337 Bool_t log = gPad->GetLogx() || gPad->GetLogy();
6338 if (mode != 'i') resize = true;
6339
6340 TPad *is_pad = dynamic_cast<TPad *>( object );
6341
6343
6344 if (is_pad && is_pad->GetMother())
6345 is_pad->GetMother()->cd();
6346
6347 static TPad *tmpGuideLinePad = nullptr;
6348
6349 //delete all existing Guidelines and create new invisible pad
6350 if (tmpGuideLinePad) {
6351 ctxt.PadDeleted(tmpGuideLinePad);
6352 auto guidePadClicked = (object == tmpGuideLinePad); // in case of funny button click combination.
6353 tmpGuideLinePad->Delete();
6354 tmpGuideLinePad = nullptr;
6355 if (guidePadClicked) return;
6356 }
6357
6358 // Get Primitives
6359 prims = gPad->GetListOfPrimitives();
6360 n = TMath::Min(15,prims->GetSize());
6361 Int_t lineColor = TColor::GetColor(239, 202, 0);
6362
6363 TAttBBox2D *cur = dynamic_cast<TAttBBox2D *>( object );
6364 if (cur) {
6365 //create invisible TPad above gPad
6366 if (!tmpGuideLinePad){
6367 tmpGuideLinePad = new TPad("tmpGuideLinePad", "tmpGuideLinePad", 0, 0, 1, 1);
6368 Double_t x1, y1, x2, y2;
6369 gPad->GetRange(x1, y1, x2, y2);
6370 tmpGuideLinePad->Range(x1, y1, x2, y2);
6371 tmpGuideLinePad->SetFillStyle(0);
6372 tmpGuideLinePad->SetFillColor(0);
6373 tmpGuideLinePad->Draw();
6374 tmpGuideLinePad->cd();
6375 gPad->GetRange(x1, y1, x2, y2);
6376 }
6377 if (cling && !log) threshold = 7;
6378 else threshold = 1;
6379
6380 Rectangle_t BBox = cur->GetBBox();
6381 TPoint center = cur->GetBBoxCenter();
6382
6383 otherDist.clear();
6384 curDist.clear();
6385
6386 switch (event) {
6387
6388 case kButton1Down:
6389 case kButton1Motion:
6390 MX = gPad->GetX1() + 0.5 * (gPad->GetX2()-gPad->GetX1());
6391 MY = gPad->GetY1() + 0.5 * (gPad->GetY2()-gPad->GetY1());
6392 pMX = gPad->XtoPixel(MX);
6393 pMY = gPad->YtoPixel(MY);
6394 // Middlelines
6395 if (TMath::Abs(pMX-center.GetX())<threshold) {
6396 if (cling && (!resize)) {
6397 cur->SetBBoxCenterX(pMX);
6398 center = cur->GetBBoxCenter();
6399 BBox = cur->GetBBox();
6400 center = cur->GetBBoxCenter();
6401 }
6402 L = new TLine(MX, gPad->GetY1(), MX, gPad->GetY2());
6403 L->SetBit(kCanDelete);
6404 L->SetLineColor(lineColor);
6405 L->Draw();
6406 }
6407 if (TMath::Abs(pMY-center.GetY())<threshold) {
6408 if (cling && (!resize)) {
6409 cur->SetBBoxCenterY(pMY);
6410 center = cur->GetBBoxCenter();
6411 BBox = cur->GetBBox();
6412 center = cur->GetBBoxCenter();
6413 }
6414 L = new TLine(gPad->GetX1(), MY, gPad->GetX2(), MY);
6415 L->SetBit(kCanDelete);
6416 L->SetLineColor(lineColor);
6417 L->Draw();
6418 }
6419 // Alignment to other objects
6420 for (UInt_t i = 0; i<n; i++) {
6421 TAttBBox2D *other = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6422 if (other) {
6423 if (other != cur) {
6424 TPoint centerOther = other->GetBBoxCenter();
6425 if (TMath::Abs(center.GetX()-centerOther.GetX())<threshold) {
6426 if (cling && (!resize)) {
6427 cur->SetBBoxCenterX(centerOther.GetX());
6428 BBox = cur->GetBBox();
6429 center = cur->GetBBoxCenter();
6430 }
6431 L = new TLine(gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(center.GetY()-gPad->VtoPixel(0)),
6432 gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)));
6433 L->SetLineColor(lineColor);
6434 L->Draw();
6435 L->SetBit(kCanDelete);
6436 }
6437 if (TMath::Abs(center.GetY()-centerOther.GetY())<threshold) {
6438 if (cling && (!resize)) {
6439 cur->SetBBoxCenterY(centerOther.GetY());
6440 BBox = cur->GetBBox();
6441 center = cur->GetBBoxCenter();
6442 }
6443 L = new TLine(gPad->PixeltoX(center.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)),
6444 gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)));
6445 L->SetBit(kCanDelete);
6446 L->SetLineColor(lineColor);
6447 L->Draw();
6448 }
6449 }
6450 }
6451 }
6452 // Get Distances between objects
6453 for (UInt_t i = 0; i<n; i++) {
6454 TAttBBox2D *a = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6455 if (a) {
6456 aBBox = a->GetBBox();
6457 for (UInt_t j = i+1; j<n; j++) {
6458 TAttBBox2D *b = dynamic_cast<TAttBBox2D *>( prims->At(j) );
6459 if (b) {
6460 bBBox = b->GetBBox();
6461
6462 //only when bounding boxes overlap in x or y direction
6463 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
6464 if ((aBBox.fY+aBBox.fHeight<bBBox.fY)||(bBBox.fY+bBBox.fHeight<aBBox.fY)) {//No overlap in Y-direction required
6465 dField abDist = dField();
6466 if (aBBox.fY>bBBox.fY) abDist = dField(a, b, TMath::Abs(aBBox.fY-(bBBox.fY+bBBox.fHeight)), 'y');
6467 else abDist = dField(a, b, TMath::Abs(bBBox.fY-(aBBox.fY+aBBox.fHeight)), 'y');
6468 if ((b != cur)&&(a != cur)) otherDist.push_back(abDist);
6469 else curDist.push_back(abDist);
6470 }
6471 } 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
6472 if ((aBBox.fX+aBBox.fWidth<bBBox.fX)||(bBBox.fX+bBBox.fWidth<aBBox.fX)) {//No overlap in x-direction required
6473 dField abDist = dField();
6474 if (aBBox.fX>bBBox.fX) abDist = dField(a, b, TMath::Abs(aBBox.fX-(bBBox.fX+bBBox.fWidth)), 'x');
6475 else abDist = dField(a, b, TMath::Abs(bBBox.fX-(aBBox.fX+aBBox.fWidth)), 'x');
6476 if ((b != cur)&&(a != cur)) otherDist.push_back(abDist);
6477 else curDist.push_back(abDist);
6478 }
6479 }
6480 }
6481 }
6482 }
6483 }
6484 // Show equal distances
6485 for (UInt_t i = 0; i<curDist.size(); i++) {
6486 for (UInt_t j = 0; j<otherDist.size(); j++) {
6487 if ((curDist[i].fdir == otherDist[j].fdir) && (otherDist[j].fdir=='x') && (TMath::Abs(curDist[i].fdist-otherDist[j].fdist)<threshold)) {
6488 if (cling && (!movedX) && (!resize)) {
6489 if ((cur->GetBBoxCenter().fX < curDist[i].fb->GetBBoxCenter().fX)||(cur->GetBBoxCenter().fX < curDist[i].fa->GetBBoxCenter().fX))
6490 cur->SetBBoxCenterX(cur->GetBBoxCenter().fX - otherDist[j].fdist + curDist[i].fdist);
6491 else cur->SetBBoxCenterX(cur->GetBBoxCenter().fX + otherDist[j].fdist - curDist[i].fdist);
6492 movedX = true;
6493 }
6494 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'x');
6495 DrawDist(otherDist[j].fa->GetBBox(), otherDist[j].fb->GetBBox(), 'x');
6496 }
6497 if ((curDist[i].fdir == otherDist[j].fdir) && (otherDist[j].fdir=='y') && (TMath::Abs(curDist[i].fdist-otherDist[j].fdist)<threshold)) {
6498 if (cling && (!movedY) && (!resize)) {
6499 if ((cur->GetBBoxCenter().fY < curDist[i].fb->GetBBoxCenter().fY)||(cur->GetBBoxCenter().fY < curDist[i].fa->GetBBoxCenter().fY))
6500 cur->SetBBoxCenterY(cur->GetBBoxCenter().fY - otherDist[j].fdist + curDist[i].fdist);
6501 else cur->SetBBoxCenterY(cur->GetBBoxCenter().fY + otherDist[j].fdist - curDist[i].fdist);
6502 movedY = true;
6503 }
6504 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'y');
6505 DrawDist(otherDist[j].fa->GetBBox(), otherDist[j].fb->GetBBox(), 'y');
6506 }
6507 }
6508 for (UInt_t j = i; j<curDist.size(); j++) {
6509 if (i!=j) {
6510 if ((curDist[i].fdir == curDist[j].fdir) && (curDist[j].fdir=='x') && (TMath::Abs(curDist[i].fdist-curDist[j].fdist)<threshold)) {
6511 if (cling && (!movedX) && (!resize)) {
6512 if ((cur->GetBBoxCenter().fX < curDist[i].fb->GetBBoxCenter().fX)||(cur->GetBBoxCenter().fX < curDist[i].fa->GetBBoxCenter().fX))
6513 cur->SetBBoxCenterX(cur->GetBBoxCenter().fX - floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6514 else cur->SetBBoxCenterX(cur->GetBBoxCenter().fX + floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6515 }
6516 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'x');
6517 DrawDist(curDist[j].fa->GetBBox(), curDist[j].fb->GetBBox(), 'x');
6518 }
6519
6520 if ((curDist[i].fdir == curDist[j].fdir) && (curDist[j].fdir=='y') && (TMath::Abs(curDist[i].fdist-curDist[j].fdist)<threshold)) {
6521 if (cling && (!movedY) && (!resize)) {
6522 if ((cur->GetBBoxCenter().fY < curDist[i].fb->GetBBoxCenter().fY)||(cur->GetBBoxCenter().fY < curDist[i].fa->GetBBoxCenter().fY))
6523 cur->SetBBoxCenterY(cur->GetBBoxCenter().fY - floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6524 else cur->SetBBoxCenterY(cur->GetBBoxCenter().fY + floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6525 }
6526 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'y');
6527 DrawDist(curDist[j].fa->GetBBox(), curDist[j].fb->GetBBox(), 'y');
6528 }
6529 }
6530 }
6531 }
6532 if (resize) {
6533 // Show equal Sizes
6534 for (UInt_t i = 0; i<n; i++) {
6535 TAttBBox2D *a = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6536 if (a && (cur != a)) {
6537 aBBox = a->GetBBox();
6538
6539 if ((TMath::Abs(aBBox.fWidth - BBox.fWidth)<threshold) && (mode != 't') && (mode != 'b')) {
6540 if (cling) {
6541 if (mode == 'l') cur->SetBBoxX1(BBox.fX + BBox.fWidth - aBBox.fWidth);
6542 if (mode == 'r') cur->SetBBoxX2(BBox.fX + aBBox.fWidth);
6543 if ((mode == '1')||(mode == '4')) cur->SetBBoxX1(BBox.fX + BBox.fWidth - aBBox.fWidth);
6544 if ((mode == '2')||(mode == '3')) cur->SetBBoxX2(BBox.fX + aBBox.fWidth);
6545 BBox = cur->GetBBox();
6546 }
6547
6548 A = new TArrow(gPad->PixeltoX(aBBox.fX), gPad->PixeltoY(aBBox.fY-dSizeArrow-gPad->VtoPixel(0)),
6549 gPad->PixeltoX(aBBox.fX+aBBox.fWidth), gPad->PixeltoY(aBBox.fY-dSizeArrow-gPad->VtoPixel(0)), 0.01, "<|>");
6550 A->SetBit(kCanDelete);
6553 A->Draw();
6554
6555 A = new TArrow(gPad->PixeltoX(BBox.fX), gPad->PixeltoY(BBox.fY-dSizeArrow-gPad->VtoPixel(0)),
6556 gPad->PixeltoX(BBox.fX+BBox.fWidth), gPad->PixeltoY(BBox.fY-dSizeArrow-gPad->VtoPixel(0)), 0.01, "<|>");
6557 A->SetBit(kCanDelete);
6560 A->Draw();
6561 }
6562 if ((TMath::Abs(aBBox.fHeight - BBox.fHeight)<threshold) && (mode != 'r') && (mode != 'l')) {
6563 if (cling) {
6564 if (mode == 't') cur->SetBBoxY1(BBox.fY + BBox.fHeight - aBBox.fHeight);
6565 if (mode == 'b') cur->SetBBoxY2(BBox.fY + aBBox.fHeight);
6566 if ((mode == '1')||(mode == '2')) cur->SetBBoxY1(BBox.fY + BBox.fHeight - aBBox.fHeight);
6567 if ((mode == '3')||(mode == '4')) cur->SetBBoxY2(BBox.fY + aBBox.fHeight);
6568 BBox = cur->GetBBox();
6569 }
6570 A = new TArrow(gPad->PixeltoX(aBBox.fX-dSizeArrow), gPad->PixeltoY(aBBox.fY-gPad->VtoPixel(0)),
6571 gPad->PixeltoX(aBBox.fX-dSizeArrow), gPad->PixeltoY(aBBox.fY+aBBox.fHeight-gPad->VtoPixel(0)), 0.01, "<|>");
6572 A->SetBit(kCanDelete);
6575 A->Draw();
6576
6577 A = new TArrow(gPad->PixeltoX(BBox.fX-dSizeArrow), gPad->PixeltoY(BBox.fY-gPad->VtoPixel(0)),
6578 gPad->PixeltoX(BBox.fX-dSizeArrow), gPad->PixeltoY(BBox.fY+BBox.fHeight-gPad->VtoPixel(0)), 0.01, "<|>");
6579 A->SetBit(kCanDelete);
6582 A->Draw();
6583 }
6584 }
6585 }
6586 }
6587
6588 break;
6589
6590 case kButton1Up:
6591 if (tmpGuideLinePad) {
6592 // All the arrows and lines in that pad are also deleted because
6593 // they all have the bit kCanDelete on.
6594 tmpGuideLinePad->Delete();
6595 tmpGuideLinePad = nullptr;
6596 }
6597 break;
6598 }
6599 }
6600
6601 gPad->Modified(kTRUE);
6602}
6603
6604////////////////////////////////////////////////////////////////////////////////
6605/// Return kTRUE if the crosshair has been activated (via SetCrosshair).
6606
6608{
6609 return (Bool_t)GetCrosshair();
6610}
6611
6612////////////////////////////////////////////////////////////////////////////////
6613/// Return the crosshair type (from the mother canvas)
6614/// crosshair type = 0 means no crosshair.
6615
6617{
6618 if (this == (TPad*)fCanvas)
6619 return fCrosshair;
6620 return fCanvas ? fCanvas->GetCrosshair() : 0;
6621}
6622
6623////////////////////////////////////////////////////////////////////////////////
6624/// Set crosshair active/inactive.
6625/// - If crhair != 0, a crosshair will be drawn in the pad and its sub-pads.
6626/// - If the canvas crhair = 1 , the crosshair spans the full canvas.
6627/// - If the canvas crhair > 1 , the crosshair spans only the pad.
6628
6630{
6631 if (!fCanvas) return;
6633 fCrosshairPos = 0;
6634
6635 if (this != (TPad*)fCanvas) fCanvas->SetCrosshair(crhair);
6636}
6637
6638////////////////////////////////////////////////////////////////////////////////
6639/// static function to set the maximum Pick Distance fgMaxPickDistance
6640/// This parameter is used in TPad::Pick to select an object if
6641/// its DistancetoPrimitive returns a value < fgMaxPickDistance
6642/// The default value is 5 pixels. Setting a smaller value will make
6643/// picking more precise but also more difficult
6644
6649
6650////////////////////////////////////////////////////////////////////////////////
6651/// Set tool tip text associated with this pad. The delay is in
6652/// milliseconds (minimum 250). To remove tool tip call method with
6653/// text = 0.
6654
6656{
6657 if (fTip) {
6659 fTip = nullptr;
6660 }
6661
6662 if (text && strlen(text))
6663 fTip = CreateToolTip((TBox*)nullptr, text, delayms);
6664}
6665
6666////////////////////////////////////////////////////////////////////////////////
6667/// Set pad vertical (default) or horizontal
6668
6670{
6671 if (vert) ResetBit(kHori);
6672 else SetBit(kHori);
6673}
6674
6675////////////////////////////////////////////////////////////////////////////////
6676/// Stream a class object.
6677
6679{
6680 UInt_t R__s, R__c;
6683 TObject *obj;
6684 if (b.IsReading()) {
6685 Version_t v = b.ReadVersion(&R__s, &R__c);
6686 if (v > 5) {
6687 if (!gPad)
6688 gPad = new TCanvas(GetName());
6689 fMother = (TPad*)gPad;
6691 TContext ctxt(this, kFALSE);
6692 fPixmapID = -1; // -1 means pixmap will be created by ResizePad()
6693 gReadLevel++;
6694 gROOT->SetReadingObject(kTRUE);
6695
6696 b.ReadClassBuffer(TPad::Class(), this, v, R__s, R__c);
6697
6698 //Set the kCanDelete bit in all objects in the pad such that when the pad
6699 //is deleted all objects in the pad are deleted too.
6700 //Also set must cleanup bit which normally set for all primitives add to pad,
6701 // but may be reset in IO like TH1::Streamer does
6702 TIter next(fPrimitives);
6703 while ((obj = next())) {
6704 obj->SetBit(kCanDelete);
6705 obj->SetBit(kMustCleanup);
6706 }
6707
6708 fModified = kTRUE;
6709 fPadPointer = nullptr;
6710 gReadLevel--;
6711 if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
6712 gROOT->SetReadingObject(kFALSE);
6713 return;
6714 }
6715
6716 //====process old versions before automatic schema evolution
6717 if (v < 5) { //old TPad in single precision
6718 if (v < 3) { //old TPad derived from TWbox
6719 b.ReadVersion(); // TVirtualPad::Streamer(b)
6720 b.ReadVersion(); // TWbox::Streamer(b)
6721 b.ReadVersion(); // TBox::Streamer(b)
6725 b >> single; fX1 = single;
6726 b >> single; fY1 = single;
6727 b >> single; fX2 = single;
6728 b >> single; fY2 = single;
6729 b >> fBorderSize;
6730 b >> fBorderMode;
6732 } else { //new TPad
6735 b >> single; fX1 = single;
6736 b >> single; fY1 = single;
6737 b >> single; fX2 = single;
6738 b >> single; fY2 = single;
6739 b >> fBorderSize;
6740 b >> fBorderMode;
6741 }
6742 b >> fLogx;
6743 b >> fLogy;
6744 b >> fLogz;
6746 b >> single; fXtoPixelk = single;
6747 b >> single; fXtoPixel = single;
6749 b >> single; fYtoPixelk = single;
6750 b >> single; fYtoPixel = single;
6752 b >> single; fUtoPixelk = single;
6753 b >> single; fUtoPixel = single;
6755 b >> single; fVtoPixelk = single;
6756 b >> single; fVtoPixel = single;
6758 b >> single; fPixeltoXk = single;
6759 b >> single; fPixeltoX = single;
6761 b >> single; fPixeltoYk = single;
6762 b >> single; fPixeltoY = single;
6763 b >> single; fXlowNDC = single;
6764 b >> single; fYlowNDC = single;
6765 b >> single; fWNDC = single;
6766 b >> single; fHNDC = single;
6767 b >> single; fAbsXlowNDC = single;
6768 b >> single; fAbsYlowNDC = single;
6769 b >> single; fAbsWNDC = single;
6770 b >> single; fAbsHNDC = single;
6771 b >> single; fUxmin = single;
6772 b >> single; fUymin = single;
6773 b >> single; fUxmax = single;
6774 b >> single; fUymax = single;
6775 } else {
6778 b >> fX1;
6779 b >> fY1;
6780 b >> fX2;
6781 b >> fY2;
6782 b >> fBorderSize;
6783 b >> fBorderMode;
6784 b >> fLogx;
6785 b >> fLogy;
6786 b >> fLogz;
6787 b >> fXtoAbsPixelk;
6788 b >> fXtoPixelk;
6789 b >> fXtoPixel;
6790 b >> fYtoAbsPixelk;
6791 b >> fYtoPixelk;
6792 b >> fYtoPixel;
6793 b >> fUtoAbsPixelk;
6794 b >> fUtoPixelk;
6795 b >> fUtoPixel;
6796 b >> fVtoAbsPixelk;
6797 b >> fVtoPixelk;
6798 b >> fVtoPixel;
6799 b >> fAbsPixeltoXk;
6800 b >> fPixeltoXk;
6801 b >> fPixeltoX;
6802 b >> fAbsPixeltoYk;
6803 b >> fPixeltoYk;
6804 b >> fPixeltoY;
6805 b >> fXlowNDC;
6806 b >> fYlowNDC;
6807 b >> fWNDC;
6808 b >> fHNDC;
6809 b >> fAbsXlowNDC;
6810 b >> fAbsYlowNDC;
6811 b >> fAbsWNDC;
6812 b >> fAbsHNDC;
6813 b >> fUxmin;
6814 b >> fUymin;
6815 b >> fUxmax;
6816 b >> fUymax;
6817 }
6818
6819 if (!gPad)
6820 gPad = new TCanvas(GetName());
6821 if (gReadLevel == 0)
6823 else
6824 fMother = (TPad *)gPad;
6825 if (!fMother)
6826 fMother = (TPad *)gPad;
6827 if (fMother)
6829 gPad = fMother;
6830 fPixmapID = -1; // -1 means pixmap will be created by ResizePad()
6831 //-------------------------
6832 // read objects and their drawing options
6833 // b >> fPrimitives;
6834 gReadLevel++;
6835 gROOT->SetReadingObject(kTRUE);
6836 fPrimitives = new TList;
6837 b >> nobjects;
6838 if (nobjects > 0) {
6839 TContext ctxt(this, kFALSE);
6840 char drawoption[64];
6841 for (Int_t i = 0; i < nobjects; i++) {
6842 b >> obj;
6843 b >> nch;
6844 b.ReadFastArray(drawoption,nch);
6846 gPad = this; // gPad may be modified in b >> obj if obj is a pad
6847 }
6848 }
6849 gReadLevel--;
6850 gROOT->SetReadingObject(kFALSE);
6851 //////////////////////////////////////////////////////////////////////////
6852
6853 if (v > 3) {
6854 b >> fExecs;
6855 }
6856 fName.Streamer(b);
6857 fTitle.Streamer(b);
6858 b >> fPadPaint;
6859 fModified = kTRUE;
6860 b >> fGridx;
6861 b >> fGridy;
6862 b >> fFrame;
6863 b >> fView;
6864 if (v < 5) {
6865 b >> single; fTheta = single;
6866 b >> single; fPhi = single;
6867 } else {
6868 b >> fTheta;
6869 b >> fPhi;
6870 }
6871 fPadPointer = nullptr;
6872 b >> fNumber;
6873 b >> fAbsCoord;
6874 if (v > 1) {
6875 b >> fTickx;
6876 b >> fTicky;
6877 } else {
6878 fTickx = fTicky = 0;
6879 }
6880 if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
6881 b.CheckByteCount(R__s, R__c, TPad::IsA());
6882 //====end of old versions
6883
6884 } else {
6885 b.WriteClassBuffer(TPad::Class(),this);
6886 }
6887}
6888
6889////////////////////////////////////////////////////////////////////////////////
6890/// Force a copy of current style for all objects in pad.
6891
6893{
6894 if (gStyle->IsReading()) {
6906 fLogx = gStyle->GetOptLogx();
6907 fLogy = gStyle->GetOptLogy();
6908 fLogz = gStyle->GetOptLogz();
6909 } else {
6924 }
6925
6926 if (!fPrimitives) fPrimitives = new TList;
6927 TIter next(GetListOfPrimitives());
6928 TObject *obj;
6929
6930 while ((obj = next())) {
6931 obj->UseCurrentStyle();
6932 }
6933
6934 TPaveText *title = (TPaveText*)FindObject("title");
6935 if (title) {
6936 if (gStyle->IsReading()) {
6938 title->SetTextFont(gStyle->GetTitleFont(""));
6941 if (!gStyle->GetOptTitle()) delete title;
6942 } else {
6944 gStyle->SetTitleFont(title->GetTextFont());
6947 }
6948 }
6950
6951 if (gStyle->IsReading()) Modified();
6952}
6953
6954////////////////////////////////////////////////////////////////////////////////
6955/// Loop and sleep until a primitive with name=pname is found in the pad.
6956///
6957/// If emode is given, the editor is automatically set to emode, ie
6958/// it is not required to have the editor control bar.
6959///
6960/// The possible values for emode are:
6961/// - emode = "" (default). User will select the mode via the editor bar
6962/// - emode = "Arc", "Line", "Arrow", "Button", "Diamond", "Ellipse",
6963/// - emode = "Pad","pave", "PaveLabel","PaveText", "PavesText",
6964/// - emode = "PolyLine", "CurlyLine", "CurlyArc", "Text", "Marker", "CutG"
6965///
6966/// If emode is specified and it is not valid, "PolyLine" is assumed. If emode
6967/// is not specified or ="", an attempt is to use pname[1...]
6968///
6969/// for example if pname="TArc", emode="Arc" will be assumed.
6970/// When this function is called within a macro, the macro execution
6971/// is suspended until a primitive corresponding to the arguments
6972/// is found in the pad.
6973///
6974/// If CRTL/C is typed in the pad, the function returns 0.
6975///
6976/// While this function is executing, one can use the mouse, interact
6977/// with the graphics pads, use the Inspector, Browser, TreeViewer, etc.
6978///
6979/// Examples:
6980/// ~~~ {.cpp}
6981/// c1.WaitPrimitive(); // Return the first created primitive
6982/// // whatever it is.
6983/// // If a double-click with the mouse is executed
6984/// // in the pad or any key pressed, the function
6985/// // returns 0.
6986/// c1.WaitPrimitive("ggg"); // Set the editor in mode "PolyLine/Graph"
6987/// // Create a polyline, then using the context
6988/// // menu item "SetName", change the name
6989/// // of the created TGraph to "ggg"
6990/// c1.WaitPrimitive("TArc");// Set the editor in mode "Arc". Returns
6991/// // as soon as a TArc object is created.
6992/// c1.WaitPrimitive("lat","Text"); // Set the editor in Text/Latex mode.
6993/// // Create a text object, then Set its name to "lat"
6994/// ~~~
6995/// The following macro waits for 10 primitives of any type to be created.
6996///
6997/// ~~~ {.cpp}
6998///{
6999/// TCanvas c1("c1");
7000/// TObject *obj;
7001/// for (Int_t i=0;i<10;i++) {
7002/// obj = gPad->WaitPrimitive();
7003/// if (!obj) break;
7004/// printf("Loop i=%d, found objIsA=%s, name=%s\n",
7005/// i,obj->ClassName(),obj->GetName());
7006/// }
7007///}
7008/// ~~~
7009///
7010/// If ROOT runs in batch mode a call to this method does nothing.
7011
7012TObject *TPad::WaitPrimitive(const char *pname, const char *emode)
7013{
7014 if (!gPad || IsWeb())
7015 return nullptr;
7016
7017 if (emode && strlen(emode)) gROOT->SetEditorMode(emode);
7018 if (gROOT->GetEditorMode() == 0 && pname && strlen(pname) > 2) gROOT->SetEditorMode(&pname[1]);
7019
7020 if (!fPrimitives) fPrimitives = new TList;
7022 TObject *oldlast = gPad->GetListOfPrimitives() ? gPad->GetListOfPrimitives()->Last() : nullptr;
7023 TObject *obj = nullptr;
7025 Bool_t hasname = pname && (strlen(pname) > 0);
7026 if ((!pname || !pname[0]) && (!emode || !emode[0])) testlast = kTRUE;
7027 if (testlast) gROOT->SetEditorMode();
7028 while (!gSystem->ProcessEvents() && gROOT->GetSelectedPad() && gPad) {
7029 if (gROOT->GetEditorMode() == 0) {
7030 if (hasname) {
7031 obj = FindObject(pname);
7032 if (obj) return obj;
7033 }
7034 if (testlast) {
7035 if (!gPad->GetListOfPrimitives()) return nullptr;
7036 obj = gPad->GetListOfPrimitives()->Last();
7037 if (obj != oldlast) return obj;
7038 Int_t event = GetEvent();
7039 if (event == kButton1Double || event == kKeyPress) {
7040 //the following statement is required against other loop executions
7041 //before returning
7042 fCanvas->HandleInput((EEventType)-1,0,0);
7043 return nullptr;
7044 }
7045 }
7046 }
7047 gSystem->Sleep(10);
7048 }
7049
7050 return nullptr;
7051}
7052
7053////////////////////////////////////////////////////////////////////////////////
7054/// Create a tool tip and return its pointer.
7055
7057{
7058 if (gPad->IsBatch()) return nullptr;
7059 return (TObject*)gROOT->ProcessLineFast(TString::Format("new TGToolTip((TBox*)0x%zx,\"%s\",%d)",
7060 (size_t)box,text,(Int_t)delayms).Data());
7061}
7062
7063////////////////////////////////////////////////////////////////////////////////
7064/// Delete tool tip object.
7065
7067{
7068 // delete tip;
7069 if (!tip) return;
7070 gROOT->ProcessLineFast(TString::Format("delete (TGToolTip*)0x%zx", (size_t)tip).Data());
7071}
7072
7073////////////////////////////////////////////////////////////////////////////////
7074/// Reset tool tip, i.e. within time specified in CreateToolTip the
7075/// tool tip will pop up.
7076
7078{
7079 if (!tip) return;
7080 // tip->Reset(this);
7081 gROOT->ProcessLineFast(TString::Format("((TGToolTip*)0x%zx)->Reset((TPad*)0x%zx)",
7082 (size_t)tip,(size_t)this).Data());
7083}
7084
7085////////////////////////////////////////////////////////////////////////////////
7086/// Hide tool tip.
7087
7089{
7090 if (!tip) return;
7091 // tip->Hide();
7092 gROOT->ProcessLineFast(TString::Format("((TGToolTip*)0x%zx)->Hide()", (size_t)tip).Data());
7093}
7094
7095////////////////////////////////////////////////////////////////////////////////
7096/// Deprecated: use TPad::GetViewer3D() instead
7097
7099{
7100 ::Info("TPad::x3d()", "This function is deprecated. Use %s->GetViewer3D(\"x3d\") instead",this->GetName());
7101
7102 // Default on GetViewer3D is pad - for x3d it was x3d...
7103 if (!type || !type[0]) {
7104 type = "x3d";
7105 }
7107}
7108
7109////////////////////////////////////////////////////////////////////////////////
7110/// Create/obtain handle to 3D viewer. Valid types are:
7111/// - 'pad' - pad drawing via TViewer3DPad
7112/// any others registered with plugin manager supporting TVirtualViewer3D
7113/// If an invalid/null type is requested then the current viewer is returned
7114/// (if any), otherwise a default 'pad' type is returned
7115
7117{
7119
7120 if ((!type || !*type || (strstr(type, "gl") && !strstr(type, "ogl"))) && (!fCanvas || !fCanvas->UseGL()))
7121 type = "pad";
7122
7123 if (type && *type) {
7124 if (gPluginMgr->FindHandler("TVirtualViewer3D", type))
7125 validType = kTRUE;
7126 }
7127
7128 // Invalid/null type requested?
7129 if (!validType) {
7130 // Return current viewer if there is one
7131 if (fViewer3D)
7132 return fViewer3D;
7133 // otherwise default to the pad
7134 else
7135 type = "pad";
7136 }
7137
7138 // Ensure we can create the new viewer before removing any existing one
7139 TVirtualViewer3D *newViewer = nullptr;
7140
7142
7143 // External viewers need to be created via plugin manager via interface...
7144 if (!strstr(type,"pad")) {
7146
7147 if (!newViewer) {
7148 Warning("GetViewer3D", "Cannot create 3D viewer of type: %s", type);
7149 // Return the existing viewer
7150 return fViewer3D;
7151 }
7152
7153 if (strstr(type, "gl") && !strstr(type, "ogl")) {
7156 Modified();
7157 } else {
7159 }
7160
7161 } else {
7162 newViewer = new TViewer3DPad(*this);
7163 }
7164
7165 // If we had a previous viewer destroy it now
7166 // In this case we do take responsibility for destroying viewer
7167 // c.f. ReleaseViewer3D
7168 delete fViewer3D;
7169
7170 // Set and return new viewer
7172
7173 // Ensure any new external viewer is painted
7174 // For internal TViewer3DPad type we assume this is being
7175 // create on demand due to a paint - so this is not required
7176 if (createdExternal) {
7177 Modified();
7178 Update();
7179 }
7180
7181 return fViewer3D;
7182}
7183
7184////////////////////////////////////////////////////////////////////////////////
7185/// Release current (external) viewer
7186
7188{
7189 fViewer3D = nullptr;
7190
7191 // We would like to ensure the pad is repainted
7192 // when external viewer is closed down. However
7193 // a modify/paint call here will repaint the pad
7194 // before the external viewer window actually closes.
7195 // So the pad would have to be redraw twice over.
7196 // Currently we just have to live with the pad staying blank
7197 // any click in pad will refresh.
7198}
7199
7200////////////////////////////////////////////////////////////////////////////////
7201/// Get GL device.
7202
7204{
7205 return fGLDevice;
7206}
7207
7208////////////////////////////////////////////////////////////////////////////////
7209/// Emit RecordPave() signal.
7210
7212{
7213 Emit("RecordPave(const TObject*)", (Longptr_t)obj);
7214}
7215
7216////////////////////////////////////////////////////////////////////////////////
7217/// Emit RecordLatex() signal.
7218
7220{
7221 Emit("RecordLatex(const TObject*)", (Longptr_t)obj);
7222}
7223
7224////////////////////////////////////////////////////////////////////////////////
7225/// Get pad painter from TCanvas.
7226
7228{
7229 if (!fCanvas) return nullptr;
7230 return fCanvas->GetCanvasPainter();
7231}
7232
7233////////////////////////////////////////////////////////////////////////////////
7234/// Return the bounding Box of the Pad
7235
7237{
7238 Rectangle_t BBox{0, 0, 0, 0};
7239 if (gPad) {
7240 BBox.fX = gPad->XtoPixel(fXlowNDC * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1());
7241 BBox.fY = gPad->YtoPixel((fYlowNDC + fHNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1());
7242 BBox.fWidth = gPad->XtoPixel((fXlowNDC + fWNDC) * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1()) -
7243 gPad->XtoPixel(fXlowNDC * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1());
7244 BBox.fHeight = gPad->YtoPixel((fYlowNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1()) -
7245 gPad->YtoPixel((fYlowNDC + fHNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1());
7246 }
7247 return BBox;
7248}
7249
7250////////////////////////////////////////////////////////////////////////////////
7251/// Return the center of the Pad as TPoint in pixels
7252
7254{
7255 TPoint p(0, 0);
7256 if (gPad) {
7257 Double_t x = ((fXlowNDC + 0.5 * fWNDC) * (gPad->GetX2() - gPad->GetX1())) + gPad->GetX1();
7258 Double_t y = ((fYlowNDC + 0.5 * fHNDC) * (gPad->GetY2() - gPad->GetY1())) + gPad->GetY1();
7259 p.SetX(gPad->XtoPixel(x));
7260 p.SetY(gPad->YtoPixel(y));
7261 }
7262 return p;
7263}
7264
7265////////////////////////////////////////////////////////////////////////////////
7266/// Set center of the Pad
7267
7269{
7270 if (!gPad)
7271 return;
7272 fXlowNDC = (gPad->PixeltoX(p.GetX()) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1()) - 0.5 * fWNDC;
7273 fYlowNDC =
7274 (gPad->PixeltoY(p.GetY() - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - 0.5 * fHNDC;
7275 ResizePad();
7276}
7277
7278////////////////////////////////////////////////////////////////////////////////
7279/// Set X coordinate of the center of the Pad
7280
7282{
7283 if (!gPad)
7284 return;
7285 fXlowNDC = (gPad->PixeltoX(x) - gPad->GetX1())/(gPad->GetX2()-gPad->GetX1())-0.5*fWNDC;
7286 ResizePad();
7287}
7288
7289////////////////////////////////////////////////////////////////////////////////
7290/// Set Y coordinate of the center of the Pad
7291
7293{
7294 if (!gPad)
7295 return;
7296 fYlowNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - 0.5 * fHNDC;
7297 ResizePad();
7298}
7299
7300////////////////////////////////////////////////////////////////////////////////
7301/// Set lefthandside of BoundingBox to a value
7302/// (resize in x direction on left)
7303
7305{
7306 if (!gPad)
7307 return;
7308 fXlowNDC = (gPad->PixeltoX(x) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1());
7310 ResizePad();
7311}
7312
7313////////////////////////////////////////////////////////////////////////////////
7314/// Set right hand side of BoundingBox to a value
7315/// (resize in x direction on right)
7316
7318{
7319 if (!gPad)
7320 return;
7321 fWNDC = (gPad->PixeltoX(x) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1()) - fXlowNDC;
7322 ResizePad();
7323}
7324
7325////////////////////////////////////////////////////////////////////////////////
7326/// Set top of BoundingBox to a value (resize in y direction on top)
7327
7329{
7330 if (!gPad)
7331 return;
7332 fHNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - fYlowNDC;
7333 ResizePad();
7334}
7335
7336////////////////////////////////////////////////////////////////////////////////
7337/// Set bottom of BoundingBox to a value
7338/// (resize in y direction on bottom)
7339
7341{
7342 if (!gPad)
7343 return;
7344 fYlowNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1());
7346 ResizePad();
7347}
7348
7349////////////////////////////////////////////////////////////////////////////////
7350/// Mark pad modified
7351/// Will be repainted when TCanvas::Update() will be called next time
7352
7354{
7355 if (!fModified && flag) Emit("Modified()");
7356 fModified = flag;
7357}
7358
7359////////////////////////////////////////////////////////////////////////////////
7360/// Convert absolute pixel into X/Y coordinates
7361
7367
7368
7369////////////////////////////////////////////////////////////////////////////////
7370/// Convert pixel to X coordinate
7371
7373{
7374 if (fAbsCoord) return fAbsPixeltoXk + px*fPixeltoX;
7375 else return fPixeltoXk + px*fPixeltoX;
7376}
7377
7378////////////////////////////////////////////////////////////////////////////////
7379/// Convert pixel to Y coordinate
7380
7382{
7383 if (fAbsCoord) return fAbsPixeltoYk + py*fPixeltoY;
7384 else return fPixeltoYk + py*fPixeltoY;
7385}
7386
7387////////////////////////////////////////////////////////////////////////////////
7388/// Convert pixel to X/Y coordinates
7389
7395
7396////////////////////////////////////////////////////////////////////////////////
7397/// Convert X/Y into absolute pixel coordinates - integer
7398
7404
7405////////////////////////////////////////////////////////////////////////////////
7406/// Check value for valid range for pixel values
7407
7409{
7410 return v < -kMaxPixel ? -kMaxPixel : (v > kMaxPixel ? kMaxPixel : v);
7411}
7412
7413////////////////////////////////////////////////////////////////////////////////
7414/// Convert X/Y into absolute pixel coordinates - doble
7415/// Introduced to avoid pixel rounding problems
7416
7422
7423////////////////////////////////////////////////////////////////////////////////
7424/// Convert X/Y into pixel coordinates - integer
7425
7427{
7428 xpixel = XtoPixel(x);
7429 ypixel = YtoPixel(y);
7430}
7431
7432////////////////////////////////////////////////////////////////////////////////
7433/// Convert X/Y into pixel coordinates - double
7434
7440
7441////////////////////////////////////////////////////////////////////////////////
7442/// Convert X NDC to pixel
7443
7448
7449////////////////////////////////////////////////////////////////////////////////
7450/// Convert Y NDC to pixel
7451
7456
7457////////////////////////////////////////////////////////////////////////////////
7458/// Convert X NDC to absolute pixel
7459
7464
7465////////////////////////////////////////////////////////////////////////////////
7466/// Convert Y NDC to absolute pixel
7467
7472
7473////////////////////////////////////////////////////////////////////////////////
7474/// Convert X coordinate to absolute pixel
7475
7480
7481////////////////////////////////////////////////////////////////////////////////
7482/// Convert X coordinate to pixel
7483
7488
7489////////////////////////////////////////////////////////////////////////////////
7490/// Convert Y coordinate to absolute pixel
7491
7496
7497////////////////////////////////////////////////////////////////////////////////
7498/// Convert a vertical distance [y1,y2] to pixel
7499
7501{
7502 double h1 = fYtoAbsPixelk + y1 * fYtoPixel;
7503 double h2 = fYtoAbsPixelk + y2 * fYtoPixel;
7504 return TMath::Nint(pixel_boundary(std::abs(h1 - h2)));
7505}
7506
7507////////////////////////////////////////////////////////////////////////////////
7508/// Convert a horizontal distance [x1,x2] to pixel
7509
7511{
7512 double w1 = fXtoAbsPixelk + x1 * fXtoPixel;
7513 double w2 = fXtoAbsPixelk + x2 * fXtoPixel;
7514 return TMath::Nint(pixel_boundary(std::abs(w1 - w2)));
7515}
7516
7517
7518////////////////////////////////////////////////////////////////////////////////
7519/// Convert Y coordinate to pixel
7520
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:525
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
short Style_t
Style number (short)
Definition RtypesCore.h:96
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Color_t
Color number (short)
Definition RtypesCore.h:99
float Size_t
Attribute size (float)
Definition RtypesCore.h:103
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:89
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
short Width_t
Line width (short)
Definition RtypesCore.h:98
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
@ kRed
Definition Rtypes.h:67
@ kBlack
Definition Rtypes.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gDirectory
Definition TDirectory.h:385
R__EXTERN TEnv * gEnv
Definition TEnv.h: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:148
const Int_t kMAXLEVELS
Definition TGeometry.h:27
float xmin
float ymin
float xmax
float ymax
#define gInterpreter
Double_t pixel_boundary(Double_t v)
Check value for valid range for pixel values.
Definition TPad.cxx:7408
static Int_t gReadLevel
Definition TPad.cxx:69
static Bool_t ContainsTImage(TList *li)
Auxiliary function.
Definition TPad.cxx:4809
#define NotFree(i, j)
Definition TPad.cxx:3297
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:159
#define R__LOCKGUARD(mutex)
R__EXTERN TVirtualPS * gVirtualPS
Definition TVirtualPS.h:88
#define gPad
R__EXTERN Int_t(* gThreadXAR)(const char *xact, Int_t nb, void **ar, Int_t *iret)
#define snprintf
Definition civetweb.c:1579
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:30
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:1978
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:2623
Color_t GetHighLightColor() const override
Definition TCanvas.h:142
Bool_t EnsurePSPainter(Bool_t create, TVirtualPadPainter *&oldp)
Replace canvas painter For intenral use only - when creating PS images.
Definition TCanvas.cxx:2633
Bool_t IsGrayscale()
Check whether this canvas is to be drawn in grayscale mode.
Definition TCanvas.cxx:2574
void SaveSource(const char *filename="", Option_t *option="")
Save primitives in this canvas as a C++ macro file.
Definition TCanvas.cxx:1817
virtual void HandleInput(EEventType button, Int_t x, Int_t y)
Handle Input Events.
Definition TCanvas.cxx:1238
void UpdateAsync() override
Asynchronous pad update.
Definition TCanvas.cxx:2552
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:1955
TVirtualPad * GetSelectedPad() const override
Definition TCanvas.h:150
void SetCursor(ECursor cursor) override
Set cursor.
Definition TCanvas.cxx:1969
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:1137
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:2496
virtual void Cleared(TVirtualPad *pad)
Emit pad Cleared signal.
Definition TCanvas.cxx:777
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:2127
Int_t GetEvent() const override
Definition TCanvas.h:139
Bool_t IsWeb() const override
Is web canvas.
Definition TCanvas.cxx:1499
void SetBatch(Bool_t batch=kTRUE) override
Toggle batch mode.
Definition TCanvas.cxx:1937
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:3870
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:4631
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:4612
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition TClass.cxx:3828
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3694
void ls(Option_t *option="") const override
List (ls) all objects in this collection.
void Browse(TBrowser *b) override
Browse this collection (called by TBrowser).
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:22
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1926
static TString SavePrimitiveColor(Int_t ci)
Convert color in C++ statement which can be used in SetColor directives Produced statement either inc...
Definition TColor.cxx:2556
static void SetGrayscale(Bool_t set=kTRUE)
Set whether all colors should return grayscale values.
Definition TColor.cxx:2604
static void Pave(Int_t event, Int_t px, Int_t py, Int_t mode)
Create a new pavetext in gPad.
static void Line(Int_t event, Int_t px, Int_t py, Int_t mode)
Create a new line/arrow in this gPad.
static void PolyLine(Int_t event, Int_t px, Int_t py, Int_t mode)
Create a new PolyLine in gPad.
static void Text(Int_t event, Int_t px, Int_t py, Int_t mode)
Create a new TLatex at the cursor position in gPad.
static void Ellipse(Int_t event, Int_t px, Int_t py, Int_t mode)
Create a new arc/ellipse in this gPad.
static void Pad(Int_t event, Int_t px, Int_t py, Int_t)
Create a new pad in gPad.
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition TDatime.h:37
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx: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:284
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:462
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:997
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:227
virtual void UseCurrentStyle()
Set current style settings in this object This function is called when either TCanvas::UseCurrentStyl...
Definition TObject.cxx:909
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1084
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:425
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:888
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:549
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1098
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:507
void MakeZombie()
Definition TObject.h:55
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition TObject.cxx:293
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:631
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:1072
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:4623
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:6194
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:3146
Int_t VtoPixel(Double_t v) const override
Convert Y NDC to pixel.
Definition TPad.cxx:7452
void PaintBorder(Color_t color, Bool_t tops)
Paint the pad border.
Definition TPad.cxx:3687
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:3162
void SetView(TView *view=nullptr) override
Set the current TView. Delete previous view if view=0.
Definition TPad.cxx:6159
TVirtualViewer3D * GetViewer3D(Option_t *type="") override
Create/obtain handle to 3D viewer.
Definition TPad.cxx:7116
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:4095
void PaintLine3D(Float_t *p1, Float_t *p2) override
Paint 3-D line in the CurrentPad.
Definition TPad.cxx:4276
static Int_t fgMaxPickDistance
Maximum Pick Distance.
Definition TPad.h:115
void ResizePad(Option_t *option="") override
Compute pad conversion coefficients.
Definition TPad.cxx:5639
void PaintMarker3D(Double_t x, Double_t y, Double_t z) override
Paint 3-D marker in the CurrentPad.
Definition TPad.cxx:4312
void PaintPolyMarker(Int_t n, Float_t *x, Float_t *y, Option_t *option="") override
Paint polymarker in CurrentPad World coordinates.
Definition TPad.cxx:4465
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:7219
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:5862
void CopyBackgroundPixmaps(TPad *stop, Int_t x, Int_t y)
Copy pixmaps of pads laying below pad "stop" into pad "stop".
Definition TPad.cxx:3953
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:3579
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:7328
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:3231
void SetLogz(Int_t value=1) override
Set Lin/Log scale for Z.
Definition TPad.cxx:6075
Bool_t fEmbeddedGL
!
Definition TPad.h:87
Int_t UtoAbsPixel(Double_t u) const override
Convert X NDC to absolute pixel.
Definition TPad.cxx:7460
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:7484
void SetAttFillPS(Color_t color, Style_t style) override
Set postscript fill area attributes.
Definition TPad.cxx:6170
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:7292
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:7066
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:7362
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:5422
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:3822
void SetEditable(Bool_t mode=kTRUE) override
Set pad editable yes/no If a pad is not editable:
Definition TPad.cxx:6019
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:3760
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:6645
void PixeltoXY(Double_t xpixel, Double_t ypixel, Double_t &x, Double_t &y) override
Convert pixel to X/Y coordinates.
Definition TPad.cxx:7390
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:7317
void SetBBoxX1(const Int_t x) override
Set lefthandside of BoundingBox to a value (resize in x direction on left)
Definition TPad.cxx:7304
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:6038
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:3570
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:3600
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:6135
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:7500
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:7426
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:6892
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:7468
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:5346
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:7399
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:7012
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:6206
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:7381
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:4659
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:4018
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:7521
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:4241
Int_t GetGLDevice() override
Get GL device.
Definition TPad.cxx:7203
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:7211
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:3750
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:6064
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:7098
Bool_t HasCrosshair() const override
Return kTRUE if the crosshair has been activated (via SetCrosshair).
Definition TPad.cxx:6607
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:3207
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:3972
void Modified(Bool_t flag=true) override
Mark pad modified Will be repainted when TCanvas::Update() will be called next time.
Definition TPad.cxx:7353
void RecursiveRemove(TObject *obj) override
Recursively remove object from a pad and its sub-pads.
Definition TPad.cxx:5404
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:7088
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:6655
void PaintPolyLine(Int_t n, Float_t *x, Float_t *y, Option_t *option="") override
Paint polyline in CurrentPad World coordinates.
Definition TPad.cxx:4335
Int_t WtoAbsPixel(Double_t x1, Double_t x2) const override
Convert a horizontal distance [x1,x2] to pixel.
Definition TPad.cxx:7510
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:3558
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:6182
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:4529
UInt_t GetPadWidth() const override
Get pad width.
Definition TPad.cxx:2838
void Streamer(TBuffer &) override
Stream a class object.
Definition TPad.cxx:6678
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:4570
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:7444
TPoint GetBBoxCenter() override
Return the center of the Pad as TPoint in pixels.
Definition TPad.cxx:7253
void FillCollideGridTFrame(TObject *o)
Definition TPad.cxx:3362
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:3302
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:3388
void SetFixedAspectRatio(Bool_t fixed=kTRUE) override
Fix pad aspect ratio to current value if fixed is true.
Definition TPad.cxx:5995
Short_t GetBorderSize() const override
Definition TPad.h:200
void RedrawAxis(Option_t *option="") override
Redraw the frame axis.
Definition TPad.cxx:5465
void DrawDist(Rectangle_t aBBox, Rectangle_t bBBox, char mode)
Draw Arrows to indicated equal distances of Objects with given BBoxes.
Definition TPad.cxx:6231
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:7492
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:4061
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:5384
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:7077
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:7236
void Paint(Option_t *option="") override
Paint all primitives in pad.
Definition TPad.cxx:3612
void FillCollideGridTBox(TObject *o)
Definition TPad.cxx:3345
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:3501
TString fName
Pad name.
Definition TPad.h:109
void SetVertical(Bool_t vert=kTRUE) override
Set pad vertical (default) or horizontal.
Definition TPad.cxx:6669
void FillCollideGridTH1(TObject *o)
Definition TPad.cxx:3419
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:4584
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:5799
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:4263
void Print(const char *filename="") const override
This method is equivalent to SaveAs("filename"). See TPad::SaveAs for details.
Definition TPad.cxx:4800
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:7227
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:6315
Int_t GetCrosshair() const
Return the crosshair type (from the mother canvas) crosshair type = 0 means no crosshair.
Definition TPad.cxx:6616
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:3909
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:7268
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:7372
void PaintPolyLineNDC(Int_t n, Double_t *x, Double_t *y, Option_t *option="") override
Paint polyline in CurrentPad NDC coordinates.
Definition TPad.cxx:4435
Bool_t IsVertical() const override
Definition TPad.h:278
Int_t IncrementPaletteColor(Int_t i, TString opt) override
Increment (i==1) or set (i>1) the number of autocolor in the pad.
Definition TPad.cxx:3132
void PaintPadFrame(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax) override
Paint histogram/graph frame.
Definition TPad.cxx:3803
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:4610
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:4451
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:6050
void ReleaseViewer3D(Option_t *type="") override
Release current (external) viewer.
Definition TPad.cxx:7187
void SetCrosshair(Int_t crhair=1) override
Set crosshair active/inactive.
Definition TPad.cxx:6629
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:7281
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:7056
@ 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 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:4778
Double_t GetAbsXlowNDC() const override
Definition TPad.h:222
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:7476
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:7340
Double_t XtoPad(Double_t x) const override
Convert x from X to pad.
Definition TPad.cxx:3588
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:3044
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:3052
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2901
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
TString & ReplaceSpecialCppChars()
Find special characters which are typically used in printf() calls and replace them by appropriate es...
Definition TString.cxx:1121
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:703
const char * Data() const
Definition TString.h:384
virtual void Streamer(TBuffer &)
Stream a string object.
Definition TString.cxx:1418
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2385
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2363
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:660
Int_t GetOptLogy() const
Definition TStyle.h:250
void SetPadBorderMode(Int_t mode=1)
Definition TStyle.h:361
void SetPadTopMargin(Float_t margin=0.1)
Definition TStyle.h:363
void SetOptLogx(Int_t logx=1)
Definition TStyle.h:333
void SetPadBottomMargin(Float_t margin=0.1)
Definition TStyle.h:362
Int_t GetOptTitle() const
Definition TStyle.h:248
Int_t GetPadTickX() const
Definition TStyle.h:219
Bool_t IsReading() const
Definition TStyle.h:300
Color_t GetPadColor() const
Definition TStyle.h:210
void SetPadRightMargin(Float_t margin=0.1)
Definition TStyle.h:365
void SetTitleFont(Style_t font=62, Option_t *axis="X")
Definition TStyle.cxx:1776
Float_t GetPadRightMargin() const
Definition TStyle.h:216
void SetTitleBorderSize(Width_t size=2)
Definition TStyle.h:412
Float_t GetDateX() const
Definition TStyle.h:199
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1217
void SetPadTickY(Int_t ticky)
Definition TStyle.h:369
Color_t GetTitleFillColor() const
Definition TStyle.h:273
void SetPadTickX(Int_t tickx)
Definition TStyle.h:368
Int_t GetOptDate() const
Definition TStyle.h:244
Bool_t GetPadGridY() const
Definition TStyle.h:218
void SetPadGridX(Bool_t gridx)
Definition TStyle.h:366
void SetTitleTextColor(Color_t color=1)
Definition TStyle.h:409
Float_t GetPadLeftMargin() const
Definition TStyle.h:215
Double_t GetHatchesSpacing() const
Definition TStyle.h:203
Bool_t GetPadGridX() const
Definition TStyle.h:217
void SetPadLeftMargin(Float_t margin=0.1)
Definition TStyle.h:364
void SetPadGridY(Bool_t gridy)
Definition TStyle.h:367
void SetOptLogy(Int_t logy=1)
Definition TStyle.h:334
Int_t GetOptFile() const
Definition TStyle.h:245
TAttText * GetAttDate()
Definition TStyle.h:170
Int_t GetPadTickY() const
Definition TStyle.h:220
Width_t GetPadBorderSize() const
Definition TStyle.h:211
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
void SetTitleFillColor(Color_t color=1)
Definition TStyle.h:408
Float_t GetPadBottomMargin() const
Definition TStyle.h:213
void SetOptLogz(Int_t logz=1)
Definition TStyle.h:335
void SetPadColor(Color_t color=19)
Definition TStyle.h:359
Color_t GetTitleTextColor() const
Definition TStyle.h:274
Int_t GetOptLogx() const
Definition TStyle.h:249
Float_t GetDateY() const
Definition TStyle.h:200
Int_t GetPadBorderMode() const
Definition TStyle.h:212
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1176
Int_t GetOptLogz() const
Definition TStyle.h:251
void SetPadBorderSize(Width_t size=1)
Definition TStyle.h:360
Int_t GetHatchesLineWidth() const
Definition TStyle.h:202
Float_t GetPadTopMargin() const
Definition TStyle.h:214
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx: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:603
virtual void SetNDC(Bool_t isNDC=kTRUE)
Set NDC mode on if isNDC = kTRUE, off otherwise.
Definition TText.cxx:737
See TView3D.
Definition TView.h:25
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual void ResizePad()=0
virtual void GetRange(Float_t *min, Float_t *max)=0
Provides 3D viewer interface (TVirtualViewer3D) support on a pad.
TVirtualPS is an abstract interface to Postscript, PDF, SVG.
Definition TVirtualPS.h:30
virtual void NewPage()=0
virtual void Open(const char *filename, Int_t type=-111)=0
virtual void DrawFrame(Double_t xl, Double_t yl, Double_t xt, Double_t yt, Int_t mode, Int_t border, Int_t dark, Int_t light)=0
To make it possible to use GL for 2D graphic in a TPad/TCanvas.
virtual void DestroyDrawable(Int_t device)=0
virtual void 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:903
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:704
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t Exp(Double_t x)
Returns the base-e exponential function of x, which is e raised to the power x.
Definition TMath.h:720
Double_t Floor(Double_t x)
Rounds x downward, returning the largest integral value that is not greater than x.
Definition TMath.h:691
Double_t Ceil(Double_t x)
Rounds x upward, returning the smallest integral value that is not less than x.
Definition TMath.h:679
Int_t Finite(Double_t x)
Check if it is finite with a mask in order to be consistent in presence of fast math.
Definition TMath.h:781
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:767
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:732
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:605
constexpr Double_t Pi()
Definition TMath.h:40
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:773
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
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:6284
TAttBBox2D * fb
Definition TPad.cxx:6286
dField()
Definition TPad.cxx:6291
char fdir
Definition TPad.cxx:6288
dField(TAttBBox2D *a, TAttBBox2D *b, Int_t dist, char direction)
Definition TPad.cxx:6295
TAttBBox2D * fa
Definition TPad.cxx:6285
Int_t fdist
Definition TPad.cxx:6287
TMarker m
Definition textangle.C:8