#include "TGPicture.h"
#include "TGListBox.h"
#include "TGScrollBar.h"
#include "TGResourcePool.h"
#include "TSystem.h"
#include "Riostream.h"
const TGFont *TGTextLBEntry::fgDefaultFont = 0;
TGGC         *TGTextLBEntry::fgDefaultGC = 0;
ClassImp(TGLBEntry)
ClassImp(TGTextLBEntry)
ClassImp(TGLineLBEntry)
ClassImp(TGLBContainer)
ClassImp(TGListBox)
TGLBEntry::TGLBEntry(const TGWindow *p, Int_t id, UInt_t options, Pixel_t back) :
             TGFrame(p, 10, 10, options | kOwnBackground, back)
{
   
   fActive = kFALSE;
   fEntryId = id;
   fBkcolor = back;
   fEditDisabled = kEditDisable | kEditDisableGrab;
   SetWindowName();
}
void TGLBEntry::Activate(Bool_t a)
{
   
   if (fActive == a) return;
   fActive = a;
   fClient->NeedRedraw(this);
}
void TGLBEntry::Toggle()
{
   
   fActive = !fActive;
   fClient->NeedRedraw(this);
}
TGTextLBEntry::TGTextLBEntry(const TGWindow *p, TGString *s, Int_t id,
      GContext_t norm, FontStruct_t font, UInt_t options, ULong_t back) :
   TGLBEntry(p, id, options, back)
{
   
   fText        = s;
   fTextChanged = kTRUE;
   fFontStruct  = font;
   fNormGC      = norm;
   int max_ascent, max_descent;
   if (fText) fTWidth  = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;
   Resize(fTWidth, fTHeight + 1);
   fEditDisabled = kEditDisable | kEditDisableGrab;
   SetWindowName();
}
TGTextLBEntry::~TGTextLBEntry()
{
   
   if (fText) delete fText;
}
void TGTextLBEntry::DrawCopy(Handle_t id, Int_t x, Int_t y)
{
   
   int max_ascent, max_descent;
   y += (fHeight - fTHeight) >> 1;
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   if (fActive) {
      gVirtualX->SetForeground(fNormGC, fgDefaultSelectedBackground );
      gVirtualX->FillRectangle(id,fNormGC, x, y, fWidth, fHeight); 
      gVirtualX->SetForeground(fNormGC, fClient->GetResourcePool()->GetSelectedFgndColor());
      fText->Draw(id, fNormGC, x + 3, y + max_ascent);
   } else {
      gVirtualX->SetForeground(fNormGC, fBkcolor);
      gVirtualX->FillRectangle(id, fNormGC, x, y, fWidth, fHeight);
      gVirtualX->SetForeground(fNormGC, GetForeground());
      fText->Draw(id, fNormGC, x + 3, y + max_ascent);
   }
}
void TGTextLBEntry::DoRedraw()
{
   
   DrawCopy(fId, 0, 0);
}
void TGTextLBEntry::SetText(TGString *new_text)
{
   
   if (fText) delete fText;
   fText = new_text;
   fTextChanged = kTRUE;
   int max_ascent, max_descent;
   fTWidth = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;
   Resize(fTWidth + 3, fTHeight + 1);
   fClient->NeedRedraw(this);
}
FontStruct_t TGTextLBEntry::GetDefaultFontStruct()
{
   
   
   if (!fgDefaultFont)
      fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
   return fgDefaultFont->GetFontStruct();
}
const TGGC &TGTextLBEntry::GetDefaultGC()
{
   
   if (!fgDefaultGC)
      fgDefaultGC = new TGGC(*gClient->GetResourcePool()->GetFrameGC());
   return *fgDefaultGC;
}
TGLineLBEntry::TGLineLBEntry(const TGWindow *p, Int_t id, const char *str,
                             UInt_t w, Style_t style, UInt_t options, ULong_t back) :
   TGTextLBEntry(p, new TGString(str), id, GetDefaultGC()(),
                 GetDefaultFontStruct(), options, back)
{
   
   GCValues_t gcv;
   gcv.fMask =  kGCLineStyle | kGCLineWidth | kGCFillStyle | kGCDashList;
   fLineWidth = gcv.fLineWidth  = w;
   gcv.fFillStyle  = kFillSolid;
   gcv.fDashLen = 2;
   gcv.fDashOffset = 0;
   memcpy(gcv.fDashes, "\x5\x5", 3);
   gcv.fLineStyle = kLineOnOffDash;
   fLineGC = fClient->GetGC(&gcv, kTRUE);
   SetLineStyle(style);
   int max_ascent, max_descent;
   fTWidth  = gVirtualX->TextWidth(GetDefaultFontStruct(), "8", 1);
   fTWidth += 15;                     
   gVirtualX->GetFontProperties(GetDefaultFontStruct(),
                                max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;
   Resize(fTWidth, fTHeight + 1);
   fEditDisabled = kEditDisable | kEditDisableGrab;
   SetWindowName();
}
TGLineLBEntry::~TGLineLBEntry()
{
   
   fClient->FreeGC(fLineGC);
}
void  TGLineLBEntry::Update(TGLBEntry *e)
{
   
   TGTextLBEntry::Update(e);
   fClient->FreeGC(fLineGC);
   fLineGC = ((TGLineLBEntry *)e)->GetLineGC();
   fLineGC->AddReference();
}
void TGLineLBEntry::SetLineStyle(Style_t linestyle)
{
   
   static const char* dashed = "\x3\x3";
   static const char* dotted= "\x1\x2";
   static const char* dasheddotted = "\x3\x4\x1\x4";
   static const char* ls05 = "\x5\x3\x1\x3";
   static const char* ls06 = "\x5\x3\x1\x3\x1\x3\x1\x3";
   static const char* ls07 = "\x5\x5";
   static const char* ls08 = "\x5\x3\x1\x3\x1\x3";
   static const char* ls09 = "\x20\x5";
   static const char* ls10 = "\x20\x10\x1\x10";
   if (linestyle <= 1)  {
      fLineGC->SetLineStyle(kLineSolid);
   } else {
      switch (linestyle) {
         case 2:
            fLineGC->SetDashList(dashed, 2);
            break;
         case 3:
            fLineGC->SetDashList(dotted, 2);
            break;
         case 4:
            fLineGC->SetDashList(dasheddotted, 4);
            break;
         case 5:
            fLineGC->SetDashList(ls05, 4);
            break;
         case 6:
            fLineGC->SetDashList(ls06, 8);
            break;
         case 7:
            fLineGC->SetDashList(ls07, 2);
            break;
         case 8:
            fLineGC->SetDashList(ls08, 6);
            break;
         case 9:
            fLineGC->SetDashList(ls09, 2);
            break;
         case 10:
            fLineGC->SetDashList(ls10, 4);
            break;
      }
   }
   fLineGC->SetCapStyle(0); 
   fLineStyle = linestyle;
}
void TGLineLBEntry::SetLineWidth(Int_t width)
{
   
   fLineWidth = width;
   fLineGC->SetLineWidth(fLineWidth);
}
void TGLineLBEntry::DrawCopy(Handle_t id, Int_t x, Int_t y)
{
   
   TGTextLBEntry::DrawCopy(id, x, y);
   if (!strcmp(TGTextLBEntry::GetTitle(),"None")) return;
   if (fActive) {
      gVirtualX->SetForeground(fLineGC->GetGC(),
                               fClient->GetResourcePool()->GetSelectedFgndColor());
   } else {
      gVirtualX->SetForeground(fLineGC->GetGC(),
                               fClient->GetResourcePool()->GetBlackColor());
   }
   gVirtualX->DrawLine(id, fLineGC->GetGC(), x + fTWidth + 5, y + fHeight/2,
                       x + fWidth - 5, y + fHeight/2);
}
void TGLineLBEntry::DoRedraw()
{
   
   DrawCopy(fId, 0, 0);
}
TGIconLBEntry::TGIconLBEntry(const TGWindow *p, Int_t id, const char *str,
                             const TGPicture *pic,
                             UInt_t , Style_t , UInt_t options, ULong_t back) :
   TGTextLBEntry(p, new TGString(str), id, GetDefaultGC()(),
                 GetDefaultFontStruct(), options, back)
{
   
   int max_ascent, max_descent;
   fPicture = pic;
   if (fPicture) {
      fTWidth += fPicture->GetWidth() + 4;
      ((TGPicture *)pic)->AddReference();
   }
   else 
      fTWidth += 20;
   gVirtualX->GetFontProperties(GetDefaultFontStruct(),
                                max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;
   if (fPicture->GetHeight() > fTHeight)
      fTHeight = fPicture->GetHeight();
   Resize(fTWidth, fTHeight + 1);
   fEditDisabled = kEditDisable | kEditDisableGrab;
   SetWindowName();
}
TGIconLBEntry::~TGIconLBEntry()
{
   
   
   fClient->FreePicture(fPicture);
}
void  TGIconLBEntry::Update(TGLBEntry *e)
{
   
   TGTextLBEntry::Update(e);
}
void TGIconLBEntry::DrawCopy(Handle_t id, Int_t x, Int_t y)
{
   
   
   Int_t off_x = 0;
   if (fPicture) {
      fPicture->Draw(id, fNormGC, x + 2, y);
      off_x = fPicture->GetWidth() + 4;
   }
   TGTextLBEntry::DrawCopy(id, x + off_x, y);
}
void TGIconLBEntry::DoRedraw()
{
   
   DrawCopy(fId, 0, 0);
}
void TGIconLBEntry::SetPicture(const TGPicture *pic)
{
   
   fClient->FreePicture(fPicture);
   ((TGPicture *)pic)->AddReference();
   fPicture   = pic;
}
class TGLBFrameElement : public TGFrameElement {
public:
   TGLBFrameElement(TGFrame *f, TGLayoutHints *l) : TGFrameElement(f, l) {}
   virtual ~TGLBFrameElement() {}
   Bool_t IsSortable() const { return kTRUE; }
   Int_t  Compare(const TObject *obj) const {
      if (!fFrame->InheritsFrom(TGTextLBEntry::Class())) {
         return 0;
      }
      TGTextLBEntry *f1 = (TGTextLBEntry*)fFrame;
      TGTextLBEntry *f2 = (TGTextLBEntry *) ((TGFrameElement *) obj)->fFrame;
      double d1, d2;
      const char *t1 = f1->GetText()->Data();
      const char *t2 = f2->GetText()->Data();
      if ((d1 = atof(t1)) && (d2 = atof(t2))) {
         return (d1 > d2);
      } else {
         return strcmp(t1, t2);
      }
      return 0;
   }
};
TGLBContainer::TGLBContainer(const TGWindow *p, UInt_t w, UInt_t h,
                             UInt_t options, ULong_t back) :
   TGContainer(p, w, h, options, back)
{
   
   fLastActive = 0;
   fMsgWindow  = p;
   fMultiSelect = kFALSE;
   fChangeStatus = kFALSE;
   SetWindowName();
   fEditDisabled = kEditDisableGrab | kEditDisableBtnEnable | kEditDisableKeyEnable;
}
TGLBContainer::~TGLBContainer()
{
   
   Cleanup();
}
void TGLBContainer::Layout()
{
   
   TGContainer::Layout();
   TGFrame::Resize(fListBox->GetViewPort()->GetWidth(), fHeight);
}
void TGLBContainer::AddEntry(TGLBEntry *lbe, TGLayoutHints *lhints)
{
   
   
   lbe->SetBackgroundColor(fgWhitePixel);
   TGLBFrameElement *nw = new TGLBFrameElement(lbe, lhints ? lhints : fgDefaultHints);
   fList->Add(nw);
   fClient->NeedRedraw(this);
}
void TGLBContainer::InsertEntry(TGLBEntry *lbe, TGLayoutHints *lhints, Int_t afterID)
{
   
   
   
   lbe->SetBackgroundColor(fgWhitePixel);
   TGLBEntry      *e;
   TGFrameElement *el, *nw;
   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      e = (TGLBEntry *) el->fFrame;
      if (e->EntryId() == afterID) break;
   }
   if (!el && afterID != -1) {
      nw = new TGLBFrameElement(lbe, lhints ? lhints : fgDefaultHints);
      fList->Add(nw);
   } else {
      nw = new TGLBFrameElement(lbe, lhints);
      nw->fFrame  = lbe;
      nw->fLayout = lhints;
      nw->fState  = 1;
      
      if (afterID == -1)
         fList->AddFirst(nw);
      else
         fList->AddAfter(el, nw);
   }
   fClient->NeedRedraw(this);
}
void TGLBContainer::AddEntrySort(TGLBEntry *lbe, TGLayoutHints *lhints)
{
   
   
   lbe->SetBackgroundColor(fgWhitePixel);
   TGLBEntry      *e;
   TGFrameElement *el, *nw;
   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      e = (TGLBEntry *) el->fFrame;
      if (e->EntryId() > lbe->EntryId()) break;
   }
   if (!el) {
      nw = new TGLBFrameElement(lbe, lhints ? lhints : fgDefaultHints);
      fList->Add(nw);
   } else {
      nw = new TGLBFrameElement(lbe, lhints);
      nw->fFrame  = lbe;
      nw->fLayout = lhints;
      nw->fState  = 1;
      
      fList->AddBefore(el, nw);
   }
   fClient->NeedRedraw(this);
}
void TGLBContainer::RemoveEntry(Int_t id)
{
   
   
   TGLBEntry      *e;
   TGFrameElement *el;
   TGLayoutHints  *l;
   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      e = (TGLBEntry *) el->fFrame;
      l = el->fLayout;
      if (e->EntryId() == id) {
         if (fLastActive == e) fLastActive = 0;
         e->DestroyWindow();
         fList->Remove(el);  
         delete el;          
         delete e;
         delete l;
         break;
      }
   }
   fClient->NeedRedraw(this);
}
void TGLBContainer::RemoveEntries(Int_t from_ID, Int_t to_ID)
{
   
   
   TGLBEntry      *e;
   TGFrameElement *el;
   TGLayoutHints  *l;
   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      e = (TGLBEntry *) el->fFrame;
      l = el->fLayout;
      if ((e->EntryId() >= from_ID) && (e->EntryId() <= to_ID)) {
         if (fLastActive == e) fLastActive = 0;
         e->DestroyWindow();
         fList->Remove(el);  
         delete el;          
         delete e;
         delete l;
      }
   }
   fClient->NeedRedraw(this);
}
void TGLBContainer::RemoveAll()
{
   
 
   TGLBEntry      *e;
   TGFrameElement *el;
   TGLayoutHints  *l;
   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      e = (TGLBEntry *) el->fFrame;
      l = el->fLayout;
      if (fLastActive == e) fLastActive = 0;
      e->DestroyWindow();
      fList->Remove(el);  
      delete el;          
      delete e;
      delete l;
   }
   fClient->NeedRedraw(this);
}  
TGLBEntry *TGLBContainer::Select(Int_t id)
{
   
   
   return Select(id, kTRUE);
}
TGLBEntry *TGLBContainer::Select(Int_t id, Bool_t sel)
{
   
   
   TGLBEntry      *f;
   TGFrameElement *el;
   if (fLastActive) {
      fLastActive->Activate(kFALSE);
      fLastActive = 0;
   }
   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      f = (TGLBEntry *) el->fFrame;
      if (f->EntryId() == id) {
         f->Activate(sel);
         if (fMultiSelect == kFALSE && sel == kTRUE) {
            fLastActive = f;
            fLastActiveEl = el;
         }
         fClient->NeedRedraw(this);
         return f;
      }
   }
   return 0;
}
Int_t TGLBContainer::GetSelected() const
{
   
   
   if (fLastActive == 0) return -1;
   return fLastActive->EntryId();
}
Bool_t TGLBContainer::GetSelection(Int_t id)
{
   
   TGLBEntry     *f;
   TGFrameElement *el;
   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      f = (TGLBEntry *) el->fFrame;
      if (f->EntryId() == id)
         return f->IsActive();
   }
   return kFALSE;
}
void TGLBContainer::GetSelectedEntries(TList *selected)
{
   
   
   TGLBEntry      *f;
   TGFrameElement *el;
   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      f = (TGLBEntry *) el->fFrame;
      if (f->IsActive()) {
         selected->Add(f);
      }
   }
}
void TGLBContainer::SetMultipleSelections(Bool_t multi)
{
   
   TGFrameElement *el;
   fMultiSelect = multi;
   if (!fMultiSelect) {
      
      TIter next(fList);
      while ((el = (TGFrameElement *) next())) {
         ((TGLBEntry *)(el->fFrame))->Activate(kFALSE);
      }
   }
   fLastActive = 0;
   fLastActiveEl = 0;
   fClient->NeedRedraw(this);
}
TGVScrollBar *TGLBContainer::GetVScrollbar() const
{
   
   return fListBox ? fListBox->GetVScrollbar() : 0;
}
void TGLBContainer::SetVsbPosition(Int_t newPos)
{
   
   TGVScrollBar *vb = GetVScrollbar();
   if (vb && vb->IsMapped()) {
      vb->SetPosition(newPos);
   }
}
Bool_t TGLBContainer::HandleButton(Event_t *event)
{
   
   int xf0, yf0, xff, yff;
   TGLBEntry *f;
   TGFrameElement *el;
   TGLBEntry *last = fLastActive;
   TGPosition pos = GetPagePosition();
   Int_t x = pos.fX + event->fX;
   Int_t y = pos.fY + event->fY;
   Bool_t activate = kFALSE;
   
   if (fClient->IsEditable() && (event->fCode == kButton3)) {
      return kTRUE;
   }
   TGVScrollBar *vb = GetVScrollbar();
   if ((event->fCode == kButton4) && vb){
      
      Int_t newpos = vb->GetPosition() - 1;
      if (newpos < 0) newpos = 0;
      vb->SetPosition(newpos);
      fClient->NeedRedraw(this);
      return kTRUE;
   }
   if ((event->fCode == kButton5) && vb) {
      
      Int_t newpos = vb->GetPosition() + 1;
      vb->SetPosition(newpos);
      fClient->NeedRedraw(this);
      return kTRUE;
   }
   gVirtualX->SetInputFocus(fId);
   if (fMultiSelect) {
      if (event->fType == kButtonPress) {
         TIter next(fList);
         while ((el = (TGFrameElement *) next())) {
            f = (TGLBEntry *) el->fFrame;
            xf0 = f->GetX();
            yf0 = f->GetY();
            xff = xf0 + f->GetWidth();
            yff = yf0 + f->GetHeight();
            activate = fMapSubwindows ? (f->GetId() == (Window_t)event->fUser[0]) :
                        (x > xf0) && (x < xff) && (y > yf0) &&  (y < yff);
            if (activate)  {
               fLastActive = f;
               fLastActiveEl = el;
               f->Toggle();
               fChangeStatus = f->IsActive() ? 1 : 0;
               SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
                           f->EntryId(), 0);
               break;
            }
         }
      } else {
         fChangeStatus = -1;
      }
   } else {
      if (event->fType == kButtonPress) {
         if (fLastActive) {
            fLastActive->Activate(kFALSE);
            fLastActive = 0;
         }
         TIter next(fList);
         while ((el = (TGFrameElement *) next())) {
            f = (TGLBEntry *) el->fFrame;
            xf0 = f->GetX();
            yf0 = f->GetY();
            xff = xf0 + f->GetWidth();
            yff = yf0 + f->GetHeight();
            activate = fMapSubwindows ? (f->GetId() == (Window_t)event->fUser[0]) :
                        (x > xf0) && (x < xff) && (y > yf0) &&  (y < yff) && !f->IsActive();
            if (activate)  {
               f->Activate(kTRUE);
               fLastActive = f;
               fLastActiveEl = el;
            } else {
               f->Activate(kFALSE);
            }
         }
      } else {
         if (fLastActive) {
            f = fLastActive;
            SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
                        f->EntryId(), 0);
         }
      }
   }
   if (event->fType == kButtonRelease) {
      fScrolling = kFALSE;
      gSystem->RemoveTimer(fScrollTimer);
   }
   if (fChangeStatus || (last != fLastActive)) fClient->NeedRedraw(this);
   return kTRUE;
}
Bool_t TGLBContainer::HandleMotion(Event_t *event)
{
   
   int xf0, yf0, xff, yff;
   static Long_t was = gSystem->Now();
   Long_t now = (long)gSystem->Now();
   if ((now-was) < 50) return kFALSE;
   was = now;
   TGLBEntry *f;
   TGFrameElement *el;
   TGPosition pos = GetPagePosition();
   TGDimension dim = GetPageDimension();
   Int_t x = pos.fX + event->fX;
   Int_t y = pos.fY + event->fY;
   Bool_t activate = kFALSE;
   TGLBEntry *last = fLastActive;
   if (fMultiSelect) {
      if ((event->fY < 10) || (event->fY > Int_t(dim.fHeight) - 10)) {
         if (!fScrolling) {
            fScrollTimer->Reset();
            gSystem->AddTimer(fScrollTimer);
         }
         fScrolling = kTRUE;
      }
      else if (fChangeStatus >= 0) {
         TIter next(fList);
         while ((el = (TGFrameElement *) next())) {
            f = (TGLBEntry *) el->fFrame;
            xf0 = f->GetX();
            yf0 = f->GetY();
            xff = xf0 + f->GetWidth();
            yff = yf0 + f->GetHeight();
            activate = fMapSubwindows ? (f->GetId() == (Window_t)event->fUser[0]) :
                        (x > xf0) && (x < xff) && (y > yf0) &&  (y < yff);
            if (activate) {
               if (fChangeStatus != (f->IsActive() ? 1 : 0)) {
                  f->Toggle();
                  fClient->NeedRedraw(this);
                  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
                              f->EntryId(), 0);
               }
               break;
            }
         }
      }
   } else if (fListBox->GetParent()->InheritsFrom("TGComboBoxPopup")) {
      TIter next(fList);
      while ((el = (TGFrameElement *) next())) {
         f = (TGLBEntry *) el->fFrame;
         xf0 = f->GetX();
         yf0 = f->GetY();
         xff = xf0 + f->GetWidth();
         yff = yf0 + f->GetHeight();
         activate = fMapSubwindows ? (f->GetId() == (Window_t)event->fUser[0]) :
                        (x > xf0) && (x < xff) && (y > yf0) &&  (y < yff)  && !f->IsActive();;
         if (activate)  {
            f->Activate(kTRUE);
            fLastActive = f;
         } else {
            f->Activate(kFALSE);
         }
         if (last != fLastActive) fClient->NeedRedraw(this);
      }
   }
   return kTRUE;
}
void TGLBContainer::OnAutoScroll()
{
   
   TGFrameElement* el = 0;
   TGLBEntry *f = 0;
   Int_t yf0, yff;
   Bool_t changed = kFALSE;
   TGDimension dim = GetPageDimension();
   TGPosition pos = GetPagePosition();
   Window_t  dum1, dum2;
   Event_t   ev;
   ev.fType  = kButtonPress;
   Int_t     x, y;
   
   gVirtualX->QueryPointer(fId,dum1,dum2,ev.fXRoot,ev.fYRoot,x,y,ev.fState);
   TGVScrollBar *vb = GetVScrollbar();
   if (y > 0 && y < 10) {
      
      Int_t newpos = vb->GetPosition() - 1;
      if (newpos < 0) newpos = 0;
      vb->SetPosition(newpos);
      changed = kTRUE;
   }
   else if (y > (Int_t)dim.fHeight - 10 && y < (Int_t)dim.fHeight) {
      
      Int_t newpos = vb->GetPosition() + 1;
      vb->SetPosition(newpos);
      changed = kTRUE;
   }
   if (changed && fChangeStatus >= 0) {
      pos = GetPagePosition();
      TIter next(fList);
      while ((el = (TGFrameElement *) next())) {
         f = (TGLBEntry *) el->fFrame;
         yf0 = f->GetY();
         yff = yf0 + f->GetHeight();
         if ((y + pos.fY > yf0) && (y + pos.fY < yff)) {
            if (fChangeStatus != (f->IsActive() ? 1 : 0)) {
               f->Toggle();
               fClient->NeedRedraw(this);
               SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
                           f->EntryId(), 0);
            }
            break;
         }
      }
   }
}
Int_t TGLBContainer::GetPos(Int_t id)
{
   
   
   
   Int_t          pos = 0;
   TGLBEntry      *f;
   TGFrameElement *el;
   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      f = (TGLBEntry *) el->fFrame;
      if (f->EntryId() == id)
         return pos;
      pos++;
   }
   return -1;
}
TGListBox::TGListBox(const TGWindow *p, Int_t id,
                     UInt_t options, ULong_t back) :
   TGCompositeFrame(p, 10, 10, options, back)
{
   
   fMsgWindow = p;
   fWidgetId  = id;
   fItemVsize = 1;
   fIntegralHeight = kTRUE;
   InitListBox();
}
TGListBox::~TGListBox()
{
   
   if (!MustCleanup()) {
      delete fVScrollbar;
      delete fVport;
      delete fLbc;
   }
}
void TGListBox::InitListBox()
{
   
   fVport = new TGViewPort(this, 6, 6, kChildFrame | kOwnBackground, fgWhitePixel);
   fVScrollbar = new TGVScrollBar(this, kDefaultScrollBarWidth, 6);
   fLbc = new TGLBContainer(fVport, 10, 10, kVerticalFrame, fgWhitePixel);
   fLbc->fViewPort = fVport;
   fLbc->Associate(this);
   fLbc->SetListBox(this);
   SetContainer(fLbc);
   AddFrame(fVport, 0);
   AddFrame(fVScrollbar, 0);
   fVScrollbar->Associate(this);
   fVScrollbar->AddInput(kButtonPressMask | kButtonReleaseMask | 
                         kPointerMotionMask);
   fLbc->RemoveInput(kPointerMotionMask);
   fLbc->AddInput(kButtonPressMask | kButtonReleaseMask | kButtonMotionMask);
   fVport->SetEditDisabled(kEditDisable | kEditDisableGrab);
   fVScrollbar->SetEditDisabled(kEditDisable | kEditDisableGrab | kEditDisableBtnEnable);
   fLbc->SetEditDisabled(kEditDisableGrab | kEditDisableBtnEnable | kEditDisableKeyEnable);
   fEditDisabled = kEditDisableLayout;
   
   delete fLayoutManager;
   fLayoutManager = 0;
}
void TGListBox::DrawBorder()
{
   
   switch (fOptions & (kSunkenFrame | kRaisedFrame | kDoubleBorder)) {
      case kSunkenFrame | kDoubleBorder:
         gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, fWidth-2, 0);
         gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, 0, fHeight-2);
         gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, fWidth-3, 1);
         gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, 1, fHeight-3);
         gVirtualX->DrawLine(fId, GetHilightGC()(), 0, fHeight-1, fWidth-1, fHeight-1);
         gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth-1, fHeight-1, fWidth-1, 0);
         gVirtualX->DrawLine(fId, GetBckgndGC()(),  1, fHeight-2, fWidth-2, fHeight-2);
         gVirtualX->DrawLine(fId, GetBckgndGC()(),  fWidth-2, 1, fWidth-2, fHeight-2);
         break;
      default:
         TGCompositeFrame::DrawBorder();
         break;
   }
}
void TGListBox::AddEntry(TGString *s, Int_t id)
{
   
   
   
   TGTextLBEntry *lbe;
   TGLayoutHints *lhints;
   lbe = new TGTextLBEntry(fLbc, s, id);
   lhints = new TGLayoutHints(kLHintsExpandX | kLHintsTop);
   fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
   fLbc->AddEntry(lbe, lhints);
}
void TGListBox::AddEntry(const char *s, Int_t id)
{
   
   
   AddEntry(new TGString(s), id);
}
void TGListBox::AddEntry(TGLBEntry *lbe, TGLayoutHints *lhints)
{
   
   
   fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
   fLbc->AddEntry(lbe, lhints);
}
void TGListBox::AddEntrySort(TGString *s, Int_t id)
{
   
   
   
   
   
   TGTextLBEntry *lbe;
   TGLayoutHints *lhints;
   lbe = new TGTextLBEntry(fLbc, s, id);
   lhints = new TGLayoutHints(kLHintsExpandX | kLHintsTop);
   fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
   fLbc->AddEntrySort(lbe, lhints);
}
void TGListBox::AddEntrySort(const char *s, Int_t id)
{
   
   
   
   
   AddEntrySort(new TGString(s), id);
}
void TGListBox::AddEntrySort(TGLBEntry *lbe, TGLayoutHints *lhints)
{
   
   
   
   
   fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
   fLbc->AddEntrySort(lbe, lhints);
}
void TGListBox::InsertEntry(TGString *s, Int_t id, Int_t afterID)
{
   
   
   TGTextLBEntry *lbe;
   TGLayoutHints *lhints;
   lbe = new TGTextLBEntry(fLbc, s, id);
   lhints = new TGLayoutHints(kLHintsExpandX | kLHintsTop);
   fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
   fLbc->InsertEntry(lbe, lhints, afterID);
}
void TGListBox::InsertEntry(const char *s, Int_t id, Int_t afterID)
{
   
   InsertEntry(new TGString(s), id, afterID);
}
void TGListBox::NewEntry(const char *s)
{
   
   Int_t selected = fLbc->GetSelected();
   
   if ((selected < 0) || (selected == GetNumberOfEntries())) {
      AddEntry(s, GetNumberOfEntries()+1);
   } else {
      InsertEntry(s, GetNumberOfEntries()+1, selected);
   }
   Layout();
} 
void TGListBox:: RemoveEntry(Int_t id)
{
   
   
   
   if (id > 0) {
      fLbc->RemoveEntry(id);
      Layout();
      return;
   }
   if (!fLbc->GetMultipleSelections()) {
      fLbc->RemoveEntry(fLbc->GetSelected());
      Layout();
      return;
   }
   TList li;
   fLbc->GetSelectedEntries(&li);
   TGLBEntry *e;
   TIter next(&li);
   while ((e = (TGLBEntry*)next())) {
      fLbc->RemoveEntry(e->EntryId());
   }
   Layout();
}
void TGListBox::RemoveAll()
{
   
   
   fLbc->RemoveAll();
   Layout();
}
void TGListBox::RemoveEntries(Int_t from_ID, Int_t to_ID)
{
   
   
   fLbc->RemoveEntries(from_ID, to_ID);
   Layout();
}
void TGListBox::InsertEntry(TGLBEntry *lbe, TGLayoutHints *lhints, int afterID)
{
   
   
   fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
   fLbc->InsertEntry(lbe, lhints, afterID);
}
TGLBEntry *TGListBox::GetEntry(Int_t id) const
{
   
   TIter next(fLbc->GetList());
   TGFrameElement *el;
   while ((el = (TGFrameElement *)next())) {
      TGLBEntry *lbe = (TGLBEntry *)el->fFrame;
      if (lbe->EntryId() == id) return lbe;
   }
   return 0;
}
void TGListBox::SetTopEntry(Int_t id)
{
   
   Int_t idPos;
   idPos = fLbc->GetPos(id);
   
   if (idPos < 0)
      return;
   
   Layout();
   
   
   
   
   fVScrollbar->SetPosition(idPos);
}
void TGListBox::Resize(UInt_t w, UInt_t h)
{
   
   
   if (fIntegralHeight)
      h = TMath::Max(fItemVsize, ((h - (fBorderWidth << 1)) / fItemVsize) * fItemVsize)
                     + (fBorderWidth << 1);
   TGCompositeFrame::Resize(w, h);
   fClient->NeedRedraw(this);
}
void TGListBox::MoveResize(Int_t x, Int_t y, UInt_t w, UInt_t h)
{
   
   if (fIntegralHeight)
      h = TMath::Max(fItemVsize, ((h - (fBorderWidth << 1)) / fItemVsize) * fItemVsize)
                     + (fBorderWidth << 1);
   TGCompositeFrame::MoveResize(x, y, w, h);
   fClient->NeedRedraw(this);
}
TGDimension TGListBox::GetDefaultSize() const
{
   
   UInt_t h;
   if (fIntegralHeight)
      h = TMath::Max(fItemVsize, ((fHeight - (fBorderWidth << 1)) / fItemVsize) * fItemVsize)
                     + (fBorderWidth << 1);
   else
      h = fHeight;
   return TGDimension(fWidth, h);
}
void TGListBox::Layout()
{
   
   TGFrame *container;
   UInt_t   cw, ch, tch;
   Bool_t   need_vsb;
   need_vsb = kFALSE;
   container = fVport->GetContainer();
   
   cw = fWidth - (fBorderWidth << 1);
   ch = fHeight - (fBorderWidth << 1);
   container->SetWidth(cw);
   container->SetHeight(ch);
   if (container->GetDefaultHeight() > ch) {
      need_vsb = kTRUE;
      cw -= fVScrollbar->GetDefaultWidth();
      if ((Int_t) cw < 0) {
         Warning("Layout", "width would become too small, setting to 10");
         cw = 10;
      }
      container->SetWidth(cw);
   }
   fVport->MoveResize(fBorderWidth, fBorderWidth, cw, ch);
   container->Layout();
   tch = TMath::Max(container->GetDefaultHeight(), ch);
   container->SetHeight(0); 
   container->Resize(cw, tch);
   
   if (need_vsb) {
      fVScrollbar->MoveResize(cw+fBorderWidth, fBorderWidth, fVScrollbar->GetDefaultWidth(), ch);
      fVScrollbar->MapWindow();
   } else {
      fVScrollbar->UnmapWindow();
      fVScrollbar->SetPosition(0);
   }
   fVScrollbar->SetRange(container->GetHeight()/fItemVsize, fVport->GetHeight()/fItemVsize);
   fClient->NeedRedraw(container);
}
void TGListBox::SortByName(Bool_t ascend)
{
   
   fLbc->GetList()->Sort(ascend);
   Layout();
   fClient->NeedRedraw(fLbc);
}
Int_t TGListBox::GetSelected() const
{
   
   TGLBContainer *ct = (TGLBContainer *) fVport->GetContainer();
   return ct->GetSelected();
}
void TGListBox::GetSelectedEntries(TList *selected)
{
   
   
   fLbc->GetSelectedEntries(selected);
}
void TGListBox::ChangeBackground(Pixel_t back)
{
   
   fBackground = back;
   TIter next(fLbc->GetList());
   TGFrameElement *el;
   while ((el = (TGFrameElement *)next())) {
      TGLBEntry *lbe = (TGLBEntry *)el->fFrame;
      lbe->SetBackgroundColor(back);
   }
   fClient->NeedRedraw(fLbc);
}
Bool_t TGListBox::ProcessMessage(Long_t msg, Long_t parm1, Long_t)
{
   
   
   switch (GET_MSG(msg)) {
      case kC_VSCROLL:
         switch (GET_SUBMSG(msg)) {
            case kSB_SLIDERTRACK:
            case kSB_SLIDERPOS:
               fVport->SetVPos(Int_t(-parm1 * fItemVsize));
               break;
         }
         break;
      case kC_CONTAINER:
         switch (GET_SUBMSG(msg)) {
            case kCT_ITEMCLICK:
               {
                  SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_LISTBOX),
                              fWidgetId, parm1);
                  if (GetMultipleSelections()) SelectionChanged();
                  TGLBEntry *entry = GetSelectedEntry();
                  if (entry) {
                     if (entry->InheritsFrom(TGTextLBEntry::Class())) {
                        const char *text;
                        text = ((TGTextLBEntry*)entry)->GetText()->GetString();
                        Selected(text);
                     }
                     Selected(fWidgetId, (Int_t) parm1);
                     Selected((Int_t) parm1);
                  }
               }
            break;
         }
         break;
      default:
         break;
   }
   return kTRUE;
}
void TGListBox::Selected(Int_t widgetId, Int_t id)
{
   
   Long_t args[2];
   args[0] = widgetId;
   args[1] = id;
   Emit("Selected(Int_t,Int_t)", args);
}
TGLBEntry *TGListBox::FindEntry(const char *name) const
{
   
   fLbc->UnSelectAll();
   TGFrameElement *el = (TGFrameElement *)fLbc->FindItem(name);
   return (TGLBEntry *)(el ? el->fFrame : 0);
}
void TGListBox::SavePrimitive(ostream &out, Option_t *option )
{
    
   if (fBackground != GetWhitePixel()) SaveUserColor(out, option);
   out << endl << "   // list box" << endl;
   out<<"   TGListBox *";
   out << GetName() << " = new TGListBox(" << fParent->GetName();
   if (fBackground == GetWhitePixel()) {
      if (GetOptions() == (kSunkenFrame | kDoubleBorder)) {
         if (fWidgetId == -1) {
            out <<");" << endl;
         } else {
            out << "," << fWidgetId << ");" << endl;
         }
      } else {
         out << "," << fWidgetId << "," << GetOptionString() <<");" << endl;
      }
   } else {
      out << "," << fWidgetId << "," << GetOptionString() << ",ucolor);" << endl;
   }
   if (!fLbc->GetList()) return;
   TGFrameElement *el;
   TIter next(fLbc->GetList());
   while ((el = (TGFrameElement *) next())) {
      out << "   " << GetName() << "->AddEntry(";
      el->fFrame->SavePrimitive(out, option);
      out << ");"<< endl;
   }
   out << "   " << GetName() << "->Resize(" << GetWidth() << "," << GetHeight()
       << ");" << endl;
}
void TGTextLBEntry::SavePrimitive(ostream &out, Option_t * )
{
   
   char quote = '"';
   out << quote << GetText()->GetString() << quote << "," << EntryId();
}
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.