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