#include <stdlib.h>
#include "TROOT.h"
#include "TGListTree.h"
#include "TGPicture.h"
#include "TGCanvas.h"
#include "TGScrollBar.h"
#include "TGToolTip.h"
#include "KeySymbols.h"
#include "TGTextEditDialogs.h"
#include "TGResourcePool.h"
#include "TGMsgBox.h"
#include "TError.h"
#include "TColor.h"
#include "TSystem.h"
#include "TString.h"
#include "TObjString.h"
#include "TGDNDManager.h"
#include "TBufferFile.h"
#include "Riostream.h"
Pixel_t          TGListTree::fgGrayPixel = 0;
const TGFont    *TGListTree::fgDefaultFont = 0;
TGGC            *TGListTree::fgDrawGC = 0;
TGGC            *TGListTree::fgLineGC = 0;
TGGC            *TGListTree::fgHighlightGC = 0;
TGGC            *TGListTree::fgColorGC = 0;
const TGPicture *TGListTree::fgOpenPic = 0;
const TGPicture *TGListTree::fgClosedPic = 0;
const TGPicture *TGListTree::fgCheckedPic = 0;
const TGPicture *TGListTree::fgUncheckedPic = 0;
ClassImp(TGListTreeItem)
ClassImp(TGListTreeItemStd)
ClassImp(TGListTree)
TGListTreeItem::TGListTreeItem(TGClient *client) :
   fClient(client),
   fParent    (0), fFirstchild(0), fLastchild (0), fPrevsibling(0), 
   fNextsibling(0),fOpen (kFALSE), fDNDState  (0),
   fY         (0), fXtext     (0), fYtext(0), fHeight(0)
{
   
}
UInt_t TGListTreeItem::GetPicWidth() const
{
   
   return GetPicture()->GetWidth();
}
TGListTreeItemStd::TGListTreeItemStd(TGClient *client, const char *name,
                                     const TGPicture *opened,
                                     const TGPicture *closed,
                                     Bool_t checkbox) :
   TGListTreeItem(client)
{
   
   fText = name;
   fCheckBox = checkbox;
   fChecked = kTRUE;
   if (!opened)
      opened = TGListTree::GetOpenPic();
   else
      ((TGPicture *)opened)->AddReference();
   if (!closed)
      closed = TGListTree::GetClosedPic();
   else
      ((TGPicture *)closed)->AddReference();
   fOpenPic   = opened;
   fClosedPic = closed;
   fCheckedPic   = TGListTree::GetCheckedPic();
   fUncheckedPic = TGListTree::GetUncheckedPic();
   fActive = kFALSE;
   fOwnsData = kFALSE;
   fUserData = 0;
   fHasColor = kFALSE;
   fColor = 0;
   fDNDState = 0;
}
TGListTreeItemStd::~TGListTreeItemStd()
{
   
   if (fOwnsData && fUserData) {
      TObject *obj = static_cast<TObject *>(fUserData);
      delete dynamic_cast<TObject *>(obj);
   }
   fClient->FreePicture(fOpenPic);
   fClient->FreePicture(fClosedPic);
   fClient->FreePicture(fCheckedPic);
   fClient->FreePicture(fUncheckedPic);
}
Pixel_t TGListTreeItemStd::GetActiveColor() const
{
   
   return TGFrame::GetDefaultSelectedBackground();
}
Bool_t TGListTreeItemStd::HasCheckedChild(Bool_t first)
{
   
   TGListTreeItem *item = this;
   while (item) {
      if (item->IsChecked()) {
         return kTRUE;
      }
      if (item->GetFirstChild()) {
         if (item->GetFirstChild()->HasCheckedChild())
            return kTRUE;
      }
      if (!first)
         item = item->GetNextSibling();
      else
         break;
   }
   return kFALSE;
}
Bool_t TGListTreeItemStd::HasUnCheckedChild(Bool_t first)
{
   
   TGListTreeItem *item = this;
   while (item) {
      if (!item->IsChecked()) {
         return kTRUE;
      }
      if (item->GetFirstChild()) {
         if (item->GetFirstChild()->HasUnCheckedChild())
            return kTRUE;
      }
      if (!first)
         item = item->GetNextSibling();
      else
         break;
   }
   return kFALSE;
}
void TGListTreeItemStd::UpdateState()
{
   
   if ((!fChecked && HasCheckedChild(kTRUE)) ||
       (fChecked && HasUnCheckedChild(kTRUE))) {
      SetCheckBoxPictures(gClient->GetPicture("checked_dis_t.xpm"),
                          gClient->GetPicture("unchecked_dis_t.xpm"));
   }
   else {
      SetCheckBoxPictures(gClient->GetPicture("checked_t.xpm"),
                          gClient->GetPicture("unchecked_t.xpm"));
   }
}
void TGListTreeItemStd::CheckAllChildren(Bool_t state)
{
   
   
   
   if (state) {
      if (!IsChecked())
         CheckItem();
   } else {
      if (IsChecked())
         Toggle();
   }
   CheckChildren(GetFirstChild(), state);
   UpdateState();   
}
void TGListTreeItemStd::CheckChildren(TGListTreeItem *item, Bool_t state)
{
   
   
   if (!item) return;
   while (item) {
      if (state){
         if (!item->IsChecked())
            item->CheckItem();
      } else {
         if (item->IsChecked())
            item->Toggle();
      }
      if (item->GetFirstChild()) {
         CheckChildren(item->GetFirstChild(), state);
      }
      item->UpdateState();   
      item = item->GetNextSibling();
   }
}
void TGListTreeItemStd::SetCheckBox(Bool_t on)
{
   
   fCheckBox = on;
}
void TGListTreeItemStd::SetCheckBoxPictures(const TGPicture *checked,
                                         const TGPicture *unchecked)
{
   
   fClient->FreePicture(fCheckedPic);
   fClient->FreePicture(fUncheckedPic);
   if (!checked) {
         ::Warning("TGListTreeItem::SetCheckBoxPictures", "checked picture not specified, defaulting to checked_t");
         checked = fClient->GetPicture("checked_t.xpm");
   } else
      ((TGPicture *)checked)->AddReference();
   if (!unchecked) {
         ::Warning("TGListTreeItem::SetCheckBoxPictures", "unchecked picture not specified, defaulting to unchecked_t");
         unchecked = fClient->GetPicture("unchecked_t.xpm");
   } else
      ((TGPicture *)unchecked)->AddReference();
   fCheckedPic   = checked;
   fUncheckedPic = unchecked;
}
void TGListTreeItemStd::SetPictures(const TGPicture *opened, const TGPicture *closed)
{
   
   fClient->FreePicture(fOpenPic);
   fClient->FreePicture(fClosedPic);
   if (!opened) {
      ::Warning("TGListTreeItem::SetPictures", "opened picture not specified, defaulting to ofolder_t");
      opened = fClient->GetPicture("ofolder_t.xpm");
   } else
      ((TGPicture *)opened)->AddReference();
   if (!closed) {
      ::Warning("TGListTreeItem::SetPictures", "closed picture not specified, defaulting to folder_t");
      closed = fClient->GetPicture("folder_t.xpm");
   } else
      ((TGPicture *)closed)->AddReference();
   fOpenPic   = opened;
   fClosedPic = closed;
}
TGListTree::TGListTree(TGWindow *p, UInt_t w, UInt_t h, UInt_t options,
                       ULong_t back) :
   TGContainer(p, w, h, options, back)
{
   
   fMsgWindow   = p;
   fCanvas      = 0;
   fTip         = 0;
   fTipItem     = 0;
   fAutoTips    = kFALSE;
   fAutoCheckBoxPic = kTRUE;
   fDisableOpen = kFALSE;
   fBdown       = kFALSE;
   fUserControlled = kFALSE;
   fEventHandled   = kFALSE;
   fGrayPixel   = GetGrayPixel();
   fFont        = GetDefaultFontStruct();
   fDrawGC      = GetDrawGC()();
   fLineGC      = GetLineGC()();
   fHighlightGC = GetHighlightGC()();
   fColorGC     = GetColorGC()();
   fFirst = fLast = fSelected = fCurrent = fBelowMouse = 0;
   fDefw = fDefh = 1;
   fHspacing = 2;
   fVspacing = 2;  
   fIndent   = 3;  
   fMargin   = 2;
   fXDND = fYDND = 0;
   fDNDData.fData = 0;
   fDNDData.fDataLength = 0;
   fDNDData.fDataType = 0;
   fBuf = 0;
   fColorMode = kDefault;
   fCheckMode = kSimple;
   if (fCanvas) fCanvas->GetVScrollbar()->SetSmallIncrement(20);
   gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
                         kButtonPressMask | kButtonReleaseMask,
                         kNone, kNone);
   AddInput(kPointerMotionMask | kEnterWindowMask |
            kLeaveWindowMask | kKeyPressMask);
   SetWindowName();
   fDNDTypeList = new Atom_t[3];
   fDNDTypeList[0] = gVirtualX->InternAtom("application/root", kFALSE);
   fDNDTypeList[1] = gVirtualX->InternAtom("text/uri-list", kFALSE);
   fDNDTypeList[2] = 0;
   gVirtualX->SetDNDAware(fId, fDNDTypeList);
   SetDNDTarget(kTRUE);
   fEditDisabled = kEditDisable | kEditDisableGrab | kEditDisableBtnEnable;
}
TGListTree::TGListTree(TGCanvas *p,UInt_t options,ULong_t back) :
   TGContainer(p, options, back)
{
   
   fMsgWindow   = p;
   fTip         = 0;
   fTipItem     = 0;
   fAutoTips    = kFALSE;
   fAutoCheckBoxPic = kTRUE;
   fDisableOpen = kFALSE;
   fBdown       = kFALSE;
   fUserControlled = kFALSE;
   fEventHandled   = kFALSE;
   fGrayPixel   = GetGrayPixel();
   fFont        = GetDefaultFontStruct();
   fDrawGC      = GetDrawGC()();
   fLineGC      = GetLineGC()();
   fHighlightGC = GetHighlightGC()();
   fColorGC     = GetColorGC()();
   fFirst = fLast = fSelected = fCurrent = fBelowMouse = 0;
   fDefw = fDefh = 1;
   fHspacing = 2;
   fVspacing = 2;  
   fIndent   = 3;  
   fMargin   = 2;
   fXDND = fYDND = 0;
   fDNDData.fData = 0;
   fDNDData.fDataLength = 0;
   fDNDData.fDataType = 0;
   fBuf = 0;
   fColorMode = kDefault;
   fCheckMode = kSimple;
   if (fCanvas) fCanvas->GetVScrollbar()->SetSmallIncrement(20);
   gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
                         kButtonPressMask | kButtonReleaseMask,
                         kNone, kNone);
   AddInput(kPointerMotionMask | kEnterWindowMask |
            kLeaveWindowMask | kKeyPressMask);
   SetWindowName();
   fDNDTypeList = new Atom_t[3];
   fDNDTypeList[0] = gVirtualX->InternAtom("application/root", kFALSE);
   fDNDTypeList[1] = gVirtualX->InternAtom("text/uri-list", kFALSE);
   fDNDTypeList[2] = 0;
   gVirtualX->SetDNDAware(fId, fDNDTypeList);
   SetDNDTarget(kTRUE);
   fEditDisabled = kEditDisable | kEditDisableGrab | kEditDisableBtnEnable;
}
TGListTree::~TGListTree()
{
   
   TGListTreeItem *item, *sibling;
   delete [] fDNDTypeList;
   delete fTip;
   item = fFirst;
   while (item) {
      if (item->fFirstchild) {
         PDeleteChildren(item->fFirstchild);
      }
      sibling = item->fNextsibling;
      delete item;
      item = sibling;
   }
}
Int_t TGListTree::FontHeight()
{
   
   if (!fgDefaultFont)
      fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
   return fgDefaultFont->TextHeight();
}
Int_t TGListTree::FontAscent()
{
   
   FontMetrics_t m;
   if (!fgDefaultFont)
      fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
   fgDefaultFont->GetFontMetrics(&m);
   return m.fAscent;
}
Int_t TGListTree::TextWidth(const char *c)
{
   
   if (!fgDefaultFont)
      fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
   return fgDefaultFont->TextWidth(c);
}
void TGListTree::HighlightItem(TGListTreeItem *item, Bool_t state, Bool_t draw)
{
   
   if (item) {
      if ((item == fSelected) && !state) {
         fSelected = 0;
         if (draw) DrawItemName(fId, item);
      } else if (state != item->IsActive()) { 
         item->SetActive(state);
         if (draw) DrawItemName(fId, item);
      }
   }
}
void TGListTree::HighlightChildren(TGListTreeItem *item, Bool_t state, Bool_t draw)
{
   
   while (item) {
      HighlightItem(item, state, draw);
      if (item->fFirstchild)
         HighlightChildren(item->fFirstchild, state, (item->IsOpen()) ? draw : kFALSE);
      item = item->fNextsibling;
   }
}
void TGListTree::UnselectAll(Bool_t draw)
{
   
   ClearViewPort();
   HighlightChildren(fFirst, kFALSE, draw);
}
Bool_t TGListTree::HandleButton(Event_t *event)
{
   
   TGListTreeItem *item;
   if (fTip) fTip->Hide();
   Int_t page = 0;
   if (event->fCode == kButton4 || event->fCode == kButton5) {
      if (!fCanvas) return kTRUE;
      if (fCanvas->GetContainer()->GetHeight()) {
         
         Int_t r = fCanvas->GetViewPort()->GetHeight() / 5;
         page = TMath::Min(r, 90);
      }
   }
   if (event->fCode == kButton4) {
      
      Int_t newpos = fCanvas->GetVsbPosition() - page;
      if (newpos < 0) newpos = 0;
      fCanvas->SetVsbPosition(newpos);
      return kTRUE;
   }
   if (event->fCode == kButton5) {
      
      Int_t newpos = fCanvas->GetVsbPosition() + page;
      fCanvas->SetVsbPosition(newpos);
      return kTRUE;
   }
   if (event->fType == kButtonPress) {
      if ((item = FindItem(event->fY)) != 0) {
         if (event->fCode == kButton1) {
            Int_t minx, maxx;
            Int_t minxchk = 0, maxxchk = 0;
            if (item->HasCheckBox()) {
               minxchk = (item->fXtext - item->GetCheckBoxPicture()->GetWidth());
               maxxchk = (item->fXtext - 4);
               maxx = maxxchk - Int_t(item->GetPicWidth()) - 8;
               minx = minxchk - Int_t(item->GetPicWidth()) - 16;
            }
            else {
               maxx = (item->fXtext - Int_t(item->GetPicWidth())) - 8;
               minx = (item->fXtext - Int_t(item->GetPicWidth())) - 16;
            }
            if ((item->HasCheckBox()) && (event->fX < maxxchk) &&
               (event->fX > minxchk))
            {
               ToggleItem(item);
               if (fCheckMode == kRecursive) {
                  CheckAllChildren(item, item->IsChecked());
               }
               UpdateChecked(item, kTRUE);
               Checked((TObject *)item->GetUserData(), item->IsChecked());
               return kTRUE;
            }
            if ((event->fX < maxx) && (event->fX > minx)) {
               item->SetOpen(!item->IsOpen());
               ClearViewPort();
               return kTRUE;
            }
         }
         
         if (event->fCode == kButton1) {
            fXDND = event->fX;
            fYDND = event->fY;
            fBdown = kTRUE;
         }
         if (!fUserControlled) {
            if (fSelected) fSelected->SetActive(kFALSE);
            UnselectAll(kTRUE);
            
            fCurrent = fSelected = item;
            HighlightItem(item, kTRUE, kTRUE);
            SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_ITEMCLICK),
                        event->fCode, (event->fYRoot << 16) | event->fXRoot);
         }
         else {
            fCurrent = fSelected = item;
            ClearViewPort();
         }
         Clicked(item, event->fCode);
         Clicked(item, event->fCode, event->fXRoot, event->fYRoot);
         Clicked(item, event->fCode, event->fState, event->fXRoot, event->fYRoot);
      }
   }
   if (event->fType == kButtonRelease) {
      fBdown = kFALSE;
   }
   return kTRUE;
}
Bool_t TGListTree::HandleDoubleClick(Event_t *event)
{
   
   TGListTreeItem *item = 0;
   if (event->fCode == kButton4 || event->fCode == kButton5) {
      return kFALSE;
   }
   
   
   if (fDisableOpen && event->fCode == kButton1 && (item = FindItem(event->fY)) != 0) {
      SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_ITEMDBLCLICK),
                  event->fCode, (event->fYRoot << 16) | event->fXRoot);
      DoubleClicked(item, event->fCode);
      DoubleClicked(item, event->fCode, event->fXRoot, event->fYRoot);
      return kTRUE;
   }
   item = FindItem(event->fY);
   
   if (event->fCode == kButton1 && item) {
      ClearViewPort();
      item->SetOpen(!item->IsOpen());
      if (!fUserControlled) {
         if (item != fSelected) { 
            if (fSelected) fSelected->SetActive(kFALSE); 
            UnselectAll(kTRUE);
            HighlightItem(item, kTRUE, kTRUE);
         }
      }
      SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_ITEMDBLCLICK),
                  event->fCode, (event->fYRoot << 16) | event->fXRoot);
      DoubleClicked(item, event->fCode);
      DoubleClicked(item, event->fCode, event->fXRoot, event->fYRoot);
   }
   if (!fUserControlled)
      fSelected = item;
   return kTRUE;
}
Bool_t TGListTree::HandleCrossing(Event_t *event)
{
   
   if (event->fType == kLeaveNotify) {
      if (fTip) {
         fTip->Hide();
         fTipItem = 0;
      }
      if (!fUserControlled) {
         if (fCurrent)
            DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
         if (fBelowMouse)
            DrawOutline(fId, fBelowMouse, 0xffffff, kTRUE);
         fCurrent = 0;
      }
      if (fBelowMouse) {
         fBelowMouse = 0;
         MouseOver(0);
         MouseOver(0, event->fState);
      }
   }
   return kTRUE;
}
Atom_t TGListTree::HandleDNDPosition(Int_t , Int_t y, Atom_t action,
                                      Int_t , Int_t )
{
   
   static TGListTreeItem *olditem = 0;
   TGListTreeItem *item;
   if ((item = FindItem(y)) != 0) {
      if (item->IsDNDTarget()) {
         fDropItem = item;
         if (olditem)
            HighlightItem(olditem, kFALSE, kTRUE);
         HighlightItem(item, kTRUE, kTRUE);
         olditem = item;
         return action;
      }
   }
   fDropItem = 0;
   if (olditem) {
      HighlightItem(olditem, kFALSE, kTRUE);
      olditem = 0;
   }
   return kNone;
}
Atom_t TGListTree::HandleDNDEnter(Atom_t *typelist)
{
   
   Atom_t ret = kNone;
   for (int i = 0; typelist[i] != kNone; ++i) {
      if (typelist[i] == fDNDTypeList[0])
         ret = fDNDTypeList[0];
      if (typelist[i] == fDNDTypeList[1])
         ret = fDNDTypeList[1];
   }
   return ret;
}
Bool_t TGListTree::HandleDNDLeave()
{
   
   return kTRUE;
}
Bool_t TGListTree::HandleDNDDrop(TDNDData *data)
{
   
   DataDropped(fDropItem, data);
   HighlightItem(fDropItem, kFALSE, kTRUE);
   
   return kTRUE;
}
void TGListTree::DataDropped(TGListTreeItem *item, TDNDData *data)
{
   
   Long_t args[2];
   args[0] = (Long_t)item;
   args[1] = (Long_t)data;
   Emit("DataDropped(TGListTreeItem*,TDNDData*)", args);
}
Bool_t TGListTree::HandleMotion(Event_t *event)
{
   
   
   TGListTreeItem *item;
   TGPosition pos = GetPagePosition();
   if (gDNDManager->IsDragging()) {
      gDNDManager->Drag(event->fXRoot, event->fYRoot,
                        TGDNDManager::GetDNDActionCopy(), event->fTime);
   } else if ((item = FindItem(event->fY)) != 0) {
      if (!fUserControlled) {
         if (fCurrent)
            DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
         if (fBelowMouse)
            DrawOutline(fId, fBelowMouse, 0xffffff, kTRUE);
         DrawOutline(fId, item);
         fCurrent = item;
      }
      if (item != fBelowMouse) {
         fBelowMouse = item;
         MouseOver(fBelowMouse);
         MouseOver(fBelowMouse, event->fState);
      }
      if (item->HasCheckBox()) {
         if ((event->fX < (item->fXtext - 4) &&
             (event->fX > (item->fXtext - (Int_t)item->GetCheckBoxPicture()->GetWidth()))))
         {
            gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kPointer));
            return kTRUE;
         }
         else {
            gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kHand));
         }
      }
      if (!gDNDManager->IsDragging()) {
         if (fBdown && ((abs(event->fX - fXDND) > 2) || (abs(event->fY - fYDND) > 2))) {
            if (gDNDManager && item->IsDNDSource()) {
               if (!fBuf) fBuf = new TBufferFile(TBuffer::kWrite);
               fBuf->Reset();
               
               
               if (item->GetUserData()) {
                  TObject *obj = static_cast<TObject *>(item->GetUserData());
                  if (dynamic_cast<TObject *>(obj)) {
                     TObjString *ostr = dynamic_cast<TObjString *>(obj);
                     if (ostr) {
                        TString& str = ostr->String();
                        if (str.BeginsWith("file://")) {
                           fDNDData.fDataType = fDNDTypeList[1];
                           fDNDData.fData = (void *)strdup(str.Data());
                           fDNDData.fDataLength = str.Length()+1;
                        }
                     }
                     else {
                        fDNDData.fDataType = fDNDTypeList[0];
                        fBuf->WriteObject((TObject *)item->GetUserData());
                        fDNDData.fData = fBuf->Buffer();
                        fDNDData.fDataLength = fBuf->Length();
                     }
                  }
               }
               else {
                  fDNDData.fDataType = fDNDTypeList[1];
                  TString str = Form("file://%s/%s\r\n",
                              gSystem->UnixPathName(gSystem->WorkingDirectory()),
                              item->GetText());
                  fDNDData.fData = (void *)strdup(str.Data());
                  fDNDData.fDataLength = str.Length()+1;
               }
               SetDragPixmap(item->GetPicture());
               gDNDManager->StartDrag(this, event->fXRoot, event->fYRoot);
            }
         }
      }
      if (gDNDManager->IsDragging()) {
         gDNDManager->Drag(event->fXRoot, event->fYRoot,
                           TGDNDManager::GetDNDActionCopy(), event->fTime);
      } else {
         if (fTipItem == item) return kTRUE;
         if (!fUserControlled) { 
            MouseOver(item);
            MouseOver(item, event->fState);
         }
         gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kHand));
      }
      if (fTip)
         fTip->Hide();
      if (item->GetTipTextLength() > 0) {
         SetToolTipText(item->GetTipText(), item->fXtext,
                        item->fY - pos.fY + item->fHeight - 4, 1000);
      } else if (fAutoTips && item->GetUserData()) {
         
         
         TObject *obj = (TObject *)item->GetUserData();
         if (obj->InheritsFrom(TObject::Class())) {
            SetToolTipText(obj->GetTitle(), item->fXtext,
                           item->fY - pos.fY + item->fHeight - 4, 1000);
         }
      }
      fTipItem = item;
   } else {
      if (fBelowMouse) {
         fBelowMouse = 0;
         MouseOver(fBelowMouse);
         MouseOver(fBelowMouse, event->fState);
      }
      gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kPointer));
   }
   return kTRUE;
}
Bool_t TGListTree::HandleKey(Event_t *event)
{
   
   
   char   input[10];
   Int_t  n;
   UInt_t keysym;
   TGListTreeItem *item = 0;
   fLastEventState = event->fState;
   if (fTip) fTip->Hide();
   if (event->fType == kGKeyPress) {
      gVirtualX->LookupString(event, input, sizeof(input), keysym);
      n = strlen(input);
      if (!event->fState && (EKeySym)keysym == kKey_Escape) {
         if (gDNDManager->IsDragging()) gDNDManager->EndDrag();
      }
      item = fCurrent;
      if (!item) return kFALSE;
      fEventHandled = kFALSE;
      KeyPressed(item, keysym, event->fState);
      if (fUserControlled && fEventHandled)
         return kTRUE;
      
      switch ((EKeySym)keysym) {
         case kKey_Enter:
         case kKey_Return:
            event->fType = kButtonPress;
            event->fCode = kButton1;
            if (fSelected == item) {
               
               ClearViewPort();
               item->SetOpen(!item->IsOpen());
               DoubleClicked(item, 1);
            } else {
               
               ClearViewPort();
               if (fSelected) fSelected->SetActive(kFALSE);
               fSelected = item;
               fSelected->SetActive(kTRUE);
               HighlightItem(item, kTRUE, kTRUE);
               Clicked(item, 1);
               Clicked(item, 1, event->fXRoot, event->fYRoot);
               Clicked(item, 1, event->fState, event->fXRoot, event->fYRoot);
            }
            break;
         case kKey_Space:
            if (item->HasCheckBox()) {
               ToggleItem(item);
               if (fCheckMode == kRecursive) {
                  CheckAllChildren(item, item->IsChecked());
               }
               UpdateChecked(item, kTRUE);
               Checked((TObject *)item->GetUserData(), item->IsChecked());
            }
            break;
         case kKey_F5:
            Layout();
            break;
         case kKey_F7:
            Search();
            break;
         case kKey_Left:
            ClearViewPort();
            item->SetOpen(kFALSE);
            break;
         case kKey_Right:
            ClearViewPort();
            item->SetOpen(kTRUE);
            break;
         case kKey_Up:
            LineUp(event->fState & kKeyShiftMask);
            break;
         case kKey_Down:
            LineDown(event->fState & kKeyShiftMask);
            break;
         case kKey_PageUp:
            PageUp(event->fState & kKeyShiftMask);
            break;
         case kKey_PageDown:
            PageDown(event->fState & kKeyShiftMask);
            break;
         case kKey_Home:
            Home(event->fState & kKeyShiftMask);
            break;
         case kKey_End:
            End(event->fState & kKeyShiftMask);
            break;
         default:
            break;
      }
   }
   return kTRUE;
}
void TGListTree::MouseOver(TGListTreeItem *entry)
{
   
   Emit("MouseOver(TGListTreeItem*)", (Long_t)entry);
}
void TGListTree::MouseOver(TGListTreeItem *entry, UInt_t mask)
{
   
   Long_t args[2];
   args[0] = (Long_t)entry;
   args[1] = mask;
   Emit("MouseOver(TGListTreeItem*,UInt_t)", args);
}
void TGListTree::KeyPressed(TGListTreeItem *entry, UInt_t keysym, UInt_t mask)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   Long_t args[3];
   args[0] = (Long_t)entry;
   args[1] = (Long_t)keysym;
   args[2] = (Long_t)mask;
   Emit("KeyPressed(TGListTreeItem*,ULong_t,ULong_t)", args);
   SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_KEY), keysym, mask);
}
void TGListTree::ReturnPressed(TGListTreeItem *entry)
{
   
   Emit("ReturnPressed(TGListTreeItem*)", (Long_t)entry);
}
void TGListTree::Checked(TObject *entry, Bool_t on)
{
   
   Long_t args[2];
   args[0] = (Long_t)entry;
   args[1] = on;
   Emit("Checked(TObject*,Bool_t)", args);
}
void TGListTree::Clicked(TGListTreeItem *entry, Int_t btn)
{
   
   Long_t args[2];
   args[0] = (Long_t)entry;
   args[1] = btn;
   Emit("Clicked(TGListTreeItem*,Int_t)", args);
}
void TGListTree::Clicked(TGListTreeItem *entry, Int_t btn, Int_t x, Int_t y)
{
   
   Long_t args[4];
   args[0] = (Long_t)entry;
   args[1] = btn;
   args[2] = x;
   args[3] = y;
   Emit("Clicked(TGListTreeItem*,Int_t,Int_t,Int_t)", args);
}
void TGListTree::Clicked(TGListTreeItem *entry, Int_t btn, UInt_t mask, Int_t x, Int_t y)
{
   
   Long_t args[5];
   args[0] = (Long_t)entry;
   args[1] = btn;
   args[2] = mask;
   args[3] = x;
   args[4] = y;
   Emit("Clicked(TGListTreeItem*,Int_t,UInt_t,Int_t,Int_t)", args);
}
void TGListTree::DoubleClicked(TGListTreeItem *entry, Int_t btn)
{
   
   Long_t args[2];
   args[0] = (Long_t)entry;
   args[1] = btn;
   Emit("DoubleClicked(TGListTreeItem*,Int_t)", args);
}
void TGListTree::DoubleClicked(TGListTreeItem *entry, Int_t btn, Int_t x, Int_t y)
{
   
   Long_t args[4];
   args[0] = (Long_t)entry;
   args[1] = btn;
   args[2] = x;
   args[3] = y;
   Emit("DoubleClicked(TGListTreeItem*,Int_t,Int_t,Int_t)", args);
}
void TGListTree::Home(Bool_t )
{
   
   if (fCanvas) fCanvas->SetVsbPosition(0);
}
void TGListTree::End(Bool_t )
{
   
   if (fCanvas) fCanvas->SetVsbPosition((Int_t)fHeight);
}
void TGListTree::PageUp(Bool_t )
{
   
   if (!fCanvas) return;
   TGDimension dim = GetPageDimension();
   Int_t newpos = fCanvas->GetVsbPosition() - dim.fHeight;
   if (newpos<0) newpos = 0;
   fCanvas->SetVsbPosition(newpos);
}
void TGListTree::PageDown(Bool_t )
{
   
   if (!fCanvas) return;
   TGDimension dim = GetPageDimension();
   Int_t newpos = fCanvas->GetVsbPosition() + dim.fHeight;
   fCanvas->SetVsbPosition(newpos);
}
void TGListTree::LineUp(Bool_t )
{
   
   Int_t height;
   if (!fCurrent) return;
   
   TGDimension dim = GetPageDimension();
   TGPosition pos = GetPagePosition();
   const TGPicture *pic1 = fCurrent->GetPicture();
   height = pic1->GetHeight() + fVspacing;
   Int_t findy = (fCurrent->fY - height) + (fMargin - pos.fY);
   TGListTreeItem *next = FindItem(findy);
   if (next && (next != fCurrent)) {
      DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
      if (findy <= 2*height) {
         Int_t newpos = fCanvas->GetVsbPosition() - height;
         if (newpos<0) newpos = 0;
         fCanvas->SetVsbPosition(newpos);
      }
      DrawOutline(fId, next);
      fCurrent = next;
   }
}
void TGListTree::LineDown(Bool_t )
{
   
   Int_t height;
   if (!fCurrent) return;
   
   TGDimension dim = GetPageDimension();
   TGPosition pos = GetPagePosition();
   const TGPicture *pic1 = fCurrent->GetPicture();
   height = pic1->GetHeight() + fVspacing;
   Int_t findy = (fCurrent->fY + height) + (fMargin - pos.fY);
   TGListTreeItem *next = FindItem(findy);
   if (next && (next != fCurrent)) {
      DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
      if (findy >= ((Int_t)dim.fHeight - 2*height)) {
         Int_t newpos = fCanvas->GetVsbPosition() + height;
         if (newpos<0) newpos = 0;
         fCanvas->SetVsbPosition(newpos);
      }
      DrawOutline(fId, next);
      fCurrent = next;
   }
}
void TGListTree::AdjustPosition(TGListTreeItem *item)
{
   
   
   TGListTreeItem *it = item;
   if (!it) it = fSelected;
   if (!it) {
      HighlightItem(fFirst); 
      return;
   }
   Int_t y = 0;
   Int_t yparent = 0;
   Int_t vh = 0;
   Int_t v = 0;
   if (it) {
      y = it->fY;
      if (it->GetParent()) yparent = it->GetParent()->fY;
   }
   if (y==0) y = yparent; 
   if (fCanvas->GetVScrollbar()->IsMapped()) {
      vh = fCanvas->GetVScrollbar()->GetPosition()+(Int_t)fViewPort->GetHeight();
      if (y<fCanvas->GetVScrollbar()->GetPosition()) {
         v = TMath::Max(0,y-(Int_t)fViewPort->GetHeight()/2);
         fCanvas->SetVsbPosition(v);
      } else if (y+(Int_t)it->fHeight>vh) {
         v = TMath::Min((Int_t)GetHeight()-(Int_t)fViewPort->GetHeight(),
                        y+(Int_t)it->fHeight-(Int_t)fViewPort->GetHeight()/2);
         if (v<0) v = 0;
         fCanvas->SetVsbPosition(v);
      }
   }
}
void TGListTree::Search(Bool_t )
{
   
   Int_t ret = 0;
   char msg[256];
   static TString buf;
   TGSearchType *srch = new TGSearchType;
   srch->fBuffer = (char*)buf.Data();
   TGListTreeItem *item;
   new TGSearchDialog(fClient->GetDefaultRoot(), fCanvas, 400, 150, srch, &ret);
   if (ret) {
      item = FindItemByPathname(srch->fBuffer);
      if (!item) {
         sprintf(msg, "Couldn't find \"%s\"", srch->fBuffer);
         gVirtualX->Bell(20);
         new TGMsgBox(fClient->GetDefaultRoot(), fCanvas, "Container", msg,
                      kMBIconExclamation, kMBOk, 0);
      } else {
         ClearHighlighted();
         HighlightItem(item);
      }
   }
   buf = srch->fBuffer;
   delete srch;
}
void TGListTree::DrawRegion(Int_t , Int_t y, UInt_t , UInt_t h)
{
   
   static GContext_t gcBg = 0;
   
   if (y > (Int_t)fViewPort->GetHeight()) {
      return;
   }
   y = y < 0 ? 0 : y;
   UInt_t w = fViewPort->GetWidth();
   
   if (((Int_t)w < 1) || (w > 32768) || ((Int_t)h < 1)) {
      return;
   }
   Pixmap_t pixmap = gVirtualX->CreatePixmap(fId, w, fViewPort->GetHeight());
   if (!gcBg) {
      GCValues_t gcValues;
      gcValues.fForeground = fBackground;
      gcValues.fForeground = fBackground;
      gcValues.fGraphicsExposures = kTRUE;
      gcValues.fMask = kGCForeground | kGCBackground | kGCGraphicsExposures;
      gcBg = gVirtualX->CreateGC(fId, &gcValues);
   }
   gVirtualX->SetForeground(gcBg, fBackground);
   gVirtualX->FillRectangle(pixmap, gcBg, 0, 0, w, fViewPort->GetHeight());
   Draw(pixmap, 0, fViewPort->GetHeight());
   gVirtualX->CopyArea(pixmap, fId, gcBg, 0, y, w, fViewPort->GetHeight(), 0, y);
   gVirtualX->DeletePixmap(pixmap);
   gVirtualX->Update(kFALSE);
}
void TGListTree::Draw(Handle_t id, Int_t yevent, Int_t hevent)
{
   
   TGListTreeItem *item;
   Int_t  x, y, xbranch;
   UInt_t width, height, old_width, old_height;
   
   
   fExposeTop = yevent - FontHeight();
   fExposeBottom = yevent + hevent + FontHeight();
   old_width  = fDefw;
   old_height = fDefh;
   fDefw = fDefh = 1;
   TGPosition pos = GetPagePosition();
   x = -pos.fX;
   y = fMargin;
   item = fFirst;
   while (item) {
      xbranch = -1;
      DrawItem(id, item, x, y, &xbranch, &width, &height);
      width += pos.fX + x + fHspacing + fMargin;
      if (width > fDefw) fDefw = width;
      y += height + fVspacing;
      if (item->fFirstchild && item->IsOpen()) {
         y = DrawChildren(id, item->fFirstchild, x, y, xbranch);
      }
      item = item->fNextsibling;
   }
   fDefh = y + fMargin;
   if ((old_width != fDefw) || (old_height != fDefh)) {
      fCanvas->Layout();
   }
}
Int_t TGListTree::DrawChildren(Handle_t id, TGListTreeItem *item,
                               Int_t x, Int_t y, Int_t xroot)
{
   
   UInt_t width, height;
   Int_t  xbranch;
   TGPosition pos = GetPagePosition();
   x += fIndent + (Int_t)item->fParent->GetPicWidth();
   while (item) {
      xbranch = xroot;
      DrawItem(id, item, x, y, &xbranch, &width, &height);
      width += pos.fX + x + fHspacing + fMargin;
      if (width > fDefw) fDefw = width;
      y += height + fVspacing;
      if ((item->fFirstchild) && (item->IsOpen())) {
         y = DrawChildren(id, item->fFirstchild, x, y, xbranch);
      }
      item = item->fNextsibling;
   }
   return y;
}
void TGListTree::DrawItem(Handle_t id, TGListTreeItem *item, Int_t x, Int_t y,
                          Int_t *xroot, UInt_t *retwidth, UInt_t *retheight)
{
   
   Int_t  xpic1, ypic1, xbranch, ybranch, xtext, ytext, xline, yline, xc;
   Int_t  xpic2 = 0, ypic2 = 0;
   UInt_t height;
   const TGPicture *pic1 = item->GetPicture();
   const TGPicture *pic2 = item->GetCheckBoxPicture();
   
   height = FontHeight();
   xline = 0;
   xpic1 = x;
   xtext = x + fHspacing + (Int_t)item->GetPicWidth();
   if (pic2) {
      if (pic2->GetHeight() > height) {
         ytext = y + (Int_t)((pic2->GetHeight() - height) >> 1);
         height = pic2->GetHeight();
         ypic2 = y;
      } else {
         ytext = y;
         ypic2 = y + (Int_t)((height - pic2->GetHeight()) >> 1);
      }
      xpic2 = xpic1 + pic1->GetWidth() + 1;
      xtext += pic2->GetWidth();
   } else {
      ypic1 = y;
      xline = 0;
   }
   if (pic1) {
      if (pic1->GetHeight() > height) {
         ytext = y + (Int_t)((pic1->GetHeight() - height) >> 1);
         height = pic1->GetHeight();
         ypic1 = y;
      } else {
         ytext = y;
         ypic1 = y + (Int_t)((height - pic1->GetHeight()) >> 1);
      }
      xbranch = xpic1 + (Int_t)(pic1->GetWidth() >> 1);
      ybranch = ypic1 + (Int_t)pic1->GetHeight();
      yline = ypic1 + (Int_t)(pic1->GetHeight() >> 1);
      if (xline == 0) xline = xpic1;
   } else {
      if (xline == 0) xline = xpic1;
      ypic1 = ytext = y;
      xbranch = xpic1 + (Int_t)(item->GetPicWidth() >> 1);
      yline = ybranch = ypic1 + (Int_t)(height >> 1);
      yline = ypic1 + (Int_t)(height >> 1);
   }
   
   ++height; height &= ~1;
   
   item->fY      = y;
   item->fXtext  = xtext;
   item->fYtext  = ytext;
   item->fHeight = height;
   
   TGPosition  pos = GetPagePosition();
   TGDimension dim = GetPageDimension();
   Int_t yp        = y       - pos.fY;
   Int_t ylinep    = yline   - pos.fY;
   Int_t ybranchp  = ybranch - pos.fY;
   Int_t ypicp     = ypic1   - pos.fY;
   if ((yp >= fExposeTop) && (yp <= (Int_t)dim.fHeight))
   {
      if (*xroot >= 0) {
         xc = *xroot;
         if (item->fNextsibling) {
            gVirtualX->DrawLine(id, fLineGC, xc, yp, xc, yp+height);
         } else {
            gVirtualX->DrawLine(id, fLineGC, xc, yp, xc, ylinep);
         }
         TGListTreeItem *p = item->fParent;
         while (p) {
            xc -= (fIndent + (Int_t)item->GetPicWidth());
            if (p->fNextsibling) {
               gVirtualX->DrawLine(id, fLineGC, xc, yp, xc, yp+height);
            }
            p = p->fParent;
         }
         gVirtualX->DrawLine(id, fLineGC, *xroot, ylinep, xpic1, ylinep);
         DrawNode(id, item, *xroot, yline);
      }
      if (item->IsOpen() && item->fFirstchild) {
         gVirtualX->DrawLine(id, fLineGC, xbranch, ybranchp, xbranch, 
                             yp+height);
      }
      pic1->Draw(id, fDrawGC, xpic1, ypicp);
      if (pic2)
         pic2->Draw(id, fDrawGC, xpic2, ypicp);
      DrawItemName(id, item);
   }
   *xroot = xbranch;
   *retwidth  = TextWidth(item->GetText()) + item->GetPicWidth();
   *retheight = height;
}
void TGListTree::DrawOutline(Handle_t id, TGListTreeItem *item, Pixel_t col, 
                             Bool_t clear)
{
   
   Int_t posx;
   TGPosition pos = GetPagePosition();
   TGDimension dim = GetPageDimension();
   posx = item->fXtext - item->GetPicWidth();
   posx -= 5;
   if (item->HasCheckBox())
      posx -= item->GetCheckBoxPicture()->GetWidth();
   if (clear) {
      gVirtualX->SetForeground(fDrawGC, fCanvas->GetContainer()->GetBackground());
      
   }
   else
      gVirtualX->SetForeground(fDrawGC, col);
   gVirtualX->DrawRectangle(id, fDrawGC, posx, item->fYtext-pos.fY-2, 
                            dim.fWidth-posx-2, FontHeight()+4);
   gVirtualX->SetForeground(fDrawGC, fgBlackPixel);
}
void TGListTree::DrawActive(Handle_t id, TGListTreeItem *item)
{
   
   UInt_t width;
   TGPosition pos = GetPagePosition();
   TGDimension dim = GetPageDimension();
   width = TextWidth(item->GetText());
   gVirtualX->SetForeground(fDrawGC, item->GetActiveColor());
   gVirtualX->FillRectangle(id, fDrawGC, item->fXtext-1, 
                    item->fYtext-pos.fY, width+2, FontHeight());
   gVirtualX->SetForeground(fDrawGC, fgBlackPixel);
   gVirtualX->DrawString(id, fHighlightGC, item->fXtext, 
                         item->fYtext - pos.fY + FontAscent(),
                         item->GetText(), item->GetTextLength());
}
void TGListTree::DrawItemName(Handle_t id, TGListTreeItem *item)
{
   
   TGPosition pos = GetPagePosition();
   TGDimension dim = GetPageDimension();
   if (item->IsActive()) {
      DrawActive(id, item);
   }
   else { 
      gVirtualX->FillRectangle(id, fHighlightGC, item->fXtext, 
                       item->fYtext-pos.fY, dim.fWidth-item->fXtext-2,
                       FontHeight());
      gVirtualX->DrawString(id, fDrawGC,
                       item->fXtext, item->fYtext-pos.fY + FontAscent(),
                       item->GetText(), item->GetTextLength());
   }
   if (item == fCurrent) {
      DrawOutline(id, item);
   }
   if (fColorMode != 0 && item->HasColor()) {
      UInt_t width = TextWidth(item->GetText());
      gVirtualX->SetForeground(fColorGC, TColor::Number2Pixel(item->GetColor()));
      if (fColorMode & kColorUnderline) {
         Int_t y = item->fYtext-pos.fY + FontAscent() + 2;
         gVirtualX->DrawLine(id, fColorGC, item->fXtext, y, item->fXtext + width, y);
      }
      if (fColorMode & kColorBox) {
         Int_t x = item->fXtext + width + 4;
         Int_t y = item->fYtext - pos.fY  + 3;
         Int_t h = FontAscent()    - 4;
         gVirtualX->FillRectangle(id, fColorGC, x, y, h, h);
         gVirtualX->DrawRectangle(id, fDrawGC,  x, y, h, h);
      }
   }
}
void TGListTree::DrawNode(Handle_t id, TGListTreeItem *item, Int_t x, Int_t y)
{
   
   TGPosition pos = GetPagePosition();
   Int_t yp = y - pos.fY;
   if (item->fFirstchild) {
      gVirtualX->DrawLine(id, fHighlightGC, x, yp-2, x, yp+2);
      gVirtualX->SetForeground(fHighlightGC, fgBlackPixel);
      gVirtualX->DrawLine(id, fHighlightGC, x-2, yp, x+2, yp);
      if (!item->IsOpen())
         gVirtualX->DrawLine(id, fHighlightGC, x, yp-2, x, yp+2);
      gVirtualX->SetForeground(fHighlightGC, fGrayPixel);
      gVirtualX->DrawLine(id, fHighlightGC, x-4, yp-4, x+4, yp-4);
      gVirtualX->DrawLine(id, fHighlightGC, x+4, yp-4, x+4, yp+4);
      gVirtualX->DrawLine(id, fHighlightGC, x-4, yp+4, x+4, yp+4);
      gVirtualX->DrawLine(id, fHighlightGC, x-4, yp-4, x-4, yp+4);
      gVirtualX->SetForeground(fHighlightGC, fgWhitePixel);
   }
}
void TGListTree::SetToolTipText(const char *text, Int_t x, Int_t y, Long_t delayms)
{
   
   
   
   
   if (delayms == 0) {
      delete fTip;
      fTip = 0;
      return;
   }
   if (text && strlen(text)) {
      if (!fTip)
         fTip = new TGToolTip(fClient->GetDefaultRoot(), this, text, delayms);
      else
         fTip->SetText(text);
      fTip->SetPosition(x, y);
      fTip->Reset();
   }
}
void TGListTree::RemoveReference(TGListTreeItem *item)
{
   
   
   ClearViewPort();
   
   if (item->fPrevsibling) {
      item->fPrevsibling->fNextsibling = item->fNextsibling;
      if (item->fNextsibling)
         item->fNextsibling->fPrevsibling = item->fPrevsibling;
   } else {
      
      if (item->fParent)
         item->fParent->fFirstchild = item->fNextsibling;
      else
         fFirst = item->fNextsibling;
      if (item->fNextsibling)
         item->fNextsibling->fPrevsibling = 0;
   }
}
void TGListTree::PDeleteChildren(TGListTreeItem *item)
{
   
   TGListTreeItem *sibling;
   while (item) {
      if (item->fFirstchild) {
         PDeleteChildren(item->fFirstchild);
         item->fFirstchild = 0;
      }
      sibling = item->fNextsibling;
      if (fSelected == item)
         fSelected = 0;
      delete item;
      item = sibling;
   }
}
void TGListTree::InsertChild(TGListTreeItem *parent, TGListTreeItem *item)
{
   
   TGListTreeItem *i;
   item->fParent = parent;
   item->fNextsibling = item->fPrevsibling = 0;
   if (parent) {
      if (parent->fFirstchild) {
         if (parent->fLastchild) {
            i = parent->fLastchild;
         }
         else {
            i = parent->fFirstchild;
            while (i->fNextsibling) i = i->fNextsibling;
         }
         i->fNextsibling = item;
         item->fPrevsibling = i;
      } else {
         parent->fFirstchild = item;
      }
      parent->fLastchild = item;
   } else {  
      if (fFirst) {
         if (fLast) {
            i = fLast;
         }
         else {
            i = fFirst;
            while (i->fNextsibling) i = i->fNextsibling;
         }
         i->fNextsibling = item;
         item->fPrevsibling = i;
      } else {
         fFirst = item;
      }
      fLast = item;
   }
   if (item->HasCheckBox())
      UpdateChecked(item);
}
void TGListTree::InsertChildren(TGListTreeItem *parent, TGListTreeItem *item)
{
   
   TGListTreeItem *next, *newnext;
   
   
   
   
   
   
   
   next = item->fNextsibling;
   
   InsertChild(parent, item);
   
   
   newnext = item->fNextsibling;
   
   item->fNextsibling = next;
   
   
   
   while (item->fNextsibling) {
      item->fParent = parent;
      item = item->fNextsibling;
   }
   
   item->fNextsibling = newnext;
   if (newnext)
      newnext->fPrevsibling = item;
}
Int_t TGListTree::SearchChildren(TGListTreeItem *item, Int_t y, Int_t findy,
                                 TGListTreeItem **finditem)
{
   
   UInt_t height;
   const TGPicture *pic;
   while (item) {
      
      pic = item->GetPicture();
      
      height = FontHeight();
      if (pic->GetHeight() > height)
         height = pic->GetHeight();
      if ((findy >= y) && (findy <= y + (Int_t)height)) {
         *finditem = item;
         return -1;
      }
      y += (Int_t)height + fVspacing;
      if (item->fFirstchild && item->IsOpen()) {
         y = SearchChildren(item->fFirstchild, y, findy, finditem);
         if (*finditem) return -1;
      }
      item = item->fNextsibling;
   }
   return y;
}
TGListTreeItem *TGListTree::FindItem(Int_t findy)
{
   
   Int_t  y;
   UInt_t height;
   TGListTreeItem *item, *finditem;
   const TGPicture *pic;
   TGPosition pos = GetPagePosition();
   y = fMargin - pos.fY;
   item = fFirst;
   finditem = 0;
   while (item && !finditem) {
      
      pic = item->GetPicture();
      
      height = FontHeight();
      if (pic && (pic->GetHeight() > height))
         height = pic->GetHeight();
      if ((findy >= y) && (findy <= y + (Int_t)height))
         return item;
      y += (Int_t)height + fVspacing;
      if ((item->fFirstchild) && (item->IsOpen())) {
         y = SearchChildren(item->fFirstchild, y, findy, &finditem);
         
      }
      item = item->fNextsibling;
   }
   return finditem;
}
void TGListTree::AddItem(TGListTreeItem *parent, TGListTreeItem *item)
{
   
   InsertChild(parent, item);
   if ((parent == 0) || (parent && parent->IsOpen()))
      ClearViewPort();
}
TGListTreeItem *TGListTree::AddItem(TGListTreeItem *parent, const char *string,
                                    const TGPicture *open, const TGPicture *closed,
                                    Bool_t checkbox)
{
   
   TGListTreeItem *item;
   item = new TGListTreeItemStd(fClient, string, open, closed, checkbox);
   InsertChild(parent, item);
   if ((parent == 0) || (parent && parent->IsOpen()))
      ClearViewPort();
   return item;
}
TGListTreeItem *TGListTree::AddItem(TGListTreeItem *parent, const char *string,
                                    void *userData, const TGPicture *open,
                                    const TGPicture *closed,
                                    Bool_t checkbox)
{
   
   
   TGListTreeItem *item = FindChildByData(parent, userData);
   if (!item) {
      item = AddItem(parent, string, open, closed, checkbox);
      if (item) item->SetUserData(userData);
   }
   return item;
}
void TGListTree::RenameItem(TGListTreeItem *item, const char *string)
{
   
   if (item) {
      item->Rename(string);
   }
   DoRedraw();
}
Int_t TGListTree::DeleteItem(TGListTreeItem *item)
{
   
   if (item->fFirstchild) {
      PDeleteChildren(item->fFirstchild);
   }
   item->fFirstchild = 0;
   RemoveReference(item);
   if (fSelected == item) {
      fSelected = 0;
   }
   if (fCurrent == item) {
      DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
      fCurrent = item->GetPrevSibling();
      if (! fCurrent) {
         fCurrent = item->GetNextSibling();
         if (! fCurrent)
            fCurrent = item->GetParent();
      }
   }
   if (fBelowMouse == item) {
      DrawOutline(fId, fBelowMouse, 0xffffff, kTRUE);
      fBelowMouse = 0;
      MouseOver(0);
      MouseOver(0,fLastEventState);
   }
   fCurrent = fBelowMouse = 0;
   delete item;
   fClient->NeedRedraw(this);
   return 1;
}
void TGListTree::OpenItem(TGListTreeItem *item)
{
   
   if (item) {
      item->SetOpen(kTRUE);
      DoRedraw(); 
      AdjustPosition(item);
   }
}
void TGListTree::CloseItem(TGListTreeItem *item)
{
   
   if (item) {
      item->SetOpen(kFALSE);
      DoRedraw(); 
      AdjustPosition(item);
   }
}
Int_t TGListTree::RecursiveDeleteItem(TGListTreeItem *item, void *ptr)
{
   
   
   if (item && ptr) {
      if (item->GetUserData() == ptr) {
         DeleteItem(item);
      } else {
         if (item->IsOpen() && item->fFirstchild) {
            RecursiveDeleteItem(item->fFirstchild,  ptr);
         }
         RecursiveDeleteItem(item->fNextsibling, ptr);
      }
   }
   return 1;
}
void TGListTree::SetToolTipItem(TGListTreeItem *item, const char *string)
{
   
   
   
   if (item) {
      item->SetTipText(string);
   }
}
Int_t TGListTree::DeleteChildren(TGListTreeItem *item)
{
   
   if (!fUserControlled) {
      
      
      
      
      fCurrent = fBelowMouse = 0;
   }
   if (item->fFirstchild) {
      PDeleteChildren(item->fFirstchild);
   }
   item->fFirstchild = 0;
   DoRedraw();
   return 1;
}
Int_t TGListTree::Reparent(TGListTreeItem *item, TGListTreeItem *newparent)
{
   
   
   RemoveReference(item);
   
   InsertChild(newparent, item);
   DoRedraw();
   return 1;
}
Int_t TGListTree::ReparentChildren(TGListTreeItem *item,
                                 TGListTreeItem *newparent)
{
   
   TGListTreeItem *first;
   if (item->fFirstchild) {
      first = item->fFirstchild;
      item->fFirstchild = 0;
      InsertChildren(newparent, first);
      DoRedraw();
      return 1;
   }
   return 0;
}
extern "C"
Int_t Compare(const void *item1, const void *item2)
{
   return strcmp((*((TGListTreeItem **) item1))->GetText(),
                 (*((TGListTreeItem **) item2))->GetText());
}
Int_t TGListTree::Sort(TGListTreeItem *item)
{
   
   TGListTreeItem *first, *parent, **list;
   size_t i, count;
   
   while (item->fPrevsibling) item = item->fPrevsibling;
   first = item;
   parent = first->fParent;
   
   count = 1;
   while (item->fNextsibling) item = item->fNextsibling, count++;
   if (count <= 1) return 1;
   list = new TGListTreeItem* [count];
   list[0] = first;
   count = 1;
   while (first->fNextsibling) {
      list[count] = first->fNextsibling;
      count++;
      first = first->fNextsibling;
   }
   ::qsort(list, count, sizeof(TGListTreeItem*), ::Compare);
   list[0]->fPrevsibling = 0;
   for (i = 0; i < count; i++) {
      if (i < count - 1)
         list[i]->fNextsibling = list[i + 1];
      if (i > 0)
         list[i]->fPrevsibling = list[i - 1];
   }
   list[count - 1]->fNextsibling = 0;
   if (parent)
      parent->fFirstchild = list[0];
   else
      fFirst = list[0];
   delete [] list;
   DoRedraw();
   return 1;
}
Int_t TGListTree::SortSiblings(TGListTreeItem *item)
{
   
   return Sort(item);
}
Int_t TGListTree::SortChildren(TGListTreeItem *item)
{
   
   TGListTreeItem *first;
   if (item) {
      first = item->fFirstchild;
      if (first) {
         SortSiblings(first);
      }
   } else {
      if (fFirst) {
         first = fFirst->fFirstchild;
         if (first) {
            SortSiblings(first);
         }
      }
   }
   DoRedraw();
   return 1;
}
TGListTreeItem *TGListTree::FindSiblingByName(TGListTreeItem *item, const char *name)
{
   
   
   if (item) {
      while (item->fPrevsibling) {
         item = item->fPrevsibling;
      }
      while (item) {
         if (strcmp(item->GetText(), name) == 0) {
            return item;
         }
         item = item->fNextsibling;
      }
      return item;
   }
   return 0;
}
TGListTreeItem *TGListTree::FindSiblingByData(TGListTreeItem *item, void *userData)
{
   
   
   if (item) {
      while (item->fPrevsibling) {
         item = item->fPrevsibling;
      }
      while (item) {
         if (item->GetUserData() == userData) {
            return item;
         }
         item = item->fNextsibling;
      }
      return item;
   }
   return 0;
}
TGListTreeItem *TGListTree::FindChildByName(TGListTreeItem *item, const char *name)
{
   
   
   if (item && item->fFirstchild) {
      item = item->fFirstchild;
   } else if (!item && fFirst) {
      item = fFirst;
   } else {
      item = 0;
   }
   while (item) {
      if (strcmp(item->GetText(), name) == 0) {
         return item;
      }
      item = item->fNextsibling;
   }
   return 0;
}
TGListTreeItem *TGListTree::FindChildByData(TGListTreeItem *item, void *userData)
{
   
   
   if (item && item->fFirstchild) {
      item = item->fFirstchild;
   } else if (!item && fFirst) {
      item = fFirst;
   } else {
      item = 0;
   }
   while (item) {
      if (item->GetUserData() == userData) {
         return item;
      }
      item = item->fNextsibling;
   }
   return 0;
}
TGListTreeItem *TGListTree::FindItemByPathname(const char *path)
{
   
   
   if (!path || !*path) return 0;
   const char *p = path, *s;
   char dirname[256];
   TGListTreeItem *item = 0;
   item = FindChildByName(item, "/");
   TGListTreeItem *diritem = 0;
   TString fulldir;
start:
   while (1) {
      while (*p && *p == '/') p++;
      if (!*p) break;
      s = strchr(p, '/');
      if (!s) {
         strcpy(dirname, p);
      } else {
         strncpy(dirname, p, s-p);
         dirname[s-p] = 0;
      }
      item = FindChildByName(item, dirname);
      if (!diritem && dirname[0]) {
         fulldir += "/";
         fulldir += dirname;
         if ((diritem=FindChildByName(0, fulldir.Data()))) {
            if (!s || !strlen(s)) return diritem;
            p = ++s;
            item = diritem;
            goto start;
         }
      }
      if (!s || !strlen(s)) return item;
      p = ++s;
   }
   return 0;
}
void TGListTree::HighlightItem(TGListTreeItem *item)
{
   
   UnselectAll(kFALSE);
   HighlightItem(item, kTRUE, kFALSE);
   AdjustPosition(item);
}
void TGListTree::ClearHighlighted()
{
   
   UnselectAll(kFALSE);
}
void TGListTree::GetPathnameFromItem(TGListTreeItem *item, char *path, Int_t depth)
{
   
   
   char tmppath[1024];
   *path = '\0';
   while (item) {
      sprintf(tmppath, "/%s%s", item->GetText(), path);
      strcpy(path, tmppath);
      item = item->fParent;
      if (--depth == 0 && item) {
         sprintf(tmppath, "...%s", path);
         strcpy(path, tmppath);
         return;
      }
   }
}
Pixel_t TGListTree::GetGrayPixel()
{
   
   static Bool_t init = kFALSE;
   if (!init) {
      if (!gClient->GetColorByName("#808080", fgGrayPixel))
         fgGrayPixel = fgBlackPixel;
      init = kTRUE;
   }
   return fgGrayPixel;
}
FontStruct_t TGListTree::GetDefaultFontStruct()
{
   
   if (!fgDefaultFont)
      fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
   return fgDefaultFont->GetFontStruct();
}
const TGGC &TGListTree::GetDrawGC()
{
   
   if (!fgDrawGC) {
      GCValues_t gcv;
      gcv.fMask = kGCLineStyle  | kGCLineWidth  | kGCFillStyle |
                  kGCForeground | kGCBackground | kGCFont;
      gcv.fLineStyle  = kLineSolid;
      gcv.fLineWidth  = 0;
      gcv.fFillStyle  = kFillSolid;
      gcv.fFont       = fgDefaultFont->GetFontHandle();
      gcv.fBackground = fgWhitePixel;
      gcv.fForeground = fgBlackPixel;
      fgDrawGC = gClient->GetGC(&gcv, kTRUE);
   }
   return *fgDrawGC;
}
const TGGC &TGListTree::GetLineGC()
{
   
   if (!fgLineGC) {
      GCValues_t gcv;
      gcv.fMask = kGCLineStyle  | kGCLineWidth  | kGCFillStyle |
                  kGCForeground | kGCBackground | kGCFont;
      gcv.fLineStyle  = kLineOnOffDash;
      gcv.fLineWidth  = 0;
      gcv.fFillStyle  = kFillSolid;
      gcv.fFont       = fgDefaultFont->GetFontHandle();
      gcv.fBackground = fgWhitePixel;
      gcv.fForeground = GetGrayPixel();
      fgLineGC = gClient->GetGC(&gcv, kTRUE);
      fgLineGC->SetDashOffset(0);
      fgLineGC->SetDashList("\x1\x1", 2);
   }
   return *fgLineGC;
}
const TGGC &TGListTree::GetHighlightGC()
{
   
   if (!fgHighlightGC) {
      GCValues_t gcv;
      gcv.fMask = kGCLineStyle  | kGCLineWidth  | kGCFillStyle |
                  kGCForeground | kGCBackground | kGCFont;
      gcv.fLineStyle  = kLineSolid;
      gcv.fLineWidth  = 0;
      gcv.fFillStyle  = kFillSolid;
      gcv.fFont       = fgDefaultFont->GetFontHandle();
      gcv.fBackground = fgDefaultSelectedBackground;
      gcv.fForeground = fgWhitePixel;
      fgHighlightGC = gClient->GetGC(&gcv, kTRUE);
   }
   return *fgHighlightGC;
}
const TGGC &TGListTree::GetColorGC()
{
   
   if (!fgColorGC) {
      GCValues_t gcv;
      gcv.fMask = kGCLineStyle  | kGCLineWidth  | kGCFillStyle |
                  kGCForeground | kGCBackground;
      gcv.fLineStyle  = kLineSolid;
      gcv.fLineWidth  = 1;
      gcv.fFillStyle  = kFillSolid;
      gcv.fBackground = fgDefaultSelectedBackground;
      gcv.fForeground = fgWhitePixel;
      fgColorGC = gClient->GetGC(&gcv, kTRUE);
   }
   return *fgColorGC;
}
const TGPicture *TGListTree::GetOpenPic()
{
   
   if (!fgOpenPic)
      fgOpenPic = gClient->GetPicture("ofolder_t.xpm");
   ((TGPicture *)fgOpenPic)->AddReference();
   return fgOpenPic;
}
const TGPicture *TGListTree::GetClosedPic()
{
   
   if (!fgClosedPic)
      fgClosedPic = gClient->GetPicture("folder_t.xpm");
   ((TGPicture *)fgClosedPic)->AddReference();
   return fgClosedPic;
}
const TGPicture *TGListTree::GetCheckedPic()
{
   
   if (!fgCheckedPic)
      fgCheckedPic = gClient->GetPicture("checked_t.xpm");
   ((TGPicture *)fgCheckedPic)->AddReference();
   return fgCheckedPic;
}
const TGPicture *TGListTree::GetUncheckedPic()
{
   
   if (!fgUncheckedPic)
      fgUncheckedPic = gClient->GetPicture("unchecked_t.xpm");
   ((TGPicture *)fgUncheckedPic)->AddReference();
   return fgUncheckedPic;
}
void TGListTree::SavePrimitive(ostream &out, Option_t *option )
{
   
   if (fBackground != GetWhitePixel()) SaveUserColor(out, option);
   out << endl << "   // list tree" << endl;
   out << "   TGListTree *";
   if ((fParent->GetParent())->InheritsFrom(TGCanvas::Class())) {
      out << GetName() << " = new TGListTree(" << GetCanvas()->GetName();
   } else {
      out << GetName() << " = new TGListTree(" << fParent->GetName();
      out << "," << GetWidth() << "," << GetHeight();
   }
   if (fBackground == GetWhitePixel()) {
      if (GetOptions() == kSunkenFrame) {
         out <<");" << endl;
      } else {
         out << "," << GetOptionString() <<");" << endl;
      }
   } else {
      out << "," << GetOptionString() << ",ucolor);" << endl;
   }
   out << endl;
   static Int_t n = 0;
   TGListTreeItem *current;
   current = GetFirstItem();
   out << "   const TGPicture *popen;       //used for list tree items" << endl;
   out << "   const TGPicture *pclose;      //used for list tree items" << endl;
   out << endl;
   while (current) {
      out << "   TGListTreeItem *item" << n << " = " << GetName() << "->AddItem(";
      current->SavePrimitive(out, Form("%d",n), n);
      if (current->IsOpen())
         out << "   " << GetName() << "->OpenItem(item" << n << ");" << endl;
      else
         out << "   " << GetName() << "->CloseItem(item" << n << ");" << endl;
      if (current == fSelected)
         out << "   " << GetName() << "->SetSelected(item" << n << ");" << endl;
      n++;
      if (current->fFirstchild) {
         SaveChildren(out, current->fFirstchild, n);
      }
      current = current->fNextsibling;
   }
   out << endl;
}
void TGListTree::SaveChildren(ostream &out, TGListTreeItem *item, Int_t &n)
{
   
   Int_t p = n-1;
   while (item) {
      out << "   TGListTreeItem *item" << n << " = " << GetName() << "->AddItem(";
      item->SavePrimitive(out, Form("%d",p),n);
      n++;
      if (item->fFirstchild) {
         SaveChildren(out, item->fFirstchild, n);
      }
      item = item->fNextsibling;
   }
}
void TGListTreeItemStd::SavePrimitive(ostream &out, Option_t *option, Int_t n)
{
   
   static const TGPicture *oldopen=0;
   static const TGPicture *oldclose=0;
   static const TGPicture *oldcheck=0;
   static const TGPicture *olduncheck=0;
   static Bool_t makecheck = kTRUE;
   static Bool_t makeuncheck = kTRUE;
   static Color_t oldcolor = -1;
   char quote = '"';
   TString s = Form("%d",n);
   if (!fParent)
      out << "NULL,";
   else
      out << "item" << option << ",";
   out << quote << GetText() << quote;
   out << ");" << endl;
   if (oldopen != fOpenPic) {
      oldopen = fOpenPic;
      out << "   popen = gClient->GetPicture(" << quote
          << gSystem->ExpandPathName(gSystem->UnixPathName(fOpenPic->GetName()))
          << quote << ");" << endl;
   }
   if (oldclose != fClosedPic) {
      oldclose = fClosedPic;
      out << "   pclose = gClient->GetPicture(" << quote
          << gSystem->ExpandPathName(gSystem->UnixPathName(fClosedPic->GetName()))
          << quote << ");" << endl;
   }
   out << "   item" << s.Data() << "->SetPictures(popen, pclose);" << endl;
   if (HasCheckBox()) {
      if (fCheckedPic && makecheck) {
         out << "   const TGPicture *pcheck;        //used for checked items" << endl;
         makecheck = kFALSE;
      }
      if (fUncheckedPic && makeuncheck) {
         out << "   const TGPicture *puncheck;      //used for unchecked items" << endl;
         makeuncheck = kFALSE;
      }
      out << "   item" << s.Data() << "->CheckItem();" << endl;
      if (oldcheck != fCheckedPic) {
         oldcheck = fCheckedPic;
         out << "   pcheck = gClient->GetPicture(" << quote
             << gSystem->ExpandPathName(gSystem->UnixPathName(fCheckedPic->GetName()))
             << quote << ");" << endl;
      }
      if (olduncheck != fUncheckedPic) {
         olduncheck = fUncheckedPic;
         out << "   puncheck = gClient->GetPicture(" << quote
             << gSystem->ExpandPathName(gSystem->UnixPathName(fUncheckedPic->GetName()))
             << quote << ");" << endl;
      }
      out << "   item" << s.Data() << "->SetCheckBoxPictures(pcheck, puncheck);" << endl;
      out << "   item" << s.Data() << "->SetCheckBox(kTRUE);" << endl;
   }
   if (fHasColor) {
      if (oldcolor != fColor) {
         oldcolor = fColor;
         out << "   item" << s.Data() << "->SetColor(" << fColor << ");" << endl;
      }
   }
   if (fTipText.Length() > 0) {
      out << "   item" << s.Data() << "->SetTipText(" << quote
          << GetTipText() << quote << ");" << endl;
   }
}
void TGListTree::CheckItem(TGListTreeItem *item, Bool_t check)
{
   
   item->CheckItem(check);
}
void TGListTree::SetCheckBox(TGListTreeItem *item, Bool_t on)
{
   
   item->SetCheckBox(on);
}
void TGListTree::ToggleItem(TGListTreeItem *item)
{
   
   item->Toggle();
}
void TGListTree::UpdateChecked(TGListTreeItem *item, Bool_t redraw)
{
   
   if (fAutoCheckBoxPic == kFALSE) return;
   TGListTreeItem *parent;
   TGListTreeItem *current;
   current = item->GetFirstChild();
   parent  = current ? current : item;
   
   while (parent && parent->HasCheckBox()) {
      if ((!parent->IsChecked() && parent->HasCheckedChild(kTRUE)) ||
          (parent->IsChecked() && parent->HasUnCheckedChild(kTRUE))) {
         parent->SetCheckBoxPictures(fClient->GetPicture("checked_dis_t.xpm"),
                                     fClient->GetPicture("unchecked_dis_t.xpm"));
      }
      else {
         parent->SetCheckBoxPictures(fClient->GetPicture("checked_t.xpm"),
                                     fClient->GetPicture("unchecked_t.xpm"));
      }
      parent = parent->GetParent();
      if (parent && fCheckMode == kRecursive) {
         if (!parent->IsChecked() && parent->GetFirstChild() && 
             !parent->GetFirstChild()->HasUnCheckedChild()) {
            parent->SetCheckBoxPictures(fClient->GetPicture("checked_t.xpm"),
                                        fClient->GetPicture("unchecked_t.xpm"));
            parent->CheckItem(kTRUE);
         }
         else if (parent->IsChecked() && parent->GetFirstChild() && 
                  !parent->GetFirstChild()->HasCheckedChild()) {
            parent->SetCheckBoxPictures(fClient->GetPicture("checked_t.xpm"),
                                        fClient->GetPicture("unchecked_t.xpm"));
            parent->CheckItem(kFALSE);
         }
      }
   }
   if (redraw) {
      ClearViewPort();
   }
}
TGListTreeItem *TGListTree::FindItemByObj(TGListTreeItem *item, void *ptr)
{
   
   
   TGListTreeItem *fitem;
   if (item && ptr) {
      if (item->GetUserData() == ptr)
         return item;
      else {
         if (item->fFirstchild) {
            fitem = FindItemByObj(item->fFirstchild,  ptr);
            if (fitem) return fitem;
         }
         return FindItemByObj(item->fNextsibling, ptr);
      }
   }
   return 0;
}
void TGListTree::GetChecked(TList *checked)
{
   
   
   
   
   if (!checked || !fFirst) return;
   TGListTreeItem *current = fFirst;
   if (current->IsChecked()) {
      checked->Add(new TObjString(current->GetText()));
   }
   while(current) {
      if (current->GetFirstChild())
         GetCheckedChildren(checked, current->GetFirstChild());
      current = current->GetNextSibling();
   }
}
void TGListTree::GetCheckedChildren(TList *checked, TGListTreeItem *item)
{
   
   if (!checked || !item) return;
   while (item) {
      if (item->IsChecked()) {
         checked->Add(new TObjString(item->GetText()));
      }
      if (item->GetFirstChild()) {
         GetCheckedChildren(checked, item->GetFirstChild());
      }
      item = item->GetNextSibling();
   }
}
void TGListTree::CheckAllChildren(TGListTreeItem *item, Bool_t state)
{
   
   
   
   if (item) 
      item->CheckAllChildren(state);
}
Last change: Wed Jun 25 08:41:50 2008
Last generated: 2008-06-25 08:41
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.