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 ((color == 10) && (style > 3000) && (style < 3100))
3719 color = 1;
3720
3721 if (do_paint_box) {
3722 pp->SetAttFill({color, style});
3723 pp->SetAttLine(*this);
3724 PaintBox(fX1, fY1, fX2, fY2);
3725 }
3726 } else
3727 color = -color;
3728
3729 if (IsTransparent() || (fBorderMode == 0))
3730 return;
3731
3732 // then paint 3d frame (depending on bordermode)
3733 // Paint a 3D frame around the pad.
3734
3735 TWbox box;
3736 box.SetFillColor(color);
3737 box.SetFillStyle(GetFillStyle());
3739
3740 box.PaintBorderOn(this, fX1, fY1, fX2, fY2,
3743}
3744
3745////////////////////////////////////////////////////////////////////////////////
3746/// Paint a frame border with Postscript - no longer used
3747
3753
3754////////////////////////////////////////////////////////////////////////////////
3755/// Paint the current date and time if the option `Date` is set on via `gStyle->SetOptDate()`
3756/// Paint the current file name if the option `File` is set on via `gStyle->SetOptFile()`
3757
3759{
3760 if (fCanvas == this) {
3761 if (gStyle->GetOptDate()) {
3762 TDatime dt;
3763 const char *dates;
3764 char iso[16];
3765 if (gStyle->GetOptDate() < 10) {
3766 //by default use format like "Wed Sep 25 17:10:35 2002"
3767 dates = dt.AsString();
3768 } else if (gStyle->GetOptDate() < 20) {
3769 //use ISO format like 2002-09-25
3770 strlcpy(iso,dt.AsSQLString(),16);
3771 dates = iso;
3772 } else {
3773 //use ISO format like 2002-09-25 17:10:35
3774 dates = dt.AsSQLString();
3775 }
3777 tdate.SetTextSize( gStyle->GetAttDate()->GetTextSize());
3778 tdate.SetTextFont( gStyle->GetAttDate()->GetTextFont());
3779 tdate.SetTextColor(gStyle->GetAttDate()->GetTextColor());
3780 tdate.SetTextAlign(gStyle->GetAttDate()->GetTextAlign());
3781 tdate.SetTextAngle(gStyle->GetAttDate()->GetTextAngle());
3782 tdate.SetNDC();
3783 tdate.Paint();
3784 }
3785 if (gStyle->GetOptFile() && gFile) {
3786 TText tfile(1. - gStyle->GetDateX(),gStyle->GetDateY(),gFile->GetName());
3790 tfile.SetTextAlign(31);
3792 tfile.SetNDC();
3793 tfile.Paint();
3794 }
3795 }
3796}
3797
3798////////////////////////////////////////////////////////////////////////////////
3799/// Paint histogram/graph frame.
3800
3802{
3803 if (!fPrimitives) fPrimitives = new TList;
3805 TFrame *frame = GetFrame();
3806 frame->SetX1(xmin);
3807 frame->SetX2(xmax);
3808 frame->SetY1(ymin);
3809 frame->SetY2(ymax);
3810 if (!glist->FindObject(fFrame)) {
3811 glist->AddFirst(frame);
3813 }
3814 frame->Paint();
3815}
3816
3817////////////////////////////////////////////////////////////////////////////////
3818/// Traverse pad hierarchy and (re)paint only modified pads.
3819
3821{
3823 if (IsModified()) {
3824 fViewer3D->PadPaint(this);
3826 }
3828 auto lnk = pList ? pList->FirstLink() : nullptr;
3829 while (lnk) {
3830 auto obj = lnk->GetObject();
3831 if (obj->InheritsFrom(TPad::Class()))
3832 ((TPad*)obj)->PaintModified();
3833 lnk = lnk->Next();
3834 }
3835 return;
3836 }
3837
3840 gVirtualPS = nullptr;
3841
3842 TVirtualPadPainter *oldpp = nullptr;
3844
3845 if (fCanvas) {
3846 // check if special PS painter should be assigned to TCanvas
3849 }
3850
3852 fPadPaint = 1;
3853 {
3854 TContext ctxt(this, kTRUE);
3855 if (IsModified() || IsTransparent())
3857
3858 PaintDate();
3859
3861 auto lnk = pList ? pList->FirstLink() : nullptr;
3862
3863 while (lnk) {
3864 TObject *obj = lnk->GetObject();
3865 if (obj->InheritsFrom(TPad::Class())) {
3866 ((TPad*)obj)->PaintModified();
3867 } else if (IsModified() || IsTransparent()) {
3868
3869 // Create a pad 3D viewer if none exists and we encounter a
3870 // 3D shape
3871 if (!fViewer3D && obj->InheritsFrom(TAtt3D::Class())) {
3872 GetViewer3D("pad");
3873 }
3874
3875 // Open a 3D scene if required
3876 if (fViewer3D && !fViewer3D->BuildingScene()) {
3879 }
3880
3881 obj->Paint(lnk->GetOption());
3882 }
3883 lnk = lnk->Next();
3884 }
3885 }
3886
3887 fPadPaint = 0;
3889
3890 // This must be done after modified flag is cleared, as some
3891 // viewers will invoke another paint by marking pad modified again
3892 if (began3DScene && fViewer3D)
3894
3895 if (replace_pp && fCanvas)
3897
3899}
3900
3901////////////////////////////////////////////////////////////////////////////////
3902/// Paint box in CurrentPad World coordinates.
3903///
3904/// - if option[0] = 's' the box is forced to be paint with style=0
3905/// - if option[0] = 'l' the box contour is drawn
3906
3908{
3909 auto pp = GetPainter();
3910 if (!pp)
3911 return;
3912
3913 pp->OnPad(this);
3914
3915 Style_t style = pp->GetAttFill().GetFillStyle();
3917 if (option && *option == 's')
3919 else if (option && *option == 'l')
3921
3922 if (style >= 3100 && style < 4000) {
3923 Double_t xb[4] = {x1, x1, x2, x2};
3924 Double_t yb[4] = {y1, y2, y2, y1};
3926 } else if (style >= 0 && style < 1000) {
3928 } else if (style >= 1000 && style < 2000) {
3929 draw_fill = kTRUE;
3930 } else if (style > 3000 && style < 3100) {
3931 draw_fill = style < 3026;
3932 } else if (style >= 4000 && style <= 4100) {
3933 // transparency styles, supported now by all painters
3934 draw_fill = style > 4000;
3935 } else if (style > 0)
3937
3938 if (draw_fill && !skip_fill)
3939 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
3940
3941 if (draw_border)
3942 pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow);
3943
3944 Modified();
3945}
3946
3947////////////////////////////////////////////////////////////////////////////////
3948/// Copy pixmaps of pads laying below pad "stop" into pad "stop". This
3949/// gives the effect of pad "stop" being transparent.
3950
3952{
3953 Int_t px, py;
3954 XYtoAbsPixel(GetX1(), GetY2(), px, py);
3955 /// Copy pixmap of this pad as background of the current pad.
3956 if (auto pp = GetPainter())
3957 pp->CopyDrawable(GetPixmapID(), px - x, py - y);
3958
3959 TIter next(GetListOfPrimitives());
3960 while (auto obj = next()) {
3961 if (obj == stop)
3962 break;
3963 if (auto pad = dynamic_cast<TPad *>(obj))
3964 pad->CopyBackgroundPixmaps(stop, x, y);
3965 }
3966}
3967
3968////////////////////////////////////////////////////////////////////////////////
3969
3971{
3972 Warning("TPad::PaintFillArea", "Float_t signature is obsolete. Use Double_t signature.");
3973}
3974
3975////////////////////////////////////////////////////////////////////////////////
3976/// Paint fill area in CurrentPad World coordinates.
3977
3979{
3980 if (nn < 3)
3981 return;
3985 } else {
3986 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
3987 }
3988
3989 Int_t nc = 2*nn+1;
3990 std::vector<Double_t> x(nc, 0.);
3991 std::vector<Double_t> y(nc, 0.);
3992
3993 Int_t n = ClipPolygon(nn, xx, yy, nc, x.data(), y.data(), xmin, ymin, xmax, ymax);
3994 if (!n)
3995 return;
3996
3997 auto pp = GetPainter();
3998 if (!pp)
3999 return;
4000
4001 pp->OnPad(this);
4002
4003 // Paint the fill area with hatches
4004 Int_t fillstyle = pp->GetFillStyle();
4005 if (fillstyle >= 3100 && fillstyle < 4000)
4006 PaintFillAreaHatches(nn, x.data(), y.data(), fillstyle);
4007 else
4008 pp->DrawFillArea(n, x.data(), y.data());
4009
4010 Modified();
4011}
4012
4013////////////////////////////////////////////////////////////////////////////////
4014/// Paint fill area in CurrentPad NDC coordinates.
4015
4017{
4018 std::vector<Double_t> xw(n), yw(n);
4019 for (int i=0; i<n; i++) {
4020 xw[i] = fX1 + x[i]*(fX2 - fX1);
4021 yw[i] = fY1 + y[i]*(fY2 - fY1);
4022 }
4023 PaintFillArea(n, xw.data(), yw.data(), option);
4024}
4025
4026////////////////////////////////////////////////////////////////////////////////
4027/// This function paints hatched fill area according to the FillStyle value
4028/// The convention for the Hatch is the following:
4029///
4030/// `FillStyle = 3ijk`
4031///
4032/// - i (1-9) : specify the space between each hatch
4033/// 1 = minimum 9 = maximum
4034/// the final spacing is i*GetHatchesSpacing(). The hatches spacing
4035/// is set by SetHatchesSpacing()
4036/// - j (0-9) : specify angle between 0 and 90 degrees
4037/// * 0 = 0
4038/// * 1 = 10
4039/// * 2 = 20
4040/// * 3 = 30
4041/// * 4 = 45
4042/// * 5 = Not drawn
4043/// * 6 = 60
4044/// * 7 = 70
4045/// * 8 = 80
4046/// * 9 = 90
4047/// - k (0-9) : specify angle between 90 and 180 degrees
4048/// * 0 = 180
4049/// * 1 = 170
4050/// * 2 = 160
4051/// * 3 = 150
4052/// * 4 = 135
4053/// * 5 = Not drawn
4054/// * 6 = 120
4055/// * 7 = 110
4056/// * 8 = 100
4057/// * 9 = 90
4058
4060{
4061 static Double_t ang1[10] = { 0., 10., 20., 30., 45.,5., 60., 70., 80., 89.99};
4062 static Double_t ang2[10] = {180.,170.,160.,150.,135.,5.,120.,110.,100., 89.99};
4063
4064 Int_t fasi = FillStyle % 1000;
4065 Int_t idSPA = fasi / 100;
4066 Int_t iAng2 = (fasi - 100 * idSPA) / 10;
4067 Int_t iAng1 = fasi % 10;
4068 Double_t dy = 0.003 * idSPA * gStyle->GetHatchesSpacing();
4070 auto pp = GetPainter();
4071 if (!pp)
4072 return;
4073
4074 // Save the current line attributes and change to draw hatches
4075 TAttLine saveatt = pp->GetAttLine();
4076
4077 pp->SetAttLine({ pp->GetAttFill().GetFillColor(), 1, lw });
4078
4079 // Draw the hatches
4080 if (ang1[iAng1] != 5.)
4082 if (ang2[iAng2] != 5.)
4084
4085 pp->SetAttLine(saveatt);
4086}
4087
4088////////////////////////////////////////////////////////////////////////////////
4089/// This routine draw hatches inclined with the
4090/// angle "angle" and spaced of "dy" in normalized device
4091/// coordinates in the surface defined by n,xx,yy.
4092
4095{
4096 Int_t i, i1, i2, nbi;
4098 const Double_t angr = TMath::Pi()*(180.-angle)/180.;
4099 const Double_t epsil = 0.0001;
4100
4101 std::vector<Double_t> xli;
4102 std::vector<Double_t> yli;
4103
4104 Double_t xt1, xt2, yt1, yt2;
4105 Double_t x, y, x1, x2, y1, y2, a, b, xi, xip, xin, yi, yip;
4106
4107 Double_t rwxmin = gPad->GetX1();
4108 Double_t rwxmax = gPad->GetX2();
4109 Double_t rwymin = gPad->GetY1();
4110 Double_t rwymax = gPad->GetY2();
4111 ratiox = 1./(rwxmax-rwxmin);
4112 ratioy = 1./(rwymax-rwymin);
4113
4116 if (TMath::Abs(cosa) <= epsil) cosa=0.;
4117 if (TMath::Abs(sina) <= epsil) sina=0.;
4118 sinb = -sina;
4119 cosb = cosa;
4120
4121 // Values needed to compute the hatches in TRUE normalized space (NDC)
4122 Int_t iw = (Int_t)gPad->GetWw();
4123 Int_t ih = (Int_t)gPad->GetWh();
4125 gPad->GetPadPar(x1p,y1p,x2p,y2p);
4126 iw = (Int_t)(iw*x2p)-(Int_t)(iw*x1p);
4127 ih = (Int_t)(ih*y2p)-(Int_t)(ih*y1p);
4130
4131 // Search ymin and ymax
4132 ymin = 1.;
4133 ymax = 0.;
4134 for (i=1; i<=nn; i++) {
4135 x = wndc*ratiox*(xx[i-1]-rwxmin);
4136 y = hndc*ratioy*(yy[i-1]-rwymin);
4137 yrot = sina*x+cosa*y;
4138 if (yrot > ymax) ymax = yrot;
4139 if (yrot < ymin) ymin = yrot;
4140 }
4141
4142 Int_t yindx = (Int_t) (ymax/dy);
4143
4144 while (dy * yindx >= ymin) {
4145 ycur = dy * yindx--;
4146 nbi = 0;
4147
4148 xli.clear();
4149 yli.clear();
4150
4151 for (i=2; i<=nn+1; i++) {
4152 i2 = i;
4153 i1 = i-1;
4154 if (i == nn+1) i2=1;
4155
4156 x1 = wndc*ratiox*(xx[i1-1]-rwxmin);
4157 y1 = hndc*ratioy*(yy[i1-1]-rwymin);
4158 x2 = wndc*ratiox*(xx[i2-1]-rwxmin);
4159 y2 = hndc*ratioy*(yy[i2-1]-rwymin);
4160
4161 xt1 = cosa*x1-sina*y1;
4162 yt1 = sina*x1+cosa*y1;
4163 xt2 = cosa*x2-sina*y2;
4164 yt2 = sina*x2+cosa*y2;
4165
4166 // Line segment parallel to oy
4167 if (xt1 == xt2) {
4168 if (yt1 < yt2) {
4169 yi = yt1;
4170 yip = yt2;
4171 } else {
4172 yi = yt2;
4173 yip = yt1;
4174 }
4175 if ((yi <= ycur) && (ycur < yip)) {
4176 nbi++;
4177 xli.push_back(xt1);
4178 }
4179 continue;
4180 }
4181
4182 // Line segment parallel to ox
4183 if (yt1 == yt2) {
4184 if (yt1 == ycur) {
4185 nbi++;
4186 xli.push_back(xt1);
4187 nbi++;
4188 xli.push_back(xt2);
4189 }
4190 continue;
4191 }
4192
4193 // Other line segment
4194 a = (yt1-yt2)/(xt1-xt2);
4195 b = (yt2*xt1-xt2*yt1)/(xt1-xt2);
4196
4197 if (xt1 < xt2) {
4198 xi = xt1;
4199 xip = xt2;
4200 } else {
4201 xi = xt2;
4202 xip = xt1;
4203 }
4204
4205 xin = (ycur-b)/a;
4206
4207 if ((xi <= xin) && (xin < xip) &&
4208 (TMath::Min(yt1,yt2) <= ycur) &&
4209 (ycur < TMath::Max(yt1,yt2))) {
4210 nbi++;
4211 xli.push_back(xin);
4212 }
4213 }
4214
4215 // Sorting of the x coordinates intersections
4216 std::sort(xli.begin(), xli.end());
4217
4218 // Draw the hatches
4219 if ((nbi%2 != 0) || (nbi == 0))
4220 continue;
4221
4222 for (i=0; i<nbi; ++i) {
4223 // Rotate back the hatches - first calculate y coordinate
4224 Double_t ytmp = sinb*xli[i] + cosb*ycur;
4225 xli[i] = cosb*xli[i] - sinb*ycur;
4226 // Convert hatches' positions from true NDC to WC to handle cliping
4227 xli[i] = (xli[i]/wndc)*(rwxmax-rwxmin)+rwxmin;
4229 yli.push_back(ytmp);
4230 }
4231
4232 gPad->PaintSegments(nbi/2, xli.data(), yli.data());
4233 }
4234}
4235
4236////////////////////////////////////////////////////////////////////////////////
4237/// Paint line in CurrentPad World coordinates.
4238
4240{
4241 Double_t x[2] = {x1, x2}, y[2] = {y1, y2};
4242
4243 //If line is totally clipped, return
4245 if (Clip(x,y,fUxmin,fUymin,fUxmax,fUymax) == 2) return;
4246 } else {
4247 if (Clip(x,y,fX1,fY1,fX2,fY2) == 2) return;
4248 }
4249
4250 if (auto pp = GetPainter()) {
4251 pp->OnPad(this);
4252 pp->DrawLine(x[0], y[0], x[1], y[1]);
4253 }
4254
4255 Modified();
4256}
4257
4258////////////////////////////////////////////////////////////////////////////////
4259/// Paint line in normalized coordinates.
4260
4262{
4263 if (auto pp = GetPainter()) {
4264 pp->OnPad(this);
4265 pp->DrawLineNDC(u1, v1, u2, v2);
4266 }
4267
4268 Modified();
4269}
4270
4271////////////////////////////////////////////////////////////////////////////////
4272/// Paint 3-D line in the CurrentPad.
4273
4275{
4276 if (!fView) return;
4277
4278 // convert from 3-D to 2-D pad coordinate system
4279 Double_t xpad[6];
4280 Double_t temp[3];
4281 Int_t i;
4282 for (i=0;i<3;i++) temp[i] = p1[i];
4283 fView->WCtoNDC(temp, &xpad[0]);
4284 for (i=0;i<3;i++) temp[i] = p2[i];
4285 fView->WCtoNDC(temp, &xpad[3]);
4286 PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
4287}
4288
4289////////////////////////////////////////////////////////////////////////////////
4290/// Paint 3-D line in the CurrentPad.
4291
4293{
4294 if (!fView) return;
4295
4296 // convert from 3-D to 2-D pad coordinate system
4297 Double_t xpad[6];
4298 Double_t temp[3];
4299 Int_t i;
4300 for (i=0;i<3;i++) temp[i] = p1[i];
4301 fView->WCtoNDC(temp, &xpad[0]);
4302 for (i=0;i<3;i++) temp[i] = p2[i];
4303 fView->WCtoNDC(temp, &xpad[3]);
4304 PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
4305}
4306
4307////////////////////////////////////////////////////////////////////////////////
4308/// Paint 3-D marker in the CurrentPad.
4309
4311{
4312 if (!fView) return;
4313
4314 Double_t rmin[3], rmax[3];
4316
4317 // convert from 3-D to 2-D pad coordinate system
4318 Double_t xpad[3];
4319 Double_t temp[3];
4320 temp[0] = x;
4321 temp[1] = y;
4322 temp[2] = z;
4323 if (x<rmin[0] || x>rmax[0]) return;
4324 if (y<rmin[1] || y>rmax[1]) return;
4325 if (z<rmin[2] || z>rmax[2]) return;
4326 fView->WCtoNDC(temp, &xpad[0]);
4327 PaintPolyMarker(1, &xpad[0], &xpad[1]);
4328}
4329
4330////////////////////////////////////////////////////////////////////////////////
4331/// Paint polyline in CurrentPad World coordinates.
4332
4334{
4335 if (n < 2) return;
4336
4340 } else {
4341 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4342 }
4343 Int_t i, i1=-1,np=1;
4344 for (i=0; i<n-1; i++) {
4345 Double_t x1=x[i];
4346 Double_t y1=y[i];
4347 Double_t x2=x[i+1];
4348 Double_t y2=y[i+1];
4349 Int_t iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4350 if (iclip == 2) {
4351 i1 = -1;
4352 continue;
4353 }
4354 np++;
4355 if (i1 < 0)
4356 i1 = i;
4357 if (iclip == 0 && i < n-2)
4358 continue;
4359 if (auto pp = GetPainter()) {
4360 pp->OnPad(this);
4361 pp->DrawPolyLine(np, &x[i1], &y[i1]);
4362 }
4363 if (iclip) {
4364 x[i] = x1;
4365 y[i] = y1;
4366 x[i+1] = x2;
4367 y[i+1] = y2;
4368 }
4369 i1 = -1;
4370 np = 1;
4371 }
4372
4373 Modified();
4374}
4375
4376////////////////////////////////////////////////////////////////////////////////
4377/// Paint polyline in CurrentPad World coordinates.
4378///
4379/// If option[0] == 'C' no clipping
4380
4382{
4383 if (n < 2) return;
4384
4389 } else {
4390 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4391 if (option && (option[0] == 'C')) mustClip = kFALSE;
4392 }
4393
4394 Int_t i, i1=-1, np = 1, iclip = 0;
4395
4396 for (i=0; i < n-1; i++) {
4397 Double_t x1 = x[i];
4398 Double_t y1 = y[i];
4399 Double_t x2 = x[i+1];
4400 Double_t y2 = y[i+1];
4401 if (mustClip) {
4402 iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4403 if (iclip == 2) {
4404 i1 = -1;
4405 continue;
4406 }
4407 }
4408 np++;
4409 if (i1 < 0)
4410 i1 = i;
4411 if (iclip == 0 && i < n-2)
4412 continue;
4413 if (auto pp = GetPainter()) {
4414 pp->OnPad(this);
4415 pp->DrawPolyLine(np, &x[i1], &y[i1]);
4416 }
4417 if (iclip) {
4418 x[i] = x1;
4419 y[i] = y1;
4420 x[i+1] = x2;
4421 y[i+1] = y2;
4422 }
4423 i1 = -1;
4424 np = 1;
4425 }
4426
4427 Modified();
4428}
4429
4430////////////////////////////////////////////////////////////////////////////////
4431/// Paint polyline in CurrentPad NDC coordinates.
4432
4434{
4435 if (n <= 0)
4436 return;
4437
4438 if (auto pp = GetPainter()) {
4439 pp->OnPad(this);
4440 pp->DrawPolyLineNDC(n, x, y);
4441 }
4442
4443 Modified();
4444}
4445
4446////////////////////////////////////////////////////////////////////////////////
4447/// Paint 3-D polyline in the CurrentPad.
4448
4450{
4451 if (!fView) return;
4452
4453 // Loop on each individual line
4454 for (Int_t i = 1; i < n; i++)
4455 PaintLine3D(&p[3*i-3], &p[3*i]);
4456
4457 Modified();
4458}
4459
4460////////////////////////////////////////////////////////////////////////////////
4461/// Paint polymarker in CurrentPad World coordinates.
4462
4464{
4465 Int_t n = TMath::Abs(nn);
4467 if (nn > 0 || TestBit(TGraph::kClipFrame)) {
4469 } else {
4470 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4471 }
4472 Int_t i,i1=-1,np=0;
4473 for (i=0; i<n; i++) {
4474 if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
4475 np++;
4476 if (i1 < 0) i1 = i;
4477 if (i < n-1) continue;
4478 }
4479 if (np == 0)
4480 continue;
4481 if (auto pp = GetPainter()) {
4482 pp->OnPad(this);
4483 pp->DrawPolyMarker(np, &x[i1], &y[i1]);
4484 }
4485 i1 = -1;
4486 np = 0;
4487 }
4488 Modified();
4489}
4490
4491////////////////////////////////////////////////////////////////////////////////
4492/// Paint polymarker in CurrentPad World coordinates.
4493
4495{
4496 Int_t n = TMath::Abs(nn);
4498 if (nn > 0 || TestBit(TGraph::kClipFrame)) {
4500 } else {
4501 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4502 }
4503 Int_t i,i1=-1,np=0;
4504 for (i=0; i<n; i++) {
4505 if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
4506 np++;
4507 if (i1 < 0) i1 = i;
4508 if (i < n-1) continue;
4509 }
4510 if (np == 0)
4511 continue;
4512 if (auto pp = GetPainter()) {
4513 pp->OnPad(this);
4514 pp->DrawPolyMarker(np, &x[i1], &y[i1]);
4515 }
4516 i1 = -1;
4517 np = 0;
4518 }
4519 Modified();
4520}
4521
4522////////////////////////////////////////////////////////////////////////////////
4523/// Paint N individual segments
4524/// Provided arrays should have 2*n elements
4525/// IMPORTANT! Provided arrays can be modified after function call!
4526
4528{
4529 if (n < 1)
4530 return;
4531
4536 } else {
4537 xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
4538 if (option && *option == 'C') mustClip = kFALSE;
4539 }
4540
4541 if (!mustClip)
4542 isAny = kTRUE;
4543 else {
4544 for (Int_t i = 0; i < 2*n; i+=2) {
4545 Int_t iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
4546 if (iclip == 2)
4547 x[i] = y[i] = x[i+1] = y[i+1] = 0;
4548 else
4549 isAny = kTRUE;
4550 }
4551 }
4552
4553 if (isAny)
4554 if (auto pp = GetPainter()) {
4555 pp->OnPad(this);
4556 pp->DrawSegments(n, x, y);
4557 }
4558
4559 Modified();
4560}
4561
4562
4563////////////////////////////////////////////////////////////////////////////////
4564/// Paint N individual segments in NDC coordinates
4565/// Provided arrays should have 2*n elements
4566/// IMPORTANT! Provided arrays can be modified after function call!
4567
4569{
4570 if (auto pp = GetPainter()) {
4571 pp->OnPad(this);
4572 pp->DrawSegmentsNDC(n, u, v);
4573 }
4574
4575 Modified();
4576}
4577
4578
4579////////////////////////////////////////////////////////////////////////////////
4580/// Paint text in CurrentPad World coordinates.
4581
4583{
4584 Modified();
4585
4586 if (auto pp = GetPainter()) {
4587 pp->OnPad(this);
4588 pp->DrawText(x, y, text, TVirtualPadPainter::kClear);
4589 }
4590}
4591
4592////////////////////////////////////////////////////////////////////////////////
4593/// Paint text in CurrentPad World coordinates.
4594
4595void TPad::PaintText(Double_t x, Double_t y, const wchar_t *text)
4596{
4597 Modified();
4598
4599 if (auto pp = GetPainter()) {
4600 pp->OnPad(this);
4601 pp->DrawText(x, y, text, TVirtualPadPainter::kClear);
4602 }
4603}
4604
4605////////////////////////////////////////////////////////////////////////////////
4606/// Paint text with URL in CurrentPad World coordinates.
4607
4608void TPad::PaintTextUrl(Double_t x, Double_t y, const char *text, const char *url)
4609{
4610 Modified();
4611
4612 if (auto pp = GetPainter()) {
4613 pp->OnPad(this);
4614 pp->DrawTextUrl(x, y, text, url);
4615 }
4616}
4617
4618////////////////////////////////////////////////////////////////////////////////
4619/// Paint text in CurrentPad NDC coordinates.
4620
4622{
4623 Modified();
4624
4625 if (auto pp = GetPainter()) {
4626 pp->OnPad(this);
4627 pp->DrawTextNDC(u, v, text, TVirtualPadPainter::kClear);
4628 }
4629}
4630
4631////////////////////////////////////////////////////////////////////////////////
4632/// Paint text in CurrentPad NDC coordinates.
4633
4635{
4636 Modified();
4637
4638 if (auto pp = GetPainter()) {
4639 pp->OnPad(this);
4640 pp->DrawTextNDC(u, v, text, TVirtualPadPainter::kClear);
4641 }
4642}
4643
4644////////////////////////////////////////////////////////////////////////////////
4645/// Search for an object at pixel position px,py.
4646///
4647/// Check if point is in this pad.
4648///
4649/// If yes, check if it is in one of the sub-pads
4650///
4651/// If found in the pad, compute closest distance of approach
4652/// to each primitive.
4653///
4654/// If one distance of approach is found to be within the limit Distancemaximum
4655/// the corresponding primitive is selected and the routine returns.
4656
4658{
4659 //the two following statements are necessary under NT (multithreaded)
4660 //when a TCanvas object is being created and a thread calling TPad::Pick
4661 //before the TPad constructor has completed in the other thread
4662 if (!gPad) return nullptr; //Andy Haas
4663 if (!GetListOfPrimitives()) return nullptr; //Andy Haas
4664
4665 Int_t dist;
4666 // Search if point is in pad itself
4667 Double_t x = AbsPixeltoX(px);
4668 Double_t y = AbsPixeltoY(py);
4669 if (this != gPad->GetCanvas()) {
4670 if (!((x >= fX1 && x <= fX2) && (y >= fY1 && y <= fY2))) return nullptr;
4671 }
4672
4673 // search for a primitive in this pad or its sub-pads
4674 static TObjOptLink dummyLink(nullptr,""); //place holder for when no link available
4675
4676 TContext ctxt(this, kFALSE); // since no drawing will be done, don't use cd() for efficiency reasons
4677
4678 TPad *pick = nullptr;
4679 TPad *picked = this;
4680 pickobj = nullptr;
4682 dummyLink.SetObject(this);
4683 pickobj = &dummyLink;
4684 }
4685
4686 // Loop backwards over the list of primitives. The first non-pad primitive
4687 // found is the selected one. However, we have to keep going down the
4688 // list to see if there is maybe a pad overlaying the primitive. In that
4689 // case look into the pad for a possible primitive. Once a pad has been
4690 // found we can terminate the loop.
4691 Bool_t gotPrim = kFALSE; // true if found a non pad primitive
4693
4694 //We can have 3d stuff in pad. If canvas prefers to draw
4695 //such stuff with OpenGL, the selection of 3d objects is
4696 //a gl viewer business so, in first cycle we do not
4697 //call DistancetoPrimitive for TAtt3D descendants.
4698 //In case of gl we first try to select 2d object first.
4699
4700 while (lnk) {
4701 TObject *obj = lnk->GetObject();
4702
4703 //If canvas prefers GL, all 3d objects must be drawn/selected by
4704 //gl viewer
4705 if (obj->InheritsFrom(TAtt3D::Class()) && fEmbeddedGL) {
4706 lnk = lnk->Prev();
4707 continue;
4708 }
4709
4710 fPadPointer = obj;
4711 if (obj->InheritsFrom(TPad::Class())) {
4712 pick = ((TPad*)obj)->Pick(px, py, pickobj);
4713 if (pick) {
4714 picked = pick;
4715 break;
4716 }
4717 } else if (!gROOT->GetEditorMode()) {
4718 if (!gotPrim) {
4719 if (!obj->TestBit(kCannotPick)) {
4720 dist = obj->DistancetoPrimitive(px, py);
4721 if (dist < fgMaxPickDistance) {
4722 pickobj = lnk;
4723 gotPrim = kTRUE;
4724 if (dist == 0) break;
4725 }
4726 }
4727 }
4728 }
4729
4730 lnk = lnk->Prev();
4731 }
4732
4733 //if no primitive found, check if we have a TView
4734 //if yes, return the view except if you are in the lower or upper X range
4735 //of the pad.
4736 //In case canvas prefers gl, fView existence
4737 //automatically means viewer3d existence. (?)
4738
4739 if (fView && !gotPrim) {
4740 Double_t dx = 0.05*(fUxmax-fUxmin);
4741 if ((x > fUxmin + dx) && (x < fUxmax-dx)) {
4742
4743 if (fEmbeddedGL) {
4744 //No 2d stuff was selected, but we have gl-viewer. Let it select an object in
4745 //scene (or select itself). In any case it'll internally call
4746 //gPad->SetSelected(ptr) as, for example, hist painter does.
4747 py -= Int_t((1 - GetHNDC() - GetYlowNDC()) * GetWh());
4748 px -= Int_t(GetXlowNDC() * GetWw());
4750 }
4751 else
4752 dummyLink.SetObject(fView);
4753 }
4754 }
4755
4756 if (picked->InheritsFrom(TButton::Class())) {
4758 if (!button->IsEditable()) pickobj = nullptr;
4759 }
4760
4761 if (TestBit(kCannotPick)) {
4762
4763 if (picked == this) {
4764 // cannot pick pad itself!
4765 picked = nullptr;
4766 }
4767
4768 }
4769
4770 return picked;
4771}
4772
4773////////////////////////////////////////////////////////////////////////////////
4774/// Pop pad to the top of the stack.
4775
4777{
4779 return;
4780 if (!fPrimitives)
4781 fPrimitives = new TList;
4782 if (this == fMother->GetListOfPrimitives()->Last())
4783 return;
4784
4786 while (auto obj = next())
4787 if (obj == this) {
4788 TString opt = next.GetOption();
4789 fMother->Remove(this, kFALSE); // do not issue modified
4790 fMother->Add(this, opt.Data());
4791 return;
4792 }
4793}
4794
4795////////////////////////////////////////////////////////////////////////////////
4796/// This method is equivalent to `SaveAs("filename")`. See TPad::SaveAs for details.
4797
4798void TPad::Print(const char *filename) const
4799{
4800 ((TPad*)this)->SaveAs(filename);
4801}
4802
4803////////////////////////////////////////////////////////////////////////////////
4804/// Auxiliary function. Returns kTRUE if list contains an object inherited
4805/// from TImage
4806
4808{
4809 TIter next(li);
4810
4811 while (auto obj = next()) {
4812 if (obj->InheritsFrom(TImage::Class())) {
4813 return kTRUE;
4814 } else if (obj->InheritsFrom(TPad::Class())) {
4815 if (ContainsTImage(((TPad*)obj)->GetListOfPrimitives())) {
4816 return kTRUE;
4817 }
4818 }
4819 }
4820 return kFALSE;
4821}
4822
4823////////////////////////////////////////////////////////////////////////////////
4824/// Save Canvas contents in a file in one of various formats.
4825///
4826/// \anchor TPadPrint
4827/// option can be:
4828///
4829/// - `ps`: a Postscript file is produced (default). [See special cases](\ref TPadPrintPS).
4830/// - `Portrait`: Postscript file is produced (Portrait)
4831/// - `Landscape`: Postscript file is produced (Landscape)
4832/// - `eps`: an Encapsulated Postscript file is produced
4833/// - `Preview`: an [Encapsulated Postscript file with preview](\ref TPadPrintPreview) is produced.
4834/// - `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.
4835/// - `Title:`: The character string after `Title:` becomes a table
4836/// of content entry (for PDF files).
4837/// - `EmbedFonts`: a [PDF file with embedded fonts](\ref TPadPrintEmbedFonts) is generated.
4838/// - `svg`: a SVG file is produced
4839/// - `tex`: a TeX file is produced
4840/// - `Standalone`: a [standalone TeX file](\ref TPadPrintStandalone) is produced.
4841/// - `gif`: a GIF file is produced
4842/// - `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
4843/// - `xpm`: a XPM file is produced
4844/// - `png`: a PNG file is produced
4845/// - `jpg`: a JPEG file is produced. NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
4846/// - `tiff`: a TIFF file is produced
4847/// - `cxx`: a C++ macro file is produced
4848/// - `xml`: a XML file
4849/// - `json`: a JSON file
4850/// - `root`: a ROOT binary file
4851///
4852/// `filename` = 0 - filename is defined by `GetName` and its
4853/// extension is defined with the option
4854///
4855/// When Postscript output is selected (`ps`, `eps`), the canvas is saved
4856/// to `filename.ps` or `filename.eps`. The aspect ratio of the canvas is preserved
4857/// on the Postscript file. When the "ps" option is selected, the Postscript
4858/// page will be landscape format if the canvas is in landscape format, otherwise
4859/// portrait format is selected.
4860///
4861/// The physical size of the Postscript page is the one selected in the
4862/// current style. This size can be modified via TStyle::SetPaperSize.
4863///
4864/// Examples:
4865/// ~~~ {.cpp}
4866/// gStyle->SetPaperSize(TStyle::kA4); //default
4867/// gStyle->SetPaperSize(TStyle::kUSLetter);
4868/// ~~~
4869/// where TStyle::kA4 and TStyle::kUSLetter are defined in the enum
4870/// EPaperSize in TStyle.h
4871///
4872/// An alternative is to call:
4873/// ~~~ {.cpp}
4874/// gStyle->SetPaperSize(20,26); same as kA4
4875/// or gStyle->SetPaperSize(20,24); same as kUSLetter
4876/// ~~~
4877/// The above numbers take into account some margins and are in centimeters.
4878///
4879/// \anchor TPadPrintPreview
4880/// ### The "Preview" option
4881///
4882/// The "Preview" option allows to generate a preview (in the TIFF format) within
4883/// the Encapsulated Postscript file. This preview can be used by programs like
4884/// MSWord to visualize the picture on screen. The "Preview" option relies on the
4885/// ["epstool" command](http://www.cs.wisc.edu/~ghost/gsview/epstool.htm).
4886///
4887/// Example:
4888/// ~~~ {.cpp}
4889/// canvas->Print("example.eps","Preview");
4890/// ~~~
4891///
4892/// \anchor TPadPrintEmbedFonts
4893/// ### The "EmbedFonts" option
4894///
4895/// The "EmbedFonts" option allows to embed the fonts used in a PDF file inside
4896/// that file. This option relies on the ["gs" command](https://ghostscript.com).
4897///
4898/// Example:
4899/// ~~~ {.cpp}
4900/// canvas->Print("example.pdf","EmbedFonts");
4901/// ~~~
4902///
4903/// \anchor TPadPrintStandalone
4904/// ### The "Standalone" option
4905/// The "Standalone" option allows to generate a TeX file ready to be processed by
4906/// tools like `pdflatex`.
4907///
4908/// Example:
4909/// ~~~ {.cpp}
4910/// canvas->Print("example.tex","Standalone");
4911/// ~~~
4912///
4913/// \anchor TPadPrintPS
4914/// ### Writing several canvases to the same Postscript or PDF file:
4915///
4916/// - if the Postscript or PDF file name finishes with "(", the file is not closed
4917/// - if the Postscript or PDF file name finishes with ")" and the file has been opened
4918/// with "(", the file is closed.
4919///
4920/// Example:
4921/// ~~~ {.cpp}
4922/// {
4923/// TCanvas c1("c1");
4924/// h1.Draw();
4925/// c1.Print("c1.ps("); //write canvas and keep the ps file open
4926/// h2.Draw();
4927/// c1.Print("c1.ps"); canvas is added to "c1.ps"
4928/// h3.Draw();
4929/// c1.Print("c1.ps)"); canvas is added to "c1.ps" and ps file is closed
4930/// }
4931/// ~~~
4932/// In the previous example replacing "ps" by "pdf" will create a multi-pages PDF file.
4933///
4934/// Note that the following sequence writes the canvas to "c1.ps" and closes the ps file.:
4935/// ~~~ {.cpp}
4936/// TCanvas c1("c1");
4937/// h1.Draw();
4938/// c1.Print("c1.ps");
4939/// ~~~
4940/// The `TCanvas::Print("file.ps(")` mechanism is very useful, but it can be
4941/// a little inconvenient to have the action of opening/closing a file
4942/// being atomic with printing a page. Particularly if pages are being
4943/// generated in some loop one needs to detect the special cases of first
4944/// and last page and then munge the argument to Print() accordingly.
4945///
4946/// The "[" and "]" can be used instead of "(" and ")" to open / close without
4947/// actual printing.
4948///
4949/// Example:
4950/// ~~~ {.cpp}
4951/// c1.Print("file.ps["); // No actual print, just open file.ps
4952/// for (int i=0; i<10; ++i) {
4953/// // fill canvas for context i
4954/// // ...
4955///
4956/// c1.Print("file.ps"); // actually print canvas to file
4957/// }// end loop
4958/// c1.Print("file.ps]"); // No actual print, just close.
4959/// ~~~
4960/// As before, the same macro is valid for PDF files.
4961///
4962/// It is possible to print a canvas into an animated GIF file by specifying the
4963/// file name as "myfile.gif+" or "myfile.gif+NN", where NN*10ms is delay
4964/// between the subimages' display. If NN is omitted the delay between
4965/// subimages is zero. Each picture is added in the animation thanks to a loop
4966/// similar to the following one:
4967/// ~~~ {.cpp}
4968/// for (int i=0; i<10; ++i) {
4969/// // fill canvas for context i
4970/// // ...
4971///
4972/// c1.Print("file.gif+5"); // print canvas to GIF file with 50ms delays
4973/// }// end loop
4974/// ~~~
4975/// The delay between each frame must be specified in each Print() statement.
4976/// If the file "myfile.gif" already exists, the new frame are appended at
4977/// the end of the file. To avoid this, delete it first with `gSystem->Unlink(myfile.gif);`
4978/// If you want the gif file to repeat or loop forever, check TASImage::WriteImage documentation
4979
4981{
4982 if (!GetCanvas())
4983 return;
4984
4986
4987 // "[" and "]" are special characters for ExpandPathName. When they are at the end
4988 // of the file name (see help) they must be removed before doing ExpandPathName.
4989 if (fs1.EndsWith("[")) {
4990 fs1.Replace((fs1.Length()-1),1," ");
4992 fs1.Replace((fs1.Length()-1),1,"[");
4993 } else if (fs1.EndsWith("]")) {
4994 fs1.Replace((fs1.Length()-1),1," ");
4996 fs1.Replace((fs1.Length()-1),1,"]");
4997 } else {
4999 }
5000
5001 // Set the default option as "Postscript" (Should be a data member of TPad)
5002 const char *opt_default = "ps";
5003
5004 TString opt = !option ? opt_default : option;
5006
5007 Bool_t title = kFALSE;
5008 if (strstr(opt,"Title:")) title = kTRUE;
5009
5010 if (!fs1.Length()) {
5011 psname = GetName();
5012 psname += opt;
5013 } else {
5014 psname = fs1;
5015 }
5016
5017 // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
5018 if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
5019 psname = GetName();
5020 psname.Append(fs1);
5021 psname.Prepend("/");
5022 psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
5023 }
5024
5025 // Save pad/canvas in alternative formats
5027 if (!title && strstr(opt, "gif+")) {
5029 image = kTRUE;
5030 } else if (!title && strstr(opt, "gif")) {
5032 image = kTRUE;
5033 } else if (!title && strstr(opt, "png")) {
5035 image = kTRUE;
5036 } else if (!title && strstr(opt, "jpg")) {
5038 image = kTRUE;
5039 } else if (!title && strstr(opt, "tiff")) {
5041 image = kTRUE;
5042 } else if (!title && strstr(opt, "xpm")) {
5044 image = kTRUE;
5045 } else if (!title && strstr(opt, "bmp")) {
5047 image = kTRUE;
5048 }
5049
5050 if (GetCanvas()->IsWeb() && GetPainter() &&
5051 (strstr(opt,"svg") || strstr(opt,"pdf") || (gtype == TImage::kJpeg) || (gtype == TImage::kPng))) {
5052 GetPainter()->SaveImage(this, psname.Data(), gtype);
5053 return;
5054 }
5055
5056 if (!GetCanvas()->IsBatch() && GetPainter())
5058
5059
5060 if (!gROOT->IsBatch() && image) {
5062 Int_t wid = (this == GetCanvas()) ? GetCanvas()->GetCanvasID() : GetPixmapID();
5063 Color_t hc = gPad->GetCanvas()->GetHighLightColor();
5064 gPad->GetCanvas()->SetHighLightColor(-1);
5065 gPad->Modified();
5066 gPad->Update();
5067 if (GetPainter()) {
5069 GetPainter()->SaveImage(this, psname.Data(), gtype);
5070 }
5071 if (!gSystem->AccessPathName(psname.Data())) {
5072 Info("Print", "GIF file %s has been created", psname.Data());
5073 }
5074 gPad->GetCanvas()->SetHighLightColor(hc);
5075 return;
5076 }
5077 if (gtype != TImage::kUnknown) {
5078 Color_t hc = gPad->GetCanvas()->GetHighLightColor();
5079 gPad->GetCanvas()->SetHighLightColor(-1);
5080 gPad->Modified();
5081 gPad->Update();
5082 gPad->GetCanvasImp()->UpdateDisplay(1, kTRUE);
5083 if (GetPainter())
5084 GetPainter()->SaveImage(this, psname, gtype);
5085 if (!gSystem->AccessPathName(psname)) {
5086 Info("Print", "file %s has been created", psname.Data());
5087 }
5088 gPad->GetCanvas()->SetHighLightColor(hc);
5089 } else {
5090 Warning("Print", "Unsupported image format %s", psname.Data());
5091 }
5092 return;
5093 }
5094
5095 //==============Save pad/canvas as a C++ script==============================
5096 if (!title && strstr(opt,"cxx")) {
5097 GetCanvas()->SaveSource(psname, "");
5098 return;
5099 }
5100
5101 //==============Save pad/canvas as a root file===============================
5102 if (!title && strstr(opt,"root")) {
5103 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5104 return;
5105 }
5106
5107 //==============Save pad/canvas as a XML file================================
5108 if (!title && strstr(opt,"xml")) {
5109 // Plugin XML driver
5110 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5111 return;
5112 }
5113
5114 //==============Save pad/canvas as a JSON file================================
5115 if (!title && strstr(opt,"json")) {
5116 if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
5117 return;
5118 }
5119
5120 //==============Save pad/canvas as a SVG file================================
5121 if (!title && strstr(opt,"svg")) {
5122 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5123
5125 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5126 noScreen = kTRUE;
5128 }
5129
5130 TContext ctxt(this, kTRUE);
5131
5132 if (!gVirtualPS) {
5133 // Plugin Postscript/SVG driver
5134 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "svg")) {
5135 if (h->LoadPlugin() == -1)
5136 return;
5137 h->ExecPlugin(0);
5138 }
5139 }
5140
5141 // Create a new SVG file
5142 if (gVirtualPS) {
5147 }
5148
5149 Paint();
5150 if (noScreen)
5152 if (wasModified && !IsBatch())
5153 Modified(kTRUE);
5154
5156 Info("Print", "SVG file %s has been created", psname.Data());
5157
5158 delete gVirtualPS;
5159 gVirtualPS = nullptr;
5160
5161 return;
5162 }
5163
5164 //==============Save pad/canvas as a TeX file================================
5165 if (!title && (strstr(opt,"tex") || strstr(opt,"Standalone"))) {
5166 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5167
5169 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5170 noScreen = kTRUE;
5172 }
5173
5174 TContext ctxt(this, kTRUE);
5175
5176 if (!gVirtualPS) {
5177 // Plugin Postscript/SVG driver
5178 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "tex")) {
5179 if (h->LoadPlugin() == -1)
5180 return;
5181 h->ExecPlugin(0);
5182 }
5183 }
5184
5186 if (strstr(opt,"Standalone")) standalone = kTRUE;
5187
5188 // Create a new TeX file
5189 if (gVirtualPS) {
5191 if (standalone) gVirtualPS->SetTitle("Standalone");
5195 }
5196 Paint();
5197 if (noScreen)
5199 if (wasModified && !IsBatch())
5200 Modified(kTRUE);
5201
5202 if (!gSystem->AccessPathName(psname)) {
5203 if (standalone) {
5204 Info("Print", "Standalone TeX file %s has been created", psname.Data());
5205 } else{
5206 Info("Print", "TeX file %s has been created", psname.Data());
5207 }
5208 }
5209
5210 delete gVirtualPS;
5211 gVirtualPS = nullptr;
5212
5213 return;
5214 }
5215
5216 //==============Save pad/canvas as a Postscript file=========================
5217
5218 // in case we read directly from a Root file and the canvas
5219 // is not on the screen, set batch mode
5220
5223 if (!image) {
5224 // The parenthesis mechanism is only valid for PS and PDF files.
5225 copen = psname.EndsWith("("); if (copen) psname[psname.Length()-1] = 0;
5226 cclose = psname.EndsWith(")"); if (cclose) psname[psname.Length()-1] = 0;
5227 copenb = psname.EndsWith("["); if (copenb) psname[psname.Length()-1] = 0;
5228 ccloseb = psname.EndsWith("]"); if (ccloseb) psname[psname.Length()-1] = 0;
5229 }
5230 gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
5232 if (copen || copenb) mustClose = kFALSE;
5233 if (cclose || ccloseb) mustClose = kTRUE;
5234
5236 if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
5237 noScreen = kTRUE;
5239 }
5240 Int_t pstype = 111;
5243 Double_t ratio = ycanvas/xcanvas;
5244 if (ratio < 1) pstype = 112;
5245 if (strstr(opt,"Portrait")) pstype = 111;
5246 if (strstr(opt,"Landscape")) pstype = 112;
5247 if (strstr(opt,"eps")) pstype = 113;
5248 if (strstr(opt,"Preview")) pstype = 113;
5249
5250 TContext ctxt(this, kTRUE);
5252
5253 if (!gVirtualPS || mustOpen) {
5254
5255 const char *pluginName = "ps"; // Plugin Postscript driver
5256 if (strstr(opt,"pdf") || title || strstr(opt,"EmbedFonts"))
5257 pluginName = "pdf";
5258 else if (image)
5259 pluginName = "image"; // Plugin TImageDump driver
5260
5261 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", pluginName)) {
5262 if (h->LoadPlugin() == -1)
5263 return;
5264 h->ExecPlugin(0);
5265 }
5266
5267 // Create a new Postscript, PDF or image file
5268 if (gVirtualPS)
5270 const Ssiz_t titlePos = opt.Index("Title:");
5271 if (titlePos != kNPOS) {
5272 if (gVirtualPS)
5273 gVirtualPS->SetTitle(opt.Data()+titlePos+6);
5274 opt.Replace(titlePos,opt.Length(),"pdf");
5275 }
5276 if (gVirtualPS)
5278 if (gVirtualPS)
5280 if (!copenb) {
5281 if (!strstr(opt,"pdf") || image) {
5283 }
5284 Paint();
5285 }
5287
5288 if (mustClose) {
5289 gROOT->GetListOfSpecials()->Remove(gVirtualPS);
5290 delete gVirtualPS;
5291 gVirtualPS = psave;
5292 } else {
5293 gROOT->GetListOfSpecials()->Add(gVirtualPS);
5294 gVirtualPS = nullptr;
5295 }
5296
5297 if (!gSystem->AccessPathName(psname)) {
5298 if (!copen) Info("Print", "%s file %s has been created", opt.Data(), psname.Data());
5299 else Info("Print", "%s file %s has been created using the current canvas", opt.Data(), psname.Data());
5300 }
5301 } else {
5302 // Append to existing Postscript, PDF or GIF file
5303 if (!ccloseb) {
5305 Paint();
5306 }
5307 const Ssiz_t titlePos = opt.Index("Title:");
5308 if (titlePos != kNPOS) {
5309 gVirtualPS->SetTitle(opt.Data()+titlePos+6);
5310 opt.Replace(titlePos,opt.Length(),"pdf");
5311 } else if (!ccloseb) {
5312 gVirtualPS->SetTitle("PDF");
5313 }
5314 if (mustClose) {
5315 if (cclose) Info("Print", "Current canvas added to %s file %s and file closed", opt.Data(), psname.Data());
5316 else Info("Print", "%s file %s has been closed", opt.Data(), psname.Data());
5317 gROOT->GetListOfSpecials()->Remove(gVirtualPS);
5318 delete gVirtualPS;
5319 gVirtualPS = nullptr;
5320 } else {
5321 Info("Print", "Current canvas added to %s file %s", opt.Data(), psname.Data());
5322 gVirtualPS = nullptr;
5323 }
5324 }
5325
5326 if (wasModified && !IsBatch())
5327 Modified(kTRUE);
5328
5329 if (strstr(opt,"Preview"))
5330 gSystem->Exec(TString::Format("epstool --quiet -t6p %s %s", psname.Data(), psname.Data()).Data());
5331 if (strstr(opt,"EmbedFonts")) {
5332 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",
5333 psname.Data()).Data());
5334 gSystem->Rename("pdf_temp.pdf", psname.Data());
5335 }
5336
5337}
5338
5339////////////////////////////////////////////////////////////////////////////////
5340/// Set world coordinate system for the pad.
5341/// Emits signal "RangeChanged()", in the slot get the range
5342/// via GetRange().
5343
5345{
5346 if ((x1 >= x2) || (y1 >= y2)) {
5347 Error("Range", "illegal world coordinates range: x1=%f, y1=%f, x2=%f, y2=%f",x1,y1,x2,y2);
5348 return;
5349 }
5350
5351 fUxmin = x1;
5352 fUxmax = x2;
5353 fUymin = y1;
5354 fUymax = y2;
5355
5356 if (fX1 == x1 && fY1 == y1 && fX2 == x2 && fY2 == y2) return;
5357
5358 fX1 = x1;
5359 fY1 = y1;
5360 fX2 = x2;
5361 fY2 = y2;
5362
5363 // compute pad conversion coefficients
5364 ResizePad();
5365
5366 if (gPad == this && GetPainter())
5368
5369 // emit signal
5370 RangeChanged();
5371}
5372
5373////////////////////////////////////////////////////////////////////////////////
5374/// Set axis coordinate system for the pad.
5375/// The axis coordinate system is a subset of the world coordinate system
5376/// xmin,ymin is the origin of the current coordinate system,
5377/// xmax is the end of the X axis, ymax is the end of the Y axis.
5378/// By default a margin of 10 per cent is left on all sides of the pad
5379/// Emits signal "RangeAxisChanged()", in the slot get the axis range
5380/// via GetRangeAxis().
5381
5383{
5384 if ((xmin >= xmax) || (ymin >= ymax)) {
5385 Error("RangeAxis", "illegal axis coordinates range: xmin=%f, ymin=%f, xmax=%f, ymax=%f",
5386 xmin, ymin, xmax, ymax);
5387 return;
5388 }
5389
5390 fUxmin = xmin;
5391 fUymin = ymin;
5392 fUxmax = xmax;
5393 fUymax = ymax;
5394
5395 // emit signal
5397}
5398
5399////////////////////////////////////////////////////////////////////////////////
5400/// Recursively remove object from a pad and its sub-pads.
5401
5403{
5404 if (fCanvas) {
5405 if (obj == fCanvas->GetSelected()) fCanvas->SetSelected(nullptr);
5406 if (obj == fCanvas->GetClickSelected()) fCanvas->SetClickSelected(nullptr);
5407 }
5408 if (obj == fView) fView = nullptr;
5409 if (!fPrimitives) return;
5412 if (nold != fPrimitives->GetSize()) fModified = kTRUE;
5413}
5414
5415////////////////////////////////////////////////////////////////////////////////
5416/// Remove object from list of primitives
5417/// When \par modified set to kTRUE (default) pad will be marked as modified - if object really removed
5418/// Returns result of GetListOfPrimitives()->Remove(obj) or nullptr if list of primitives not exists
5419
5421{
5422 TObject *res = nullptr;
5423 if (fPrimitives)
5424 res = fPrimitives->Remove(obj);
5425 if (res && modified)
5426 Modified();
5427 return res;
5428}
5429
5430////////////////////////////////////////////////////////////////////////////////
5431/// Redraw the frame axis.
5432///
5433/// Redrawing axis may be necessary in case of superimposed histograms
5434/// when one or more histograms have a fill color.
5435///
5436/// Instead of calling this function, it may be more convenient
5437/// to call directly `h1->Draw("sameaxis")` where h1 is the pointer
5438/// to the first histogram drawn in the pad.
5439///
5440/// By default, if the pad has the options gridx or/and gridy activated,
5441/// the grid is not drawn by this function.
5442///
5443/// If option="g" is specified, this will force the drawing of the grid
5444/// on top of the picture
5445///
5446/// To redraw the axis tick marks do:
5447/// ~~~ {.cpp}
5448/// gPad->RedrawAxis();
5449/// ~~~
5450/// To redraw the axis grid do:
5451/// ~~~ {.cpp}
5452/// gPad->RedrawAxis("G");
5453/// ~~~
5454/// To redraw the axis tick marks and the axis grid do:
5455/// ~~~ {.cpp}
5456/// gPad->RedrawAxis();
5457/// gPad->RedrawAxis("G");
5458/// ~~~
5459///
5460/// If option="f" is specified, this will force the drawing of the frame
5461/// around the plot.
5462
5464{
5465 TString opt = option;
5466 opt.ToLower();
5467
5468 TContext ctxt(this, kTRUE);
5469
5470 TH1 *hobj = nullptr;
5471
5472 // Get the first histogram drawing the axis in the list of primitives
5473 if (!fPrimitives) fPrimitives = new TList;
5474 TIter next(fPrimitives);
5475 TObject *obj;
5476 while ((obj = next())) {
5477 if (obj->InheritsFrom(TH1::Class())) {
5478 hobj = (TH1*)obj;
5479 break;
5480 }
5481 if (obj->InheritsFrom(TMultiGraph::Class())) {
5482 TMultiGraph *mg = (TMultiGraph*)obj;
5483 if (mg) hobj = mg->GetHistogram();
5484 break;
5485 }
5486 if (obj->InheritsFrom(TGraph::Class())) {
5487 TGraph *g = (TGraph*)obj;
5488 if (g) hobj = g->GetHistogram();
5489 break;
5490 }
5491 if (obj->InheritsFrom(THStack::Class())) {
5492 THStack *hs = (THStack*)obj;
5493 if (hs) hobj = hs->GetHistogram();
5494 break;
5495 }
5496 }
5497
5498 if (hobj) {
5499 if (opt.Contains("g")) hobj->DrawCopy("sameaxig");
5500 else hobj->DrawCopy("sameaxis");
5501 }
5502
5503 if (opt.Contains("f")) {
5504 auto b = new TBox(gPad->GetUxmin(), gPad->GetUymin(),
5505 gPad->GetUxmax(), gPad->GetUymax());
5506 b->SetFillStyle(0);
5507 b->SetLineStyle(gPad->GetFrameLineStyle());
5508 b->SetLineWidth(gPad->GetFrameLineWidth());
5509 b->SetLineColor(gPad->GetFrameLineColor());
5510 b->Draw();
5511 }
5512}
5513
5514////////////////////////////////////////////////////////////////////////////////
5515/// Compute pad conversion coefficients.
5516///
5517/// ### Conversion from x to px
5518///
5519/// \f[\frac{x-xmin}{xrange} = \frac{px-pxlow}{pxrange}\f]
5520/// with:
5521/// \f[ xrange = xmax-xmin \f]
5522/// \f[ pxrange = pxmax-pxmin \f]
5523///
5524/// \f[
5525/// \Rightarrow px = \frac{pxrange(x-xmin)}{xrange} + pxlow = fXtoPixelk + fXtoPixel \times x
5526/// \f]
5527///
5528/// \f[
5529/// \Rightarrow fXtoPixelk = pxlow - pxrange \frac{xmin}{xrange}
5530/// \f]
5531/// \f[
5532/// fXtoPixel = \frac{pxrange}{xrange}
5533/// \f]
5534/// where:
5535/// \f[
5536/// pxlow = fAbsXlowNDC \times fCw
5537/// \f]
5538/// \f[
5539/// pxrange = fAbsWNDC \times fCw
5540/// \f]
5541///
5542/// ### Conversion from y to py
5543///
5544/// \f[\frac{y-ymin}{yrange} = \frac{py-pylow}{pyrange}\f]
5545/// with:
5546/// \f[ yrange = ymax-ymin \f]
5547/// \f[ pyrange = pymax-pymin \f]
5548///
5549/// \f[
5550/// \Rightarrow py = \frac{pyrange(y-xmin)}{yrange} + pylow = fYtoPixelk + fYtoPixel \times y
5551/// \f]
5552///
5553/// \f[
5554/// \Rightarrow fYtoPixelk = pylow - pyrange \frac{ymin}{yrange}
5555/// \f]
5556/// \f[
5557/// fYtoPixel = \frac{pyrange}{yrange}
5558/// \f]
5559/// where:
5560/// \f[
5561/// pylow = fAbsYlowNDC \times fCh
5562/// \f]
5563/// \f[
5564/// pyrange = fAbsHNDC \times fCh
5565/// \f]
5566///
5567/// ### Conversion from px to x
5568///
5569/// \f[
5570/// \Rightarrow x = \frac{xrange(px-pxlow)}{pxrange}+ xmin = fPixeltoXk + fPixeltoX \times px
5571/// \f]
5572///
5573/// \f[
5574/// \Rightarrow fPixeltoXk = xmin - pxlow \times\frac{xrange}{pxrange}
5575/// \f]
5576/// \f[
5577/// fPixeltoX = \frac{xrange}{pxrange}
5578/// \f]
5579///
5580/// ### Conversion from py to y
5581///
5582/// \f[
5583/// \Rightarrow y = \frac{yrange(py-pylow)}{pyrange}+ ymin = fPixeltoYk + fPixeltoY \times py
5584/// \f]
5585///
5586/// \f[
5587/// \Rightarrow fPixeltoYk = ymin - pylow \times\frac{yrange}{pyrange}
5588/// \f]
5589/// \f[
5590/// fPixeltoY = \frac{yrange}{pyrange}
5591/// \f]
5592///
5593/// ### Computation of the coefficients in case of LOG scales
5594///
5595/// #### Conversion from pixel coordinates to world coordinates
5596///
5597/// \f[
5598/// u = \frac{Log(x) - Log(xmin)}{Log(xmax) - Log(xmin)} = \frac{Log(x/xmin)}{Log(xmax/xmin)} = \frac{px - pxlow}{pxrange}
5599/// \f]
5600///
5601/// \f[ \Rightarrow Log(\frac{x}{xmin}) = u \times Log(\frac{xmax}{xmin}) \f]
5602/// \f[ x = xmin \times e^{(u \times Log(\frac{xmax}{xmin})} \f]
5603/// Let:
5604/// \f[ alfa = \frac{Log(\frac{xmax}{xmin})}{fAbsWNDC} \f]
5605///
5606/// \f[ x = xmin \times e^{(-alfa \times pxlow)} + e^{(alfa \times px)} \f]
5607/// \f[ x = fPixeltoXk \times e^{(fPixeltoX \times px)} \f]
5608/// \f[ ==> fPixeltoXk = xmin \times e^{(-alfa*pxlow)} \f]
5609/// \f[ fPixeltoX = alfa \f]
5610///
5611/// \f[
5612/// v = \frac{Log(y) - Log(ymin)}{Log(ymax) - Log(ymin)} = \frac{Log(y/ymin)}{Log(ymax/ymin)} = \frac{py - pylow}{pyrange}
5613/// \f]
5614/// Let:
5615/// \f[ beta = Log(\frac{ymax}{ymin}) \f]
5616/// \f[ Log(\frac{y}{ymin}) = beta \times pylow - beta \times py \f]
5617/// \f[ \frac{y}{ymin} = e^{(beta \times pylow - beta \times py)} \f]
5618/// \f[ y = ymin \times e^{(beta \times pylow)} \times e^{(-beta \times py)}\f]
5619/// \f[ \Rightarrow y = fPixeltoYk \times e^{(fPixeltoY \times py)} \f]
5620/// \f[ fPixeltoYk = ymin \times e^{(beta \times pylow)} \f]
5621/// \f[ fPixeltoY = -beta \f]
5622///
5623/// #### Conversion from World coordinates to pixel coordinates
5624///
5625/// \f[ px = pxlow + u*pxrange \f]
5626/// \f[ = pxlow + Log(x/xmin)/alfa \f]
5627/// \f[ = pxlow -Log(xmin)/alfa + Log(x)/alfa \f]
5628/// \f[ = fXtoPixelk + fXtoPixel*Log(x) \f]
5629/// \f[ \Rightarrow fXtoPixelk = pxlow -Log(xmin)/alfa \f]
5630/// \f[ \Rightarrow fXtoPixel = 1/alfa \f]
5631///
5632/// \f[ py = pylow - Log(y/ymin)/beta \f]
5633/// \f[ = fYtoPixelk + fYtoPixel*Log(y) \f]
5634/// \f[ \Rightarrow fYtoPixelk = pylow - Log(ymin)/beta \f]
5635/// \f[ fYtoPixel = 1/beta \f]
5636
5638{
5639
5640 if (!gPad) {
5641 Error("ResizePad", "Cannot resize pad. No current pad available.");
5642 return;
5643 }
5644 if (gPad->GetWw()==0.0||gPad->GetWh()==0.0) {
5645 Warning("ResizePad", "gPad has at least one zero dimension.");
5646 return;
5647 }
5648 if (fX1==fX2||fY1==fY2) {
5649 Warning("ResizePad", "The pad has at least one zero dimension.");
5650 return;
5651 }
5652 // Recompute subpad positions in case pad has been moved/resized
5653 TPad *parent = fMother;
5654 if (this == gPad->GetCanvas()) {
5657 fAbsWNDC = fWNDC;
5658 fAbsHNDC = fHNDC;
5659 }
5660 else {
5661 if (parent->GetAbsHNDC()==0.0||parent->GetAbsWNDC()==0.0||fHNDC==0.0||fWNDC==0.0) {
5662 Warning("ResizePad", "The parent pad has at least one zero dimension.");
5663 return;
5664 }
5665 fAbsXlowNDC = fXlowNDC*parent->GetAbsWNDC() + parent->GetAbsXlowNDC();
5666 fAbsYlowNDC = fYlowNDC*parent->GetAbsHNDC() + parent->GetAbsYlowNDC();
5667 fAbsWNDC = fWNDC*parent->GetAbsWNDC();
5668 fAbsHNDC = fHNDC*parent->GetAbsHNDC();
5669 }
5670
5671 Double_t ww = (Double_t)gPad->GetWw();
5672 Double_t wh = (Double_t)gPad->GetWh();
5677
5678 // Linear X axis
5679 Double_t rounding = 0.; // was used before to adjust somehow wrong int trunctation by coordiantes transformation
5680 Double_t xrange = fX2 - fX1;
5681 fXtoAbsPixelk = rounding + pxlow - pxrange*fX1/xrange; //origin at left
5685 fPixeltoXk = fX1;
5687 // Linear Y axis
5688 Double_t yrange = fY2 - fY1;
5689 fYtoAbsPixelk = rounding + pylow - pyrange*fY1/yrange; //origin at top
5693 fPixeltoYk = fY1;
5695
5696 // Coefficients to convert from pad NDC coordinates to pixel coordinates
5697
5704
5705 // Coefficients to convert from canvas pixels to pad world coordinates
5706
5707 // Resize all sub-pads
5708 if (!fPrimitives)
5709 fPrimitives = new TList;
5710 TIter next(GetListOfPrimitives());
5711 while (auto obj = next()) {
5712 if (obj->InheritsFrom(TPad::Class()))
5713 ((TPad *)obj)->ResizePad(option);
5714 }
5715
5716 // Reset all current sizes
5717 if (gPad->IsBatch())
5718 fPixmapID = 0;
5719 else if (auto pp = GetPainter()) {
5720 if (pp->IsNative()) {
5721 // TODO: check if this is necessary
5722 auto attl = pp->GetAttLine();
5723 attl.SetLineColor(-1);
5724 pp->SetAttLine(attl);
5725 auto attt = pp->GetAttText();
5726 attt.SetTextSize(-1);
5727 pp->OnPad(this);
5728 pp->SetAttText(attt);
5729 // create or re-create off-screen pixmap
5730 if (fPixmapID) {
5731 int w = TMath::Abs(XtoPixel(fX2) - XtoPixel(fX1));
5732 int h = TMath::Abs(YtoPixel(fY2) - YtoPixel(fY1));
5733 //protection in case of wrong pad parameters.
5734 //without this protection, the OpenPixmap or ResizePixmap crashes with
5735 //the message "Error in <RootX11ErrorHandler>: BadValue (integer parameter out of range for operation)"
5736 //resulting in a frozen xterm
5739 Warning("ResizePad", "Inf/NaN propagated to the pad. Check drawn objects.");
5740 if (w <= 0 || w > 10000) {
5741 Warning("ResizePad", "%s width changed from %d to %d\n",GetName(),w,10);
5742 w = 10;
5743 }
5744 if (h <= 0 || h > 10000) {
5745 Warning("ResizePad", "%s height changed from %d to %d\n",GetName(),h,10);
5746 h = 10;
5747 }
5748 if (fPixmapID == -1) // this case is handled via the ctor
5749 fPixmapID = pp->CreateDrawable(w, h);
5750 else if (pp->ResizeDrawable(fPixmapID, w, h)) {
5751 Resized();
5752 Modified(kTRUE);
5753 }
5754 }
5755 }
5756 }
5757 if (fView) {
5758 if (gPad == this) {
5759 fView->ResizePad();
5760 } else {
5761 TContext ctxt(this, kTRUE);
5762 fView->ResizePad();
5763 }
5764 }
5765}
5766
5767////////////////////////////////////////////////////////////////////////////////
5768/// Save the pad content in a file.
5769///
5770/// The file's format used to save the pad is determined by the `filename` extension:
5771///
5772/// - if `filename` is empty, the file produced is `padname.ps`
5773/// - if `filename` starts with a dot, the padname is added in front
5774/// - if `filename` ends with `.ps`, a Postscript file is produced
5775/// - if `filename` ends with `.eps`, an Encapsulated Postscript file is produced
5776/// - 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.
5777/// - if `filename` ends with `.svg`, a SVG file is produced
5778/// - if `filename` ends with `.tex`, a TeX file is produced
5779/// - if `filename` ends with `.gif`, a GIF file is produced
5780/// - 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
5781/// - if `filename` ends with `.xpm`, a XPM file is produced
5782/// - if `filename` ends with `.png`, a PNG file is produced
5783/// - if `filename` ends with `.bmp`, a BMP file is produced
5784/// - if `filename` ends with `.jpg` or `.jpeg` a JPEG file is produced NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
5785/// - if `filename` ends with `.tiff`, a TIFF file is produced
5786/// - if `filename` ends with `.C`, `.cxx`,`.cpp` or `.cc`, a C++ macro file is produced
5787/// - if `filename` ends with `.root`, a Root file is produced
5788/// - if `filename` ends with `.xml`, a XML file is produced
5789/// - if `filename` ends with `.json`, a JSON file is produced
5790///
5791/// \remarks
5792/// - The parameter `option` is not used.
5793/// - This method calls [TPad::Print(const char *filename, Option_t *option)](\ref TPadPrint)
5794/// the value of `option` is determined by the `filename` extension.
5795/// - Postscript and PDF formats allow to have [several pictures in one file](\ref TPadPrintPS).
5796
5797void TPad::SaveAs(const char *filename, Option_t * /*option*/) const
5798{
5801
5802 if (!lenfil) { psname = GetName(); psname.Append(".ps"); }
5803 else psname = filename;
5804
5805 // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
5806 if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
5807 psname = GetName();
5808 psname.Append(filename);
5809 psname.Prepend("/");
5810 psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
5811 }
5812
5813 if (psname.EndsWith(".gif"))
5814 ((TPad*)this)->Print(psname,"gif");
5815 else if (psname.Contains(".gif+"))
5816 ((TPad*)this)->Print(psname,"gif+");
5817 else if (psname.EndsWith(".C") || psname.EndsWith(".cxx") || psname.EndsWith(".cpp") || psname.EndsWith(".cc"))
5818 ((TPad*)this)->Print(psname,"cxx");
5819 else if (psname.EndsWith(".root"))
5820 ((TPad*)this)->Print(psname,"root");
5821 else if (psname.EndsWith(".xml"))
5822 ((TPad*)this)->Print(psname,"xml");
5823 else if (psname.EndsWith(".json"))
5824 ((TPad*)this)->Print(psname,"json");
5825 else if (psname.EndsWith(".eps"))
5826 ((TPad*)this)->Print(psname,"eps");
5827 else if (psname.EndsWith(".pdf"))
5828 ((TPad*)this)->Print(psname,"pdf");
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(".svg"))
5838 ((TPad*)this)->Print(psname,"svg");
5839 else if (psname.EndsWith(".tex"))
5840 ((TPad*)this)->Print(psname,"tex");
5841 else if (psname.EndsWith(".xpm"))
5842 ((TPad*)this)->Print(psname,"xpm");
5843 else if (psname.EndsWith(".png"))
5844 ((TPad*)this)->Print(psname,"png");
5845 else if (psname.EndsWith(".jpg"))
5846 ((TPad*)this)->Print(psname,"jpg");
5847 else if (psname.EndsWith(".jpeg"))
5848 ((TPad*)this)->Print(psname,"jpg");
5849 else if (psname.EndsWith(".bmp"))
5850 ((TPad*)this)->Print(psname,"bmp");
5851 else if (psname.EndsWith(".tiff"))
5852 ((TPad*)this)->Print(psname,"tiff");
5853 else
5854 ((TPad*)this)->Print(psname,"ps");
5855}
5856
5857////////////////////////////////////////////////////////////////////////////////
5858/// Save primitives in this pad on the C++ source file out.
5859
5860void TPad::SavePrimitive(std::ostream &out, Option_t * option /*= ""*/)
5861{
5862 TContext ctxt(this, kFALSE); // not interactive
5863
5865
5866 // check for space in the pad name
5867 auto p = padName.Index(" ");
5868 if (p != kNPOS)
5869 padName.Resize(p);
5870
5871 TString opt = option;
5872 if (!opt.Contains("toplevel")) {
5873 static Int_t pcounter = 0;
5874 padName += TString::Format("__%d", pcounter++);
5875 padName = gInterpreter->MapCppName(padName);
5876 }
5877
5878 const char *pname = padName.Data();
5879 const char *cname = padName.Data();
5880
5881 if (padName.Length() == 0) {
5882 pname = "unnamed";
5883 if (this == gPad->GetCanvas())
5884 cname = "c1";
5885 else
5886 cname = "pad";
5887 }
5888
5889 // Write pad parameters
5890 if (this != gPad->GetCanvas()) {
5891 out << " \n";
5892 out << "// ------------>Primitives in pad: " << GetName() << "\n";
5893 out << " TPad *" << cname << " = new TPad(\"" << GetName() << "\", \""
5894 << TString(GetTitle()).ReplaceSpecialCppChars() << "\", " << fXlowNDC << ", " << fYlowNDC << ", "
5895 << fXlowNDC + fWNDC << ", " << fYlowNDC + fHNDC << ");\n";
5896 out << " " << cname << "->Draw();\n";
5897 out << " " << cname << "->cd();\n";
5898 }
5899 out << " " << cname << "->Range(" << fX1 << "," << fY1 << "," << fX2 << "," << fY2 << ");\n";
5900 TView *view = GetView();
5901 if (view) {
5902 Double_t rmin[3], rmax[3];
5903 view->GetRange(rmin, rmax);
5904 out << " TView::CreateView(1)->SetRange(" << rmin[0] << ", " << rmin[1] << ", " << rmin[2] << ", " << rmax[0]
5905 << ", " << rmax[1] << ", " << rmax[2] << ");\n";
5906 }
5907
5908 SaveFillAttributes(out, cname, -1, -1);
5909
5910 if (GetBorderMode() != 1)
5911 out << " " << cname << "->SetBorderMode(" << GetBorderMode() << ");\n";
5912 if (GetBorderSize() != 4)
5913 out << " " << cname << "->SetBorderSize(" << GetBorderSize() << ");\n";
5914 if (GetLogx())
5915 out << " " << cname << "->SetLogx();\n";
5916 if (GetLogy())
5917 out << " " << cname << "->SetLogy();\n";
5918 if (GetLogz())
5919 out << " " << cname << "->SetLogz();\n";
5920 if (GetGridx())
5921 out << " " << cname << "->SetGridx();\n";
5922 if (GetGridy())
5923 out << " " << cname << "->SetGridy();\n";
5924 if (GetTickx())
5925 out << " " << cname << "->SetTickx(" << GetTickx() << ");\n";
5926 if (GetTicky())
5927 out << " " << cname << "->SetTicky(" << GetTicky() << ");\n";
5928 if (GetTheta() != 30)
5929 out << " " << cname << "->SetTheta(" << GetTheta() << ");\n";
5930 if (GetPhi() != 30)
5931 out << " " << cname << "->SetPhi(" << GetPhi() << ");\n";
5932 if (TMath::Abs(fLeftMargin - 0.1) > 0.01)
5933 out << " " << cname << "->SetLeftMargin(" << GetLeftMargin() << ");\n";
5934 if (TMath::Abs(fRightMargin - 0.1) > 0.01)
5935 out << " " << cname << "->SetRightMargin(" << GetRightMargin() << ");\n";
5936 if (TMath::Abs(fTopMargin - 0.1) > 0.01)
5937 out << " " << cname << "->SetTopMargin(" << GetTopMargin() << ");\n";
5938 if (TMath::Abs(fBottomMargin - 0.1) > 0.01)
5939 out << " " << cname << "->SetBottomMargin(" << GetBottomMargin() << ");\n";
5940
5942 out << " " << cname << "->SetFrameFillColor(" << TColor::SavePrimitiveColor(GetFrameFillColor()) << ");\n";
5943 if (GetFrameFillStyle() != 1001)
5944 out << " " << cname << "->SetFrameFillStyle(" << GetFrameFillStyle() << ");\n";
5945 if (GetFrameLineStyle() != 1)
5946 out << " " << cname << "->SetFrameLineStyle(" << GetFrameLineStyle() << ");\n";
5947 if (GetFrameLineColor() != 1)
5948 out << " " << cname << "->SetFrameLineColor(" << TColor::SavePrimitiveColor(GetFrameLineColor()) << ");\n";
5949 if (GetFrameLineWidth() != 1)
5950 out << " " << cname << "->SetFrameLineWidth(" << GetFrameLineWidth() << ");\n";
5951 if (GetFrameBorderMode() != 0)
5952 out << " " << cname << "->SetFrameBorderMode(" << GetFrameBorderMode() << ");\n";
5953 if (GetFrameBorderSize() != 1)
5954 out << " " << cname << "->SetFrameBorderSize(" << GetFrameBorderSize() << ");\n";
5955
5956 TFrame *frame = fFrame;
5957 if (!frame)
5958 frame = (TFrame *)GetPrimitive("TFrame");
5959 if (frame) {
5960 if (frame->GetFillColor() != GetFillColor())
5961 out << " " << cname << "->SetFrameFillColor(" << TColor::SavePrimitiveColor(frame->GetFillColor()) << ");\n";
5962 if (frame->GetFillStyle() != 1001)
5963 out << " " << cname << "->SetFrameFillStyle(" << frame->GetFillStyle() << ");\n";
5964 if (frame->GetLineStyle() != 1)
5965 out << " " << cname << "->SetFrameLineStyle(" << frame->GetLineStyle() << ");\n";
5966 if (frame->GetLineColor() != 1)
5967 out << " " << cname << "->SetFrameLineColor(" << TColor::SavePrimitiveColor(frame->GetLineColor()) << ");\n";
5968 if (frame->GetLineWidth() != 1)
5969 out << " " << cname << "->SetFrameLineWidth(" << frame->GetLineWidth() << ");\n";
5970 if (frame->GetBorderMode() != 0)
5971 out << " " << cname << "->SetFrameBorderMode(" << frame->GetBorderMode() << ");\n";
5972 if (frame->GetBorderSize() != 1)
5973 out << " " << cname << "->SetFrameBorderSize(" << frame->GetBorderSize() << ");\n";
5974 }
5975
5976 TIter next(GetListOfPrimitives());
5977
5978 while (auto obj = next()) {
5979 obj->SavePrimitive(out, (Option_t *)next.GetOption());
5980 if (obj->InheritsFrom(TPad::Class())) {
5981 if (opt.Contains("toplevel"))
5982 out << " " << pname << "->cd();\n";
5983 else
5984 out << " " << cname << "->cd();\n";
5985 }
5986 }
5987 out << " " << cname << "->Modified();\n";
5988}
5989
5990////////////////////////////////////////////////////////////////////////////////
5991/// Fix pad aspect ratio to current value if fixed is true.
5992
5994{
5995 if (fixed) {
5996 if (!fFixedAspectRatio) {
5997 if (fHNDC != 0.)
5999 else {
6000 Error("SetAspectRatio", "cannot fix aspect ratio, height of pad is 0");
6001 return;
6002 }
6004 }
6005 } else {
6007 fAspectRatio = 0;
6008 }
6009}
6010
6011////////////////////////////////////////////////////////////////////////////////
6012/// Set pad editable yes/no
6013/// If a pad is not editable:
6014/// - one cannot modify the pad and its objects via the mouse.
6015/// - one cannot add new objects to the pad
6016
6018{
6019 fEditable = mode;
6020
6021 TObject *obj;
6022 if (!fPrimitives) fPrimitives = new TList;
6023 TIter next(GetListOfPrimitives());
6024 while ((obj = next())) {
6025 if (obj->InheritsFrom(TPad::Class())) {
6026 TPad *pad = (TPad*)obj;
6027 pad->SetEditable(mode);
6028 }
6029 }
6030}
6031
6032////////////////////////////////////////////////////////////////////////////////
6033/// Override TAttFill::FillStyle for TPad because we want to handle style=0
6034/// as style 4000.
6035
6037{
6038 if (fstyle == 0) fstyle = 4000;
6040}
6041
6042////////////////////////////////////////////////////////////////////////////////
6043/// Set Lin/Log scale for X
6044/// - value = 0 X scale will be linear
6045/// - value = 1 X scale will be logarithmic (base 10)
6046/// - value > 1 reserved for possible support of base e or other
6047
6049{
6050 fLogx = value;
6051 delete fView; fView = nullptr;
6052 Modified();
6054}
6055
6056////////////////////////////////////////////////////////////////////////////////
6057/// Set Lin/Log scale for Y
6058/// - value = 0 Y scale will be linear
6059/// - value = 1 Y scale will be logarithmic (base 10)
6060/// - value > 1 reserved for possible support of base e or other
6061
6063{
6064 fLogy = value;
6065 delete fView; fView = nullptr;
6066 Modified();
6068}
6069
6070////////////////////////////////////////////////////////////////////////////////
6071/// Set Lin/Log scale for Z
6072
6074{
6075 fLogz = value;
6076 delete fView; fView = nullptr;
6077 Modified();
6079}
6080
6081////////////////////////////////////////////////////////////////////////////////
6082/// Set canvas range for pad and resize the pad. If the aspect ratio
6083/// was fixed before the call it will be un-fixed.
6084
6086{
6087 // Reorder points to make sure xlow,ylow is bottom left point and
6088 // xup,yup is top right point.
6089 if (xup < xlow) {
6090 Double_t x = xlow;
6091 xlow = xup;
6092 xup = x;
6093 }
6094 if (yup < ylow) {
6095 Double_t y = ylow;
6096 ylow = yup;
6097 yup = y;
6098 }
6099
6100 // Check if the new pad position is valid.
6101 if ((xlow < 0) || (xlow > 1) || (ylow < 0) || (ylow > 1)) {
6102 Error("TPad", "illegal bottom left position: x=%f, y=%f", xlow, ylow);
6103 return;
6104 }
6105 if ((xup < 0) || (xup > 1) || (yup < 0) || (yup > 1)) {
6106 Error("TPad", "illegal top right position: x=%f, y=%f", xup, yup);
6107 return;
6108 }
6109 if (xup-xlow <= 0) {
6110 Error("TPad", "illegal width: %f", xup-xlow);
6111 return;
6112 }
6113 if (yup-ylow <= 0) {
6114 Error("TPad", "illegal height: %f", yup-ylow);
6115 return;
6116 }
6117
6118 fXlowNDC = xlow;
6119 fYlowNDC = ylow;
6120 fXUpNDC = xup;
6121 fYUpNDC = yup;
6122 fWNDC = xup - xlow;
6123 fHNDC = yup - ylow;
6124
6126
6127 ResizePad();
6128}
6129
6130////////////////////////////////////////////////////////////////////////////////
6131/// Set all pad parameters.
6132
6133void TPad::SetPad(const char *name, const char *title,
6134 Double_t xlow, Double_t ylow, Double_t xup, Double_t yup,
6136{
6137 fName = name;
6138 fTitle = title;
6139 SetFillStyle(1001);
6144 if (color >= 0) SetFillColor(color);
6147 else fBorderSize = bordersize;
6149 else fBorderMode = bordermode;
6150
6151 SetPad(xlow, ylow, xup, yup);
6152}
6153
6154////////////////////////////////////////////////////////////////////////////////
6155/// Set the current TView. Delete previous view if view=0
6156
6158{
6159 if (!view) delete fView;
6160 fView = view;
6161}
6162
6163////////////////////////////////////////////////////////////////////////////////
6164/// Set postscript fill area attributes.
6165///
6166/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6167
6169{
6170 if (auto pp = GetPainter())
6171 if (pp->GetPS())
6172 pp->SetAttFill({color, style});
6173}
6174
6175////////////////////////////////////////////////////////////////////////////////
6176/// Set postscript line attributes.
6177///
6178/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6179
6181{
6182 if (auto pp = GetPainter())
6183 if (pp->GetPS())
6184 pp->SetAttLine({color, style, lwidth});
6185}
6186
6187////////////////////////////////////////////////////////////////////////////////
6188/// Set postscript marker attributes.
6189///
6190/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6191
6193{
6194 if (auto pp = GetPainter())
6195 if (pp->GetPS())
6196 pp->SetAttMarker({color, style, msize});
6197}
6198
6199////////////////////////////////////////////////////////////////////////////////
6200/// Set postscript text attributes.
6201///
6202/// DEPRECATED!!! No longer used by ROOT, kept only for backward compatibility
6203
6205{
6206 if (auto pp = GetPainter())
6207 if (pp->GetPS()) {
6208 if (font % 10 > 2) {
6211 Float_t dy;
6212 if (wh < hh) {
6214 tsize = dy/(GetX2()-GetX1());
6215 } else {
6217 tsize = dy/(GetY2()-GetY1());
6218 }
6219 }
6220 pp->OnPad(this);
6221 pp->SetAttText({align, angle, color, font, tsize});
6222 }
6223}
6224
6225////////////////////////////////////////////////////////////////////////////////
6226/// Draw Arrows to indicated equal distances of Objects with given BBoxes.
6227/// Used by ShowGuidelines
6228
6230{
6231 Int_t lineColor = TColor::GetColor(239, 202, 0);
6232 Int_t x1,x2,y1,y2;
6233 x1 = x2 = y1 = y2 = 0;
6234 if (mode == 'x') {
6235 if (aBBox.fX<bBBox.fX) {
6236 x1 = aBBox.fX+aBBox.fWidth;
6237 x2 = bBBox.fX;
6238 }
6239 else {
6240 x1 = bBBox.fX+bBBox.fWidth;
6241 x2 = aBBox.fX;
6242 }
6243
6244 if ((aBBox.fY > bBBox.fY) && (aBBox.fY + aBBox.fHeight < bBBox.fY + bBBox.fHeight))
6245 y1 = y2 = aBBox.fY + TMath::Nint(0.5*(Double_t)(aBBox.fHeight))+1;
6246 else if ((bBBox.fY > aBBox.fY) && (bBBox.fY + bBBox.fHeight < aBBox.fY + aBBox.fHeight))
6247 y1 = y2 = bBBox.fY + TMath::Nint(0.5*(Double_t)(bBBox.fHeight))+1;
6248 else if (aBBox.fY>bBBox.fY) y1 = y2 = aBBox.fY-TMath::Nint(0.5*(Double_t)(aBBox.fY-(bBBox.fY+bBBox.fHeight)));
6249 else y1 = y2 = bBBox.fY-TMath::Nint(0.5*(Double_t)(bBBox.fY-(aBBox.fY+aBBox.fHeight)));
6250 }
6251 else if (mode == 'y') {
6252 if (aBBox.fY<bBBox.fY) {
6253 y1 = aBBox.fY+aBBox.fHeight;
6254 y2 = bBBox.fY;
6255 }
6256 else {
6257 y1 = bBBox.fY+bBBox.fHeight;
6258 y2 = aBBox.fY;
6259 }
6260 if ((aBBox.fX > bBBox.fX) && (aBBox.fX + aBBox.fWidth < bBBox.fX + bBBox.fWidth))
6261 x1 = x2 = aBBox.fX + TMath::Nint(0.5*(Double_t)(aBBox.fWidth))+1;
6262 else if ((bBBox.fX > aBBox.fX) && (bBBox.fX + bBBox.fWidth < aBBox.fX + aBBox.fWidth))
6263 x1 = x2 = bBBox.fX + TMath::Nint(0.5*(Double_t)(bBBox.fWidth))+1;
6264 else if (aBBox.fX>bBBox.fX) x1 = x2 = aBBox.fX+TMath::Nint(0.5*(Double_t)(bBBox.fX+bBBox.fWidth-aBBox.fX));
6265 else x1 = x2 = bBBox.fX+TMath::Nint(0.5*(Double_t)(aBBox.fX+aBBox.fWidth-bBBox.fX));
6266 }
6267
6268 TArrow *A = new TArrow(gPad->PixeltoX(x1), gPad->PixeltoY(y1-gPad->VtoPixel(0)), gPad->PixeltoX(x2), gPad->PixeltoY(y2-gPad->VtoPixel(0)), 0.01, "<|>");
6269 A->SetBit(kCanDelete);
6271 A->SetLineWidth(1);
6273 A->Draw();
6274
6275 return;
6276}
6277
6278////////////////////////////////////////////////////////////////////////////////
6279/// struct used by ShowGuidelines to store the distance Field between objects
6280/// in the canvas.
6281
6282struct dField {
6286 char fdir;
6287
6288
6290 : fa(nullptr), fb(nullptr), fdist(0), fdir(' ')
6291 {}
6292
6294 : fa(a), fb(b), fdist(dist), fdir(direction)
6295 {}
6296};
6297
6298////////////////////////////////////////////////////////////////////////////////
6299/// Shows lines to indicate if a TAttBBox2D object is aligned to
6300/// the center or to another object, shows distance arrows if two
6301/// objects on screen have the same distance to another object
6302/// Call from primitive in Execute Event, in ButtonMotion after
6303/// the new coordinates have been set, to 'stick'
6304/// once when button is up to delete lines
6305///
6306/// modes: t (Top), b (bottom), l (left), r (right), i (inside)
6307/// in resize modes (t,b,l,r) only size arrows are sticky
6308///
6309/// in mode, the function gets the point on the element that is clicked to
6310/// move (i) or resize (all others). The expected values are:
6311/// \image html gpad_pad5.png
6312
6313void TPad::ShowGuidelines(TObject *object, const Int_t event, const char mode, const bool cling )
6314{
6315 // When the object is moved with arrow or when the ShowGuideLines flag
6316 // is off we do show guide lines.
6317 if ((event == kArrowKeyRelease) || (event == kArrowKeyPress) ||
6318 !gEnv->GetValue("Canvas.ShowGuideLines", 0)) return;
6319
6320 std::vector<dField> curDist;
6321 std::vector<dField> otherDist;
6322 Int_t pMX, pMY;
6323 Double_t MX, MY;
6325 TList *prims;
6326 UInt_t n;
6328 aBBox = bBBox = Rectangle_t();
6329 TLine *L;
6330 TArrow *A;
6331 Int_t dSizeArrow = 12; // distance of arrows indicating same size from BBox in px
6332 Bool_t movedX, movedY; // make sure the current object is moved just once
6333 movedX = movedY = false;
6334 Bool_t resize = false; // indicates resize mode
6335 Bool_t log = gPad->GetLogx() || gPad->GetLogy();
6336 if (mode != 'i') resize = true;
6337
6338 TPad *is_pad = dynamic_cast<TPad *>( object );
6339
6341
6342 if (is_pad && is_pad->GetMother())
6343 is_pad->GetMother()->cd();
6344
6345 static TPad *tmpGuideLinePad = nullptr;
6346
6347 //delete all existing Guidelines and create new invisible pad
6348 if (tmpGuideLinePad) {
6349 ctxt.PadDeleted(tmpGuideLinePad);
6350 auto guidePadClicked = (object == tmpGuideLinePad); // in case of funny button click combination.
6351 tmpGuideLinePad->Delete();
6352 tmpGuideLinePad = nullptr;
6353 if (guidePadClicked) return;
6354 }
6355
6356 // Get Primitives
6357 prims = gPad->GetListOfPrimitives();
6358 n = TMath::Min(15,prims->GetSize());
6359 Int_t lineColor = TColor::GetColor(239, 202, 0);
6360
6361 TAttBBox2D *cur = dynamic_cast<TAttBBox2D *>( object );
6362 if (cur) {
6363 //create invisible TPad above gPad
6364 if (!tmpGuideLinePad){
6365 tmpGuideLinePad = new TPad("tmpGuideLinePad", "tmpGuideLinePad", 0, 0, 1, 1);
6366 Double_t x1, y1, x2, y2;
6367 gPad->GetRange(x1, y1, x2, y2);
6368 tmpGuideLinePad->Range(x1, y1, x2, y2);
6369 tmpGuideLinePad->SetFillStyle(0);
6370 tmpGuideLinePad->SetFillColor(0);
6371 tmpGuideLinePad->Draw();
6372 tmpGuideLinePad->cd();
6373 gPad->GetRange(x1, y1, x2, y2);
6374 }
6375 if (cling && !log) threshold = 7;
6376 else threshold = 1;
6377
6378 Rectangle_t BBox = cur->GetBBox();
6379 TPoint center = cur->GetBBoxCenter();
6380
6381 otherDist.clear();
6382 curDist.clear();
6383
6384 switch (event) {
6385
6386 case kButton1Down:
6387 case kButton1Motion:
6388 MX = gPad->GetX1() + 0.5 * (gPad->GetX2()-gPad->GetX1());
6389 MY = gPad->GetY1() + 0.5 * (gPad->GetY2()-gPad->GetY1());
6390 pMX = gPad->XtoPixel(MX);
6391 pMY = gPad->YtoPixel(MY);
6392 // Middlelines
6393 if (TMath::Abs(pMX-center.GetX())<threshold) {
6394 if (cling && (!resize)) {
6395 cur->SetBBoxCenterX(pMX);
6396 center = cur->GetBBoxCenter();
6397 BBox = cur->GetBBox();
6398 center = cur->GetBBoxCenter();
6399 }
6400 L = new TLine(MX, gPad->GetY1(), MX, gPad->GetY2());
6401 L->SetBit(kCanDelete);
6402 L->SetLineColor(lineColor);
6403 L->Draw();
6404 }
6405 if (TMath::Abs(pMY-center.GetY())<threshold) {
6406 if (cling && (!resize)) {
6407 cur->SetBBoxCenterY(pMY);
6408 center = cur->GetBBoxCenter();
6409 BBox = cur->GetBBox();
6410 center = cur->GetBBoxCenter();
6411 }
6412 L = new TLine(gPad->GetX1(), MY, gPad->GetX2(), MY);
6413 L->SetBit(kCanDelete);
6414 L->SetLineColor(lineColor);
6415 L->Draw();
6416 }
6417 // Alignment to other objects
6418 for (UInt_t i = 0; i<n; i++) {
6419 TAttBBox2D *other = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6420 if (other) {
6421 if (other != cur) {
6422 TPoint centerOther = other->GetBBoxCenter();
6423 if (TMath::Abs(center.GetX()-centerOther.GetX())<threshold) {
6424 if (cling && (!resize)) {
6425 cur->SetBBoxCenterX(centerOther.GetX());
6426 BBox = cur->GetBBox();
6427 center = cur->GetBBoxCenter();
6428 }
6429 L = new TLine(gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(center.GetY()-gPad->VtoPixel(0)),
6430 gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)));
6431 L->SetLineColor(lineColor);
6432 L->Draw();
6433 L->SetBit(kCanDelete);
6434 }
6435 if (TMath::Abs(center.GetY()-centerOther.GetY())<threshold) {
6436 if (cling && (!resize)) {
6437 cur->SetBBoxCenterY(centerOther.GetY());
6438 BBox = cur->GetBBox();
6439 center = cur->GetBBoxCenter();
6440 }
6441 L = new TLine(gPad->PixeltoX(center.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)),
6442 gPad->PixeltoX(centerOther.GetX()), gPad->PixeltoY(centerOther.GetY()-gPad->VtoPixel(0)));
6443 L->SetBit(kCanDelete);
6444 L->SetLineColor(lineColor);
6445 L->Draw();
6446 }
6447 }
6448 }
6449 }
6450 // Get Distances between objects
6451 for (UInt_t i = 0; i<n; i++) {
6452 TAttBBox2D *a = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6453 if (a) {
6454 aBBox = a->GetBBox();
6455 for (UInt_t j = i+1; j<n; j++) {
6456 TAttBBox2D *b = dynamic_cast<TAttBBox2D *>( prims->At(j) );
6457 if (b) {
6458 bBBox = b->GetBBox();
6459
6460 //only when bounding boxes overlap in x or y direction
6461 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
6462 if ((aBBox.fY+aBBox.fHeight<bBBox.fY)||(bBBox.fY+bBBox.fHeight<aBBox.fY)) {//No overlap in Y-direction required
6463 dField abDist = dField();
6464 if (aBBox.fY>bBBox.fY) abDist = dField(a, b, TMath::Abs(aBBox.fY-(bBBox.fY+bBBox.fHeight)), 'y');
6465 else abDist = dField(a, b, TMath::Abs(bBBox.fY-(aBBox.fY+aBBox.fHeight)), 'y');
6466 if ((b != cur)&&(a != cur)) otherDist.push_back(abDist);
6467 else curDist.push_back(abDist);
6468 }
6469 } 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
6470 if ((aBBox.fX+aBBox.fWidth<bBBox.fX)||(bBBox.fX+bBBox.fWidth<aBBox.fX)) {//No overlap in x-direction required
6471 dField abDist = dField();
6472 if (aBBox.fX>bBBox.fX) abDist = dField(a, b, TMath::Abs(aBBox.fX-(bBBox.fX+bBBox.fWidth)), 'x');
6473 else abDist = dField(a, b, TMath::Abs(bBBox.fX-(aBBox.fX+aBBox.fWidth)), 'x');
6474 if ((b != cur)&&(a != cur)) otherDist.push_back(abDist);
6475 else curDist.push_back(abDist);
6476 }
6477 }
6478 }
6479 }
6480 }
6481 }
6482 // Show equal distances
6483 for (UInt_t i = 0; i<curDist.size(); i++) {
6484 for (UInt_t j = 0; j<otherDist.size(); j++) {
6485 if ((curDist[i].fdir == otherDist[j].fdir) && (otherDist[j].fdir=='x') && (TMath::Abs(curDist[i].fdist-otherDist[j].fdist)<threshold)) {
6486 if (cling && (!movedX) && (!resize)) {
6487 if ((cur->GetBBoxCenter().fX < curDist[i].fb->GetBBoxCenter().fX)||(cur->GetBBoxCenter().fX < curDist[i].fa->GetBBoxCenter().fX))
6488 cur->SetBBoxCenterX(cur->GetBBoxCenter().fX - otherDist[j].fdist + curDist[i].fdist);
6489 else cur->SetBBoxCenterX(cur->GetBBoxCenter().fX + otherDist[j].fdist - curDist[i].fdist);
6490 movedX = true;
6491 }
6492 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'x');
6493 DrawDist(otherDist[j].fa->GetBBox(), otherDist[j].fb->GetBBox(), 'x');
6494 }
6495 if ((curDist[i].fdir == otherDist[j].fdir) && (otherDist[j].fdir=='y') && (TMath::Abs(curDist[i].fdist-otherDist[j].fdist)<threshold)) {
6496 if (cling && (!movedY) && (!resize)) {
6497 if ((cur->GetBBoxCenter().fY < curDist[i].fb->GetBBoxCenter().fY)||(cur->GetBBoxCenter().fY < curDist[i].fa->GetBBoxCenter().fY))
6498 cur->SetBBoxCenterY(cur->GetBBoxCenter().fY - otherDist[j].fdist + curDist[i].fdist);
6499 else cur->SetBBoxCenterY(cur->GetBBoxCenter().fY + otherDist[j].fdist - curDist[i].fdist);
6500 movedY = true;
6501 }
6502 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'y');
6503 DrawDist(otherDist[j].fa->GetBBox(), otherDist[j].fb->GetBBox(), 'y');
6504 }
6505 }
6506 for (UInt_t j = i; j<curDist.size(); j++) {
6507 if (i!=j) {
6508 if ((curDist[i].fdir == curDist[j].fdir) && (curDist[j].fdir=='x') && (TMath::Abs(curDist[i].fdist-curDist[j].fdist)<threshold)) {
6509 if (cling && (!movedX) && (!resize)) {
6510 if ((cur->GetBBoxCenter().fX < curDist[i].fb->GetBBoxCenter().fX)||(cur->GetBBoxCenter().fX < curDist[i].fa->GetBBoxCenter().fX))
6511 cur->SetBBoxCenterX(cur->GetBBoxCenter().fX - floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6512 else cur->SetBBoxCenterX(cur->GetBBoxCenter().fX + floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6513 }
6514 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'x');
6515 DrawDist(curDist[j].fa->GetBBox(), curDist[j].fb->GetBBox(), 'x');
6516 }
6517
6518 if ((curDist[i].fdir == curDist[j].fdir) && (curDist[j].fdir=='y') && (TMath::Abs(curDist[i].fdist-curDist[j].fdist)<threshold)) {
6519 if (cling && (!movedY) && (!resize)) {
6520 if ((cur->GetBBoxCenter().fY < curDist[i].fb->GetBBoxCenter().fY)||(cur->GetBBoxCenter().fY < curDist[i].fa->GetBBoxCenter().fY))
6521 cur->SetBBoxCenterY(cur->GetBBoxCenter().fY - floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6522 else cur->SetBBoxCenterY(cur->GetBBoxCenter().fY + floor(0.5*(curDist[j].fdist - curDist[i].fdist)));
6523 }
6524 DrawDist(curDist[i].fa->GetBBox(), curDist[i].fb->GetBBox(), 'y');
6525 DrawDist(curDist[j].fa->GetBBox(), curDist[j].fb->GetBBox(), 'y');
6526 }
6527 }
6528 }
6529 }
6530 if (resize) {
6531 // Show equal Sizes
6532 for (UInt_t i = 0; i<n; i++) {
6533 TAttBBox2D *a = dynamic_cast<TAttBBox2D *>( prims->At(i) );
6534 if (a && (cur != a)) {
6535 aBBox = a->GetBBox();
6536
6537 if ((TMath::Abs(aBBox.fWidth - BBox.fWidth)<threshold) && (mode != 't') && (mode != 'b')) {
6538 if (cling) {
6539 if (mode == 'l') cur->SetBBoxX1(BBox.fX + BBox.fWidth - aBBox.fWidth);
6540 if (mode == 'r') cur->SetBBoxX2(BBox.fX + aBBox.fWidth);
6541 if ((mode == '1')||(mode == '4')) cur->SetBBoxX1(BBox.fX + BBox.fWidth - aBBox.fWidth);
6542 if ((mode == '2')||(mode == '3')) cur->SetBBoxX2(BBox.fX + aBBox.fWidth);
6543 BBox = cur->GetBBox();
6544 }
6545
6546 A = new TArrow(gPad->PixeltoX(aBBox.fX), gPad->PixeltoY(aBBox.fY-dSizeArrow-gPad->VtoPixel(0)),
6547 gPad->PixeltoX(aBBox.fX+aBBox.fWidth), gPad->PixeltoY(aBBox.fY-dSizeArrow-gPad->VtoPixel(0)), 0.01, "<|>");
6548 A->SetBit(kCanDelete);
6551 A->Draw();
6552
6553 A = new TArrow(gPad->PixeltoX(BBox.fX), gPad->PixeltoY(BBox.fY-dSizeArrow-gPad->VtoPixel(0)),
6554 gPad->PixeltoX(BBox.fX+BBox.fWidth), gPad->PixeltoY(BBox.fY-dSizeArrow-gPad->VtoPixel(0)), 0.01, "<|>");
6555 A->SetBit(kCanDelete);
6558 A->Draw();
6559 }
6560 if ((TMath::Abs(aBBox.fHeight - BBox.fHeight)<threshold) && (mode != 'r') && (mode != 'l')) {
6561 if (cling) {
6562 if (mode == 't') cur->SetBBoxY1(BBox.fY + BBox.fHeight - aBBox.fHeight);
6563 if (mode == 'b') cur->SetBBoxY2(BBox.fY + aBBox.fHeight);
6564 if ((mode == '1')||(mode == '2')) cur->SetBBoxY1(BBox.fY + BBox.fHeight - aBBox.fHeight);
6565 if ((mode == '3')||(mode == '4')) cur->SetBBoxY2(BBox.fY + aBBox.fHeight);
6566 BBox = cur->GetBBox();
6567 }
6568 A = new TArrow(gPad->PixeltoX(aBBox.fX-dSizeArrow), gPad->PixeltoY(aBBox.fY-gPad->VtoPixel(0)),
6569 gPad->PixeltoX(aBBox.fX-dSizeArrow), gPad->PixeltoY(aBBox.fY+aBBox.fHeight-gPad->VtoPixel(0)), 0.01, "<|>");
6570 A->SetBit(kCanDelete);
6573 A->Draw();
6574
6575 A = new TArrow(gPad->PixeltoX(BBox.fX-dSizeArrow), gPad->PixeltoY(BBox.fY-gPad->VtoPixel(0)),
6576 gPad->PixeltoX(BBox.fX-dSizeArrow), gPad->PixeltoY(BBox.fY+BBox.fHeight-gPad->VtoPixel(0)), 0.01, "<|>");
6577 A->SetBit(kCanDelete);
6580 A->Draw();
6581 }
6582 }
6583 }
6584 }
6585
6586 break;
6587
6588 case kButton1Up:
6589 if (tmpGuideLinePad) {
6590 // All the arrows and lines in that pad are also deleted because
6591 // they all have the bit kCanDelete on.
6592 tmpGuideLinePad->Delete();
6593 tmpGuideLinePad = nullptr;
6594 }
6595 break;
6596 }
6597 }
6598
6599 gPad->Modified(kTRUE);
6600}
6601
6602////////////////////////////////////////////////////////////////////////////////
6603/// Return kTRUE if the crosshair has been activated (via SetCrosshair).
6604
6606{
6607 return (Bool_t)GetCrosshair();
6608}
6609
6610////////////////////////////////////////////////////////////////////////////////
6611/// Return the crosshair type (from the mother canvas)
6612/// crosshair type = 0 means no crosshair.
6613
6615{
6616 if (this == (TPad*)fCanvas)
6617 return fCrosshair;
6618 return fCanvas ? fCanvas->GetCrosshair() : 0;
6619}
6620
6621////////////////////////////////////////////////////////////////////////////////
6622/// Set crosshair active/inactive.
6623/// - If crhair != 0, a crosshair will be drawn in the pad and its sub-pads.
6624/// - If the canvas crhair = 1 , the crosshair spans the full canvas.
6625/// - If the canvas crhair > 1 , the crosshair spans only the pad.
6626
6628{
6629 if (!fCanvas) return;
6631 fCrosshairPos = 0;
6632
6633 if (this != (TPad*)fCanvas) fCanvas->SetCrosshair(crhair);
6634}
6635
6636////////////////////////////////////////////////////////////////////////////////
6637/// static function to set the maximum Pick Distance fgMaxPickDistance
6638/// This parameter is used in TPad::Pick to select an object if
6639/// its DistancetoPrimitive returns a value < fgMaxPickDistance
6640/// The default value is 5 pixels. Setting a smaller value will make
6641/// picking more precise but also more difficult
6642
6647
6648////////////////////////////////////////////////////////////////////////////////
6649/// Set tool tip text associated with this pad. The delay is in
6650/// milliseconds (minimum 250). To remove tool tip call method with
6651/// text = 0.
6652
6654{
6655 if (fTip) {
6657 fTip = nullptr;
6658 }
6659
6660 if (text && strlen(text))
6661 fTip = CreateToolTip((TBox*)nullptr, text, delayms);
6662}
6663
6664////////////////////////////////////////////////////////////////////////////////
6665/// Set pad vertical (default) or horizontal
6666
6668{
6669 if (vert) ResetBit(kHori);
6670 else SetBit(kHori);
6671}
6672
6673////////////////////////////////////////////////////////////////////////////////
6674/// Stream a class object.
6675
6677{
6678 UInt_t R__s, R__c;
6681 TObject *obj;
6682 if (b.IsReading()) {
6683 Version_t v = b.ReadVersion(&R__s, &R__c);
6684 if (v > 5) {
6685 if (!gPad)
6686 gPad = new TCanvas(GetName());
6687 fMother = (TPad*)gPad;
6689 TContext ctxt(this, kFALSE);
6690 fPixmapID = -1; // -1 means pixmap will be created by ResizePad()
6691 gReadLevel++;
6692 gROOT->SetReadingObject(kTRUE);
6693
6694 b.ReadClassBuffer(TPad::Class(), this, v, R__s, R__c);
6695
6696 //Set the kCanDelete bit in all objects in the pad such that when the pad
6697 //is deleted all objects in the pad are deleted too.
6698 //Also set must cleanup bit which normally set for all primitives add to pad,
6699 // but may be reset in IO like TH1::Streamer does
6700 TIter next(fPrimitives);
6701 while ((obj = next())) {
6702 obj->SetBit(kCanDelete);
6703 obj->SetBit(kMustCleanup);
6704 }
6705
6706 fModified = kTRUE;
6707 fPadPointer = nullptr;
6708 gReadLevel--;
6709 if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
6710 gROOT->SetReadingObject(kFALSE);
6711 return;
6712 }
6713
6714 //====process old versions before automatic schema evolution
6715 if (v < 5) { //old TPad in single precision
6716 if (v < 3) { //old TPad derived from TWbox
6717 b.ReadVersion(); // TVirtualPad::Streamer(b)
6718 b.ReadVersion(); // TWbox::Streamer(b)
6719 b.ReadVersion(); // TBox::Streamer(b)
6723 b >> single; fX1 = single;
6724 b >> single; fY1 = single;
6725 b >> single; fX2 = single;
6726 b >> single; fY2 = single;
6727 b >> fBorderSize;
6728 b >> fBorderMode;
6730 } else { //new TPad
6733 b >> single; fX1 = single;
6734 b >> single; fY1 = single;
6735 b >> single; fX2 = single;
6736 b >> single; fY2 = single;
6737 b >> fBorderSize;
6738 b >> fBorderMode;
6739 }
6740 b >> fLogx;
6741 b >> fLogy;
6742 b >> fLogz;
6744 b >> single; fXtoPixelk = single;
6745 b >> single; fXtoPixel = single;
6747 b >> single; fYtoPixelk = single;
6748 b >> single; fYtoPixel = single;
6750 b >> single; fUtoPixelk = single;
6751 b >> single; fUtoPixel = single;
6753 b >> single; fVtoPixelk = single;
6754 b >> single; fVtoPixel = single;
6756 b >> single; fPixeltoXk = single;
6757 b >> single; fPixeltoX = single;
6759 b >> single; fPixeltoYk = single;
6760 b >> single; fPixeltoY = single;
6761 b >> single; fXlowNDC = single;
6762 b >> single; fYlowNDC = single;
6763 b >> single; fWNDC = single;
6764 b >> single; fHNDC = single;
6765 b >> single; fAbsXlowNDC = single;
6766 b >> single; fAbsYlowNDC = single;
6767 b >> single; fAbsWNDC = single;
6768 b >> single; fAbsHNDC = single;
6769 b >> single; fUxmin = single;
6770 b >> single; fUymin = single;
6771 b >> single; fUxmax = single;
6772 b >> single; fUymax = single;
6773 } else {
6776 b >> fX1;
6777 b >> fY1;
6778 b >> fX2;
6779 b >> fY2;
6780 b >> fBorderSize;
6781 b >> fBorderMode;
6782 b >> fLogx;
6783 b >> fLogy;
6784 b >> fLogz;
6785 b >> fXtoAbsPixelk;
6786 b >> fXtoPixelk;
6787 b >> fXtoPixel;
6788 b >> fYtoAbsPixelk;
6789 b >> fYtoPixelk;
6790 b >> fYtoPixel;
6791 b >> fUtoAbsPixelk;
6792 b >> fUtoPixelk;
6793 b >> fUtoPixel;
6794 b >> fVtoAbsPixelk;
6795 b >> fVtoPixelk;
6796 b >> fVtoPixel;
6797 b >> fAbsPixeltoXk;
6798 b >> fPixeltoXk;
6799 b >> fPixeltoX;
6800 b >> fAbsPixeltoYk;
6801 b >> fPixeltoYk;
6802 b >> fPixeltoY;
6803 b >> fXlowNDC;
6804 b >> fYlowNDC;
6805 b >> fWNDC;
6806 b >> fHNDC;
6807 b >> fAbsXlowNDC;
6808 b >> fAbsYlowNDC;
6809 b >> fAbsWNDC;
6810 b >> fAbsHNDC;
6811 b >> fUxmin;
6812 b >> fUymin;
6813 b >> fUxmax;
6814 b >> fUymax;
6815 }
6816
6817 if (!gPad)
6818 gPad = new TCanvas(GetName());
6819 if (gReadLevel == 0)
6821 else
6822 fMother = (TPad *)gPad;
6823 if (!fMother)
6824 fMother = (TPad *)gPad;
6825 if (fMother)
6827 gPad = fMother;
6828 fPixmapID = -1; // -1 means pixmap will be created by ResizePad()
6829 //-------------------------
6830 // read objects and their drawing options
6831 // b >> fPrimitives;
6832 gReadLevel++;
6833 gROOT->SetReadingObject(kTRUE);
6834 fPrimitives = new TList;
6835 b >> nobjects;
6836 if (nobjects > 0) {
6837 TContext ctxt(this, kFALSE);
6838 char drawoption[64];
6839 for (Int_t i = 0; i < nobjects; i++) {
6840 b >> obj;
6841 b >> nch;
6842 b.ReadFastArray(drawoption,nch);
6844 gPad = this; // gPad may be modified in b >> obj if obj is a pad
6845 }
6846 }
6847 gReadLevel--;
6848 gROOT->SetReadingObject(kFALSE);
6849 //////////////////////////////////////////////////////////////////////////
6850
6851 if (v > 3) {
6852 b >> fExecs;
6853 }
6854 fName.Streamer(b);
6855 fTitle.Streamer(b);
6856 b >> fPadPaint;
6857 fModified = kTRUE;
6858 b >> fGridx;
6859 b >> fGridy;
6860 b >> fFrame;
6861 b >> fView;
6862 if (v < 5) {
6863 b >> single; fTheta = single;
6864 b >> single; fPhi = single;
6865 } else {
6866 b >> fTheta;
6867 b >> fPhi;
6868 }
6869 fPadPointer = nullptr;
6870 b >> fNumber;
6871 b >> fAbsCoord;
6872 if (v > 1) {
6873 b >> fTickx;
6874 b >> fTicky;
6875 } else {
6876 fTickx = fTicky = 0;
6877 }
6878 if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
6879 b.CheckByteCount(R__s, R__c, TPad::IsA());
6880 //====end of old versions
6881
6882 } else {
6883 b.WriteClassBuffer(TPad::Class(),this);
6884 }
6885}
6886
6887////////////////////////////////////////////////////////////////////////////////
6888/// Force a copy of current style for all objects in pad.
6889
6891{
6892 if (gStyle->IsReading()) {
6904 fLogx = gStyle->GetOptLogx();
6905 fLogy = gStyle->GetOptLogy();
6906 fLogz = gStyle->GetOptLogz();
6907 } else {
6922 }
6923
6924 if (!fPrimitives) fPrimitives = new TList;
6925 TIter next(GetListOfPrimitives());
6926 TObject *obj;
6927
6928 while ((obj = next())) {
6929 obj->UseCurrentStyle();
6930 }
6931
6932 TPaveText *title = (TPaveText*)FindObject("title");
6933 if (title) {
6934 if (gStyle->IsReading()) {
6936 title->SetTextFont(gStyle->GetTitleFont(""));
6939 if (!gStyle->GetOptTitle()) delete title;
6940 } else {
6942 gStyle->SetTitleFont(title->GetTextFont());
6945 }
6946 }
6948
6949 if (gStyle->IsReading()) Modified();
6950}
6951
6952////////////////////////////////////////////////////////////////////////////////
6953/// Loop and sleep until a primitive with name=pname is found in the pad.
6954///
6955/// If emode is given, the editor is automatically set to emode, ie
6956/// it is not required to have the editor control bar.
6957///
6958/// The possible values for emode are:
6959/// - emode = "" (default). User will select the mode via the editor bar
6960/// - emode = "Arc", "Line", "Arrow", "Button", "Diamond", "Ellipse",
6961/// - emode = "Pad","pave", "PaveLabel","PaveText", "PavesText",
6962/// - emode = "PolyLine", "CurlyLine", "CurlyArc", "Text", "Marker", "CutG"
6963///
6964/// If emode is specified and it is not valid, "PolyLine" is assumed. If emode
6965/// is not specified or ="", an attempt is to use pname[1...]
6966///
6967/// for example if pname="TArc", emode="Arc" will be assumed.
6968/// When this function is called within a macro, the macro execution
6969/// is suspended until a primitive corresponding to the arguments
6970/// is found in the pad.
6971///
6972/// If CRTL/C is typed in the pad, the function returns 0.
6973///
6974/// While this function is executing, one can use the mouse, interact
6975/// with the graphics pads, use the Inspector, Browser, TreeViewer, etc.
6976///
6977/// Examples:
6978/// ~~~ {.cpp}
6979/// c1.WaitPrimitive(); // Return the first created primitive
6980/// // whatever it is.
6981/// // If a double-click with the mouse is executed
6982/// // in the pad or any key pressed, the function
6983/// // returns 0.
6984/// c1.WaitPrimitive("ggg"); // Set the editor in mode "PolyLine/Graph"
6985/// // Create a polyline, then using the context
6986/// // menu item "SetName", change the name
6987/// // of the created TGraph to "ggg"
6988/// c1.WaitPrimitive("TArc");// Set the editor in mode "Arc". Returns
6989/// // as soon as a TArc object is created.
6990/// c1.WaitPrimitive("lat","Text"); // Set the editor in Text/Latex mode.
6991/// // Create a text object, then Set its name to "lat"
6992/// ~~~
6993/// The following macro waits for 10 primitives of any type to be created.
6994///
6995/// ~~~ {.cpp}
6996///{
6997/// TCanvas c1("c1");
6998/// TObject *obj;
6999/// for (Int_t i=0;i<10;i++) {
7000/// obj = gPad->WaitPrimitive();
7001/// if (!obj) break;
7002/// printf("Loop i=%d, found objIsA=%s, name=%s\n",
7003/// i,obj->ClassName(),obj->GetName());
7004/// }
7005///}
7006/// ~~~
7007///
7008/// If ROOT runs in batch mode a call to this method does nothing.
7009
7010TObject *TPad::WaitPrimitive(const char *pname, const char *emode)
7011{
7012 if (!gPad || IsWeb())
7013 return nullptr;
7014
7015 if (emode && strlen(emode)) gROOT->SetEditorMode(emode);
7016 if (gROOT->GetEditorMode() == 0 && pname && strlen(pname) > 2) gROOT->SetEditorMode(&pname[1]);
7017
7018 if (!fPrimitives) fPrimitives = new TList;
7020 TObject *oldlast = gPad->GetListOfPrimitives() ? gPad->GetListOfPrimitives()->Last() : nullptr;
7021 TObject *obj = nullptr;
7023 Bool_t hasname = pname && (strlen(pname) > 0);
7024 if ((!pname || !pname[0]) && (!emode || !emode[0])) testlast = kTRUE;
7025 if (testlast) gROOT->SetEditorMode();
7026 while (!gSystem->ProcessEvents() && gROOT->GetSelectedPad() && gPad) {
7027 if (gROOT->GetEditorMode() == 0) {
7028 if (hasname) {
7029 obj = FindObject(pname);
7030 if (obj) return obj;
7031 }
7032 if (testlast) {
7033 if (!gPad->GetListOfPrimitives()) return nullptr;
7034 obj = gPad->GetListOfPrimitives()->Last();
7035 if (obj != oldlast) return obj;
7036 Int_t event = GetEvent();
7037 if (event == kButton1Double || event == kKeyPress) {
7038 //the following statement is required against other loop executions
7039 //before returning
7040 fCanvas->HandleInput((EEventType)-1,0,0);
7041 return nullptr;
7042 }
7043 }
7044 }
7045 gSystem->Sleep(10);
7046 }
7047
7048 return nullptr;
7049}
7050
7051////////////////////////////////////////////////////////////////////////////////
7052/// Create a tool tip and return its pointer.
7053
7055{
7056 if (gPad->IsBatch()) return nullptr;
7057 return (TObject*)gROOT->ProcessLineFast(TString::Format("new TGToolTip((TBox*)0x%zx,\"%s\",%d)",
7058 (size_t)box,text,(Int_t)delayms).Data());
7059}
7060
7061////////////////////////////////////////////////////////////////////////////////
7062/// Delete tool tip object.
7063
7065{
7066 // delete tip;
7067 if (!tip) return;
7068 gROOT->ProcessLineFast(TString::Format("delete (TGToolTip*)0x%zx", (size_t)tip).Data());
7069}
7070
7071////////////////////////////////////////////////////////////////////////////////
7072/// Reset tool tip, i.e. within time specified in CreateToolTip the
7073/// tool tip will pop up.
7074
7076{
7077 if (!tip) return;
7078 // tip->Reset(this);
7079 gROOT->ProcessLineFast(TString::Format("((TGToolTip*)0x%zx)->Reset((TPad*)0x%zx)",
7080 (size_t)tip,(size_t)this).Data());
7081}
7082
7083////////////////////////////////////////////////////////////////////////////////
7084/// Hide tool tip.
7085
7087{
7088 if (!tip) return;
7089 // tip->Hide();
7090 gROOT->ProcessLineFast(TString::Format("((TGToolTip*)0x%zx)->Hide()", (size_t)tip).Data());
7091}
7092
7093////////////////////////////////////////////////////////////////////////////////
7094/// Deprecated: use TPad::GetViewer3D() instead
7095
7097{
7098 ::Info("TPad::x3d()", "This function is deprecated. Use %s->GetViewer3D(\"x3d\") instead",this->GetName());
7099
7100 // Default on GetViewer3D is pad - for x3d it was x3d...
7101 if (!type || !type[0]) {
7102 type = "x3d";
7103 }
7105}
7106
7107////////////////////////////////////////////////////////////////////////////////
7108/// Create/obtain handle to 3D viewer. Valid types are:
7109/// - 'pad' - pad drawing via TViewer3DPad
7110/// any others registered with plugin manager supporting TVirtualViewer3D
7111/// If an invalid/null type is requested then the current viewer is returned
7112/// (if any), otherwise a default 'pad' type is returned
7113
7115{
7117
7118 if ((!type || !*type || (strstr(type, "gl") && !strstr(type, "ogl"))) && (!fCanvas || !fCanvas->UseGL()))
7119 type = "pad";
7120
7121 if (type && *type) {
7122 if (gPluginMgr->FindHandler("TVirtualViewer3D", type))
7123 validType = kTRUE;
7124 }
7125
7126 // Invalid/null type requested?
7127 if (!validType) {
7128 // Return current viewer if there is one
7129 if (fViewer3D)
7130 return fViewer3D;
7131 // otherwise default to the pad
7132 else
7133 type = "pad";
7134 }
7135
7136 // Ensure we can create the new viewer before removing any existing one
7137 TVirtualViewer3D *newViewer = nullptr;
7138
7140
7141 // External viewers need to be created via plugin manager via interface...
7142 if (!strstr(type,"pad")) {
7144
7145 if (!newViewer) {
7146 Warning("GetViewer3D", "Cannot create 3D viewer of type: %s", type);
7147 // Return the existing viewer
7148 return fViewer3D;
7149 }
7150
7151 if (strstr(type, "gl") && !strstr(type, "ogl")) {
7154 Modified();
7155 } else {
7157 }
7158
7159 } else {
7160 newViewer = new TViewer3DPad(*this);
7161 }
7162
7163 // If we had a previous viewer destroy it now
7164 // In this case we do take responsibility for destroying viewer
7165 // c.f. ReleaseViewer3D
7166 delete fViewer3D;
7167
7168 // Set and return new viewer
7170
7171 // Ensure any new external viewer is painted
7172 // For internal TViewer3DPad type we assume this is being
7173 // create on demand due to a paint - so this is not required
7174 if (createdExternal) {
7175 Modified();
7176 Update();
7177 }
7178
7179 return fViewer3D;
7180}
7181
7182////////////////////////////////////////////////////////////////////////////////
7183/// Release current (external) viewer
7184
7186{
7187 fViewer3D = nullptr;
7188
7189 // We would like to ensure the pad is repainted
7190 // when external viewer is closed down. However
7191 // a modify/paint call here will repaint the pad
7192 // before the external viewer window actually closes.
7193 // So the pad would have to be redraw twice over.
7194 // Currently we just have to live with the pad staying blank
7195 // any click in pad will refresh.
7196}
7197
7198////////////////////////////////////////////////////////////////////////////////
7199/// Get GL device.
7200
7202{
7203 return fGLDevice;
7204}
7205
7206////////////////////////////////////////////////////////////////////////////////
7207/// Emit RecordPave() signal.
7208
7210{
7211 Emit("RecordPave(const TObject*)", (Longptr_t)obj);
7212}
7213
7214////////////////////////////////////////////////////////////////////////////////
7215/// Emit RecordLatex() signal.
7216
7218{
7219 Emit("RecordLatex(const TObject*)", (Longptr_t)obj);
7220}
7221
7222////////////////////////////////////////////////////////////////////////////////
7223/// Get pad painter from TCanvas.
7224
7226{
7227 if (!fCanvas) return nullptr;
7228 return fCanvas->GetCanvasPainter();
7229}
7230
7231////////////////////////////////////////////////////////////////////////////////
7232/// Return the bounding Box of the Pad
7233
7235{
7236 Rectangle_t BBox{0, 0, 0, 0};
7237 if (gPad) {
7238 BBox.fX = gPad->XtoPixel(fXlowNDC * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1());
7239 BBox.fY = gPad->YtoPixel((fYlowNDC + fHNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1());
7240 BBox.fWidth = gPad->XtoPixel((fXlowNDC + fWNDC) * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1()) -
7241 gPad->XtoPixel(fXlowNDC * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1());
7242 BBox.fHeight = gPad->YtoPixel((fYlowNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1()) -
7243 gPad->YtoPixel((fYlowNDC + fHNDC) * (gPad->GetY2() - gPad->GetY1()) + gPad->GetY1());
7244 }
7245 return BBox;
7246}
7247
7248////////////////////////////////////////////////////////////////////////////////
7249/// Return the center of the Pad as TPoint in pixels
7250
7252{
7253 TPoint p(0, 0);
7254 if (gPad) {
7255 Double_t x = ((fXlowNDC + 0.5 * fWNDC) * (gPad->GetX2() - gPad->GetX1())) + gPad->GetX1();
7256 Double_t y = ((fYlowNDC + 0.5 * fHNDC) * (gPad->GetY2() - gPad->GetY1())) + gPad->GetY1();
7257 p.SetX(gPad->XtoPixel(x));
7258 p.SetY(gPad->YtoPixel(y));
7259 }
7260 return p;
7261}
7262
7263////////////////////////////////////////////////////////////////////////////////
7264/// Set center of the Pad
7265
7267{
7268 if (!gPad)
7269 return;
7270 fXlowNDC = (gPad->PixeltoX(p.GetX()) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1()) - 0.5 * fWNDC;
7271 fYlowNDC =
7272 (gPad->PixeltoY(p.GetY() - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - 0.5 * fHNDC;
7273 ResizePad();
7274}
7275
7276////////////////////////////////////////////////////////////////////////////////
7277/// Set X coordinate of the center of the Pad
7278
7280{
7281 if (!gPad)
7282 return;
7283 fXlowNDC = (gPad->PixeltoX(x) - gPad->GetX1())/(gPad->GetX2()-gPad->GetX1())-0.5*fWNDC;
7284 ResizePad();
7285}
7286
7287////////////////////////////////////////////////////////////////////////////////
7288/// Set Y coordinate of the center of the Pad
7289
7291{
7292 if (!gPad)
7293 return;
7294 fYlowNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - 0.5 * fHNDC;
7295 ResizePad();
7296}
7297
7298////////////////////////////////////////////////////////////////////////////////
7299/// Set lefthandside of BoundingBox to a value
7300/// (resize in x direction on left)
7301
7303{
7304 if (!gPad)
7305 return;
7306 fXlowNDC = (gPad->PixeltoX(x) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1());
7308 ResizePad();
7309}
7310
7311////////////////////////////////////////////////////////////////////////////////
7312/// Set right hand side of BoundingBox to a value
7313/// (resize in x direction on right)
7314
7316{
7317 if (!gPad)
7318 return;
7319 fWNDC = (gPad->PixeltoX(x) - gPad->GetX1()) / (gPad->GetX2() - gPad->GetX1()) - fXlowNDC;
7320 ResizePad();
7321}
7322
7323////////////////////////////////////////////////////////////////////////////////
7324/// Set top of BoundingBox to a value (resize in y direction on top)
7325
7327{
7328 if (!gPad)
7329 return;
7330 fHNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1()) - fYlowNDC;
7331 ResizePad();
7332}
7333
7334////////////////////////////////////////////////////////////////////////////////
7335/// Set bottom of BoundingBox to a value
7336/// (resize in y direction on bottom)
7337
7339{
7340 if (!gPad)
7341 return;
7342 fYlowNDC = (gPad->PixeltoY(y - gPad->VtoPixel(0)) - gPad->GetY1()) / (gPad->GetY2() - gPad->GetY1());
7344 ResizePad();
7345}
7346
7347////////////////////////////////////////////////////////////////////////////////
7348/// Mark pad modified
7349/// Will be repainted when TCanvas::Update() will be called next time
7350
7352{
7353 if (!fModified && flag) Emit("Modified()");
7354 fModified = flag;
7355}
7356
7357////////////////////////////////////////////////////////////////////////////////
7358/// Convert absolute pixel into X/Y coordinates
7359
7365
7366
7367////////////////////////////////////////////////////////////////////////////////
7368/// Convert pixel to X coordinate
7369
7371{
7372 if (fAbsCoord) return fAbsPixeltoXk + px*fPixeltoX;
7373 else return fPixeltoXk + px*fPixeltoX;
7374}
7375
7376////////////////////////////////////////////////////////////////////////////////
7377/// Convert pixel to Y coordinate
7378
7380{
7381 if (fAbsCoord) return fAbsPixeltoYk + py*fPixeltoY;
7382 else return fPixeltoYk + py*fPixeltoY;
7383}
7384
7385////////////////////////////////////////////////////////////////////////////////
7386/// Convert pixel to X/Y coordinates
7387
7393
7394////////////////////////////////////////////////////////////////////////////////
7395/// Convert X/Y into absolute pixel coordinates - integer
7396
7402
7403////////////////////////////////////////////////////////////////////////////////
7404/// Check value for valid range for pixel values
7405
7407{
7408 return v < -kMaxPixel ? -kMaxPixel : (v > kMaxPixel ? kMaxPixel : v);
7409}
7410
7411////////////////////////////////////////////////////////////////////////////////
7412/// Convert X/Y into absolute pixel coordinates - doble
7413/// Introduced to avoid pixel rounding problems
7414
7420
7421////////////////////////////////////////////////////////////////////////////////
7422/// Convert X/Y into pixel coordinates - integer
7423
7425{
7426 xpixel = XtoPixel(x);
7427 ypixel = YtoPixel(y);
7428}
7429
7430////////////////////////////////////////////////////////////////////////////////
7431/// Convert X/Y into pixel coordinates - double
7432
7438
7439////////////////////////////////////////////////////////////////////////////////
7440/// Convert X NDC to pixel
7441
7446
7447////////////////////////////////////////////////////////////////////////////////
7448/// Convert Y NDC to pixel
7449
7454
7455////////////////////////////////////////////////////////////////////////////////
7456/// Convert X NDC to absolute pixel
7457
7462
7463////////////////////////////////////////////////////////////////////////////////
7464/// Convert Y NDC to absolute pixel
7465
7470
7471////////////////////////////////////////////////////////////////////////////////
7472/// Convert X coordinate to absolute pixel
7473
7478
7479////////////////////////////////////////////////////////////////////////////////
7480/// Convert X coordinate to pixel
7481
7486
7487////////////////////////////////////////////////////////////////////////////////
7488/// Convert Y coordinate to absolute pixel
7489
7494
7495////////////////////////////////////////////////////////////////////////////////
7496/// Convert a vertical distance [y1,y2] to pixel
7497
7499{
7500 double h1 = fYtoAbsPixelk + y1 * fYtoPixel;
7501 double h2 = fYtoAbsPixelk + y2 * fYtoPixel;
7502 return TMath::Nint(pixel_boundary(std::abs(h1 - h2)));
7503}
7504
7505////////////////////////////////////////////////////////////////////////////////
7506/// Convert a horizontal distance [x1,x2] to pixel
7507
7509{
7510 double w1 = fXtoAbsPixelk + x1 * fXtoPixel;
7511 double w2 = fXtoAbsPixelk + x2 * fXtoPixel;
7512 return TMath::Nint(pixel_boundary(std::abs(w1 - w2)));
7513}
7514
7515
7516////////////////////////////////////////////////////////////////////////////////
7517/// Convert Y coordinate to pixel
7518
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
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:89
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
short Width_t
Line width (short)
Definition RtypesCore.h:98
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
@ kRed
Definition Rtypes.h:67
@ kBlack
Definition Rtypes.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gDirectory
Definition TDirectory.h:385
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
#define gFile
Definition TFile.h:439
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t cursor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t SetFillStyle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char cname
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void SetCursor
Option_t Option_t SetFillColor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Option_t Option_t style
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t button
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
char name[80]
Definition TGX11.cxx: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:7406
static Int_t gReadLevel
Definition TPad.cxx:69
static Bool_t ContainsTImage(TList *li)
Auxiliary function.
Definition TPad.cxx:4807
#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:426
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:87
#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:1968
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:2613
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:2623
Bool_t IsGrayscale()
Check whether this canvas is to be drawn in grayscale mode.
Definition TCanvas.cxx:2564
void SaveSource(const char *filename="", Option_t *option="")
Save primitives in this canvas as a C++ macro file.
Definition TCanvas.cxx:1807
virtual void HandleInput(EEventType button, Int_t x, Int_t y)
Handle Input Events.
Definition TCanvas.cxx:1228
void UpdateAsync() override
Asynchronous pad update.
Definition TCanvas.cxx:2542
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:1945
TVirtualPad * GetSelectedPad() const override
Definition TCanvas.h:150
void SetCursor(ECursor cursor) override
Set cursor.
Definition TCanvas.cxx:1959
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:1127
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:2486
virtual void Cleared(TVirtualPad *pad)
Emit pad Cleared signal.
Definition TCanvas.cxx:767
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:2117
Int_t GetEvent() const override
Definition TCanvas.h:139
Bool_t IsWeb() const override
Is web canvas.
Definition TCanvas.cxx:1489
void SetBatch(Bool_t batch=kTRUE) override
Toggle batch mode.
Definition TCanvas.cxx:1927
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:503
TExec is a utility class that can be used to execute a C++ command when some event happens in a pad.
Definition TExec.h:26
Define a Frame.
Definition TFrame.h:19
static TClass * Class()
void Paint(Option_t *option="") override
Paint this wbox with its current attributes.
Definition TFrame.cxx:127
void UseCurrentStyle() override
Replace current frame attributes by current style.
Definition TFrame.cxx:157
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
static TClass * Class()
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
@ kIsZoomed
Bit set when zooming on Y axis.
Definition TH1.h:407
static TClass * Class()
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
EImageFileTypes
Definition TImage.h:36
@ kBmp
Definition TImage.h:45
@ kPng
Definition TImage.h:40
@ kJpeg
Definition TImage.h:41
@ kXpm
Definition TImage.h:37
@ kAnimGif
Definition TImage.h:55
@ kUnknown
Definition TImage.h:54
@ kTiff
Definition TImage.h:49
@ kGif
Definition TImage.h:48
static TClass * Class()
Option_t * GetOption() const
This class displays a legend box (TPaveText) containing several legend entries.
Definition TLegend.h:23
Use the TLine constructor to create a simple line.
Definition TLine.h:22
Iterator of linked list.
Definition TList.h:196
Option_t * GetOption() const override
Returns the object option stored in the list.
Definition TList.cxx:1274
A doubly linked list.
Definition TList.h:38
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition TList.cxx:532
virtual TObjLink * LastLink() const
Definition TList.h:110
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void RecursiveRemove(TObject *obj) override
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition TList.cxx:894
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
void AddLast(TObject *obj) override
Add object at the end of the list.
Definition TList.cxx:149
TObject * Last() const override
Return the last object in the list. Returns 0 when list is empty.
Definition TList.cxx:823
virtual TObjLink * FirstLink() const
Definition TList.h:107
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
Each ROOT class (see TClass) has a linked list of methods.
Definition TMethod.h:38
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TH1F * GetHistogram()
Returns a pointer to the histogram used to draw the axis.
static TClass * Class()
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
static TClass * Class()
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:149
Mother of all ROOT objects.
Definition TObject.h:42
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Computes distance from point (px,py) to the object.
Definition TObject.cxx:281
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:459
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:994
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:224
virtual void UseCurrentStyle()
Set current style settings in this object This function is called when either TCanvas::UseCurrentStyl...
Definition TObject.cxx:906
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1081
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:422
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:885
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:546
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1095
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:504
void MakeZombie()
Definition TObject.h:55
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition TObject.cxx:290
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:628
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:76
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:73
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1069
The most important graphics class in the ROOT system.
Definition TPad.h:28
Short_t GetBorderMode() const override
Definition TPad.h: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:4621
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:6192
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:7450
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:6157
TVirtualViewer3D * GetViewer3D(Option_t *type="") override
Create/obtain handle to 3D viewer.
Definition TPad.cxx:7114
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:4093
void PaintLine3D(Float_t *p1, Float_t *p2) override
Paint 3-D line in the CurrentPad.
Definition TPad.cxx:4274
static Int_t fgMaxPickDistance
Maximum Pick Distance.
Definition TPad.h:115
void ResizePad(Option_t *option="") override
Compute pad conversion coefficients.
Definition TPad.cxx:5637
void PaintMarker3D(Double_t x, Double_t y, Double_t z) override
Paint 3-D marker in the CurrentPad.
Definition TPad.cxx:4310
void PaintPolyMarker(Int_t n, Float_t *x, Float_t *y, Option_t *option="") override
Paint polymarker in CurrentPad World coordinates.
Definition TPad.cxx:4463
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:7217
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:5860
void CopyBackgroundPixmaps(TPad *stop, Int_t x, Int_t y)
Copy pixmaps of pads laying below pad "stop" into pad "stop".
Definition TPad.cxx:3951
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:7326
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:6073
Bool_t fEmbeddedGL
!
Definition TPad.h:87
Int_t UtoAbsPixel(Double_t u) const override
Convert X NDC to absolute pixel.
Definition TPad.cxx:7458
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:7482
void SetAttFillPS(Color_t color, Style_t style) override
Set postscript fill area attributes.
Definition TPad.cxx:6168
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:7290
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:7064
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:7360
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:5420
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:3820
void SetEditable(Bool_t mode=kTRUE) override
Set pad editable yes/no If a pad is not editable:
Definition TPad.cxx:6017
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:3758
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:6643
void PixeltoXY(Double_t xpixel, Double_t ypixel, Double_t &x, Double_t &y) override
Convert pixel to X/Y coordinates.
Definition TPad.cxx:7388
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:7315
void SetBBoxX1(const Int_t x) override
Set lefthandside of BoundingBox to a value (resize in x direction on left)
Definition TPad.cxx:7302
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:6036
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:6133
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:7498
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:7424
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:6890
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:7466
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:5344
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:7397
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:7010
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:6204
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:7379
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:4657
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:4016
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:7519
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:4239
Int_t GetGLDevice() override
Get GL device.
Definition TPad.cxx:7201
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:7209
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:3748
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:6062
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:7096
Bool_t HasCrosshair() const override
Return kTRUE if the crosshair has been activated (via SetCrosshair).
Definition TPad.cxx:6605
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:3970
void Modified(Bool_t flag=true) override
Mark pad modified Will be repainted when TCanvas::Update() will be called next time.
Definition TPad.cxx:7351
void RecursiveRemove(TObject *obj) override
Recursively remove object from a pad and its sub-pads.
Definition TPad.cxx:5402
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:7086
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:6653
void PaintPolyLine(Int_t n, Float_t *x, Float_t *y, Option_t *option="") override
Paint polyline in CurrentPad World coordinates.
Definition TPad.cxx:4333
Int_t WtoAbsPixel(Double_t x1, Double_t x2) const override
Convert a horizontal distance [x1,x2] to pixel.
Definition TPad.cxx:7508
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:6180
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:4527
UInt_t GetPadWidth() const override
Get pad width.
Definition TPad.cxx:2838
void Streamer(TBuffer &) override
Stream a class object.
Definition TPad.cxx:6676
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:4568
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:7442
TPoint GetBBoxCenter() override
Return the center of the Pad as TPoint in pixels.
Definition TPad.cxx:7251
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:5993
Short_t GetBorderSize() const override
Definition TPad.h:200
void RedrawAxis(Option_t *option="") override
Redraw the frame axis.
Definition TPad.cxx:5463
void DrawDist(Rectangle_t aBBox, Rectangle_t bBBox, char mode)
Draw Arrows to indicated equal distances of Objects with given BBoxes.
Definition TPad.cxx:6229
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:7490
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:4059
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:5382
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:7075
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:7234
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:6667
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:4582
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:5797
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:4261
void Print(const char *filename="") const override
This method is equivalent to SaveAs("filename"). See TPad::SaveAs for details.
Definition TPad.cxx:4798
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:7225
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:6313
Int_t GetCrosshair() const
Return the crosshair type (from the mother canvas) crosshair type = 0 means no crosshair.
Definition TPad.cxx:6614
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:3907
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:7266
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:7370
void PaintPolyLineNDC(Int_t n, Double_t *x, Double_t *y, Option_t *option="") override
Paint polyline in CurrentPad NDC coordinates.
Definition TPad.cxx:4433
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:3801
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:4608
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:4449
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:6048
void ReleaseViewer3D(Option_t *type="") override
Release current (external) viewer.
Definition TPad.cxx:7185
void SetCrosshair(Int_t crhair=1) override
Set crosshair active/inactive.
Definition TPad.cxx:6627
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:7279
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:7054
@ 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:4776
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:7474
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:7338
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:3053
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:3061
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2910
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
TString & ReplaceSpecialCppChars()
Find special characters which are typically used in printf() calls and replace them by appropriate es...
Definition TString.cxx:1121
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:703
const char * Data() const
Definition TString.h:384
virtual void Streamer(TBuffer &)
Stream a string object.
Definition TString.cxx:1418
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2384
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2362
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:660
Int_t GetOptLogy() const
Definition TStyle.h:250
void SetPadBorderMode(Int_t mode=1)
Definition TStyle.h:361
void SetPadTopMargin(Float_t margin=0.1)
Definition TStyle.h:363
void SetOptLogx(Int_t logx=1)
Definition TStyle.h:333
void SetPadBottomMargin(Float_t margin=0.1)
Definition TStyle.h:362
Int_t GetOptTitle() const
Definition TStyle.h:248
Int_t GetPadTickX() const
Definition TStyle.h:219
Bool_t IsReading() const
Definition TStyle.h:300
Color_t GetPadColor() const
Definition TStyle.h:210
void SetPadRightMargin(Float_t margin=0.1)
Definition TStyle.h:365
void SetTitleFont(Style_t font=62, Option_t *axis="X")
Definition TStyle.cxx:1776
Float_t GetPadRightMargin() const
Definition TStyle.h:216
void SetTitleBorderSize(Width_t size=2)
Definition TStyle.h:412
Float_t GetDateX() const
Definition TStyle.h:199
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1217
void SetPadTickY(Int_t ticky)
Definition TStyle.h:369
Color_t GetTitleFillColor() const
Definition TStyle.h:273
void SetPadTickX(Int_t tickx)
Definition TStyle.h:368
Int_t GetOptDate() const
Definition TStyle.h:244
Bool_t GetPadGridY() const
Definition TStyle.h:218
void SetPadGridX(Bool_t gridx)
Definition TStyle.h:366
void SetTitleTextColor(Color_t color=1)
Definition TStyle.h:409
Float_t GetPadLeftMargin() const
Definition TStyle.h:215
Double_t GetHatchesSpacing() const
Definition TStyle.h:203
Bool_t GetPadGridX() const
Definition TStyle.h:217
void SetPadLeftMargin(Float_t margin=0.1)
Definition TStyle.h:364
void SetPadGridY(Bool_t gridy)
Definition TStyle.h:367
void SetOptLogy(Int_t logy=1)
Definition TStyle.h:334
Int_t GetOptFile() const
Definition TStyle.h:245
TAttText * GetAttDate()
Definition TStyle.h:170
Int_t GetPadTickY() const
Definition TStyle.h:220
Width_t GetPadBorderSize() const
Definition TStyle.h:211
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
void SetTitleFillColor(Color_t color=1)
Definition TStyle.h:408
Float_t GetPadBottomMargin() const
Definition TStyle.h:213
void SetOptLogz(Int_t logz=1)
Definition TStyle.h:335
void 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:609
virtual void SetNDC(Bool_t isNDC=kTRUE)
Set NDC mode on if isNDC = kTRUE, off otherwise.
Definition TText.cxx:739
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:415
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:6282
TAttBBox2D * fb
Definition TPad.cxx:6284
dField()
Definition TPad.cxx:6289
char fdir
Definition TPad.cxx:6286
dField(TAttBBox2D *a, TAttBBox2D *b, Int_t dist, char direction)
Definition TPad.cxx:6293
TAttBBox2D * fa
Definition TPad.cxx:6283
Int_t fdist
Definition TPad.cxx:6285
TMarker m
Definition textangle.C:8