<commit_before>// @(#)root/gui:$Id$
// Author: <NAME>   17/01/98

/*************************************************************************
 * Copyright (C) 1995-2000, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/
/**************************************************************************

    This source is based on Xclass95, a Win95-looking GUI toolkit.
    Copyright (C) 1996, 1997 <NAME>, <NAME>, <NAME>.

    Xclass95 is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

**************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGListView, TGLVContainer and TGLVEntry                              //
//                                                                      //
// A list view is a widget that can contain a number of items           //
// arranged in a grid or list. The items can be represented either      //
// by a string or by an icon.                                           //
//                                                                      //
// The TGListView is user callable. The other classes are service       //
// classes of the list view.                                            //
//                                                                      //
// A list view can generate the following events:                       //
// kC_CONTAINER, kCT_SELCHANGED, total items, selected items.           //
// kC_CONTAINER, kCT_ITEMCLICK, which button, location (y<<16|x).       //
// kC_CONTAINER, kCT_ITEMDBLCLICK, which button, location (y<<16|x).    //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGListView.h"
#include "TGPicture.h"
#include "TGButton.h"
#include "TGScrollBar.h"
#include "TGResourcePool.h"
#include "TList.h"
#include "TSystem.h"
#include "TGMimeTypes.h"
#include "TObjString.h"
#include "Riostream.h"

const TGFont *TGLVEntry::fgDefaultFont = 0;
TGGC         *TGLVEntry::fgDefaultGC = 0;

const TGFont *TGListView::fgDefaultFont = 0;
TGGC         *TGListView::fgDefaultGC = 0;


ClassImp(TGLVEntry)
ClassImp(TGLVContainer)
ClassImp(TGListView)

//______________________________________________________________________________
TGLVEntry::TGLVEntry(const TGWindow *p, const TGPicture *bigpic,
                     const TGPicture *smallpic, TGString *name,
                     TGString **subnames, EListViewMode viewMode,
                     UInt_t options, ULong_t back) :
   TGFrame(p, 10, 10, options, back)
{
   // Create a list view item.

   fSelPic = 0;

   fCurrent  =
   fBigPic   = bigpic;
   fSmallPic = smallpic;

   fCheckMark  = fClient->GetPicture("checkmark_t.xpm");
   fChecked = kFALSE;

   fItemName = name;
   fSubnames = subnames;
   fUserData = 0;

   fCpos  =
   fJmode = 0;

   fActive = kFALSE;

   fFontStruct = GetDefaultFontStruct();
   fNormGC     = GetDefaultGC()();

   Int_t max_ascent, max_descent;
   fTWidth = gVirtualX->TextWidth(fFontStruct,
                                  fItemName ? fItemName->GetString() : "",
                                  fItemName ? fItemName->GetLength() : 0);
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;

   if (fSubnames) {
      Int_t i;
      for (i = 0; fSubnames[i] != 0; ++i)
         ;
      fCtw = new int[i+1];
      fCtw[i] = 0;
      for (i = 0; fSubnames[i] != 0; ++i) {
         fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
                                        fSubnames[i]->GetLength());
      }
   } else {
      fCtw = 0;
   }

   fViewMode = (EListViewMode)-1;
   SetViewMode(viewMode);
}

//______________________________________________________________________________
TGLVEntry::TGLVEntry(const TGLVContainer *p, const TString& name,
                     const TString& cname, TGString **subnames,
                     UInt_t options, Pixel_t back) :
   TGFrame(p, 10, 10, options, back)
{
   // Create a list view item.
   //
   // name - is name of item.
   // cname - is name of icon. In most cases this is class name of object
   //         associated with this item.

   fSelPic = 0;

   fCurrent  =
   fBigPic   = fClient->GetMimeTypeList()->GetIcon(cname, kFALSE);
   fCheckMark  = fClient->GetPicture("checkmark_t.xpm");
   fChecked = kFALSE;

   if (!fBigPic) {
      fBigPic = fClient->GetPicture("doc_s.xpm");
   }
   fSmallPic = fClient->GetMimeTypeList()->GetIcon(cname, kTRUE);
   if (!fSmallPic) {
      fSmallPic = fClient->GetPicture("doc_t.xpm");
   }

   fItemName = new TGString(name);
   fSubnames = subnames;
   fUserData = 0;

   fCpos  =
   fJmode = 0;

   fActive = kFALSE;

   fFontStruct = GetDefaultFontStruct();
   fNormGC     = GetDefaultGC()();

   Int_t max_ascent, max_descent;
   fTWidth = gVirtualX->TextWidth(fFontStruct, fItemName->GetString(), fItemName->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;

   if (fSubnames) {
      Int_t i;
      for (i = 0; fSubnames[i] != 0; ++i)
         ;
      fCtw = new int[i+1];
      fCtw[i] = 0;
      for (i = 0; fSubnames[i] != 0; ++i) {
         fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
                                        fSubnames[i]->GetLength());
      }
   } else {
      fCtw = 0;
   }

   fViewMode = (EListViewMode)-1;
   SetViewMode((EListViewMode)p->GetViewMode());
}

//______________________________________________________________________________
TGLVEntry::~TGLVEntry()
{
   // Delete a list view item.

   if (fItemName) delete fItemName;
   if (fSelPic) delete fSelPic;
   if (fSubnames) {
      for (Int_t i = 0; fSubnames[i] != 0; ++i) delete fSubnames[i];
      delete [] fSubnames;
      delete [] fCtw;
   }
}

//______________________________________________________________________________
void TGLVEntry::SetSubnames(const char* n1,const char* n2,const char* n3,
                            const char* n4,const char* n5,const char* n6,
                            const char* n7,const char* n8,const char* n9,
                            const char* n10,const char* n11,const char* n12)
{
   // Sets new subnames.

   if (fSubnames) {
      for (Int_t i = 0; fSubnames[i] != 0; ++i) delete fSubnames[i];
      delete [] fSubnames;
      delete [] fCtw;
   }

   Int_t ncol = 0;
   fSubnames = 0;

   if (n12 && strlen(n12)) ncol=12;
   else if (n11 && strlen(n11)) ncol=11;
   else if (n10 && strlen(n10)) ncol=10;
   else if (n9 && strlen(n9)) ncol=9;
   else if (n8 && strlen(n8)) ncol=8;
   else if (n7 && strlen(n7)) ncol=7;
   else if (n6 && strlen(n6)) ncol=6;
   else if (n5 && strlen(n5)) ncol=5;
   else if (n4 && strlen(n4)) ncol=4;
   else if (n3 && strlen(n3)) ncol=3;
   else if (n2 && strlen(n2)) ncol=2;
   else if (n1 && strlen(n1)) ncol=1;

   if (!ncol) return;

   fSubnames = new TGString* [ncol+1];

   if (ncol>11) fSubnames[11] = new TGString(n12);
   if (ncol>10) fSubnames[10] = new TGString(n11);
   if (ncol>9) fSubnames[9] = new TGString(n10);
   if (ncol>8) fSubnames[8] = new TGString(n9);
   if (ncol>7) fSubnames[7] = new TGString(n8);
   if (ncol>6) fSubnames[6] = new TGString(n7);
   if (ncol>5) fSubnames[5] = new TGString(n6);
   if (ncol>4) fSubnames[4] = new TGString(n5);
   if (ncol>3) fSubnames[3] = new TGString(n4);
   if (ncol>2) fSubnames[2] = new TGString(n3);
   if (ncol>1) fSubnames[1] = new TGString(n2);
   if (ncol>0) fSubnames[0] = new TGString(n1);
   fSubnames[ncol] = 0;

   fCtw = new int[ncol];
   fCtw[ncol-1] = 0;

   for (int i = 0; i<ncol; i++) {
      fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
                                     fSubnames[i]->GetLength());
   }
}

//______________________________________________________________________________
void TGLVEntry::Activate(Bool_t a)
{
   // Make list view item active.

   if (fActive == a) return;
   fActive = a;

   if (fActive) {
      fSelPic = new TGSelectedPicture(gClient, fCurrent);
   } else {
      if (fSelPic) delete fSelPic;
      fSelPic = 0;
   }
   DoRedraw();
}

//______________________________________________________________________________
void TGLVEntry::SetViewMode(EListViewMode viewMode)
{
   // Set the view mode for this list item.

   if (viewMode != fViewMode) {
      fViewMode = viewMode;
      if (viewMode == kLVLargeIcons)
         fCurrent = fBigPic;
      else
         fCurrent = fSmallPic;
      if (fActive) {
         if (fSelPic) delete fSelPic;
         fSelPic = new TGSelectedPicture(gClient, fCurrent);
      }
      gVirtualX->ClearWindow(fId);
      Resize(GetDefaultSize());
      fClient->NeedRedraw(this);
   }
}

//______________________________________________________________________________
void TGLVEntry::SetPictures(const TGPicture *bigpic, const TGPicture *smallpic)
{
   // change pictures

   if (!bigpic || !smallpic) return;

   gVirtualX->ClearWindow(fId);

   fBigPic = bigpic;
   fSmallPic = smallpic;
   fCurrent = fViewMode == kLVLargeIcons ? fBigPic : fSmallPic;

   if (fSelPic) delete fSelPic;
   fSelPic = new TGSelectedPicture(gClient, fCurrent);

   Resize();
   gVirtualX->ClearWindow(fId);
}

//______________________________________________________________________________
void TGLVEntry::DoRedraw()
{
   // Redraw list view item.
   // List view item is placed and layouted in the container frame,
   // but is drawn in viewport.

   DrawCopy(fId, 0, 0);
}

//______________________________________________________________________________
void TGLVEntry::DrawCopy(Handle_t id, Int_t x, Int_t y)
{
   // Draw list view item in other window.
   // List view item is placed and layout in the container frame,
   // but is drawn in viewport.

   Int_t ix, iy, lx, ly;
   Int_t max_ascent, max_descent;

   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTWidth = gVirtualX->TextWidth(fFontStruct, fItemName->GetString(), fItemName->GetLength());
   fTHeight = max_ascent + max_descent;

   if (fViewMode == kLVLargeIcons) {
      ix = (fWidth - fCurrent->GetWidth()) >> 1;
      iy = 0;
      lx = (fWidth - fTWidth) >> 1;
      ly = fHeight - (fTHeight + 1) - 2;
   } else {
      ix = 0;
      iy = (fHeight - fCurrent->GetHeight()) >> 1;
      lx = fCurrent->GetWidth() + 2;
      ly = (fHeight - (fTHeight + 1)) >> 1;
   }

   if ((fChecked) && (fCheckMark)) {
      if (fViewMode == kLVLargeIcons) {
         fCheckMark->Draw(id, fNormGC, x + ix + 8, y + iy + 8);
         gVirtualX->SetForeground(fNormGC, fgWhitePixel);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, fTWidth, fTHeight + 1);
         gVirtualX->SetForeground(fNormGC, fgBlackPixel);
      }
      else {
         fCheckMark->Draw(id, fNormGC, x + ix, y + iy);
         gVirtualX->SetForeground(fNormGC, fgWhitePixel);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, fTWidth, fTHeight + 1);
         gVirtualX->SetForeground(fNormGC, fgBlackPixel);
      }
   }
   // This if tries to print the elements with ... appened at the end if
   // the widht of the string is longer than that of the column
   if (fViewMode == kLVDetails && fSubnames && fCpos && fJmode && fCtw) {
      TString tmpString = *fItemName;
      Int_t ftmpWidth = gVirtualX->TextWidth(fFontStruct, tmpString,
                                             tmpString.Length());
      if ( ftmpWidth > (fCpos[0] - lx) ) {
         for (Int_t j = fItemName->Length() - 1 ; j > 0; j--) {
            tmpString =  (*fItemName)(0,j) + "...";
            ftmpWidth = gVirtualX->TextWidth(GetDefaultFontStruct(), tmpString,
                                             tmpString.Length());
            if ( ftmpWidth <= (fCpos[0] - lx) ) {
               break;
            }
         }
      }
      if (fActive) {
         if (fSelPic) fSelPic->Draw(id, fNormGC, x + ix, y + iy);
         gVirtualX->SetForeground(fNormGC, fgDefaultSelectedBackground);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, ftmpWidth, fTHeight + 1);
         gVirtualX->SetForeground(fNormGC, fClient->GetResourcePool()->GetSelectedFgndColor());
      } else {
         fCurrent->Draw(id, fNormGC, x + ix, y + iy);
         gVirtualX->SetForeground(fNormGC, fgWhitePixel);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, ftmpWidth, fTHeight + 1);
         gVirtualX->SetForeground(fNormGC, fgBlackPixel);
      }

      TGString tmpTGString(tmpString);
      tmpTGString.Draw(id, fNormGC, x+lx, y+ly + max_ascent);
   } else {
      if (fActive) {
         if (fSelPic) fSelPic->Draw(id, fNormGC, x + ix, y + iy);
         gVirtualX->SetForeground(fNormGC, fgDefaultSelectedBackground);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, fTWidth, fTHeight + 1);
         gVirtualX->SetForeground(fNormGC, fClient->GetResourcePool()->GetSelectedFgndColor());
      } else {
         fCurrent->Draw(id, fNormGC, x + ix, y + iy);
         gVirtualX->SetForeground(fNormGC, fgWhitePixel);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, fTWidth, fTHeight + 1);
         gVirtualX->SetForeground(fNormGC, fgBlackPixel);
      }
      fItemName->Draw(id, fNormGC, x+lx, y+ly + max_ascent);
   }
   gVirtualX->SetForeground(fNormGC, fgBlackPixel);

   if (fViewMode == kLVDetails) {
      if (fSubnames && fCpos && fJmode && fCtw) {
         int i;

         // Again fixes the size of the strings
         for (i = 0; fSubnames[i] != 0; ++i) {
            TString tmpString = *fSubnames[i];
            Int_t ftmpWidth = gVirtualX->TextWidth(fFontStruct, tmpString,
                                                   tmpString.Length());
            if ( ftmpWidth > (fCpos[i+1] - fCpos[i]) ) {
               for (int j = fSubnames[i]->Length() - 1 ; j > 0; j--) {
                  tmpString =  (*fSubnames[i])(0,j) + "...";
                  ftmpWidth = gVirtualX->TextWidth(GetDefaultFontStruct(),
                                                   tmpString,
                                                   tmpString.Length());
                  if ( ftmpWidth <= (fCpos[i+1] - fCpos[i]) ) {
                     break;
                  }
               }
            }
            if (fCpos[i] == 0)
               break;
            if (fJmode[i] == kTextRight)
               lx = fCpos[i+1] - ftmpWidth - 2;
            else if (fJmode[i] == kTextCenterX)
               lx = (fCpos[i] + fCpos[i+1] - ftmpWidth) >> 1;
            else // default to TEXT_LEFT
               lx = fCpos[i] + 2;

            //if (x + lx < 0) continue; // out of left boundary or mess in name
            TGString tmpTGString(tmpString);
            tmpTGString.Draw(id, fNormGC, x + lx, y + ly + max_ascent);
         }
      }
   }
}

//______________________________________________________________________________
TGDimension TGLVEntry::GetDefaultSize() const
{
   // Get default size of list item.

   TGDimension size;
   TGDimension isize(fCurrent ? fCurrent->GetWidth() : 0,
                     fCurrent ? fCurrent->GetHeight() : 0);
   TGDimension lsize(fTWidth, fTHeight+1);

   switch (fViewMode) {
      default:
      case kLVLargeIcons:
         size.fWidth = TMath::Max(isize.fWidth, lsize.fWidth);
         size.fHeight = isize.fHeight + lsize.fHeight + 6;
         break;

      case kLVSmallIcons:
      case kLVList:
      case kLVDetails:
         size.fWidth = isize.fWidth + lsize.fWidth + 4;
         size.fHeight = TMath::Max(isize.fHeight, lsize.fHeight);
         break;
   }
   return size;
}

//______________________________________________________________________________
FontStruct_t TGLVEntry::GetDefaultFontStruct()
{
   // Return the default font structure in use.

   if (!fgDefaultFont)
      fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
   return fgDefaultFont->GetFontStruct();
}

//______________________________________________________________________________
const TGGC &TGLVEntry::GetDefaultGC()
{
   // Return the default graphics context in use.

   if (!fgDefaultGC) {
      fgDefaultGC = new TGGC(*gClient->GetResourcePool()->GetFrameGC());
      fgDefaultGC->SetFont(fgDefaultFont->GetFontHandle());
   }
   return *fgDefaultGC;
}


//______________________________________________________________________________
TGLVContainer::TGLVContainer(const TGWindow *p, UInt_t w, UInt_t h,
                             UInt_t options, ULong_t back) :
   TGContainer(p, w, h, options, back)
{
   // Create a list view container. This is the (large) frame that contains
   // all the list items. It will be shown through a TGViewPort (which is
   // created by the TGCanvas derived TGListView).

   fListView = 0;
   fLastActive = 0;
   fCpos = fJmode = 0;
   fMultiSelect = kFALSE;

   fViewMode = kLVLargeIcons;
   fItemLayout = new TGLayoutHints(kLHintsExpandY | kLHintsCenterX);

   SetLayoutManager(new TGTileLayout(this, 8));
}

//______________________________________________________________________________
TGLVContainer::TGLVContainer(TGCanvas *p,UInt_t options, ULong_t back) :
   TGContainer(p,options, back)
{
   // Create a list view container. This is the (large) frame that contains
   // all the list items. It will be shown through a TGViewPort (which is
   // created by the TGCanvas derived TGListView).

   fListView = 0;
   fLastActive = 0;
   fCpos = fJmode = 0;
   fMultiSelect = kFALSE;

   fViewMode = kLVLargeIcons;
   fItemLayout = new TGLayoutHints(kLHintsExpandY | kLHintsCenterX);

   SetLayoutManager(new TGTileLayout(this, 8));

   if (p->InheritsFrom(TGListView::Class())) fListView = (TGListView*)p;
}

//______________________________________________________________________________
TGLVContainer::~TGLVContainer()
{
   // Delete list view container.

   if (!MustCleanup()) {
      RemoveAll();
      delete fItemLayout;
   }
}

//______________________________________________________________________________
void  TGLVContainer::SetColHeaders(const char* n1,const char* n2,const char* n3,
                                   const char* n4,const char* n5,const char* n6,
                                   const char* n7,const char* n8,const char* n9,
                                   const char* n10,const char* n11,const char* n12)
{
   // set columns headers

   if (!fListView) return;

   Int_t ncol = -1;
   if (n12 && strlen(n12)) ncol=12;
   else if (n11 && strlen(n11)) ncol=11;
   else if (n10 && strlen(n10)) ncol=10;
   else if (n9 && strlen(n9)) ncol=9;
   else if (n8 && strlen(n8)) ncol=8;
   else if (n7 && strlen(n7)) ncol=7;
   else if (n6 && strlen(n6)) ncol=6;
   else if (n5 && strlen(n5)) ncol=5;
   else if (n4 && strlen(n4)) ncol=4;
   else if (n3 && strlen(n3)) ncol=3;
   else if (n2 && strlen(n2)) ncol=2;
   else if (n1 && strlen(n1)) ncol=1;

   if (ncol<0) return;

   fListView->SetHeaders(ncol);
   if (ncol>0) fListView->SetHeader(n1, kTextCenterX, kTextLeft , 0);
   if (ncol>1) fListView->SetHeader(n2, kTextCenterX, kTextLeft , 1);
   if (ncol>2) fListView->SetHeader(n3, kTextCenterX, kTextLeft , 2);
   if (ncol>3) fListView->SetHeader(n4, kTextCenterX, kTextLeft , 3);
   if (ncol>4) fListView->SetHeader(n5, kTextCenterX, kTextLeft , 4);
   if (ncol>5) fListView->SetHeader(n6, kTextCenterX, kTextLeft , 5);
   if (ncol>6) fListView->SetHeader(n7, kTextCenterX, kTextLeft , 6);
   if (ncol>7) fListView->SetHeader(n8, kTextCenterX, kTextLeft , 7);
   if (ncol>8) fListView->SetHeader(n9, kTextCenterX, kTextLeft , 8);
   if (ncol>9) fListView->SetHeader(n10, kTextCenterX, kTextLeft , 9);
   if (ncol>10) fListView->SetHeader(n11, kTextCenterX, kTextLeft , 10);
   if (ncol>11) fListView->SetHeader(n12, kTextCenterX, kTextLeft , 11);

   fListView->Layout();
}

//______________________________________________________________________________
void TGLVContainer::SetViewMode(EListViewMode viewMode)
{
   // Set list view mode for container.

   if (fViewMode != viewMode) {
      TGLayoutHints *oldLayout = fItemLayout;

      EListViewMode old = fViewMode;
      fViewMode = viewMode;
      if (fListView) fListView->SetViewMode(viewMode);

      if (viewMode == kLVLargeIcons)
         fItemLayout = new TGLayoutHints(kLHintsExpandY | kLHintsCenterX);
      else
         fItemLayout = new TGLayoutHints(kLHintsLeft | kLHintsCenterY);
<commit_msg>Change the way the current (selected) item is highlighted (full width)<commit_after>// @(#)root/gui:$Id$
// Author: <NAME>   17/01/98

/*************************************************************************
 * Copyright (C) 1995-2000, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/
/**************************************************************************

    This source is based on Xclass95, a Win95-looking GUI toolkit.
    Copyright (C) 1996, 1997 <NAME>, <NAME>, <NAME>.

    Xclass95 is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

**************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGListView, TGLVContainer and TGLVEntry                              //
//                                                                      //
// A list view is a widget that can contain a number of items           //
// arranged in a grid or list. The items can be represented either      //
// by a string or by an icon.                                           //
//                                                                      //
// The TGListView is user callable. The other classes are service       //
// classes of the list view.                                            //
//                                                                      //
// A list view can generate the following events:                       //
// kC_CONTAINER, kCT_SELCHANGED, total items, selected items.           //
// kC_CONTAINER, kCT_ITEMCLICK, which button, location (y<<16|x).       //
// kC_CONTAINER, kCT_ITEMDBLCLICK, which button, location (y<<16|x).    //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGListView.h"
#include "TGPicture.h"
#include "TGButton.h"
#include "TGScrollBar.h"
#include "TGResourcePool.h"
#include "TList.h"
#include "TSystem.h"
#include "TGMimeTypes.h"
#include "TObjString.h"
#include "Riostream.h"

const TGFont *TGLVEntry::fgDefaultFont = 0;
TGGC         *TGLVEntry::fgDefaultGC = 0;

const TGFont *TGListView::fgDefaultFont = 0;
TGGC         *TGListView::fgDefaultGC = 0;


ClassImp(TGLVEntry)
ClassImp(TGLVContainer)
ClassImp(TGListView)

//______________________________________________________________________________
TGLVEntry::TGLVEntry(const TGWindow *p, const TGPicture *bigpic,
                     const TGPicture *smallpic, TGString *name,
                     TGString **subnames, EListViewMode viewMode,
                     UInt_t options, ULong_t back) :
   TGFrame(p, 10, 10, options, back)
{
   // Create a list view item.

   fSelPic = 0;

   fCurrent  =
   fBigPic   = bigpic;
   fSmallPic = smallpic;

   fCheckMark  = fClient->GetPicture("checkmark_t.xpm");
   fChecked = kFALSE;

   fItemName = name;
   fSubnames = subnames;
   fUserData = 0;

   fCpos  =
   fJmode = 0;

   fActive = kFALSE;

   fFontStruct = GetDefaultFontStruct();
   fNormGC     = GetDefaultGC()();

   Int_t max_ascent, max_descent;
   fTWidth = gVirtualX->TextWidth(fFontStruct,
                                  fItemName ? fItemName->GetString() : "",
                                  fItemName ? fItemName->GetLength() : 0);
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;

   if (fSubnames) {
      Int_t i;
      for (i = 0; fSubnames[i] != 0; ++i)
         ;
      fCtw = new int[i+1];
      fCtw[i] = 0;
      for (i = 0; fSubnames[i] != 0; ++i) {
         fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
                                        fSubnames[i]->GetLength());
      }
   } else {
      fCtw = 0;
   }

   fViewMode = (EListViewMode)-1;
   SetViewMode(viewMode);
}

//______________________________________________________________________________
TGLVEntry::TGLVEntry(const TGLVContainer *p, const TString& name,
                     const TString& cname, TGString **subnames,
                     UInt_t options, Pixel_t back) :
   TGFrame(p, 10, 10, options, back)
{
   // Create a list view item.
   //
   // name - is name of item.
   // cname - is name of icon. In most cases this is class name of object
   //         associated with this item.

   fSelPic = 0;

   fCurrent  =
   fBigPic   = fClient->GetMimeTypeList()->GetIcon(cname, kFALSE);
   fCheckMark  = fClient->GetPicture("checkmark_t.xpm");
   fChecked = kFALSE;

   if (!fBigPic) {
      fBigPic = fClient->GetPicture("doc_s.xpm");
   }
   fSmallPic = fClient->GetMimeTypeList()->GetIcon(cname, kTRUE);
   if (!fSmallPic) {
      fSmallPic = fClient->GetPicture("doc_t.xpm");
   }

   fItemName = new TGString(name);
   fSubnames = subnames;
   fUserData = 0;

   fCpos  =
   fJmode = 0;

   fActive = kFALSE;

   fFontStruct = GetDefaultFontStruct();
   fNormGC     = GetDefaultGC()();

   Int_t max_ascent, max_descent;
   fTWidth = gVirtualX->TextWidth(fFontStruct, fItemName->GetString(), fItemName->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;

   if (fSubnames) {
      Int_t i;
      for (i = 0; fSubnames[i] != 0; ++i)
         ;
      fCtw = new int[i+1];
      fCtw[i] = 0;
      for (i = 0; fSubnames[i] != 0; ++i) {
         fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
                                        fSubnames[i]->GetLength());
      }
   } else {
      fCtw = 0;
   }

   fViewMode = (EListViewMode)-1;
   SetViewMode((EListViewMode)p->GetViewMode());
}

//______________________________________________________________________________
TGLVEntry::~TGLVEntry()
{
   // Delete a list view item.

   if (fItemName) delete fItemName;
   if (fSelPic) delete fSelPic;
   if (fSubnames) {
      for (Int_t i = 0; fSubnames[i] != 0; ++i) delete fSubnames[i];
      delete [] fSubnames;
      delete [] fCtw;
   }
}

//______________________________________________________________________________
void TGLVEntry::SetSubnames(const char* n1,const char* n2,const char* n3,
                            const char* n4,const char* n5,const char* n6,
                            const char* n7,const char* n8,const char* n9,
                            const char* n10,const char* n11,const char* n12)
{
   // Sets new subnames.

   if (fSubnames) {
      for (Int_t i = 0; fSubnames[i] != 0; ++i) delete fSubnames[i];
      delete [] fSubnames;
      delete [] fCtw;
   }

   Int_t ncol = 0;
   fSubnames = 0;

   if (n12 && strlen(n12)) ncol=12;
   else if (n11 && strlen(n11)) ncol=11;
   else if (n10 && strlen(n10)) ncol=10;
   else if (n9 && strlen(n9)) ncol=9;
   else if (n8 && strlen(n8)) ncol=8;
   else if (n7 && strlen(n7)) ncol=7;
   else if (n6 && strlen(n6)) ncol=6;
   else if (n5 && strlen(n5)) ncol=5;
   else if (n4 && strlen(n4)) ncol=4;
   else if (n3 && strlen(n3)) ncol=3;
   else if (n2 && strlen(n2)) ncol=2;
   else if (n1 && strlen(n1)) ncol=1;

   if (!ncol) return;

   fSubnames = new TGString* [ncol+1];

   if (ncol>11) fSubnames[11] = new TGString(n12);
   if (ncol>10) fSubnames[10] = new TGString(n11);
   if (ncol>9) fSubnames[9] = new TGString(n10);
   if (ncol>8) fSubnames[8] = new TGString(n9);
   if (ncol>7) fSubnames[7] = new TGString(n8);
   if (ncol>6) fSubnames[6] = new TGString(n7);
   if (ncol>5) fSubnames[5] = new TGString(n6);
   if (ncol>4) fSubnames[4] = new TGString(n5);
   if (ncol>3) fSubnames[3] = new TGString(n4);
   if (ncol>2) fSubnames[2] = new TGString(n3);
   if (ncol>1) fSubnames[1] = new TGString(n2);
   if (ncol>0) fSubnames[0] = new TGString(n1);
   fSubnames[ncol] = 0;

   fCtw = new int[ncol];
   fCtw[ncol-1] = 0;

   for (int i = 0; i<ncol; i++) {
      fCtw[i] = gVirtualX->TextWidth(fFontStruct, fSubnames[i]->GetString(),
                                     fSubnames[i]->GetLength());
   }
}

//______________________________________________________________________________
void TGLVEntry::Activate(Bool_t a)
{
   // Make list view item active.

   if (fActive == a) return;
   fActive = a;

   if (fActive) {
      fSelPic = new TGSelectedPicture(gClient, fCurrent);
   } else {
      if (fSelPic) delete fSelPic;
      fSelPic = 0;
   }
   DoRedraw();
}

//______________________________________________________________________________
void TGLVEntry::SetViewMode(EListViewMode viewMode)
{
   // Set the view mode for this list item.

   if (viewMode != fViewMode) {
      fViewMode = viewMode;
      if (viewMode == kLVLargeIcons)
         fCurrent = fBigPic;
      else
         fCurrent = fSmallPic;
      if (fActive) {
         if (fSelPic) delete fSelPic;
         fSelPic = new TGSelectedPicture(gClient, fCurrent);
      }
      gVirtualX->ClearWindow(fId);
      Resize(GetDefaultSize());
      fClient->NeedRedraw(this);
   }
}

//______________________________________________________________________________
void TGLVEntry::SetPictures(const TGPicture *bigpic, const TGPicture *smallpic)
{
   // change pictures

   if (!bigpic || !smallpic) return;

   gVirtualX->ClearWindow(fId);

   fBigPic = bigpic;
   fSmallPic = smallpic;
   fCurrent = fViewMode == kLVLargeIcons ? fBigPic : fSmallPic;

   if (fSelPic) delete fSelPic;
   fSelPic = new TGSelectedPicture(gClient, fCurrent);

   Resize();
   gVirtualX->ClearWindow(fId);
}

//______________________________________________________________________________
void TGLVEntry::DoRedraw()
{
   // Redraw list view item.
   // List view item is placed and layouted in the container frame,
   // but is drawn in viewport.

   DrawCopy(fId, 0, 0);
}

//______________________________________________________________________________
void TGLVEntry::DrawCopy(Handle_t id, Int_t x, Int_t y)
{
   // Draw list view item in other window.
   // List view item is placed and layout in the container frame,
   // but is drawn in viewport.

   Int_t ix, iy, lx, ly;
   Int_t max_ascent, max_descent;

   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTWidth = gVirtualX->TextWidth(fFontStruct, fItemName->GetString(), fItemName->GetLength());
   fTHeight = max_ascent + max_descent;

   if (fViewMode == kLVLargeIcons) {
      ix = (fWidth - fCurrent->GetWidth()) >> 1;
      iy = 0;
      lx = (fWidth - fTWidth) >> 1;
      ly = fHeight - (fTHeight + 1) - 2;
   } else {
      ix = 0;
      iy = (fHeight - fCurrent->GetHeight()) >> 1;
      lx = fCurrent->GetWidth() + 2;
      ly = (fHeight - (fTHeight + 1)) >> 1;
   }

   if ((fChecked) && (fCheckMark)) {
      if (fViewMode == kLVLargeIcons) {
         fCheckMark->Draw(id, fNormGC, x + ix + 8, y + iy + 8);
         gVirtualX->SetForeground(fNormGC, fgWhitePixel);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, fTWidth, fTHeight + 1);
         gVirtualX->SetForeground(fNormGC, fgBlackPixel);
      }
      else {
         fCheckMark->Draw(id, fNormGC, x + ix, y + iy);
         gVirtualX->SetForeground(fNormGC, fgWhitePixel);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y, fWidth-lx, fHeight);
         gVirtualX->SetForeground(fNormGC, fgBlackPixel);
      }
   }
   // This if tries to print the elements with ... appened at the end if
   // the widht of the string is longer than that of the column
   if (fViewMode == kLVDetails && fSubnames && fCpos && fJmode && fCtw) {
      TString tmpString = *fItemName;
      Int_t ftmpWidth = gVirtualX->TextWidth(fFontStruct, tmpString,
                                             tmpString.Length());
      if ( ftmpWidth > (fCpos[0] - lx) ) {
         for (Int_t j = fItemName->Length() - 1 ; j > 0; j--) {
            tmpString =  (*fItemName)(0,j) + "...";
            ftmpWidth = gVirtualX->TextWidth(GetDefaultFontStruct(), tmpString,
                                             tmpString.Length());
            if ( ftmpWidth <= (fCpos[0] - lx) ) {
               break;
            }
         }
      }
      if (fActive) {
         if (fSelPic) fSelPic->Draw(id, fNormGC, x + ix, y + iy);
         gVirtualX->SetForeground(fNormGC, fgDefaultSelectedBackground);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y, fWidth-(lx+4), fHeight);
         gVirtualX->SetForeground(fNormGC, fClient->GetResourcePool()->GetSelectedFgndColor());
      } else {
         fCurrent->Draw(id, fNormGC, x + ix, y + iy);
         gVirtualX->SetForeground(fNormGC, fgWhitePixel);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y, fWidth-(lx+4), fHeight);
         gVirtualX->SetForeground(fNormGC, fgBlackPixel);
      }

      TGString tmpTGString(tmpString);
      tmpTGString.Draw(id, fNormGC, x+lx, y+ly + max_ascent);
   } else if (fViewMode == kLVLargeIcons) {
      if (fActive) {
         if (fSelPic) fSelPic->Draw(id, fNormGC, x + ix, y + iy);
         gVirtualX->SetForeground(fNormGC, fgDefaultSelectedBackground);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, fTWidth, fTHeight + 1);
         gVirtualX->SetForeground(fNormGC, fClient->GetResourcePool()->GetSelectedFgndColor());
      } else {
         fCurrent->Draw(id, fNormGC, x + ix, y + iy);
         gVirtualX->SetForeground(fNormGC, fgWhitePixel);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y + ly, fTWidth, fTHeight + 1);
         gVirtualX->SetForeground(fNormGC, fgBlackPixel);
      }
      fItemName->Draw(id, fNormGC, x+lx, y+ly + max_ascent);
   } else {
      if (fActive) {
         gVirtualX->SetForeground(fNormGC, fgDefaultSelectedBackground);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y, fWidth-lx, fHeight);
         gVirtualX->SetForeground(fNormGC, fClient->GetResourcePool()->GetSelectedFgndColor());
         if (fSelPic) fSelPic->Draw(id, fNormGC, x + ix, y + iy);
      } else {
         gVirtualX->SetForeground(fNormGC, fgWhitePixel);
         gVirtualX->FillRectangle(id, fNormGC, x + lx, y, fWidth-lx, fHeight);
         gVirtualX->SetForeground(fNormGC, fgBlackPixel);
         fCurrent->Draw(id, fNormGC, x + ix, y + iy);
      }
      fItemName->Draw(id, fNormGC, x+lx, y+ly + max_ascent);
   }

   if (fViewMode == kLVDetails) {
      if (fSubnames && fCpos && fJmode && fCtw) {
         int i;

         if (fActive) {
            gVirtualX->SetForeground(fNormGC, fClient->GetResourcePool()->GetSelectedFgndColor());
         } else {
            gVirtualX->SetForeground(fNormGC, fgBlackPixel);
         }
         // Again fixes the size of the strings
         for (i = 0; fSubnames[i] != 0; ++i) {
            TString tmpString = *fSubnames[i];
            Int_t ftmpWidth = gVirtualX->TextWidth(fFontStruct, tmpString,
                                                   tmpString.Length());
            if ( ftmpWidth > (fCpos[i+1] - fCpos[i]) ) {
               for (int j = fSubnames[i]->Length() - 1 ; j > 0; j--) {
                  tmpString =  (*fSubnames[i])(0,j) + "...";
                  ftmpWidth = gVirtualX->TextWidth(GetDefaultFontStruct(),
                                                   tmpString,
                                                   tmpString.Length());
                  if ( ftmpWidth <= (fCpos[i+1] - fCpos[i]) ) {
                     break;
                  }
               }
            }
            if (fCpos[i] == 0)
               break;
            if (fJmode[i] == kTextRight)
               lx = fCpos[i+1] - ftmpWidth - 2;
            else if (fJmode[i] == kTextCenterX)
               lx = (fCpos[i] + fCpos[i+1] - ftmpWidth) >> 1;
            else // default to TEXT_LEFT
               lx = fCpos[i] + 2;

            //if (x + lx < 0) continue; // out of left boundary or mess in name
            TGString tmpTGString(tmpString);
            tmpTGString.Draw(id, fNormGC, x + lx, y + ly + max_ascent);
         }
      }
   }
   gVirtualX->SetForeground(fNormGC, fgBlackPixel);
}

//______________________________________________________________________________
TGDimension TGLVEntry::GetDefaultSize() const
{
   // Get default size of list item.

   TGDimension size;
   TGDimension isize(fCurrent ? fCurrent->GetWidth() : 0,
                     fCurrent ? fCurrent->GetHeight() : 0);
   TGDimension lsize(fTWidth, fTHeight+1);

   switch (fViewMode) {
      default:
      case kLVLargeIcons:
         size.fWidth = TMath::Max(isize.fWidth, lsize.fWidth);
         size.fHeight = isize.fHeight + lsize.fHeight + 6;
         break;

      case kLVSmallIcons:
      case kLVList:
      case kLVDetails:
         size.fWidth = isize.fWidth + lsize.fWidth + 4;
         size.fHeight = TMath::Max(isize.fHeight, lsize.fHeight);
         break;
   }
   return size;
}

//______________________________________________________________________________
FontStruct_t TGLVEntry::GetDefaultFontStruct()
{
   // Return the default font structure in use.

   if (!fgDefaultFont)
      fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
   return fgDefaultFont->GetFontStruct();
}

//______________________________________________________________________________
const TGGC &TGLVEntry::GetDefaultGC()
{
   // Return the default graphics context in use.

   if (!fgDefaultGC) {
      fgDefaultGC = new TGGC(*gClient->GetResourcePool()->GetFrameGC());
      fgDefaultGC->SetFont(fgDefaultFont->GetFontHandle());
   }
   return *fgDefaultGC;
}


//______________________________________________________________________________
TGLVContainer::TGLVContainer(const TGWindow *p, UInt_t w, UInt_t h,
                             UInt_t options, ULong_t back) :
   TGContainer(p, w, h, options, back)
{
   // Create a list view container. This is the (large) frame that contains
   // all the list items. It will be shown through a TGViewPort (which is
   // created by the TGCanvas derived TGListView).

   fListView = 0;
   fLastActive = 0;
   fCpos = fJmode = 0;
   fMultiSelect = kFALSE;

   fViewMode = kLVLargeIcons;
   fItemLayout = new TGLayoutHints(kLHintsExpandY | kLHintsCenterX);

   SetLayoutManager(new TGTileLayout(this, 8));
}

//______________________________________________________________________________
TGLVContainer::TGLVContainer(TGCanvas *p,UInt_t options, ULong_t back) :
   TGContainer(p,options, back)
{
   // Create a list view container. This is the (large) frame that contains
   // all the list items. It will be shown through a TGViewPort (which is
   // created by the TGCanvas derived TGListView).

   fListView = 0;
   fLastActive = 0;
   fCpos = fJmode = 0;
   fMultiSelect = kFALSE;

   fViewMode = kLVLargeIcons;
   fItemLayout = new TGLayoutHints(kLHintsExpandY | kLHintsCenterX);

   SetLayoutManager(new TGTileLayout(this, 8));

   if (p->InheritsFrom(TGListView::Class())) fListView = (TGListView*)p;
}

//______________________________________________________________________________
TGLVContainer::~TGLVContainer()
{
   // Delete list view container.

   if (!MustCleanup()) {
      RemoveAll();
      delete fItemLayout;
   }
}

//______________________________________________________________________________
void  TGLVContainer::SetColHeaders(const char* n1,const char* n2,const char* n3,
                                   const char* n4,const char* n5,const char* n6,
                                   const char* n7,const char* n8,const char* n9,
                                   const char* n10,const char* n11,const char* n12)
{
   // set columns headers

   if (!fListView) return;

   Int_t ncol = -1;
   if (n12 && strlen(n12)) ncol=12;
   else if (n11 && strlen(n11)) ncol=11;
   else if (n10 && strlen(n10)) ncol=10;
   else if (n9 && strlen(n9)) ncol=9;
   else if (n8 && strlen(n8)) ncol=8;
   else if (n7 && strlen(n7)) ncol=7;
   else if (n6 && strlen(n6)) ncol=6;
   else if (n5 && strlen(n5)) ncol=5;
   else if (n4 && strlen(n4)) ncol=4;
   else if (n3 && strlen(n3)) ncol=3;
   else if (n2 && strlen(n2)) ncol=2;
   else if (n1 && strlen(n1)) ncol=1;

   if (ncol<0) return;

   fListView->SetHeaders(ncol);
   if (ncol>0) fListView->SetHeader(n1, kTextCenterX, kTextLeft , 0);
   if (ncol>1) fListView->SetHeader(n2, kTextCenterX, kTextLeft , 1);
   if (ncol>2) fListView->SetHeader(n3, kTextCenterX, kTextLeft , 2);
   if (ncol>3) fListView->SetHeader(n4, kTextCenterX, kTextLeft , 3);
   if (ncol>4) fListView->SetHeader(n5, kTextCenterX, kTextLeft , 4);
   if (ncol>5) fListView->SetHeader(n6, kTextCenterX, kTextLeft , 5);
   if (ncol>6) fListView->SetHeader(n7, kTextCenterX, kTextLeft , 6);
   if (ncol>7) fListView->SetHeader(n8, kTextCenterX, kTextLeft , 7);
   if (ncol>8) fListView->SetHeader(n9, kTextCenterX, kTextLeft , 8);
   if (ncol>9) fListView->SetHeader(n10, kTextCenterX, kTextLeft , 9);
   if (ncol>10) fListView->SetHeader(n11, kTextCenterX, kTextLeft , 10);
   if (ncol>11) fListView->SetHeader(n12, kTextCenterX, kTextLeft , 11);

   fListView->Layout();
}

//______________________________________________________________________________
void TGLVContainer::SetViewMode(EListViewMode viewMode)
{
   // Set list view mode for container.

   if (fViewMode != viewMode) {
      TGLayoutHints *oldLayout = fItemLayout;

      EListViewMode old = fViewMode;
      fViewMode = viewMode;
      if (fListView) fListView->SetViewMode(viewMode);

      if (viewMode == kLVLargeIcons)
         fItemLayout = new TGLayoutHints(kLHintsExpandY | kLHintsCenterX);
      else
         fItemLayout = new TGLayoutHints(kLHintsExpandX | kLHintsCenterY);

{'fraction_non_alphanumeric': 0.13901730746892788, 'fraction_numerical': 0.01577418980137066, 'mean_word_length': 2.408234362628662, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 302, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 84, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1329961', 'n_tokens_mistral': 14531, 'n_tokens_neox': 13610, 'n_words': 3257}