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