TGListTree.cxx

Go to the documentation of this file.
00001 // @(#)root/gui:$Id: TGListTree.cxx 37379 2010-12-07 18:37:12Z bellenot $
00002 // Author: Fons Rademakers   25/02/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 // TGListTree and TGListTreeItem                                        //
00026 //                                                                      //
00027 // A list tree is a widget that can contain a number of items           //
00028 // arranged in a tree structure. The items are represented by small     //
00029 // folder icons that can be either open or closed.                      //
00030 //                                                                      //
00031 // The TGListTree is user callable. The TGListTreeItem is a service     //
00032 // class of the list tree.                                              //
00033 //                                                                      //
00034 // A list tree can generate the following events:                       //
00035 // kC_LISTTREE, kCT_ITEMCLICK, which button, location (y<<16|x).        //
00036 // kC_LISTTREE, kCT_ITEMDBLCLICK, which button, location (y<<16|x).     //
00037 //                                                                      //
00038 //////////////////////////////////////////////////////////////////////////
00039 
00040 #include <stdlib.h>
00041 
00042 #include "TROOT.h"
00043 #include "TGListTree.h"
00044 #include "TGPicture.h"
00045 #include "TGCanvas.h"
00046 #include "TGScrollBar.h"
00047 #include "TGToolTip.h"
00048 #include "KeySymbols.h"
00049 #include "TGTextEditDialogs.h"
00050 #include "TGResourcePool.h"
00051 #include "TGMsgBox.h"
00052 #include "TError.h"
00053 #include "TColor.h"
00054 #include "TSystem.h"
00055 #include "TString.h"
00056 #include "TObjString.h"
00057 #include "TGDNDManager.h"
00058 #include "TBufferFile.h"
00059 #include "Riostream.h"
00060 
00061 Pixel_t          TGListTree::fgGrayPixel = 0;
00062 const TGFont    *TGListTree::fgDefaultFont = 0;
00063 TGGC            *TGListTree::fgDrawGC = 0;
00064 TGGC            *TGListTree::fgLineGC = 0;
00065 TGGC            *TGListTree::fgHighlightGC = 0;
00066 TGGC            *TGListTree::fgColorGC = 0;
00067 const TGPicture *TGListTree::fgOpenPic = 0;
00068 const TGPicture *TGListTree::fgClosedPic = 0;
00069 const TGPicture *TGListTree::fgCheckedPic = 0;
00070 const TGPicture *TGListTree::fgUncheckedPic = 0;
00071 
00072 
00073 ClassImp(TGListTreeItem)
00074 ClassImp(TGListTreeItemStd)
00075 ClassImp(TGListTree)
00076 
00077 /******************************************************************************/
00078 /******************************************************************************/
00079 // TGListTreeItem
00080 /******************************************************************************/
00081 
00082 //______________________________________________________________________________
00083 TGListTreeItem::TGListTreeItem(TGClient *client) :
00084    fClient(client),
00085    fParent    (0), fFirstchild(0), fLastchild (0), fPrevsibling(0), 
00086    fNextsibling(0),fOpen (kFALSE), fDNDState  (0),
00087    fY         (0), fXtext     (0), fYtext(0), fHeight(0)
00088 {
00089    // Constructor.
00090 }
00091 
00092 //______________________________________________________________________________
00093 UInt_t TGListTreeItem::GetPicWidth() const
00094 {
00095    // Return width of item's icon.
00096 
00097    return GetPicture()->GetWidth();
00098 }
00099 
00100 /******************************************************************************/
00101 /******************************************************************************/
00102 // TGListTreeItemStd
00103 /******************************************************************************/
00104 
00105 //______________________________________________________________________________
00106 TGListTreeItemStd::TGListTreeItemStd(TGClient *client, const char *name,
00107                                      const TGPicture *opened,
00108                                      const TGPicture *closed,
00109                                      Bool_t checkbox) :
00110    TGListTreeItem(client)
00111 {
00112    // Create list tree item.
00113 
00114    fText = name;
00115    fCheckBox = checkbox;
00116    fChecked = kTRUE;
00117 
00118    if (!opened)
00119       opened = TGListTree::GetOpenPic();
00120    else
00121       ((TGPicture *)opened)->AddReference();
00122 
00123    if (!closed)
00124       closed = TGListTree::GetClosedPic();
00125    else
00126       ((TGPicture *)closed)->AddReference();
00127 
00128    fOpenPic   = opened;
00129    fClosedPic = closed;
00130 
00131    fCheckedPic   = TGListTree::GetCheckedPic();
00132    fUncheckedPic = TGListTree::GetUncheckedPic();
00133 
00134    fActive = kFALSE;
00135 
00136    fOwnsData = kFALSE;
00137    fUserData = 0;
00138 
00139    fHasColor = kFALSE;
00140    fColor = 0;
00141    fDNDState = 0;
00142 }
00143 
00144 //______________________________________________________________________________
00145 TGListTreeItemStd::~TGListTreeItemStd()
00146 {
00147    // Delete list tree item.
00148 
00149    if (fOwnsData && fUserData) {
00150       TObject *obj = static_cast<TObject *>(fUserData);
00151       delete dynamic_cast<TObject *>(obj);
00152    }
00153    fClient->FreePicture(fOpenPic);
00154    fClient->FreePicture(fClosedPic);
00155    fClient->FreePicture(fCheckedPic);
00156    fClient->FreePicture(fUncheckedPic);
00157 }
00158 
00159 //______________________________________________________________________________
00160 Pixel_t TGListTreeItemStd::GetActiveColor() const
00161 {
00162    // Return color for marking items that are active or selected.
00163 
00164    return TGFrame::GetDefaultSelectedBackground();
00165 }
00166 
00167 //______________________________________________________________________________
00168 Bool_t TGListTreeItemStd::HasCheckedChild(Bool_t first)
00169 {
00170    // Add all child items of 'item' into the list 'checked'.
00171 
00172    TGListTreeItem *item = this;
00173 
00174    while (item) {
00175       if (item->IsChecked()) {
00176          return kTRUE;
00177       }
00178       if (item->GetFirstChild()) {
00179          if (item->GetFirstChild()->HasCheckedChild())
00180             return kTRUE;
00181       }
00182       if (!first)
00183          item = item->GetNextSibling();
00184       else
00185          break;
00186    }
00187    return kFALSE;
00188 }
00189 
00190 //______________________________________________________________________________
00191 Bool_t TGListTreeItemStd::HasUnCheckedChild(Bool_t first)
00192 {
00193    // Add all child items of 'item' into the list 'checked'.
00194 
00195    TGListTreeItem *item = this;
00196 
00197    while (item) {
00198       if (!item->IsChecked()) {
00199          return kTRUE;
00200       }
00201       if (item->GetFirstChild()) {
00202          if (item->GetFirstChild()->HasUnCheckedChild())
00203             return kTRUE;
00204       }
00205       if (!first)
00206          item = item->GetNextSibling();
00207       else
00208          break;
00209    }
00210    return kFALSE;
00211 }
00212 
00213 //______________________________________________________________________________
00214 void TGListTreeItemStd::UpdateState()
00215 {
00216    // Update the state of the node 'item' according to the children states.
00217 
00218    if ((!fChecked && HasCheckedChild(kTRUE)) ||
00219        (fChecked && HasUnCheckedChild(kTRUE))) {
00220       SetCheckBoxPictures(gClient->GetPicture("checked_dis_t.xpm"),
00221                           gClient->GetPicture("unchecked_dis_t.xpm"));
00222    }
00223    else {
00224       SetCheckBoxPictures(gClient->GetPicture("checked_t.xpm"),
00225                           gClient->GetPicture("unchecked_t.xpm"));
00226    }
00227 }
00228 
00229 //______________________________________________________________________________
00230 void TGListTreeItemStd::CheckAllChildren(Bool_t state)
00231 {
00232    // Set all child items of this one checked if state=kTRUE,
00233    // unchecked if state=kFALSE.
00234    
00235    if (state) {
00236       if (!IsChecked())
00237          CheckItem();
00238    } else {
00239       if (IsChecked())
00240          Toggle();
00241    }
00242    CheckChildren(GetFirstChild(), state);
00243    UpdateState();   
00244 }
00245 
00246 //______________________________________________________________________________
00247 void TGListTreeItemStd::CheckChildren(TGListTreeItem *item, Bool_t state)
00248 {
00249    // Set all child items of 'item' checked if state=kTRUE;
00250    // unchecked if state=kFALSE.
00251 
00252    if (!item) return;
00253 
00254    while (item) {
00255       if (state){
00256          if (!item->IsChecked())
00257             item->CheckItem();
00258       } else {
00259          if (item->IsChecked())
00260             item->Toggle();
00261       }
00262       if (item->GetFirstChild()) {
00263          CheckChildren(item->GetFirstChild(), state);
00264       }
00265       item->UpdateState();   
00266       item = item->GetNextSibling();
00267    }
00268 }
00269 
00270 //______________________________________________________________________________
00271 void TGListTreeItemStd::SetCheckBox(Bool_t on)
00272 {
00273    // Set a check box on the tree node.
00274 
00275    fCheckBox = on;
00276 }
00277 
00278 //___________________________________________________________________________
00279 void TGListTreeItemStd::SetCheckBoxPictures(const TGPicture *checked,
00280                                          const TGPicture *unchecked)
00281 {
00282    // Change list tree check item icons.
00283 
00284    fClient->FreePicture(fCheckedPic);
00285    fClient->FreePicture(fUncheckedPic);
00286 
00287    if (!checked) {
00288          ::Warning("TGListTreeItem::SetCheckBoxPictures", "checked picture not specified, defaulting to checked_t");
00289          checked = fClient->GetPicture("checked_t.xpm");
00290    } else
00291       ((TGPicture *)checked)->AddReference();
00292 
00293    if (!unchecked) {
00294          ::Warning("TGListTreeItem::SetCheckBoxPictures", "unchecked picture not specified, defaulting to unchecked_t");
00295          unchecked = fClient->GetPicture("unchecked_t.xpm");
00296    } else
00297       ((TGPicture *)unchecked)->AddReference();
00298 
00299    fCheckedPic   = checked;
00300    fUncheckedPic = unchecked;
00301 }
00302 
00303 //___________________________________________________________________________
00304 void TGListTreeItemStd::SetPictures(const TGPicture *opened, const TGPicture *closed)
00305 {
00306    // Change list tree item icons.
00307 
00308    fClient->FreePicture(fOpenPic);
00309    fClient->FreePicture(fClosedPic);
00310 
00311    if (!opened) {
00312       ::Warning("TGListTreeItem::SetPictures", "opened picture not specified, defaulting to ofolder_t");
00313       opened = fClient->GetPicture("ofolder_t.xpm");
00314    } else
00315       ((TGPicture *)opened)->AddReference();
00316 
00317    if (!closed) {
00318       ::Warning("TGListTreeItem::SetPictures", "closed picture not specified, defaulting to folder_t");
00319       closed = fClient->GetPicture("folder_t.xpm");
00320    } else
00321       ((TGPicture *)closed)->AddReference();
00322 
00323    fOpenPic   = opened;
00324    fClosedPic = closed;
00325 }
00326 
00327 
00328 /******************************************************************************/
00329 /******************************************************************************/
00330 // TGListTree
00331 /******************************************************************************/
00332 
00333 //______________________________________________________________________________
00334 TGListTree::TGListTree(TGWindow *p, UInt_t w, UInt_t h, UInt_t options,
00335                        ULong_t back) :
00336    TGContainer(p, w, h, options, back)
00337 {
00338    // Create a list tree widget.
00339 
00340    fMsgWindow   = p;
00341    fCanvas      = 0;
00342    fTip         = 0;
00343    fTipItem     = 0;
00344    fAutoTips    = kFALSE;
00345    fAutoCheckBoxPic = kTRUE;
00346    fDisableOpen = kFALSE;
00347    fBdown       = kFALSE;
00348    fUserControlled = kFALSE;
00349    fEventHandled   = kFALSE;
00350 
00351    fGrayPixel   = GetGrayPixel();
00352    fFont        = GetDefaultFontStruct();
00353 
00354    fDrawGC      = GetDrawGC()();
00355    fLineGC      = GetLineGC()();
00356    fHighlightGC = GetHighlightGC()();
00357    fColorGC     = GetColorGC()();
00358 
00359    fFirst = fLast = fSelected = fCurrent = fBelowMouse = 0;
00360    fDefw = fDefh = 1;
00361 
00362    fHspacing = 2;
00363    fVspacing = 2;  // 0;
00364    fIndent   = 3;  // 0;
00365    fMargin   = 2;
00366 
00367    fXDND = fYDND = 0;
00368    fDNDData.fData = 0;
00369    fDNDData.fDataLength = 0;
00370    fDNDData.fDataType = 0;
00371    fBuf = 0;
00372 
00373    fColorMode = kDefault;
00374    fCheckMode = kSimple;
00375    if (fCanvas) fCanvas->GetVScrollbar()->SetSmallIncrement(20);
00376 
00377    gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
00378                          kButtonPressMask | kButtonReleaseMask,
00379                          kNone, kNone);
00380 
00381    AddInput(kPointerMotionMask | kEnterWindowMask |
00382             kLeaveWindowMask | kKeyPressMask);
00383    SetWindowName();
00384 
00385    fDNDTypeList = new Atom_t[3];
00386    fDNDTypeList[0] = gVirtualX->InternAtom("application/root", kFALSE);
00387    fDNDTypeList[1] = gVirtualX->InternAtom("text/uri-list", kFALSE);
00388    fDNDTypeList[2] = 0;
00389    gVirtualX->SetDNDAware(fId, fDNDTypeList);
00390    SetDNDTarget(kTRUE);
00391    fEditDisabled = kEditDisable | kEditDisableGrab | kEditDisableBtnEnable;
00392 }
00393 
00394 //______________________________________________________________________________
00395 TGListTree::TGListTree(TGCanvas *p,UInt_t options,ULong_t back) :
00396    TGContainer(p, options, back)
00397 {
00398    // Create a list tree widget.
00399 
00400    fMsgWindow   = p;
00401    fTip         = 0;
00402    fTipItem     = 0;
00403    fAutoTips    = kFALSE;
00404    fAutoCheckBoxPic = kTRUE;
00405    fDisableOpen = kFALSE;
00406    fBdown       = kFALSE;
00407    fUserControlled = kFALSE;
00408    fEventHandled   = kFALSE;
00409 
00410    fGrayPixel   = GetGrayPixel();
00411    fFont        = GetDefaultFontStruct();
00412 
00413    fDrawGC      = GetDrawGC()();
00414    fLineGC      = GetLineGC()();
00415    fHighlightGC = GetHighlightGC()();
00416    fColorGC     = GetColorGC()();
00417 
00418    fFirst = fLast = fSelected = fCurrent = fBelowMouse = 0;
00419    fDefw = fDefh = 1;
00420 
00421    fHspacing = 2;
00422    fVspacing = 2;  // 0;
00423    fIndent   = 3;  // 0;
00424    fMargin   = 2;
00425 
00426    fXDND = fYDND = 0;
00427    fDNDData.fData = 0;
00428    fDNDData.fDataLength = 0;
00429    fDNDData.fDataType = 0;
00430    fBuf = 0;
00431 
00432    fColorMode = kDefault;
00433    fCheckMode = kSimple;
00434    if (fCanvas) fCanvas->GetVScrollbar()->SetSmallIncrement(20);
00435 
00436    gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
00437                          kButtonPressMask | kButtonReleaseMask,
00438                          kNone, kNone);
00439 
00440    AddInput(kPointerMotionMask | kEnterWindowMask |
00441             kLeaveWindowMask | kKeyPressMask);
00442    SetWindowName();
00443 
00444    fDNDTypeList = new Atom_t[3];
00445    fDNDTypeList[0] = gVirtualX->InternAtom("application/root", kFALSE);
00446    fDNDTypeList[1] = gVirtualX->InternAtom("text/uri-list", kFALSE);
00447    fDNDTypeList[2] = 0;
00448    gVirtualX->SetDNDAware(fId, fDNDTypeList);
00449    SetDNDTarget(kTRUE);
00450    fEditDisabled = kEditDisable | kEditDisableGrab | kEditDisableBtnEnable;
00451 }
00452 
00453 //______________________________________________________________________________
00454 TGListTree::~TGListTree()
00455 {
00456    // Delete list tree widget.
00457 
00458    TGListTreeItem *item, *sibling;
00459 
00460    delete [] fDNDTypeList;
00461    delete fTip;
00462 
00463    item = fFirst;
00464    while (item) {
00465       PDeleteChildren(item);
00466       sibling = item->fNextsibling;
00467       delete item;
00468       item = sibling;
00469    }
00470 }
00471 
00472 //--- text utility functions
00473 
00474 //______________________________________________________________________________
00475 Int_t TGListTree::FontHeight()
00476 {
00477    // Returns height of currently used font.
00478 
00479    if (!fgDefaultFont)
00480       fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
00481    return fgDefaultFont->TextHeight();
00482 }
00483 
00484 //______________________________________________________________________________
00485 Int_t TGListTree::FontAscent()
00486 {
00487    // Returns ascent of currently used font.
00488 
00489    FontMetrics_t m;
00490    if (!fgDefaultFont)
00491       fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
00492    fgDefaultFont->GetFontMetrics(&m);
00493    return m.fAscent;
00494 }
00495 
00496 //______________________________________________________________________________
00497 Int_t TGListTree::TextWidth(const char *c)
00498 {
00499    // Returns text width relative to currently used font.
00500 
00501    if (!fgDefaultFont)
00502       fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
00503    return fgDefaultFont->TextWidth(c);
00504 }
00505 
00506 //---- highlighting utilities
00507 
00508 //______________________________________________________________________________
00509 void TGListTree::HighlightItem(TGListTreeItem *item, Bool_t state, Bool_t draw)
00510 {
00511    // Highlight tree item.
00512 
00513    if (item) {
00514       if ((item == fSelected) && !state) {
00515          fSelected = 0;
00516          if (draw) DrawItemName(fId, item);
00517       } else if (state != item->IsActive()) { // !!!! leave active alone ...
00518          item->SetActive(state);
00519          if (draw) DrawItemName(fId, item);
00520       }
00521    }
00522 }
00523 
00524 //______________________________________________________________________________
00525 void TGListTree::HighlightChildren(TGListTreeItem *item, Bool_t state, Bool_t draw)
00526 {
00527    // Higlight item children.
00528 
00529    while (item) {
00530       HighlightItem(item, state, draw);
00531       if (item->fFirstchild)
00532          HighlightChildren(item->fFirstchild, state, (item->IsOpen()) ? draw : kFALSE);
00533       item = item->fNextsibling;
00534    }
00535 }
00536 
00537 //______________________________________________________________________________
00538 void TGListTree::UnselectAll(Bool_t draw)
00539 {
00540    // Unselect all items.
00541 
00542    ClearViewPort();
00543    HighlightChildren(fFirst, kFALSE, draw);
00544 }
00545 
00546 //______________________________________________________________________________
00547 Bool_t TGListTree::HandleButton(Event_t *event)
00548 {
00549    // Handle button events in the list tree.
00550 
00551    TGListTreeItem *item;
00552 
00553    if (fTip) fTip->Hide();
00554 
00555    Int_t page = 0;
00556    if (event->fCode == kButton4 || event->fCode == kButton5) {
00557       if (!fCanvas) return kTRUE;
00558       if (fCanvas->GetContainer()->GetHeight()) {
00559 //         page = Int_t(Float_t(fCanvas->GetViewPort()->GetHeight() *
00560 //                              fCanvas->GetViewPort()->GetHeight()) /
00561 //                              fCanvas->GetContainer()->GetHeight());
00562          // choose page size either 1/5 of viewport or 5 lines (90)
00563          Int_t r = fCanvas->GetViewPort()->GetHeight() / 5;
00564          page = TMath::Min(r, 90);
00565       }
00566    }
00567 
00568    if (event->fCode == kButton4) {
00569       //scroll up
00570       Int_t newpos = fCanvas->GetVsbPosition() - page;
00571       if (newpos < 0) newpos = 0;
00572       fCanvas->SetVsbPosition(newpos);
00573       return kTRUE;
00574    }
00575    if (event->fCode == kButton5) {
00576       // scroll down
00577       Int_t newpos = fCanvas->GetVsbPosition() + page;
00578       fCanvas->SetVsbPosition(newpos);
00579       return kTRUE;
00580    }
00581 
00582    if (event->fType == kButtonPress) {
00583       if ((item = FindItem(event->fY)) != 0) {
00584          if (event->fCode == kButton1) {
00585             Int_t minx, maxx;
00586             Int_t minxchk = 0, maxxchk = 0;
00587             if (item->HasCheckBox()) {
00588                minxchk = (item->fXtext - item->GetCheckBoxPicture()->GetWidth());
00589                maxxchk = (item->fXtext - 4);
00590                maxx = maxxchk - Int_t(item->GetPicWidth()) - 8;
00591                minx = minxchk - Int_t(item->GetPicWidth()) - 16;
00592             }
00593             else {
00594                maxx = (item->fXtext - Int_t(item->GetPicWidth())) - 8;
00595                minx = (item->fXtext - Int_t(item->GetPicWidth())) - 16;
00596             }
00597             if ((item->HasCheckBox()) && (event->fX < maxxchk) &&
00598                (event->fX > minxchk))
00599             {
00600                ToggleItem(item);
00601                if (fCheckMode == kRecursive) {
00602                   CheckAllChildren(item, item->IsChecked());
00603                }
00604                UpdateChecked(item, kTRUE);
00605                Checked((TObject *)item->GetUserData(), item->IsChecked());
00606                return kTRUE;
00607             }
00608             if ((event->fX < maxx) && (event->fX > minx)) {
00609                item->SetOpen(!item->IsOpen());
00610                ClearViewPort();
00611                return kTRUE;
00612             }
00613          }
00614          // DND specific
00615          if (event->fCode == kButton1) {
00616             fXDND = event->fX;
00617             fYDND = event->fY;
00618             fBdown = kTRUE;
00619          }
00620          if (!fUserControlled) {
00621             if (fSelected) fSelected->SetActive(kFALSE);
00622             UnselectAll(kTRUE);
00623             //item->fActive = kTRUE; // this is done below w/redraw
00624             fCurrent = fSelected = item;
00625             HighlightItem(item, kTRUE, kTRUE);
00626             SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_ITEMCLICK),
00627                         event->fCode, (event->fYRoot << 16) | event->fXRoot);
00628          }
00629          else {
00630             fCurrent = fSelected = item;
00631             ClearViewPort();
00632          }
00633          Clicked(item, event->fCode);
00634          Clicked(item, event->fCode, event->fXRoot, event->fYRoot);
00635          Clicked(item, event->fCode, event->fState, event->fXRoot, event->fYRoot);
00636       }
00637    }
00638    if (event->fType == kButtonRelease) {
00639       fBdown = kFALSE;
00640    }
00641    return kTRUE;
00642 }
00643 
00644 //______________________________________________________________________________
00645 Bool_t TGListTree::HandleDoubleClick(Event_t *event)
00646 {
00647    // Handle double click event in the list tree (only for kButton1).
00648 
00649    TGListTreeItem *item = 0;
00650 
00651    if (event->fCode == kButton4 || event->fCode == kButton5) {
00652       return kFALSE;
00653    }
00654    // If fDisableOpen is set, only send message and emit signals.
00655    // It allows user to customize handling of double click events.
00656    if (fDisableOpen && event->fCode == kButton1 && (item = FindItem(event->fY)) != 0) {
00657       SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_ITEMDBLCLICK),
00658                   event->fCode, (event->fYRoot << 16) | event->fXRoot);
00659       DoubleClicked(item, event->fCode);
00660       DoubleClicked(item, event->fCode, event->fXRoot, event->fYRoot);
00661       return kTRUE;
00662    }
00663    item = FindItem(event->fY);
00664 
00665    // Otherwise, just use default behaviour (open item).
00666    if (event->fCode == kButton1 && item) {
00667       ClearViewPort();
00668       item->SetOpen(!item->IsOpen());
00669       if (!fUserControlled) {
00670          if (item != fSelected) { // huh?!
00671             if (fSelected) fSelected->SetActive(kFALSE); // !!!!
00672             UnselectAll(kTRUE);
00673             HighlightItem(item, kTRUE, kTRUE);
00674          }
00675       }
00676       SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_ITEMDBLCLICK),
00677                   event->fCode, (event->fYRoot << 16) | event->fXRoot);
00678       DoubleClicked(item, event->fCode);
00679       DoubleClicked(item, event->fCode, event->fXRoot, event->fYRoot);
00680    }
00681    if (!fUserControlled)
00682       fSelected = item;
00683    return kTRUE;
00684 }
00685 
00686 //______________________________________________________________________________
00687 Bool_t TGListTree::HandleCrossing(Event_t *event)
00688 {
00689    // Handle mouse crossing event.
00690 
00691    if (event->fType == kLeaveNotify) {
00692       if (fTip) {
00693          fTip->Hide();
00694          fTipItem = 0;
00695       }
00696       if (!fUserControlled) {
00697          if (fCurrent)
00698             DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
00699          if (fBelowMouse)
00700             DrawOutline(fId, fBelowMouse, 0xffffff, kTRUE);
00701          fCurrent = 0;
00702       }
00703       if (fBelowMouse) {
00704          fBelowMouse = 0;
00705          MouseOver(0);
00706          MouseOver(0, event->fState);
00707       }
00708    }
00709    return kTRUE;
00710 }
00711 
00712 //______________________________________________________________________________
00713 Atom_t TGListTree::HandleDNDPosition(Int_t /*x*/, Int_t y, Atom_t action,
00714                                       Int_t /*xroot*/, Int_t /*yroot*/)
00715 {
00716    // Handle dragging position events.
00717 
00718    static TGListTreeItem *olditem = 0;
00719    TGListTreeItem *item;
00720    if ((item = FindItem(y)) != 0) {
00721       if (item->IsDNDTarget()) {
00722          fDropItem = item;
00723          if (olditem)
00724             HighlightItem(olditem, kFALSE, kTRUE);
00725          HighlightItem(item, kTRUE, kTRUE);
00726          olditem = item;
00727          return action;
00728       }
00729    }
00730    fDropItem = 0;
00731    if (olditem) {
00732       HighlightItem(olditem, kFALSE, kTRUE);
00733       olditem = 0;
00734    }
00735    return kNone;
00736 }
00737 
00738 //______________________________________________________________________________
00739 Atom_t TGListTree::HandleDNDEnter(Atom_t *typelist)
00740 {
00741    // Handle drag enter events.
00742 
00743    Atom_t ret = kNone;
00744    for (int i = 0; typelist[i] != kNone; ++i) {
00745       if (typelist[i] == fDNDTypeList[0])
00746          ret = fDNDTypeList[0];
00747       if (typelist[i] == fDNDTypeList[1])
00748          ret = fDNDTypeList[1];
00749    }
00750    return ret;
00751 }
00752 
00753 //______________________________________________________________________________
00754 Bool_t TGListTree::HandleDNDLeave()
00755 {
00756    // Handle drag leave events.
00757 
00758    return kTRUE;
00759 }
00760 
00761 //______________________________________________________________________________
00762 Bool_t TGListTree::HandleDNDDrop(TDNDData *data)
00763 {
00764    // Handle drop events.
00765 
00766    DataDropped(fDropItem, data);
00767    HighlightItem(fDropItem, kFALSE, kTRUE);
00768    //ClearHighlighted();
00769    return kTRUE;
00770 }
00771 
00772 //______________________________________________________________________________
00773 void TGListTree::DataDropped(TGListTreeItem *item, TDNDData *data)
00774 {
00775    // Emit DataDropped() signal.
00776 
00777    Long_t args[2];
00778 
00779    args[0] = (Long_t)item;
00780    args[1] = (Long_t)data;
00781 
00782    Emit("DataDropped(TGListTreeItem*,TDNDData*)", args);
00783 }
00784 
00785 //______________________________________________________________________________
00786 Bool_t TGListTree::HandleMotion(Event_t *event)
00787 {
00788    // Handle mouse motion event. Used to set tool tip, to emit
00789    // MouseOver() signal and for DND handling.
00790 
00791    TGListTreeItem *item;
00792    TGPosition pos = GetPagePosition();
00793 
00794    if (gDNDManager->IsDragging()) {
00795       gDNDManager->Drag(event->fXRoot, event->fYRoot,
00796                         TGDNDManager::GetDNDActionCopy(), event->fTime);
00797    } else if ((item = FindItem(event->fY)) != 0) {
00798       if (!fUserControlled) {
00799          if (fCurrent)
00800             DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
00801          if (fBelowMouse)
00802             DrawOutline(fId, fBelowMouse, 0xffffff, kTRUE);
00803          DrawOutline(fId, item);
00804          fCurrent = item;
00805       }
00806       if (item != fBelowMouse) {
00807          fBelowMouse = item;
00808          MouseOver(fBelowMouse);
00809          MouseOver(fBelowMouse, event->fState);
00810       }
00811 
00812       if (item->HasCheckBox()) {
00813          if ((event->fX < (item->fXtext - 4) &&
00814              (event->fX > (item->fXtext - (Int_t)item->GetCheckBoxPicture()->GetWidth()))))
00815          {
00816             gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kPointer));
00817             return kTRUE;
00818          }
00819          else {
00820             gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kHand));
00821          }
00822       }
00823       if (!gDNDManager->IsDragging()) {
00824          if (fBdown && ((abs(event->fX - fXDND) > 2) || (abs(event->fY - fYDND) > 2))) {
00825             if (gDNDManager && item->IsDNDSource()) {
00826                if (!fBuf) fBuf = new TBufferFile(TBuffer::kWrite);
00827                fBuf->Reset();
00828                // !!!!! Here check virtual Bool_t HandlesDragAndDrop()
00829                // and let the item handle this.
00830                if (item->GetUserData()) {
00831                   TObject *obj = static_cast<TObject *>(item->GetUserData());
00832                   if (dynamic_cast<TObject *>(obj)) {
00833                      TObjString *ostr = dynamic_cast<TObjString *>(obj);
00834                      if (ostr) {
00835                         TString& str = ostr->String();
00836                         if (str.BeginsWith("file://")) {
00837                            fDNDData.fDataType = fDNDTypeList[1];
00838                            fDNDData.fData = (void *)strdup(str.Data());
00839                            fDNDData.fDataLength = str.Length()+1;
00840                         }
00841                      }
00842                      else {
00843                         fDNDData.fDataType = fDNDTypeList[0];
00844                         fBuf->WriteObject((TObject *)item->GetUserData());
00845                         fDNDData.fData = fBuf->Buffer();
00846                         fDNDData.fDataLength = fBuf->Length();
00847                      }
00848                   }
00849                }
00850                else {
00851                   fDNDData.fDataType = fDNDTypeList[1];
00852                   TString str = TString::Format("file://%s/%s\r\n",
00853                                 gSystem->UnixPathName(gSystem->WorkingDirectory()),
00854                                 item->GetText());
00855                   fDNDData.fData = (void *)strdup(str.Data());
00856                   fDNDData.fDataLength = str.Length()+1;
00857                }
00858                TString xmpname = item->GetPicture()->GetName();
00859                if (xmpname.EndsWith("_t.xpm"))
00860                   xmpname.ReplaceAll("_t.xpm", "_s.xpm");
00861                if (xmpname.EndsWith("_t.xpm__16x16"))
00862                   xmpname.ReplaceAll("_t.xpm__16x16", "_s.xpm");
00863                const TGPicture *pic = fClient->GetPicture(xmpname.Data());
00864                if (!pic) pic = item->GetPicture();
00865                if (pic) SetDragPixmap(pic);
00866                //SetDragPixmap(item->GetPicture());
00867                gDNDManager->StartDrag(this, event->fXRoot, event->fYRoot);
00868             }
00869          }
00870       }
00871       if (gDNDManager->IsDragging()) {
00872          gDNDManager->Drag(event->fXRoot, event->fYRoot,
00873                            TGDNDManager::GetDNDActionCopy(), event->fTime);
00874       } else {
00875          if (fTipItem == item) return kTRUE;
00876          if (!fUserControlled) { // !!!! what is this? It was called above once?
00877             MouseOver(item);
00878             MouseOver(item, event->fState);
00879          }
00880          gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kHand));
00881       }
00882 
00883       if (fTip)
00884          fTip->Hide();
00885 
00886       if (item->GetTipTextLength() > 0) {
00887 
00888          SetToolTipText(item->GetTipText(), item->fXtext,
00889                         item->fY - pos.fY + item->fHeight, 1000);
00890 
00891       } else if (fAutoTips && item->GetUserData()) {
00892          // must derive from TObject (in principle user can put pointer
00893          // to anything in user data field). Add check.
00894          TObject *obj = (TObject *)item->GetUserData();
00895          if (obj->InheritsFrom(TObject::Class())) {
00896             SetToolTipText(obj->GetTitle(), item->fXtext,
00897                            item->fY - pos.fY + item->fHeight, 1000);
00898          }
00899       }
00900       fTipItem = item;
00901    } else {
00902       if (fBelowMouse) {
00903          fBelowMouse = 0;
00904          MouseOver(fBelowMouse);
00905          MouseOver(fBelowMouse, event->fState);
00906       }
00907       gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kPointer));
00908    }
00909    return kTRUE;
00910 }
00911 
00912 //______________________________________________________________________________
00913 Bool_t TGListTree::HandleKey(Event_t *event)
00914 {
00915    // The key press event handler converts a key press to some line editor
00916    // action.
00917 
00918    char   input[10];
00919    Int_t  n;
00920    UInt_t keysym;
00921    TGListTreeItem *item = 0;
00922 
00923    fLastEventState = event->fState;
00924    if (fTip) fTip->Hide();
00925 
00926    if (event->fType == kGKeyPress) {
00927       gVirtualX->LookupString(event, input, sizeof(input), keysym);
00928       n = strlen(input);
00929 
00930       if (!event->fState && (EKeySym)keysym == kKey_Escape) {
00931          if (gDNDManager->IsDragging()) gDNDManager->EndDrag();
00932       }
00933 
00934       item = fCurrent;
00935       if (!item) return kFALSE;
00936 
00937       fEventHandled = kFALSE;
00938       KeyPressed(item, keysym, event->fState);
00939 
00940       if (fUserControlled && fEventHandled)
00941          return kTRUE;
00942       
00943       switch ((EKeySym)keysym) {
00944          case kKey_Enter:
00945          case kKey_Return:
00946             event->fType = kButtonPress;
00947             event->fCode = kButton1;
00948 
00949             if (fSelected == item) {
00950                // treat 'Enter' and 'Return' as a double click
00951                ClearViewPort();
00952                item->SetOpen(!item->IsOpen());
00953                DoubleClicked(item, 1);
00954             } else {
00955                // treat 'Enter' and 'Return' as a click
00956                ClearViewPort();
00957                if (fSelected) fSelected->SetActive(kFALSE);
00958                fSelected = item;
00959                fSelected->SetActive(kTRUE);
00960                HighlightItem(item, kTRUE, kTRUE);
00961                Clicked(item, 1);
00962                Clicked(item, 1, event->fXRoot, event->fYRoot);
00963                Clicked(item, 1, event->fState, event->fXRoot, event->fYRoot);
00964             }
00965             break;
00966          case kKey_Space:
00967             if (item->HasCheckBox()) {
00968                ToggleItem(item);
00969                if (fCheckMode == kRecursive) {
00970                   CheckAllChildren(item, item->IsChecked());
00971                }
00972                UpdateChecked(item, kTRUE);
00973                Checked((TObject *)item->GetUserData(), item->IsChecked());
00974             }
00975             break;
00976          case kKey_F5:
00977             Layout();
00978             break;
00979          case kKey_F7:
00980             Search();
00981             break;
00982          case kKey_Left:
00983             ClearViewPort();
00984             item->SetOpen(kFALSE);
00985             break;
00986          case kKey_Right:
00987             ClearViewPort();
00988             item->SetOpen(kTRUE);
00989             break;
00990          case kKey_Up:
00991             LineUp(event->fState & kKeyShiftMask);
00992             break;
00993          case kKey_Down:
00994             LineDown(event->fState & kKeyShiftMask);
00995             break;
00996          case kKey_PageUp:
00997             PageUp(event->fState & kKeyShiftMask);
00998             break;
00999          case kKey_PageDown:
01000             PageDown(event->fState & kKeyShiftMask);
01001             break;
01002          case kKey_Home:
01003             Home(event->fState & kKeyShiftMask);
01004             break;
01005          case kKey_End:
01006             End(event->fState & kKeyShiftMask);
01007             break;
01008          default:
01009             break;
01010       }
01011 
01012    }
01013    return kTRUE;
01014 }
01015 
01016 //______________________________________________________________________________
01017 void TGListTree::MouseOver(TGListTreeItem *entry)
01018 {
01019    // Signal emitted when pointer is over entry.
01020 
01021    Emit("MouseOver(TGListTreeItem*)", (Long_t)entry);
01022 }
01023 
01024 //______________________________________________________________________________
01025 void TGListTree::MouseOver(TGListTreeItem *entry, UInt_t mask)
01026 {
01027    // Signal emitted when pointer is over entry.
01028 
01029    Long_t args[2];
01030    args[0] = (Long_t)entry;
01031    args[1] = mask;
01032    Emit("MouseOver(TGListTreeItem*,UInt_t)", args);
01033 }
01034 
01035 //______________________________________________________________________________
01036 void TGListTree::KeyPressed(TGListTreeItem *entry, UInt_t keysym, UInt_t mask)
01037 {
01038    // Signal emitted when keyboard key pressed
01039    //
01040    // entry - selected item
01041    // keysym - defined in "KeySymbols.h"
01042    // mask - modifier key mask, defined in "GuiTypes.h"
01043    //
01044    // const Mask_t kKeyShiftMask   = BIT(0);
01045    // const Mask_t kKeyLockMask    = BIT(1);
01046    // const Mask_t kKeyControlMask = BIT(2);
01047    // const Mask_t kKeyMod1Mask    = BIT(3);   // typically the Alt key
01048    // const Mask_t kButton1Mask    = BIT(8);
01049    // const Mask_t kButton2Mask    = BIT(9);
01050    // const Mask_t kButton3Mask    = BIT(10);
01051    // const Mask_t kButton4Mask    = BIT(11);
01052    // const Mask_t kButton5Mask    = BIT(12);
01053    // const Mask_t kAnyModifier    = BIT(15);
01054 
01055    Long_t args[3];
01056    args[0] = (Long_t)entry;
01057    args[1] = (Long_t)keysym;
01058    args[2] = (Long_t)mask;
01059    Emit("KeyPressed(TGListTreeItem*,ULong_t,ULong_t)", args);
01060    SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_KEY), keysym, mask);
01061 }
01062 
01063 //______________________________________________________________________________
01064 void TGListTree::ReturnPressed(TGListTreeItem *entry)
01065 {
01066    // Emit ReturnPressed() signal.
01067 
01068    Emit("ReturnPressed(TGListTreeItem*)", (Long_t)entry);
01069 }
01070 
01071 //______________________________________________________________________________
01072 void TGListTree::Checked(TObject *entry, Bool_t on)
01073 {
01074    // Emit Checked() signal.
01075 
01076    Long_t args[2];
01077 
01078    args[0] = (Long_t)entry;
01079    args[1] = on;
01080 
01081    Emit("Checked(TObject*,Bool_t)", args);
01082 }
01083 
01084 //______________________________________________________________________________
01085 void TGListTree::Clicked(TGListTreeItem *entry, Int_t btn)
01086 {
01087    // Emit Clicked() signal.
01088 
01089    Long_t args[2];
01090 
01091    args[0] = (Long_t)entry;
01092    args[1] = btn;
01093 
01094    Emit("Clicked(TGListTreeItem*,Int_t)", args);
01095 }
01096 
01097 //______________________________________________________________________________
01098 void TGListTree::Clicked(TGListTreeItem *entry, Int_t btn, Int_t x, Int_t y)
01099 {
01100    // Emit Clicked() signal.
01101 
01102    Long_t args[4];
01103 
01104    args[0] = (Long_t)entry;
01105    args[1] = btn;
01106    args[2] = x;
01107    args[3] = y;
01108 
01109    Emit("Clicked(TGListTreeItem*,Int_t,Int_t,Int_t)", args);
01110 }
01111 
01112 //______________________________________________________________________________
01113 void TGListTree::Clicked(TGListTreeItem *entry, Int_t btn, UInt_t mask, Int_t x, Int_t y)
01114 {
01115    // Emit Clicked() signal.
01116 
01117    Long_t args[5];
01118 
01119    args[0] = (Long_t)entry;
01120    args[1] = btn;
01121    args[2] = mask;
01122    args[3] = x;
01123    args[4] = y;
01124 
01125    Emit("Clicked(TGListTreeItem*,Int_t,UInt_t,Int_t,Int_t)", args);
01126 }
01127 
01128 //______________________________________________________________________________
01129 void TGListTree::DoubleClicked(TGListTreeItem *entry, Int_t btn)
01130 {
01131    // Emit DoubleClicked() signal.
01132 
01133    Long_t args[2];
01134 
01135    args[0] = (Long_t)entry;
01136    args[1] = btn;
01137 
01138    Emit("DoubleClicked(TGListTreeItem*,Int_t)", args);
01139 }
01140 
01141 //______________________________________________________________________________
01142 void TGListTree::DoubleClicked(TGListTreeItem *entry, Int_t btn, Int_t x, Int_t y)
01143 {
01144    // Emit DoubleClicked() signal.
01145 
01146    Long_t args[4];
01147 
01148    args[0] = (Long_t)entry;
01149    args[1] = btn;
01150    args[2] = x;
01151    args[3] = y;
01152 
01153    Emit("DoubleClicked(TGListTreeItem*,Int_t,Int_t,Int_t)", args);
01154 }
01155 
01156 //______________________________________________________________________________
01157 void TGListTree::Home(Bool_t /*select*/)
01158 {
01159    // Move content to the top.
01160 
01161    if (fCanvas) fCanvas->SetVsbPosition(0);
01162 }
01163 
01164 //______________________________________________________________________________
01165 void TGListTree::End(Bool_t /*select*/)
01166 {
01167    // Move content to the bottom.
01168 
01169    if (fCanvas) fCanvas->SetVsbPosition((Int_t)fHeight);
01170 }
01171 
01172 //______________________________________________________________________________
01173 void TGListTree::PageUp(Bool_t /*select*/)
01174 {
01175    // Move content one page up.
01176 
01177    if (!fCanvas) return;
01178 
01179    TGDimension dim = GetPageDimension();
01180 
01181    Int_t newpos = fCanvas->GetVsbPosition() - dim.fHeight;
01182    if (newpos<0) newpos = 0;
01183 
01184    fCanvas->SetVsbPosition(newpos);
01185 }
01186 
01187 //______________________________________________________________________________
01188 void TGListTree::PageDown(Bool_t /*select*/)
01189 {
01190    // Move content one page down.
01191 
01192    if (!fCanvas) return;
01193 
01194    TGDimension dim = GetPageDimension();
01195 
01196    Int_t newpos = fCanvas->GetVsbPosition() + dim.fHeight;
01197 
01198    fCanvas->SetVsbPosition(newpos);
01199 }
01200 
01201 //______________________________________________________________________________
01202 void TGListTree::LineUp(Bool_t /*select*/)
01203 {
01204    // Move content one item-size up.
01205 
01206    Int_t height;
01207    if (!fCurrent) return;
01208    
01209    TGDimension dim = GetPageDimension();
01210    TGPosition pos = GetPagePosition();
01211    const TGPicture *pic1 = fCurrent->GetPicture();
01212    height = pic1->GetHeight() + fVspacing;
01213    Int_t findy = (fCurrent->fY - height) + (fMargin - pos.fY);
01214    TGListTreeItem *next = FindItem(findy);
01215    if (next && (next != fCurrent)) {
01216       DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
01217       if (findy <= 2*height) {
01218          Int_t newpos = fCanvas->GetVsbPosition() - height;
01219          if (newpos<0) newpos = 0;
01220          fCanvas->SetVsbPosition(newpos);
01221       }
01222       DrawOutline(fId, next);
01223       fCurrent = next;
01224    }
01225 }
01226 
01227 //______________________________________________________________________________
01228 void TGListTree::LineDown(Bool_t /*select*/)
01229 {
01230    // Move content one item-size down.
01231 
01232    Int_t height;
01233    if (!fCurrent) return;
01234    
01235    TGDimension dim = GetPageDimension();
01236    TGPosition pos = GetPagePosition();
01237    const TGPicture *pic1 = fCurrent->GetPicture();
01238    height = pic1->GetHeight() + fVspacing;
01239    Int_t findy = (fCurrent->fY + height) + (fMargin - pos.fY);
01240    TGListTreeItem *next = FindItem(findy);
01241    if (next && (next != fCurrent)) {
01242       DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
01243       if (findy >= ((Int_t)dim.fHeight - 2*height)) {
01244          Int_t newpos = fCanvas->GetVsbPosition() + height;
01245          if (newpos<0) newpos = 0;
01246          fCanvas->SetVsbPosition(newpos);
01247       }
01248       DrawOutline(fId, next);
01249       fCurrent = next;
01250    }
01251 }
01252 
01253 //______________________________________________________________________________
01254 void TGListTree::AdjustPosition(TGListTreeItem *item)
01255 {
01256    // Move content to position of item. If item is 0, move to position
01257    // of currently selected item.
01258 
01259    TGListTreeItem *it = item;
01260 
01261    if (!it) it = fSelected;
01262    if (!it) {
01263       HighlightItem(fFirst); // recursive call of this function
01264       return;
01265    }
01266 
01267    Int_t y = 0;
01268    Int_t yparent = 0;
01269    Int_t vh = 0;
01270    Int_t v = 0;
01271 
01272    if (it) {
01273       y = it->fY;
01274       if (it->GetParent()) yparent = it->GetParent()->fY;
01275    }
01276 
01277    if (y==0) y = yparent; // item->fY not initiated yet
01278 
01279    if (fCanvas->GetVScrollbar()->IsMapped()) {
01280       vh = fCanvas->GetVScrollbar()->GetPosition()+(Int_t)fViewPort->GetHeight();
01281 
01282       if (y<fCanvas->GetVScrollbar()->GetPosition()) {
01283          v = TMath::Max(0,y-(Int_t)fViewPort->GetHeight()/2);
01284          fCanvas->SetVsbPosition(v);
01285       } else if (y+(Int_t)it->fHeight>vh) {
01286          v = TMath::Min((Int_t)GetHeight()-(Int_t)fViewPort->GetHeight(),
01287                         y+(Int_t)it->fHeight-(Int_t)fViewPort->GetHeight()/2);
01288          if (v<0) v = 0;
01289          fCanvas->SetVsbPosition(v);
01290       }
01291    }
01292 }
01293 
01294 //______________________________________________________________________________
01295 void TGListTree::Search(Bool_t /*close*/)
01296 {
01297    // Invokes search dialog. Looks for item with the entered name.
01298 
01299    Int_t ret = 0;
01300    char msg[256];
01301    static TString buf;
01302 
01303    TGSearchType *srch = new TGSearchType;
01304    srch->fBuffer = (char*)buf.Data();
01305 
01306    TGListTreeItem *item;
01307    new TGSearchDialog(fClient->GetDefaultRoot(), fCanvas, 400, 150, srch, &ret);
01308 
01309    if (ret) {
01310       item = FindItemByPathname(srch->fBuffer);
01311       if (!item) {
01312          snprintf(msg, 255, "Couldn't find \"%s\"", srch->fBuffer);
01313          gVirtualX->Bell(20);
01314          new TGMsgBox(fClient->GetDefaultRoot(), fCanvas, "Container", msg,
01315                       kMBIconExclamation, kMBOk, 0);
01316       } else {
01317          ClearHighlighted();
01318          HighlightItem(item);
01319       }
01320    }
01321    buf = srch->fBuffer;
01322    delete srch;
01323 }
01324 
01325 //---- drawing functions
01326 
01327 //______________________________________________________________________________
01328 void TGListTree::DrawRegion(Int_t /*x*/, Int_t y, UInt_t /*w*/, UInt_t h)
01329 {
01330    // Redraw list tree.
01331 
01332    static GContext_t gcBg = 0;
01333 
01334    // sanity checks
01335    if (y > (Int_t)fViewPort->GetHeight()) {
01336       return;
01337    }
01338 
01339    y = y < 0 ? 0 : y;
01340    UInt_t w = fViewPort->GetWidth();
01341 
01342    // more sanity checks
01343    if (((Int_t)w < 1) || (w > 32768) || ((Int_t)h < 1)) {
01344       return;
01345    }
01346 
01347    Pixmap_t pixmap = gVirtualX->CreatePixmap(fId, w, fViewPort->GetHeight());
01348 
01349    if (!gcBg) {
01350       GCValues_t gcValues;
01351       gcValues.fForeground = fBackground;
01352       gcValues.fForeground = fBackground;
01353       gcValues.fGraphicsExposures = kTRUE;
01354       gcValues.fMask = kGCForeground | kGCBackground | kGCGraphicsExposures;
01355       gcBg = gVirtualX->CreateGC(fId, &gcValues);
01356    }
01357 
01358    gVirtualX->SetForeground(gcBg, fBackground);
01359    gVirtualX->FillRectangle(pixmap, gcBg, 0, 0, w, fViewPort->GetHeight());
01360 
01361    Draw(pixmap, 0, fViewPort->GetHeight());
01362 
01363    gVirtualX->CopyArea(pixmap, fId, gcBg, 0, y, w, fViewPort->GetHeight(), 0, y);
01364 
01365    gVirtualX->DeletePixmap(pixmap);
01366    gVirtualX->Update(kFALSE);
01367 }
01368 
01369 //______________________________________________________________________________
01370 void TGListTree::Draw(Handle_t id, Int_t yevent, Int_t hevent)
01371 {
01372    // Draw list tree widget.
01373 
01374    TGListTreeItem *item;
01375    Int_t  x, y, xbranch;
01376    UInt_t width, height, old_width, old_height;
01377 
01378    // Overestimate the expose region to be sure to draw an item that gets
01379    // cut by the region
01380    fExposeTop = yevent - FontHeight();
01381    fExposeBottom = yevent + hevent + FontHeight();
01382    old_width  = fDefw;
01383    old_height = fDefh;
01384    fDefw = fDefh = 1;
01385 
01386    TGPosition pos = GetPagePosition();
01387    x = -pos.fX;
01388    y = fMargin;
01389    item = fFirst;
01390 
01391    while (item) {
01392       xbranch = -1;
01393 
01394       DrawItem(id, item, x, y, &xbranch, &width, &height);
01395 
01396       width += pos.fX + x + fHspacing + fMargin;
01397 
01398       if (width > fDefw) fDefw = width;
01399 
01400       y += height + fVspacing;
01401       if (item->fFirstchild && item->IsOpen()) {
01402          y = DrawChildren(id, item->fFirstchild, x, y, xbranch);
01403       }
01404 
01405       item = item->fNextsibling;
01406    }
01407 
01408    fDefh = y + fMargin;
01409 
01410    if ((old_width != fDefw) || (old_height != fDefh)) {
01411       fCanvas->Layout();
01412    }
01413 }
01414 
01415 //______________________________________________________________________________
01416 Int_t TGListTree::DrawChildren(Handle_t id, TGListTreeItem *item,
01417                                Int_t x, Int_t y, Int_t xroot)
01418 {
01419    // Draw children of item in list tree.
01420 
01421    UInt_t width, height;
01422    Int_t  xbranch;
01423    TGPosition pos = GetPagePosition();
01424 
01425    x += fIndent + (Int_t)item->fParent->GetPicWidth();
01426    while (item) {
01427       xbranch = xroot;
01428 
01429       DrawItem(id, item, x, y, &xbranch, &width, &height);
01430 
01431       width += pos.fX + x + fHspacing + fMargin;
01432       if (width > fDefw) fDefw = width;
01433 
01434       y += height + fVspacing;
01435       if ((item->fFirstchild) && (item->IsOpen())) {
01436          y = DrawChildren(id, item->fFirstchild, x, y, xbranch);
01437       }
01438 
01439       item = item->fNextsibling;
01440    }
01441    return y;
01442 }
01443 
01444 //______________________________________________________________________________
01445 void TGListTree::DrawItem(Handle_t id, TGListTreeItem *item, Int_t x, Int_t y,
01446                           Int_t *xroot, UInt_t *retwidth, UInt_t *retheight)
01447 {
01448    // Draw list tree item.
01449 
01450    Int_t  xpic1, ypic1, xbranch, ybranch, xtext, ytext, xline, yline, xc;
01451    Int_t  xpic2 = 0, ypic2 = 0;
01452    UInt_t height;
01453    const TGPicture *pic1 = item->GetPicture();
01454    const TGPicture *pic2 = item->GetCheckBoxPicture();
01455 
01456    // Compute the height of this line
01457    height = FontHeight();
01458    xline = 0;
01459    xpic1 = x;
01460    xtext = x + fHspacing + (Int_t)item->GetPicWidth();
01461    if (pic2) {
01462       if (pic2->GetHeight() > height) {
01463          ytext = y + (Int_t)((pic2->GetHeight() - height) >> 1);
01464          height = pic2->GetHeight();
01465          ypic2 = y;
01466       } else {
01467          ytext = y;
01468          ypic2 = y + (Int_t)((height - pic2->GetHeight()) >> 1);
01469       }
01470       xpic2 = xpic1 + pic1->GetWidth() + 1;
01471       xtext += pic2->GetWidth();
01472    } else {
01473       ypic1 = y;
01474       xline = 0;
01475    }
01476    if (pic1) {
01477       if (pic1->GetHeight() > height) {
01478          ytext = y + (Int_t)((pic1->GetHeight() - height) >> 1);
01479          height = pic1->GetHeight();
01480          ypic1 = y;
01481       } else {
01482          ytext = y;
01483          ypic1 = y + (Int_t)((height - pic1->GetHeight()) >> 1);
01484       }
01485       xbranch = xpic1 + (Int_t)(pic1->GetWidth() >> 1);
01486       ybranch = ypic1 + (Int_t)pic1->GetHeight();
01487       yline = ypic1 + (Int_t)(pic1->GetHeight() >> 1);
01488       if (xline == 0) xline = xpic1;
01489    } else {
01490       if (xline == 0) xline = xpic1;
01491       ypic1 = ytext = y;
01492       xbranch = xpic1 + (Int_t)(item->GetPicWidth() >> 1);
01493       yline = ybranch = ypic1 + (Int_t)(height >> 1);
01494       yline = ypic1 + (Int_t)(height >> 1);
01495    }
01496 
01497    // height must be even, otherwise our dashed line wont appear properly
01498    //++height; height &= ~1;
01499 
01500    // Save the basic graphics info for use by other functions
01501    item->fY      = y;
01502    item->fXtext  = xtext;
01503    item->fYtext  = ytext;
01504    item->fHeight = height;
01505 
01506    // projected coordinates
01507    TGPosition  pos = GetPagePosition();
01508    TGDimension dim = GetPageDimension();
01509    Int_t yp        = y       - pos.fY;
01510    Int_t ylinep    = yline   - pos.fY;
01511    Int_t ybranchp  = ybranch - pos.fY;
01512    Int_t ypicp     = ypic1   - pos.fY;
01513 
01514    if ((yp >= fExposeTop) && (yp <= (Int_t)dim.fHeight))
01515    {
01516       if (*xroot >= 0) {
01517          xc = *xroot;
01518 
01519          if (item->fNextsibling) {
01520             gVirtualX->DrawLine(id, fLineGC, xc, yp, xc, yp+height);
01521          } else {
01522             gVirtualX->DrawLine(id, fLineGC, xc, yp, xc, ylinep);
01523          }
01524 
01525          TGListTreeItem *p = item->fParent;
01526          while (p) {
01527             xc -= (fIndent + (Int_t)item->GetPicWidth());
01528             if (p->fNextsibling) {
01529                gVirtualX->DrawLine(id, fLineGC, xc, yp, xc, yp+height);
01530             }
01531             p = p->fParent;
01532          }
01533          gVirtualX->DrawLine(id, fLineGC, *xroot, ylinep, xpic1, ylinep);
01534          DrawNode(id, item, *xroot, yline);
01535       }
01536       if (item->IsOpen() && item->fFirstchild) {
01537          gVirtualX->DrawLine(id, fLineGC, xbranch, ybranchp, xbranch, 
01538                              yp+height);
01539       }
01540       if (pic1)
01541          pic1->Draw(id, fDrawGC, xpic1, ypicp);
01542       if (pic2)
01543          pic2->Draw(id, fDrawGC, xpic2, ypicp);
01544       DrawItemName(id, item);
01545    }
01546 
01547    *xroot = xbranch;
01548    *retwidth  = TextWidth(item->GetText()) + item->GetPicWidth();
01549    *retheight = height;
01550 }
01551 
01552 //______________________________________________________________________________
01553 void TGListTree::DrawOutline(Handle_t id, TGListTreeItem *item, Pixel_t col, 
01554                              Bool_t clear)
01555 {
01556    // Draw a outline of color 'col' around an item.
01557 
01558    Int_t posx;
01559    TGPosition pos = GetPagePosition();
01560    TGDimension dim = GetPageDimension();
01561 
01562    posx = item->fXtext - item->GetPicWidth();
01563    posx -= 5;
01564    if (item->HasCheckBox())
01565       posx -= item->GetCheckBoxPicture()->GetWidth();
01566    if (clear) {
01567       gVirtualX->SetForeground(fDrawGC, fCanvas->GetContainer()->GetBackground());
01568       //ClearViewPort();  // time consuming!!!
01569    }
01570    else
01571       gVirtualX->SetForeground(fDrawGC, col);
01572    gVirtualX->DrawRectangle(id, fDrawGC, posx, item->fYtext-pos.fY-2, 
01573                             dim.fWidth-posx-2, FontHeight()+4);
01574    gVirtualX->SetForeground(fDrawGC, fgBlackPixel);
01575 }
01576 
01577 //______________________________________________________________________________
01578 void TGListTree::DrawActive(Handle_t id, TGListTreeItem *item)
01579 {
01580    // Draw active item with its active color.
01581 
01582    UInt_t width;
01583    TGPosition pos = GetPagePosition();
01584    TGDimension dim = GetPageDimension();
01585 
01586    width = TextWidth(item->GetText());
01587    gVirtualX->SetForeground(fDrawGC, item->GetActiveColor());
01588    gVirtualX->FillRectangle(id, fDrawGC, item->fXtext-1, 
01589                     item->fYtext-pos.fY, width+2, FontHeight()+1);
01590    gVirtualX->SetForeground(fDrawGC, fgBlackPixel);
01591    gVirtualX->DrawString(id, fHighlightGC, item->fXtext, 
01592                          item->fYtext - pos.fY + FontAscent(),
01593                          item->GetText(), item->GetTextLength());
01594 }
01595 
01596 //______________________________________________________________________________
01597 void TGListTree::DrawItemName(Handle_t id, TGListTreeItem *item)
01598 {
01599    // Draw name of list tree item.
01600 
01601    TGPosition pos = GetPagePosition();
01602    TGDimension dim = GetPageDimension();
01603 
01604    if (item->IsActive()) {
01605       DrawActive(id, item);
01606    }
01607    else { // if (!item->IsActive() && (item != fSelected)) {
01608       gVirtualX->FillRectangle(id, fHighlightGC, item->fXtext, 
01609                        item->fYtext-pos.fY, dim.fWidth-item->fXtext-2,
01610                        FontHeight()+1);
01611       gVirtualX->DrawString(id, fDrawGC,
01612                        item->fXtext, item->fYtext-pos.fY + FontAscent(),
01613                        item->GetText(), item->GetTextLength());
01614    }
01615    if (item == fCurrent) {
01616       DrawOutline(id, item);
01617    }
01618 
01619    if (fColorMode != 0 && item->HasColor()) {
01620       UInt_t width = TextWidth(item->GetText());
01621       gVirtualX->SetForeground(fColorGC, TColor::Number2Pixel(item->GetColor()));
01622       if (fColorMode & kColorUnderline) {
01623          Int_t y = item->fYtext-pos.fY + FontAscent() + 2;
01624          gVirtualX->DrawLine(id, fColorGC, item->fXtext, y, item->fXtext + width, y);
01625       }
01626       if (fColorMode & kColorBox) {
01627          Int_t x = item->fXtext + width + 4;
01628          Int_t y = item->fYtext - pos.fY  + 3;
01629          Int_t h = FontAscent()    - 4;
01630          gVirtualX->FillRectangle(id, fColorGC, x, y, h, h);
01631          gVirtualX->DrawRectangle(id, fDrawGC,  x, y, h, h);
01632       }
01633    }
01634 }
01635 
01636 //______________________________________________________________________________
01637 void TGListTree::DrawNode(Handle_t id, TGListTreeItem *item, Int_t x, Int_t y)
01638 {
01639    // Draw node (little + in box).
01640 
01641    TGPosition pos = GetPagePosition();
01642    Int_t yp = y - pos.fY;
01643 
01644    if (item->fFirstchild) {
01645       gVirtualX->DrawLine(id, fHighlightGC, x, yp-2, x, yp+2);
01646       gVirtualX->SetForeground(fHighlightGC, fgBlackPixel);
01647       gVirtualX->DrawLine(id, fHighlightGC, x-2, yp, x+2, yp);
01648       if (!item->IsOpen())
01649          gVirtualX->DrawLine(id, fHighlightGC, x, yp-2, x, yp+2);
01650       gVirtualX->SetForeground(fHighlightGC, fGrayPixel);
01651       gVirtualX->DrawLine(id, fHighlightGC, x-4, yp-4, x+4, yp-4);
01652       gVirtualX->DrawLine(id, fHighlightGC, x+4, yp-4, x+4, yp+4);
01653       gVirtualX->DrawLine(id, fHighlightGC, x-4, yp+4, x+4, yp+4);
01654       gVirtualX->DrawLine(id, fHighlightGC, x-4, yp-4, x-4, yp+4);
01655       gVirtualX->SetForeground(fHighlightGC, fgWhitePixel);
01656    }
01657 }
01658 
01659 //______________________________________________________________________________
01660 void TGListTree::SetToolTipText(const char *text, Int_t x, Int_t y, Long_t delayms)
01661 {
01662    // Set tool tip text associated with this item. The delay is in
01663    // milliseconds (minimum 250). To remove tool tip call method with
01664    // delayms = 0. To change delayms you first have to call this method
01665    // with delayms=0.
01666 
01667    if (delayms == 0) {
01668       delete fTip;
01669       fTip = 0;
01670       return;
01671    }
01672 
01673    if (text && strlen(text)) {
01674       if (!fTip)
01675          fTip = new TGToolTip(fClient->GetDefaultRoot(), this, text, delayms);
01676       else
01677          fTip->SetText(text);
01678       fTip->SetPosition(x, y);
01679       fTip->Reset();
01680    }
01681 }
01682 
01683 //______________________________________________________________________________
01684 void TGListTree::RemoveReference(TGListTreeItem *item)
01685 {
01686    // This function removes the specified item from the linked list.
01687    // It does not do anything with the data contained in the item, though.
01688 
01689    ClearViewPort();
01690 
01691    // Disentangle from front (previous-sibling, parent's first child)
01692    if (item->fPrevsibling) {
01693       item->fPrevsibling->fNextsibling = item->fNextsibling;
01694    } else {
01695       if (item->fParent)
01696          item->fParent->fFirstchild = item->fNextsibling;
01697       else
01698          fFirst = item->fNextsibling;
01699    }
01700    // Disentangle from end (next-sibling, parent's last child)
01701    if (item->fNextsibling) {
01702       item->fNextsibling->fPrevsibling = item->fPrevsibling;
01703    } else {
01704       if (item->fParent)
01705          item->fParent->fLastchild = item->fPrevsibling;
01706       else
01707          fLast = item->fPrevsibling;
01708    }
01709 }
01710 
01711 //______________________________________________________________________________
01712 void TGListTree::PDeleteItem(TGListTreeItem *item)
01713 {
01714    // Delete given item. Takes care of list-tree state members
01715    // fSelected, fCurrent and fBelowMouse.
01716 
01717    if (fSelected == item) {
01718       fSelected = 0;
01719    }
01720    if (fCurrent == item) {
01721       DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
01722       fCurrent = item->GetPrevSibling();
01723       if (! fCurrent) {
01724          fCurrent = item->GetNextSibling();
01725          if (! fCurrent)
01726             fCurrent = item->GetParent();
01727       }
01728    }
01729    if (fBelowMouse == item) {
01730       DrawOutline(fId, fBelowMouse, 0xffffff, kTRUE);
01731       fBelowMouse = 0;
01732       MouseOver(0);
01733       MouseOver(0,fLastEventState);
01734    }
01735 
01736    delete item; 
01737 }
01738 
01739 //______________________________________________________________________________
01740 void TGListTree::PDeleteChildren(TGListTreeItem *item)
01741 {
01742    // Recursively delete all children of an item.
01743 
01744    TGListTreeItem *child = item->fFirstchild;
01745 
01746    while (child) {
01747       TGListTreeItem *next = child->fNextsibling;
01748       PDeleteChildren(child);
01749       PDeleteItem(child);
01750       child = next;
01751    }
01752 
01753    item->fFirstchild = item->fLastchild = 0;
01754 }
01755 
01756 //______________________________________________________________________________
01757 void TGListTree::InsertChild(TGListTreeItem *parent, TGListTreeItem *item)
01758 {
01759    // Insert child in list.
01760 
01761    TGListTreeItem *i;
01762 
01763    item->fParent = parent;
01764    item->fNextsibling = item->fPrevsibling = 0;
01765 
01766    if (parent) {
01767 
01768       if (parent->fFirstchild) {
01769          if (parent->fLastchild) {
01770             i = parent->fLastchild;
01771          }
01772          else {
01773             i = parent->fFirstchild;
01774             while (i->fNextsibling) i = i->fNextsibling;
01775          }
01776          i->fNextsibling = item;
01777          item->fPrevsibling = i;
01778       } else {
01779          parent->fFirstchild = item;
01780       }
01781       parent->fLastchild = item;
01782 
01783    } else {  // if parent == 0, this is a top level entry
01784 
01785       if (fFirst) {
01786          if (fLast) {
01787             i = fLast;
01788          }
01789          else {
01790             i = fFirst;
01791             while (i->fNextsibling) i = i->fNextsibling;
01792          }
01793          i->fNextsibling = item;
01794          item->fPrevsibling = i;
01795       } else {
01796          fFirst = item;
01797       }
01798       fLast = item;
01799    }
01800    if (item->HasCheckBox())
01801       UpdateChecked(item);
01802 }
01803 
01804 //______________________________________________________________________________
01805 void TGListTree::InsertChildren(TGListTreeItem *parent, TGListTreeItem *item)
01806 {
01807    // Insert a list of ALREADY LINKED children into another list
01808 
01809    TGListTreeItem *next, *newnext;
01810 
01811    //while (item) {
01812    //   next = item->fNextsibling;
01813    //   InsertChild(parent, item);
01814    //   item = next;
01815    //}
01816    //return;
01817 
01818    // Save the reference for the next item in the new list
01819    next = item->fNextsibling;
01820 
01821    // Insert the first item in the new list into the existing list
01822    InsertChild(parent, item);
01823 
01824    // The first item is inserted, with its prev and next siblings updated
01825    // to fit into the existing list. So, save the existing list reference
01826    newnext = item->fNextsibling;
01827 
01828    // Now, mark the first item's next sibling to point back to the new list
01829    item->fNextsibling = next;
01830 
01831    // Mark the parents of the new list to the new parent. The order of the
01832    // rest of the new list should be OK, and the second item should still
01833    // point to the first, even though the first was reparented.
01834    while (item->fNextsibling) {
01835       item->fParent = parent;
01836       item = item->fNextsibling;
01837    }
01838 
01839    // Fit the end of the new list back into the existing list
01840    item->fNextsibling = newnext;
01841    if (newnext)
01842       newnext->fPrevsibling = item;
01843 }
01844 
01845 //______________________________________________________________________________
01846 Int_t TGListTree::SearchChildren(TGListTreeItem *item, Int_t y, Int_t findy,
01847                                  TGListTreeItem **finditem)
01848 {
01849    // Search child item.
01850 
01851    UInt_t height;
01852    const TGPicture *pic;
01853 
01854    while (item) {
01855       // Select the pixmap to use
01856       pic = item->GetPicture();
01857 
01858       // Compute the height of this line
01859       height = FontHeight();
01860       if (pic->GetHeight() > height)
01861          height = pic->GetHeight();
01862 
01863       if ((findy >= y) && (findy <= y + (Int_t)height)) {
01864          *finditem = item;
01865          return -1;
01866       }
01867 
01868       y += (Int_t)height + fVspacing;
01869       if (item->fFirstchild && item->IsOpen()) {
01870          y = SearchChildren(item->fFirstchild, y, findy, finditem);
01871          if (*finditem) return -1;
01872       }
01873 
01874       item = item->fNextsibling;
01875    }
01876 
01877    return y;
01878 }
01879 
01880 //______________________________________________________________________________
01881 TGListTreeItem *TGListTree::FindItem(Int_t findy)
01882 {
01883    // Find item at postion findy.
01884 
01885    Int_t  y;
01886    UInt_t height;
01887    TGListTreeItem *item, *finditem;
01888    const TGPicture *pic;
01889    TGPosition pos = GetPagePosition();
01890 
01891    y = fMargin - pos.fY;
01892    item = fFirst;
01893    finditem = 0;
01894    while (item && !finditem) {
01895       // Select the pixmap to use
01896       pic = item->GetPicture();
01897 
01898       // Compute the height of this line
01899       height = FontHeight();
01900       if (pic && (pic->GetHeight() > height))
01901          height = pic->GetHeight();
01902 
01903       if ((findy >= y) && (findy <= y + (Int_t)height))
01904          return item;
01905 
01906       y += (Int_t)height + fVspacing;
01907       if ((item->fFirstchild) && (item->IsOpen())) {
01908          y = SearchChildren(item->fFirstchild, y, findy, &finditem);
01909          //if (finditem) return finditem;
01910       }
01911       item = item->fNextsibling;
01912    }
01913 
01914    return finditem;
01915 }
01916 
01917 //----- Public Functions
01918 
01919 //______________________________________________________________________________
01920 void TGListTree::AddItem(TGListTreeItem *parent, TGListTreeItem *item)
01921 {
01922    // Add given item to list tree.
01923 
01924    InsertChild(parent, item);
01925 
01926    if ((parent == 0) || (parent && parent->IsOpen()))
01927       ClearViewPort();
01928 }
01929 
01930 //______________________________________________________________________________
01931 TGListTreeItem *TGListTree::AddItem(TGListTreeItem *parent, const char *string,
01932                                     const TGPicture *open, const TGPicture *closed,
01933                                     Bool_t checkbox)
01934 {
01935    // Add item to list tree. Returns new item.
01936 
01937    TGListTreeItem *item;
01938 
01939    item = new TGListTreeItemStd(fClient, string, open, closed, checkbox);
01940    InsertChild(parent, item);
01941 
01942    if ((parent == 0) || (parent && parent->IsOpen()))
01943       ClearViewPort();
01944    return item;
01945 }
01946 
01947 //______________________________________________________________________________
01948 TGListTreeItem *TGListTree::AddItem(TGListTreeItem *parent, const char *string,
01949                                     void *userData, const TGPicture *open,
01950                                     const TGPicture *closed,
01951                                     Bool_t checkbox)
01952 {
01953    // Add item to list tree. If item with same userData already exists
01954    // don't add it. Returns new item.
01955 
01956    TGListTreeItem *item = FindChildByData(parent, userData);
01957    if (!item) {
01958       item = AddItem(parent, string, open, closed, checkbox);
01959       if (item) item->SetUserData(userData);
01960    }
01961 
01962    return item;
01963 }
01964 
01965 //______________________________________________________________________________
01966 void TGListTree::RenameItem(TGListTreeItem *item, const char *string)
01967 {
01968    // Rename item in list tree.
01969 
01970    if (item) {
01971       item->Rename(string);
01972    }
01973 
01974    DoRedraw();
01975 }
01976 
01977 //______________________________________________________________________________
01978 Int_t TGListTree::DeleteItem(TGListTreeItem *item)
01979 {
01980    // Delete item from list tree.
01981 
01982    if (!fUserControlled)
01983       fCurrent = fBelowMouse = 0;
01984 
01985    PDeleteChildren(item);
01986    RemoveReference(item);
01987    PDeleteItem(item);
01988 
01989    fClient->NeedRedraw(this);
01990 
01991    return 1;
01992 }
01993 
01994 //______________________________________________________________________________
01995 void TGListTree::OpenItem(TGListTreeItem *item)
01996 {
01997    // Open item in list tree (i.e. show child items).
01998 
01999    if (item) {
02000       item->SetOpen(kTRUE);
02001       DoRedraw(); // force layout
02002       AdjustPosition(item);
02003    }
02004 }
02005 
02006 //______________________________________________________________________________
02007 void TGListTree::CloseItem(TGListTreeItem *item)
02008 {
02009    // Close item in list tree (i.e. hide child items).
02010 
02011    if (item) {
02012       item->SetOpen(kFALSE);
02013       DoRedraw(); // force layout
02014       AdjustPosition(item);
02015    }
02016 }
02017 
02018 //______________________________________________________________________________
02019 Int_t TGListTree::RecursiveDeleteItem(TGListTreeItem *item, void *ptr)
02020 {
02021    // Delete item with fUserData == ptr. Search tree downwards starting
02022    // at item.
02023 
02024    if (item && ptr) {
02025       if (item->GetUserData() == ptr) {
02026          DeleteItem(item);
02027       } else {
02028          if (item->IsOpen() && item->fFirstchild) {
02029             RecursiveDeleteItem(item->fFirstchild,  ptr);
02030          }
02031          RecursiveDeleteItem(item->fNextsibling, ptr);
02032       }
02033    }
02034    return 1;
02035 }
02036 
02037 //______________________________________________________________________________
02038 void TGListTree::SetToolTipItem(TGListTreeItem *item, const char *string)
02039 {
02040    // Set tooltip text for this item. By default an item for which the
02041    // userData is a pointer to an TObject the TObject::GetTitle() will
02042    // be used to get the tip text.
02043 
02044    if (item) {
02045       item->SetTipText(string);
02046    }
02047 }
02048 
02049 //______________________________________________________________________________
02050 Int_t TGListTree::DeleteChildren(TGListTreeItem *item)
02051 {
02052    // Delete children of item from list.
02053 
02054    if (!fUserControlled)
02055       fCurrent = fBelowMouse = 0;
02056 
02057    PDeleteChildren(item);
02058 
02059    DoRedraw();
02060 
02061    return 1;
02062 }
02063 
02064 //______________________________________________________________________________
02065 Int_t TGListTree::Reparent(TGListTreeItem *item, TGListTreeItem *newparent)
02066 {
02067    // Make newparent the new parent of item.
02068 
02069    // Remove the item from its old location.
02070    RemoveReference(item);
02071 
02072    // The item is now unattached. Reparent it.
02073    InsertChild(newparent, item);
02074 
02075    DoRedraw();
02076 
02077    return 1;
02078 }
02079 
02080 //______________________________________________________________________________
02081 Int_t TGListTree::ReparentChildren(TGListTreeItem *item,
02082                                  TGListTreeItem *newparent)
02083 {
02084    // Make newparent the new parent of the children of item.
02085 
02086    TGListTreeItem *first;
02087 
02088    if (item->fFirstchild) {
02089       first = item->fFirstchild;
02090       item->fFirstchild = 0;
02091 
02092       InsertChildren(newparent, first);
02093 
02094       DoRedraw();
02095       return 1;
02096    }
02097    return 0;
02098 }
02099 
02100 //______________________________________________________________________________
02101 extern "C"
02102 Int_t Compare(const void *item1, const void *item2)
02103 {
02104    return strcmp((*((TGListTreeItem **) item1))->GetText(),
02105                  (*((TGListTreeItem **) item2))->GetText());
02106 }
02107 
02108 //______________________________________________________________________________
02109 Int_t TGListTree::Sort(TGListTreeItem *item)
02110 {
02111    // Sort items starting with item.
02112 
02113    TGListTreeItem *first, *parent, **list;
02114    size_t i, count;
02115 
02116    // Get first child in list;
02117    while (item->fPrevsibling) item = item->fPrevsibling;
02118 
02119    first = item;
02120    parent = first->fParent;
02121 
02122    // Count the children
02123    count = 1;
02124    while (item->fNextsibling) item = item->fNextsibling, count++;
02125    if (count <= 1) return 1;
02126 
02127    list = new TGListTreeItem* [count];
02128    list[0] = first;
02129    count = 1;
02130    while (first->fNextsibling) {
02131       list[count] = first->fNextsibling;
02132       count++;
02133       first = first->fNextsibling;
02134    }
02135 
02136    ::qsort(list, count, sizeof(TGListTreeItem*), ::Compare);
02137 
02138    list[0]->fPrevsibling = 0;
02139    for (i = 0; i < count; i++) {
02140       if (i < count - 1)
02141          list[i]->fNextsibling = list[i + 1];
02142       if (i > 0)
02143          list[i]->fPrevsibling = list[i - 1];
02144    }
02145    list[count - 1]->fNextsibling = 0;
02146    if (parent) {
02147       parent->fFirstchild = list[0];
02148       parent->fLastchild  = list[count-1];
02149    }
02150    else {
02151       fFirst = list[0];
02152       fLast  = list[count-1];
02153    }
02154 
02155    delete [] list;
02156 
02157    DoRedraw();
02158 
02159    return 1;
02160 }
02161 
02162 //______________________________________________________________________________
02163 Int_t TGListTree::SortSiblings(TGListTreeItem *item)
02164 {
02165    // Sort siblings of item.
02166 
02167    return Sort(item);
02168 }
02169 
02170 //______________________________________________________________________________
02171 Int_t TGListTree::SortChildren(TGListTreeItem *item)
02172 {
02173    // Sort children of item.
02174 
02175    TGListTreeItem *first;
02176 
02177    if (item) {
02178       first = item->fFirstchild;
02179       if (first) {
02180          SortSiblings(first);
02181       }
02182    } else {
02183       if (fFirst) {
02184          first = fFirst->fFirstchild;
02185          if (first) {
02186             SortSiblings(first);
02187          }
02188       }
02189    }
02190    DoRedraw();
02191    return 1;
02192 }
02193 
02194 //______________________________________________________________________________
02195 TGListTreeItem *TGListTree::FindSiblingByName(TGListTreeItem *item, const char *name)
02196 {
02197    // Find sibling of item by name.
02198 
02199    // Get first child in list
02200    if (item) {
02201       while (item->fPrevsibling) {
02202          item = item->fPrevsibling;
02203       }
02204 
02205       while (item) {
02206          if (strcmp(item->GetText(), name) == 0) {
02207             return item;
02208          }
02209          item = item->fNextsibling;
02210       }
02211       return item;
02212    }
02213    return 0;
02214 }
02215 
02216 //______________________________________________________________________________
02217 TGListTreeItem *TGListTree::FindSiblingByData(TGListTreeItem *item, void *userData)
02218 {
02219    // Find sibling of item by userData.
02220 
02221    // Get first child in list
02222    if (item) {
02223       while (item->fPrevsibling) {
02224          item = item->fPrevsibling;
02225       }
02226 
02227       while (item) {
02228          if (item->GetUserData() == userData) {
02229             return item;
02230          }
02231          item = item->fNextsibling;
02232       }
02233       return item;
02234    }
02235    return 0;
02236 }
02237 
02238 //______________________________________________________________________________
02239 TGListTreeItem *TGListTree::FindChildByName(TGListTreeItem *item, const char *name)
02240 {
02241    // Find child of item by name.
02242 
02243    // Get first child in list
02244    if (item && item->fFirstchild) {
02245       item = item->fFirstchild;
02246    } else if (!item && fFirst) {
02247       item = fFirst;
02248    } else {
02249       item = 0;
02250    }
02251 
02252    while (item) {
02253       if (strcmp(item->GetText(), name) == 0) {
02254          return item;
02255       }
02256       item = item->fNextsibling;
02257    }
02258    return 0;
02259 }
02260 
02261 //______________________________________________________________________________
02262 TGListTreeItem *TGListTree::FindChildByData(TGListTreeItem *item, void *userData)
02263 {
02264    // Find child of item by userData.
02265 
02266    // Get first child in list
02267    if (item && item->fFirstchild) {
02268       item = item->fFirstchild;
02269    } else if (!item && fFirst) {
02270       item = fFirst;
02271    } else {
02272       item = 0;
02273    }
02274 
02275    while (item) {
02276       if (item->GetUserData() == userData) {
02277          return item;
02278       }
02279       item = item->fNextsibling;
02280    }
02281    return 0;
02282 }
02283 
02284 //______________________________________________________________________________
02285 TGListTreeItem *TGListTree::FindItemByPathname(const char *path)
02286 {
02287    // Find item by pathname. Pathname is in the form of /xx/yy/zz. If zz
02288    // in path /xx/yy is found it returns item, 0 otherwise.
02289 
02290    if (!path || !*path) return 0;
02291 
02292    const char *p = path, *s;
02293    char dirname[1024];
02294    TGListTreeItem *item = 0;
02295    item = FindChildByName(item, "/");
02296    TGListTreeItem *diritem = 0;
02297    TString fulldir;
02298 
02299 start:
02300    while (1) {
02301       while (*p && *p == '/') p++;
02302       if (!*p) break;
02303 
02304       s = strchr(p, '/');
02305 
02306       if (!s) {
02307          strlcpy(dirname, p, 1024);
02308       } else {
02309          strlcpy(dirname, p, (s-p)+1);
02310       }
02311 
02312       item = FindChildByName(item, dirname);
02313 
02314       if (!diritem && dirname[0]) {
02315          fulldir += "/";
02316          fulldir += dirname;
02317 
02318          if ((diritem=FindChildByName(0, fulldir.Data()))) {
02319             if (!s || !strlen(s)) return diritem;
02320             p = ++s;
02321             item = diritem;
02322             goto start;
02323          }
02324       }
02325 
02326       if (!s || !strlen(s)) return item;
02327       p = ++s;
02328    }
02329    return 0;
02330 }
02331 
02332 //______________________________________________________________________________
02333 void TGListTree::HighlightItem(TGListTreeItem *item)
02334 {
02335    // Highlight item.
02336 
02337    UnselectAll(kFALSE);
02338    HighlightItem(item, kTRUE, kFALSE);
02339    AdjustPosition(item);
02340 }
02341 
02342 //______________________________________________________________________________
02343 void TGListTree::ClearHighlighted()
02344 {
02345    // Un highlight items.
02346 
02347    UnselectAll(kFALSE);
02348 }
02349 
02350 //______________________________________________________________________________
02351 void TGListTree::GetPathnameFromItem(TGListTreeItem *item, char *path, Int_t depth)
02352 {
02353    // Get pathname from item. Use depth to limit path name to last
02354    // depth levels. By default depth is not limited.
02355 
02356    char tmppath[1024];
02357 
02358    *path = '\0';
02359    while (item) {
02360       snprintf(tmppath, 1023, "/%s%s", item->GetText(), path);
02361       strlcpy(path, tmppath, 1024);
02362       item = item->fParent;
02363       if (--depth == 0 && item) {
02364          snprintf(tmppath, 1023, "...%s", path);
02365          strlcpy(path, tmppath, 1024);
02366          return;
02367       }
02368    }
02369 }
02370 
02371 //______________________________________________________________________________
02372 Pixel_t TGListTree::GetGrayPixel()
02373 {
02374    // Return gray draw color in use.
02375 
02376    static Bool_t init = kFALSE;
02377    if (!init) {
02378       if (!gClient->GetColorByName("#808080", fgGrayPixel))
02379          fgGrayPixel = fgBlackPixel;
02380       init = kTRUE;
02381    }
02382    return fgGrayPixel;
02383 }
02384 
02385 //______________________________________________________________________________
02386 FontStruct_t TGListTree::GetDefaultFontStruct()
02387 {
02388    // Return default font structure in use.
02389 
02390    if (!fgDefaultFont)
02391       fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
02392    return fgDefaultFont->GetFontStruct();
02393 }
02394 
02395 //______________________________________________________________________________
02396 const TGGC &TGListTree::GetDrawGC()
02397 {
02398    // Return default graphics context in use.
02399 
02400    if (!fgDrawGC) {
02401       GCValues_t gcv;
02402 
02403       gcv.fMask = kGCLineStyle  | kGCLineWidth  | kGCFillStyle |
02404                   kGCForeground | kGCBackground | kGCFont;
02405       gcv.fLineStyle  = kLineSolid;
02406       gcv.fLineWidth  = 0;
02407       gcv.fFillStyle  = kFillSolid;
02408       gcv.fFont       = fgDefaultFont->GetFontHandle();
02409       gcv.fBackground = fgWhitePixel;
02410       gcv.fForeground = fgBlackPixel;
02411 
02412       fgDrawGC = gClient->GetGC(&gcv, kTRUE);
02413    }
02414    return *fgDrawGC;
02415 }
02416 
02417 //______________________________________________________________________________
02418 const TGGC &TGListTree::GetLineGC()
02419 {
02420    // Return graphics context in use for line drawing.
02421 
02422    if (!fgLineGC) {
02423       GCValues_t gcv;
02424 
02425       gcv.fMask = kGCLineStyle  | kGCLineWidth  | kGCFillStyle |
02426                   kGCForeground | kGCBackground | kGCFont;
02427       gcv.fLineStyle  = kLineOnOffDash;
02428       gcv.fLineWidth  = 0;
02429       gcv.fFillStyle  = kFillSolid;
02430       gcv.fFont       = fgDefaultFont->GetFontHandle();
02431       gcv.fBackground = fgWhitePixel;
02432       gcv.fForeground = GetGrayPixel();
02433 
02434       fgLineGC = gClient->GetGC(&gcv, kTRUE);
02435       fgLineGC->SetDashOffset(0);
02436       fgLineGC->SetDashList("\x1\x1", 2);
02437    }
02438    return *fgLineGC;
02439 }
02440 
02441 //______________________________________________________________________________
02442 const TGGC &TGListTree::GetHighlightGC()
02443 {
02444    // Return graphics context for highlighted frame background.
02445 
02446    if (!fgHighlightGC) {
02447       GCValues_t gcv;
02448 
02449       gcv.fMask = kGCLineStyle  | kGCLineWidth  | kGCFillStyle |
02450                   kGCForeground | kGCBackground | kGCFont;
02451       gcv.fLineStyle  = kLineSolid;
02452       gcv.fLineWidth  = 0;
02453       gcv.fFillStyle  = kFillSolid;
02454       gcv.fFont       = fgDefaultFont->GetFontHandle();
02455       gcv.fBackground = fgDefaultSelectedBackground;
02456       gcv.fForeground = fgWhitePixel;
02457 
02458       fgHighlightGC = gClient->GetGC(&gcv, kTRUE);
02459    }
02460    return *fgHighlightGC;
02461 }
02462 
02463 //______________________________________________________________________________
02464 const TGGC &TGListTree::GetColorGC()
02465 {
02466    // Return graphics context for highlighted frame background.
02467 
02468    if (!fgColorGC) {
02469       GCValues_t gcv;
02470 
02471       gcv.fMask = kGCLineStyle  | kGCLineWidth  | kGCFillStyle |
02472                   kGCForeground | kGCBackground;
02473       gcv.fLineStyle  = kLineSolid;
02474       gcv.fLineWidth  = 1;
02475       gcv.fFillStyle  = kFillSolid;
02476       gcv.fBackground = fgDefaultSelectedBackground;
02477       gcv.fForeground = fgWhitePixel;
02478 
02479       fgColorGC = gClient->GetGC(&gcv, kTRUE);
02480    }
02481    return *fgColorGC;
02482 }
02483 
02484 //______________________________________________________________________________
02485 const TGPicture *TGListTree::GetOpenPic()
02486 {
02487    // Returns the icon used by items in open state.
02488 
02489    if (!fgOpenPic)
02490       fgOpenPic = gClient->GetPicture("ofolder_t.xpm");
02491    ((TGPicture *)fgOpenPic)->AddReference();
02492    return fgOpenPic;
02493 }
02494 
02495 //______________________________________________________________________________
02496 const TGPicture *TGListTree::GetClosedPic()
02497 {
02498    // Returns the icon used by items in closed state.
02499 
02500    if (!fgClosedPic)
02501       fgClosedPic = gClient->GetPicture("folder_t.xpm");
02502    ((TGPicture *)fgClosedPic)->AddReference();
02503    return fgClosedPic;
02504 }
02505 
02506 //______________________________________________________________________________
02507 const TGPicture *TGListTree::GetCheckedPic()
02508 {
02509    // Returns the icon used for checked checkbox.
02510 
02511    if (!fgCheckedPic)
02512       fgCheckedPic = gClient->GetPicture("checked_t.xpm");
02513    ((TGPicture *)fgCheckedPic)->AddReference();
02514    return fgCheckedPic;
02515 }
02516 
02517 //______________________________________________________________________________
02518 const TGPicture *TGListTree::GetUncheckedPic()
02519 {
02520    // Returns the icon used for unchecked checkbox.
02521 
02522    if (!fgUncheckedPic)
02523       fgUncheckedPic = gClient->GetPicture("unchecked_t.xpm");
02524    ((TGPicture *)fgUncheckedPic)->AddReference();
02525    return fgUncheckedPic;
02526 }
02527 
02528 //______________________________________________________________________________
02529 void TGListTree::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
02530 {
02531    // Save a list tree widget as a C++ statements on output stream out.
02532 
02533    if (fBackground != GetWhitePixel()) SaveUserColor(out, option);
02534 
02535    out << endl << "   // list tree" << endl;
02536    out << "   TGListTree *";
02537 
02538    if ((fParent->GetParent())->InheritsFrom(TGCanvas::Class())) {
02539       out << GetName() << " = new TGListTree(" << GetCanvas()->GetName();
02540    } else {
02541       out << GetName() << " = new TGListTree(" << fParent->GetName();
02542       out << "," << GetWidth() << "," << GetHeight();
02543    }
02544 
02545    if (fBackground == GetWhitePixel()) {
02546       if (GetOptions() == kSunkenFrame) {
02547          out <<");" << endl;
02548       } else {
02549          out << "," << GetOptionString() <<");" << endl;
02550       }
02551    } else {
02552       out << "," << GetOptionString() << ",ucolor);" << endl;
02553    }
02554    if (option && strstr(option, "keep_names"))
02555       out << "   " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
02556 
02557    out << endl;
02558 
02559    static Int_t n = 0;
02560 
02561    TGListTreeItem *current;
02562    current = GetFirstItem();
02563 
02564    out << "   const TGPicture *popen;       //used for list tree items" << endl;
02565    out << "   const TGPicture *pclose;      //used for list tree items" << endl;
02566    out << endl;
02567 
02568    while (current) {
02569       out << "   TGListTreeItem *item" << n << " = " << GetName() << "->AddItem(";
02570       current->SavePrimitive(out, TString::Format("%d",n), n);
02571       if (current->IsOpen())
02572          out << "   " << GetName() << "->OpenItem(item" << n << ");" << endl;
02573       else
02574          out << "   " << GetName() << "->CloseItem(item" << n << ");" << endl;
02575 
02576       if (current == fSelected)
02577          out << "   " << GetName() << "->SetSelected(item" << n << ");" << endl;
02578 
02579       n++;
02580       if (current->fFirstchild) {
02581          SaveChildren(out, current->fFirstchild, n);
02582       }
02583       current = current->fNextsibling;
02584    }
02585 
02586    out << endl;
02587 }
02588 
02589 //______________________________________________________________________________
02590 void TGListTree::SaveChildren(ostream &out, TGListTreeItem *item, Int_t &n)
02591 {
02592    // Save child items as a C++ statements on output stream out.
02593 
02594    Int_t p = n-1;
02595    while (item) {
02596       out << "   TGListTreeItem *item" << n << " = " << GetName() << "->AddItem(";
02597       item->SavePrimitive(out, TString::Format("%d",p),n);
02598       n++;
02599       if (item->fFirstchild) {
02600          SaveChildren(out, item->fFirstchild, n);
02601       }
02602       item = item->fNextsibling;
02603    }
02604 }
02605 
02606 //______________________________________________________________________________
02607 void TGListTreeItemStd::SavePrimitive(ostream &out, Option_t *option, Int_t n)
02608 {
02609    // Save a list tree item attributes as a C++ statements on output stream.
02610 
02611    static const TGPicture *oldopen=0;
02612    static const TGPicture *oldclose=0;
02613    static const TGPicture *oldcheck=0;
02614    static const TGPicture *olduncheck=0;
02615    static Bool_t makecheck = kTRUE;
02616    static Bool_t makeuncheck = kTRUE;
02617    static Color_t oldcolor = -1;
02618 
02619    char quote = '"';
02620    TString s = TString::Format("%d", n);
02621 
02622    if (!fParent)
02623       out << "NULL,";
02624    else
02625       out << "item" << option << ",";
02626    TString text = GetText();
02627    text.ReplaceAll('\\', "\\\\");
02628    text.ReplaceAll("\"", "\\\"");
02629    out << quote << text << quote;
02630    out << ");" << endl;
02631 
02632    if (oldopen != fOpenPic) {
02633       oldopen = fOpenPic;
02634       out << "   popen = gClient->GetPicture(" << quote
02635           << gSystem->ExpandPathName(gSystem->UnixPathName(fOpenPic->GetName()))
02636           << quote << ");" << endl;
02637    }
02638    if (oldclose != fClosedPic) {
02639       oldclose = fClosedPic;
02640       out << "   pclose = gClient->GetPicture(" << quote
02641           << gSystem->ExpandPathName(gSystem->UnixPathName(fClosedPic->GetName()))
02642           << quote << ");" << endl;
02643    }
02644    out << "   item" << s.Data() << "->SetPictures(popen, pclose);" << endl;
02645    if (HasCheckBox()) {
02646       if (fCheckedPic && makecheck) {
02647          out << "   const TGPicture *pcheck;        //used for checked items" << endl;
02648          makecheck = kFALSE;
02649       }
02650       if (fUncheckedPic && makeuncheck) {
02651          out << "   const TGPicture *puncheck;      //used for unchecked items" << endl;
02652          makeuncheck = kFALSE;
02653       }
02654       out << "   item" << s.Data() << "->CheckItem();" << endl;
02655       if (fCheckedPic && oldcheck != fCheckedPic) {
02656          oldcheck = fCheckedPic;
02657          out << "   pcheck = gClient->GetPicture(" << quote
02658              << gSystem->ExpandPathName(gSystem->UnixPathName(fCheckedPic->GetName()))
02659              << quote << ");" << endl;
02660       }
02661       if (fUncheckedPic && olduncheck != fUncheckedPic) {
02662          olduncheck = fUncheckedPic;
02663          out << "   puncheck = gClient->GetPicture(" << quote
02664              << gSystem->ExpandPathName(gSystem->UnixPathName(fUncheckedPic->GetName()))
02665              << quote << ");" << endl;
02666       }
02667       out << "   item" << s.Data() << "->SetCheckBoxPictures(pcheck, puncheck);" << endl;
02668       out << "   item" << s.Data() << "->SetCheckBox(kTRUE);" << endl;
02669    }
02670    if (fHasColor) {
02671       if (oldcolor != fColor) {
02672          oldcolor = fColor;
02673          out << "   item" << s.Data() << "->SetColor(" << fColor << ");" << endl;
02674       }
02675    }
02676    if (fTipText.Length() > 0) {
02677       TString tiptext = GetTipText();
02678       tiptext.ReplaceAll('\\', "\\\\");
02679       tiptext.ReplaceAll("\n", "\\n");
02680       tiptext.ReplaceAll("\"", "\\\"");
02681       out << "   item" << s.Data() << "->SetTipText(" << quote
02682           << tiptext << quote << ");" << endl;
02683    }
02684 
02685 }
02686 
02687 //______________________________________________________________________________
02688 void TGListTree::CheckItem(TGListTreeItem *item, Bool_t check)
02689 {
02690    // Set check button state for the node 'item'.
02691 
02692    item->CheckItem(check);
02693 }
02694 
02695 //______________________________________________________________________________
02696 void TGListTree::SetCheckBox(TGListTreeItem *item, Bool_t on)
02697 {
02698    // Set check button state for the node 'item'.
02699 
02700    item->SetCheckBox(on);
02701 }
02702 
02703 //______________________________________________________________________________
02704 void TGListTree::ToggleItem(TGListTreeItem *item)
02705 {
02706    // Toggle check button state of the node 'item'.
02707 
02708    item->Toggle();
02709 }
02710 
02711 //______________________________________________________________________________
02712 void TGListTree::UpdateChecked(TGListTreeItem *item, Bool_t redraw)
02713 {
02714    // Update the state of the node 'item' according to the children states.
02715 
02716    if (fAutoCheckBoxPic == kFALSE) return;
02717 
02718    TGListTreeItem *parent;
02719    TGListTreeItem *current;
02720    current = item->GetFirstChild();
02721    parent  = current ? current : item;
02722    // recursively check parent/children status
02723    while (parent && parent->HasCheckBox()) {
02724       if ((!parent->IsChecked() && parent->HasCheckedChild(kTRUE)) ||
02725           (parent->IsChecked() && parent->HasUnCheckedChild(kTRUE))) {
02726          parent->SetCheckBoxPictures(fClient->GetPicture("checked_dis_t.xpm"),
02727                                      fClient->GetPicture("unchecked_dis_t.xpm"));
02728       }
02729       else {
02730          parent->SetCheckBoxPictures(fClient->GetPicture("checked_t.xpm"),
02731                                      fClient->GetPicture("unchecked_t.xpm"));
02732       }
02733       parent = parent->GetParent();
02734       if (parent && fCheckMode == kRecursive) {
02735          if (!parent->IsChecked() && parent->GetFirstChild() && 
02736              !parent->GetFirstChild()->HasUnCheckedChild()) {
02737             parent->SetCheckBoxPictures(fClient->GetPicture("checked_t.xpm"),
02738                                         fClient->GetPicture("unchecked_t.xpm"));
02739             parent->CheckItem(kTRUE);
02740          }
02741          else if (parent->IsChecked() && parent->GetFirstChild() && 
02742                   !parent->GetFirstChild()->HasCheckedChild()) {
02743             parent->SetCheckBoxPictures(fClient->GetPicture("checked_t.xpm"),
02744                                         fClient->GetPicture("unchecked_t.xpm"));
02745             parent->CheckItem(kFALSE);
02746          }
02747       }
02748    }
02749    if (redraw) {
02750       ClearViewPort();
02751    }
02752 }
02753 
02754 //______________________________________________________________________________
02755 TGListTreeItem *TGListTree::FindItemByObj(TGListTreeItem *item, void *ptr)
02756 {
02757    // Find item with fUserData == ptr. Search tree downwards starting
02758    // at item.
02759 
02760    TGListTreeItem *fitem;
02761    if (item && ptr) {
02762       if (item->GetUserData() == ptr)
02763          return item;
02764       else {
02765          if (item->fFirstchild) {
02766             fitem = FindItemByObj(item->fFirstchild,  ptr);
02767             if (fitem) return fitem;
02768          }
02769          return FindItemByObj(item->fNextsibling, ptr);
02770       }
02771    }
02772    return 0;
02773 }
02774 
02775 //______________________________________________________________________________
02776 void TGListTree::GetChecked(TList *checked)
02777 {
02778    // Add all checked list tree items of this list tree into 
02779    // the list 'checked'. This list is not adopted and must
02780    // be deleted by the user later.
02781    
02782    if (!checked || !fFirst) return;
02783    TGListTreeItem *current = fFirst;
02784    if (current->IsChecked()) {
02785       checked->Add(new TObjString(current->GetText()));
02786    }
02787    while(current) {
02788       if (current->GetFirstChild())
02789          GetCheckedChildren(checked, current->GetFirstChild());
02790       current = current->GetNextSibling();
02791    }
02792 }
02793 
02794 //______________________________________________________________________________
02795 void TGListTree::GetCheckedChildren(TList *checked, TGListTreeItem *item)
02796 {
02797    // Add all child items of 'item' into the list 'checked'.
02798 
02799    if (!checked || !item) return;
02800 
02801    while (item) {
02802       if (item->IsChecked()) {
02803          checked->Add(new TObjString(item->GetText()));
02804       }
02805       if (item->GetFirstChild()) {
02806          GetCheckedChildren(checked, item->GetFirstChild());
02807       }
02808       item = item->GetNextSibling();
02809    }
02810 }
02811 
02812 //______________________________________________________________________________
02813 void TGListTree::CheckAllChildren(TGListTreeItem *item, Bool_t state)
02814 {
02815    // Check all child items of 'item' and 'item' itself according
02816    // to the state value: kTRUE means check all, kFALSE - uncheck all.
02817    
02818    if (item) 
02819       item->CheckAllChildren(state);
02820 }
02821 

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