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