TGListView.cxx

Go to the documentation of this file.
00001 // @(#)root/gui:$Id: TGListView.cxx 35582 2010-09-22 13:38:27Z bellenot $
00002 // Author: Fons Rademakers   17/01/98
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 
00013     This source is based on Xclass95, a Win95-looking GUI toolkit.
00014     Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
00015 
00016     Xclass95 is free software; you can redistribute it and/or
00017     modify it under the terms of the GNU Library General Public
00018     License as published by the Free Software Foundation; either
00019     version 2 of the License, or (at your option) any later version.
00020 
00021 **************************************************************************/
00022 
00023 //////////////////////////////////////////////////////////////////////////
00024 //                                                                      //
00025 // TGListView, TGLVContainer and TGLVEntry                              //
00026 //                                                                      //
00027 // A list view is a widget that can contain a number of items           //
00028 // arranged in a grid or list. The items can be represented either      //
00029 // by a string or by an icon.                                           //
00030 //                                                                      //
00031 // The TGListView is user callable. The other classes are service       //
00032 // classes of the list view.                                            //
00033 //                                                                      //
00034 // A list view can generate the following events:                       //
00035 // kC_CONTAINER, kCT_SELCHANGED, total items, selected items.           //
00036 // kC_CONTAINER, kCT_ITEMCLICK, which button, location (y<<16|x).       //
00037 // kC_CONTAINER, kCT_ITEMDBLCLICK, which button, location (y<<16|x).    //
00038 //                                                                      //
00039 //////////////////////////////////////////////////////////////////////////
00040 
00041 #include "TGListView.h"
00042 #include "TGPicture.h"
00043 #include "TGButton.h"
00044 #include "TGScrollBar.h"
00045 #include "TGResourcePool.h"
00046 #include "TList.h"
00047 #include "TSystem.h"
00048 #include "TGMimeTypes.h"
00049 #include "TObjString.h"
00050 #include "Riostream.h"
00051 
00052 const TGFont *TGLVEntry::fgDefaultFont = 0;
00053 TGGC         *TGLVEntry::fgDefaultGC = 0;
00054 
00055 const TGFont *TGListView::fgDefaultFont = 0;
00056 TGGC         *TGListView::fgDefaultGC = 0;
00057 
00058 
00059 ClassImp(TGLVEntry)
00060 ClassImp(TGLVContainer)
00061 ClassImp(TGListView)
00062 
00063 //______________________________________________________________________________
00064 TGLVEntry::TGLVEntry(const TGWindow *p, const TGPicture *bigpic,
00065                      const TGPicture *smallpic, TGString *name,
00066                      TGString **subnames, EListViewMode viewMode,
00067                      UInt_t options, ULong_t back) :
00068    TGFrame(p, 10, 10, options, back)
00069 {
00070    // Create a list view item.
00071 
00072    fSelPic = 0;
00073 
00074    fCurrent  =
00075    fBigPic   = bigpic;
00076    fSmallPic = smallpic;
00077 
00078    fCheckMark  = fClient->GetPicture("checkmark_t.xpm");
00079    fChecked = kFALSE;
00080 
00081    fItemName = name;
00082    fSubnames = subnames;
00083    fUserData = 0;
00084 
00085    fCpos  =
00086    fJmode = 0;
00087 
00088    fActive = kFALSE;
00089 
00090    fFontStruct = GetDefaultFontStruct();
00091    fNormGC     = GetDefaultGC()();
00092 
00093    Int_t max_ascent, max_descent;
00094    fTWidth = gVirtualX->TextWidth(fFontStruct,
00095                                   fItemName ? fItemName->GetString() : "",
00096                                   fItemName ? fItemName->GetLength() : 0);
00097    gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
00098    fTHeight = max_ascent + max_descent;
00099 
00100    if (fSubnames) {
00101       Int_t i;
00102       for (i = 0; fSubnames[i] != 0; ++i)
00103          ;
00104       fCtw = new int[i+1];
00105       fCtw[i] = 0;
00106       for (i = 0; fSubnames[i] != 0; ++i) {
00107          fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
00108                                         fSubnames[i]->GetLength());
00109       }
00110    } else {
00111       fCtw = 0;
00112    }
00113 
00114    fViewMode = (EListViewMode)-1;
00115    SetViewMode(viewMode);
00116 }
00117 
00118 //______________________________________________________________________________
00119 TGLVEntry::TGLVEntry(const TGLVContainer *p, const TString& name,
00120                      const TString& cname, TGString **subnames,
00121                      UInt_t options, Pixel_t back) :
00122    TGFrame(p, 10, 10, options, back)
00123 {
00124    // Create a list view item.
00125    //
00126    // name - is name of item.
00127    // cname - is name of icon. In most cases this is class name of object
00128    //         associated with this item.
00129 
00130    fSelPic = 0;
00131 
00132    fCurrent  =
00133    fBigPic   = fClient->GetMimeTypeList()->GetIcon(cname, kFALSE);
00134    fCheckMark  = fClient->GetPicture("checkmark_t.xpm");
00135    fChecked = kFALSE;
00136 
00137    if (!fBigPic) {
00138       fBigPic = fClient->GetPicture("doc_s.xpm");
00139    }
00140    fSmallPic = fClient->GetMimeTypeList()->GetIcon(cname, kTRUE);
00141    if (!fSmallPic) {
00142       fSmallPic = fClient->GetPicture("doc_t.xpm");
00143    }
00144 
00145    fItemName = new TGString(name);
00146    fSubnames = subnames;
00147    fUserData = 0;
00148 
00149    fCpos  =
00150    fJmode = 0;
00151 
00152    fActive = kFALSE;
00153 
00154    fFontStruct = GetDefaultFontStruct();
00155    fNormGC     = GetDefaultGC()();
00156 
00157    Int_t max_ascent, max_descent;
00158    fTWidth = gVirtualX->TextWidth(fFontStruct, fItemName->GetString(), fItemName->GetLength());
00159    gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
00160    fTHeight = max_ascent + max_descent;
00161 
00162    if (fSubnames) {
00163       Int_t i;
00164       for (i = 0; fSubnames[i] != 0; ++i)
00165          ;
00166       fCtw = new int[i+1];
00167       fCtw[i] = 0;
00168       for (i = 0; fSubnames[i] != 0; ++i) {
00169          fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
00170                                         fSubnames[i]->GetLength());
00171       }
00172    } else {
00173       fCtw = 0;
00174    }
00175 
00176    fViewMode = (EListViewMode)-1;
00177    SetViewMode((EListViewMode)p->GetViewMode());
00178 }
00179 
00180 //______________________________________________________________________________
00181 TGLVEntry::~TGLVEntry()
00182 {
00183    // Delete a list view item.
00184 
00185    if (fItemName) delete fItemName;
00186    if (fSelPic) delete fSelPic;
00187    if (fSubnames) {
00188       for (Int_t i = 0; fSubnames[i] != 0; ++i) delete fSubnames[i];
00189       delete [] fSubnames;
00190       delete [] fCtw;
00191    }
00192 }
00193 
00194 //______________________________________________________________________________
00195 void TGLVEntry::SetSubnames(const char* n1,const char* n2,const char* n3,
00196                             const char* n4,const char* n5,const char* n6,
00197                             const char* n7,const char* n8,const char* n9,
00198                             const char* n10,const char* n11,const char* n12)
00199 {
00200    // Sets new subnames.
00201 
00202    if (fSubnames) {
00203       for (Int_t i = 0; fSubnames[i] != 0; ++i) delete fSubnames[i];
00204       delete [] fSubnames;
00205       delete [] fCtw;
00206    }
00207 
00208    Int_t ncol = 0;
00209    fSubnames = 0;
00210 
00211    if (n12 && strlen(n12)) ncol=12;
00212    else if (n11 && strlen(n11)) ncol=11;
00213    else if (n10 && strlen(n10)) ncol=10;
00214    else if (n9 && strlen(n9)) ncol=9;
00215    else if (n8 && strlen(n8)) ncol=8;
00216    else if (n7 && strlen(n7)) ncol=7;
00217    else if (n6 && strlen(n6)) ncol=6;
00218    else if (n5 && strlen(n5)) ncol=5;
00219    else if (n4 && strlen(n4)) ncol=4;
00220    else if (n3 && strlen(n3)) ncol=3;
00221    else if (n2 && strlen(n2)) ncol=2;
00222    else if (n1 && strlen(n1)) ncol=1;
00223 
00224    if (!ncol) return;
00225 
00226    fSubnames = new TGString* [ncol+1];
00227 
00228    if (ncol>11) fSubnames[11] = new TGString(n12);
00229    if (ncol>10) fSubnames[10] = new TGString(n11);
00230    if (ncol>9) fSubnames[9] = new TGString(n10);
00231    if (ncol>8) fSubnames[8] = new TGString(n9);
00232    if (ncol>7) fSubnames[7] = new TGString(n8);
00233    if (ncol>6) fSubnames[6] = new TGString(n7);
00234    if (ncol>5) fSubnames[5] = new TGString(n6);
00235    if (ncol>4) fSubnames[4] = new TGString(n5);
00236    if (ncol>3) fSubnames[3] = new TGString(n4);
00237    if (ncol>2) fSubnames[2] = new TGString(n3);
00238    if (ncol>1) fSubnames[1] = new TGString(n2);
00239    if (ncol>0) fSubnames[0] = new TGString(n1);
00240    fSubnames[ncol] = 0;
00241 
00242    fCtw = new int[ncol];
00243    fCtw[ncol-1] = 0;
00244 
00245    for (int i = 0; i<ncol; i++) {
00246       fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
00247                                      fSubnames[i]->GetLength());
00248    }
00249 }
00250 
00251 //______________________________________________________________________________
00252 void TGLVEntry::Activate(Bool_t a)
00253 {
00254    // Make list view item active.
00255 
00256    if (fActive == a) return;
00257    fActive = a;
00258 
00259    if (fActive) {
00260       fSelPic = new TGSelectedPicture(gClient, fCurrent);
00261    } else {
00262       if (fSelPic) delete fSelPic;
00263       fSelPic = 0;
00264    }
00265    DoRedraw();
00266 }
00267 
00268 //______________________________________________________________________________
00269 void TGLVEntry::SetViewMode(EListViewMode viewMode)
00270 {
00271    // Set the view mode for this list item.
00272 
00273    if (viewMode != fViewMode) {
00274       fViewMode = viewMode;
00275       if (viewMode == kLVLargeIcons)
00276          fCurrent = fBigPic;
00277       else
00278          fCurrent = fSmallPic;
00279       if (fActive) {
00280          if (fSelPic) delete fSelPic;
00281          fSelPic = new TGSelectedPicture(gClient, fCurrent);
00282       }
00283       gVirtualX->ClearWindow(fId);
00284       Resize(GetDefaultSize());
00285       fClient->NeedRedraw(this);
00286    }
00287 }
00288 
00289 //______________________________________________________________________________
00290 void TGLVEntry::SetPictures(const TGPicture *bigpic, const TGPicture *smallpic)
00291 {
00292    // change pictures
00293 
00294    if (!bigpic || !smallpic) return;
00295 
00296    gVirtualX->ClearWindow(fId);
00297 
00298    fBigPic = bigpic;
00299    fSmallPic = smallpic;
00300    fCurrent = fViewMode == kLVLargeIcons ? fBigPic : fSmallPic;
00301 
00302    if (fSelPic) delete fSelPic;
00303    fSelPic = new TGSelectedPicture(gClient, fCurrent);
00304 
00305    Resize();
00306    gVirtualX->ClearWindow(fId);
00307 }
00308 
00309 //______________________________________________________________________________
00310 void TGLVEntry::DoRedraw()
00311 {
00312    // Redraw list view item.
00313    // List view item is placed and layouted in the container frame,
00314    // but is drawn in viewport.
00315 
00316    DrawCopy(fId, 0, 0);
00317 }
00318 
00319 //______________________________________________________________________________
00320 void TGLVEntry::DrawCopy(Handle_t id, Int_t x, Int_t y)
00321 {
00322    // Draw list view item in other window.
00323    // List view item is placed and layout in the container frame,
00324    // but is drawn in viewport.
00325 
00326    Int_t ix, iy, lx, ly;
00327    Int_t max_ascent, max_descent;
00328 
00329    gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
00330    fTWidth = gVirtualX->TextWidth(fFontStruct, fItemName->GetString(), fItemName->GetLength());
00331    fTHeight = max_ascent + max_descent;
00332 
00333    if (fViewMode == kLVLargeIcons) {
00334       ix = (fWidth - fCurrent->GetWidth()) >> 1;
00335       iy = 0;
00336       lx = (fWidth - fTWidth) >> 1;
00337       ly = fHeight - (fTHeight + 1) - 2;
00338    } else {
00339       ix = 0;
00340       iy = (fHeight - fCurrent->GetHeight()) >> 1;
00341       lx = fCurrent->GetWidth() + 2;
00342       ly = (fHeight - (fTHeight + 1)) >> 1;
00343    }
00344 
00345    if ((fChecked) && (fCheckMark)) {
00346       if (fViewMode == kLVLargeIcons) {
00347          fCheckMark->Draw(id, fNormGC, x + ix + 8, y + iy + 8);
00348          gVirtualX->SetForeground(fNormGC, fgWhitePixel);
00349          gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, fTWidth, fTHeight + 1);
00350          gVirtualX->SetForeground(fNormGC, fgBlackPixel);
00351       }
00352       else {
00353          fCheckMark->Draw(id, fNormGC, x + ix, y + iy);
00354          gVirtualX->SetForeground(fNormGC, fgWhitePixel);
00355          gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, fTWidth, fTHeight + 1);
00356          gVirtualX->SetForeground(fNormGC, fgBlackPixel);
00357       }
00358    }
00359    // This if tries to print the elements with ... appened at the end if
00360    // the widht of the string is longer than that of the column
00361    if (fViewMode == kLVDetails && fSubnames && fCpos && fJmode && fCtw) {
00362       TString tmpString = *fItemName;
00363       Int_t ftmpWidth = gVirtualX->TextWidth(fFontStruct, tmpString,
00364                                              tmpString.Length());
00365       if ( ftmpWidth > (fCpos[0] - lx) ) {
00366          for (Int_t j = fItemName->Length() - 1 ; j > 0; j--) {
00367             tmpString =  (*fItemName)(0,j) + "...";
00368             ftmpWidth = gVirtualX->TextWidth(GetDefaultFontStruct(), tmpString,
00369                                              tmpString.Length());
00370             if ( ftmpWidth <= (fCpos[0] - lx) ) {
00371                break;
00372             }
00373          }
00374       }
00375       if (fActive) {
00376          if (fSelPic) fSelPic->Draw(id, fNormGC, x + ix, y + iy);
00377          gVirtualX->SetForeground(fNormGC, fgDefaultSelectedBackground);
00378          gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, ftmpWidth, fTHeight + 1);
00379          gVirtualX->SetForeground(fNormGC, fClient->GetResourcePool()->GetSelectedFgndColor());
00380       } else {
00381          fCurrent->Draw(id, fNormGC, x + ix, y + iy);
00382          gVirtualX->SetForeground(fNormGC, fgWhitePixel);
00383          gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, ftmpWidth, fTHeight + 1);
00384          gVirtualX->SetForeground(fNormGC, fgBlackPixel);
00385       }
00386 
00387       TGString tmpTGString(tmpString);
00388       tmpTGString.Draw(id, fNormGC, x+lx, y+ly + max_ascent);
00389    } else {
00390       if (fActive) {
00391          if (fSelPic) fSelPic->Draw(id, fNormGC, x + ix, y + iy);
00392          gVirtualX->SetForeground(fNormGC, fgDefaultSelectedBackground);
00393          gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, fTWidth, fTHeight + 1);
00394          gVirtualX->SetForeground(fNormGC, fClient->GetResourcePool()->GetSelectedFgndColor());
00395       } else {
00396          fCurrent->Draw(id, fNormGC, x + ix, y + iy);
00397          gVirtualX->SetForeground(fNormGC, fgWhitePixel);
00398          gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, fTWidth, fTHeight + 1);
00399          gVirtualX->SetForeground(fNormGC, fgBlackPixel);
00400       }
00401       fItemName->Draw(id, fNormGC, x+lx, y+ly + max_ascent);
00402    }
00403    gVirtualX->SetForeground(fNormGC, fgBlackPixel);
00404 
00405    if (fViewMode == kLVDetails) {
00406       if (fSubnames && fCpos && fJmode && fCtw) {
00407          int i;
00408 
00409          // Again fixes the size of the strings
00410          for (i = 0; fSubnames[i] != 0; ++i) {
00411             TString tmpString = *fSubnames[i];
00412             Int_t ftmpWidth = gVirtualX->TextWidth(fFontStruct, tmpString,
00413                                                    tmpString.Length());
00414             if ( ftmpWidth > (fCpos[i+1] - fCpos[i]) ) {
00415                for (int j = fSubnames[i]->Length() - 1 ; j > 0; j--) {
00416                   tmpString =  (*fSubnames[i])(0,j) + "...";
00417                   ftmpWidth = gVirtualX->TextWidth(GetDefaultFontStruct(),
00418                                                    tmpString,
00419                                                    tmpString.Length());
00420                   if ( ftmpWidth <= (fCpos[i+1] - fCpos[i]) ) {
00421                      break;
00422                   }
00423                }
00424             }
00425             if (fCpos[i] == 0)
00426                break;
00427             if (fJmode[i] == kTextRight)
00428                lx = fCpos[i+1] - ftmpWidth - 2;
00429             else if (fJmode[i] == kTextCenterX)
00430                lx = (fCpos[i] + fCpos[i+1] - ftmpWidth) >> 1;
00431             else // default to TEXT_LEFT
00432                lx = fCpos[i] + 2;
00433 
00434             //if (x + lx < 0) continue; // out of left boundary or mess in name
00435             TGString tmpTGString(tmpString);
00436             tmpTGString.Draw(id, fNormGC, x + lx, y + ly + max_ascent);
00437          }
00438       }
00439    }
00440 }
00441 
00442 //______________________________________________________________________________
00443 TGDimension TGLVEntry::GetDefaultSize() const
00444 {
00445    // Get default size of list item.
00446 
00447    TGDimension size;
00448    TGDimension isize(fCurrent ? fCurrent->GetWidth() : 0,
00449                      fCurrent ? fCurrent->GetHeight() : 0);
00450    TGDimension lsize(fTWidth, fTHeight+1);
00451 
00452    switch (fViewMode) {
00453       default:
00454       case kLVLargeIcons:
00455          size.fWidth = TMath::Max(isize.fWidth, lsize.fWidth);
00456          size.fHeight = isize.fHeight + lsize.fHeight + 6;
00457          break;
00458 
00459       case kLVSmallIcons:
00460       case kLVList:
00461       case kLVDetails:
00462          size.fWidth = isize.fWidth + lsize.fWidth + 4;
00463          size.fHeight = TMath::Max(isize.fHeight, lsize.fHeight);
00464          break;
00465    }
00466    return size;
00467 }
00468 
00469 //______________________________________________________________________________
00470 FontStruct_t TGLVEntry::GetDefaultFontStruct()
00471 {
00472    // Return the default font structure in use.
00473 
00474    if (!fgDefaultFont)
00475       fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
00476    return fgDefaultFont->GetFontStruct();
00477 }
00478 
00479 //______________________________________________________________________________
00480 const TGGC &TGLVEntry::GetDefaultGC()
00481 {
00482    // Return the default graphics context in use.
00483 
00484    if (!fgDefaultGC) {
00485       fgDefaultGC = new TGGC(*gClient->GetResourcePool()->GetFrameGC());
00486       fgDefaultGC->SetFont(fgDefaultFont->GetFontHandle());
00487    }
00488    return *fgDefaultGC;
00489 }
00490 
00491 
00492 //______________________________________________________________________________
00493 TGLVContainer::TGLVContainer(const TGWindow *p, UInt_t w, UInt_t h,
00494                              UInt_t options, ULong_t back) :
00495    TGContainer(p, w, h, options, back)
00496 {
00497    // Create a list view container. This is the (large) frame that contains
00498    // all the list items. It will be shown through a TGViewPort (which is
00499    // created by the TGCanvas derived TGListView).
00500 
00501    fListView = 0;
00502    fLastActive = 0;
00503    fCpos = fJmode = 0;
00504    fMultiSelect = kFALSE;
00505 
00506    fViewMode = kLVLargeIcons;
00507    fItemLayout = new TGLayoutHints(kLHintsExpandY | kLHintsCenterX);
00508 
00509    SetLayoutManager(new TGTileLayout(this, 8));
00510 }
00511 
00512 //______________________________________________________________________________
00513 TGLVContainer::TGLVContainer(TGCanvas *p,UInt_t options, ULong_t back) :
00514    TGContainer(p,options, back)
00515 {
00516    // Create a list view container. This is the (large) frame that contains
00517    // all the list items. It will be shown through a TGViewPort (which is
00518    // created by the TGCanvas derived TGListView).
00519 
00520    fListView = 0;
00521    fLastActive = 0;
00522    fCpos = fJmode = 0;
00523    fMultiSelect = kFALSE;
00524 
00525    fViewMode = kLVLargeIcons;
00526    fItemLayout = new TGLayoutHints(kLHintsExpandY | kLHintsCenterX);
00527 
00528    SetLayoutManager(new TGTileLayout(this, 8));
00529 
00530    if (p->InheritsFrom(TGListView::Class())) fListView = (TGListView*)p;
00531 }
00532 
00533 //______________________________________________________________________________
00534 TGLVContainer::~TGLVContainer()
00535 {
00536    // Delete list view container.
00537 
00538    if (!MustCleanup()) {
00539       RemoveAll();
00540       delete fItemLayout;
00541    }
00542 }
00543 
00544 //______________________________________________________________________________
00545 void  TGLVContainer::SetColHeaders(const char* n1,const char* n2,const char* n3,
00546                                    const char* n4,const char* n5,const char* n6,
00547                                    const char* n7,const char* n8,const char* n9,
00548                                    const char* n10,const char* n11,const char* n12)
00549 {
00550    // set columns headers
00551 
00552    if (!fListView) return;
00553 
00554    Int_t ncol = -1;
00555    if (n12 && strlen(n12)) ncol=12;
00556    else if (n11 && strlen(n11)) ncol=11;
00557    else if (n10 && strlen(n10)) ncol=10;
00558    else if (n9 && strlen(n9)) ncol=9;
00559    else if (n8 && strlen(n8)) ncol=8;
00560    else if (n7 && strlen(n7)) ncol=7;
00561    else if (n6 && strlen(n6)) ncol=6;
00562    else if (n5 && strlen(n5)) ncol=5;
00563    else if (n4 && strlen(n4)) ncol=4;
00564    else if (n3 && strlen(n3)) ncol=3;
00565    else if (n2 && strlen(n2)) ncol=2;
00566    else if (n1 && strlen(n1)) ncol=1;
00567 
00568    if (ncol<0) return;
00569 
00570    fListView->SetHeaders(ncol);
00571    if (ncol>0) fListView->SetHeader(n1, kTextCenterX, kTextLeft , 0);
00572    if (ncol>1) fListView->SetHeader(n2, kTextCenterX, kTextLeft , 1);
00573    if (ncol>2) fListView->SetHeader(n3, kTextCenterX, kTextLeft , 2);
00574    if (ncol>3) fListView->SetHeader(n4, kTextCenterX, kTextLeft , 3);
00575    if (ncol>4) fListView->SetHeader(n5, kTextCenterX, kTextLeft , 4);
00576    if (ncol>5) fListView->SetHeader(n6, kTextCenterX, kTextLeft , 5);
00577    if (ncol>6) fListView->SetHeader(n7, kTextCenterX, kTextLeft , 6);
00578    if (ncol>7) fListView->SetHeader(n8, kTextCenterX, kTextLeft , 7);
00579    if (ncol>8) fListView->SetHeader(n9, kTextCenterX, kTextLeft , 8);
00580    if (ncol>9) fListView->SetHeader(n10, kTextCenterX, kTextLeft , 9);
00581    if (ncol>10) fListView->SetHeader(n11, kTextCenterX, kTextLeft , 10);
00582    if (ncol>11) fListView->SetHeader(n12, kTextCenterX, kTextLeft , 11);
00583 
00584    fListView->Layout();
00585 }
00586 
00587 //______________________________________________________________________________
00588 void TGLVContainer::SetViewMode(EListViewMode viewMode)
00589 {
00590    // Set list view mode for container.
00591 
00592    if (fViewMode != viewMode) {
00593       TGLayoutHints *oldLayout = fItemLayout;
00594 
00595       EListViewMode old = fViewMode;
00596       fViewMode = viewMode;
00597       if (fListView) fListView->SetViewMode(viewMode);
00598 
00599       if (viewMode == kLVLargeIcons)
00600          fItemLayout = new TGLayoutHints(kLHintsExpandY | kLHintsCenterX);
00601       else
00602          fItemLayout = new TGLayoutHints(kLHintsLeft | kLHintsCenterY);
00603 
00604       TGFrameElement *el;
00605       TIter next(fList);
00606       while ((el = (TGFrameElement *) next())) {
00607          el->fLayout = fItemLayout;
00608          ((TGLVEntry *) el->fFrame)->SetViewMode(viewMode);
00609       }
00610       delete oldLayout;
00611 
00612       switch (viewMode) {
00613          default:
00614          case kLVLargeIcons:
00615             SetLayoutManager(new TGTileLayout(this, 8));
00616             break;
00617 
00618          case kLVSmallIcons:
00619             SetLayoutManager(new TGTileLayout(this, 2));
00620             break;
00621 
00622          case kLVList:
00623             SetLayoutManager(new TGListLayout(this, 2));
00624             break;
00625 
00626          case kLVDetails:
00627             SetLayoutManager(new TGListDetailsLayout(this, 2));
00628             break;
00629       }
00630 
00631       TGCanvas *canvas = (TGCanvas *) this->GetParent()->GetParent();
00632 
00633       // layout and adjust position after layout
00634       UInt_t height = fHeight;
00635       UInt_t width = fWidth;
00636       TGPosition pos = GetPagePosition();
00637       canvas->Layout();
00638       pos.fX = (pos.fX*fWidth)/width;
00639       pos.fY = (pos.fY*fHeight)/height;
00640 
00641       if (old == kLVList) { // switch x <-> y
00642          SetVsbPosition(pos.fX);
00643          SetHsbPosition(0);
00644       } else if (fViewMode == kLVList) {
00645          SetHsbPosition(pos.fY);
00646       } else {
00647          SetVsbPosition(pos.fY);
00648          SetHsbPosition(pos.fX);
00649       }
00650    }
00651 }
00652 
00653 //______________________________________________________________________________
00654 void TGLVContainer::SetColumns(Int_t *cpos, Int_t *jmode)
00655 {
00656    // Set column information for list items.
00657 
00658    fCpos  = cpos;
00659    fJmode = jmode;
00660 
00661    TGFrameElement *el;
00662    TIter next(fList);
00663    while ((el = (TGFrameElement *) next())) {
00664       ((TGLVEntry *) el->fFrame)->SetColumns(fCpos, fJmode);
00665    }
00666    Layout();
00667 }
00668 
00669 //______________________________________________________________________________
00670 TGDimension TGLVContainer::GetMaxItemSize() const
00671 {
00672    // Get size of largest item in container.
00673 
00674    TGDimension csize, maxsize(0,0);
00675 
00676    TGFrameElement *el;
00677    TIter next(fList);
00678    while ((el = (TGFrameElement *) next())) {
00679       csize = el->fFrame->GetDefaultSize();
00680       maxsize.fWidth  = TMath::Max(maxsize.fWidth, csize.fWidth);
00681       maxsize.fHeight = TMath::Max(maxsize.fHeight, csize.fHeight);
00682    }
00683    if (fViewMode == kLVLargeIcons) {
00684       maxsize.fWidth  += 8;
00685       maxsize.fHeight += 8;
00686    } else {
00687       maxsize.fWidth  += 2;
00688       maxsize.fHeight += 2;
00689    }
00690    return maxsize;
00691 }
00692 
00693 //______________________________________________________________________________
00694 Int_t TGLVContainer::GetMaxSubnameWidth(Int_t idx) const
00695 {
00696    // Get width of largest subname in container.
00697 
00698    if (idx == 0) {
00699       return GetMaxItemSize().fWidth;
00700    }
00701 
00702    Int_t width, maxwidth = 0;
00703 
00704    TGFrameElement *el;
00705    TIter next(fList);
00706    while ((el = (TGFrameElement *) next())) {
00707       TGLVEntry *entry = (TGLVEntry *) el->fFrame;
00708       width = entry->GetSubnameWidth(idx-1);
00709       maxwidth = TMath::Max(maxwidth, width);
00710    }
00711    return maxwidth;
00712 }
00713 
00714 //______________________________________________________________________________
00715 void TGLVContainer::RemoveItemWithData(void *userData)
00716 {
00717    // Remove item with fUserData == userData from container.
00718 
00719    TGFrameElement *el;
00720    TIter next(fList);
00721    while ((el = (TGFrameElement *) next())) {
00722       TGLVEntry *f = (TGLVEntry *) el->fFrame;
00723       if (f->GetUserData() == userData) {
00724          RemoveItem(f);
00725          break;
00726       }
00727    }
00728 }
00729 
00730 //______________________________________________________________________________
00731 void TGLVContainer::ActivateItem(TGFrameElement* el)
00732 {
00733    // Select/activate item.
00734 
00735    TGContainer::ActivateItem(el);
00736    fLastActive = (TGLVEntry*)el->fFrame;
00737 }
00738 
00739 //______________________________________________________________________________
00740 void TGLVContainer::DeActivateItem(TGFrameElement* el)
00741 {
00742    // Unselect/deactivate item.
00743 
00744    TGContainer::DeActivateItem(el);
00745    fLastActive = (TGLVEntry*)el->fFrame;
00746 }
00747 
00748 //______________________________________________________________________________
00749 Bool_t TGLVContainer::HandleButton(Event_t* event)
00750 {
00751    // Handle mouse button event in container.
00752 
00753    if ( !fMultiSelect ) {
00754       return TGContainer::HandleButton(event);
00755    }
00756 
00757    Int_t total = 0, selected = fSelected, page = 0;
00758 
00759    TGPosition pos = GetPagePosition();
00760    TGDimension dim = GetPageDimension();
00761    Int_t newpos;
00762    page = dim.fHeight/4;
00763 
00764    if (event->fCode == kButton4) {
00765       //scroll up
00766       newpos = pos.fY - page;
00767       if (newpos < 0) newpos = 0;
00768       fCanvas->SetVsbPosition(newpos);
00769       return kTRUE;
00770    }
00771    if (event->fCode == kButton5) {
00772       // scroll down
00773       newpos = fCanvas->GetVsbPosition() + page;
00774       fCanvas->SetVsbPosition(newpos);
00775       return kTRUE;
00776    }
00777 
00778    Int_t xx = pos.fX + event->fX; // translate coordinates
00779    Int_t yy = pos.fY + event->fY;
00780 
00781    if (event->fType == kButtonPress) {
00782       gVirtualX->SetInputFocus(fId);
00783 
00784       fXp = pos.fX + event->fX;
00785       fYp = pos.fY + event->fY;
00786 
00787       TGFrameElement *el;
00788       TIter next(fList);
00789       Bool_t select_frame = kFALSE;
00790 
00791       if (event->fState & kKeyShiftMask) {
00792          Bool_t inSelection = kFALSE;
00793          TGLVEntry* last = fLastActive;
00794 
00795          while ((el = (TGFrameElement *) next())) {
00796             select_frame = kFALSE;
00797 
00798             if (!fMapSubwindows) {
00799                if ((Int_t(el->fFrame->GetY()) + (Int_t)el->fFrame->GetHeight() > yy ) &&
00800                   (Int_t(el->fFrame->GetX()) + (Int_t)el->fFrame->GetWidth() > xx ) &&
00801                   (Int_t(el->fFrame->GetY()) < yy) &&
00802                   (Int_t(el->fFrame->GetX()) < xx))  {
00803                   select_frame = kTRUE;
00804                }
00805             } else {
00806                if (el->fFrame->GetId() == (Window_t)event->fUser[0]) {
00807                   select_frame = kTRUE;
00808                }
00809             }
00810 
00811             if (select_frame || last==el->fFrame)
00812                inSelection = !inSelection;
00813             if (inSelection || select_frame) {
00814                if ( !el->fFrame->IsActive() ) {
00815                   selected++;
00816                   ActivateItem(el);
00817                }
00818                Clicked(el->fFrame, event->fCode);
00819                Clicked(el->fFrame, event->fCode, event->fXRoot, event->fYRoot);
00820             }
00821             total++;
00822          }
00823       } else if (event->fState & kKeyControlMask) {
00824          // DO NOTHING!
00825       } else {
00826          UnSelectAll();
00827          total = selected = 0;
00828       }
00829 
00830       select_frame = kFALSE;
00831       while ((el = (TGFrameElement *) next())) {
00832          select_frame = kFALSE;
00833 
00834          if (!fMapSubwindows) {
00835             if ((Int_t(el->fFrame->GetY()) + (Int_t)el->fFrame->GetHeight() > yy ) &&
00836                (Int_t(el->fFrame->GetX()) + (Int_t)el->fFrame->GetWidth() > xx ) &&
00837                (Int_t(el->fFrame->GetY()) < yy) &&
00838                (Int_t(el->fFrame->GetX()) < xx))  {
00839                select_frame = kTRUE;
00840             }
00841          } else {
00842             if (el->fFrame->GetId() == (Window_t)event->fUser[0]) {
00843                select_frame = kTRUE;
00844             }
00845          }
00846 
00847          if (select_frame) {
00848             if ( el->fFrame->IsActive() ) {
00849                selected--;
00850                DeActivateItem(el);
00851             } else {
00852                selected++;
00853                ActivateItem(el);
00854             }
00855             Clicked(el->fFrame, event->fCode);
00856             Clicked(el->fFrame, event->fCode, event->fXRoot, event->fYRoot);
00857          }
00858          total++;
00859       }
00860 
00861       if (fTotal != total || fSelected != selected) {
00862          fTotal = total;
00863          fSelected = selected;
00864          SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED),
00865                      fTotal, fSelected);
00866       }
00867 
00868       if ( selected == 0 ) {
00869          fDragging = kTRUE;
00870          fX0 = fXf = fXp;
00871          fY0 = fYf = fYp;
00872          //if (fMapSubwindows)
00873             gVirtualX->DrawRectangle(fId, GetLineGC()(), fX0, fY0, fXf-fX0,
00874                                      fYf-fY0);
00875       }
00876    }
00877 
00878    if (event->fType == kButtonRelease) {
00879       gVirtualX->SetInputFocus(fId);
00880 
00881       if (fDragging) {
00882          fDragging = kFALSE;
00883          fScrolling = kFALSE;
00884 
00885          if (gSystem) gSystem->RemoveTimer(fScrollTimer);
00886          //if (fMapSubwindows)
00887             gVirtualX->DrawRectangle(fId, GetLineGC()(), fX0, fY0, fXf-fX0,
00888                                      fYf-fY0);
00889       } else {
00890          SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
00891                      event->fCode, (event->fYRoot << 16) | event->fXRoot);
00892       }
00893    }
00894    fClient->NeedRedraw(this);
00895    return kTRUE;
00896 }
00897 
00898 //______________________________________________________________________________
00899 TList *TGLVContainer::GetSelectedItems()
00900 {
00901    // Get list of selected items in container.
00902 
00903    TGFrameElement *el;
00904    TIter next(fList);
00905    TList *ret = new TList();
00906 
00907    while ((el = (TGFrameElement *) next())) {
00908       if (el->fFrame->IsActive()) {
00909          ret->Add(new TObjString(((TGLVEntry*)el->fFrame)->GetItemName()->GetString()));
00910       }
00911    }
00912    return ret;
00913 }
00914 
00915 //______________________________________________________________________________
00916 void TGLVContainer::LineLeft(Bool_t select)
00917 {
00918    // Move current position one column left.
00919 
00920    // in details mode just move one line up
00921    if (fViewMode == kLVDetails) return LineUp(select);
00922 
00923    TGPosition pos = GetPagePosition();
00924    TGDimension dim = GetPageDimension();
00925 
00926    TGFrameElement *fe = (TGFrameElement*)fList->First();
00927    if (!fe) return; // empty list
00928 
00929    TGFrameElement *old = fLastActiveEl;
00930 
00931    if (fViewMode == kLVSmallIcons && fe == old) return;
00932 
00933    if (old) DeActivateItem(old);   //
00934    else fLastActiveEl = fe;
00935 
00936    TGDimension ms = fListView->GetMaxItemSize();
00937    Int_t dx = ms.fWidth;
00938    Int_t dy = ms.fHeight;
00939 
00940    Int_t y = fLastActiveEl->fFrame->GetY();
00941    Int_t x = fLastActiveEl->fFrame->GetX() - dx + 2;
00942 
00943    Int_t hw = pos.fX + dim.fWidth;
00944 
00945    TGHScrollBar *hb = GetHScrollbar();
00946    if (hb && hb->IsMapped()) {
00947       Int_t pg = (hb->GetPageSize()*GetWidth())/fViewPort->GetWidth();
00948       hw += pg;
00949    }
00950    if (x <= 0) { // move one line up
00951       x = hw;
00952       y = y - dy;
00953    }
00954 
00955    fe = FindFrame(x, y);
00956    if (fe && fe->fFrame->GetY() > fLastActiveEl->fFrame->GetY()) {
00957       // cannot go down with the left key
00958       x = hw;
00959       y = y - dy;
00960       fe = FindFrame(x, y);
00961    }
00962    if (fViewMode == kLVList) {
00963       if (fe && fe->fFrame->GetY() <= fLastActiveEl->fFrame->GetY() - (2 * dy)) {
00964          // avoid jumping more than one line up
00965          x = fe->fFrame->GetX() - dx;
00966          fe = FindFrame(x, y);
00967       }
00968       // cannot go down and/or right with the left key
00969       if (fe && fe->fFrame->GetY() >= fLastActiveEl->fFrame->GetY() &&
00970           fe->fFrame->GetX() >= fLastActiveEl->fFrame->GetX())
00971          fe = fLastActiveEl;
00972    }
00973    if (!fe || fe->fFrame->GetY() > fLastActiveEl->fFrame->GetY())
00974       fe = (TGFrameElement*)fList->First();
00975    if (!select) fSelected=1;
00976 
00977    ActivateItem(fe);
00978    AdjustPosition();
00979 }
00980 
00981 //______________________________________________________________________________
00982 void TGLVContainer::LineRight(Bool_t select)
00983 {
00984    // Move current position one column right.
00985 
00986    // in details mode just move one line down
00987    if (fViewMode == kLVDetails) return LineDown(select);
00988 
00989    TGPosition pos = GetPagePosition();
00990    TGDimension dim = GetPageDimension();
00991 
00992    TGFrameElement *fe = (TGFrameElement*)fList->Last();
00993    if (!fe) return;
00994 
00995    TGFrameElement *old = fLastActiveEl;
00996 
00997    if (fViewMode == kLVSmallIcons && fe == old) return;
00998 
00999    if (old) DeActivateItem(old);
01000    else fLastActiveEl = (TGFrameElement*)fList->First();
01001 
01002    TGDimension ms = fListView->GetMaxItemSize();
01003    Int_t dx = ms.fWidth;
01004    Int_t dy = ms.fHeight;
01005 
01006    Int_t y = fLastActiveEl->fFrame->GetY();
01007    Int_t x = fLastActiveEl->fFrame->GetX() + dx - 2;
01008 
01009    Int_t hw = pos.fX + dim.fWidth - dx;
01010 
01011    TGHScrollBar *hb =  GetHScrollbar();
01012    if (x > hw && (hb && !hb->IsMapped())) { // move one line down
01013       x = 0;
01014       y = y + dy;
01015    }
01016 
01017    fe = FindFrame(x, y);
01018    if (fe && fe->fFrame->GetY() < fLastActiveEl->fFrame->GetY()) {
01019       // cannot go up with the right key
01020       x = 0;
01021       y = y + dy;
01022       fe = FindFrame(x, y);
01023    }
01024    if (fViewMode == kLVList) {
01025       // cannot go up and/or left with the right key
01026       if (fe && fe->fFrame->GetY() <= fLastActiveEl->fFrame->GetY() &&
01027           fe->fFrame->GetX() <= fLastActiveEl->fFrame->GetX())
01028          fe = fLastActiveEl;
01029    }
01030    if (!fe || fe->fFrame->GetY() < fLastActiveEl->fFrame->GetY())
01031       fe = (TGFrameElement*)fList->Last();
01032    if (!select) fSelected = 1;
01033 
01034    ActivateItem(fe);
01035    AdjustPosition();
01036 }
01037 
01038 //______________________________________________________________________________
01039 void TGLVContainer::LineUp(Bool_t select)
01040 {
01041    // Make current position first line in window by scrolling up.
01042 
01043    TGFrameElement *fe = (TGFrameElement*)fList->First();
01044    if (!fe) return;
01045 
01046    TGFrameElement *old = fLastActiveEl;
01047 
01048    if (old) {
01049       DeActivateItem(old);
01050    } else {
01051       fLastActiveEl = (TGFrameElement*)fList->First();
01052    }
01053 
01054    TGDimension ms = fListView->GetMaxItemSize();
01055    Int_t dy = ms.fHeight;
01056 
01057    Int_t y = fLastActiveEl->fFrame->GetY() - dy;
01058    Int_t x = fLastActiveEl->fFrame->GetX();
01059 
01060    fe = FindFrame(x, y);
01061    if (!fe) fe = (TGFrameElement*)fList->First();
01062    if (fe->fFrame->GetY() > fLastActiveEl->fFrame->GetY()) fe = fLastActiveEl;
01063    if (!select) fSelected = 1;
01064 
01065    ActivateItem(fe);
01066    AdjustPosition();
01067 }
01068 
01069 //______________________________________________________________________________
01070 void TGLVContainer::LineDown(Bool_t select)
01071 {
01072    // Move one line down.
01073 
01074    TGFrameElement *fe = (TGFrameElement*)fList->Last();
01075    if (!fe) return;
01076 
01077    TGFrameElement *old = fLastActiveEl;
01078 
01079    if (old) DeActivateItem(old);
01080    else fLastActiveEl = (TGFrameElement*)fList->First();
01081 
01082    TGDimension ms = fListView->GetMaxItemSize();
01083    Int_t dy = ms.fHeight;
01084 
01085    Int_t y = fLastActiveEl->fFrame->GetY() + dy;
01086    Int_t x = fLastActiveEl->fFrame->GetX();
01087 
01088    fe = FindFrame(x, y);
01089    if (!fe) fe = (TGFrameElement*)fList->Last();
01090    if (fe->fFrame->GetY() < fLastActiveEl->fFrame->GetY()) fe = fLastActiveEl;
01091    if (!select) fSelected = 1;
01092 
01093    ActivateItem(fe);
01094    AdjustPosition();
01095 }
01096 
01097 
01098 //______________________________________________________________________________
01099 TGDimension TGLVContainer::GetPageDimension() const
01100 {
01101    // Returns page dimension.
01102 
01103    TGDimension ret;
01104    if (!fViewPort) return ret;
01105 
01106    ret.fWidth = fViewPort->GetWidth();
01107    ret.fHeight = fViewPort->GetHeight();
01108    return ret;
01109 }
01110 
01111 //______________________________________________________________________________
01112 TGListView::TGListView(const TGWindow *p, UInt_t w, UInt_t h,
01113                        UInt_t options, ULong_t back) :
01114    TGCanvas(p, w, h, options, back)
01115 {
01116    // Create a list view widget.
01117 
01118    fViewMode    = kLVLargeIcons;
01119    fNColumns    = 0;
01120    fColumns     = 0;
01121    fJmode       = 0;
01122    fColHeader   = 0;
01123    fColNames    = 0;
01124    fSplitHeader = 0;
01125    fJustChanged = kFALSE;
01126    fMinColumnSize = 25;
01127    fFontStruct = GetDefaultFontStruct();
01128    fNormGC     = GetDefaultGC()();
01129    if (fHScrollbar)
01130       fHScrollbar->Connect("PositionChanged(Int_t)", "TGListView",
01131                            this, "ScrollHeader(Int_t)");
01132    fHeader = new TGHeaderFrame(fVport, 20, 20, kChildFrame | kFixedWidth);
01133 
01134    SetDefaultHeaders();
01135 }
01136 
01137 //______________________________________________________________________________
01138 TGListView::~TGListView()
01139 {
01140    // Delete a list view widget.
01141 
01142    if (fNColumns) {
01143       delete [] fColumns;
01144       delete [] fJmode;
01145       for (int i = 0; i < fNColumns; i++) {
01146          delete fColHeader[i];
01147          delete fSplitHeader[i];
01148       }
01149       delete [] fColHeader;
01150       delete [] fColNames;
01151       delete [] fSplitHeader;
01152       delete fHeader;
01153    }
01154 }
01155 
01156 //______________________________________________________________________________
01157 void TGListView::ScrollHeader(Int_t pos)
01158 {
01159    // Scroll header buttons with horizontal scrollbar
01160 
01161    Int_t  i, xl = - pos;
01162    if (fViewMode == kLVDetails) {
01163       for (i = 0; i < fNColumns-1; ++i) {
01164          fColHeader[i]->Move(xl, 0);
01165          xl += fColHeader[i]->GetWidth();
01166          fSplitHeader[i]->Move(xl,fSplitHeader[i]->GetHeight());
01167       }
01168       fColHeader[i]->Move(xl, 0);
01169       xl += fColHeader[i]->GetWidth();
01170       fSplitHeader[i]->Move(xl,fSplitHeader[i]->GetHeight());
01171    }
01172 }
01173 
01174 //______________________________________________________________________________
01175 void TGListView::SetHeaders(Int_t ncolumns)
01176 {
01177    // Set number of headers, i.e. columns that will be shown in detailed view.
01178    // This method must be followed by exactly ncolumns SetHeader() calls,
01179    // making sure that every header (i.e. idx) is set (for and example see
01180    // SetDefaultHeaders()).
01181 
01182    if (ncolumns <= 0) {
01183       Error("SetHeaders", "number of columns must be > 0");
01184       return;
01185    }
01186 
01187    if (fNColumns) {
01188       delete [] fColumns;
01189       delete [] fJmode;
01190       for (int i = 0; i < fNColumns; i++) {
01191          if (fColHeader[i]) fColHeader[i]->DestroyWindow();
01192          delete fColHeader[i];
01193          delete fSplitHeader[i];
01194       }
01195       delete [] fColHeader;
01196       delete [] fSplitHeader;
01197       delete [] fColNames;
01198    }
01199 
01200    fNColumns  = ncolumns+1;    // one extra for the blank filler header
01201    fColumns   = new int[fNColumns];
01202    fJmode     = new int[fNColumns];
01203    fColHeader = new TGTextButton* [fNColumns];
01204    fColNames  = new TString [fNColumns];
01205    fSplitHeader = new TGVFileSplitter* [fNColumns];
01206 
01207    for (int i = 0; i < fNColumns; i++) {
01208       fColHeader[i] = 0;
01209       fJmode[i] = kTextLeft;
01210       fSplitHeader[i] = new TGVFileSplitter(fHeader, 10);
01211       fSplitHeader[i]->Connect("LayoutListView()", "TGListView",
01212                                this, "Layout()");
01213       fSplitHeader[i]->Connect("LayoutHeader(TGFrame *)", "TGListView",
01214                                this, "LayoutHeader(TGFrame *)");
01215       fSplitHeader[i]->Connect("DoubleClicked(TGVFileSplitter*)", "TGListView",
01216                                this, "SetDefaultColumnWidth(TGVFileSplitter*)");
01217    }
01218 
01219    // create blank filler header
01220    fColNames[fNColumns-1] = "";
01221    fColHeader[fNColumns-1] = new TGTextButton(fHeader, new TGHotString(""), -1,
01222                                     fNormGC, fFontStruct, kRaisedFrame |
01223                                     kDoubleBorder | kFixedWidth);
01224    fColHeader[fNColumns-1]->Associate(this);
01225    fColHeader[fNColumns-1]->SetTextJustify(kTextCenterX | kTextCenterY);
01226    fColHeader[fNColumns-1]->SetState(kButtonDisabled);
01227    fColHeader[fNColumns-1]->SetState(kButtonDisabled);
01228    fJmode[fNColumns-1]   = kTextCenterX;
01229    fColumns[fNColumns-1] = 0;
01230    fSplitHeader[fNColumns-1]->SetFrame(fColHeader[fNColumns-1], kTRUE);
01231    fHeader->SetColumnsInfo(fNColumns, fColHeader, fSplitHeader);
01232    fJustChanged = kTRUE;
01233 }
01234 
01235 //______________________________________________________________________________
01236 void TGListView::SetHeader(const char *s, Int_t hmode, Int_t cmode, Int_t idx)
01237 {
01238    // Set header button idx [0-fNColumns>, hmode is the x text alignmode
01239    // (ETextJustification) for the header text and cmode is the x text
01240    // alignmode for the item text.
01241 
01242    if (idx < 0 || idx >= fNColumns-1) {
01243       Error("SetHeader", "header index must be [0 - %d>", fNColumns-1);
01244       return;
01245    }
01246    delete fColHeader[idx];
01247 
01248    fColNames[idx] = s;
01249    fColHeader[idx] = new TGTextButton(fHeader, new TGHotString(s), idx,
01250                                       fNormGC, fFontStruct, kRaisedFrame |
01251                                       kDoubleBorder | kFixedWidth);
01252    TString txt = s;
01253    txt.ToLower();
01254    if (txt.Contains("modified")) txt += " date";
01255    if (txt.Contains("attributes")) txt = "type";
01256    fColHeader[idx]->SetToolTipText(Form("Click to sort by %s", txt.Data()));
01257    fColHeader[idx]->Associate(this);
01258    fColHeader[idx]->SetTextJustify(hmode | kTextCenterY);
01259    fSplitHeader[idx]->SetFrame(fColHeader[idx], kTRUE);
01260 
01261    // fJmode and fColumns contain values for columns idx > 0. idx==0 is
01262    // the small icon with the object name
01263    if (idx > 0)
01264       fJmode[idx-1] = cmode;
01265 
01266    if (!fColHeader[0]) return;
01267    int xl = fColHeader[0]->GetDefaultWidth() + 10 + fSplitHeader[0]->GetDefaultWidth();
01268    for (int i = 1; i < fNColumns; i++) {
01269       fColumns[i-1] = xl;
01270       if (!fColHeader[i]) break;
01271       xl += fColHeader[i]->GetDefaultWidth() + fSplitHeader[i]->GetDefaultWidth();
01272    }
01273 }
01274 
01275 //______________________________________________________________________________
01276 const char *TGListView::GetHeader(Int_t idx) const
01277 {
01278    // Returns name of header idx. If illegal idx or header not set for idx
01279    // 0 is returned.
01280 
01281    if (idx >= 0 && idx < fNColumns-1 && fColHeader[idx])
01282       return (const char*) fColNames[idx];
01283    return 0;
01284 }
01285 
01286 //______________________________________________________________________________
01287 void TGListView::SetDefaultHeaders()
01288 {
01289    // Default headers are: Name, Attributes, Size, Owner, Group, Modified.
01290    // The default is good for file system items.
01291 
01292    SetHeaders(6);
01293    SetHeader("Name",       kTextLeft,    kTextLeft,    0);
01294    SetHeader("Attributes", kTextCenterX, kTextCenterX, 1);
01295    SetHeader("Size",       kTextRight,   kTextRight,   2);
01296    SetHeader("Owner",      kTextCenterX, kTextCenterX, 3);
01297    SetHeader("Group",      kTextCenterX, kTextCenterX, 4);
01298    SetHeader("Modified",   kTextCenterX, kTextCenterX, 5);
01299 }
01300 
01301 //______________________________________________________________________________
01302 void TGListView::SetViewMode(EListViewMode viewMode)
01303 {
01304    // Set list view mode.
01305 
01306    TGLVContainer *container;
01307 
01308    if (fViewMode != viewMode) {
01309       fJustChanged = kTRUE;
01310       fViewMode = viewMode;
01311       container = (TGLVContainer *) fVport->GetContainer();
01312       if (container) container->SetViewMode(viewMode);
01313       Layout();
01314    }
01315 }
01316 
01317 //______________________________________________________________________________
01318 void TGListView::SetContainer(TGFrame *f)
01319 {
01320    // Set list view container. Container must be at least of type
01321    // TGLVContainer.
01322 
01323    if (f->InheritsFrom(TGLVContainer::Class())) {
01324       TGCanvas::SetContainer(f);
01325       ((TGLVContainer *) f)->SetColumns(fColumns, fJmode);
01326       ((TGLVContainer *) f)->SetListView(this);
01327    } else
01328       Error("SetContainer", "frame must inherit from TGLVContainer");
01329 }
01330 
01331 //______________________________________________________________________________
01332 void TGListView::SetIncrements(Int_t hInc, Int_t vInc)
01333 {
01334    // Set horizontal and vertical scrollbar increments.
01335 
01336    fHScrollbar->SetSmallIncrement(hInc);
01337    fVScrollbar->SetSmallIncrement(vInc);
01338 }
01339 
01340 //______________________________________________________________________________
01341 void TGListView::SetDefaultColumnWidth(TGVFileSplitter* splitter)
01342 {
01343    // Set default column width of the columns headers.
01344 
01345    TGLVContainer *container = (TGLVContainer *) fVport->GetContainer();
01346 
01347    if (!container) {
01348       Error("SetDefaultColumnWidth", "no listview container set yet");
01349       return;
01350    }
01351    container->ClearViewPort();
01352 
01353    for (int i = 0; i < fNColumns; ++i) {
01354       if ( fSplitHeader[i] == splitter ) {
01355          TString dt = fColHeader[i]->GetString();
01356          UInt_t bsize = gVirtualX->TextWidth(fColHeader[i]->GetFontStruct(),
01357                                              dt.Data(), dt.Length());
01358          UInt_t w = TMath::Max(fColHeader[i]->GetDefaultWidth(), bsize + 20);
01359          if (i == 0) w = TMath::Max(fMaxSize.fWidth + 10, w);
01360          if (i > 0)  w = TMath::Max(container->GetMaxSubnameWidth(i) + 40, (Int_t)w);
01361          fColHeader[i]->Resize(w, fColHeader[i]->GetHeight());
01362          Layout();
01363       }
01364    }
01365 }
01366 
01367 //______________________________________________________________________________
01368 void TGListView::ResizeColumns()
01369 {
01370    // Resize column headers to show whole item names.
01371 
01372    for (int i = 0; i < fNColumns; ++i) {
01373       TGLVContainer *container = (TGLVContainer *) fVport->GetContainer();
01374       if (!container) {
01375          Error("ResizeColumns", "no listview container set yet");
01376          return;
01377       }
01378       fMaxSize = container->GetMaxItemSize();
01379       SetDefaultColumnWidth(fSplitHeader[i]);
01380    }
01381 }
01382 
01383 //______________________________________________________________________________
01384 void TGListView::Layout()
01385 {
01386    // Layout list view components (container and contents of container).
01387 
01388    Int_t  i, xl = 0;
01389    UInt_t w, h = 0;
01390 
01391    TGLVContainer *container = (TGLVContainer *) fVport->GetContainer();
01392 
01393    if (!container) {
01394       Error("Layout", "no listview container set yet");
01395       return;
01396    }
01397 
01398    fMaxSize = container->GetMaxItemSize();
01399 
01400    if (fViewMode == kLVDetails) {
01401       h = fColHeader[0]->GetDefaultHeight()-4;
01402       fHeader->MoveResize(0, 0, fWidth, h);
01403       fHeader->MapWindow();
01404       for (i = 0; i < fNColumns-1; ++i) {
01405          fColHeader[i]->SetText(fColNames[i]);
01406 
01407          if ( fJustChanged ) {
01408             w = TMath::Min(fMaxSize.fWidth + 10, fColHeader[i]->GetDefaultWidth());
01409             if (w < fMinColumnSize) w = fColHeader[i]->GetDefaultWidth();
01410             if (i == 0) w = TMath::Max(fMaxSize.fWidth + 10, w);
01411             if (i > 0)  w = TMath::Max(container->GetMaxSubnameWidth(i) + 40, (Int_t)w);
01412          } else {
01413             w = fColHeader[i]->GetWidth();
01414          }
01415          w = TMath::Max(fMinColumnSize, w);
01416          if ( fColHeader[i]->GetDefaultWidth() > w ) {
01417             for (int j = fColNames[i].Length() - 1 ; j > 0; j--) {
01418                fColHeader[i]->SetText( fColNames[i](0,j) + "..." );
01419                if ( fColHeader[i]->GetDefaultWidth() < w )
01420                   break;
01421             }
01422          }
01423 
01424          fColHeader[i]->MoveResize(xl, 0, w, h);
01425          fColHeader[i]->MapWindow();
01426          xl += w;
01427          fSplitHeader[i]->Move(xl, 0);
01428          fSplitHeader[i]->MapWindow();
01429          fColumns[i] = xl-2;  // -2 is fSep in the layout routine
01430       }
01431       fColHeader[i]->MoveResize(xl, 0, fVport->GetWidth()-xl, h);
01432       fColHeader[i]->MapWindow();
01433       fSplitHeader[i]->Move(fVport->GetWidth(), fSplitHeader[i]->GetHeight());
01434       fSplitHeader[i]->MapWindow();
01435       fVScrollbar->RaiseWindow();
01436 
01437       container->SetColumns(fColumns, fJmode);
01438 
01439    } else {
01440       for (i = 0; i < fNColumns; ++i) {
01441          fColHeader[i]->UnmapWindow();
01442          fSplitHeader[i]->UnmapWindow();
01443       }
01444       fHeader->UnmapWindow();
01445    }
01446    TGLayoutManager *lm = container->GetLayoutManager();
01447 
01448    lm->SetDefaultWidth(xl);
01449    TGCanvas::Layout();
01450 
01451    if (fViewMode == kLVDetails) {
01452       container->Resize(container->GetWidth(), container->GetHeight()+h);
01453       fVScrollbar->SetRange((Int_t)container->GetHeight(),
01454                             (Int_t)fVport->GetHeight());
01455       if (fJustChanged) {
01456          fVport->MoveResize(fBorderWidth, fBorderWidth, fVport->GetWidth(),
01457                             fVport->GetHeight());
01458          container->Move(0, h);
01459       } else {
01460          container->DrawRegion(0, 0, fVport->GetWidth(), fVport->GetHeight());
01461       }
01462       fColHeader[i]->MoveResize(xl, 0, fVport->GetWidth()-xl, h);
01463       fColHeader[i]->MapWindow();
01464    } else {
01465       fVport->MoveResize(fBorderWidth, fBorderWidth, fVport->GetWidth(),
01466                          fVport->GetHeight());
01467       container->Move(0, 0);
01468    }
01469 
01470    fJustChanged = kFALSE;
01471 }
01472 
01473 //______________________________________________________________________________
01474 void TGListView::LayoutHeader(TGFrame *head)
01475 {
01476    // Layout list view components (container and contents of container).
01477 
01478    Int_t  i, xl = 0;
01479    UInt_t w, h = 0;
01480    static Int_t oldPos = 0;
01481    if (head == 0) oldPos = 0;
01482 
01483    TGLVContainer *container = (TGLVContainer *) fVport->GetContainer();
01484 
01485    if (!container) {
01486       Error("Layout", "no listview container set yet");
01487       return;
01488    }
01489    fMaxSize = container->GetMaxItemSize();
01490    Int_t posx = container->GetPagePosition().fX;
01491 
01492    if (fViewMode == kLVDetails) {
01493       h = fColHeader[0]->GetDefaultHeight()-4;
01494       fHeader->MoveResize(0, 0, fWidth, h);
01495       fHeader->MapWindow();
01496       for (i = 0; i < fNColumns-1; ++i) {
01497          fColHeader[i]->SetText(fColNames[i]);
01498 
01499          if ( fJustChanged ) {
01500             w = TMath::Min(fMaxSize.fWidth + 10, fColHeader[i]->GetDefaultWidth());
01501             if (w < fMinColumnSize) w = fColHeader[i]->GetDefaultWidth();
01502             if (i == 0) w = TMath::Max(fMaxSize.fWidth + 10, w);
01503             if (i > 0)  w = TMath::Max(container->GetMaxSubnameWidth(i) + 40, (Int_t)w);
01504          } else {
01505             w = fColHeader[i]->GetWidth();
01506          }
01507          w = TMath::Max(fMinColumnSize, w);
01508          if ( fColHeader[i]->GetDefaultWidth() > w ) {
01509             for (int j = fColNames[i].Length() - 1 ; j > 0; j--) {
01510                fColHeader[i]->SetText( fColNames[i](0,j) + "..." );
01511                if ( fColHeader[i]->GetDefaultWidth() < w )
01512                   break;
01513             }
01514          }
01515 
01516          if ((TGFrame *)fColHeader[i] == head) {
01517             if (oldPos > 0) {
01518                gVirtualX->DrawLine(container->GetId(), container->GetLineGC()(),
01519                                    oldPos - posx, 0, oldPos - posx, fVport->GetHeight());
01520             }
01521             gVirtualX->DrawLine(container->GetId(), container->GetLineGC()(),
01522                                 xl + w - posx, 0, xl + w - posx, fVport->GetHeight());
01523             oldPos = xl + w;
01524          }
01525 
01526          fColHeader[i]->MoveResize(xl - posx, 0, w, h);
01527          fColHeader[i]->MapWindow();
01528          xl += w;
01529          fSplitHeader[i]->Move(xl, 0);
01530          fSplitHeader[i]->MapWindow();
01531          fColumns[i] = xl-2;  // -2 is fSep in the layout routine
01532       }
01533       fColHeader[i]->MoveResize(xl - posx, 0, fVport->GetWidth()-xl, h);
01534       fColHeader[i]->MapWindow();
01535       fSplitHeader[i]->Move(fVport->GetWidth(),  fSplitHeader[i]->GetHeight());
01536       fSplitHeader[i]->MapWindow();
01537       fVScrollbar->RaiseWindow();
01538    }
01539    fJustChanged = kFALSE;
01540 }
01541 
01542 //______________________________________________________________________________
01543 Bool_t TGListView::ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2)
01544 {
01545    // Handle messages generated by the list view components.
01546 
01547    TGLVContainer *cnt = (TGLVContainer*)GetContainer();
01548 
01549    const TGLVEntry *entry;
01550    void *p = 0;
01551 
01552    entry = (TGLVEntry *) cnt->GetNextSelected(&p);
01553 
01554    switch (GET_SUBMSG(msg)) {
01555       case kCT_ITEMCLICK:
01556          if ((cnt->NumSelected() == 1) && (entry != 0)) {
01557             Int_t x = (Int_t)(parm2 & 0xffff);
01558             Int_t y = (Int_t)((parm2 >> 16) & 0xffff);
01559             Clicked((TGLVEntry*)entry, (Int_t)parm1);
01560             Clicked((TGLVEntry*)entry, (Int_t)parm1, x, y);
01561          }
01562          break;
01563       case kCT_ITEMDBLCLICK:
01564          if ((cnt->NumSelected() == 1) && (entry!=0)) {
01565             Int_t x = (Int_t)(parm2 & 0xffff);
01566             Int_t y = (Int_t)((parm2 >> 16) & 0xffff);
01567             DoubleClicked((TGLVEntry*)entry, (Int_t)parm1);
01568             DoubleClicked((TGLVEntry*)entry, (Int_t)parm1, x, y);
01569          }
01570          break;
01571       case kCT_SELCHANGED:
01572          SelectionChanged();
01573          break;
01574       default:
01575          break;
01576    }
01577    return TGCanvas::ProcessMessage(msg, parm1, parm2);
01578 }
01579 
01580 //______________________________________________________________________________
01581 void TGListView::Clicked(TGLVEntry *entry, Int_t btn)
01582 {
01583    // Emit Clicked() signal.
01584 
01585    Long_t args[2];
01586 
01587    args[0] = (Long_t)entry;
01588    args[1] = btn;
01589 
01590    Emit("Clicked(TGLVEntry*,Int_t)", args);
01591 }
01592 
01593 //______________________________________________________________________________
01594 void TGListView::Clicked(TGLVEntry *entry, Int_t btn, Int_t x, Int_t y)
01595 {
01596    // Emit Clicked() signal.
01597 
01598    Long_t args[4];
01599 
01600    args[0] = (Long_t)entry;
01601    args[1] = btn;
01602    args[2] = x;
01603    args[3] = y;
01604 
01605    Emit("Clicked(TGLVEntry*,Int_t,Int_t,Int_t)", args);
01606 }
01607 
01608 //______________________________________________________________________________
01609 void TGListView::DoubleClicked(TGLVEntry *entry, Int_t btn)
01610 {
01611    // Emit DoubleClicked() signal.
01612 
01613    Long_t args[2];
01614 
01615    args[0] = (Long_t)entry;
01616    args[1] = btn;
01617 
01618    Emit("DoubleClicked(TGLVEntry*,Int_t)", args);
01619 }
01620 
01621 //______________________________________________________________________________
01622 void TGListView::DoubleClicked(TGLVEntry *entry, Int_t btn, Int_t x, Int_t y)
01623 {
01624    // Emit DoubleClicked() signal.
01625 
01626    Long_t args[4];
01627 
01628    args[0] = (Long_t)entry;
01629    args[1] = btn;
01630    args[2] = x;
01631    args[3] = y;
01632 
01633    Emit("DoubleClicked(TGLVEntry*,Int_t,Int_t,Int_t)", args);
01634 }
01635 
01636 //______________________________________________________________________________
01637 FontStruct_t TGListView::GetDefaultFontStruct()
01638 {
01639    // Return the default font structure in use.
01640 
01641    if (!fgDefaultFont)
01642       fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
01643    return fgDefaultFont->GetFontStruct();
01644 }
01645 
01646 //______________________________________________________________________________
01647 const TGGC &TGListView::GetDefaultGC()
01648 {
01649    // Return the default graphics context in use.
01650 
01651    if (!fgDefaultGC) {
01652       fgDefaultGC = new TGGC(*gClient->GetResourcePool()->GetFrameGC());
01653       fgDefaultGC->SetFont(fgDefaultFont->GetFontHandle());
01654    }
01655    return *fgDefaultGC;
01656 }
01657 
01658 //______________________________________________________________________________
01659 void TGListView::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
01660 {
01661    // Save a list view widget as a C++ statement(s) on output stream out.
01662 
01663    if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
01664 
01665    out << endl << "   // list view" << endl;
01666    out <<"   TGListView *";
01667    out << GetName() << " = new TGListView(" << fParent->GetName()
01668        << "," << GetWidth() << "," << GetHeight();
01669 
01670    if (fBackground == GetDefaultFrameBackground()) {
01671       if (GetOptions() == (kSunkenFrame | kDoubleBorder)) {
01672          out <<");" << endl;
01673       } else {
01674          out << "," << GetOptionString() <<");" << endl;
01675       }
01676    } else {
01677       out << "," << GetOptionString() << ",ucolor);" << endl;
01678    }
01679    if (option && strstr(option, "keep_names"))
01680       out << "   " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
01681 
01682    GetContainer()->SavePrimitive(out, option);
01683 
01684    out << endl;
01685    out << "   " << GetName() << "->SetContainer(" << GetContainer()->GetName()
01686                 << ");" << endl;
01687    out << "   " << GetName() << "->SetViewMode(";
01688    switch (fViewMode) {
01689       case kLVLargeIcons:
01690          out << "kLVLargeIcons";
01691          break;
01692       case kLVSmallIcons:
01693          out << "kLVSmallIcons";
01694          break;
01695       case kLVList:
01696          out << "kLVList";
01697          break;
01698       case kLVDetails:
01699          out << "kLVDetails";
01700          break;
01701    }
01702    out << ");" << endl;
01703 
01704    out << "   " << GetContainer()->GetName() << "->Resize();" << endl;
01705 
01706    if (fHScrollbar && fHScrollbar->IsMapped()) {
01707    out << "   " << GetName() << "->SetHsbPosition(" << GetHsbPosition()
01708        << ");" << endl;
01709    }
01710 
01711    if (fVScrollbar && fVScrollbar->IsMapped()) {
01712    out << "   " << GetName() << "->SetVsbPosition(" << GetVsbPosition()
01713        << ");" << endl;
01714    }
01715 }
01716 
01717 //______________________________________________________________________________
01718 void TGLVContainer::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
01719 {
01720    // Save a list view container as a C++ statement(s) on output stream out.
01721 
01722    if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
01723 
01724    out << endl << "   // list view container" << endl;
01725    out << "   TGLVContainer *";
01726 
01727    if ((fParent->GetParent())->InheritsFrom(TGCanvas::Class())) {
01728       out << GetName() << " = new TGLVContainer(" << GetCanvas()->GetName();
01729    } else {
01730       out << GetName() << " = new TGLVContainer(" << fParent->GetName();
01731       out << "," << GetWidth() << "," << GetHeight();
01732    }
01733    if (fBackground == GetDefaultFrameBackground()) {
01734       if (GetOptions() == (kSunkenFrame | kDoubleBorder)) {
01735          out <<");" << endl;
01736       } else {
01737          out << "," << GetOptionString() <<");" << endl;
01738       }
01739    } else {
01740       out << "," << GetOptionString() << ",ucolor);" << endl;
01741    }
01742    if (option && strstr(option, "keep_names"))
01743       out << "   " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
01744 }

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