TLegend.cxx

Go to the documentation of this file.
00001 // @(#)root/graf:$Id: TLegend.cxx 36225 2010-10-09 18:46:31Z brun $
00002 // Author: Matthew.Adam.Dobbs   06/09/99
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 <stdio.h>
00013 
00014 #include "TStyle.h"
00015 #include "TLatex.h"
00016 #include "TLine.h"
00017 #include "TBox.h"
00018 #include "TMarker.h"
00019 #include "TLegend.h"
00020 #include "TList.h"
00021 #include "TVirtualPad.h"
00022 #include "TMath.h"
00023 #include "TROOT.h"
00024 #include "TLegendEntry.h"
00025 #include "Riostream.h"
00026 #include "TMultiGraph.h"
00027 #include "THStack.h"
00028 
00029 
00030 ClassImp(TLegend)
00031 
00032 
00033 //______________________________________________________________________________
00034 /* Begin_Html
00035 <center><h2>Legend class</h2></center>
00036 This class displays a legend box (TPaveText) containing several legend entries.
00037 Each legend entry is made of a reference to a ROOT object, a text label and an
00038 option specifying which graphical attributes (marker/line/fill) should be
00039 displayed.
00040 <p>
00041 The following example shows how to create a legend. In this example the legend
00042 contains a histogram, a function and a graph. The histogram is put in the legend
00043 using its reference pointer whereas the graph and the function are added
00044 using their names. Note that, because <tt>TGraph</tt> contructors do not have the
00045 <tt>TGraph</tt> name as parameter, the graph name should be specified using the
00046 <tt>SetName</tt> method.
00047 <p>
00048 When an object is added by name, a scan is performed on the list of objects
00049 contained in the current pad (<tt>gPad</tt>) and also in the possible
00050 <tt>TMultiGraph</tt> and <tt>THStack</tt> present in the pad. If a matching
00051 name is found, the coresponding object is added in the legend using its pointer.
00052 
00053 End_Html
00054 Begin_Macro(source)
00055 {
00056    TCanvas *c1 = new TCanvas("c1","c1",600,500);
00057    gStyle->SetOptStat(0);
00058 
00059    TH1F *h1 = new TH1F("h1","TLegend Example",200,-10,10);
00060    h1->FillRandom("gaus",30000);
00061    h1->SetFillColor(kGreen);
00062    h1->SetFillStyle(3003);
00063    h1->Draw();
00064 
00065    TF1 *f1=new TF1("f1","1000*TMath::Abs(sin(x)/x)",-10,10);
00066    f1->SetLineColor(kBlue);
00067    f1->SetLineWidth(4);
00068    f1->Draw("same");
00069 
00070    const Int_t n = 20;
00071    Double_t x[n], y[n], ex[n], ey[n];
00072    for (Int_t i=0;i<n;i++) {
00073       x[i]  = i*0.1;
00074       y[i]  = 1000*sin(x[i]+0.2);
00075       x[i]  = 17.8*x[i]-8.9;
00076       ex[i] = 1.0;
00077       ey[i] = 10.*i;
00078    }
00079    TGraphErrors *gr = new TGraphErrors(n,x,y,ex,ey);
00080    gr->SetName("gr");
00081    gr->SetLineColor(kRed);
00082    gr->SetLineWidth(2);
00083    gr->SetMarkerStyle(21);
00084    gr->SetMarkerSize(1.3);
00085    gr->SetMarkerColor(7);
00086    gr->Draw("P");
00087 
00088    leg = new TLegend(0.1,0.7,0.48,0.9);
00089    leg->SetHeader("The Legend Title");
00090    leg->AddEntry(h1,"Histogram filled with random numbers","f");
00091    leg->AddEntry("f1","Function abs(#frac{sin(x)}{x})","l");
00092    leg->AddEntry("gr","Graph with error bars","lep");
00093    leg->Draw();
00094 
00095    return c1;
00096 }
00097 End_Macro
00098 Begin_Html
00099 
00100 Note that the <tt>TPad</tt> class has a method to build automatically a legend
00101 for all objects in the pad. It is called <tt>TPad::BuildLegend()</tt>.
00102 <p>
00103 Each item in the legend is added using the <tt>AddEntry</tt> method. This
00104 method defines the object to be added (by reference or name), the label
00105 associated to this object and an option which a combination of:
00106 <ul>
00107 <li> L: draw line associated with TAttLine if obj inherits from TAttLine
00108 <li> P: draw polymarker associated with TAttMarker if obj inherits from TAttMarker
00109 <li> F: draw a box with fill associated wit TAttFill if obj inherits TAttFill
00110 <li> E: draw vertical error bar if option "L" is also specified
00111 </ul>
00112 <p>
00113 As shown in the following example, passing a NULL pointer as first parameter in
00114 <tt>AddEntry</tt> is also valid. This allows to add text or blank lines in a
00115 legend.
00116 
00117 End_Html
00118 Begin_Macro(source)
00119 {
00120    TCanvas *c2 = new TCanvas("c2","c2",500,300);
00121 
00122    TLegend* leg = new TLegend(0.2, 0.2, .8, .8);
00123    TH1* h = new TH1F("", "", 1, 0, 1);
00124 
00125    leg->AddEntry(h, "Histogram \"h\"", "l"); 
00126    leg->AddEntry((TObject*)0, "", "");  
00127    leg->AddEntry((TObject*)0, "Some text", "");
00128    leg->AddEntry((TObject*)0, "", "");  
00129    leg->AddEntry(h, "Histogram \"h\" again", "l");
00130 
00131    leg->Draw();
00132    return c2;
00133 }
00134 End_Macro
00135 */
00136 
00137 
00138 //______________________________________________________________________________
00139 TLegend::TLegend(): TPave(), TAttText()
00140 {
00141    /* Begin_Html
00142    Default constructor.
00143    End_Html */
00144 
00145    fPrimitives = 0;
00146    SetDefaults();
00147 }
00148 
00149 
00150 //______________________________________________________________________________
00151 TLegend::TLegend( Double_t x1, Double_t y1,Double_t x2, Double_t y2,
00152                   const char *header, Option_t *option)
00153         :TPave(x1,y1,x2,y2,4,option), TAttText(12,0,1,gStyle->GetTextFont(),0)
00154 {
00155    /* Begin_Html
00156    Normal Contructor.
00157    <p>
00158    A TLegend is a Pave with several TLegendEntry(s).
00159    x1,y1,x2,y2 are the coordinates of the Legend in the current pad
00160    (in normalized coordinates by default)
00161    "header" is the title that will be displayed at the top of the legend
00162    it is treated like a regular entry and supports TLatex. The default
00163    is no header (header = 0).
00164    The options are the same as for TPave Default = "brNDC"
00165    End_Html */
00166 
00167    fPrimitives = new TList;
00168    if ( header && strlen(header) > 0) {
00169       TLegendEntry *headerEntry = new TLegendEntry( 0, header, "h" );
00170       headerEntry->SetTextAlign(0);
00171       headerEntry->SetTextAngle(0);
00172       headerEntry->SetTextColor(0);
00173       headerEntry->SetTextFont(62); // default font is 62 for the header
00174       headerEntry->SetTextSize(0);
00175       fPrimitives->AddFirst(headerEntry);
00176    }
00177    SetDefaults();
00178    SetBorderSize(gStyle->GetLegendBorderSize());
00179 }
00180 
00181 
00182 //______________________________________________________________________________
00183 TLegend::TLegend( const TLegend &legend ) : TPave(legend), TAttText(legend),
00184                                             fPrimitives(0)
00185 {
00186    /* Begin_Html
00187    Copy constuctor.
00188    End_Html */
00189 
00190   if (legend.fPrimitives) {
00191       fPrimitives = new TList();
00192       TListIter it(legend.fPrimitives);
00193       while (TLegendEntry *e = (TLegendEntry *)it.Next()) {
00194          TLegendEntry *newentry = new TLegendEntry(*e);
00195          fPrimitives->Add(newentry);
00196       }
00197    }
00198    ((TLegend&)legend).Copy(*this);
00199 }
00200 
00201 
00202 //______________________________________________________________________________
00203 TLegend& TLegend::operator=(const TLegend &lg)
00204 {
00205    /* Begin_Html
00206    Assignment operator.
00207    End_Html */
00208 
00209    if(this!=&lg) {
00210       TPave::operator=(lg);
00211       TAttText::operator=(lg);
00212       fPrimitives=lg.fPrimitives;
00213       fEntrySeparation=lg.fEntrySeparation;
00214       fMargin=lg.fMargin;
00215       fNColumns=lg.fNColumns;
00216    }
00217    return *this;
00218 }
00219 
00220 
00221 //______________________________________________________________________________
00222 TLegend::~TLegend()
00223 {
00224    /* Begin_Html
00225    Default destructor.
00226    End_Html */
00227 
00228    if (fPrimitives) fPrimitives->Delete();
00229    delete fPrimitives;
00230    fPrimitives = 0;
00231 }
00232 
00233 
00234 //______________________________________________________________________________
00235 TLegendEntry *TLegend::AddEntry(const TObject *obj, const char *label, Option_t *option)
00236 {
00237    /* Begin_Html
00238    Add a new entry to this legend. "obj" is the object to be represented.
00239    "label" is the text you wish to associate with obj in the legend.
00240    If "label" is null or empty, the title of the object will be used.
00241    <p>
00242    Options are:
00243    <ul>
00244    <li> L: draw line associated with TAttLine if obj inherits from TAttLine
00245    <li> P: draw polymarker associated with TAttMarker if obj inherits from TAttMarker
00246    <li> F: draw a box with fill associated wit TAttFill if obj inherits TAttFill
00247    <li> E: draw vertical error bar if option "L" is also specified
00248    </ul>
00249    End_Html */
00250 
00251    const char *lab = label;
00252 
00253    if (obj && (!label || strlen(label)==0)) lab = obj->GetTitle();
00254    TLegendEntry *newentry = new TLegendEntry( obj, lab, option );
00255    if ( !fPrimitives ) fPrimitives = new TList;
00256    fPrimitives->Add(newentry);
00257    return newentry;
00258 }
00259 
00260 
00261 //______________________________________________________________________________
00262 TLegendEntry *TLegend::AddEntry(const char *name, const char *label, Option_t *option)
00263 {
00264    /* Begin_Html
00265    Add a new entry to this legend. "name" is the name of an object in the pad to
00266    be represented label is the text you wish to associate with obj in the legend
00267    if label is null or empty, the title of the object will be used.
00268    <p>
00269    Options are:
00270    <ul>
00271    <li> L: draw line associated with TAttLine if obj inherits from TAttLine
00272    <li> P: draw polymarker associated with TAttMarker if obj inherits from TAttMarker
00273    <li> F: draw a box with fill associated wit TAttFill if obj inherits TAttFill
00274    <li> E: draw vertical error bar if option "L" is also specified
00275    </ul>
00276    End_Html */
00277 
00278    TObject *obj = gPad->FindObject(name);
00279 
00280    // If the object "name" has not been found, the following code tries to
00281    // find it in TMultiGraph or THStack possibly present in the current pad.
00282    if (!obj) {
00283       TList *lop = gPad->GetListOfPrimitives();
00284       if (lop) {
00285          TObject *o=0;
00286          TIter next(lop);
00287          while( (o=next()) ) {
00288             if ( o->InheritsFrom(TMultiGraph::Class() ) ) {
00289                TList * grlist = ((TMultiGraph *)o)->GetListOfGraphs();
00290                obj = grlist->FindObject(name);
00291                if (obj) continue;
00292             }
00293             if ( o->InheritsFrom(THStack::Class() ) ) {
00294                TList * hlist = ((THStack *)o)->GetHists();
00295                obj = hlist->FindObject(name);
00296                if (obj) continue;
00297             }
00298          }
00299       }
00300    }
00301 
00302    return AddEntry( obj, label, option );
00303 }
00304 
00305 
00306 //______________________________________________________________________________
00307 void TLegend::Clear( Option_t *)
00308 {
00309    /* Begin_Html
00310    Clear all entries in this legend, including the header.
00311    End_Html */
00312 
00313    if (!fPrimitives) return;
00314    fPrimitives->Delete();
00315 }
00316 
00317 
00318 //______________________________________________________________________________
00319 void TLegend::Copy( TObject &obj ) const
00320 {
00321    /* Begin_Html
00322    Copy this legend into "obj".
00323    End_Html */
00324 
00325    TPave::Copy(obj);
00326    TAttText::Copy((TLegend&)obj);
00327    ((TLegend&)obj).fEntrySeparation = fEntrySeparation;
00328    ((TLegend&)obj).fMargin = fMargin;
00329    ((TLegend&)obj).fNColumns = fNColumns;
00330 }
00331 
00332 
00333 //______________________________________________________________________________
00334 void TLegend::DeleteEntry()
00335 {
00336    /* Begin_Html
00337    Delete entry at the mouse position.
00338    End_Html */
00339 
00340    if ( !fPrimitives ) return;
00341    TLegendEntry* entry = GetEntry();   // get entry pointed by the mouse
00342    if ( !entry ) return;
00343    fPrimitives->Remove(entry);
00344    delete entry;
00345 }
00346 
00347 
00348 //______________________________________________________________________________
00349 void TLegend::Draw( Option_t *option )
00350 {
00351    /* Begin_Html
00352    Draw this legend with its current attributes.
00353    End_Html */
00354 
00355    AppendPad(option);
00356 }
00357 
00358 
00359 //______________________________________________________________________________
00360 void TLegend::EditEntryAttFill()
00361 {
00362    /* Begin_Html
00363    Edit the fill attributes for the entry pointed by the mouse.
00364    End_Html */
00365 
00366    TLegendEntry* entry = GetEntry();   // get entry pointed by the mouse
00367    if ( !entry ) return;
00368    gROOT->SetSelectedPrimitive( entry );
00369    entry->SetFillAttributes();
00370 }
00371 
00372 
00373 //______________________________________________________________________________
00374 void TLegend::EditEntryAttLine()
00375 {
00376    /* Begin_Html
00377    Edit the line attributes for the entry pointed by the mouse.
00378    End_Html */
00379 
00380    TLegendEntry* entry = GetEntry();   // get entry pointed by the mouse
00381    if ( !entry ) return;
00382    gROOT->SetSelectedPrimitive( entry );
00383    entry->SetLineAttributes();
00384 }
00385 
00386 
00387 //______________________________________________________________________________
00388 void TLegend::EditEntryAttMarker()
00389 {
00390    /* Begin_Html
00391    Edit the marker attributes for the entry pointed by the mouse.
00392    End_Html */
00393 
00394    TLegendEntry* entry = GetEntry();   // get entry pointed by the mouse
00395    if ( !entry ) return;
00396    gROOT->SetSelectedPrimitive( entry );
00397    entry->SetMarkerAttributes();
00398 }
00399 
00400 
00401 //______________________________________________________________________________
00402 void TLegend::EditEntryAttText()
00403 {
00404    /* Begin_Html
00405    Edit the text attributes for the entry pointed by the mouse.
00406    End_Html */
00407 
00408    TLegendEntry* entry = GetEntry();   // get entry pointed by the mouse
00409    if ( !entry ) return;
00410    gROOT->SetSelectedPrimitive( entry );
00411    entry->SetTextAttributes();
00412 }
00413 
00414 
00415 //______________________________________________________________________________
00416 TLegendEntry *TLegend::GetEntry() const
00417 {
00418    /* Begin_Html
00419    Get entry pointed to by the mouse.
00420    This method is mostly a tool for other methods inside this class.
00421    End_Html */
00422 
00423    Int_t nRows = GetNRows();
00424    if ( nRows == 0 ) return 0;
00425 
00426    Double_t ymouse = gPad->AbsPixeltoY(gPad->GetEventY());
00427    Double_t yspace = (fY2 - fY1)/nRows;
00428 
00429    Double_t ybottomOfEntry = fY2;  // y-location of bottom of 0th entry
00430    TIter next(fPrimitives);
00431    TLegendEntry *entry;
00432    while (( entry = (TLegendEntry *)next() )) {
00433       ybottomOfEntry -= yspace;
00434       if ( ybottomOfEntry < ymouse ) return entry;
00435    }
00436    return 0;
00437 }
00438 
00439 
00440 //______________________________________________________________________________
00441 const char *TLegend::GetHeader() const
00442 {
00443    /* Begin_Html
00444    Returns the header, which is the title that appears at the top
00445    of the legend.
00446    End_Html */
00447 
00448    if ( !fPrimitives ) return 0;
00449       TIter next(fPrimitives);
00450    TLegendEntry *first;   // header is always the first entry
00451    if ((  first = (TLegendEntry*)next()  )) {
00452       TString opt = first->GetOption();
00453       opt.ToLower();
00454       if ( opt.Contains("h") ) return first->GetLabel();
00455    }
00456    return 0;
00457 }
00458 
00459 
00460 //______________________________________________________________________________
00461 void TLegend::InsertEntry( const char* objectName, const char* label, Option_t* option)
00462 {
00463    /* Begin_Html
00464    Add a new entry before the entry at the mouse position.
00465    End_Html */
00466 
00467    TLegendEntry* beforeEntry = GetEntry();   // get entry pointed by the mouse
00468    TObject *obj = gPad->FindObject( objectName );
00469 
00470    // note either obj OR beforeEntry may be zero at this point
00471 
00472    TLegendEntry *newentry = new TLegendEntry( obj, label, option );
00473 
00474    if ( !fPrimitives ) fPrimitives = new TList;
00475    if ( beforeEntry ) {
00476       fPrimitives->AddBefore( (TObject*)beforeEntry, (TObject*)newentry );
00477    } else {
00478       fPrimitives->Add((TObject*)newentry);
00479    }
00480 }
00481 
00482 
00483 //______________________________________________________________________________
00484 void TLegend::Paint( Option_t* option )
00485 {
00486    /* Begin_Html
00487    Paint this legend with its current attributes.
00488    End_Html */
00489 
00490    TPave::ConvertNDCtoPad();
00491    TPave::PaintPave(fX1,fY1,fX2,fY2,GetBorderSize(),option);
00492    PaintPrimitives();
00493 }
00494 
00495 
00496 //______________________________________________________________________________
00497 Int_t TLegend::GetNRows() const
00498 {
00499    /* Begin_Html
00500    Get the number of rows.
00501    End_Html */
00502 
00503    Int_t nEntries = 0;
00504    if ( fPrimitives ) nEntries = fPrimitives->GetSize();
00505    if ( nEntries == 0 ) return 0;
00506 
00507    Int_t nRows;
00508    if(GetHeader() != NULL) nRows = 1 + (Int_t) TMath::Ceil((Double_t) (nEntries-1)/fNColumns);
00509    else  nRows = (Int_t) TMath::Ceil((Double_t) nEntries/fNColumns);
00510 
00511    return nRows;
00512 }
00513 
00514 
00515 //______________________________________________________________________________
00516 void TLegend::SetNColumns(Int_t nColumns)
00517 {
00518    /* Begin_Html
00519    Set the number of columns for the legend. The header, if set, is given
00520    its own row. After that, every nColumns entries are inserted into the
00521    same row. For example, if one calls legend.SetNColumns(2), and there
00522    is no header, then the first two TObjects added to the legend will be
00523    in the first row, the next two will appear in the second row, and so on.
00524    End_Html */
00525 
00526    if(nColumns < 1) {
00527       Warning("TLegend::SetNColumns", "illegal value nColumns = %d; keeping fNColumns = %d", nColumns, fNColumns);
00528       return;
00529    }
00530    fNColumns = nColumns;
00531 }
00532 
00533 
00534 //______________________________________________________________________________
00535 void TLegend::PaintPrimitives()
00536 {
00537    /* Begin_Html
00538    Paint the entries (list of primitives) for this legend.
00539    End_Html */
00540 
00541    Int_t nRows = GetNRows();
00542    if ( nRows == 0 ) return;
00543 
00544    // Evaluate text size as a function of the number of entries
00545    //  taking into account their real size after drawing latex
00546    // Note: in pixel coords y1 > y2=0, but x2 > x1=0
00547    //       in NDC          y2 > y1,   and x2 > x1
00548 
00549    Double_t x1 = fX1NDC;
00550    Double_t y1 = fY1NDC;
00551    Double_t x2 = fX2NDC;
00552    Double_t y2 = fY2NDC;
00553    Double_t margin = fMargin*( x2-x1 )/fNColumns;
00554    Double_t boxwidth = margin;
00555    Double_t boxw = boxwidth*0.35;
00556    Double_t yspace = (y2-y1)/nRows;
00557    Double_t textsize = GetTextSize();
00558    Double_t save_textsize = textsize;
00559    Double_t* columnWidths = new Double_t[fNColumns];
00560    memset(columnWidths, 0, fNColumns*sizeof(Double_t));
00561 
00562    if ( textsize == 0 ) {
00563       textsize = ( 1. - fEntrySeparation ) * yspace;
00564 
00565       // find the max width and height (in pad coords) of one latex entry label
00566       Double_t maxentrywidth = 0, maxentryheight = 0;
00567       TIter nextsize(fPrimitives);
00568       TLegendEntry *entrysize;
00569       Int_t iColumn = 0;
00570       while (( entrysize = (TLegendEntry *)nextsize() )) {
00571          TLatex entrytex( 0, 0, entrysize->GetLabel() );
00572          entrytex.SetNDC();
00573          Style_t tfont = entrysize->GetTextFont();
00574          if (tfont == 0) tfont = GetTextFont();
00575          entrytex.SetTextFont(tfont);
00576          entrytex.SetTextSize(textsize);
00577          if ( entrytex.GetYsize() > maxentryheight ) {
00578             maxentryheight = entrytex.GetYsize();
00579          }
00580          TString opt = entrysize->GetOption();
00581          opt.ToLower();
00582          if ( opt.Contains("h") ) {
00583             if ( entrytex.GetXsize() > maxentrywidth ) {
00584                maxentrywidth = entrytex.GetXsize();
00585             }
00586          } else {
00587             if ( entrytex.GetXsize() > columnWidths[iColumn] ) {
00588                columnWidths[iColumn] = entrytex.GetXsize();
00589             }
00590             iColumn++;
00591             iColumn %= fNColumns;
00592          }
00593          Double_t tmpMaxWidth = 0.0;
00594          for(int i=0; i<fNColumns; i++) tmpMaxWidth += columnWidths[i];
00595          if ( tmpMaxWidth > maxentrywidth) maxentrywidth = tmpMaxWidth;
00596       }
00597       // make sure all labels fit in the allotted space
00598       Double_t tmpsize_h = maxentryheight /(gPad->GetY2() - gPad->GetY1());
00599       textsize = TMath::Min( textsize, tmpsize_h );
00600       Double_t tmpsize_w = textsize*(fX2-fX1)*(1.0-fMargin)/maxentrywidth;
00601       if(fNColumns > 1) tmpsize_w = textsize*(fX2-fX1)*(1.0-fMargin-fColumnSeparation)/maxentrywidth;
00602       textsize = TMath::Min( textsize, tmpsize_w );
00603       SetTextSize( textsize );
00604    }
00605 
00606    // Update column widths, put into NDC units
00607    // block off this section of code to make sure all variables are local:
00608    // don't want to ruin initialization of these variables later on
00609    {
00610       TIter next(fPrimitives);
00611       TLegendEntry *entry;
00612       Int_t iColumn = 0;
00613       memset(columnWidths, 0, fNColumns*sizeof(Double_t));
00614       while (( entry = (TLegendEntry *)next() )) {
00615          TLatex entrytex( 0, 0, entry->GetLabel() );
00616          entrytex.SetNDC();
00617          Style_t tfont = entry->GetTextFont();
00618          if (tfont == 0) tfont = GetTextFont();
00619          entrytex.SetTextFont(tfont);
00620          if(entry->GetTextSize() == 0) entrytex.SetTextSize(textsize);
00621          TString opt = entry->GetOption();
00622          opt.ToLower();
00623          if (!opt.Contains("h")) {
00624             if ( entrytex.GetXsize() > columnWidths[iColumn] ) {
00625                columnWidths[iColumn] = entrytex.GetXsize();
00626             }
00627             iColumn++;
00628             iColumn %= fNColumns;
00629          }
00630       }
00631       double totalWidth = 0.0;
00632       for(int i=0; i<fNColumns; i++) totalWidth += columnWidths[i];
00633       if(fNColumns > 1) totalWidth /= (1.0-fMargin-fColumnSeparation);
00634       else totalWidth /= (1.0 - fMargin);
00635       for(int i=0; i<fNColumns; i++) {
00636          columnWidths[i] = columnWidths[i]/totalWidth*(x2-x1) + margin;
00637       }
00638    }
00639 
00640    Double_t ytext = y2 + 0.5*yspace;  // y-location of 0th entry
00641 
00642    // iterate over and paint all the TLegendEntries
00643    TIter next(fPrimitives);
00644    TLegendEntry *entry;
00645    Int_t iColumn = 0;
00646    while (( entry = (TLegendEntry *)next() )) {
00647       if(iColumn == 0) ytext -= yspace;
00648 
00649       // Draw Label in Latexmargin
00650 
00651       Short_t talign = entry->GetTextAlign();
00652       Float_t tangle = entry->GetTextAngle();
00653       Color_t tcolor = entry->GetTextColor();
00654       Style_t tfont  = entry->GetTextFont();
00655       Size_t  tsize  = entry->GetTextSize();
00656       // if the user hasn't set a parameter, then set it to the TLegend value
00657       if (talign == 0) entry->SetTextAlign(GetTextAlign());
00658       if (tangle == 0) entry->SetTextAngle(GetTextAngle());
00659       if (tcolor == 0) entry->SetTextColor(GetTextColor());
00660       if (tfont  == 0) entry->SetTextFont(GetTextFont());
00661       if (tsize  == 0) entry->SetTextSize(GetTextSize());
00662       // set x,y according to the requested alignment
00663       Double_t x=0,y=0;
00664       Int_t halign = entry->GetTextAlign()/10;
00665       Double_t entrymargin = margin;
00666       // for the header the margin is near zero
00667       TString opt = entry->GetOption();
00668       opt.ToLower();
00669       x1 = fX1NDC;
00670       x2 = fX2NDC;
00671       if ( opt.Contains("h") ) entrymargin = margin/10.;
00672       else if (fNColumns > 1) {
00673          for(int i=0; i<iColumn; i++) x1 += columnWidths[i] + fColumnSeparation*(fX2NDC-fX1NDC)/(fNColumns-1);
00674          x2 = x1 + columnWidths[iColumn];
00675          iColumn++;
00676          iColumn %= fNColumns;
00677       }
00678       if (halign == 1) x = x1 + entrymargin;
00679       if (halign == 2) x = 0.5*( (x1+entrymargin) + x2 );
00680       if (halign == 3) x = x2 - entrymargin/10.;
00681       Int_t valign = entry->GetTextAlign()%10;
00682       if (valign == 1) y = ytext - (1. - fEntrySeparation)* yspace/2.;
00683       if (valign == 2) y = ytext;
00684       if (valign == 3) y = ytext + (1. - fEntrySeparation)* yspace/2.;
00685       //
00686       TLatex entrytex( x, y, entry->GetLabel() );
00687       entrytex.SetNDC();
00688       entry->TAttText::Copy(entrytex);
00689       entrytex.Paint();
00690       // reset attributes back to their original values
00691       entry->SetTextAlign(talign);
00692       entry->SetTextAngle(tangle);
00693       entry->SetTextColor(tcolor);
00694       entry->SetTextFont(tfont);
00695       entry->SetTextSize(tsize);
00696 
00697       // define x,y as the center of the symbol for this entry
00698       Double_t xsym = x1 + margin/2.;
00699       Double_t ysym = ytext;
00700 
00701       TObject *eobj = entry->GetObject();
00702 
00703       // Draw fill pattern (in a box)
00704 
00705       if ( opt.Contains("f")) {
00706          if (eobj && eobj->InheritsFrom(TAttFill::Class())) {
00707             dynamic_cast<TAttFill*>(eobj)->Copy(*entry);
00708          }
00709 
00710          // box total height is yspace*0.7
00711          entry->TAttFill::Modify();
00712          Double_t xf[4],yf[4];
00713          xf[0] = xsym - boxw;
00714          yf[0] = ysym - yspace*0.35;
00715          xf[1] = xsym + boxw;
00716          yf[1] = yf[0];
00717          xf[2] = xf[1];
00718          yf[2] = ysym + yspace*0.35;
00719          xf[3] = xf[0];
00720          yf[3] = yf[2];
00721          for (Int_t i=0;i<4;i++) {
00722             xf[i] = gPad->GetX1() + xf[i]*(gPad->GetX2()-gPad->GetX1());
00723             yf[i] = gPad->GetY1() + yf[i]*(gPad->GetY2()-gPad->GetY1());
00724          }
00725          gPad->PaintFillArea(4,xf,yf);
00726       }
00727 
00728       // Draw line
00729 
00730       if ( opt.Contains("l") || opt.Contains("f")) {
00731 
00732          if (eobj && eobj->InheritsFrom(TAttLine::Class())) {
00733             dynamic_cast<TAttLine*>(eobj)->Copy(*entry);
00734          }
00735          // line total length (in x) is margin*0.8
00736          TLine entryline( xsym - boxw, ysym, xsym + boxw, ysym );
00737          entryline.SetBit(TLine::kLineNDC);
00738          entry->TAttLine::Copy(entryline);
00739          // if the entry is filled, then surround the box with the line instead
00740          if ( opt.Contains("f") && !opt.Contains("l")) {
00741             // box total height is yspace*0.7
00742             boxwidth = yspace*
00743                (gPad->GetX2()-gPad->GetX1())/(gPad->GetY2()-gPad->GetY1());
00744             if ( boxwidth > margin ) boxwidth = margin;
00745 
00746             entryline.PaintLineNDC( xsym - boxw, ysym + yspace*0.35,
00747                                  xsym + boxw, ysym + yspace*0.35);
00748             entryline.PaintLineNDC( xsym - boxw, ysym - yspace*0.35,
00749                                  xsym + boxw, ysym - yspace*0.35);
00750             entryline.PaintLineNDC( xsym + boxw, ysym - yspace*0.35,
00751                                  xsym + boxw, ysym + yspace*0.35);
00752             entryline.PaintLineNDC( xsym - boxw, ysym - yspace*0.35,
00753                                  xsym - boxw, ysym + yspace*0.35);
00754          } else {
00755             entryline.Paint();
00756             if (opt.Contains("e")) {
00757                entryline.PaintLineNDC( xsym, ysym - yspace*0.30,
00758                                        xsym, ysym + yspace*0.30);
00759             }
00760          }
00761       }
00762 
00763       // Draw Polymarker
00764 
00765       if ( opt.Contains("p")) {
00766 
00767          if (eobj && eobj->InheritsFrom(TAttMarker::Class())) {
00768             dynamic_cast<TAttMarker*>(eobj)->Copy(*entry);
00769          }
00770          TMarker entrymarker( xsym, ysym, 0 );
00771          entrymarker.SetNDC();
00772          entry->TAttMarker::Copy(entrymarker);
00773          entrymarker.Paint();
00774       }
00775    }
00776 
00777    SetTextSize(save_textsize);
00778    delete [] columnWidths;
00779 }
00780 
00781 
00782 //______________________________________________________________________________
00783 void TLegend::Print( Option_t* option ) const
00784 {
00785    /* Begin_Html
00786    Dump this TLegend and its contents.
00787    End_Html */
00788 
00789    TPave::Print( option );
00790    if (fPrimitives) fPrimitives->Print();
00791 }
00792 
00793 
00794 //______________________________________________________________________________
00795 void TLegend::RecursiveRemove(TObject *obj)
00796 {
00797    /* Begin_Html
00798    Reset the legend entries pointing to "obj".
00799    End_Html */
00800 
00801    TIter next(fPrimitives);
00802    TLegendEntry *entry;
00803    while (( entry = (TLegendEntry *)next() )) {
00804       if (entry->GetObject() == obj) entry->SetObject((TObject*)0);
00805    }
00806 }
00807 
00808 
00809 //______________________________________________________________________________
00810 void TLegend::SavePrimitive(ostream &out, Option_t* )
00811 {
00812    /* Begin_Html
00813    Save this legend as C++ statements on output stream out
00814    to be used with the SaveAs .C option.
00815    End_Html */
00816 
00817    out << "   " << endl;
00818    char quote = '"';
00819    if ( gROOT->ClassSaved( TLegend::Class() ) ) {
00820       out << "   ";
00821    } else {
00822       out << "   TLegend *";
00823    }
00824    // note, we can always use NULL header, since its included in primitives
00825    out << "leg = new TLegend("<<GetX1NDC()<<","<<GetY1NDC()<<","
00826        <<GetX2NDC()<<","<<GetY2NDC()<<","
00827        << "NULL" << "," <<quote<< fOption <<quote<<");" << endl;
00828    if (fBorderSize != 4) {
00829       out<<"   leg->SetBorderSize("<<fBorderSize<<");"<<endl;
00830    }
00831    SaveTextAttributes(out,"leg",12,0,1,42,0);
00832    SaveLineAttributes(out,"leg",-1,-1,-1);
00833    SaveFillAttributes(out,"leg",-1,-1);
00834    if ( fPrimitives ) {
00835       TIter next(fPrimitives);
00836       TLegendEntry *entry;
00837       while (( entry = (TLegendEntry *)next() )) entry->SaveEntry(out,"leg");
00838    }
00839    out << "   leg->Draw();"<<endl;
00840 }
00841 
00842 
00843 //______________________________________________________________________________
00844 void TLegend::SetEntryLabel( const char* label )
00845 {
00846    /* Begin_Html
00847    Edit the label of the entry pointed to by the mouse.
00848    End_Html */
00849 
00850    TLegendEntry* entry = GetEntry();   // get entry pointed by the mouse
00851    if ( entry ) entry->SetLabel( label );
00852 }
00853 
00854 
00855 //______________________________________________________________________________
00856 void TLegend::SetEntryOption( Option_t* option )
00857 {
00858    /* Begin_Html
00859    Edit the option of the entry pointed to by the mouse.
00860    End_Html */
00861 
00862    TLegendEntry* entry = GetEntry();   // get entry pointed by the mouse
00863    if ( entry ) entry->SetOption( option );
00864 }
00865 
00866 
00867 //______________________________________________________________________________
00868 void TLegend::SetHeader( const char *header )
00869 {
00870    /* Begin_Html
00871    Sets the header, which is the "title" that appears at the top of the legend.
00872    End_Html */
00873 
00874    if ( !fPrimitives ) fPrimitives = new TList;
00875    TIter next(fPrimitives);
00876    TLegendEntry *first;   // header is always the first entry
00877    if ((  first = (TLegendEntry*)next() )) {
00878       TString opt = first->GetOption();
00879       opt.ToLower();
00880       if ( opt.Contains("h") ) {
00881          first->SetLabel(header);
00882          return;
00883       }
00884    }
00885    first = new TLegendEntry( 0, header, "h" );
00886    first->SetTextAlign(0);
00887    first->SetTextAngle(0);
00888    first->SetTextColor(0);
00889    first->SetTextFont(GetTextFont()); // default font is TLegend font for the header
00890    first->SetTextSize(0);
00891    fPrimitives->AddFirst((TObject*)first);
00892 }

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