TPad.cxx

Go to the documentation of this file.
00001 // @(#)root/gpad:$Id: TPad.cxx 37057 2010-11-29 08:50:16Z couet $
00002 // Author: Rene Brun   12/12/94
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include <string.h>
00013 #include <stdlib.h>
00014 
00015 #include "Riostream.h"
00016 #include "TROOT.h"
00017 #include "TError.h"
00018 #include "TMath.h"
00019 #include "TSystem.h"
00020 #include "TStyle.h"
00021 #include "TH1.h"
00022 #include "TClass.h"
00023 #include "TBaseClass.h"
00024 #include "TClassTable.h"
00025 #include "TVirtualPS.h"
00026 #include "TVirtualX.h"
00027 #include "TVirtualViewer3D.h"
00028 #include "TView.h"
00029 #include "TPoint.h"
00030 #include "TGraph.h"
00031 #include "TMultiGraph.h"
00032 #include "THStack.h"
00033 #include "TPaveText.h"
00034 #include "TGroupButton.h"
00035 #include "TBrowser.h"
00036 #include "TVirtualGL.h"
00037 #include "TString.h"
00038 #include "TDataMember.h"
00039 #include "TMethod.h"
00040 #include "TDataType.h"
00041 #include "TRealData.h"
00042 #include "TFrame.h"
00043 #include "TExec.h"
00044 #include "TDatime.h"
00045 #include "TColor.h"
00046 #include "TCanvas.h"
00047 #include "TPluginManager.h"
00048 #include "TEnv.h"
00049 #include "TImage.h"
00050 #include "TViewer3DPad.h"
00051 #include "TBuffer3D.h"
00052 #include "TBuffer3DTypes.h"
00053 #include "TCreatePrimitives.h"
00054 #include "TLegend.h"
00055 #include "TAtt3D.h"
00056 #include "TObjString.h"
00057 #include "TApplication.h"
00058 #include "TVirtualPadPainter.h"
00059 
00060 static Int_t gReadLevel = 0;
00061 
00062 Int_t TPad::fgMaxPickDistance = 5;
00063 
00064 ClassImpQ(TPad)
00065 
00066 
00067 //______________________________________________________________________________
00068 //  The Pad class is the most important graphics class in the ROOT system.
00069 //Begin_Html
00070 /*
00071 <img src="gif/tpad_classtree.gif">
00072 */
00073 //End_Html
00074 //  A Pad is contained in a Canvas.
00075 //  A Pad may contain other pads (unlimited pad hierarchy).
00076 //  A pad is a linked list of primitives of any type (graphics objects,
00077 //  histograms, detectors, tracks, etc.).
00078 //  Adding a new element into a pad is in general performed by the Draw
00079 //  member function of the object classes.
00080 //  It is important to realize that the pad is a linked list of references
00081 //  to the original object.
00082 //  For example, in case of a histogram, the histogram.Draw() operation
00083 //  only stores a reference to the histogram object and not a graphical
00084 //  representation of this histogram.
00085 //  When the mouse is used to change (say the bin content), the bin content
00086 //  of the original histogram is changed !!
00087 //
00088 //  The convention used in ROOT is that a Draw operation only adds
00089 //  a reference to the object. The effective drawing is performed
00090 //  when the canvas receives a signal to be painted.
00091 //  This signal is generally sent when typing carriage return in the
00092 //  command input or when a graphical operation has been performed on one
00093 //  of the pads of this canvas.
00094 //  When a Canvas/Pad is repainted, the member function Paint for all
00095 //  objects in the Pad linked list is invoked.
00096 //
00097 //  When the mouse is moved on the Pad, The member function DistancetoPrimitive
00098 //  is called for all the elements in the pad. DistancetoPrimitive returns
00099 //  the distance in pixels to this object.
00100 //  when the object is within the distance window, the member function
00101 //  ExecuteEvent is called for this object.
00102 //  in ExecuteEvent, move, changes can be performed on the object.
00103 //  For examples of DistancetoPrimitive and ExecuteEvent functions,
00104 //  see classes TLine::DistancetoPrimitive, TLine::ExecuteEvent
00105 //              TBox::DistancetoPrimitive,  TBox::ExecuteEvent
00106 //              TH1::DistancetoPrimitive,   TH1::ExecuteEvent
00107 //
00108 //  A Pad supports linear and log scales coordinate systems.
00109 //  The transformation coefficients are explained in TPad::ResizePad.
00110 //  An example of pads hierarchy is shown below:
00111 //Begin_Html
00112 /*
00113 <img src="examples/gif/canvas.gif">
00114 */
00115 //End_Html
00116 //
00117 
00118 
00119 //______________________________________________________________________________
00120 TPad::TPad()
00121 {
00122    // Pad default constructor.
00123 
00124    fModified   = kTRUE;
00125    fTip        = 0;
00126    fPadPointer = 0;
00127    fPrimitives = 0;
00128    fExecs      = 0;
00129    fCanvas     = 0;
00130    fMother     = 0;
00131    fPadPaint   = 0;
00132    fPixmapID   = -1;
00133    fGLDevice   = -1;
00134    fCopyGLDevice = kFALSE;
00135    fEmbeddedGL = kFALSE;
00136    fTheta      = 30;
00137    fPhi        = 30;
00138    fNumber     = 0;
00139    fAbsCoord   = kFALSE;
00140    fEditable   = kTRUE;
00141    fCrosshair  = 0;
00142    fCrosshairPos = 0;
00143    fPadView3D  = 0;
00144    fMother     = (TPad*)gPad;
00145 
00146    fAbsHNDC      = 0.;
00147    fAbsPixeltoXk = 0.;
00148    fAbsPixeltoYk = 0.;
00149    fAbsWNDC      = 0.;
00150    fAbsXlowNDC   = 0.;
00151    fAbsYlowNDC   = 0.;
00152    fBorderMode   = 0;
00153    fBorderSize   = 0;
00154    fPixeltoX     = 0;
00155    fPixeltoXk    = 0.;
00156    fPixeltoY     = 0.;
00157    fPixeltoYk    = 0.;
00158    fUtoAbsPixelk = 0.;
00159    fUtoPixel     = 0.;
00160    fUtoPixelk    = 0.;
00161    fVtoAbsPixelk = 0.;
00162    fVtoPixel     = 0.;
00163    fVtoPixelk    = 0.;
00164    fXtoAbsPixelk = 0.;
00165    fXtoPixel     = 0.;
00166    fXtoPixelk    = 0.;
00167    fYtoAbsPixelk = 0.;
00168    fYtoPixel     = 0.;
00169    fYtoPixelk   = 0.;
00170 
00171    fFixedAspectRatio = kFALSE;
00172    fAspectRatio      = 0.;
00173 
00174    fLogx  = 0;
00175    fLogy  = 0;
00176    fLogz  = 0;
00177    fGridx = 0;
00178    fGridy = 0;
00179    fTickx = 0;
00180    fTicky = 0;
00181    fFrame = 0;
00182    fView  = 0;
00183 
00184    fUxmin = fUymin = fUxmax = fUymax = 0;
00185 
00186    // Set default world coordinates to NDC [0,1]
00187    fX1 = 0;
00188    fX2 = 1;
00189    fY1 = 0;
00190    fY2 = 1;
00191 
00192    // Set default pad range
00193    fXlowNDC = 0;
00194    fYlowNDC = 0;
00195    fWNDC    = 1;
00196    fHNDC    = 1;
00197 
00198    fViewer3D = 0;
00199    SetBit(kMustCleanup);
00200 
00201    // the following line is temporarily disabled. It has side effects
00202    // when the pad is a TDrawPanelHist or a TFitPanel.
00203    // the line was supposed to fix a problem with DrawClonePad
00204    //   gROOT->SetSelectedPad(this);
00205 }
00206 
00207 
00208 //______________________________________________________________________________
00209 TPad::TPad(const char *name, const char *title, Double_t xlow,
00210            Double_t ylow, Double_t xup, Double_t yup,
00211            Color_t color, Short_t bordersize, Short_t bordermode)
00212           : TVirtualPad(name,title,xlow,ylow,xup,yup,color,bordersize,bordermode)
00213 {
00214    // Pad constructor.
00215    //
00216    //  A pad is a linked list of primitives.
00217    //  A pad is contained in a canvas. It may contain other pads.
00218    //  A pad has attributes. When a pad is created, the attributes
00219    //  defined in the current style are copied to the pad attributes.
00220    //
00221    //  xlow [0,1] is the position of the bottom left point of the pad
00222    //             expressed in the mother pad reference system
00223    //  ylow [0,1] is the Y position of this point.
00224    //  xup  [0,1] is the x position of the top right point of the pad
00225    //             expressed in the mother pad reference system
00226    //  yup  [0,1] is the Y position of this point.
00227    //
00228    //  the bordersize is in pixels
00229    //  bordermode = -1 box looks as it is behind the screen
00230    //  bordermode = 0  no special effects
00231    //  bordermode = 1  box looks as it is in front of the screen
00232 
00233    fModified   = kTRUE;
00234    fTip        = 0;
00235    fBorderSize = bordersize;
00236    fBorderMode = bordermode;
00237    if (gPad)   fCanvas = gPad->GetCanvas();
00238    else        fCanvas = (TCanvas*)this;
00239    fMother     = (TPad*)gPad;
00240    fPrimitives = new TList;
00241    fExecs      = new TList;
00242    fPadPointer = 0;
00243    fTheta      = 30;
00244    fPhi        = 30;
00245    fGridx      = gStyle->GetPadGridX();
00246    fGridy      = gStyle->GetPadGridY();
00247    fTickx      = gStyle->GetPadTickX();
00248    fTicky      = gStyle->GetPadTickY();
00249    fFrame      = 0;
00250    fView       = 0;
00251    fPadPaint   = 0;
00252    fPadView3D  = 0;
00253    fPixmapID   = -1;      // -1 means pixmap will be created by ResizePad()
00254    fCopyGLDevice = kFALSE;
00255    fEmbeddedGL = kFALSE;
00256    fNumber     = 0;
00257    fAbsCoord   = kFALSE;
00258    fEditable   = kTRUE;
00259    fCrosshair  = 0;
00260    fCrosshairPos = 0;
00261 
00262    fFixedAspectRatio = kFALSE;
00263    fAspectRatio      = 0.;
00264 
00265    fViewer3D = 0;
00266 
00267    fGLDevice = fCanvas->GetGLDevice();
00268    // Set default world coordinates to NDC [0,1]
00269    fX1 = 0;
00270    fX2 = 1;
00271    fY1 = 0;
00272    fY2 = 1;
00273 
00274    if (!gPad) {
00275       Error("TPad", "You must create a TCanvas before creating a TPad");
00276       MakeZombie();
00277       return;
00278    }
00279 
00280    TPad *padsav = (TPad*)gPad;
00281 
00282    if ((xlow < 0) || (xlow > 1) || (ylow < 0) || (ylow > 1)) {
00283       Error("TPad", "illegal bottom left position: x=%f, y=%f", xlow, ylow);
00284       goto zombie;
00285    }
00286    if ((xup < 0) || (xup > 1) || (yup < 0) || (yup > 1)) {
00287       Error("TPad", "illegal top right position: x=%f, y=%f", xup, yup);
00288       goto zombie;
00289    }
00290 
00291    fLogx = gStyle->GetOptLogx();
00292    fLogy = gStyle->GetOptLogy();
00293    fLogz = gStyle->GetOptLogz();
00294 
00295    fUxmin = fUymin = fUxmax = fUymax = 0;
00296 
00297    // Set pad parameters and Compute conversion coeeficients
00298    SetPad(name, title, xlow, ylow, xup, yup, color, bordersize, bordermode);
00299    Range(0, 0, 1, 1);
00300    SetBit(kMustCleanup);
00301    SetBit(kCanDelete);
00302 
00303    padsav->cd();
00304    return;
00305 
00306 zombie:
00307    // error in creating pad occured, make this pad a zombie
00308    MakeZombie();
00309    padsav->cd();
00310 }
00311 
00312 
00313 //______________________________________________________________________________
00314 TPad::~TPad()
00315 {
00316    // Pad destructor.
00317 
00318    if (!TestBit(kNotDeleted)) return;
00319    Close();
00320    CloseToolTip(fTip);
00321    DeleteToolTip(fTip);
00322    SafeDelete(fPrimitives);
00323    SafeDelete(fExecs);
00324    delete fViewer3D;
00325 }
00326 
00327 
00328 //______________________________________________________________________________
00329 void TPad::AddExec(const char *name, const char*command)
00330 {
00331    // Add a new TExec object to the list of Execs.
00332    // When an event occurs in the pad (mouse click, etc) the list of CINT commands
00333    // in the list of Execs are executed via TPad::AutoExec.
00334    //  When a pad event occurs (mouse move, click, etc) all the commands
00335    //  contained in the fExecs list are executed in the order found in the list.
00336    //  This facility is activated by default. It can be deactivated by using
00337    //  the canvas "Option" menu.
00338    //  The following examples of TExec commands are provided in the tutorials:
00339    //  macros exec1.C and exec2.C.
00340    //  Example1 of use of exec1.C
00341    //  ==========================
00342    //  Root > TFile f("hsimple.root")
00343    //  Root > hpx.Draw()
00344    //  Root > c1.AddExec("ex1",".x exec1.C")
00345    //   At this point you can use the mouse to click on the contour of
00346    //   the histogram hpx. When the mouse is clicked, the bin number and its
00347    //   contents are printed.
00348    //  Example2 of use of exec1.C
00349    //  ==========================
00350    //  Root > TFile f("hsimple.root")
00351    //  Root > hpxpy.Draw()
00352    //  Root > c1.AddExec("ex2",".x exec2.C")
00353    //    When moving the mouse in the canvas, a second canvas shows the
00354    //    projection along X of the bin corresponding to the Y position
00355    //    of the mouse. The resulting histogram is fitted with a gaussian.
00356    //    A "dynamic" line shows the current bin position in Y.
00357    //    This more elaborated example can be used as a starting point
00358    //    to develop more powerful interactive applications exploiting CINT
00359    //    as a development engine.
00360 
00361    if (!fExecs) fExecs = new TList;
00362    TExec *ex = new TExec(name,command);
00363    fExecs->Add(ex);
00364 }
00365 
00366 
00367 //______________________________________________________________________________
00368 void TPad::AutoExec()
00369 {
00370    // Execute the list of Execs when a pad event occurs.
00371 
00372    if (GetCrosshair()) DrawCrosshair();
00373 
00374    if (!fExecs) fExecs = new TList;
00375    TIter next(fExecs);
00376    TExec *exec;
00377    while ((exec = (TExec*)next())) {
00378       exec->Exec();
00379    }
00380 }
00381 
00382 
00383 //______________________________________________________________________________
00384 void TPad::Browse(TBrowser *b)
00385 {
00386    // Browse pad.
00387 
00388    cd();
00389    if (fPrimitives) fPrimitives->Browse(b);
00390 }
00391 
00392 
00393 //______________________________________________________________________________
00394 TLegend *TPad::BuildLegend(Double_t x1, Double_t y1, Double_t x2, Double_t y2,
00395                            const char* title)
00396 {
00397    // Build a legend from the graphical objects in the pad
00398    //
00399    // A simple method to to build automatically a TLegend from the primitives in
00400    // a TPad. Only those deriving from TAttLine, TAttMarker and TAttFill are
00401    // added, excluding TPave and TFrame derived classes.
00402    // x1, y1, x2, y2 are the Tlegend coordinates.
00403    // title is the legend title. By default it is " ".
00404    //
00405    // If the pad contains some TMultiGraph or THStack the individual graphs or
00406    // histograms in them are added to the TLegend.
00407 
00408    TList *lop=GetListOfPrimitives();
00409    if (!lop) return 0;
00410    TLegend *leg=0;
00411    TIter next(lop);
00412    TString mes;
00413    TObject *o=0;
00414    while( (o=next()) ) {
00415       if((o->InheritsFrom(TAttLine::Class()) || o->InheritsFrom(TAttMarker::Class()) ||
00416           o->InheritsFrom(TAttFill::Class())) &&
00417          ( !(o->InheritsFrom(TFrame::Class())) && !(o->InheritsFrom(TPave::Class())) )) {
00418             if (!leg) leg = new TLegend(x1, y1, x2, y2, title);
00419             if (o->InheritsFrom(TNamed::Class()) && strlen(((TNamed *)o)->GetTitle()))
00420                mes = ((TNamed *)o)->GetTitle();
00421             else if (strlen(o->GetName()))
00422                mes = o->GetName();
00423             else
00424                mes = o->ClassName();
00425             TString opt("");
00426             if (o->InheritsFrom(TAttLine::Class()))   opt += "l";
00427             if (o->InheritsFrom(TAttMarker::Class())) opt += "p";
00428             if (o->InheritsFrom(TAttFill::Class()))   opt += "f";
00429             leg->AddEntry(o,mes.Data(),opt.Data());
00430       } else if ( o->InheritsFrom(TMultiGraph::Class() ) ) {
00431          if (!leg) leg = new TLegend(x1, y1, x2, y2, title);
00432          TList * grlist = ((TMultiGraph *)o)->GetListOfGraphs();
00433          TIter nextgraph(grlist);
00434          TGraph * gr;
00435          TObject * obj;
00436          while ((obj = nextgraph())) {
00437             gr = (TGraph*) obj;
00438             if      (strlen(gr->GetTitle())) mes = gr->GetTitle();
00439             else if (strlen(gr->GetName()))  mes = gr->GetName();
00440             else                             mes = gr->ClassName();
00441             leg->AddEntry( obj, mes.Data(), "lpf" );
00442          }
00443       } else if ( o->InheritsFrom(THStack::Class() ) ) {
00444          if (!leg) leg = new TLegend(x1, y1, x2, y2, title);
00445          TList * hlist = ((THStack *)o)->GetHists();
00446          TIter nexthist(hlist);
00447          TH1 * hist;
00448          TObject * obj;
00449          while ((obj = nexthist())) {
00450             hist = (TH1*) obj;
00451             if      (strlen(hist->GetTitle())) mes = hist->GetTitle();
00452             else if (strlen(hist->GetName()))  mes = hist->GetName();
00453             else                               mes = hist->ClassName();
00454             leg->AddEntry( obj, mes.Data(), "lpf" );
00455          }
00456       }
00457    }
00458    if (leg) {
00459       TVirtualPad *gpadsave;
00460       gpadsave = gPad;
00461       this->cd();
00462       leg->Draw();
00463       gpadsave->cd();
00464    } else {
00465       Info("BuildLegend(void)","No object to build a TLegend.");
00466    }
00467    return leg;
00468 }
00469 
00470 
00471 //______________________________________________________________________________
00472 TVirtualPad *TPad::cd(Int_t subpadnumber)
00473 {
00474    // Set Current pad.
00475    // When a canvas/pad is divided via TPad::Divide, one can directly
00476    //  set the current path to one of the subdivisions.
00477    //  See TPad::Divide for the convention to number subpads.
00478    //  Returns the new current pad, or 0 in case of failure.
00479    //  For example:
00480    //    c1.Divide(2,3); // create 6 pads (2 divisions along x, 3 along y).
00481    //    To set the current pad to the bottom right pad, do
00482    //    c1.cd(6);
00483    //  Note1:  c1.cd() is equivalent to c1.cd(0) and sets the current pad
00484    //          to c1 itself.
00485    //  Note2:  after a statement like c1.cd(6), the global variable gPad
00486    //          points to the current pad. One can use gPad to set attributes
00487    //          of the current pad.
00488    //  Note3:  One can get a pointer to one of the sub-pads of pad with:
00489    //          TPad *subpad = (TPad*)pad->GetPad(subpadnumber);
00490 
00491    if (!subpadnumber) {
00492       gPad = this;
00493       if (!gPad->IsBatch()) GetPainter()->SelectDrawable(fPixmapID);
00494       return gPad;
00495    }
00496 
00497    TObject *obj;
00498    if (!fPrimitives) fPrimitives = new TList;
00499    TIter    next(fPrimitives);
00500    while ((obj = next())) {
00501       if (obj->InheritsFrom(TPad::Class())) {
00502          Int_t n = ((TPad*)obj)->GetNumber();
00503          if (n == subpadnumber) {
00504             return ((TPad*)obj)->cd();
00505          }
00506       }
00507    }
00508    return 0;
00509 }
00510 
00511 
00512 //______________________________________________________________________________
00513 void TPad::Clear(Option_t *option)
00514 {
00515    // Delete all pad primitives.
00516    //
00517    //   If the bit kClearAfterCR has been set for this pad, the Clear function
00518    //   will execute only after having pressed a CarriageReturn
00519    //   Set the bit with mypad->SetBit(TPad::kClearAfterCR)
00520 
00521    if (!IsEditable()) return;
00522 
00523    if (!fPadPaint) {
00524       SafeDelete(fView);
00525       if (fPrimitives) fPrimitives->Clear(option);
00526       delete fFrame; fFrame = 0;
00527    }
00528    if (fCanvas) fCanvas->Cleared(this);
00529 
00530    cd();
00531 
00532    if (TestBit(kClearAfterCR)) getchar();
00533 
00534    if (!gPad->IsBatch()) GetPainter()->ClearDrawable();
00535    if (gVirtualPS && gPad == gPad->GetCanvas()) gVirtualPS->NewPage();
00536 
00537    PaintBorder(GetFillColor(), kTRUE);
00538    fCrosshairPos = 0;
00539    ResetBit(TGraph::kClipFrame);
00540 }
00541 
00542 
00543 //___________________________________________________________
00544 Int_t TPad::Clip(Float_t *x, Float_t *y, Float_t xclipl, Float_t yclipb, Float_t xclipr, Float_t yclipt)
00545 {
00546    // Clipping routine: Cohen Sutherland algorithm.
00547    //
00548    //   If Clip ==2 the segment is outside the boundary.
00549    //   If Clip ==1 the segment has one point outside the boundary.
00550    //   If Clip ==0 the segment is inside the boundary.
00551    //
00552    // _Input parameters:
00553    //
00554    //  x[2], y[2] : Segment coordinates
00555    //  xclipl, yclipb, xclipr, yclipt : Clipping boundary
00556    //
00557    // _Output parameters:
00558    //
00559    //  x[2], y[2] : New segment coordinates
00560 
00561    const Float_t kP=10000;
00562    Int_t clip = 0;
00563 
00564    for (Int_t i=0;i<2;i++) {
00565       if (TMath::Abs(xclipl-x[i]) <= TMath::Abs(xclipr-xclipl)/kP) x[i] = xclipl;
00566       if (TMath::Abs(xclipr-x[i]) <= TMath::Abs(xclipr-xclipl)/kP) x[i] = xclipr;
00567       if (TMath::Abs(yclipb-y[i]) <= TMath::Abs(yclipt-yclipb)/kP) y[i] = yclipb;
00568       if (TMath::Abs(yclipt-y[i]) <= TMath::Abs(yclipt-yclipb)/kP) y[i] = yclipt;
00569    }
00570 
00571    // Compute the first endpoint codes.
00572    Int_t code1 = ClippingCode(x[0],y[0],xclipl,yclipb,xclipr,yclipt);
00573    Int_t code2 = ClippingCode(x[1],y[1],xclipl,yclipb,xclipr,yclipt);
00574 
00575    Double_t xt=0, yt=0;
00576    Int_t clipped = 0; //this variable could be used in a future version
00577    while(code1 + code2) {
00578       clipped = 1;
00579 
00580       // The line lies entirely outside the clipping boundary
00581       if (code1&code2) {
00582          clip = 2;
00583          return clip;
00584       }
00585 
00586       // The line is subdivided into several parts
00587       Int_t ic = code1;
00588       if (ic == 0) ic = code2;
00589       if (ic & 0x1) {
00590          yt = y[0] + (y[1]-y[0])*(xclipl-x[0])/(x[1]-x[0]);
00591          xt = xclipl;
00592       }
00593       if (ic & 0x2) {
00594          yt = y[0] + (y[1]-y[0])*(xclipr-x[0])/(x[1]-x[0]);
00595          xt = xclipr;
00596       }
00597       if (ic & 0x4) {
00598          xt = x[0] + (x[1]-x[0])*(yclipb-y[0])/(y[1]-y[0]);
00599          yt = yclipb;
00600       }
00601       if (ic & 0x8) {
00602          xt = x[0] + (x[1]-x[0])*(yclipt-y[0])/(y[1]-y[0]);
00603          yt = yclipt;
00604       }
00605       if (ic == code1) {
00606          x[0]  = xt;
00607          y[0]  = yt;
00608          code1 = ClippingCode(xt,yt,xclipl,yclipb,xclipr,yclipt);
00609       } else {
00610          x[1]  = xt;
00611          y[1]  = yt;
00612          code2 = ClippingCode(xt,yt,xclipl,yclipb,xclipr,yclipt);
00613       }
00614    }
00615    clip = clipped;
00616    return clip;
00617 }
00618 
00619 
00620 //___________________________________________________________
00621 Int_t TPad::Clip(Double_t *x, Double_t *y, Double_t xclipl, Double_t yclipb, Double_t xclipr, Double_t yclipt)
00622 {
00623    // Clipping routine: Cohen Sutherland algorithm.
00624    //
00625    //   If Clip ==2 the segment is outside the boundary.
00626    //   If Clip ==1 the segment has one point outside the boundary.
00627    //   If Clip ==0 the segment is inside the boundary.
00628    //
00629    // _Input parameters:
00630    //
00631    //  x[2], y[2] : Segment coordinates
00632    //  xclipl, yclipb, xclipr, yclipt : Clipping boundary
00633    //
00634    // _Output parameters:
00635    //
00636    //  x[2], y[2] : New segment coordinates
00637 
00638    const Double_t kP=10000;
00639    Int_t clip = 0;
00640 
00641    for (Int_t i=0;i<2;i++) {
00642       if (TMath::Abs(xclipl-x[i]) <= TMath::Abs(xclipr-xclipl)/kP) x[i] = xclipl;
00643       if (TMath::Abs(xclipr-x[i]) <= TMath::Abs(xclipr-xclipl)/kP) x[i] = xclipr;
00644       if (TMath::Abs(yclipb-y[i]) <= TMath::Abs(yclipt-yclipb)/kP) y[i] = yclipb;
00645       if (TMath::Abs(yclipt-y[i]) <= TMath::Abs(yclipt-yclipb)/kP) y[i] = yclipt;
00646    }
00647 
00648    // Compute the first endpoint codes.
00649    Int_t code1 = 0;
00650    if (x[0] < xclipl) code1 = code1 | 0x1;
00651    if (x[0] > xclipr) code1 = code1 | 0x2;
00652    if (y[0] < yclipb) code1 = code1 | 0x4;
00653    if (y[0] > yclipt) code1 = code1 | 0x8;
00654    Int_t code2 = 0;
00655    if (x[1] < xclipl) code2 = code2 | 0x1;
00656    if (x[1] > xclipr) code2 = code2 | 0x2;
00657    if (y[1] < yclipb) code2 = code2 | 0x4;
00658    if (y[1] > yclipt) code2 = code2 | 0x8;
00659 
00660    Double_t xt=0, yt=0;
00661    Int_t clipped = 0; //this variable could be used in a future version
00662    while(code1 + code2) {
00663       clipped = 1;
00664 
00665       // The line lies entirely outside the clipping boundary
00666       if (code1&code2) {
00667          clip = 2;
00668          return clip;
00669       }
00670 
00671       // The line is subdivided into several parts
00672       Int_t ic = code1;
00673       if (ic == 0) ic = code2;
00674       if (ic & 0x1) {
00675          yt = y[0] + (y[1]-y[0])*(xclipl-x[0])/(x[1]-x[0]);
00676          xt = xclipl;
00677       }
00678       if (ic & 0x2) {
00679          yt = y[0] + (y[1]-y[0])*(xclipr-x[0])/(x[1]-x[0]);
00680          xt = xclipr;
00681       }
00682       if (ic & 0x4) {
00683          xt = x[0] + (x[1]-x[0])*(yclipb-y[0])/(y[1]-y[0]);
00684          yt = yclipb;
00685       }
00686       if (ic & 0x8) {
00687          xt = x[0] + (x[1]-x[0])*(yclipt-y[0])/(y[1]-y[0]);
00688          yt = yclipt;
00689       }
00690       if (ic == code1) {
00691          x[0]  = xt;
00692          y[0]  = yt;
00693          code1 = ClippingCode(xt,yt,xclipl,yclipb,xclipr,yclipt);
00694       } else {
00695          x[1]  = xt;
00696          y[1]  = yt;
00697          code2 = ClippingCode(xt,yt,xclipl,yclipb,xclipr,yclipt);
00698       }
00699    }
00700    clip = clipped;
00701    return clip;
00702 }
00703 
00704 
00705 //___________________________________________________________
00706 Int_t TPad::ClippingCode(Double_t x, Double_t y, Double_t xcl1, Double_t ycl1, Double_t xcl2, Double_t ycl2)
00707 {
00708    // Compute the endpoint codes for TPad::Clip.
00709 
00710    Int_t code = 0;
00711    if (x < xcl1) code = code | 0x1;
00712    if (x > xcl2) code = code | 0x2;
00713    if (y < ycl1) code = code | 0x4;
00714    if (y > ycl2) code = code | 0x8;
00715    return code;
00716 }
00717 
00718 
00719 //___________________________________________________________
00720 Int_t TPad::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)
00721 {
00722    // Clip polygon using the Sutherland-Hodgman algorithm.
00723    //
00724    // Input parameters:
00725    //
00726    //  n: Number of points in the polygon to be clipped
00727    //  x[n], y[n] : Polygon do be clipped vertices
00728    //  xclipl, yclipb, xclipr, yclipt : Clipping boundary
00729    //
00730    // Output parameters:
00731    //
00732    // nn: number of points in xc and yc
00733    // xc, yc: clipped polygon vertices. The Int_t returned by this function is
00734    //         the number of points in the clipped polygon. These vectors must
00735    //         be allocated by the calling function. A size of 2*n for each is
00736    //         enough.
00737    //
00738    // Sutherland and Hodgman's polygon-clipping algorithm uses a divide-and-conquer
00739    // strategy: It solves a series of simple and identical problems that, when
00740    // combined, solve the overall problem. The simple problem is to clip a polygon
00741    // against a single infinite clip edge. Four clip edges, each defining one boundary
00742    // of the clip rectangle, successively clip a polygon against a clip rectangle.
00743    //
00744    // Steps of Sutherland-Hodgman's polygon-clipping algorithm:
00745    //
00746    // * Polygons can be clipped against each edge of the window one at a time.
00747    //   Windows/edge intersections, if any, are easy to find since the X or Y coordinates
00748    //   are already known.
00749    // * Vertices which are kept after clipping against one window edge are saved for
00750    //   clipping against the remaining edges.
00751    // * Note that the number of vertices usually changes and will often increases.
00752    //
00753    // The clip boundary determines a visible and invisible region. The edges from
00754    // vertex i to vertex i+1 can be one of four types:
00755    //
00756    // * Case 1 : Wholly inside visible region - save endpoint
00757    // * Case 2 : Exit visible region - save the intersection
00758    // * Case 3 : Wholly outside visible region - save nothing
00759    // * Case 4 : Enter visible region - save intersection and endpoint
00760 
00761    Int_t nc, nc2;
00762    Double_t x1, y1, x2, y2, slope; // Segment to be clipped
00763 
00764    Double_t *xc2 = new Double_t[nn];
00765    Double_t *yc2 = new Double_t[nn];
00766 
00767    // Clip against the left boundary
00768    x1 = x[n-1]; y1 = y[n-1];
00769    nc2 = 0;
00770    Int_t i;
00771    for (i=0; i<n; i++) {
00772       x2 = x[i]; y2 = y[i];
00773       if (x1 == x2) {
00774          slope = 0;
00775       } else {
00776          slope = (y2-y1)/(x2-x1);
00777       }
00778       if (x1 >= xclipl) {
00779          if (x2 < xclipl) {
00780             xc2[nc2] = xclipl; yc2[nc2++] = slope*(xclipl-x1)+y1;
00781          } else {
00782             xc2[nc2] = x2; yc2[nc2++] = y2;
00783          }
00784       } else {
00785          if (x2 >= xclipl) {
00786             xc2[nc2] = xclipl; yc2[nc2++] = slope*(xclipl-x1)+y1;
00787             xc2[nc2] = x2; yc2[nc2++] = y2;
00788          }
00789       }
00790       x1 = x2; y1 = y2;
00791    }
00792 
00793    // Clip against the top boundary
00794    x1 = xc2[nc2-1]; y1 = yc2[nc2-1];
00795    nc = 0;
00796    for (i=0; i<nc2; i++) {
00797       x2 = xc2[i]; y2 = yc2[i];
00798       if (y1 == y2) {
00799          slope = 0;
00800       } else {
00801          slope = (x2-x1)/(y2-y1);
00802       }
00803       if (y1 <= yclipt) {
00804          if (y2 > yclipt) {
00805             xc[nc] = x1+(yclipt-y1)*slope; yc[nc++] = yclipt;
00806          } else {
00807             xc[nc] = x2; yc[nc++] = y2;
00808          }
00809       } else {
00810          if (y2 <= yclipt) {
00811             xc[nc] = x1+(yclipt-y1)*slope; yc[nc++] = yclipt;
00812             xc[nc] = x2; yc[nc++] = y2;
00813          }
00814       }
00815       x1 = x2; y1 = y2;
00816    }
00817 
00818    // Clip against the right boundary
00819    x1 = xc[nc-1]; y1 = yc[nc-1];
00820    nc2 = 0;
00821    for (i=0; i<nc; i++) {
00822       x2 = xc[i]; y2 = yc[i];
00823       if (x1 == x2) {
00824          slope = 0;
00825       } else {
00826          slope = (y2-y1)/(x2-x1);
00827       }
00828       if (x1 <= xclipr) {
00829          if (x2 > xclipr) {
00830             xc2[nc2] = xclipr; yc2[nc2++] = slope*(xclipr-x1)+y1;
00831          } else {
00832             xc2[nc2] = x2; yc2[nc2++] = y2;
00833          }
00834       } else {
00835          if (x2 <= xclipr) {
00836             xc2[nc2] = xclipr; yc2[nc2++] = slope*(xclipr-x1)+y1;
00837             xc2[nc2] = x2; yc2[nc2++] = y2;
00838          }
00839       }
00840       x1 = x2; y1 = y2;
00841    }
00842 
00843    // Clip against the bottom boundary
00844    x1 = xc2[nc2-1]; y1 = yc2[nc2-1];
00845    nc = 0;
00846    for (i=0; i<nc2; i++) {
00847       x2 = xc2[i]; y2 = yc2[i];
00848       if (y1 == y2) {
00849          slope = 0;
00850       } else {
00851          slope = (x2-x1)/(y2-y1);
00852       }
00853       if (y1 >= yclipb) {
00854          if (y2 < yclipb) {
00855             xc[nc] = x1+(yclipb-y1)*slope; yc[nc++] = yclipb;
00856          } else {
00857             xc[nc] = x2; yc[nc++] = y2;
00858          }
00859       } else {
00860          if (y2 >= yclipb) {
00861             xc[nc] = x1+(yclipb-y1)*slope; yc[nc++] = yclipb;
00862             xc[nc] = x2; yc[nc++] = y2;
00863          }
00864       }
00865       x1 = x2; y1 = y2;
00866    }
00867 
00868    delete [] xc2;
00869    delete [] yc2;
00870 
00871    if (nc < 3) nc =0;
00872    return nc;
00873 }
00874 
00875 
00876 //______________________________________________________________________________
00877 void TPad::Close(Option_t *)
00878 {
00879    // Delete all primitives in pad and pad itself.
00880    // Pad cannot be used anymore after this call.
00881    // Emits signal "Closed()".
00882 
00883    if (!TestBit(kNotDeleted)) return;
00884    if (!fMother) return;
00885 
00886    if (fPrimitives)
00887       fPrimitives->Clear();
00888    if (fView) {
00889       if (fView->TestBit(kNotDeleted)) delete fView;
00890       fView = 0;
00891    }
00892    if (fFrame) {
00893       if (fFrame->TestBit(kNotDeleted)) delete fFrame;
00894       fFrame = 0;
00895    }
00896 
00897    // emit signal
00898    if (IsA() != TCanvas::Class())
00899       Closed();
00900 
00901    if (fPixmapID != -1) {
00902       if (gPad) {
00903          if (!gPad->IsBatch()) {
00904             GetPainter()->SelectDrawable(fPixmapID);
00905             GetPainter()->DestroyDrawable();
00906          }
00907       }
00908       fPixmapID = -1;
00909 
00910       if (!gROOT->GetListOfCanvases()) return;
00911       if (fMother == this) {
00912          gROOT->GetListOfCanvases()->Remove(this);
00913          return;   // in case of TCanvas
00914       }
00915 
00916       // remove from the mother's list of primitives
00917       if (fMother) {
00918          if (fMother->GetListOfPrimitives())
00919             fMother->GetListOfPrimitives()->Remove(this);
00920 
00921          if (gPad == this) fMother->cd();
00922       }
00923 
00924       if (fCanvas->GetPadSave() == this)
00925          fCanvas->ClearPadSave();
00926       if (fCanvas->GetSelectedPad() == this)
00927          fCanvas->SetSelectedPad(0);
00928       if (fCanvas->GetClickSelectedPad() == this)
00929          fCanvas->SetClickSelectedPad(0);
00930    }
00931 
00932    fMother = 0;
00933    if (gROOT->GetSelectedPad() == this) gROOT->SetSelectedPad(0);
00934 }
00935 
00936 
00937 //______________________________________________________________________________
00938 void TPad::CopyPixmap()
00939 {
00940    // Copy the pixmap of the pad to the canvas.
00941 
00942    int px, py;
00943    XYtoAbsPixel(fX1, fY2, px, py);
00944 
00945    if (fPixmapID != -1)
00946       GetPainter()->CopyDrawable(fPixmapID, px, py);
00947 
00948    if (this == gPad) HighLight(gPad->GetHighLightColor());
00949 }
00950 
00951 
00952 //______________________________________________________________________________
00953 void TPad::CopyPixmaps()
00954 {
00955    // Copy the sub-pixmaps of the pad to the canvas.
00956 
00957    TObject *obj;
00958    if (!fPrimitives) fPrimitives = new TList;
00959    TIter    next(GetListOfPrimitives());
00960    while ((obj = next())) {
00961       if (obj->InheritsFrom(TPad::Class())) {
00962          ((TPad*)obj)->CopyPixmap();
00963          ((TPad*)obj)->CopyPixmaps();
00964       }
00965    }
00966 }
00967 
00968 
00969 //______________________________________________________________________________
00970 void TPad::DeleteExec(const char *name)
00971 {
00972    // Remove TExec name from the list of Execs.
00973 
00974    if (!fExecs) fExecs = new TList;
00975    TExec *ex = (TExec*)fExecs->FindObject(name);
00976    if (!ex) return;
00977    fExecs->Remove(ex);
00978    delete ex;
00979 }
00980 
00981 
00982 //______________________________________________________________________________
00983 Int_t TPad::DistancetoPrimitive(Int_t px, Int_t py)
00984 {
00985    // Compute distance from point px,py to a box.
00986    //
00987    //  Compute the closest distance of approach from point px,py to the
00988    //  edges of this pad.
00989    //  The distance is computed in pixels units.
00990 
00991    Int_t pxl, pyl, pxt, pyt;
00992    Int_t px1 = gPad->XtoAbsPixel(fX1);
00993    Int_t py1 = gPad->YtoAbsPixel(fY1);
00994    Int_t px2 = gPad->XtoAbsPixel(fX2);
00995    Int_t py2 = gPad->YtoAbsPixel(fY2);
00996    if (px1 < px2) {pxl = px1; pxt = px2;}
00997    else           {pxl = px2; pxt = px1;}
00998    if (py1 < py2) {pyl = py1; pyt = py2;}
00999    else           {pyl = py2; pyt = py1;}
01000 
01001    // Are we inside the box?
01002    // ======================
01003    if ( (px > pxl && px < pxt) && (py > pyl && py < pyt) ) {
01004       if (GetFillStyle()) return 0;  //*-* if pad is filled
01005    }
01006 
01007    // Are we on the edges?
01008    // ====================
01009    Int_t dxl = TMath::Abs(px - pxl);
01010    if (py < pyl) dxl += pyl - py; if (py > pyt) dxl += py - pyt;
01011    Int_t dxt = TMath::Abs(px - pxt);
01012    if (py < pyl) dxt += pyl - py; if (py > pyt) dxt += py - pyt;
01013    Int_t dyl = TMath::Abs(py - pyl);
01014    if (px < pxl) dyl += pxl - px; if (px > pxt) dyl += px - pxt;
01015    Int_t dyt = TMath::Abs(py - pyt);
01016    if (px < pxl) dyt += pxl - px; if (px > pxt) dyt += px - pxt;
01017 
01018    Int_t distance = dxl;
01019    if (dxt < distance) distance = dxt;
01020    if (dyl < distance) distance = dyl;
01021    if (dyt < distance) distance = dyt;
01022 
01023    return distance - Int_t(0.5*fLineWidth);
01024 }
01025 
01026 
01027 //______________________________________________________________________________
01028 void TPad::Divide(Int_t nx, Int_t ny, Float_t xmargin, Float_t ymargin, Int_t color)
01029 {
01030    // Automatic pad generation by division.
01031    //
01032    //  The current canvas is divided in nx by ny equal divisions (pads).
01033    //  xmargin is the space along x between pads in percent of canvas.
01034    //  ymargin is the space along y between pads in percent of canvas.
01035    //    (see Note3 below for the special case xmargin <=0 and ymargin <=0)
01036    //  color is the color of the new pads. If 0, color is the canvas color.
01037    //  Pads are automatically named canvasname_n where n is the division number
01038    //  starting from top left pad.
01039    //       Example if canvasname=c1 , nx=2, ny=3
01040    //
01041    //    ...............................................................
01042    //    .                               .                             .
01043    //    .                               .                             .
01044    //    .                               .                             .
01045    //    .           c1_1                .           c1_2              .
01046    //    .                               .                             .
01047    //    .                               .                             .
01048    //    .                               .                             .
01049    //    ...............................................................
01050    //    .                               .                             .
01051    //    .                               .                             .
01052    //    .                               .                             .
01053    //    .           c1_3                .           c1_4              .
01054    //    .                               .                             .
01055    //    .                               .                             .
01056    //    .                               .                             .
01057    //    ...............................................................
01058    //    .                               .                             .
01059    //    .                               .                             .
01060    //    .                               .                             .
01061    //    .           c1_5                .           c1_6              .
01062    //    .                               .                             .
01063    //    .                               .                             .
01064    //    ...............................................................
01065    //
01066    //
01067    //    Once a pad is divided into subpads, one can set the current pad
01068    //    to a subpad with a given division number as illustrated above
01069    //    with TPad::cd(subpad_number).
01070    //    For example, to set the current pad to c1_4, one can do:
01071    //    c1->cd(4)
01072    //
01073    //  Note1:  c1.cd() is equivalent to c1.cd(0) and sets the current pad
01074    //          to c1 itself.
01075    //  Note2:  after a statement like c1.cd(6), the global variable gPad
01076    //          points to the current pad. One can use gPad to set attributes
01077    //          of the current pad.
01078    //  Note3:  in case xmargin <=0 and ymargin <= 0, there is no space
01079    //          between pads. The current pad margins are recomputed to
01080    //          optimize the layout.
01081 
01082    if (!IsEditable()) return;
01083 
01084 
01085    if (gThreadXAR) {
01086       void *arr[7];
01087       arr[1] = this; arr[2] = (void*)&nx;arr[3] = (void*)& ny;
01088       arr[4] = (void*)&xmargin; arr[5] = (void *)& ymargin; arr[6] = (void *)&color;
01089       if ((*gThreadXAR)("PDCD", 7, arr, 0)) return;
01090    }
01091 
01092    TPad *padsav = (TPad*)gPad;
01093    cd();
01094    if (nx <= 0) nx = 1;
01095    if (ny <= 0) ny = 1;
01096    Int_t ix,iy;
01097    Double_t x1,y1,x2,y2;
01098    Double_t dx,dy;
01099    TPad *pad;
01100    Int_t nchname  = strlen(GetName())+6;
01101    Int_t nchtitle = strlen(GetTitle())+6;
01102    char *name  = new char [nchname];
01103    char *title = new char [nchtitle];
01104    Int_t n = 0;
01105    if (color == 0) color = GetFillColor();
01106    if (xmargin > 0 && ymargin > 0) {
01107       //general case
01108       dy = 1/Double_t(ny);
01109       dx = 1/Double_t(nx);
01110       for (iy=0;iy<ny;iy++) {
01111          y2 = 1 - iy*dy - ymargin;
01112          y1 = y2 - dy + 2*ymargin;
01113          if (y1 < 0) y1 = 0;
01114          if (y1 > y2) continue;
01115          for (ix=0;ix<nx;ix++) {
01116             x1 = ix*dx + xmargin;
01117             x2 = x1 +dx -2*xmargin;
01118             if (x1 > x2) continue;
01119             n++;
01120             snprintf(name,nchname,"%s_%d",GetName(),n);
01121             pad = new TPad(name,name,x1,y1,x2,y2,color);
01122             pad->SetNumber(n);
01123             pad->Draw();
01124          }
01125       }
01126    } else {
01127       // special case when xmargin <= 0 && ymargin <= 0
01128       Double_t xl = GetLeftMargin();
01129       Double_t xr = GetRightMargin();
01130       Double_t yb = GetBottomMargin();
01131       Double_t yt = GetTopMargin();
01132       xl /= (1-xl+xr)*nx;
01133       xr /= (1-xl+xr)*nx;
01134       yb /= (1-yb+yt)*ny;
01135       yt /= (1-yb+yt)*ny;
01136       SetLeftMargin(xl);
01137       SetRightMargin(xr);
01138       SetBottomMargin(yb);
01139       SetTopMargin(yt);
01140       dx = (1-xl-xr)/nx;
01141       dy = (1-yb-yt)/ny;
01142       Int_t number = 0;
01143       for (Int_t i=0;i<nx;i++) {
01144          x1 = i*dx+xl;
01145          x2 = x1 + dx;
01146          if (i == 0) x1 = 0;
01147          if (i == nx-1) x2 = 1-xr;
01148          for (Int_t j=0;j<ny;j++) {
01149             number = j*nx + i +1;
01150             y2 = 1 -j*dy -yt;
01151             y1 = y2 - dy;
01152             if (j == 0)    y2 = 1-yt;
01153             if (j == ny-1) y1 = 0;
01154             snprintf(name,nchname,"%s_%d",GetName(),number);
01155             snprintf(title,nchtitle,"%s_%d",GetTitle(),number);
01156             pad = new TPad(name,title,x1,y1,x2,y2);
01157             pad->SetNumber(number);
01158             pad->SetBorderMode(0);
01159             if (i == 0)    pad->SetLeftMargin(xl*nx);
01160             else           pad->SetLeftMargin(0);
01161                            pad->SetRightMargin(0);
01162                            pad->SetTopMargin(0);
01163             if (j == ny-1) pad->SetBottomMargin(yb*ny);
01164             else           pad->SetBottomMargin(0);
01165             pad->Draw();
01166          }
01167       }
01168    }
01169    delete [] name;
01170    delete [] title;
01171    Modified();
01172    if (padsav) padsav->cd();
01173 }
01174 
01175 
01176 //______________________________________________________________________________
01177 void TPad::Draw(Option_t *option)
01178 {
01179    // Draw Pad in Current pad (re-parent pad if necessary).
01180 
01181    // if no canvas opened yet create a default canvas
01182    if (!gPad) {
01183       gROOT->MakeDefCanvas();
01184    }
01185 
01186    // pad cannot be in itself and it can only be in one other pad at a time
01187    if (!fPrimitives) fPrimitives = new TList;
01188    if (gPad != this) {
01189       if (fMother) fMother->GetListOfPrimitives()->Remove(this);
01190       TPad *oldMother = fMother;
01191       fCanvas = gPad->GetCanvas();
01192       //
01193       fMother = (TPad*)gPad;
01194       if (oldMother != fMother || fPixmapID == -1) ResizePad();
01195    }
01196 
01197    Paint();
01198 
01199    if (gPad->IsRetained() && gPad != this && fMother)
01200       fMother->GetListOfPrimitives()->Add(this, option);
01201 }
01202 
01203 
01204 //______________________________________________________________________________
01205 void TPad::DrawClassObject(const TObject *classobj, Option_t *option)
01206 {
01207    // Draw class inheritance tree of the class to which obj belongs.
01208    // If a class B inherits from a class A, description of B is drawn
01209    // on the right side of description of A.
01210    // Member functions overridden by B are shown in class A with a blue line
01211    // crossing-out the corresponding member function.
01212    // The following picture is the class inheritance tree of class TPaveLabel:
01213    //Begin_Html
01214    /*
01215    <img src="gif/drawclass.gif">
01216    */
01217    //End_Html
01218 
01219    char dname[256];
01220    const Int_t kMAXLEVELS = 10;
01221    TClass *clevel[kMAXLEVELS], *cl, *cll;
01222    TBaseClass *base, *cinherit;
01223    TText *ptext = 0;
01224    TString opt=option;
01225    Double_t x,y,dy,y1,v1,v2,dv;
01226    Int_t nd,nf,nc,nkd,nkf,i,j;
01227    TPaveText *pt;
01228    Int_t maxlev = 4;
01229    if (opt.Contains("2")) maxlev = 2;
01230    if (opt.Contains("3")) maxlev = 3;
01231    if (opt.Contains("5")) maxlev = 5;
01232    if (opt.Contains("6")) maxlev = 6;
01233    if (opt.Contains("7")) maxlev = 7;
01234 
01235       // Clear and Set Pad range
01236    Double_t xpad = 20.5;
01237    Double_t ypad = 27.5;
01238    Clear();
01239    Range(0,0,xpad,ypad);
01240 
01241    // Find number of levels
01242    Int_t nlevel = 0;
01243    TClass *obj = (TClass*)classobj;
01244    clevel[nlevel] = obj;
01245    TList *lbase = obj->GetListOfBases();
01246    while(lbase) {
01247       base = (TBaseClass*)lbase->First();
01248       if (!base) break;
01249       if ( base->GetClassPointer() == 0) break;
01250       nlevel++;
01251       clevel[nlevel] = base->GetClassPointer();
01252       lbase = clevel[nlevel]->GetListOfBases();
01253       if (nlevel >= maxlev-1) break;
01254    }
01255    Int_t maxelem = 0;
01256    Int_t ncdraw  = 0;
01257    Int_t ilevel, nelem;
01258    for (ilevel=nlevel;ilevel>=0;ilevel--) {
01259       cl = clevel[ilevel];
01260       nelem = cl->GetNdata() + cl->GetNmethods();
01261       if (nelem > maxelem) maxelem = nelem;
01262       nc = (nelem/50) + 1;
01263       ncdraw += nc;
01264    }
01265 
01266    Double_t tsizcm = 0.40;
01267    Double_t x1 = 0.25;
01268    Double_t x2 = 0;
01269    Double_t dx = 3.5;
01270    if (ncdraw > 4) {
01271       dx = dx - 0.42*Double_t(ncdraw-5);
01272       if (dx < 1.3) dx = 1.3;
01273       tsizcm = tsizcm - 0.03*Double_t(ncdraw-5);
01274       if (tsizcm < 0.27) tsizcm = 0.27;
01275    }
01276    Double_t tsiz = 1.2*tsizcm/ypad;
01277 
01278    // Now loop on levels
01279    for (ilevel=nlevel;ilevel>=0;ilevel--) {
01280       cl    = clevel[ilevel];
01281       nelem = cl->GetNdata() + cl->GetNmethods();
01282       if (nelem > maxelem) maxelem = nelem;
01283       nc    = (nelem/50) + 1;
01284       dy    = 0.45;
01285       if (ilevel < nlevel) x1 = x2 + 0.5;
01286       x2    = x1 + nc*dx;
01287       v2    = ypad - 0.5;
01288       lbase = cl->GetListOfBases();
01289       cinherit = 0;
01290       if (lbase) cinherit = (TBaseClass*)lbase->First();
01291 
01292       do {
01293          nd = cl->GetNdata();
01294          nf = cl->GetNmethods() - 2; //do not show default constructor and destructor
01295          if (cl->GetListOfMethods()->FindObject("Dictionary")) {
01296             nf -= 6;  // do not count the Dictionary/ClassDef functions
01297          }
01298          nkf= nf/nc +1;
01299          nkd= nd/nc +1;
01300          if (nd == 0) nkd=0;
01301          if (nf == 0) nkf=0;
01302          y1 = v2 - 0.7;
01303          v1 = y1 - Double_t(nkf+nkd+nc-1)*dy;
01304          dv = v2 - v1;
01305 
01306          // Create a new PaveText
01307          pt = new TPaveText(x1,v1,x2,v2);
01308          pt->SetBit(kCanDelete);
01309          pt->SetFillColor(19);
01310          pt->Draw();
01311          pt->SetTextColor(4);
01312          pt->SetTextFont(61);
01313          pt->SetTextAlign(12);
01314          pt->SetTextSize(tsiz);
01315          TBox *box = pt->AddBox(0,(y1+0.01-v1)/dv,0,(v2-0.01-v1)/dv);
01316          box->SetFillColor(17);
01317          pt->AddLine(0,(y1-v1)/dv,0,(y1-v1)/dv);
01318          TText *title = pt->AddText(0.5,(0.5*(y1+v2)-v1)/dv,(char*)cl->GetName());
01319          title->SetTextAlign(22);
01320          title->SetTextSize(0.6*(v2-y1)/ypad);
01321 
01322          // Draw data Members
01323          i = 0;
01324          x = 0.03;
01325          y = y1 + 0.5*dy;
01326          TDataMember *d;
01327          TIter        nextd(cl->GetListOfDataMembers());
01328          while ((d = (TDataMember *) nextd())) {
01329             if (i >= nkd) { i = 1; y = y1 - 0.5*dy; x += 1/Double_t(nc); }
01330             else { i++; y -= dy; }
01331 
01332             // Take in account the room the array index will occupy
01333 
01334             Int_t dim = d->GetArrayDim();
01335             Int_t indx = 0;
01336             snprintf(dname,256,"%s",obj->EscapeChars(d->GetName()));
01337             Int_t ldname = 0;
01338             while (indx < dim ){
01339                ldname = strlen(dname);
01340                snprintf(&dname[ldname],256,"[%d]",d->GetMaxIndex(indx));
01341                indx++;
01342             }
01343             pt->AddText(x,(y-v1)/dv,dname);
01344          }
01345 
01346          // Draw a separator line
01347          Double_t ysep;
01348          if (nd) {
01349             ysep = y1 - Double_t(nkd)*dy;
01350             pt->AddLine(0,(ysep-v1)/dv,0,(ysep-v1)/dv);
01351             ysep -= 0.5*dy;
01352          } else  ysep = y1;
01353 
01354          // Draw Member Functions
01355          Int_t fcount = 0;
01356          i = 0;
01357          x = 0.03;
01358          y = ysep + 0.5*dy;
01359          TMethod *m;
01360          TIter        nextm(cl->GetListOfMethods());
01361          while ((m = (TMethod *) nextm())) {
01362             if (
01363                !strcmp( m->GetName(), "Dictionary"    ) ||
01364                !strcmp( m->GetName(), "Class_Version" ) ||
01365                !strcmp( m->GetName(), "DeclFileName"  ) ||
01366                !strcmp( m->GetName(), "DeclFileLine"  ) ||
01367                !strcmp( m->GetName(), "ImplFileName"  ) ||
01368                !strcmp( m->GetName(), "ImplFileLine"  )
01369             ) continue;
01370             fcount++;
01371             if (fcount > nf) break;
01372             if (i >= nkf) { i = 1; y = ysep - 0.5*dy; x += 1/Double_t(nc); }
01373             else { i++; y -= dy; }
01374             ptext = pt->AddText(x,(y-v1)/dv,obj->EscapeChars(m->GetName()));
01375 
01376             // Check if method is overloaded in a derived class
01377             // If yes, Change the color of the text to blue
01378             for (j=ilevel-1;j>=0;j--) {
01379                if (cl == clevel[ilevel]) {
01380                   if (clevel[j]->GetMethodAny((char*)m->GetName())) {
01381                      ptext->SetTextColor(15);
01382                      break;
01383                   }
01384                }
01385             }
01386          }
01387 
01388          // Draw second inheritance classes for this class
01389          cll = 0;
01390          if (cinherit) {
01391             cinherit = (TBaseClass*)lbase->After(cinherit);
01392             if (cinherit) {
01393                cl  = cinherit->GetClassPointer();
01394                cll = cl;
01395                v2  = v1 -0.4;
01396                dy  = 0.35;
01397             }
01398          }
01399       } while (cll);
01400    }
01401    Update();
01402 }
01403 
01404 
01405 //______________________________________________________________________________
01406 void TPad::DrawCrosshair()
01407 {
01408    //Function called to draw a crosshair in the canvas
01409    //
01410    // Example:
01411    // Root > TFile f("hsimple.root");
01412    // Root > hpxpy.Draw();
01413    // Root > c1.SetCrosshair();
01414    // When moving the mouse in the canvas, a crosshair is drawn
01415    //
01416    // if the canvas fCrosshair = 1 , the crosshair spans the full canvas
01417    // if the canvas fCrosshair > 1 , the crosshair spans only the pad
01418 
01419    if (gPad->GetEvent() == kMouseEnter) return;
01420 
01421    TPad *cpad = (TPad*)gPad;
01422    TCanvas *canvas = cpad->GetCanvas();
01423    canvas->FeedbackMode(kTRUE);
01424 
01425    //erase old position and draw a line at current position
01426    Int_t pxmin,pxmax,pymin,pymax,pxold,pyold,px,py;
01427    pxold = fCrosshairPos%10000;
01428    pyold = fCrosshairPos/10000;
01429    px    = cpad->GetEventX();
01430    py    = cpad->GetEventY()+1;
01431    if (canvas->GetCrosshair() > 1) {  //crosshair only in the current pad
01432       pxmin = cpad->XtoAbsPixel(fX1);
01433       pxmax = cpad->XtoAbsPixel(fX2);
01434       pymin = cpad->YtoAbsPixel(fY1);
01435       pymax = cpad->YtoAbsPixel(fY2);
01436    } else { //default; crosshair spans the full canvas
01437       pxmin = 0;
01438       pxmax = canvas->GetWw();
01439       pymin = 0;
01440       pymax = cpad->GetWh();
01441    }
01442    if(pxold) gVirtualX->DrawLine(pxold,pymin,pxold,pymax);
01443    if(pyold) gVirtualX->DrawLine(pxmin,pyold,pxmax,pyold);
01444    if (cpad->GetEvent() == kButton1Down ||
01445        cpad->GetEvent() == kButton1Up   ||
01446        cpad->GetEvent() == kMouseLeave) {
01447       fCrosshairPos = 0;
01448       return;
01449    }
01450    gVirtualX->DrawLine(px,pymin,px,pymax);
01451    gVirtualX->DrawLine(pxmin,py,pxmax,py);
01452    fCrosshairPos = px + 10000*py;
01453 }
01454 
01455 
01456 //______________________________________________________________________________
01457 TH1F *TPad::DrawFrame(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, const char *title)
01458 {
01459    //  Draw a pad frame
01460    //
01461    //  Compute real pad range taking into account all margins
01462    //  Use services of TH1F class
01463    if (!IsEditable()) return 0;
01464    TPad *padsav = (TPad*)gPad;
01465    if (this !=  padsav) {
01466       Warning("DrawFrame","Drawframe must be called for the current pad only");
01467       return padsav->DrawFrame(xmin,ymin,xmax,ymax,title);
01468    }
01469 
01470    cd();
01471 
01472    TH1F *hframe = (TH1F*)FindObject("hframe");
01473    if (hframe) delete hframe;
01474    Int_t nbins = 1000;
01475    //if log scale in X, use variable bin size linear with log(x)
01476    //this gives a better precision when zooming on the axis
01477    if (fLogx && xmin > 0 && xmax > xmin) {
01478       Double_t xminl = TMath::Log(xmin);
01479       Double_t xmaxl = TMath::Log(xmax);
01480       Double_t dx = (xmaxl-xminl)/nbins;
01481       Double_t *xbins = new Double_t[nbins+1];
01482       xbins[0] = xmin;
01483       for (Int_t i=1;i<=nbins;i++) {
01484          xbins[i] = TMath::Exp(xminl+i*dx);
01485       }
01486       hframe = new TH1F("hframe",title,nbins,xbins);
01487       delete [] xbins;
01488    } else {
01489       hframe = new TH1F("hframe",title,nbins,xmin,xmax);
01490    }
01491    hframe->SetBit(TH1::kNoStats);
01492    hframe->SetBit(kCanDelete);
01493    hframe->SetMinimum(ymin);
01494    hframe->SetMaximum(ymax);
01495    hframe->GetYaxis()->SetLimits(ymin,ymax);
01496    hframe->SetDirectory(0);
01497    hframe->Draw(" ");
01498    Update();
01499    if (padsav) padsav->cd();
01500    return hframe;
01501 }
01502 
01503 //______________________________________________________________________________
01504 void TPad::DrawColorTable()
01505 {
01506    // Static function to Display Color Table in a pad.
01507 
01508    Int_t i, j;
01509    Int_t color;
01510    Double_t xlow, ylow, xup, yup, hs, ws;
01511    Double_t x1, y1, x2, y2;
01512    x1 = y1 = 0;
01513    x2 = y2 = 20;
01514 
01515    gPad->SetFillColor(0);
01516    gPad->Clear();
01517    gPad->Range(x1,y1,x2,y2);
01518 
01519    TText *text = new TText(0,0,"");
01520    text->SetTextFont(61);
01521    text->SetTextSize(0.07);
01522    text->SetTextAlign(22);
01523 
01524    TBox *box = new TBox();
01525 
01526    // Draw color table boxes.
01527    hs = (y2-y1)/Double_t(5);
01528    ws = (x2-x1)/Double_t(10);
01529    for (i=0;i<10;i++) {
01530       xlow = x1 + ws*(Double_t(i)+0.1);
01531       xup  = x1 + ws*(Double_t(i)+0.9);
01532       for (j=0;j<5;j++) {
01533          ylow = y1 + hs*(Double_t(j)+0.1);
01534          yup  = y1 + hs*(Double_t(j)+0.9);
01535          color = 10*j + i;
01536          box->SetFillStyle(1001);
01537          box->SetFillColor(color);
01538          box->DrawBox(xlow, ylow, xup, yup);
01539          box->SetFillStyle(0);
01540          box->SetLineColor(1);
01541          box->DrawBox(xlow, ylow, xup, yup);
01542          if (color == 1) text->SetTextColor(0);
01543          else            text->SetTextColor(1);
01544          text->DrawText(0.5*(xlow+xup), 0.5*(ylow+yup), Form("%d",color));
01545       }
01546    }
01547 }
01548 
01549 
01550 //______________________________________________________________________________
01551 void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py)
01552 {
01553    // Execute action corresponding to one event.
01554    //
01555    //  This member function is called when a TPad object is clicked.
01556    //
01557    //  If the mouse is clicked in one of the 4 corners of the pad (pA,pB,pC,pD)
01558    //  the pad is resized with the rubber rectangle.
01559    //
01560    //  If the mouse is clicked inside the pad, the pad is moved.
01561    //
01562    //  If the mouse is clicked on the 4 edges (pL,pR,pTop,pBot), the pad is scaled
01563    //  parallel to this edge.
01564    //
01565    //    pA                   pTop                     pB
01566    //     +--------------------------------------------+
01567    //     |                                            |
01568    //     |                                            |
01569    //     |                                            |
01570    //   pL|                 pINSIDE                    |pR
01571    //     |                                            |
01572    //     |                                            |
01573    //     |                                            |
01574    //     |                                            |
01575    //     +--------------------------------------------+
01576    //    pD                   pBot                     pC
01577    //
01578    //
01579    //  Note that this function duplicates on purpose the functionality
01580    //  already implemented in TBox::ExecuteEvent.
01581    //  If somebody modifies this function, may be similar changes should also
01582    //  be applied to TBox::ExecuteEvent.
01583 
01584    static Double_t xmin;
01585    static Double_t xmax;
01586    static Double_t ymin;
01587    static Double_t ymax;
01588 
01589    const Int_t kMaxDiff = 5;
01590    const Int_t kMinSize = 20;
01591    static Int_t pxorg, pyorg;
01592    static Int_t px1, px2, py1, py2, pxl, pyl, pxt, pyt, pxold, pyold;
01593    static Int_t px1p, px2p, py1p, py2p, pxlp, pylp, pxtp, pytp;
01594    static Bool_t pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE;
01595    Int_t  wx, wy;
01596    Bool_t opaque  = OpaqueMoving();
01597    Bool_t ropaque = OpaqueResizing();
01598    Bool_t fixedr  = HasFixedAspectRatio();
01599 
01600    if (!IsEditable() && event != kMouseEnter) return;
01601    TVirtualPad  *parent = GetMother();
01602    if (!parent->IsEditable()) return;
01603 
01604    HideToolTip(event);
01605 
01606    if (fXlowNDC < 0 && event != kButton1Down) return;
01607    if (fYlowNDC < 0 && event != kButton1Down) return;
01608 
01609    // keep old range and mouse position
01610    if (event == kButton1Down) {
01611       xmin = fX1;
01612       xmax = fX2;
01613       ymin = fY1;
01614       ymax = fY2;
01615 
01616       pxorg = px;
01617       pyorg = py;
01618    }
01619 
01620    Int_t newcode = gROOT->GetEditorMode();
01621    if (newcode)
01622       pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE;
01623    switch (newcode) {
01624       case kPad:
01625          TCreatePrimitives::Pad(event,px,py,0);
01626          break;
01627       case kMarker:
01628       case kText:
01629          TCreatePrimitives::Text(event,px,py,newcode);
01630          break;
01631       case kLine:
01632          TCreatePrimitives::Line(event,px,py,kLine);
01633          break;
01634       case kArrow:
01635          TCreatePrimitives::Line(event,px,py,kArrow);
01636          break;
01637       case kCurlyLine:
01638          TCreatePrimitives::Line(event,px,py,kCurlyLine);
01639          break;
01640       case kCurlyArc:
01641          TCreatePrimitives::Line(event,px,py,kCurlyArc);
01642          break;
01643       case kPolyLine:
01644          TCreatePrimitives::PolyLine(event,px,py,kPolyLine);
01645          break;
01646       case kCutG:
01647          TCreatePrimitives::PolyLine(event,px,py,kCutG);
01648          break;
01649       case kArc:
01650          TCreatePrimitives::Ellipse(event,px,py,kArc);
01651          break;
01652       case kEllipse:
01653          TCreatePrimitives::Ellipse(event,px,py,kEllipse);
01654          break;
01655       case kButton:
01656       case kPave:
01657       case kPaveLabel:
01658       case kPaveText:
01659       case kPavesText:
01660       case kDiamond:
01661          TCreatePrimitives::Pave(event,px,py,newcode);
01662          return;
01663       default:
01664          break;
01665       }
01666       if (newcode) return;
01667 
01668    Bool_t doing_again = kFALSE;
01669 again:
01670 
01671    switch (event) {
01672 
01673    case kMouseEnter:
01674       if (fTip)
01675          ResetToolTip(fTip);
01676       break;
01677 
01678    case kButton1Down:
01679 
01680 #ifdef WIN32
01681       Pop(); //this should be for cases where mouse has only two buttons
01682 #endif
01683       GetPainter()->SetLineColor(-1);
01684       TAttLine::Modify();  //Change line attributes only if necessary
01685       if (GetFillColor())
01686          GetPainter()->SetLineColor(GetFillColor());
01687       else
01688          GetPainter()->SetLineColor(1);
01689       GetPainter()->SetLineWidth(2);
01690 
01691       // No break !!!
01692 
01693    case kMouseMotion:
01694 
01695       px1 = XtoAbsPixel(fX1);
01696       py1 = YtoAbsPixel(fY1);
01697       px2 = XtoAbsPixel(fX2);
01698       py2 = YtoAbsPixel(fY2);
01699 
01700       if (px1 < px2) {
01701          pxl = px1;
01702          pxt = px2;
01703       } else {
01704          pxl = px2;
01705          pxt = px1;
01706       }
01707       if (py1 < py2) {
01708          pyl = py1;
01709          pyt = py2;
01710       } else {
01711          pyl = py2;
01712          pyt = py1;
01713       }
01714 
01715       px1p = parent->XtoAbsPixel(parent->GetX1()) + parent->GetBorderSize();
01716       py1p = parent->YtoAbsPixel(parent->GetY1()) - parent->GetBorderSize();
01717       px2p = parent->XtoAbsPixel(parent->GetX2()) - parent->GetBorderSize();
01718       py2p = parent->YtoAbsPixel(parent->GetY2()) + parent->GetBorderSize();
01719 
01720       if (px1p < px2p) {
01721          pxlp = px1p;
01722          pxtp = px2p;
01723       } else {
01724          pxlp = px2p;
01725          pxtp = px1p;
01726       }
01727       if (py1p < py2p) {
01728          pylp = py1p;
01729          pytp = py2p;
01730       } else {
01731          pylp = py2p;
01732          pytp = py1p;
01733       }
01734 
01735       pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE;
01736 
01737                                                          // case pA
01738       if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) {
01739          pxold = pxl; pyold = pyl; pA = kTRUE;
01740          SetCursor(kTopLeft);
01741       }
01742                                                          // case pB
01743       if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) {
01744          pxold = pxt; pyold = pyl; pB = kTRUE;
01745          SetCursor(kTopRight);
01746       }
01747                                                          // case pC
01748       if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) {
01749          pxold = pxt; pyold = pyt; pC = kTRUE;
01750          SetCursor(kBottomRight);
01751       }
01752                                                          // case pD
01753       if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) {
01754          pxold = pxl; pyold = pyt; pD = kTRUE;
01755          SetCursor(kBottomLeft);
01756       }
01757 
01758       if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
01759           TMath::Abs(py - pyl) < kMaxDiff) {             // top edge
01760          pxold = pxl; pyold = pyl; pTop = kTRUE;
01761          SetCursor(kTopSide);
01762       }
01763 
01764       if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
01765           TMath::Abs(py - pyt) < kMaxDiff) {             // bottom edge
01766          pxold = pxt; pyold = pyt; pBot = kTRUE;
01767          SetCursor(kBottomSide);
01768       }
01769 
01770       if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) &&
01771           TMath::Abs(px - pxl) < kMaxDiff) {             // left edge
01772          pxold = pxl; pyold = pyl; pL = kTRUE;
01773          SetCursor(kLeftSide);
01774       }
01775 
01776       if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) &&
01777          TMath::Abs(px - pxt) < kMaxDiff) {             // right edge
01778          pxold = pxt; pyold = pyt; pR = kTRUE;
01779          SetCursor(kRightSide);
01780       }
01781 
01782       if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
01783           (py > pyl+kMaxDiff && py < pyt-kMaxDiff)) {    // inside box
01784          pxold = px; pyold = py; pINSIDE = kTRUE;
01785          if (event == kButton1Down)
01786             SetCursor(kMove);
01787          else
01788             SetCursor(kCross);
01789       }
01790 
01791       fResizing = kFALSE;
01792       if (pA || pB || pC || pD || pTop || pL || pR || pBot)
01793          fResizing = kTRUE;
01794 
01795       if (!pA && !pB && !pC && !pD && !pTop && !pL && !pR && !pBot && !pINSIDE)
01796          SetCursor(kCross);
01797 
01798       break;
01799 
01800    case kButton1Motion:
01801 
01802       if (TestBit(kCannotMove)) break;
01803       wx = wy = 0;
01804 
01805       if (pA) {
01806          if (!ropaque) gVirtualX->DrawBox(pxold, pyt, pxt, pyold, TVirtualX::kHollow);
01807          if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; }
01808          if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; }
01809          if (px < pxlp) { px = pxlp; wx = px; }
01810          if (py < pylp) { py = pylp; wy = py; }
01811          if (fixedr) {
01812             Double_t dy = Double_t(TMath::Abs(pxt-px))/parent->UtoPixel(1.) /
01813                           fAspectRatio;
01814             Int_t npy2 = pyt - TMath::Abs(parent->VtoAbsPixel(dy) -
01815                                           parent->VtoAbsPixel(0));
01816             if (npy2 < pylp) {
01817                px = pxold;
01818                py = pyold;
01819             } else
01820                py = npy2;
01821 
01822             wx = wy = 0;
01823          }
01824          if (!ropaque) gVirtualX->DrawBox(px, pyt, pxt, py, TVirtualX::kHollow);
01825       }
01826       if (pB) {
01827          if (!ropaque) gVirtualX->DrawBox(pxl  , pyt, pxold, pyold, TVirtualX::kHollow);
01828          if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; }
01829          if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; }
01830          if (px > pxtp) { px = pxtp; wx = px; }
01831          if (py < pylp) { py = pylp; wy = py; }
01832          if (fixedr) {
01833             Double_t dy = Double_t(TMath::Abs(pxl-px))/parent->UtoPixel(1.) /
01834                           fAspectRatio;
01835             Int_t npy2 = pyt - TMath::Abs(parent->VtoAbsPixel(dy) -
01836                                           parent->VtoAbsPixel(0));
01837             if (npy2 < pylp) {
01838                px = pxold;
01839                py = pyold;
01840             } else
01841                py = npy2;
01842 
01843             wx = wy = 0;
01844          }
01845          if (!ropaque) gVirtualX->DrawBox(pxl  , pyt, px ,  py,    TVirtualX::kHollow);
01846       }
01847       if (pC) {
01848          if (!ropaque) gVirtualX->DrawBox(pxl  , pyl, pxold, pyold, TVirtualX::kHollow);
01849          if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; }
01850          if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; }
01851          if (px > pxtp) { px = pxtp; wx = px; }
01852          if (py > pytp) { py = pytp; wy = py; }
01853          if (fixedr) {
01854             Double_t dy = Double_t(TMath::Abs(pxl-px))/parent->UtoPixel(1.) /
01855                           fAspectRatio;
01856             Int_t npy2 = pyl + TMath::Abs(parent->VtoAbsPixel(dy) -
01857                                           parent->VtoAbsPixel(0));
01858             if (npy2 > pytp) {
01859                px = pxold;
01860                py = pyold;
01861             } else
01862                py = npy2;
01863 
01864             wx = wy = 0;
01865          }
01866          if (!ropaque) gVirtualX->DrawBox(pxl, pyl, px, py, TVirtualX::kHollow);
01867       }
01868       if (pD) {
01869          if (!ropaque) gVirtualX->DrawBox(pxold, pyold, pxt, pyl, TVirtualX::kHollow);
01870          if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; }
01871          if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; }
01872          if (px < pxlp) { px = pxlp; wx = px; }
01873          if (py > pytp) { py = pytp; wy = py; }
01874          if (fixedr) {
01875             Double_t dy = Double_t(TMath::Abs(pxt-px))/parent->UtoPixel(1.) /
01876                           fAspectRatio;
01877             Int_t npy2 = pyl + TMath::Abs(parent->VtoAbsPixel(dy) -
01878                                           parent->VtoAbsPixel(0));
01879             if (npy2 > pytp) {
01880                px = pxold;
01881                py = pyold;
01882             } else
01883                py = npy2;
01884 
01885             wx = wy = 0;
01886          }
01887          if (!ropaque) gVirtualX->DrawBox(px, py, pxt, pyl, TVirtualX::kHollow);
01888       }
01889       if (pTop) {
01890          if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
01891          py2 += py - pyold;
01892          if (py2 > py1-kMinSize) { py2 = py1-kMinSize; wy = py2; }
01893          if (py2 < py2p) { py2 = py2p; wy = py2; }
01894          if (fixedr) {
01895             Double_t dx = Double_t(TMath::Abs(py2-py1))/parent->VtoPixel(0) *
01896                           fAspectRatio;
01897             Int_t npx2 = px1 + parent->UtoPixel(dx);
01898             if (npx2 > px2p)
01899                py2 -= py - pyold;
01900             else
01901                px2 = npx2;
01902          }
01903          if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
01904       }
01905       if (pBot) {
01906          if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
01907          py1 += py - pyold;
01908          if (py1 < py2+kMinSize) { py1 = py2+kMinSize; wy = py1; }
01909          if (py1 > py1p) { py1 = py1p; wy = py1; }
01910          if (fixedr) {
01911             Double_t dx = Double_t(TMath::Abs(py2-py1))/parent->VtoPixel(0) *
01912                           fAspectRatio;
01913             Int_t npx2 = px1 + parent->UtoPixel(dx);
01914             if (npx2 > px2p)
01915                py1 -= py - pyold;
01916             else
01917                px2 = npx2;
01918          }
01919          if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
01920       }
01921       if (pL) {
01922          if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
01923          px1 += px - pxold;
01924          if (px1 > px2-kMinSize) { px1 = px2-kMinSize; wx = px1; }
01925          if (px1 < px1p) { px1 = px1p; wx = px1; }
01926          if (fixedr) {
01927             Double_t dy = Double_t(TMath::Abs(px2-px1))/parent->UtoPixel(1.) /
01928                           fAspectRatio;
01929             Int_t npy2 = py1 - TMath::Abs(parent->VtoAbsPixel(dy) -
01930                                           parent->VtoAbsPixel(0));
01931             if (npy2 < py2p)
01932                px1 -= px - pxold;
01933             else
01934                py2 = npy2;
01935          }
01936          if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
01937       }
01938       if (pR) {
01939          if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
01940          px2 += px - pxold;
01941          if (px2 < px1+kMinSize) { px2 = px1+kMinSize; wx = px2; }
01942          if (px2 > px2p) { px2 = px2p; wx = px2; }
01943          if (fixedr) {
01944             Double_t dy = Double_t(TMath::Abs(px2-px1))/parent->UtoPixel(1.) /
01945                           fAspectRatio;
01946             Int_t npy2 = py1 - TMath::Abs(parent->VtoAbsPixel(dy) -
01947                                           parent->VtoAbsPixel(0));
01948             if (npy2 < py2p)
01949                px2 -= px - pxold;
01950             else
01951                py2 = npy2;
01952          }
01953          if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
01954       }
01955       if (pINSIDE) {
01956          if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);  // draw the old box
01957          Int_t dx = px - pxold;
01958          Int_t dy = py - pyold;
01959          px1 += dx; py1 += dy; px2 += dx; py2 += dy;
01960          if (px1 < px1p) { dx = px1p - px1; px1 += dx; px2 += dx; wx = px+dx; }
01961          if (px2 > px2p) { dx = px2 - px2p; px1 -= dx; px2 -= dx; wx = px-dx; }
01962          if (py1 > py1p) { dy = py1 - py1p; py1 -= dy; py2 -= dy; wy = py-dy; }
01963          if (py2 < py2p) { dy = py2p - py2; py1 += dy; py2 += dy; wy = py+dy; }
01964          if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);  // draw the new box
01965       }
01966 
01967       if (wx || wy) {
01968          if (wx) px = wx;
01969          if (wy) py = wy;
01970          gVirtualX->Warp(px, py);
01971       }
01972 
01973       pxold = px;
01974       pyold = py;
01975 
01976       if ((!fResizing && opaque) || (fResizing && ropaque)) {
01977          event = kButton1Up;
01978          doing_again = kTRUE;
01979          goto again;
01980       }
01981 
01982       break;
01983 
01984    case kButton1Up:
01985       if (gROOT->IsEscaped()) {
01986          gROOT->SetEscape(kFALSE);
01987          break;
01988       }
01989 
01990       if (pA) {
01991          fX1 = AbsPixeltoX(pxold);
01992          fY1 = AbsPixeltoY(pyt);
01993          fX2 = AbsPixeltoX(pxt);
01994          fY2 = AbsPixeltoY(pyold);
01995       }
01996       if (pB) {
01997          fX1 = AbsPixeltoX(pxl);
01998          fY1 = AbsPixeltoY(pyt);
01999          fX2 = AbsPixeltoX(pxold);
02000          fY2 = AbsPixeltoY(pyold);
02001       }
02002       if (pC) {
02003          fX1 = AbsPixeltoX(pxl);
02004          fY1 = AbsPixeltoY(pyold);
02005          fX2 = AbsPixeltoX(pxold);
02006          fY2 = AbsPixeltoY(pyl);
02007       }
02008       if (pD) {
02009          fX1 = AbsPixeltoX(pxold);
02010          fY1 = AbsPixeltoY(pyold);
02011          fX2 = AbsPixeltoX(pxt);
02012          fY2 = AbsPixeltoY(pyl);
02013       }
02014       if (pTop || pBot || pL || pR || pINSIDE) {
02015          fX1 = AbsPixeltoX(px1);
02016          fY1 = AbsPixeltoY(py1);
02017          fX2 = AbsPixeltoX(px2);
02018          fY2 = AbsPixeltoY(py2);
02019       }
02020 
02021       if (pINSIDE)
02022          if (!doing_again) gPad->SetCursor(kCross);
02023 
02024       if (pA || pB || pC || pD || pTop || pL || pR || pBot)
02025          Modified(kTRUE);
02026 
02027       gVirtualX->SetLineColor(-1);
02028       gVirtualX->SetLineWidth(-1);
02029 
02030       if (px != pxorg || py != pyorg) {
02031 
02032          // Get parent corners pixels coordinates
02033          Int_t parentpx1 = fMother->XtoAbsPixel(parent->GetX1());
02034          Int_t parentpx2 = fMother->XtoAbsPixel(parent->GetX2());
02035          Int_t parentpy1 = fMother->YtoAbsPixel(parent->GetY1());
02036          Int_t parentpy2 = fMother->YtoAbsPixel(parent->GetY2());
02037 
02038          // Get pad new corners pixels coordinates
02039          Int_t apx1 = XtoAbsPixel(fX1); if (apx1 < parentpx1) {apx1 = parentpx1; }
02040          Int_t apx2 = XtoAbsPixel(fX2); if (apx2 > parentpx2) {apx2 = parentpx2; }
02041          Int_t apy1 = YtoAbsPixel(fY1); if (apy1 > parentpy1) {apy1 = parentpy1; }
02042          Int_t apy2 = YtoAbsPixel(fY2); if (apy2 < parentpy2) {apy2 = parentpy2; }
02043 
02044          // Compute new pad positions in the NDC space of parent
02045          fXlowNDC = Double_t(apx1 - parentpx1)/Double_t(parentpx2 - parentpx1);
02046          fYlowNDC = Double_t(apy1 - parentpy1)/Double_t(parentpy2 - parentpy1);
02047          fWNDC    = Double_t(apx2 - apx1)/Double_t(parentpx2 - parentpx1);
02048          fHNDC    = Double_t(apy2 - apy1)/Double_t(parentpy2 - parentpy1);
02049       }
02050 
02051       // Restore old range
02052       fX1 = xmin;
02053       fX2 = xmax;
02054       fY1 = ymin;
02055       fY2 = ymax;
02056 
02057       // Reset pad parameters and recompute conversion coefficients
02058       ResizePad();
02059 
02060       // emit signal
02061       RangeChanged();
02062 
02063       break;
02064 
02065    case kButton1Locate:
02066 
02067       ExecuteEvent(kButton1Down, px, py);
02068 
02069       while (1) {
02070          px = py = 0;
02071          event = gVirtualX->RequestLocator(1, 1, px, py);
02072 
02073          ExecuteEvent(kButton1Motion, px, py);
02074 
02075          if (event != -1) {                     // button is released
02076             ExecuteEvent(kButton1Up, px, py);
02077             return;
02078          }
02079       }
02080 
02081    case kButton2Down:
02082 
02083       Pop();
02084       break;
02085 
02086    }
02087 }
02088 
02089 
02090 //______________________________________________________________________________
02091 void TPad::ExecuteEventAxis(Int_t event, Int_t px, Int_t py, TAxis *axis)
02092 {
02093    // Execute action corresponding to one event for a TAxis object
02094    // (called by TAxis::ExecuteEvent.)
02095    //  This member function is called when an axis is clicked with the locator
02096    //
02097    //  The axis range is set between the position where the mouse is pressed
02098    //  and the position where it is released.
02099    //  If the mouse position is outside the current axis range when it is released
02100    //  the axis is unzoomed with the corresponding proportions.
02101    //  Note that the mouse does not need to be in the pad or even canvas
02102    //  when it is released.
02103 
02104    if (!IsEditable()) return;
02105 
02106    SetCursor(kHand);
02107 
02108    TView *view = GetView();
02109    static Int_t axisNumber;
02110    static Double_t ratio1, ratio2;
02111    static Int_t px1old, py1old, px2old, py2old;
02112    Int_t bin1, bin2, first, last;
02113    Double_t temp, xmin,xmax;
02114 
02115    // The CONT4 option, used to paint TH2, is a special case; it uses a 3D
02116    // drawing technique to paint a 2D plot.
02117    TString opt = axis->GetParent()->GetDrawOption();
02118    opt.ToLower();
02119    Bool_t kCont4 = kFALSE;
02120    if (strstr(opt,"cont4")) {
02121       view = 0;
02122       kCont4 = kTRUE;
02123    }
02124 
02125    switch (event) {
02126 
02127    case kButton1Down:
02128       axisNumber = 1;
02129       if (!strcmp(axis->GetName(),"xaxis")) {
02130          axisNumber = 1;
02131          if (!IsVertical()) axisNumber = 2;
02132       }
02133       if (!strcmp(axis->GetName(),"yaxis")) {
02134          axisNumber = 2;
02135          if (!IsVertical()) axisNumber = 1;
02136       }
02137       if (!strcmp(axis->GetName(),"zaxis")) {
02138          axisNumber = 3;
02139       }
02140       if (view) {
02141          view->GetDistancetoAxis(axisNumber, px, py, ratio1);
02142       } else {
02143          if (axisNumber == 1) {
02144             ratio1 = (AbsPixeltoX(px) - GetUxmin())/(GetUxmax() - GetUxmin());
02145             px1old = XtoAbsPixel(GetUxmin()+ratio1*(GetUxmax() - GetUxmin()));
02146             py1old = YtoAbsPixel(GetUymin());
02147             px2old = px1old;
02148             py2old = YtoAbsPixel(GetUymax());
02149          } else if (axisNumber == 2) {
02150             ratio1 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
02151             py1old = YtoAbsPixel(GetUymin()+ratio1*(GetUymax() - GetUymin()));
02152             px1old = XtoAbsPixel(GetUxmin());
02153             px2old = XtoAbsPixel(GetUxmax());
02154             py2old = py1old;
02155          } else {
02156             ratio1 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
02157             py1old = YtoAbsPixel(GetUymin()+ratio1*(GetUymax() - GetUymin()));
02158             px1old = XtoAbsPixel(GetUxmax());
02159             px2old = XtoAbsPixel(GetX2());
02160             py2old = py1old;
02161          }
02162          gVirtualX->DrawBox(px1old, py1old, px2old, py2old, TVirtualX::kHollow);
02163       }
02164       gVirtualX->SetLineColor(-1);
02165       // No break !!!
02166 
02167    case kButton1Motion:
02168       if (view) {
02169          view->GetDistancetoAxis(axisNumber, px, py, ratio2);
02170       } else {
02171          gVirtualX->DrawBox(px1old, py1old, px2old, py2old, TVirtualX::kHollow);
02172          if (axisNumber == 1) {
02173             ratio2 = (AbsPixeltoX(px) - GetUxmin())/(GetUxmax() - GetUxmin());
02174             px2old = XtoAbsPixel(GetUxmin()+ratio2*(GetUxmax() - GetUxmin()));
02175          } else {
02176             ratio2 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
02177             py2old = YtoAbsPixel(GetUymin()+ratio2*(GetUymax() - GetUymin()));
02178          }
02179          gVirtualX->DrawBox(px1old, py1old, px2old, py2old, TVirtualX::kHollow);
02180       }
02181    break;
02182 
02183    case kWheelUp:
02184       bin1 = axis->GetFirst()+1;
02185       bin2 = axis->GetLast()-1;
02186       axis->SetRange(bin1,bin2);
02187       gPad->Modified();
02188       gPad->Update();
02189    break;
02190 
02191    case kWheelDown:
02192       bin1 = axis->GetFirst()-1;
02193       bin2 = axis->GetLast()+1;
02194       axis->SetRange(bin1,bin2);
02195       gPad->Modified();
02196       gPad->Update();
02197    break;
02198 
02199    case kButton1Up:
02200       if (gROOT->IsEscaped()) {
02201          gROOT->SetEscape(kFALSE);
02202          break;
02203       }
02204 
02205       if (view) {
02206          view->GetDistancetoAxis(axisNumber, px, py, ratio2);
02207          if (ratio1 > ratio2) {
02208             temp   = ratio1;
02209             ratio1 = ratio2;
02210             ratio2 = temp;
02211          }
02212          if (ratio2 - ratio1 > 0.05) {
02213             TH1 *hobj = (TH1*)axis->GetParent();
02214             if (axisNumber == 3 && hobj && hobj->GetDimension() != 3) {
02215                Float_t zmin = hobj->GetMinimum();
02216                Float_t zmax = hobj->GetMaximum();
02217                if(GetLogz()){
02218                   if (zmin <= 0 && zmax > 0) zmin = TMath::Min((Double_t)1,
02219                                                                (Double_t)0.001*zmax);
02220                   zmin = TMath::Log10(zmin);
02221                   zmax = TMath::Log10(zmax);
02222                }
02223                Float_t newmin = zmin + (zmax-zmin)*ratio1;
02224                Float_t newmax = zmin + (zmax-zmin)*ratio2;
02225                if(newmin < zmin)newmin = hobj->GetBinContent(hobj->GetMinimumBin());
02226                if(newmax > zmax)newmax = hobj->GetBinContent(hobj->GetMaximumBin());
02227                if(GetLogz()){
02228                   newmin = TMath::Exp(2.302585092994*newmin);
02229                   newmax = TMath::Exp(2.302585092994*newmax);
02230                }
02231                hobj->SetMinimum(newmin);
02232                hobj->SetMaximum(newmax);
02233                hobj->SetBit(TH1::kIsZoomed);
02234             } else {
02235                first = axis->GetFirst();
02236                last  = axis->GetLast();
02237                bin1 = first + Int_t((last-first+1)*ratio1);
02238                bin2 = first + Int_t((last-first+1)*ratio2);
02239                axis->SetRange(bin1, bin2);
02240             }
02241             delete view;
02242             SetView(0);
02243             Modified(kTRUE);
02244          }
02245       } else {
02246          if (axisNumber == 1) {
02247             ratio2 = (AbsPixeltoX(px) - GetUxmin())/(GetUxmax() - GetUxmin());
02248             xmin = GetUxmin() +ratio1*(GetUxmax() - GetUxmin());
02249             xmax = GetUxmin() +ratio2*(GetUxmax() - GetUxmin());
02250             if (GetLogx() && !kCont4) {
02251                xmin = PadtoX(xmin);
02252                xmax = PadtoX(xmax);
02253             }
02254          } else if (axisNumber == 2) {
02255             ratio2 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
02256             xmin = GetUymin() +ratio1*(GetUymax() - GetUymin());
02257             xmax = GetUymin() +ratio2*(GetUymax() - GetUymin());
02258             if (GetLogy() && !kCont4) {
02259                xmin = PadtoY(xmin);
02260                xmax = PadtoY(xmax);
02261             }
02262          } else {
02263             ratio2 = (AbsPixeltoY(py) - GetUymin())/(GetUymax() - GetUymin());
02264             xmin = ratio1;
02265             xmax = ratio2;
02266          }
02267          if (xmin > xmax) {
02268             temp   = xmin;
02269             xmin   = xmax;
02270             xmax   = temp;
02271             temp   = ratio1;
02272             ratio1 = ratio2;
02273             ratio2 = temp;
02274          }
02275 
02276          // xmin and xmax need to be adjusted in case of CONT4.
02277          if (kCont4) {
02278             Double_t low = axis->GetBinLowEdge(axis->GetFirst());
02279             Double_t up  = axis->GetBinUpEdge(axis->GetLast());
02280             Double_t xmi = GetUxmin();
02281             Double_t xma = GetUxmax();
02282             xmin = ((xmin-xmi)/(xma-xmi))*(up-low)+low;
02283             xmax = ((xmax-xmi)/(xma-xmi))*(up-low)+low;
02284          }
02285 
02286          if (!strcmp(axis->GetName(),"xaxis")) axisNumber = 1;
02287          if (!strcmp(axis->GetName(),"yaxis")) axisNumber = 2;
02288          if (ratio2 - ratio1 > 0.05) {
02289             //update object owning this axis
02290             TH1 *hobj1 = (TH1*)axis->GetParent();
02291             bin1 = axis->FindFixBin(xmin);
02292             bin2 = axis->FindFixBin(xmax);
02293             if (axisNumber == 1) axis->SetRange(bin1,bin2);
02294             if (axisNumber == 2 && hobj1) {
02295                if (hobj1->GetDimension() == 1) {
02296                   if (hobj1->GetNormFactor() != 0) {
02297                      Double_t norm = hobj1->GetSumOfWeights()/hobj1->GetNormFactor();
02298                      xmin *= norm;
02299                      xmax *= norm;
02300                   }
02301                   hobj1->SetMinimum(xmin);
02302                   hobj1->SetMaximum(xmax);
02303                   hobj1->SetBit(TH1::kIsZoomed);
02304                } else {
02305                   axis->SetRange(bin1,bin2);
02306                }
02307             }
02308             //update all histograms in the pad
02309             TIter next(GetListOfPrimitives());
02310             TObject *obj;
02311             while ((obj= next())) {
02312                if (!obj->InheritsFrom(TH1::Class())) continue;
02313                TH1 *hobj = (TH1*)obj;
02314                if (hobj == hobj1) continue;
02315                bin1 = hobj->GetXaxis()->FindFixBin(xmin);
02316                bin2 = hobj->GetXaxis()->FindFixBin(xmax);
02317                if (axisNumber == 1) {
02318                   hobj->GetXaxis()->SetRange(bin1,bin2);
02319                } else if (axisNumber == 2) {
02320                   if (hobj->GetDimension() == 1) {
02321                      Double_t xxmin = xmin;
02322                      Double_t xxmax = xmax;
02323                      if (hobj->GetNormFactor() != 0) {
02324                         Double_t norm = hobj->GetSumOfWeights()/hobj->GetNormFactor();
02325                         xxmin *= norm;
02326                         xxmax *= norm;
02327                      }
02328                      hobj->SetMinimum(xxmin);
02329                      hobj->SetMaximum(xxmax);
02330                      hobj->SetBit(TH1::kIsZoomed);
02331                   } else {
02332                      hobj->GetXaxis()->SetRange(bin1,bin2);
02333                   }
02334                }
02335             }
02336             Modified(kTRUE);
02337          }
02338       }
02339       gVirtualX->SetLineColor(-1);
02340       break;
02341    }
02342 }
02343 
02344 //______________________________________________________________________________
02345 TObject *TPad::FindObject(const char *name) const
02346 {
02347    // Search if object named name is inside this pad or in pads inside this pad.
02348    //
02349    //  In case name is in several subpads the first one is returned.
02350 
02351    if (!fPrimitives) return 0;
02352    TObject *found = fPrimitives->FindObject(name);
02353    if (found) return found;
02354    TObject *cur;
02355    TIter    next(GetListOfPrimitives());
02356    while ((cur = next())) {
02357       if (cur->InheritsFrom(TPad::Class())) {
02358          found = ((TPad*)cur)->FindObject(name);
02359          if (found) return found;
02360       }
02361    }
02362     return 0;
02363 }
02364 
02365 
02366 //______________________________________________________________________________
02367 TObject *TPad::FindObject(const TObject *obj) const
02368 {
02369    // Search if obj is in pad or in pads inside this pad.
02370    //
02371    //  In case obj is in several subpads the first one is returned.
02372 
02373    if (!fPrimitives) return 0;
02374    TObject *found = fPrimitives->FindObject(obj);
02375    if (found) return found;
02376    TObject *cur;
02377    TIter    next(GetListOfPrimitives());
02378    while ((cur = next())) {
02379       if (cur->InheritsFrom(TPad::Class())) {
02380          found = ((TPad*)cur)->FindObject(obj);
02381          if (found) return found;
02382       }
02383    }
02384    return 0;
02385 }
02386 
02387 
02388 //______________________________________________________________________________
02389 Int_t TPad::GetCanvasID() const
02390 {
02391    // Get canvas identifier.
02392 
02393    return fCanvas ? fCanvas->GetCanvasID() : -1;
02394 }
02395 
02396 //______________________________________________________________________________
02397 TCanvasImp *TPad::GetCanvasImp() const
02398 {
02399    // Get canvas implementation pointer if any
02400 
02401    return fCanvas ? fCanvas->GetCanvasImp() : 0;
02402 }
02403 
02404 
02405 //______________________________________________________________________________
02406 Int_t TPad::GetEvent() const
02407 {
02408    // Get Event.
02409 
02410    return fCanvas->GetEvent();
02411 }
02412 
02413 
02414 //______________________________________________________________________________
02415 Int_t TPad::GetEventX() const
02416 {
02417    // Get X event.
02418 
02419    return fCanvas->GetEventX();
02420 }
02421 
02422 
02423 //______________________________________________________________________________
02424 Int_t TPad::GetEventY() const
02425 {
02426    // Get Y event.
02427 
02428    return fCanvas->GetEventY();
02429 }
02430 
02431 
02432 //______________________________________________________________________________
02433 TVirtualPad *TPad::GetVirtCanvas() const
02434 {
02435    // Get virtual canvas.
02436 
02437    return (TVirtualPad*) fCanvas;
02438 }
02439 
02440 
02441 //______________________________________________________________________________
02442 Color_t TPad::GetHighLightColor() const
02443 {
02444    // Get highlight color.
02445 
02446    return fCanvas->GetHighLightColor();
02447 }
02448 
02449 
02450 //______________________________________________________________________________
02451 Int_t TPad::GetMaxPickDistance()
02452 {
02453    // Static function (see also TPad::SetMaxPickDistance)
02454 
02455    return fgMaxPickDistance;
02456 }
02457 
02458 
02459 //______________________________________________________________________________
02460 TObject *TPad::GetSelected() const
02461 {
02462    // Get selected.
02463 
02464    return fCanvas->GetSelected();
02465 }
02466 
02467 
02468 //______________________________________________________________________________
02469 TVirtualPad *TPad::GetSelectedPad() const
02470 {
02471    // Get selected pad.
02472 
02473    return fCanvas->GetSelectedPad();
02474 }
02475 
02476 
02477 //______________________________________________________________________________
02478 TVirtualPad *TPad::GetPadSave() const
02479 {
02480    // Get save pad.
02481 
02482    return fCanvas->GetPadSave();
02483 }
02484 
02485 
02486 //______________________________________________________________________________
02487 UInt_t TPad::GetWh() const
02488 {
02489    // Get Wh.
02490 
02491    return fCanvas->GetWh();
02492 }
02493 
02494 
02495 //______________________________________________________________________________
02496 UInt_t TPad::GetWw() const
02497 {
02498    // Get Ww.
02499 
02500    return fCanvas->GetWw();
02501 }
02502 
02503 
02504 //______________________________________________________________________________
02505 void TPad::HideToolTip(Int_t event)
02506 {
02507    // Hide tool tip depending on the event type. Typically tool tips
02508    // are hidden when event is not a kMouseEnter and not a kMouseMotion
02509    // event.
02510 
02511    if (event != kMouseEnter && event != kMouseMotion && fTip)
02512       gPad->CloseToolTip(fTip);
02513 }
02514 
02515 
02516 //______________________________________________________________________________
02517 Bool_t TPad::IsBatch() const
02518 {
02519    // Is pad in batch mode ?
02520 
02521    return fCanvas->IsBatch();
02522 }
02523 
02524 
02525 //______________________________________________________________________________
02526 Bool_t TPad::IsRetained() const
02527 {
02528    // Is pad retained ?
02529 
02530    return fCanvas->IsRetained();
02531 }
02532 
02533 
02534 //______________________________________________________________________________
02535 Bool_t TPad::OpaqueMoving() const
02536 {
02537    // Is pad moving in opaque mode ?
02538 
02539    return fCanvas->OpaqueMoving();
02540 }
02541 
02542 
02543 //______________________________________________________________________________
02544 Bool_t TPad::OpaqueResizing() const
02545 {
02546    // Is pad resizing in opaque mode ?
02547 
02548    return fCanvas->OpaqueResizing();
02549 }
02550 
02551 
02552 //______________________________________________________________________________
02553 void TPad::SetBatch(Bool_t batch)
02554 {
02555    // Set pad in batch mode.
02556 
02557    fCanvas->SetBatch(batch);
02558 }
02559 
02560 
02561 //______________________________________________________________________________
02562 void TPad::SetCanvasSize(UInt_t ww, UInt_t wh)
02563 {
02564    // Set canvas size.
02565 
02566    fCanvas->SetCanvasSize(ww,wh);
02567 }
02568 
02569 
02570 //______________________________________________________________________________
02571 void TPad::SetCursor(ECursor cursor)
02572 {
02573    // Set cursor type.
02574 
02575    fCanvas->SetCursor(cursor);
02576 }
02577 
02578 
02579 //______________________________________________________________________________
02580 void TPad::SetDoubleBuffer(Int_t mode)
02581 {
02582    // Set double buffer mode ON or OFF.
02583 
02584    fCanvas->SetDoubleBuffer(mode);
02585 }
02586 
02587 
02588 //______________________________________________________________________________
02589 void TPad::SetSelected(TObject *obj)
02590 {
02591    // Set selected.
02592 
02593    fCanvas->SetSelected(obj);
02594 }
02595 
02596 
02597 //______________________________________________________________________________
02598 void TPad::Update()
02599 {
02600    // Update pad.
02601 
02602    fCanvas->Update();
02603 }
02604 
02605 
02606 //______________________________________________________________________________
02607 TFrame *TPad::GetFrame()
02608 {
02609    // Get frame.
02610 
02611    if (!fPrimitives) fPrimitives = new TList;
02612    TFrame     *frame = (TFrame*)GetListOfPrimitives()->FindObject(fFrame);
02613    if (!frame) frame = (TFrame*)GetListOfPrimitives()->FindObject("TFrame");
02614    fFrame = frame;
02615    if (!fFrame) {
02616       if (!frame) fFrame = new TFrame(0,0,1,1);
02617       Int_t framecolor = GetFrameFillColor();
02618       if (!framecolor) framecolor = GetFillColor();
02619       fFrame->SetFillColor(framecolor);
02620       fFrame->SetFillStyle(GetFrameFillStyle());
02621       fFrame->SetLineColor(GetFrameLineColor());
02622       fFrame->SetLineStyle(GetFrameLineStyle());
02623       fFrame->SetLineWidth(GetFrameLineWidth());
02624       fFrame->SetBorderSize(GetFrameBorderSize());
02625       fFrame->SetBorderMode(GetFrameBorderMode());
02626    }
02627    return fFrame;
02628 }
02629 
02630 
02631 //______________________________________________________________________________
02632 TObject *TPad::GetPrimitive(const char *name) const
02633 {
02634    // Get primitive.
02635 
02636    if (!fPrimitives) return 0;
02637    TIter next(fPrimitives);
02638    TObject *found, *obj;
02639    while ((obj=next())) {
02640       if (!strcmp(name, obj->GetName())) return obj;
02641       if (obj->InheritsFrom(TPad::Class())) continue;
02642       found = obj->FindObject(name);
02643       if (found) return found;
02644    }
02645    return 0;
02646 }
02647 
02648 
02649 //______________________________________________________________________________
02650 TVirtualPad *TPad::GetPad(Int_t subpadnumber) const
02651 {
02652    // Get a pointer to subpadnumber of this pad.
02653 
02654    if (!subpadnumber) {
02655       return (TVirtualPad*)this;
02656    }
02657 
02658    TObject *obj;
02659    if (!fPrimitives) return 0;
02660    TIter    next(GetListOfPrimitives());
02661    while ((obj = next())) {
02662       if (obj->InheritsFrom(TVirtualPad::Class())) {
02663          TVirtualPad *pad = (TVirtualPad*)obj;
02664          if (pad->GetNumber() == subpadnumber) return pad;
02665       }
02666    }
02667    return 0;
02668 }
02669 
02670 
02671 //______________________________________________________________________________
02672 void TPad::GetPadPar(Double_t &xlow, Double_t &ylow, Double_t &xup, Double_t &yup)
02673 {
02674    // Return lower and upper bounds of the pad in NDC coordinates.
02675 
02676    xlow = fXlowNDC;
02677    ylow = fYlowNDC;
02678    xup  = fXlowNDC+fWNDC;
02679    yup  = fYlowNDC+fHNDC;
02680 }
02681 
02682 
02683 //______________________________________________________________________________
02684 void TPad::GetRange(Double_t &x1, Double_t &y1, Double_t &x2, Double_t &y2)
02685 {
02686    // Return pad world coordinates range.
02687 
02688    x1 = fX1;
02689    y1 = fY1;
02690    x2 = fX2;
02691    y2 = fY2;
02692 }
02693 
02694 
02695 //______________________________________________________________________________
02696 void TPad::GetRangeAxis(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax)
02697 {
02698    // Return pad axis coordinates range.
02699 
02700    xmin = fUxmin;
02701    ymin = fUymin;
02702    xmax = fUxmax;
02703    ymax = fUymax;
02704 }
02705 
02706 
02707 //______________________________________________________________________________
02708 void TPad::HighLight(Color_t color, Bool_t set)
02709 {
02710    // Highlight pad.
02711    //do not highlight when printing on Postscript
02712    if (gVirtualPS && gVirtualPS->TestBit(kPrintingPS)) return;
02713 
02714    if (color <= 0) return;
02715 
02716    AbsCoordinates(kTRUE);
02717 
02718    // We do not want to have active(executable) buttons, etc highlighted
02719    // in this manner, unless we want to edit'em
02720    if (GetMother()->IsEditable() && !InheritsFrom(TButton::Class())) {
02721       //When doing a DrawClone from the GUI you would do
02722       //  - select an empty pad -
02723       //  - right click on object -
02724       //     - select DrawClone on menu -
02725       //
02726       // Without the SetSelectedPad(); in the HighLight function, the
02727       // above instruction lead to the clone to be drawn in the
02728       // same canvas as the original object.  This is because the
02729       // 'right clicking' (via TCanvas::HandleInput) changes gPad
02730       // momentarily such that when DrawClone is called, it is
02731       // not the right value (for DrawClone). Should be FIXED.
02732       gROOT->SetSelectedPad(this);
02733       if (set)
02734          PaintBorder(-color, kFALSE);
02735       else
02736          PaintBorder(-GetFillColor(), kFALSE);
02737    }
02738 
02739    AbsCoordinates(kFALSE);
02740 }
02741 
02742 
02743 //______________________________________________________________________________
02744 void TPad::ls(Option_t *option) const
02745 {
02746    // List all primitives in pad.
02747 
02748    TROOT::IndentLevel();
02749    cout <<IsA()->GetName()<<" fXlowNDC=" <<fXlowNDC<<" fYlowNDC="<<fYlowNDC<<" fWNDC="<<GetWNDC()<<" fHNDC="<<GetHNDC()
02750         <<" Name= "<<GetName()<<" Title= "<<GetTitle()<<" Option="<<option<<endl;
02751    TROOT::IncreaseDirLevel();
02752    if (!fPrimitives) return;
02753    fPrimitives->ls(option);
02754    TROOT::DecreaseDirLevel();
02755 }
02756 
02757 
02758 //______________________________________________________________________________
02759 Double_t TPad::PadtoX(Double_t x) const
02760 {
02761    // Convert x from pad to X.
02762 
02763    if (fLogx && x < 50) return Double_t(TMath::Exp(2.302585092994*x));
02764    return x;
02765 }
02766 
02767 
02768 //______________________________________________________________________________
02769 Double_t TPad::PadtoY(Double_t y) const
02770 {
02771    // Convert y from pad to Y.
02772 
02773    if (fLogy && y < 50) return Double_t(TMath::Exp(2.302585092994*y));
02774    return y;
02775 }
02776 
02777 
02778 //______________________________________________________________________________
02779 Double_t TPad::XtoPad(Double_t x) const
02780 {
02781    // Convert x from X to pad.
02782 
02783    if (fLogx) {
02784       if (x > 0) x = TMath::Log10(x);
02785       else       x = fUxmin;
02786    }
02787    return x;
02788 }
02789 
02790 
02791 //______________________________________________________________________________
02792 Double_t TPad::YtoPad(Double_t y) const
02793 {
02794    // Convert y from Y to pad.
02795 
02796    if (fLogy) {
02797       if (y > 0) y = TMath::Log10(y);
02798       else       y = fUymin;
02799    }
02800    return y;
02801 }
02802 
02803 
02804 //______________________________________________________________________________
02805 void TPad::Paint(Option_t * /*option*/)
02806 {
02807    // Paint all primitives in pad.
02808 
02809    if (!fPrimitives) fPrimitives = new TList;
02810    if (fViewer3D && fViewer3D->CanLoopOnPrimitives()) {
02811       fViewer3D->PadPaint(this);
02812       Modified(kFALSE);
02813       if (GetGLDevice()!=-1 && gVirtualPS) {
02814          TPad *padsav = (TPad*)gPad;
02815          gPad = this;
02816          gGLManager->PrintViewer(GetViewer3D());
02817          gPad = padsav;
02818       }
02819       return;
02820    }
02821 
02822    if (fCanvas) TColor::SetGrayscale(fCanvas->IsGrayscale());
02823 
02824    TPad *padsav = (TPad*)gPad;
02825 
02826    fPadPaint = 1;
02827    cd();
02828 
02829    PaintBorder(GetFillColor(), kTRUE);
02830    PaintDate();
02831 
02832    TObjOptLink *lnk = (TObjOptLink*)GetListOfPrimitives()->FirstLink();
02833    TObject *obj;
02834 
02835    Bool_t began3DScene = kFALSE;
02836    while (lnk) {
02837       obj = lnk->GetObject();
02838 
02839       // Create a pad 3D viewer if none exists and we encounter a 3D shape
02840       if (!fViewer3D && obj->InheritsFrom(TAtt3D::Class())) {
02841          GetViewer3D("pad");
02842       }
02843 
02844       // Open a 3D scene if required
02845       if (fViewer3D && !fViewer3D->BuildingScene()) {
02846          fViewer3D->BeginScene();
02847          began3DScene = kTRUE;
02848       }
02849 
02850       obj->Paint(lnk->GetOption());
02851       lnk = (TObjOptLink*)lnk->Next();
02852    }
02853 
02854    if (padsav) padsav->cd();
02855    fPadPaint = 0;
02856    Modified(kFALSE);
02857 
02858    // Close the 3D scene if we opened it. This must be done after modified
02859    // flag is cleared, as some viewers will invoke another paint by marking pad modified again
02860    if (began3DScene) {
02861       fViewer3D->EndScene();
02862    }
02863 
02864 ///// Generate the PS output using gl2ps
02865 ///if (GetGLDevice()!=-1 && gVirtualPS) {
02866 ///   gPad = this;
02867 ///   gGLManager->PrintViewer(GetViewer3D());
02868 ///   gPad = padsav;
02869 ///}
02870 }
02871 
02872 
02873 //______________________________________________________________________________
02874 void TPad::PaintBorder(Color_t color, Bool_t tops)
02875 {
02876    // Paint the pad border.
02877    // Draw first  a box as a normal filled box
02878    if(color >= 0) {
02879       TAttLine::Modify();  //Change line attributes only if necessary
02880       TAttFill::Modify();  //Change fill area attributes only if necessary
02881       PaintBox(fX1,fY1,fX2,fY2);
02882    }
02883    if (color < 0) color = -color;
02884    // then paint 3d frame (depending on bordermode)
02885    if (IsTransparent()) return;
02886    // Paint a 3D frame around the pad.
02887 
02888    if (fBorderMode == 0) return;
02889    Int_t bordersize = fBorderSize;
02890    if (bordersize <= 0) bordersize = 2;
02891 
02892    const Double_t realBsX = bordersize / (GetAbsWNDC() * GetWw()) * (fX2 - fX1);
02893    const Double_t realBsY = bordersize / (GetAbsHNDC() * GetWh()) * (fY2 - fY1);
02894 
02895    Short_t px1,py1,px2,py2;
02896    Double_t xl, xt, yl, yt;
02897 
02898    // GetDarkColor() and GetLightColor() use GetFillColor()
02899    Color_t oldcolor = GetFillColor();
02900    SetFillColor(color);
02901    TAttFill::Modify();
02902    Color_t light = 0, dark = 0;
02903    if (color != 0) {
02904       light = TColor::GetColorBright(color);
02905       dark  = TColor::GetColorDark(color);
02906    }
02907 
02908    // Compute real left bottom & top right of the box in pixels
02909    px1 = XtoPixel(fX1);   py1 = YtoPixel(fY1);
02910    px2 = XtoPixel(fX2);   py2 = YtoPixel(fY2);
02911    if (px1 < px2) {xl = fX1; xt = fX2; }
02912    else           {xl = fX2; xt = fX1;}
02913    if (py1 > py2) {yl = fY1; yt = fY2;}
02914    else           {yl = fY2; yt = fY1;}
02915 
02916    Double_t frameXs[7] = {}, frameYs[7] = {};
02917 
02918    if (!IsBatch()) {
02919       // Draw top&left part of the box
02920       frameXs[0] = xl;           frameYs[0] = yl;
02921       frameXs[1] = xl + realBsX; frameYs[1] = yl + realBsY;
02922       frameXs[2] = frameXs[1];   frameYs[2] = yt - realBsY;
02923       frameXs[3] = xt - realBsX; frameYs[3] = frameYs[2];
02924       frameXs[4] = xt;           frameYs[4] = yt;
02925       frameXs[5] = xl;           frameYs[5] = yt;
02926       frameXs[6] = xl;           frameYs[6] = yl;
02927 
02928       if (fBorderMode == -1) GetPainter()->SetFillColor(dark);
02929       else                   GetPainter()->SetFillColor(light);
02930       GetPainter()->DrawFillArea(7, frameXs, frameYs);
02931 
02932       // Draw bottom&right part of the box
02933       frameXs[0] = xl;              frameYs[0] = yl;
02934       frameXs[1] = xl + realBsX;    frameYs[1] = yl + realBsY;
02935       frameXs[2] = xt - realBsX;    frameYs[2] = frameYs[1];
02936       frameXs[3] = frameXs[2];      frameYs[3] = yt - realBsY;
02937       frameXs[4] = xt;              frameYs[4] = yt;
02938       frameXs[5] = xt;              frameYs[5] = yl;
02939       frameXs[6] = xl;              frameYs[6] = yl;
02940 
02941       if (fBorderMode == -1) GetPainter()->SetFillColor(light);
02942       else                   GetPainter()->SetFillColor(dark);
02943       GetPainter()->DrawFillArea(7, frameXs, frameYs);
02944 
02945       // If this pad is a button, highlight it
02946       if (InheritsFrom(TButton::Class()) && fBorderMode == -1) {
02947          if (TestBit(kFraming)) {  // bit set in TButton::SetFraming
02948             if (GetFillColor() != 2) GetPainter()->SetLineColor(2);
02949             else                     GetPainter()->SetLineColor(4);
02950             GetPainter()->DrawBox(xl + realBsX, yl + realBsY, xt - realBsX, yt - realBsY, TVirtualPadPainter::kHollow);
02951          }
02952       }
02953       GetPainter()->SetFillColor(-1);
02954       SetFillColor(oldcolor);
02955    }
02956 
02957    if (!tops) return;
02958 
02959    PaintBorderPS(xl, yl, xt, yt, fBorderMode, bordersize, dark, light);
02960 }
02961 
02962 
02963 //______________________________________________________________________________
02964 void TPad::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)
02965 {
02966    // Paint a frame border with Postscript.
02967 
02968    if (!gVirtualPS) return;
02969    gVirtualPS->DrawFrame(xl, yl, xt, yt, bmode,bsize,dark,light);
02970 }
02971 
02972 
02973 //______________________________________________________________________________
02974 void TPad::PaintDate()
02975 {
02976    // Paint the current date and time if the option date is on.
02977 
02978    if (fCanvas == this && gStyle->GetOptDate()) {
02979       TDatime dt;
02980       const char *dates;
02981       char iso[16];
02982       if (gStyle->GetOptDate() < 10) {
02983          //by default use format like "Wed Sep 25 17:10:35 2002"
02984          dates = dt.AsString();
02985       } else if (gStyle->GetOptDate() < 20) {
02986          //use ISO format like 2002-09-25
02987          strlcpy(iso,dt.AsSQLString(),16);
02988          dates = iso;
02989       } else {
02990          //use ISO format like 2002-09-25 17:10:35
02991          dates = dt.AsSQLString();
02992       }
02993       TText tdate(gStyle->GetDateX(),gStyle->GetDateY(),dates);
02994       tdate.SetTextSize( gStyle->GetAttDate()->GetTextSize());
02995       tdate.SetTextFont( gStyle->GetAttDate()->GetTextFont());
02996       tdate.SetTextColor(gStyle->GetAttDate()->GetTextColor());
02997       tdate.SetTextAlign(gStyle->GetAttDate()->GetTextAlign());
02998       tdate.SetTextAngle(gStyle->GetAttDate()->GetTextAngle());
02999       tdate.SetNDC();
03000       tdate.Paint();
03001    }
03002 }
03003 
03004 
03005 //______________________________________________________________________________
03006 void TPad::PaintPadFrame(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax)
03007 {
03008    // Paint histogram/graph frame.
03009 
03010    if (!fPrimitives) fPrimitives = new TList;
03011    TList *glist  = GetListOfPrimitives();
03012    TFrame *frame = GetFrame();
03013    frame->SetX1(xmin);
03014    frame->SetX2(xmax);
03015    frame->SetY1(ymin);
03016    frame->SetY2(ymax);
03017    if (!glist->FindObject(fFrame)) {
03018       glist->AddFirst(frame);
03019       fFrame->SetBit(kMustCleanup);
03020    }
03021    if (gROOT->GetForceStyle()) frame->UseCurrentStyle();
03022    frame->Paint();
03023 }
03024 
03025 
03026 //______________________________________________________________________________
03027 void TPad::PaintModified()
03028 {
03029    // Traverse pad hierarchy and (re)paint only modified pads.
03030 
03031    if (fViewer3D && fViewer3D->CanLoopOnPrimitives()) {
03032       if (IsModified()) {
03033          fViewer3D->PadPaint(this);
03034          Modified(kFALSE);
03035       }
03036       TList *pList = GetListOfPrimitives();
03037       TObjOptLink *lnk = 0;
03038       if (pList) lnk = (TObjOptLink*)pList->FirstLink();
03039       TObject *obj;
03040       while (lnk) {
03041          obj = lnk->GetObject();
03042          if (obj->InheritsFrom(TPad::Class()))
03043             ((TPad*)obj)->PaintModified();
03044          lnk = (TObjOptLink*)lnk->Next();
03045       }
03046       return;
03047    }
03048 
03049    if (fCanvas) TColor::SetGrayscale(fCanvas->IsGrayscale());
03050 
03051    TPad *padsav = (TPad*)gPad;
03052    TVirtualPS *saveps = gVirtualPS;
03053    if (gVirtualPS) {
03054       if (gVirtualPS->TestBit(kPrintingPS)) gVirtualPS = 0;
03055    }
03056    fPadPaint = 1;
03057    cd();
03058    if (IsModified() || IsTransparent()) {
03059       if ((fFillStyle < 3026) && (fFillStyle > 3000)) {
03060          if (!gPad->IsBatch()) GetPainter()->ClearDrawable();
03061       }
03062       PaintBorder(GetFillColor(), kTRUE);
03063    }
03064 
03065    PaintDate();
03066 
03067    TList *pList = GetListOfPrimitives();
03068    TObjOptLink *lnk = 0;
03069    if (pList) lnk = (TObjOptLink*)pList->FirstLink();
03070    TObject *obj;
03071 
03072    Bool_t began3DScene = kFALSE;
03073 
03074    while (lnk) {
03075       obj = lnk->GetObject();
03076       if (obj->InheritsFrom(TPad::Class())) {
03077          ((TPad*)obj)->PaintModified();
03078       } else if (IsModified() || IsTransparent()) {
03079 
03080          // Create a pad 3D viewer if none exists and we encounter a
03081          // 3D shape
03082          if (!fViewer3D && obj->InheritsFrom(TAtt3D::Class())) {
03083             GetViewer3D("pad");
03084          }
03085 
03086          // Open a 3D scene if required
03087          if (fViewer3D && !fViewer3D->BuildingScene()) {
03088             fViewer3D->BeginScene();
03089             began3DScene = kTRUE;
03090          }
03091 
03092          obj->Paint(lnk->GetOption());
03093       }
03094       lnk = (TObjOptLink*)lnk->Next();
03095    }
03096 
03097    if (padsav) padsav->cd();
03098    fPadPaint = 0;
03099    Modified(kFALSE);
03100 
03101    // This must be done after modified flag is cleared, as some
03102    // viewers will invoke another paint by marking pad modified again
03103    if (began3DScene) {
03104       fViewer3D->EndScene();
03105    }
03106 
03107    gVirtualPS = saveps;
03108 }
03109 
03110 
03111 //______________________________________________________________________________
03112 void TPad::PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t *option)
03113 {
03114    // Paint box in CurrentPad World coordinates.
03115    //
03116    // if option[0] = 's' the box is forced to be paint with style=0
03117    // if option[0] = 'l' the box contour is drawn
03118 
03119    if (!gPad->IsBatch()) {
03120       Int_t style0 = GetPainter()->GetFillStyle();
03121       Int_t style  = style0;
03122       if (option[0] == 's') {
03123          GetPainter()->SetFillStyle(0);
03124          style = 0;
03125       }
03126       if (style) {
03127          if (style > 3000 && style < 4000) {
03128             if (style < 3026) {
03129                // draw stipples with fFillColor foreground
03130                GetPainter()->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
03131             }
03132 
03133             if (style >= 3100 && style < 4000) {
03134                Double_t xb[4], yb[4];
03135                xb[0] = x1; xb[1] = x1; xb[2] = x2; xb[3] = x2;
03136                yb[0] = y1; yb[1] = y2; yb[2] = y2; yb[3] = y1;
03137                PaintFillAreaHatches(4, xb, yb, style);
03138                return;
03139             }
03140             //special case for TAttFillCanvas
03141             if (GetPainter()->GetFillColor() == 10) {
03142                GetPainter()->SetFillColor(1);
03143                GetPainter()->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
03144                GetPainter()->SetFillColor(10);
03145             }
03146          } else if (style >= 4000 && style <= 4100) {
03147             // For style >=4000 we make the window transparent.
03148             // From 4000 to 4100 the window is 100% transparent to 100% opaque
03149 
03150             //ignore this style option when this is the canvas itself
03151             if (this == fMother)
03152                GetPainter()->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
03153             else {
03154                //draw background by blitting all bottom pads
03155                int px, py;
03156                XYtoAbsPixel(fX1, fY2, px, py);
03157 
03158                if (fMother) {
03159                   fMother->CopyBackgroundPixmap(px, py);
03160                   CopyBackgroundPixmaps(fMother, this, px, py);
03161                }
03162 
03163                GetPainter()->SetOpacity(style - 4000);
03164             }
03165          } else {
03166             GetPainter()->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
03167          }
03168          if (option[0] == 'l') GetPainter()->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow);
03169       } else {
03170          GetPainter()->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow);
03171          if (option[0] == 's') GetPainter()->SetFillStyle(style0);
03172       }
03173    }
03174 
03175    if (gVirtualPS) {
03176       Int_t style0 = gVirtualPS->GetFillStyle();
03177       if (option[0] == 's') {
03178          gVirtualPS->SetFillStyle(0);
03179       } else {
03180          if (style0 >= 3100 && style0 < 4000) {
03181             Double_t xb[4], yb[4];
03182             xb[0] = x1; xb[1] = x1; xb[2] = x2; xb[3] = x2;
03183             yb[0] = y1; yb[1] = y2; yb[2] = y2; yb[3] = y1;
03184             PaintFillAreaHatches(4, xb, yb, style0);
03185             return;
03186          }
03187       }
03188       gVirtualPS->DrawBox(x1, y1, x2, y2);
03189       if (option[0] == 'l') {
03190          gVirtualPS->SetFillStyle(0);
03191          gVirtualPS->DrawBox(x1, y1, x2, y2);
03192       }
03193       if (option[0] == 's' || option[0] == 'l') gVirtualPS->SetFillStyle(style0);
03194    }
03195 
03196    Modified();
03197 }
03198 
03199 
03200 //______________________________________________________________________________
03201 void TPad::CopyBackgroundPixmaps(TPad *start, TPad *stop, Int_t x, Int_t y)
03202 {
03203    // Copy pixmaps of pads laying below pad "stop" into pad "stop". This
03204    // gives the effect of pad "stop" being transparent.
03205 
03206    TObject *obj;
03207    if (!fPrimitives) fPrimitives = new TList;
03208    TIter next(start->GetListOfPrimitives());
03209    while ((obj = next())) {
03210       if (obj->InheritsFrom(TPad::Class())) {
03211          if (obj == stop) break;
03212          ((TPad*)obj)->CopyBackgroundPixmap(x, y);
03213          ((TPad*)obj)->CopyBackgroundPixmaps((TPad*)obj, stop, x, y);
03214       }
03215    }
03216 }
03217 
03218 
03219 //______________________________________________________________________________
03220 void TPad::CopyBackgroundPixmap(Int_t x, Int_t y)
03221 {
03222    // Copy pixmap of this pad as background of the current pad.
03223 
03224    int px, py;
03225    XYtoAbsPixel(fX1, fY2, px, py);
03226    GetPainter()->CopyDrawable(GetPixmapID(), px-x, py-y);
03227 }
03228 
03229 
03230 //______________________________________________________________________________
03231 void TPad::PaintFillArea(Int_t nn, Float_t *xx, Float_t *yy, Option_t *)
03232 {
03233    // Paint fill area in CurrentPad World coordinates.
03234 
03235    Warning("TPad::PaintFillArea", "Float_t signature is obsolete");
03236 
03237    if (nn <3) return;
03238    Int_t i,iclip,n=0;
03239    Double_t xmin,xmax,ymin,ymax;
03240    Double_t u1, v1, u[2],v[2];
03241    if (TestBit(TGraph::kClipFrame)) {
03242       xmin = fUxmin; ymin = fUymin; xmax = fUxmax; ymax = fUymax;
03243    } else {
03244       xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
03245    }
03246    Double_t *x = new Double_t[2*nn+1];
03247    Double_t *y = new Double_t[2*nn+1];
03248 
03249    for (i=0;i<nn;i++) {
03250       u[0] = xx[i];
03251       v[0] = yy[i];
03252       if (i == nn-1) {
03253          u[1] = xx[0];
03254          v[1] = yy[0];
03255       } else {
03256          u[1] = xx[i+1];
03257          v[1] = yy[i+1];
03258       }
03259       u1 = u[1];
03260       v1 = v[1];
03261       iclip = Clip(u,v,xmin,ymin,xmax,ymax);
03262       if (iclip == 2) continue;
03263       if (iclip == 1) {
03264          if (u[0] == u[1] && v[0] == v[1]) continue;
03265       }
03266       x[n] = u[0];
03267       y[n] = v[0];
03268       n++;
03269       if (iclip) {
03270          if (u[1] != u1 || v[1] != v1) {
03271             x[n] = u[1];
03272             y[n] = v[1];
03273             n++;
03274          }
03275       }
03276    }
03277    x[n] = x[0];
03278    y[n] = y[0];
03279 
03280    if (n < 3) {
03281       delete [] x;
03282       delete [] y;
03283       return;
03284    }
03285 
03286    // Paint the fill area with hatches
03287    Int_t fillstyle = GetPainter()->GetFillStyle();
03288    if (gPad->IsBatch() && gVirtualPS) fillstyle = gVirtualPS->GetFillStyle();
03289    if (fillstyle >= 3100 && fillstyle < 4000) {
03290       PaintFillAreaHatches(nn, x, y, fillstyle);
03291       delete [] x;
03292       delete [] y;
03293       return;
03294    }
03295 
03296    if (!gPad->IsBatch())
03297       // invoke the graphics subsystem
03298       GetPainter()->DrawFillArea(n, x, y);
03299 
03300    if (gVirtualPS) {
03301       gVirtualPS->DrawPS(-n, x, y);
03302    }
03303    delete [] x;
03304    delete [] y;
03305    Modified();
03306 }
03307 
03308 
03309 //______________________________________________________________________________
03310 void TPad::PaintFillArea(Int_t nn, Double_t *xx, Double_t *yy, Option_t *)
03311 {
03312    // Paint fill area in CurrentPad World coordinates.
03313 
03314    if (nn <3) return;
03315    Int_t n=0;
03316    Double_t xmin,xmax,ymin,ymax;
03317    if (TestBit(TGraph::kClipFrame)) {
03318       xmin = fUxmin; ymin = fUymin; xmax = fUxmax; ymax = fUymax;
03319    } else {
03320       xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
03321    }
03322 
03323    Int_t nc = 2*nn+1;
03324    Double_t *x = new Double_t[nc];
03325    Double_t *y = new Double_t[nc];
03326    memset(x,0,8*nc);
03327    memset(y,0,8*nc);
03328 
03329    n = ClipPolygon(nn, xx, yy, nc, x, y,xmin,ymin,xmax,ymax);
03330    if (!n) {
03331       delete [] x;
03332       delete [] y;
03333       return;
03334    }
03335 
03336    // Paint the fill area with hatches
03337    Int_t fillstyle = GetPainter()->GetFillStyle();
03338    if (gPad->IsBatch() && gVirtualPS) fillstyle = gVirtualPS->GetFillStyle();
03339    if (fillstyle >= 3100 && fillstyle < 4000) {
03340       PaintFillAreaHatches(nn, x, y, fillstyle);
03341       delete [] x;
03342       delete [] y;
03343       return;
03344    }
03345 
03346    if (!gPad->IsBatch())
03347       // invoke the graphics subsystem
03348       GetPainter()->DrawFillArea(n, x, y);
03349 
03350    if (gVirtualPS) {
03351       gVirtualPS->DrawPS(-n, x, y);
03352    }
03353    delete [] x;
03354    delete [] y;
03355    Modified();
03356 }
03357 
03358 
03359 //______________________________________________________________________________
03360 void TPad::PaintFillAreaHatches(Int_t nn, Double_t *xx, Double_t *yy, Int_t FillStyle)
03361 {
03362    //   This function paints hatched fill area arcording to the FillStyle value
03363    // The convention for the Hatch is the following:
03364    //
03365    //            FillStyle = 3ijk
03366    //
03367    //    i (1-9) : specify the space between each hatch
03368    //              1 = minimum  9 = maximum
03369    //              the final spacing is i*GetHatchesSpacing(). The hatches spacing
03370    //              is set by SetHatchesSpacing()
03371    //
03372    //    j (0-9) : specify angle between 0 and 90 degrees
03373    //
03374    //              0 = 0
03375    //              1 = 10
03376    //              2 = 20
03377    //              3 = 30
03378    //              4 = 45
03379    //              5 = Not drawn
03380    //              6 = 60
03381    //              7 = 70
03382    //              8 = 80
03383    //              9 = 90
03384    //
03385    //    k (0-9) : specify angle between 90 and 180 degrees
03386    //              0 = 180
03387    //              1 = 170
03388    //              2 = 160
03389    //              3 = 150
03390    //              4 = 135
03391    //              5 = Not drawn
03392    //              6 = 120
03393    //              7 = 110
03394    //              8 = 100
03395    //              9 = 90
03396 
03397    static Double_t ang1[10] = {0., 10., 20., 30., 45.,5., 60., 70., 80., 90.};
03398    static Double_t ang2[10] = {180.,170.,160.,150.,135.,5.,120.,110.,100., 90.};
03399 
03400    Int_t fasi  = FillStyle%1000;
03401    Int_t idSPA = (Int_t)(fasi/100);
03402    Int_t iAng2 = (Int_t)((fasi-100*idSPA)/10);
03403    Int_t iAng1 = fasi%10;
03404    Double_t dy = 0.003*(Double_t)(idSPA)*gStyle->GetHatchesSpacing();
03405    Int_t lw = gStyle->GetHatchesLineWidth();
03406    Short_t lws = 0;
03407    Int_t   lss = 0;
03408    Int_t   lcs = 0;
03409 
03410    // Save the current line attributes
03411    if (!gPad->IsBatch()) {
03412       lws = GetPainter()->GetLineWidth();
03413       lss = GetPainter()->GetLineStyle();
03414       lcs = GetPainter()->GetLineColor();
03415    } else {
03416       if (gVirtualPS) {
03417          lws = gVirtualPS->GetLineWidth();
03418          lss = gVirtualPS->GetLineStyle();
03419          lcs = gVirtualPS->GetLineColor();
03420       }
03421    }
03422 
03423    // Change the current line attributes to draw the hatches
03424    if (!gPad->IsBatch()) {
03425       GetPainter()->SetLineStyle(1);
03426       GetPainter()->SetLineWidth(Short_t(lw));
03427       GetPainter()->SetLineColor(GetPainter()->GetFillColor());
03428    }
03429    if (gVirtualPS) {
03430       gVirtualPS->SetLineStyle(1);
03431       gVirtualPS->SetLineWidth(Short_t(lw));
03432       gVirtualPS->SetLineColor(gVirtualPS->GetFillColor());
03433    }
03434 
03435    // Draw the hatches
03436    if (ang1[iAng1] != 5.) PaintHatches(dy, ang1[iAng1], nn, xx, yy);
03437    if (ang2[iAng2] != 5.) PaintHatches(dy, ang2[iAng2], nn, xx, yy);
03438 
03439    // Restore the line attributes
03440    if (!gPad->IsBatch()) {
03441       GetPainter()->SetLineStyle(lss);
03442       GetPainter()->SetLineWidth(lws);
03443       GetPainter()->SetLineColor(lcs);
03444    }
03445    if (gVirtualPS) {
03446       gVirtualPS->SetLineStyle(lss);
03447       gVirtualPS->SetLineWidth(lws);
03448       gVirtualPS->SetLineColor(lcs);
03449    }
03450 }
03451 
03452 
03453 //______________________________________________________________________________
03454 void TPad::PaintHatches(Double_t dy, Double_t angle,
03455                         Int_t nn, Double_t *xx, Double_t *yy)
03456 {
03457    // This routine draw hatches inclined with the
03458    // angle "angle" and spaced of "dy" in normalized device
03459    // coordinates in the surface defined by n,xx,yy.
03460 
03461    Int_t i, i1, i2, nbi, m, inv;
03462    Double_t ratiox, ratioy, ymin, ymax, yrot, ycur;
03463    const Double_t angr  = TMath::Pi()*(180-angle)/180.;
03464    const Double_t epsil = 0.0001;
03465    const Int_t maxnbi = 100;
03466    Double_t xli[maxnbi], xlh[2], ylh[2], xt1, xt2, yt1, yt2;
03467    Double_t ll, x, y, x1, x2, y1, y2, a, b, xi, xip, xin, yi, yip;
03468 
03469    Double_t rwxmin = gPad->GetX1();
03470    Double_t rwxmax = gPad->GetX2();
03471    Double_t rwymin = gPad->GetY1();
03472    Double_t rwymax = gPad->GetY2();
03473    ratiox = 1/(rwxmax-rwxmin);
03474    ratioy = 1/(rwymax-rwymin);
03475 
03476    Double_t sina = TMath::Sin(angr), sinb;
03477    Double_t cosa = TMath::Cos(angr), cosb;
03478    if (TMath::Abs(cosa) <= epsil) cosa=0.;
03479    if (TMath::Abs(sina) <= epsil) sina=0.;
03480    sinb = -sina;
03481    cosb = cosa;
03482 
03483    // Values needed to compute the hatches in TRUE normalized space (NDC)
03484    Int_t iw = gPad->GetWw();
03485    Int_t ih = gPad->GetWh();
03486    Double_t x1p,y1p,x2p,y2p;
03487    gPad->GetPadPar(x1p,y1p,x2p,y2p);
03488    iw  = (Int_t)(iw*x2p)-(Int_t)(iw*x1p);
03489    ih  = (Int_t)(ih*y2p)-(Int_t)(ih*y1p);
03490    Double_t wndc  = TMath::Min(1.,(Double_t)iw/(Double_t)ih);
03491    Double_t hndc  = TMath::Min(1.,(Double_t)ih/(Double_t)iw);
03492 
03493    // Search ymin and ymax
03494    ymin = 1.;
03495    ymax = 0.;
03496    for (i=1; i<=nn; i++) {
03497       x    = wndc*ratiox*(xx[i-1]-rwxmin);
03498       y    = hndc*ratioy*(yy[i-1]-rwymin);
03499       yrot = sina*x+cosa*y;
03500       if (yrot > ymax) ymax = yrot;
03501       if (yrot < ymin) ymin = yrot;
03502    }
03503    ymax = (Double_t)((Int_t)(ymax/dy))*dy;
03504 
03505    for (ycur=ymax; ycur>=ymin; ycur=ycur-dy) {
03506       nbi = 0;
03507       for (i=2; i<=nn+1; i++) {
03508          i2 = i;
03509          i1 = i-1;
03510          if (i == nn+1) i2=1;
03511          x1  = wndc*ratiox*(xx[i1-1]-rwxmin);
03512          y1  = hndc*ratioy*(yy[i1-1]-rwymin);
03513          x2  = wndc*ratiox*(xx[i2-1]-rwxmin);
03514          y2  = hndc*ratioy*(yy[i2-1]-rwymin);
03515          xt1 = cosa*x1-sina*y1;
03516          yt1 = sina*x1+cosa*y1;
03517          xt2 = cosa*x2-sina*y2;
03518          yt2 = sina*x2+cosa*y2;
03519 
03520          // Line segment parallel to oy
03521          if (xt1 == xt2) {
03522             if (yt1 < yt2) {
03523                yi  = yt1;
03524                yip = yt2;
03525             } else {
03526                yi  = yt2;
03527                yip = yt1;
03528             }
03529             if ((yi <= ycur) && (ycur < yip)) {
03530                nbi++;
03531                if (nbi >= maxnbi) return;
03532                xli[nbi-1] = xt1;
03533             }
03534             continue;
03535          }
03536 
03537          // Line segment parallel to ox
03538          if (yt1 == yt2) {
03539             if (yt1 == ycur) {
03540                nbi++;
03541                if (nbi >= maxnbi) return;
03542                xli[nbi-1] = xt1;
03543                nbi++;
03544                if (nbi >= maxnbi) return;
03545                xli[nbi-1] = xt2;
03546             }
03547             continue;
03548          }
03549 
03550          // Other line segment
03551          a = (yt1-yt2)/(xt1-xt2);
03552          b = (yt2*xt1-xt2*yt1)/(xt1-xt2);
03553          if (xt1 < xt2) {
03554             xi  = xt1;
03555             xip = xt2;
03556          } else {
03557             xi  = xt2;
03558             xip = xt1;
03559          }
03560          xin = (ycur-b)/a;
03561          if  ((xi <= xin) && (xin < xip) &&
03562               (TMath::Min(yt1,yt2) <= ycur) &&
03563               (ycur < TMath::Max(yt1,yt2))) {
03564             nbi++;
03565             if (nbi >= maxnbi) return;
03566             xli[nbi-1] = xin;
03567          }
03568       }
03569 
03570       // Sorting of the x coordinates intersections
03571       inv = 0;
03572       m   = nbi-1;
03573 L30:
03574       for (i=1; i<=m; i++) {
03575          if (xli[i] < xli[i-1]) {
03576             inv++;
03577             ll       = xli[i-1];
03578             xli[i-1] = xli[i];
03579             xli[i]   = ll;
03580          }
03581       }
03582       m--;
03583       if (inv == 0) goto L50;
03584       inv = 0;
03585       goto L30;
03586 
03587       // Draw the hatches
03588 L50:
03589       if (nbi%2 != 0) continue;
03590 
03591       for (i=1; i<=nbi; i=i+2) {
03592          // Rotate back the hatches
03593          xlh[0] = cosb*xli[i-1]-sinb*ycur;
03594          ylh[0] = sinb*xli[i-1]+cosb*ycur;
03595          xlh[1] = cosb*xli[i]  -sinb*ycur;
03596          ylh[1] = sinb*xli[i]  +cosb*ycur;
03597          // Convert hatches' positions from true NDC to WC
03598          xlh[0] = (xlh[0]/wndc)*(rwxmax-rwxmin)+rwxmin;
03599          ylh[0] = (ylh[0]/hndc)*(rwymax-rwymin)+rwymin;
03600          xlh[1] = (xlh[1]/wndc)*(rwxmax-rwxmin)+rwxmin;
03601          ylh[1] = (ylh[1]/hndc)*(rwymax-rwymin)+rwymin;
03602          gPad->PaintLine(xlh[0], ylh[0], xlh[1], ylh[1]);
03603       }
03604    }
03605 }
03606 
03607 
03608 //______________________________________________________________________________
03609 void TPad::PaintLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
03610 {
03611    // Paint line in CurrentPad World coordinates.
03612 
03613    Double_t x[2], y[2];
03614    x[0] = x1;   x[1] = x2;   y[0] = y1;   y[1] = y2;
03615 
03616    //If line is totally clipped, return
03617    if (TestBit(TGraph::kClipFrame)) {
03618       if (Clip(x,y,fUxmin,fUymin,fUxmax,fUymax) == 2) return;
03619    } else {
03620       if (Clip(x,y,fX1,fY1,fX2,fY2) == 2) return;
03621    }
03622 
03623    if (!gPad->IsBatch())
03624       GetPainter()->DrawLine(x[0], y[0], x[1], y[1]);
03625 
03626    if (gVirtualPS) {
03627       gVirtualPS->DrawPS(2, x, y);
03628    }
03629 
03630    Modified();
03631 }
03632 
03633 
03634 //______________________________________________________________________________
03635 void TPad::PaintLineNDC(Double_t u1, Double_t v1,Double_t u2, Double_t v2)
03636 {
03637    static Double_t xw[2], yw[2];
03638    if (!gPad->IsBatch())
03639       GetPainter()->DrawLineNDC(u1, v1, u2, v2);
03640 
03641    if (gVirtualPS) {
03642       xw[0] = fX1 + u1*(fX2 - fX1);
03643       xw[1] = fX1 + u2*(fX2 - fX1);
03644       yw[0] = fY1 + v1*(fY2 - fY1);
03645       yw[1] = fY1 + v2*(fY2 - fY1);
03646       gVirtualPS->DrawPS(2, xw, yw);
03647    }
03648 
03649    Modified();
03650 }
03651 
03652 
03653 //______________________________________________________________________________
03654 void TPad::PaintLine3D(Float_t *p1, Float_t *p2)
03655 {
03656    // Paint 3-D line in the CurrentPad.
03657 
03658    if (!fView) return;
03659 
03660    // convert from 3-D to 2-D pad coordinate system
03661    Double_t xpad[6];
03662    Double_t temp[3];
03663    Int_t i;
03664    for (i=0;i<3;i++) temp[i] = p1[i];
03665    fView->WCtoNDC(temp, &xpad[0]);
03666    for (i=0;i<3;i++) temp[i] = p2[i];
03667    fView->WCtoNDC(temp, &xpad[3]);
03668    PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
03669 }
03670 
03671 
03672 //______________________________________________________________________________
03673 void TPad::PaintLine3D(Double_t *p1, Double_t *p2)
03674 {
03675    // Paint 3-D line in the CurrentPad.
03676 
03677    //take into account perspective view
03678    if (!fView) return;
03679    // convert from 3-D to 2-D pad coordinate system
03680    Double_t xpad[6];
03681    Double_t temp[3];
03682    Int_t i;
03683    for (i=0;i<3;i++) temp[i] = p1[i];
03684    fView->WCtoNDC(temp, &xpad[0]);
03685    for (i=0;i<3;i++) temp[i] = p2[i];
03686    fView->WCtoNDC(temp, &xpad[3]);
03687    PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
03688 }
03689 
03690 
03691 //______________________________________________________________________________
03692 void TPad::PaintPolyLine(Int_t n, Float_t *x, Float_t *y, Option_t *)
03693 {
03694    // Paint polyline in CurrentPad World coordinates.
03695 
03696    if (n < 2) return;
03697 
03698    Double_t xmin,xmax,ymin,ymax;
03699    if (TestBit(TGraph::kClipFrame)) {
03700       xmin = fUxmin; ymin = fUymin; xmax = fUxmax; ymax = fUymax;
03701    } else {
03702       xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
03703    }
03704    Int_t i, i1=-1,np=1;
03705    for (i=0; i<n-1; i++) {
03706       Double_t x1=x[i];
03707       Double_t y1=y[i];
03708       Double_t x2=x[i+1];
03709       Double_t y2=y[i+1];
03710       Int_t iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
03711       if (iclip == 2) {
03712          i1 = -1;
03713          continue;
03714       }
03715       np++;
03716       if (i1 < 0) i1 = i;
03717       if (iclip == 0 && i < n-2) continue;
03718       if (!gPad->IsBatch())
03719          GetPainter()->DrawPolyLine(np, &x[i1], &y[i1]);
03720       if (gVirtualPS) {
03721          gVirtualPS->DrawPS(np, &x[i1], &y[i1]);
03722       }
03723       if (iclip) {
03724          x[i] = x1;
03725          y[i] = y1;
03726          x[i+1] = x2;
03727          y[i+1] = y2;
03728       }
03729       i1 = -1;
03730       np = 1;
03731    }
03732 
03733    Modified();
03734 }
03735 
03736 
03737 //______________________________________________________________________________
03738 void TPad::PaintPolyLine(Int_t n, Double_t *x, Double_t *y, Option_t *option)
03739 {
03740    // Paint polyline in CurrentPad World coordinates.
03741    //
03742    //  If option[0] == 'C' no clipping
03743 
03744    if (n < 2) return;
03745 
03746    Double_t xmin,xmax,ymin,ymax;
03747    Bool_t mustClip = kTRUE;
03748    if (TestBit(TGraph::kClipFrame)) {
03749       xmin = fUxmin; ymin = fUymin; xmax = fUxmax; ymax = fUymax;
03750    } else {
03751       xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
03752       if (option && (option[0] == 'C')) mustClip = kFALSE;
03753    }
03754 
03755    Int_t i, i1=-1, np=1, iclip=0;
03756 
03757    for (i=0; i < n-1; i++) {
03758       Double_t x1=x[i];
03759       Double_t y1=y[i];
03760       Double_t x2=x[i+1];
03761       Double_t y2=y[i+1];
03762       if (mustClip) {
03763          iclip = Clip(&x[i],&y[i],xmin,ymin,xmax,ymax);
03764          if (iclip == 2) {
03765             i1 = -1;
03766             continue;
03767          }
03768       }
03769       np++;
03770       if (i1 < 0) i1 = i;
03771       if (iclip == 0 && i < n-2) continue;
03772       if (!gPad->IsBatch())
03773          GetPainter()->DrawPolyLine(np, &x[i1], &y[i1]);
03774       if (gVirtualPS) {
03775          gVirtualPS->DrawPS(np, &x[i1], &y[i1]);
03776       }
03777       if (iclip) {
03778          x[i] = x1;
03779          y[i] = y1;
03780          x[i+1] = x2;
03781          y[i+1] = y2;
03782       }
03783       i1 = -1;
03784       np = 1;
03785    }
03786 
03787    Modified();
03788 }
03789 
03790 //______________________________________________________________________________
03791 void TPad::PaintPolyLineNDC(Int_t n, Double_t *x, Double_t *y, Option_t *)
03792 {
03793    // Paint polyline in CurrentPad NDC coordinates.
03794    if (n <=0) return;
03795 
03796    if (!gPad->IsBatch())
03797       GetPainter()->DrawPolyLineNDC(n, x, y);
03798 
03799    if (gVirtualPS) {
03800       Double_t *xw = new Double_t[n];
03801       Double_t *yw = new Double_t[n];
03802       for (Int_t i=0; i<n; i++) {
03803          xw[i] = fX1 + x[i]*(fX2 - fX1);
03804          yw[i] = fY1 + y[i]*(fY2 - fY1);
03805       }
03806       gVirtualPS->DrawPS(n, xw, yw);
03807       delete [] xw;
03808       delete [] yw;
03809    }
03810    Modified();
03811 }
03812 
03813 
03814 //______________________________________________________________________________
03815 void TPad::PaintPolyLine3D(Int_t n, Double_t *p)
03816 {
03817    // Paint 3-D polyline in the CurrentPad.
03818    if (!fView) return;
03819 
03820    // Loop on each individual line
03821    for (Int_t i = 1; i < n; i++)
03822       PaintLine3D(&p[3*i-3], &p[3*i]);
03823 
03824    Modified();
03825 }
03826 
03827 
03828 //______________________________________________________________________________
03829 void TPad::PaintPolyMarker(Int_t nn, Float_t *x, Float_t *y, Option_t *)
03830 {
03831    // Paint polymarker in CurrentPad World coordinates.
03832 
03833    Int_t n = TMath::Abs(nn);
03834    Double_t xmin,xmax,ymin,ymax;
03835    if (nn > 0 || TestBit(TGraph::kClipFrame)) {
03836       xmin = fUxmin; ymin = fUymin; xmax = fUxmax; ymax = fUymax;
03837    } else {
03838       xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
03839    }
03840    Int_t i,i1=-1,np=0;
03841    for (i=0; i<n; i++) {
03842       if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
03843          np++;
03844          if (i1 < 0) i1 = i;
03845          if (i < n-1) continue;
03846       }
03847       if (np == 0) continue;
03848       if (!gPad->IsBatch())
03849          GetPainter()->DrawPolyMarker(np, &x[i1], &y[i1]);
03850       if (gVirtualPS) {
03851          gVirtualPS->DrawPolyMarker(np, &x[i1], &y[i1]);
03852       }
03853       i1 = -1;
03854       np = 0;
03855    }
03856    Modified();
03857 }
03858 
03859 
03860 //______________________________________________________________________________
03861 void TPad::PaintPolyMarker(Int_t nn, Double_t *x, Double_t *y, Option_t *)
03862 {
03863    // Paint polymarker in CurrentPad World coordinates.
03864 
03865    Int_t n = TMath::Abs(nn);
03866    Double_t xmin,xmax,ymin,ymax;
03867    if (nn > 0 || TestBit(TGraph::kClipFrame)) {
03868       xmin = fUxmin; ymin = fUymin; xmax = fUxmax; ymax = fUymax;
03869    } else {
03870       xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
03871    }
03872    Int_t i,i1=-1,np=0;
03873    for (i=0; i<n; i++) {
03874       if (x[i] >= xmin && x[i] <= xmax && y[i] >= ymin && y[i] <= ymax) {
03875          np++;
03876          if (i1 < 0) i1 = i;
03877          if (i < n-1) continue;
03878       }
03879       if (np == 0) continue;
03880       if (!gPad->IsBatch())
03881          GetPainter()->DrawPolyMarker(np, &x[i1], &y[i1]);
03882       if (gVirtualPS) {
03883          gVirtualPS->DrawPolyMarker(np, &x[i1], &y[i1]);
03884       }
03885       i1 = -1;
03886       np = 0;
03887    }
03888    Modified();
03889 }
03890 
03891 
03892 //______________________________________________________________________________
03893 void TPad::PaintText(Double_t x, Double_t y, const char *text)
03894 {
03895    // Paint text in CurrentPad World coordinates.
03896 
03897    Modified();
03898 
03899    if (!gPad->IsBatch())
03900       GetPainter()->DrawText(x, y, text, TVirtualPadPainter::kClear);
03901 
03902    if (gVirtualPS) gVirtualPS->Text(x, y, text);
03903 }
03904 
03905 
03906 //______________________________________________________________________________
03907 void TPad::PaintTextNDC(Double_t u, Double_t v, const char *text)
03908 {
03909    // Paint text in CurrentPad NDC coordinates.
03910 
03911    Modified();
03912 
03913    if (!gPad->IsBatch())
03914       GetPainter()->DrawTextNDC(u, v, text, TVirtualPadPainter::kClear);
03915 
03916    if (gVirtualPS) {
03917       Double_t x = fX1 + u*(fX2 - fX1);
03918       Double_t y = fY1 + v*(fY2 - fY1);
03919       gVirtualPS->Text(x, y, text);
03920    }
03921 }
03922 
03923 
03924 //______________________________________________________________________________
03925 TPad *TPad::Pick(Int_t px, Int_t py, TObjLink *&pickobj)
03926 {
03927    // Search for an object at pixel position px,py.
03928    //
03929    //  Check if point is in this pad.
03930    //  If yes, check if it is in one of the subpads
03931    //  If found in the pad, compute closest distance of approach
03932    //  to each primitive.
03933    //  If one distance of approach is found to be within the limit Distancemaximum
03934    //  the corresponding primitive is selected and the routine returns.
03935    //
03936 
03937    //the two following statements are necessary under NT (multithreaded)
03938    //when a TCanvas object is being created and a thread calling TPad::Pick
03939    //before the TPad constructor has completed in the other thread
03940    if (gPad == 0) return 0; //Andy Haas
03941    if (GetListOfPrimitives() == 0) return 0; //Andy Haas
03942 
03943    Int_t dist;
03944    // Search if point is in pad itself
03945    Double_t x = AbsPixeltoX(px);
03946    Double_t y = AbsPixeltoY(py);
03947    if (this != gPad->GetCanvas()) {
03948       if (!((x >= fX1 && x <= fX2) && (y >= fY1 && y <= fY2))) return 0;
03949    }
03950 
03951    // search for a primitive in this pad or its subpads
03952    static TObjOptLink dummyLink(0,"");  //place holder for when no link available
03953    TPad *padsav = (TPad*)gPad;
03954    gPad  = this;    // since no drawing will be done, don't use cd() for efficiency reasons
03955    TPad *pick   = 0;
03956    TPad *picked = this;
03957    pickobj      = 0;
03958    if (DistancetoPrimitive(px,py) < fgMaxPickDistance) {
03959       dummyLink.SetObject(this);
03960       pickobj = &dummyLink;
03961    }
03962 
03963    // Loop backwards over the list of primitives. The first non-pad primitive
03964    // found is the selected one. However, we have to keep going down the
03965    // list to see if there is maybe a pad overlaying the primitive. In that
03966    // case look into the pad for a possible primitive. Once a pad has been
03967    // found we can terminate the loop.
03968    Bool_t gotPrim = kFALSE;      // true if found a non pad primitive
03969    TObjLink *lnk = GetListOfPrimitives()->LastLink();
03970 
03971    //We can have 3d stuff in pad. If canvas prefers to draw
03972    //such stuff with OpenGL, the selection of 3d objects is
03973    //a gl viewer business so, in first cycle we do not
03974    //call DistancetoPrimitive for TAtt3D descendants.
03975    //In case of gl we first try to select 2d object first.
03976 
03977    while (lnk) {
03978       TObject *obj = lnk->GetObject();
03979 
03980       //If canvas prefers GL, all 3d objects must be drawn/selected by
03981       //gl viewer
03982       if (obj->InheritsFrom(TAtt3D::Class()) && fEmbeddedGL) {
03983          lnk = lnk->Prev();
03984          continue;
03985       }
03986 
03987       fPadPointer  = obj;
03988       if (obj->InheritsFrom(TPad::Class())) {
03989          pick = ((TPad*)obj)->Pick(px, py, pickobj);
03990          if (pick) {
03991             picked = pick;
03992             break;
03993          }
03994       } else if (!gROOT->GetEditorMode()) {
03995          if (!gotPrim) {
03996             if (!obj->TestBit(kCannotPick)) {
03997                dist = obj->DistancetoPrimitive(px, py);
03998                if (dist < fgMaxPickDistance) {
03999                   pickobj = lnk;
04000                   gotPrim = kTRUE;
04001                   if (dist == 0) break;
04002                }
04003             }
04004          }
04005       }
04006 
04007       lnk = lnk->Prev();
04008    }
04009 
04010    //if no primitive found, check if we have a TView
04011    //if yes, return the view except if you are in the lower or upper X range
04012    //of the pad.
04013    //In case canvas prefers gl, fView existance
04014    //automatically means viewer3d existance. (?)
04015 
04016    if (fView && !gotPrim) {
04017       Double_t dx = 0.05*(fUxmax-fUxmin);
04018       if ((x > fUxmin + dx) && (x < fUxmax-dx)) {
04019 
04020          if (fEmbeddedGL) {
04021             //No 2d stuff was selected, but we have gl-viewer. Let it select an object in
04022             //scene (or select itself). In any case it'll internally call
04023             //gPad->SetSelected(ptr) as, for example, hist painter does.
04024             py -= Int_t((1 - GetHNDC() - GetYlowNDC()) * GetWh());
04025             px -= Int_t(GetXlowNDC() * GetWw());
04026             fViewer3D->DistancetoPrimitive(px, py);
04027          }
04028          else
04029             dummyLink.SetObject(fView);
04030       }
04031    }
04032 
04033    if (picked->InheritsFrom(TButton::Class())) {
04034       TButton *button = (TButton*)picked;
04035       if (!button->IsEditable()) pickobj = 0;
04036    }
04037 
04038    gPad = padsav;
04039    return picked;
04040 }
04041 
04042 
04043 //___________________________________________________________________________
04044 void TPad::Pop()
04045 {
04046    // Pop pad to the top of the stack.
04047 
04048    if (!fMother) return;
04049    if (!fPrimitives) fPrimitives = new TList;
04050    if (this == fMother->GetListOfPrimitives()->Last()) return;
04051 
04052    TListIter next(fMother->GetListOfPrimitives());
04053    TObject *obj;
04054    while ((obj = next()))
04055       if (obj == this) {
04056          char *opt = StrDup(next.GetOption());
04057          fMother->GetListOfPrimitives()->Remove(this);
04058          fMother->GetListOfPrimitives()->AddLast(this, opt);
04059          delete [] opt;
04060          return;
04061       }
04062 }
04063 
04064 
04065 //______________________________________________________________________________
04066 void TPad::Print(const char *filename) const
04067 {
04068    // Save Pad contents in a file in one of various formats.
04069    //
04070    //   if filename is "", the file produced is padname.ps
04071    //   if filename starts with a dot, the padname is added in front
04072    //   if filename contains .eps, an Encapsulated Postscript file is produced
04073    //   if filename contains .gif, a GIF file is produced
04074    //   if filename contains .gif+NN, an animated GIF file is produced
04075    //   if filename contains .C or .cxx, a C++ macro file is produced
04076    //   if filename contains .root, a Root file is produced
04077    //   if filename contains .xml,  a XML file is produced
04078    //
04079    //  See comments in TPad::SaveAs or the TPad::Print function below
04080 
04081    ((TPad*)this)->SaveAs(filename);
04082 }
04083 
04084 
04085 //______________________________________________________________________________
04086 static Bool_t ContainsTImage(TList *li)
04087 {
04088    // auxilary function. Returns kTRUE if list contains an object inherited
04089    // from TImage
04090 
04091    TIter next(li);
04092    TObject *obj;
04093 
04094    while ((obj = next())) {
04095       if (obj->InheritsFrom(TImage::Class())) {
04096          return kTRUE;
04097       } else if (obj->InheritsFrom(TPad::Class())) {
04098          if (ContainsTImage(((TPad*)obj)->GetListOfPrimitives())) {
04099             return kTRUE;
04100          }
04101       }
04102    }
04103    return kFALSE;
04104 }
04105 
04106 
04107 //______________________________________________________________________________
04108 void TPad::Print(const char *filenam, Option_t *option)
04109 {
04110    // Save Pad contents in a file in one of various formats.
04111    //
04112    //   if option  =  0   - as "ps"
04113    //               "ps"  - Postscript file is produced (see special cases below)
04114    //          "Portrait" - Postscript file is produced (Portrait)
04115    //         "Landscape" - Postscript file is produced (Landscape)
04116    //            "Title:" - The character strin after "Title:" becomes a table
04117    //                       of content entry.
04118    //               "eps" - an Encapsulated Postscript file is produced
04119    //           "Preview" - an Encapsulated Postscript file with preview is produced.
04120    //               "pdf" - a PDF file is produced
04121    //               "svg" - a SVG file is produced
04122    //               "gif" - a GIF file is produced
04123    //            "gif+NN" - an animated GIF file is produced, where NN is delay in 10ms units
04124    //               "xpm" - a XPM file is produced
04125    //               "png" - a PNG file is produced
04126    //               "jpg" - a JPEG file is produced.
04127    //                       NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
04128    //              "tiff" - a TIFF file is produced
04129    //               "cxx" - a C++ macro file is produced
04130    //               "xml" - a XML file
04131    //              "root" - a ROOT binary file
04132    //
04133    //     filename = 0 - filename  is defined by the GetName and its
04134    //                    extension is defined with the option
04135    //
04136    //   When Postscript output is selected (ps, eps), the pad is saved
04137    //   to filename.ps or filename.eps. The aspect ratio of the pad is preserved
04138    //   on the Postscript file. When the "ps" option is selected, the Postscript
04139    //   page will be landscape format if the pad is in landscape format, otherwise
04140    //   portrait format is selected.
04141    //   The physical size of the Postscript page is the one selected in the
04142    //   current style. This size can be modified via TStyle::SetPaperSize.
04143    //   Examples:
04144    //        gStyle->SetPaperSize(kA4);  //default
04145    //        gStyle->SetPaperSize(kUSLetter);
04146    //     where kA4 and kUSLetter are defined in the enum EPaperSize in TStyle.h
04147    //    An alternative is to call:
04148    //        gStyle->SetPaperSize(20,26);  same as kA4
04149    // or     gStyle->SetPaperSize(20,24);  same as kUSLetter
04150    //   The above numbers take into account some margins and are in centimeters.
04151    //
04152    //  The "Preview" option allows to generate a preview (in the TIFF format) within
04153    //  the Encapsulated Postscript file. This preview can be used by programs like
04154    //  MSWord to visualize the picture on screen. The "Preview" option relies on the
04155    //  epstool command (http://www.cs.wisc.edu/~ghost/gsview/epstool.htm).
04156    //  Example:
04157    //     canvas->Print("example.eps","Preview");
04158    //
04159    //  To generate a Postscript file containing more than one picture, see
04160    //  class TPostScript.
04161    //
04162    //   Writing several canvases to the same Postscript or PDF file:
04163    //   ------------------------------------------------------------
04164    // if the Postscript or PDF file name finishes with "(", the file is not closed
04165    // if the Postscript or PDF file name finishes with ")" and the file has been opened
04166    // with "(", the file is closed. Example:
04167    //
04168    // {
04169    //    TCanvas c1("c1");
04170    //    h1.Draw();
04171    //    c1.Print("c1.ps("); //write canvas and keep the ps file open
04172    //    h2.Draw();
04173    //    c1.Print("c1.ps"); canvas is added to "c1.ps"
04174    //    h3.Draw();
04175    //    c1.Print("c1.ps)"); canvas is added to "c1.ps" and ps file is closed
04176    // }
04177    //
04178    //  In the previous example replacing "ps" by "pdf" will create a multi-pages PDF file.
04179    //
04180    //  Note that the following sequence writes the canvas to "c1.ps" and closes the ps file.:
04181    //    TCanvas c1("c1");
04182    //    h1.Draw();
04183    //    c1.Print("c1.ps");
04184    //
04185    //  The TCanvas::Print("file.ps(") mechanism is very useful, but it can be
04186    //  a little inconvenient to have the action of opening/closing a file
04187    //  being atomic with printing a page. Particularly if pages are being
04188    //  generated in some loop one needs to detect the special cases of first
04189    //  and last page and then munge the argument to Print() accordingly.
04190    //
04191    //  The "[" and "]" can be used instead of "(" and ")".  Example:
04192    //
04193    //    c1.Print("file.ps[");   // No actual print, just open file.ps
04194    //    for (int i=0; i<10; ++i) {
04195    //      // fill canvas for context i
04196    //      // ...
04197    //
04198    //      c1.Print("file.ps");  // actually print canvas to file
04199    //    }// end loop
04200    //    c1.Print("file.ps]");   // No actual print, just close.
04201    //
04202    // As before, the same macro is valid for PDF files.
04203    //
04204    // It is possible to print a pad into an animated GIF file by specifying the
04205    // file name as "myfile.gif+" or "myfile.gif+NN", where NN*10ms is delay
04206    // between the subimages' display. If NN is ommitted the delay between
04207    // subimages is zero. Each picture is added in the animation thanks to a loop
04208    // similar to the following one:
04209    //
04210    //    for (int i=0; i<10; ++i) {
04211    //      // fill canvas for context i
04212    //      // ...
04213    //
04214    //      c1.Print("file.gif+5");  // print canvas to GIF file with 50ms delays
04215    //    }// end loop
04216    //
04217    // The delay between each frame must be specified in each Print() statement.
04218 
04219    TString psname, fs1, fs2;
04220    char *filename;
04221 
04222    // "[" and "]" are special characters for ExpandPathName. When they are at the end
04223    // of the file name (see help) they must be removed before doing ExpandPathName.
04224    fs1 = filenam;
04225    if (fs1.EndsWith("[")) {
04226       fs1.Replace((fs1.Length()-1),1," ");
04227       fs2 = gSystem->ExpandPathName(fs1.Data());
04228       fs2.Replace((fs2.Length()-1),1,"[");
04229    } else if (fs1.EndsWith("]")) {
04230       fs1.Replace((fs1.Length()-1),1," ");
04231       fs2 = gSystem->ExpandPathName(fs1.Data());
04232       fs2.Replace((fs2.Length()-1),1,"]");
04233    } else {
04234       char* exppath = gSystem->ExpandPathName(fs1.Data());
04235       fs2 = exppath;
04236       delete [] exppath;
04237    }
04238    filename = (char*)fs2.Data();
04239 
04240    Int_t lenfil =  filename ? strlen(filename) : 0;
04241    const char *opt = option;
04242    Bool_t image = kFALSE;
04243 
04244    // Set the default option as "Postscript" (Should be a data member of TPad)
04245    const char *opt_default="ps";
04246    if( !opt ) opt = opt_default;
04247 
04248    if ( !lenfil )  {
04249       psname = GetName();
04250       psname += opt;
04251    } else {
04252       psname = filename;
04253    }
04254 
04255    // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
04256    if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
04257       psname = GetName();
04258       psname.Append(filename);
04259       psname.Prepend("/");
04260       psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
04261    }
04262    if (!gPad->IsBatch() && fCanvas)
04263       GetPainter()->SelectDrawable(GetCanvasID());
04264 
04265    // Save pad/canvas in alternative formats
04266    TImage::EImageFileTypes gtype = TImage::kUnknown;
04267    if (strstr(opt, "gif+")) {
04268       gtype = TImage::kAnimGif;
04269       image = kTRUE;
04270    } else if (strstr(opt, "gif")) {
04271       gtype = TImage::kGif;
04272       image = kTRUE;
04273    } else if (strstr(opt, "png")) {
04274       gtype = TImage::kPng;
04275       image = kTRUE;
04276    } else if (strstr(opt, "jpg")) {
04277       gtype = TImage::kJpeg;
04278       image = kTRUE;
04279    } else if (strstr(opt, "tiff")) {
04280       gtype = TImage::kTiff;
04281       image = kTRUE;
04282    } else if (strstr(opt, "xpm")) {
04283       gtype = TImage::kXpm;
04284       image = kTRUE;
04285    } else if (strstr(opt, "bmp")) {
04286       gtype = TImage::kBmp;
04287       image = kTRUE;
04288    }
04289 
04290    Int_t wid = 0;
04291    if (!GetCanvas()) return;
04292    if (!gROOT->IsBatch() && image) {
04293       if ((gtype == TImage::kGif) && !ContainsTImage(fPrimitives)) {
04294          wid = (this == GetCanvas()) ? GetCanvas()->GetCanvasID() : GetPixmapID();
04295          Color_t hc = gPad->GetCanvas()->GetHighLightColor();
04296          gPad->GetCanvas()->SetHighLightColor(-1);
04297          gPad->Modified();
04298          gPad->Update();
04299          GetPainter()->SelectDrawable(wid);
04300          GetPainter()->SaveImage(this, psname.Data(), gtype);
04301          if (!gSystem->AccessPathName(psname.Data())) {
04302             Info("Print", "GIF file %s has been created", psname.Data());
04303          }
04304          gPad->GetCanvas()->SetHighLightColor(hc);
04305          return;
04306       }
04307       if (gtype != TImage::kUnknown) {
04308          Color_t hc = gPad->GetCanvas()->GetHighLightColor();
04309          gPad->GetCanvas()->SetHighLightColor(-1);
04310          gPad->Modified();
04311          gPad->Update();
04312          if (gVirtualX->InheritsFrom("TGQt")) {
04313             wid = (this == GetCanvas()) ? GetCanvas()->GetCanvasID() : GetPixmapID();
04314             gVirtualX->WritePixmap(wid,UtoPixel(1.),VtoPixel(0.),(char *)psname.Data());
04315          } else {
04316             Int_t saver = gErrorIgnoreLevel;
04317             gErrorIgnoreLevel = kFatal;
04318             gVirtualX->Update(1);
04319             gSystem->Sleep(30); // syncronize
04320             GetPainter()->SaveImage(this, psname, gtype);
04321             gErrorIgnoreLevel = saver;
04322          }
04323          if (!gSystem->AccessPathName(psname)) {
04324             Info("Print", "file %s has been created", psname.Data());
04325          }
04326          gPad->GetCanvas()->SetHighLightColor(hc);
04327       } else {
04328          Warning("Print", "Unsupported image format %s", psname.Data());
04329       }
04330       return;
04331    }
04332 
04333    //==============Save pad/canvas as a C++ script==============================
04334    if (strstr(opt,"cxx")) {
04335       GetCanvas()->SaveSource(psname, "");
04336       return;
04337    }
04338 
04339    //==============Save pad/canvas as a root file===============================
04340    if (strstr(opt,"root")) {
04341       if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
04342       return;
04343    }
04344 
04345    //==============Save pad/canvas as a XML file================================
04346    if (strstr(opt,"xml")) {
04347       // Plugin XML driver
04348       if (gDirectory) gDirectory->SaveObjectAs(this,psname.Data(),"");
04349       return;
04350    }
04351 
04352    //==============Save pad/canvas as a SVG file================================
04353    if (strstr(opt,"svg")) {
04354       gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
04355 
04356       Bool_t noScreen = kFALSE;
04357       if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
04358          noScreen = kTRUE;
04359          GetCanvas()->SetBatch(kTRUE);
04360       }
04361 
04362       TPad *padsav = (TPad*)gPad;
04363       cd();
04364       TVirtualPS *psave = gVirtualPS;
04365 
04366       if (!gVirtualPS) {
04367          // Plugin Postscript/SVG driver
04368          TPluginHandler *h;
04369          if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "svg"))) {
04370             if (h->LoadPlugin() == -1)
04371                return;
04372             h->ExecPlugin(0);
04373          }
04374       }
04375 
04376       // Create a new SVG file
04377       gVirtualPS->SetName(psname);
04378       gVirtualPS->Open(psname);
04379       gVirtualPS->SetBit(kPrintingPS);
04380       gVirtualPS->NewPage();
04381       Paint();
04382       if (noScreen)  GetCanvas()->SetBatch(kFALSE);
04383 
04384       if (!gSystem->AccessPathName(psname)) Info("Print", "SVG file %s has been created", psname.Data());
04385 
04386       delete gVirtualPS;
04387       gVirtualPS = psave;
04388       gVirtualPS = 0;
04389       padsav->cd();
04390 
04391       return;
04392    }
04393 
04394    //==============Save pad/canvas as a Postscript file=========================
04395 
04396    // in case we read directly from a Root file and the canvas
04397    // is not on the screen, set batch mode
04398 
04399    char *l;
04400    Bool_t mustOpen  = kTRUE;
04401    Bool_t mustClose = kTRUE;
04402    char *copen=0, *cclose=0, *copenb=0, *ccloseb=0;
04403    if (!image) {
04404       // The parenthesis mechanism is only valid for PS and PDF files.
04405       copen   = (char*)strstr(psname.Data(),"("); if (copen)   *copen   = 0;
04406       cclose  = (char*)strstr(psname.Data(),")"); if (cclose)  *cclose  = 0;
04407       copenb  = (char*)strstr(psname.Data(),"["); if (copenb)  *copenb  = 0;
04408       ccloseb = (char*)strstr(psname.Data(),"]"); if (ccloseb) *ccloseb = 0;
04409    }
04410    gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
04411    if (gVirtualPS) {mustOpen = kFALSE; mustClose = kFALSE;}
04412    if (copen  || copenb)  mustClose = kFALSE;
04413    if (cclose || ccloseb) mustClose = kTRUE;
04414 
04415    Bool_t noScreen = kFALSE;
04416    if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
04417       noScreen = kTRUE;
04418       GetCanvas()->SetBatch(kTRUE);
04419    }
04420    Int_t pstype = 111;
04421    Double_t xcanvas = GetCanvas()->XtoPixel(GetCanvas()->GetX2());
04422    Double_t ycanvas = GetCanvas()->YtoPixel(GetCanvas()->GetY1());
04423    Double_t ratio   = ycanvas/xcanvas;
04424    if (ratio < 1)               pstype = 112;
04425    if (strstr(opt,"Portrait"))  pstype = 111;
04426    if (strstr(opt,"Landscape")) pstype = 112;
04427    if (strstr(opt,"eps"))       pstype = 113;
04428    if (strstr(opt,"Preview"))   pstype = 113;
04429    TPad *padsav = (TPad*)gPad;
04430    cd();
04431    TVirtualPS *psave = gVirtualPS;
04432 
04433    if (!gVirtualPS || mustOpen) {
04434       // Plugin Postscript driver
04435       TPluginHandler *h;
04436       if (strstr(opt,"pdf") || strstr(opt,"Title:")) {
04437          if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "pdf"))) {
04438             if (h->LoadPlugin() == -1) return;
04439             h->ExecPlugin(0);
04440          }
04441       } else if (image) {
04442          // Plugin TImageDump driver
04443          if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "image"))) {
04444             if (h->LoadPlugin() == -1) return;
04445             h->ExecPlugin(0);
04446          }
04447       } else {
04448          if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "ps"))) {
04449             if (h->LoadPlugin() == -1) return;
04450             h->ExecPlugin(0);
04451          }
04452       }
04453 
04454       // Create a new Postscript, PDF or image file
04455       gVirtualPS->SetName(psname);
04456       l = (char*)strstr(opt,"Title:");
04457       if (l) {
04458          gVirtualPS->SetTitle(&opt[6]);
04459          //Please fix this bug, we may overwrite an input argument
04460          strcpy(l,"pdf");
04461       }
04462       gVirtualPS->Open(psname,pstype);
04463       gVirtualPS->SetBit(kPrintingPS);
04464       if (!copenb) {
04465          if (!strstr(opt,"pdf") || image) gVirtualPS->NewPage();
04466          Paint();
04467       }
04468       if (noScreen) GetCanvas()->SetBatch(kFALSE);
04469       if (!gSystem->AccessPathName(psname)) Info("Print", "%s file %s has been created", opt, psname.Data());
04470 
04471       if (mustClose) {
04472          gROOT->GetListOfSpecials()->Remove(gVirtualPS);
04473          delete gVirtualPS;
04474          gVirtualPS = psave;
04475       } else {
04476          gROOT->GetListOfSpecials()->Add(gVirtualPS);
04477          gVirtualPS = 0;
04478       }
04479    } else {
04480       // Append to existing Postscript, PDF or GIF file
04481       if (!ccloseb) {
04482          gVirtualPS->NewPage();
04483          Paint();
04484       }
04485       l = (char*)strstr(opt,"Title:");
04486       if (l) {
04487          gVirtualPS->SetTitle(&opt[6]);
04488          //Please fix this bug, we may overwrite an input argument
04489          strcpy(l,"pdf");
04490       }
04491       Info("Print", "Current canvas added to %s file %s", opt, psname.Data());
04492       if (mustClose) {
04493          gROOT->GetListOfSpecials()->Remove(gVirtualPS);
04494          delete gVirtualPS;
04495          gVirtualPS = 0;
04496       } else {
04497          gVirtualPS = 0;
04498       }
04499    }
04500 
04501    if (strstr(opt,"Preview")) gSystem->Exec(Form("epstool --quiet -t6p %s %s",psname.Data(),psname.Data()));
04502 
04503    padsav->cd();
04504 }
04505 
04506 
04507 //______________________________________________________________________________
04508 void TPad::Range(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
04509 {
04510    // Set world coordinate system for the pad.
04511    // Emits signal "RangeChanged()", in the slot get the range
04512    // via GetRange().
04513 
04514    if ((x1 >= x2) || (y1 >= y2)) {
04515       Error("Range", "illegal world coordinates range: x1=%f, y1=%f, x2=%f, y2=%f",x1,y1,x2,y2);
04516       return;
04517    }
04518 
04519    fUxmin = x1;
04520    fUxmax = x2;
04521    fUymin = y1;
04522    fUymax = y2;
04523 
04524    if (fX1 == x1 && fY1 == y1 && fX2 == x2 && fY2 == y2) return;
04525 
04526    fX1  = x1;
04527    fY1  = y1;
04528    fX2  = x2;
04529    fY2  = y2;
04530 
04531    // compute pad conversion coefficients
04532    ResizePad();
04533 
04534    if (gPad == this)
04535       GetPainter()->InvalidateCS();
04536 
04537    // emit signal
04538    RangeChanged();
04539 }
04540 
04541 
04542 //______________________________________________________________________________
04543 void TPad::RangeAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax)
04544 {
04545    // Set axis coordinate system for the pad.
04546    // The axis coordinate system is a subset of the world coordinate system
04547    // xmin,ymin is the origin of the current coordinate system,
04548    // xmax is the end of the X axis, ymax is the end of the Y axis.
04549    // By default a margin of 10 per cent is left on all sides of the pad
04550    // Emits signal "RangeAxisChanged()", in the slot get the axis range
04551    // via GetRangeAxis().
04552 
04553    if ((xmin >= xmax) || (ymin >= ymax)) {
04554       Error("RangeAxis", "illegal axis coordinates range: xmin=%f, ymin=%f, xmax=%f, ymax=%f",
04555             xmin, ymin, xmax, ymax);
04556       return;
04557    }
04558 
04559    fUxmin  = xmin;
04560    fUymin  = ymin;
04561    fUxmax  = xmax;
04562    fUymax  = ymax;
04563 
04564    // emit signal
04565    RangeAxisChanged();
04566 }
04567 
04568 
04569 //______________________________________________________________________________
04570 void TPad::RecursiveRemove(TObject *obj)
04571 {
04572    // Recursively remove object from a pad and its subpads.
04573 
04574    if (obj == fCanvas->GetSelected()) fCanvas->SetSelected(0);
04575    if (obj == fCanvas->GetClickSelected()) fCanvas->SetClickSelected(0);
04576    if (obj == fView) fView = 0;
04577    if (!fPrimitives) return;
04578    Int_t nold = fPrimitives->GetSize();
04579    fPrimitives->RecursiveRemove(obj);
04580    if (nold != fPrimitives->GetSize()) fModified = kTRUE;
04581 }
04582 
04583 
04584 //______________________________________________________________________________
04585 void TPad::RedrawAxis(Option_t *option)
04586 {
04587    //  Redraw the frame axis
04588    //  Redrawing axis may be necessary in case of superimposed histograms
04589    //  when one or more histograms have a fill color
04590    //  Instead of calling this function, it may be more convenient
04591    //  to call directly h1->Draw("sameaxis") where h1 is the pointer
04592    //  to the first histogram drawn in the pad.
04593    //
04594    //  By default, if the pad has the options gridx or/and gridy activated,
04595    //  the grid is not drawn by this function.
04596    //  if option="g" is specified, this will force the drawing of the grid
04597    //  on top of the picture
04598 
04599    // get first histogram in the list of primitives
04600    TString opt = option;
04601    opt.ToLower();
04602 
04603    TPad *padsav = (TPad*)gPad;
04604    cd();
04605 
04606    if (!fPrimitives) fPrimitives = new TList;
04607    TIter next(fPrimitives);
04608    TObject *obj;
04609    while ((obj = next())) {
04610       if (obj->InheritsFrom(TH1::Class())) {
04611          TH1 *hobj = (TH1*)obj;
04612          if (opt.Contains("g")) hobj->DrawCopy("sameaxig");
04613          else                   hobj->DrawCopy("sameaxis");
04614          return;
04615       }
04616       if (obj->InheritsFrom(TMultiGraph::Class())) {
04617          TMultiGraph *mg = (TMultiGraph*)obj;
04618          if (mg) mg->GetHistogram()->DrawCopy("sameaxis");
04619          return;
04620       }
04621       if (obj->InheritsFrom(TGraph::Class())) {
04622          TGraph *g = (TGraph*)obj;
04623          if (g) g->GetHistogram()->DrawCopy("sameaxis");
04624          return;
04625       }
04626       if (obj->InheritsFrom(THStack::Class())) {
04627          THStack *hs = (THStack*)obj;
04628          if (hs) hs->GetHistogram()->DrawCopy("sameaxis");
04629          return;
04630       }
04631    }
04632 
04633    if (padsav) padsav->cd();
04634 }
04635 
04636 
04637 //______________________________________________________________________________
04638 void TPad::ResizePad(Option_t *option)
04639 {
04640    // Compute pad conversion coefficients.
04641    //
04642    //   Conversion from x to px & y to py
04643    //   =================================
04644    //
04645    //       x - xmin     px - pxlow              xrange  = xmax-xmin
04646    //       --------  =  ----------      with
04647    //        xrange        pxrange               pxrange = pxmax-pxmin
04648    //
04649    //               pxrange(x-xmin)
04650    //   ==>  px =   ---------------  + pxlow   = fXtoPixelk + fXtoPixel * x
04651    //                    xrange
04652    //
04653    //   ==>  fXtoPixelk = pxlow - pxrange*xmin/xrange
04654    //        fXtoPixel  = pxrange/xrange
04655    //           where  pxlow   = fAbsXlowNDC*fCw
04656    //                  pxrange = fAbsWNDC*fCw
04657    //
04658    //
04659    //       y - ymin     py - pylow              yrange  = ymax-ymin
04660    //       --------  =  ----------      with
04661    //        yrange        pyrange               pyrange = pymax-pymin
04662    //
04663    //               pyrange(y-ymin)
04664    //   ==>  py =   ---------------  + pylow   = fYtoPixelk + fYtoPixel * y
04665    //                    yrange
04666    //
04667    //   ==>  fYtoPixelk = pylow - pyrange*ymin/yrange
04668    //        fYtoPixel  = pyrange/yrange
04669    //           where  pylow   = (1-fAbsYlowNDC)*fCh
04670    //                  pyrange = -fAbsHNDC*fCh
04671    //
04672    //-  Conversion from px to x & py to y
04673    //   =================================
04674    //
04675    //             xrange(px-pxlow)
04676    //   ==>  x =  ----------------  + xmin  = fPixeltoXk + fPixeltoX * px
04677    //                 pxrange
04678    //-
04679    //   ==>  fPixeltoXk = xmin - pxlow*xrange/pxrange
04680    //        fPixeltoX  = xrange/pxrange
04681    //
04682    //             yrange(py-pylow)
04683    //   ==>  y =  ----------------  + ymin  = fPixeltoYk + fPixeltoY * py
04684    //                 pyrange
04685    //-
04686    //   ==>  fPixeltoYk = ymin - pylow*yrange/pyrange
04687    //        fPixeltoY  = yrange/pyrange
04688    //
04689    //-----------------------------------------------------------------------
04690    //
04691    //  Computation of the coefficients in case of LOG scales
04692    //- =====================================================
04693    //
04694    //   A, Conversion from pixel coordinates to world coordinates
04695    //
04696    //       Log(x) - Log(xmin)      Log(x/xmin)       px - pxlow
04697    //  u = --------------------- =  -------------  =  -----------
04698    //      Log(xmax) - Log(xmin)    Log(xmax/xmin)     pxrange
04699    //
04700    //  ==> Log(x/xmin) = u*Log(xmax/xmin)
04701    //      x = xmin*exp(u*Log(xmax/xmin)
04702    //   Let alfa = Log(xmax/xmin)/fAbsWNDC
04703    //
04704    //      x = xmin*exp(-alfa*pxlow) + exp(alfa*px)
04705    //      x = fPixeltoXk*exp(fPixeltoX*px)
04706    //  ==> fPixeltoXk = xmin*exp(-alfa*pxlow)
04707    //      fPixeltoX  = alfa
04708    //
04709    //       Log(y) - Log(ymin)      Log(y/ymin)       pylow - py
04710    //  v = --------------------- =  -------------  =  -----------
04711    //      Log(ymax) - Log(ymin)    Log(ymax/ymin)     pyrange
04712    //
04713    //   Let beta = Log(ymax/ymin)/pyrange
04714    //      Log(y/ymin) = beta*pylow - beta*py
04715    //      y/ymin = exp(beta*pylow - beta*py)
04716    //      y = ymin*exp(beta*pylow)*exp(-beta*py)
04717    //  ==> y = fPixeltoYk*exp(fPixeltoY*py)
04718    //      fPixeltoYk = ymin*exp(beta*pylow)
04719    //      fPixeltoY  = -beta
04720    //
04721    //-  B, Conversion from World coordinates to pixel coordinates
04722    //
04723    //  px = pxlow + u*pxrange
04724    //     = pxlow + Log(x/xmin)/alfa
04725    //     = pxlow -Log(xmin)/alfa  + Log(x)/alfa
04726    //     = fXtoPixelk + fXtoPixel*Log(x)
04727    //  ==> fXtoPixelk = pxlow -Log(xmin)/alfa
04728    //  ==> fXtoPixel  = 1/alfa
04729    //
04730    //  py = pylow - Log(y/ymin)/beta
04731    //     = fYtoPixelk + fYtoPixel*Log(y)
04732    //  ==> fYtoPixelk = pylow - Log(ymin)/beta
04733    //      fYtoPixel  = 1/beta
04734 
04735    // Recompute subpad positions in case pad has been moved/resized
04736    TPad *parent = fMother;
04737    if (this == gPad->GetCanvas()) {
04738       fAbsXlowNDC  = fXlowNDC;
04739       fAbsYlowNDC  = fYlowNDC;
04740       fAbsWNDC     = fWNDC;
04741       fAbsHNDC     = fHNDC;
04742    }
04743    else {
04744       fAbsXlowNDC  = fXlowNDC*parent->GetAbsWNDC() + parent->GetAbsXlowNDC();
04745       fAbsYlowNDC  = fYlowNDC*parent->GetAbsHNDC() + parent->GetAbsYlowNDC();
04746       fAbsWNDC     = fWNDC*parent->GetAbsWNDC();
04747       fAbsHNDC     = fHNDC*parent->GetAbsHNDC();
04748    }
04749 
04750    Double_t ww = (Double_t)gPad->GetWw();
04751    Double_t wh = (Double_t)gPad->GetWh();
04752    Double_t pxlow   = fAbsXlowNDC*ww;
04753    Double_t pylow   = (1-fAbsYlowNDC)*wh;
04754    Double_t pxrange = fAbsWNDC*ww;
04755    Double_t pyrange = -fAbsHNDC*wh;
04756 
04757    // Linear X axis
04758    Double_t rounding = 0.00005;
04759    Double_t xrange  = fX2 - fX1;
04760    fXtoAbsPixelk = rounding + pxlow - pxrange*fX1/xrange;      //origin at left
04761    fXtoPixelk = rounding +  -pxrange*fX1/xrange;
04762    fXtoPixel  = pxrange/xrange;
04763    fAbsPixeltoXk = fX1 - pxlow*xrange/pxrange;
04764    fPixeltoXk = fX1;
04765    fPixeltoX  = xrange/pxrange;
04766    // Linear Y axis
04767    Double_t yrange  = fY2 - fY1;
04768    fYtoAbsPixelk = rounding + pylow - pyrange*fY1/yrange;      //origin at top
04769    fYtoPixelk = rounding +  -pyrange - pyrange*fY1/yrange;
04770    fYtoPixel  = pyrange/yrange;
04771    fAbsPixeltoYk = fY1 - pylow*yrange/pyrange;
04772    fPixeltoYk = fY1;
04773    fPixeltoY  = yrange/pyrange;
04774 
04775    // Coefficients to convert from pad NDC coordinates to pixel coordinates
04776 
04777    fUtoAbsPixelk = rounding + pxlow;
04778    fUtoPixelk = rounding;
04779    fUtoPixel  = pxrange;
04780    fVtoAbsPixelk = rounding + pylow;
04781    fVtoPixelk = -pyrange;
04782    fVtoPixel  = pyrange;
04783 
04784    // Coefficients to convert from canvas pixels to pad world coordinates
04785 
04786    // Resize all subpads
04787    TObject *obj;
04788    if (!fPrimitives) fPrimitives = new TList;
04789    TIter    next(GetListOfPrimitives());
04790    while ((obj = next())) {
04791       if (obj->InheritsFrom(TPad::Class()))
04792          ((TPad*)obj)->ResizePad(option);
04793    }
04794 
04795    // Reset all current sizes
04796    if (gPad->IsBatch())
04797       fPixmapID = 0;
04798    else {
04799       GetPainter()->SetLineWidth(-1);
04800       GetPainter()->SetTextSize(-1);
04801 
04802       // create or re-create off-screen pixmap
04803       if (fPixmapID) {
04804          int w = TMath::Abs(XtoPixel(fX2) - XtoPixel(fX1));
04805          int h = TMath::Abs(YtoPixel(fY2) - YtoPixel(fY1));
04806          //protection in case of wrong pad parameters.
04807          //without this protection, the OpenPixmap or ResizePixmap crashes with
04808          //the message "Error in <RootX11ErrorHandler>: BadValue (integer parameter out of range for operation)"
04809          //resulting in a frozen xterm
04810          if (!(TMath::Finite(fX1)) || !(TMath::Finite(fX2))
04811              || !(TMath::Finite(fY1)) || !(TMath::Finite(fY2)))
04812             Warning("ResizePad", "Inf/NaN propagated to the pad. Check drawn objects.");
04813          if (w <= 0 || w > 10000) {
04814             Warning("ResizePad", "%s width changed from %d to %d\n",GetName(),w,10);
04815             w = 10;
04816          }
04817          if (h <= 0 || h > 10000) {
04818             Warning("ResizePad", "%s height changed from %d to %d\n",GetName(),h,10);
04819             h = 10;
04820          }
04821          if (fPixmapID == -1) {      // this case is handled via the ctor
04822             fPixmapID = GetPainter()->CreateDrawable(w, h);
04823          } else {
04824             if (gVirtualX->ResizePixmap(fPixmapID, w, h)) {
04825                Modified(kTRUE);
04826             }
04827          }
04828       }
04829    }
04830    if (fView) {
04831       TPad *padsav  = (TPad*)gPad;
04832       if (padsav == this) {
04833          fView->ResizePad();
04834       } else {
04835          cd();
04836          fView->ResizePad();
04837          padsav->cd();
04838       }
04839    }
04840 }
04841 
04842 
04843 //______________________________________________________________________________
04844 void TPad::SaveAs(const char *filename, Option_t * /*option*/) const
04845 {
04846    // Save Pad contents in a file in one of various formats.
04847    //
04848    //   if filename is "", the file produced is padname.ps
04849    //   if filename starts with a dot, the padname is added in front
04850    //   if filename contains .eps, an Encapsulated Postscript file is produced
04851    //   if filename contains .pdf, a PDF file is produced
04852    //   if filename contains .svg, a SVG file is produced
04853    //   if filename contains .gif, a GIF file is produced
04854    //   if filename contains .gif+NN, an  animated GIF file is produced
04855    //   if filename contains .xpm, a XPM file is produced
04856    //   if filename contains .png, a PNG file is produced
04857    //   if filename contains .jpg, a JPEG file is produced
04858    //     NOTE: JPEG's lossy compression will make all sharp edges fuzzy.
04859    //   if filename contains .tiff, a TIFF file is produced
04860    //   if filename contains .C or .cxx, a C++ macro file is produced
04861    //   if filename contains .root, a Root file is produced
04862    //   if filename contains .xml, a XML file is produced
04863    //
04864    //   See comments in TPad::Print for the Postscript formats
04865 
04866    TString psname;
04867    Int_t lenfil =  filename ? strlen(filename) : 0;
04868 
04869    if (!lenfil)  { psname = GetName(); psname.Append(".ps"); }
04870    else            psname = filename;
04871 
04872    // lines below protected against case like c1->SaveAs( "../ps/cs.ps" );
04873    if (psname.BeginsWith('.') && (psname.Contains('/') == 0)) {
04874       psname = GetName();
04875       psname.Append(filename);
04876       psname.Prepend("/");
04877       psname.Prepend(gEnv->GetValue("Canvas.PrintDirectory","."));
04878    }
04879 
04880    if (psname.EndsWith(".gif"))
04881       ((TPad*)this)->Print(psname,"gif");
04882    else if (psname.Contains(".gif+"))
04883       ((TPad*)this)->Print(psname,"gif+");
04884    else if (psname.EndsWith(".C") || psname.EndsWith(".cxx") || psname.EndsWith(".cpp"))
04885       ((TPad*)this)->Print(psname,"cxx");
04886    else if (psname.EndsWith(".root"))
04887       ((TPad*)this)->Print(psname,"root");
04888    else if (psname.EndsWith(".xml"))
04889       ((TPad*)this)->Print(psname,"xml");
04890    else if (psname.EndsWith(".eps"))
04891       ((TPad*)this)->Print(psname,"eps");
04892    else if (psname.EndsWith(".pdf"))
04893       ((TPad*)this)->Print(psname,"pdf");
04894    else if (psname.EndsWith(".pdf["))
04895       ((TPad*)this)->Print(psname,"pdf");
04896    else if (psname.EndsWith(".pdf]"))
04897       ((TPad*)this)->Print(psname,"pdf");
04898    else if (psname.EndsWith(".pdf("))
04899       ((TPad*)this)->Print(psname,"pdf");
04900    else if (psname.EndsWith(".pdf)"))
04901       ((TPad*)this)->Print(psname,"pdf");
04902    else if (psname.EndsWith(".svg"))
04903       ((TPad*)this)->Print(psname,"svg");
04904    else if (psname.EndsWith(".xpm"))
04905       ((TPad*)this)->Print(psname,"xpm");
04906    else if (psname.EndsWith(".png"))
04907       ((TPad*)this)->Print(psname,"png");
04908    else if (psname.EndsWith(".jpg"))
04909       ((TPad*)this)->Print(psname,"jpg");
04910    else if (psname.EndsWith(".jpeg"))
04911       ((TPad*)this)->Print(psname,"jpg");
04912    else if (psname.EndsWith(".bmp"))
04913       ((TPad*)this)->Print(psname,"bmp");
04914    else if (psname.EndsWith(".tiff"))
04915       ((TPad*)this)->Print(psname,"tiff");
04916    else
04917       ((TPad*)this)->Print(psname,"ps");
04918 }
04919 
04920 
04921 //______________________________________________________________________________
04922 void TPad::SavePrimitive(ostream &out, Option_t * /*= ""*/)
04923 {
04924    // Save primitives in this pad on the C++ source file out.
04925 
04926    TPad *padsav = (TPad*)gPad;
04927    gPad = this;
04928    char quote='"';
04929    char lcname[10];
04930    const char *cname = GetName();
04931    Int_t nch = strlen(cname);
04932    if (nch < 10) {
04933       strlcpy(lcname,cname,10);
04934       for (Int_t k=1;k<=nch;k++) {if (lcname[nch-k] == ' ') lcname[nch-k] = 0;}
04935       if (lcname[0] == 0) {
04936          if (this == gPad->GetCanvas()) {strlcpy(lcname,"c1",10);  nch = 2;}
04937          else                           {strlcpy(lcname,"pad",10); nch = 3;}
04938       }
04939       cname = lcname;
04940    }
04941 
04942    //   Write pad parameters
04943    if (this != gPad->GetCanvas()) {
04944       out <<"  "<<endl;
04945       out <<"// ------------>Primitives in pad: "<<GetName()<<endl;
04946 
04947       if (gROOT->ClassSaved(TPad::Class())) {
04948          out<<"   ";
04949       } else {
04950          out<<"   TPad *";
04951       }
04952       out<<cname<<" = new TPad("<<quote<<GetName()<<quote<<", "<<quote<<GetTitle()
04953       <<quote
04954       <<","<<fXlowNDC
04955       <<","<<fYlowNDC
04956       <<","<<fXlowNDC+fWNDC
04957       <<","<<fYlowNDC+fHNDC
04958       <<");"<<endl;
04959       out<<"   "<<cname<<"->Draw();"<<endl;
04960       out<<"   "<<cname<<"->cd();"<<endl;
04961    }
04962    out<<"   "<<cname<<"->Range("<<fX1<<","<<fY1<<","<<fX2<<","<<fY2<<");"<<endl;
04963    TView *view = GetView();
04964    Double_t rmin[3], rmax[3];
04965    if (view) {
04966       view->GetRange(rmin, rmax);
04967       out<<"   TView *view = TView::CreateView(1);"<<endl;
04968       out<<"   view->SetRange("<<rmin[0]<<","<<rmin[1]<<","<<rmin[2]<<","
04969                                <<rmax[0]<<","<<rmax[1]<<","<<rmax[2]<<");"<<endl;
04970    }
04971    if (GetFillColor() != 19) {
04972       if (GetFillColor() > 228) {
04973          TColor::SaveColor(out, GetFillColor());
04974          out<<"   "<<cname<<"->SetFillColor(ci);" << endl;
04975       } else
04976          out<<"   "<<cname<<"->SetFillColor("<<GetFillColor()<<");"<<endl;
04977    }
04978    if (GetFillStyle() != 1001) {
04979       out<<"   "<<cname<<"->SetFillStyle("<<GetFillStyle()<<");"<<endl;
04980    }
04981    if (GetBorderMode() != 1) {
04982       out<<"   "<<cname<<"->SetBorderMode("<<GetBorderMode()<<");"<<endl;
04983    }
04984    if (GetBorderSize() != 4) {
04985       out<<"   "<<cname<<"->SetBorderSize("<<GetBorderSize()<<");"<<endl;
04986    }
04987    if (GetLogx()) {
04988       out<<"   "<<cname<<"->SetLogx();"<<endl;
04989    }
04990    if (GetLogy()) {
04991       out<<"   "<<cname<<"->SetLogy();"<<endl;
04992    }
04993    if (GetLogz()) {
04994       out<<"   "<<cname<<"->SetLogz();"<<endl;
04995    }
04996    if (GetGridx()) {
04997       out<<"   "<<cname<<"->SetGridx();"<<endl;
04998    }
04999    if (GetGridy()) {
05000       out<<"   "<<cname<<"->SetGridy();"<<endl;
05001    }
05002    if (GetTickx()) {
05003       out<<"   "<<cname<<"->SetTickx("<<GetTickx()<<");"<<endl;
05004    }
05005    if (GetTicky()) {
05006       out<<"   "<<cname<<"->SetTicky("<<GetTicky()<<");"<<endl;
05007    }
05008    if (GetTheta() != 30) {
05009       out<<"   "<<cname<<"->SetTheta("<<GetTheta()<<");"<<endl;
05010    }
05011    if (GetPhi() != 30) {
05012       out<<"   "<<cname<<"->SetPhi("<<GetPhi()<<");"<<endl;
05013    }
05014    if (TMath::Abs(fLeftMargin-0.1) > 0.01) {
05015       out<<"   "<<cname<<"->SetLeftMargin("<<GetLeftMargin()<<");"<<endl;
05016    }
05017    if (TMath::Abs(fRightMargin-0.1) > 0.01) {
05018       out<<"   "<<cname<<"->SetRightMargin("<<GetRightMargin()<<");"<<endl;
05019    }
05020    if (TMath::Abs(fTopMargin-0.1) > 0.01) {
05021       out<<"   "<<cname<<"->SetTopMargin("<<GetTopMargin()<<");"<<endl;
05022    }
05023    if (TMath::Abs(fBottomMargin-0.1) > 0.01) {
05024       out<<"   "<<cname<<"->SetBottomMargin("<<GetBottomMargin()<<");"<<endl;
05025    }
05026 
05027    if (GetFrameFillColor() != GetFillColor()) {
05028       if (GetFrameFillColor() > 228) {
05029          TColor::SaveColor(out, GetFrameFillColor());
05030          out<<"   "<<cname<<"->SetFrameFillColor(ci);" << endl;
05031       } else
05032          out<<"   "<<cname<<"->SetFrameFillColor("<<GetFrameFillColor()<<");"<<endl;
05033    }
05034    if (GetFrameFillStyle() != 1001) {
05035       out<<"   "<<cname<<"->SetFrameFillStyle("<<GetFrameFillStyle()<<");"<<endl;
05036    }
05037    if (GetFrameLineStyle() != 1) {
05038       out<<"   "<<cname<<"->SetFrameLineStyle("<<GetFrameLineStyle()<<");"<<endl;
05039    }
05040    if (GetFrameLineColor() != 1) {
05041       if (GetFrameLineColor() > 228) {
05042          TColor::SaveColor(out, GetFrameLineColor());
05043          out<<"   "<<cname<<"->SetFrameLineColor(ci);" << endl;
05044       } else
05045          out<<"   "<<cname<<"->SetFrameLineColor("<<GetFrameLineColor()<<");"<<endl;
05046    }
05047    if (GetFrameLineWidth() != 1) {
05048       out<<"   "<<cname<<"->SetFrameLineWidth("<<GetFrameLineWidth()<<");"<<endl;
05049    }
05050    if (GetFrameBorderMode() != 1) {
05051       out<<"   "<<cname<<"->SetFrameBorderMode("<<GetFrameBorderMode()<<");"<<endl;
05052    }
05053    if (GetFrameBorderSize() != 1) {
05054          out<<"   "<<cname<<"->SetFrameBorderSize("<<GetFrameBorderSize()<<");"<<endl;
05055    }
05056 
05057    TFrame *frame = fFrame;
05058    if (!frame) frame = (TFrame*)GetPrimitive("TFrame");
05059    if (frame) {
05060       if (frame->GetFillColor() != GetFillColor()) {
05061          if (frame->GetFillColor() > 228) {
05062             TColor::SaveColor(out, frame->GetFillColor());
05063             out<<"   "<<cname<<"->SetFrameFillColor(ci);" << endl;
05064          } else
05065             out<<"   "<<cname<<"->SetFrameFillColor("<<frame->GetFillColor()<<");"<<endl;
05066       }
05067       if (frame->GetFillStyle() != 1001) {
05068          out<<"   "<<cname<<"->SetFrameFillStyle("<<frame->GetFillStyle()<<");"<<endl;
05069       }
05070       if (frame->GetLineStyle() != 1) {
05071          out<<"   "<<cname<<"->SetFrameLineStyle("<<frame->GetLineStyle()<<");"<<endl;
05072       }
05073       if (frame->GetLineColor() != 1) {
05074          if (frame->GetLineColor() > 228) {
05075             TColor::SaveColor(out, frame->GetLineColor());
05076             out<<"   "<<cname<<"->SetFrameLineColor(ci);" << endl;
05077          } else
05078             out<<"   "<<cname<<"->SetFrameLineColor("<<frame->GetLineColor()<<");"<<endl;
05079       }
05080       if (frame->GetLineWidth() != 1) {
05081          out<<"   "<<cname<<"->SetFrameLineWidth("<<frame->GetLineWidth()<<");"<<endl;
05082       }
05083       if (frame->GetBorderMode() != 1) {
05084          out<<"   "<<cname<<"->SetFrameBorderMode("<<frame->GetBorderMode()<<");"<<endl;
05085       }
05086       if (frame->GetBorderSize() != 1) {
05087          out<<"   "<<cname<<"->SetFrameBorderSize("<<frame->GetBorderSize()<<");"<<endl;
05088       }
05089    }
05090 
05091    TIter next(GetListOfPrimitives());
05092    TObject *obj;
05093 
05094    while ((obj = next()))
05095          obj->SavePrimitive(out, (Option_t *)next.GetOption());
05096    out<<"   "<<cname<<"->Modified();"<<endl;
05097    out<<"   "<<GetMother()->GetName()<<"->cd();"<<endl;
05098    if (padsav) padsav->cd();
05099 }
05100 
05101 
05102 //______________________________________________________________________________
05103 void TPad::SetFixedAspectRatio(Bool_t fixed)
05104 {
05105    // Fix pad aspect ratio to current value if fixed is true.
05106 
05107    if (fixed) {
05108       if (!fFixedAspectRatio) {
05109          if (fHNDC != 0.)
05110             fAspectRatio = fWNDC / fHNDC;
05111          else {
05112             Error("SetAspectRatio", "cannot fix aspect ratio, height of pad is 0");
05113             return;
05114          }
05115          fFixedAspectRatio = kTRUE;
05116       }
05117    } else {
05118       fFixedAspectRatio = kFALSE;
05119       fAspectRatio = 0;
05120    }
05121 }
05122 
05123 
05124 //______________________________________________________________________________
05125 void TPad::SetEditable(Bool_t mode)
05126 {
05127    // Set pad editable yes/no
05128    // If a pad is not editable:
05129    // - one cannot modify the pad and its objects via the mouse.
05130    // - one cannot add new objects to the pad
05131 
05132    fEditable = mode;
05133 
05134    TObject *obj;
05135    if (!fPrimitives) fPrimitives = new TList;
05136    TIter    next(GetListOfPrimitives());
05137    while ((obj = next())) {
05138       if (obj->InheritsFrom(TPad::Class())) {
05139          TPad *pad = (TPad*)obj;
05140          pad->SetEditable(mode);
05141       }
05142    }
05143 }
05144 
05145 
05146 //______________________________________________________________________________
05147 void TPad::SetFillStyle(Style_t fstyle)
05148 {
05149    // Overrride TAttFill::FillStyle for TPad because we want to handle style=0
05150    // as style 4000.
05151 
05152    if (fstyle == 0) fstyle = 4000;
05153    TAttFill::SetFillStyle(fstyle);
05154 }
05155 
05156 
05157 //______________________________________________________________________________
05158 void TPad::SetLogx(Int_t value)
05159 {
05160    // Set Lin/Log scale for X
05161    //   value = 0 X scale will be linear
05162    //   value = 1 X scale will be logarithmic (base 10)
05163    //   value > 1 reserved for possible support of base e or other
05164 
05165    fLogx = value;
05166    delete fView; fView=0;
05167    Modified();
05168 }
05169 
05170 
05171 //______________________________________________________________________________
05172 void TPad::SetLogy(Int_t value)
05173 {
05174    // Set Lin/Log scale for Y
05175    //   value = 0 Y scale will be linear
05176    //   value = 1 Y scale will be logarithmic (base 10)
05177    //   value > 1 reserved for possible support of base e or other
05178 
05179    fLogy = value;
05180    delete fView; fView=0;
05181    Modified();
05182 }
05183 
05184 
05185 //______________________________________________________________________________
05186 void TPad::SetLogz(Int_t value)
05187 {
05188    // Set Lin/Log scale for Z
05189 
05190    fLogz = value;
05191    delete fView; fView=0;
05192    Modified();
05193 }
05194 
05195 
05196 //______________________________________________________________________________
05197 void TPad::SetPad(Double_t xlow, Double_t ylow, Double_t xup, Double_t yup)
05198 {
05199    // Set canvas range for pad and resize the pad. If the aspect ratio
05200    // was fixed before the call it will be un-fixed.
05201 
05202    // Reorder points to make sure xlow,ylow is bottom left point and
05203    // xup,yup is top right point.
05204    if (xup < xlow) {
05205       Double_t x = xlow;
05206       xlow = xup;
05207       xup  = x;
05208    }
05209    if (yup < ylow) {
05210       Double_t y = ylow;
05211       ylow = yup;
05212       yup  = y;
05213    }
05214 
05215    fXlowNDC = xlow;
05216    fYlowNDC = ylow;
05217    fWNDC    = xup - xlow;
05218    fHNDC    = yup - ylow;
05219 
05220    SetFixedAspectRatio(kFALSE);
05221 
05222    ResizePad();
05223 }
05224 
05225 
05226 //______________________________________________________________________________
05227 void TPad::SetPad(const char *name, const char *title,
05228                   Double_t xlow, Double_t ylow, Double_t xup, Double_t yup,
05229                   Color_t color, Short_t bordersize, Short_t bordermode)
05230 {
05231    // Set all pad parameters.
05232 
05233    fName  = name;
05234    fTitle = title;
05235    SetFillStyle(1001);
05236    SetBottomMargin(gStyle->GetPadBottomMargin());
05237    SetTopMargin(gStyle->GetPadTopMargin());
05238    SetLeftMargin(gStyle->GetPadLeftMargin());
05239    SetRightMargin(gStyle->GetPadRightMargin());
05240    if (color >= 0)   SetFillColor(color);
05241    else              SetFillColor(gStyle->GetPadColor());
05242    if (bordersize <  0) fBorderSize = gStyle->GetPadBorderSize();
05243    else                 fBorderSize = bordersize;
05244    if (bordermode < -1) fBorderMode = gStyle->GetPadBorderMode();
05245    else                 fBorderMode = bordermode;
05246 
05247    SetPad(xlow, ylow, xup, yup);
05248 }
05249 
05250 //______________________________________________________________________________
05251 void TPad::SetView(TView *view)
05252 {
05253    // Set the current TView. Delete previous view if view=0
05254 
05255    if (!view) delete fView;
05256    fView = view;
05257 }
05258 
05259 //______________________________________________________________________________
05260 void TPad::SetAttFillPS(Color_t color, Style_t style)
05261 {
05262    // Set postscript fill area attributes.
05263 
05264    if (gVirtualPS) {
05265       gVirtualPS->SetFillColor(color);
05266       gVirtualPS->SetFillStyle(style);
05267    }
05268 }
05269 
05270 
05271 //______________________________________________________________________________
05272 void TPad::SetAttLinePS(Color_t color, Style_t style, Width_t lwidth)
05273 {
05274    // Set postscript line attributes.
05275 
05276    if (gVirtualPS) {
05277       gVirtualPS->SetLineColor(color);
05278       gVirtualPS->SetLineStyle(style);
05279       gVirtualPS->SetLineWidth(lwidth);
05280    }
05281 }
05282 
05283 
05284 //______________________________________________________________________________
05285 void TPad::SetAttMarkerPS(Color_t color, Style_t style, Size_t msize)
05286 {
05287    // Set postscript marker attributes.
05288 
05289    if (gVirtualPS) {
05290       gVirtualPS->SetMarkerColor(color);
05291       gVirtualPS->SetMarkerStyle(style);
05292       gVirtualPS->SetMarkerSize(msize);
05293    }
05294 }
05295 
05296 
05297 //______________________________________________________________________________
05298 void TPad::SetAttTextPS(Int_t align, Float_t angle, Color_t color, Style_t font, Float_t tsize)
05299 {
05300    // Set postscript text attributes.
05301 
05302    if (gVirtualPS) {
05303       gVirtualPS->SetTextAlign(align);
05304       gVirtualPS->SetTextAngle(angle);
05305       gVirtualPS->SetTextColor(color);
05306       gVirtualPS->SetTextFont(font);
05307       if (font%10 > 2) {
05308          Float_t wh = (Float_t)gPad->XtoPixel(gPad->GetX2());
05309          Float_t hh = (Float_t)gPad->YtoPixel(gPad->GetY1());
05310          Float_t dy;
05311          if (wh < hh)  {
05312             dy = AbsPixeltoX(Int_t(tsize)) - AbsPixeltoX(0);
05313             tsize = dy/(fX2-fX1);
05314          } else {
05315             dy = AbsPixeltoY(0) - AbsPixeltoY(Int_t(tsize));
05316             tsize = dy/(fY2-fY1);
05317          }
05318       }
05319       gVirtualPS->SetTextSize(tsize);
05320    }
05321 }
05322 
05323 
05324 //______________________________________________________________________________
05325 Bool_t TPad::HasCrosshair() const
05326 {
05327    // Return kTRUE if the crosshair has been activated (via SetCrosshair).
05328 
05329    return (Bool_t)GetCrosshair();
05330 }
05331 
05332 
05333 //______________________________________________________________________________
05334 Int_t TPad::GetCrosshair() const
05335 {
05336    // Return the crosshair type (from the mother canvas)
05337    // crosshair type = 0 means no crosshair.
05338 
05339    if (this == (TPad*)fCanvas)
05340       return fCrosshair;
05341    return fCanvas ? fCanvas->GetCrosshair() : 0;
05342 }
05343 
05344 
05345 //______________________________________________________________________________
05346 void TPad::SetCrosshair(Int_t crhair)
05347 {
05348    // Set crosshair active/inactive.
05349    // If crhair != 0, a crosshair will be drawn in the pad and its subpads.
05350    // If the canvas crhair = 1 , the crosshair spans the full canvas.
05351    // If the canvas crhair > 1 , the crosshair spans only the pad.
05352 
05353    fCrosshair = crhair;
05354    fCrosshairPos = 0;
05355 
05356    if (this != (TPad*)fCanvas) fCanvas->SetCrosshair(crhair);
05357 }
05358 
05359 
05360 //______________________________________________________________________________
05361 void TPad::SetMaxPickDistance(Int_t maxPick)
05362 {
05363    // static function to set the maximum Pick Distance fgMaxPickDistance
05364    // This parameter is used in TPad::Pick to select an object if
05365    // its DistancetoPrimitive returns a value < fgMaxPickDistance
05366    // The default value is 5 pixels. Setting a smaller value will make
05367    // picking more precise but also more difficult
05368 
05369    fgMaxPickDistance = maxPick;
05370 }
05371 
05372 
05373 //______________________________________________________________________________
05374 void TPad::SetToolTipText(const char *text, Long_t delayms)
05375 {
05376    // Set tool tip text associated with this pad. The delay is in
05377    // milliseconds (minimum 250). To remove tool tip call method with
05378    // text = 0.
05379 
05380    if (fTip) {
05381       DeleteToolTip(fTip);
05382       fTip = 0;
05383    }
05384 
05385    if (text && strlen(text))
05386       fTip = CreateToolTip((TBox*)0, text, delayms);
05387 }
05388 
05389 
05390 //______________________________________________________________________________
05391 void TPad::SetVertical(Bool_t vert)
05392 {
05393    // Set pad vertical (default) or horizontal
05394 
05395    if (vert) ResetBit(kHori);
05396    else      SetBit(kHori);
05397 }
05398 
05399 
05400 //_______________________________________________________________________
05401 void TPad::Streamer(TBuffer &b)
05402 {
05403    // Stream a class object.
05404 
05405    UInt_t R__s, R__c;
05406    Int_t nch, nobjects;
05407    Float_t single;
05408    TObject *obj;
05409    if (b.IsReading()) {
05410       Version_t v = b.ReadVersion(&R__s, &R__c);
05411       if (v > 5) {
05412          if (!gPad) gPad = new TCanvas(GetName());
05413          TPad *padsave = (TPad*)gPad;
05414          fMother = (TPad*)gPad;
05415          if (fMother)  fCanvas = fMother->GetCanvas();
05416          gPad      = this;
05417          fPixmapID = -1;      // -1 means pixmap will be created by ResizePad()
05418          gReadLevel++;
05419          gROOT->SetReadingObject(kTRUE);
05420 
05421          b.ReadClassBuffer(TPad::Class(), this, v, R__s, R__c);
05422 
05423          //Set the kCanDelete bit in all objects in the pad such that when the pad 
05424          //is deleted all objects in the pad are deleted too.
05425          TIter next(fPrimitives);
05426          while ((obj = next())) {
05427             obj->SetBit(kCanDelete);
05428          }
05429 
05430          fModified = kTRUE;
05431          fPadPointer = 0;
05432          gReadLevel--;
05433          if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
05434          gROOT->SetReadingObject(kFALSE);
05435          gPad = padsave;
05436          return;
05437       }
05438 
05439       //====process old versions before automatic schema evolution
05440       if (v < 5) {   //old TPad in single precision
05441          if (v < 3) {   //old TPad derived from TWbox
05442             b.ReadVersion();   //      TVirtualPad::Streamer(b)
05443             b.ReadVersion();   //      TWbox::Streamer(b)
05444             b.ReadVersion();   //      TBox::Streamer(b)
05445             TObject::Streamer(b);
05446             TAttLine::Streamer(b);
05447             TAttFill::Streamer(b);
05448             b >> single; fX1 = single;
05449             b >> single; fY1 = single;
05450             b >> single; fX2 = single;
05451             b >> single; fY2 = single;
05452             b >> fBorderSize;
05453             b >> fBorderMode;
05454             TAttPad::Streamer(b);
05455          } else {  //new TPad
05456             TVirtualPad::Streamer(b);
05457             TAttPad::Streamer(b);
05458             b >> single; fX1 = single;
05459             b >> single; fY1 = single;
05460             b >> single; fX2 = single;
05461             b >> single; fY2 = single;
05462             b >> fBorderSize;
05463             b >> fBorderMode;
05464          }
05465          b >> fLogx;
05466          b >> fLogy;
05467          b >> fLogz;
05468          b >> single; fXtoAbsPixelk = single;
05469          b >> single; fXtoPixelk    = single;
05470          b >> single; fXtoPixel     = single;
05471          b >> single; fYtoAbsPixelk = single;
05472          b >> single; fYtoPixelk    = single;
05473          b >> single; fYtoPixel     = single;
05474          b >> single; fUtoAbsPixelk = single;
05475          b >> single; fUtoPixelk    = single;
05476          b >> single; fUtoPixel     = single;
05477          b >> single; fVtoAbsPixelk = single;
05478          b >> single; fVtoPixelk    = single;
05479          b >> single; fVtoPixel     = single;
05480          b >> single; fAbsPixeltoXk = single;
05481          b >> single; fPixeltoXk    = single;
05482          b >> single; fPixeltoX     = single;
05483          b >> single; fAbsPixeltoYk = single;
05484          b >> single; fPixeltoYk    = single;
05485          b >> single; fPixeltoY     = single;
05486          b >> single; fXlowNDC      = single;
05487          b >> single; fYlowNDC      = single;
05488          b >> single; fWNDC         = single;
05489          b >> single; fHNDC         = single;
05490          b >> single; fAbsXlowNDC   = single;
05491          b >> single; fAbsYlowNDC   = single;
05492          b >> single; fAbsWNDC      = single;
05493          b >> single; fAbsHNDC      = single;
05494          b >> single; fUxmin        = single;
05495          b >> single; fUymin        = single;
05496          b >> single; fUxmax        = single;
05497          b >> single; fUymax        = single;
05498       } else {
05499          TVirtualPad::Streamer(b);
05500          TAttPad::Streamer(b);
05501          b >> fX1;
05502          b >> fY1;
05503          b >> fX2;
05504          b >> fY2;
05505          b >> fBorderSize;
05506          b >> fBorderMode;
05507          b >> fLogx;
05508          b >> fLogy;
05509          b >> fLogz;
05510          b >> fXtoAbsPixelk;
05511          b >> fXtoPixelk;
05512          b >> fXtoPixel;
05513          b >> fYtoAbsPixelk;
05514          b >> fYtoPixelk;
05515          b >> fYtoPixel;
05516          b >> fUtoAbsPixelk;
05517          b >> fUtoPixelk;
05518          b >> fUtoPixel;
05519          b >> fVtoAbsPixelk;
05520          b >> fVtoPixelk;
05521          b >> fVtoPixel;
05522          b >> fAbsPixeltoXk;
05523          b >> fPixeltoXk;
05524          b >> fPixeltoX;
05525          b >> fAbsPixeltoYk;
05526          b >> fPixeltoYk;
05527          b >> fPixeltoY;
05528          b >> fXlowNDC;
05529          b >> fYlowNDC;
05530          b >> fWNDC;
05531          b >> fHNDC;
05532          b >> fAbsXlowNDC;
05533          b >> fAbsYlowNDC;
05534          b >> fAbsWNDC;
05535          b >> fAbsHNDC;
05536          b >> fUxmin;
05537          b >> fUymin;
05538          b >> fUxmax;
05539          b >> fUymax;
05540       }
05541 
05542       if (!gPad) gPad = new TCanvas(GetName());
05543       if (gReadLevel == 0) fMother = (TPad*)gROOT->GetSelectedPad();
05544       else                fMother = (TPad*)gPad;
05545       if (!fMother) fMother = (TPad*)gPad;
05546       if (fMother)  fCanvas = fMother->GetCanvas();
05547       gPad      = fMother;
05548       fPixmapID = -1;      // -1 means pixmap will be created by ResizePad()
05549       //-------------------------
05550       // read objects and their drawing options
05551       //      b >> fPrimitives;
05552       gReadLevel++;
05553       gROOT->SetReadingObject(kTRUE);
05554       fPrimitives = new TList;
05555       b >> nobjects;
05556       if (nobjects > 0) {
05557          TPad *padsav = (TPad*)gPad;
05558          gPad = this;
05559          char drawoption[64];
05560          for (Int_t i = 0; i < nobjects; i++) {
05561             b >> obj;
05562             b >> nch;
05563             b.ReadFastArray(drawoption,nch);
05564             fPrimitives->AddLast(obj, drawoption);
05565             gPad = this; // gPad may be modified in b >> obj if obj is a pad
05566          }
05567          gPad = padsav;
05568       }
05569       gReadLevel--;
05570       gROOT->SetReadingObject(kFALSE);
05571       //-------------------------
05572       if (v > 3) {
05573          b >> fExecs;
05574       }
05575       fName.Streamer(b);
05576       fTitle.Streamer(b);
05577       b >> fPadPaint;
05578       fModified = kTRUE;
05579       b >> fGridx;
05580       b >> fGridy;
05581       b >> fFrame;
05582       b >> fView;
05583       if (v < 5) {
05584          b >> single; fTheta = single;
05585          b >> single; fPhi   = single;
05586       } else {
05587          b >> fTheta;
05588          b >> fPhi;
05589       }
05590       fPadPointer = 0;
05591       b >> fNumber;
05592       b >> fAbsCoord;
05593       if (v > 1) {
05594          b >> fTickx;
05595          b >> fTicky;
05596       } else {
05597          fTickx = fTicky = 0;
05598       }
05599       if (gReadLevel == 0 && IsA() == TPad::Class()) ResizePad();
05600       b.CheckByteCount(R__s, R__c, TPad::IsA());
05601       //====end of old versions
05602 
05603    } else {
05604       b.WriteClassBuffer(TPad::Class(),this);
05605    }
05606 }
05607 
05608 
05609 //______________________________________________________________________________
05610 void TPad::UseCurrentStyle()
05611 {
05612    // Force a copy of current style for all objects in pad.
05613 
05614    if (gStyle->IsReading()) {
05615       SetFillColor(gStyle->GetPadColor());
05616       SetBottomMargin(gStyle->GetPadBottomMargin());
05617       SetTopMargin(gStyle->GetPadTopMargin());
05618       SetLeftMargin(gStyle->GetPadLeftMargin());
05619       SetRightMargin(gStyle->GetPadRightMargin());
05620       fBorderSize = gStyle->GetPadBorderSize();
05621       fBorderMode = gStyle->GetPadBorderMode();
05622       fGridx = gStyle->GetPadGridX();
05623       fGridy = gStyle->GetPadGridY();
05624       fTickx = gStyle->GetPadTickX();
05625       fTicky = gStyle->GetPadTickY();
05626       fLogx  = gStyle->GetOptLogx();
05627       fLogy  = gStyle->GetOptLogy();
05628       fLogz  = gStyle->GetOptLogz();
05629    } else {
05630       gStyle->SetPadColor(GetFillColor());
05631       gStyle->SetPadBottomMargin(GetBottomMargin());
05632       gStyle->SetPadTopMargin(GetTopMargin());
05633       gStyle->SetPadLeftMargin(GetLeftMargin());
05634       gStyle->SetPadRightMargin(GetRightMargin());
05635       gStyle->SetPadBorderSize(GetBorderSize());
05636       gStyle->SetPadBorderMode(GetBorderMode());
05637       gStyle->SetPadGridX(fGridx);
05638       gStyle->SetPadGridY(fGridy);
05639       gStyle->SetPadTickX(fTickx);
05640       gStyle->SetPadTickY(fTicky);
05641       gStyle->SetOptLogx (fLogx);
05642       gStyle->SetOptLogy (fLogy);
05643       gStyle->SetOptLogz (fLogz);
05644    }
05645 
05646    if (!fPrimitives) fPrimitives = new TList;
05647    TIter next(GetListOfPrimitives());
05648    TObject *obj;
05649 
05650    while ((obj = next())) {
05651       obj->UseCurrentStyle();
05652    }
05653 
05654    TPaveText *title  = (TPaveText*)FindObject("title");
05655    if (title) {
05656       if (gStyle->IsReading()) {
05657          title->SetFillColor(gStyle->GetTitleFillColor());
05658          title->SetTextFont(gStyle->GetTitleFont(""));
05659          title->SetTextColor(gStyle->GetTitleTextColor());
05660          title->SetBorderSize(gStyle->GetTitleBorderSize());
05661          if (!gStyle->GetOptTitle()) delete title;
05662       } else {
05663          gStyle->SetTitleFillColor(title->GetFillColor());
05664          gStyle->SetTitleFont(title->GetTextFont());
05665          gStyle->SetTitleTextColor(title->GetTextColor());
05666          gStyle->SetTitleBorderSize(title->GetBorderSize());
05667       }
05668    }
05669    if (fFrame) fFrame->UseCurrentStyle();
05670 
05671    if (gStyle->IsReading()) Modified();
05672 }
05673 
05674 
05675 //______________________________________________________________________________
05676 TObject *TPad::WaitPrimitive(const char *pname, const char *emode)
05677 {
05678    // Loop and sleep until a primitive with name=pname
05679    // is found in the pad.
05680    // If emode is given, the editor is automatically set to emode, ie
05681    // it is not required to have the editor control bar.
05682    // The possible values for emode are:
05683    //  emode = "" (default). User will select the mode via the editor bar
05684    //        = "Arc", "Line", "Arrow", "Button", "Diamond", "Ellipse",
05685    //        = "Pad","pave", "PaveLabel","PaveText", "PavesText",
05686    //        = "PolyLine", "CurlyLine", "CurlyArc", "Text", "Marker", "CutG"
05687    // if emode is specified and it is not valid, "PolyLine" is assumed.
05688    // if emode is not specified or ="", an attempt is to use pname[1...]
05689    // for example if pname="TArc", emode="Arc" will be assumed.
05690    // When this function is called within a macro, the macro execution
05691    // is suspended until a primitive corresponding to the arguments
05692    // is found in the pad.
05693    // If CRTL/C is typed in the pad, the function returns 0.
05694    // While this function is executing, one can use the mouse, interact
05695    // with the graphics pads, use the Inspector, Browser, TreeViewer, etc.
05696    // Examples:
05697    //   c1.WaitPrimitive();      // Return the first created primitive
05698    //                            // whatever it is.
05699    //                            // If a double-click with the mouse is executed
05700    //                            // in the pad or any key pressed, the function
05701    //                            // returns 0.
05702    //   c1.WaitPrimitive("ggg"); // Set the editor in mode "PolyLine/Graph"
05703    //                            // Create a polyline, then using the context
05704    //                            // menu item "SetName", change the name
05705    //                            // of the created TGraph to "ggg"
05706    //   c1.WaitPrimitive("TArc");// Set the editor in mode "Arc". Returns
05707    //                            // as soon as a TArc object is created.
05708    //   c1.WaitPrimitive("lat","Text"); // Set the editor in Text/Latex mode.
05709    //                            // Create a text object, then Set its name to "lat"
05710    //
05711    // The following macro waits for 10 primitives of any type to be created.
05712    //{
05713    //   TCanvas c1("c1");
05714    //   TObject *obj;
05715    //   for (Int_t i=0;i<10;i++) {
05716    //      obj = gPad->WaitPrimitive();
05717    //      if (!obj) break;
05718    //      printf("Loop i=%d, found objIsA=%s, name=%s\n",
05719    //         i,obj->ClassName(),obj->GetName());
05720    //   }
05721    //}
05722 
05723    if (strlen(emode)) gROOT->SetEditorMode(emode);
05724    if (gROOT->GetEditorMode() == 0 && strlen(pname) > 2) gROOT->SetEditorMode(&pname[1]);
05725 
05726    if (!fPrimitives) fPrimitives = new TList;
05727    gSystem->ProcessEvents();
05728    TObject *oldlast = gPad->GetListOfPrimitives()->Last();
05729    TObject *obj = 0;
05730    Bool_t testlast = kFALSE;
05731    Bool_t hasname = strlen(pname) > 0;
05732    if (strlen(pname) == 0 && strlen(emode) == 0) testlast = kTRUE;
05733    if (testlast) gROOT->SetEditorMode();
05734    while (!gSystem->ProcessEvents() && gROOT->GetSelectedPad()) {
05735       if (gROOT->GetEditorMode() == 0) {
05736          if (hasname) {
05737             obj = FindObject(pname);
05738             if (obj) return obj;
05739          }
05740          if (testlast) {
05741             obj = gPad->GetListOfPrimitives()->Last();
05742             if (obj != oldlast) return obj;
05743             Int_t event = GetEvent();
05744             if (event == kButton1Double || event == kKeyPress) {
05745                //the following statement is required against other loop executions
05746                //before returning
05747                fCanvas->HandleInput((EEventType)-1,0,0);
05748                return 0;
05749             }
05750          }
05751       }
05752       gSystem->Sleep(10);
05753    }
05754 
05755    return 0;
05756 }
05757 
05758 
05759 //______________________________________________________________________________
05760 TObject *TPad::CreateToolTip(const TBox *box, const char *text, Long_t delayms)
05761 {
05762    // Create a tool tip and return its pointer.
05763 
05764    if (gPad->IsBatch()) return 0;
05765    // return new TGToolTip(box, text, delayms);
05766    return (TObject*)gROOT->ProcessLineFast(Form("new TGToolTip((TBox*)0x%lx,\"%s\",%d)",
05767                                            (Long_t)box,text,(Int_t)delayms));
05768 }
05769 
05770 
05771 //______________________________________________________________________________
05772 void TPad::DeleteToolTip(TObject *tip)
05773 {
05774    // Delete tool tip object.
05775 
05776    // delete tip;
05777    if (!tip) return;
05778    gROOT->ProcessLineFast(Form("delete (TGToolTip*)0x%lx", (Long_t)tip));
05779 }
05780 
05781 
05782 //______________________________________________________________________________
05783 void TPad::ResetToolTip(TObject *tip)
05784 {
05785    // Reset tool tip, i.e. within time specified in CreateToolTip the
05786    // tool tip will pop up.
05787 
05788    if (!tip) return;
05789    // tip->Reset(this);
05790    gROOT->ProcessLineFast(Form("((TGToolTip*)0x%lx)->Reset((TPad*)0x%lx)",
05791                           (Long_t)tip,(Long_t)this));
05792 }
05793 
05794 
05795 //______________________________________________________________________________
05796 void TPad::CloseToolTip(TObject *tip)
05797 {
05798    // Hide tool tip.
05799 
05800    if (!tip) return;
05801    // tip->Hide();
05802    gROOT->ProcessLineFast(Form("((TGToolTip*)0x%lx)->Hide()",(Long_t)tip));
05803 }
05804 
05805 
05806 //______________________________________________________________________________
05807 void TPad::x3d(Option_t *type)
05808 {
05809    // Depreciated: use TPad::GetViewer3D() instead
05810 
05811    ::Info("TPad::x3d()", "Fn is depreciated - use TPad::GetViewer3D() instead");
05812 
05813    // Default on GetViewer3D is pad - for x3d
05814    // it was x3d...
05815    if (!type || !type[0]) {
05816       type = "x3d";
05817    }
05818    GetViewer3D(type);
05819 }
05820 
05821 
05822 //______________________________________________________________________________
05823 TVirtualViewer3D *TPad::GetViewer3D(Option_t *type)
05824 {
05825    // Create/obtain handle to 3D viewer. Valid types are:
05826    //    'pad' - pad drawing via TViewer3DPad
05827    //    any others registered with plugin manager supporting TVirtualViewer3D
05828    // If an invalid/null type is requested then the current viewer is returned
05829    // (if any), otherwise a default 'pad' type is returned
05830 
05831    Bool_t validType = kFALSE;
05832 
05833    if ( (!type || !type[0] || (strstr(type, "gl") && !strstr(type, "ogl"))) && !fCanvas->UseGL())
05834       type = "pad";
05835 
05836    if (type && type[0]) {
05837 
05838       if (gPluginMgr->FindHandler("TVirtualViewer3D", type))
05839          validType = kTRUE;
05840 
05841    }
05842 
05843    // Invalid/null type requested?
05844    if (!validType) {
05845       // Return current viewer if there is one
05846       if (fViewer3D) {
05847          return fViewer3D;
05848       }
05849       // otherwise default to the pad
05850       else {
05851          type = "pad";
05852       }
05853    }
05854 
05855    // Ensure we can create the new viewer before removing any exisiting one
05856    TVirtualViewer3D *newViewer = 0;
05857 
05858    Bool_t createdExternal = kFALSE;
05859 
05860    // External viewers need to be created via plugin manager via interface...
05861    if (!strstr(type,"pad")) {
05862       newViewer = TVirtualViewer3D::Viewer3D(this,type);
05863 
05864       if (!newViewer) {
05865          Warning("TPad::CreateViewer3D", "Cannot create 3D viewer of type: %s", type);
05866 
05867          // Return the existing viewer
05868          return fViewer3D;
05869       }
05870 
05871       if (strstr(type, "gl") && !strstr(type, "ogl"))
05872          fEmbeddedGL = kTRUE, fCopyGLDevice = kTRUE, Modified();
05873       else
05874          createdExternal = kTRUE;
05875 
05876    } else
05877       newViewer = new TViewer3DPad(*this);
05878 
05879    // If we had a previous viewer destroy it now
05880    // In this case we do take responsibility for destorying viewer
05881    // c.f. ReleaseViewer3D
05882    delete fViewer3D;
05883 
05884    // Set and return new viewer
05885    fViewer3D = newViewer;
05886 
05887    // Ensure any new external viewer is painted
05888    // For internal TViewer3DPad type we assume this is being
05889    // create on demand due to a paint - so this is not required
05890    if (createdExternal) {
05891       Modified();
05892       Update();
05893    }
05894 
05895    return fViewer3D;
05896 }
05897 
05898 //______________________________________________________________________________
05899 void TPad::ReleaseViewer3D(Option_t * /*type*/ )
05900 {
05901    // Release current (external) viewer
05902    // TODO: By type
05903    fViewer3D = 0;
05904 
05905    // We would like to ensure the pad is repainted
05906    // when external viewer is closed down. However
05907    // a modify/paint call here will repaint the pad
05908    // before the external viewer window actually closes.
05909    // So the pad would have to be redraw twice over.
05910    // Currenltly we just have to live with the pad staying blank
05911    // any click in pad will refresh.
05912 }
05913 
05914 
05915 //______________________________________________________________________________
05916 Int_t TPad::GetGLDevice()
05917 {
05918    // Get GL device.
05919    return fGLDevice;
05920 }
05921 
05922 //______________________________________________________________________________
05923 void TPad::RecordPave(const TObject *obj)
05924 {
05925    // Emit RecordPave() signal.
05926 
05927    Emit("RecordPave(const TObject*)", (Long_t)obj);
05928 }
05929 
05930 //______________________________________________________________________________
05931 void TPad::RecordLatex(const TObject *obj)
05932 {
05933    // Emit RecordLatex() signal.
05934 
05935    Emit("RecordLatex(const TObject*)", (Long_t)obj);
05936 }
05937 
05938 //______________________________________________________________________________
05939 TVirtualPadPainter *TPad::GetPainter()
05940 {
05941    // Get pad painter from TCanvas.
05942 
05943    if (!fCanvas) return 0;
05944    return fCanvas->GetCanvasPainter();
05945 }

Generated on Tue Jul 5 14:14:07 2011 for ROOT_528-00b_version by  doxygen 1.5.1