#include "TGTableLayout.h"
#include "TGFrame.h"
#include "TList.h"
#include "Rtypes.h"
#include "Riostream.h"
ClassImp(TGTableLayout)
ClassImp(TGTableLayoutHints)
TGTableLayout::TGTableLayout(TGCompositeFrame *main, UInt_t nrows, UInt_t ncols,
                             Bool_t homogeneous, Int_t sep, Int_t hints)
{
   
   
   
   
   
   
   
   fMain    = main;
   fList    = fMain->GetList();
   fSep     = sep;
   fHints   = hints;
   fNrows   = nrows;
   fNcols   = ncols;
   fRow     = 0;
   fCol     = 0;
   fHomogeneous = homogeneous;
}
TGTableLayout::~TGTableLayout()
{
   
   if (fRow) delete [] fRow;
   if (fCol) delete [] fCol;
}
void TGTableLayout::FindRowColSizes()
{
   
   
   
   FindRowColSizesInit();
   FindRowColSizesSinglyAttached();
   FindRowColSizesHomogeneous();
   FindRowColSizesMultiplyAttached();
   FindRowColSizesHomogeneous();
}
void TGTableLayout::FindRowColSizesInit()
{
   
   if (fRow) delete [] fRow;
   if (fCol) delete [] fCol;
   fRow = new TableData_t[fNrows];
   fCol = new TableData_t[fNcols];
   
   UInt_t i;
   for (i = 0; i < fNrows; ++i) fRow[i].fDefSize = 0;
   for (i = 0; i < fNcols; ++i) fCol[i].fDefSize = 0;
}
void TGTableLayout::FindRowColSizesSinglyAttached()
{
   
   TIter next(fList);
   TGFrameElement *ptr;
   while ((ptr = (TGFrameElement *) next())) {
      TGTableLayoutHints *layout =
            dynamic_cast<TGTableLayoutHints*>(ptr->fLayout);
      if (!layout) {
         Error("FindRowColSizesSinglyAttached", "didn't get TGTableLayoutHints from %s, layout = 0x%lx",
               ptr->fFrame->GetName(), ptr->fLayout);
         return;
      }
      UInt_t col = layout->GetAttachLeft();
      if (col == (layout->GetAttachRight() - 1))
         fCol[col].fDefSize = TMath::Max(fCol[col].fDefSize,
                                         ptr->fFrame->GetDefaultWidth() +
                                         layout->GetPadLeft() +
                                         layout->GetPadRight());
      UInt_t row = layout->GetAttachTop();
      if (row == (layout->GetAttachBottom() - 1))
         fRow[row].fDefSize = TMath::Max(fRow[row].fDefSize,
                                         ptr->fFrame->GetDefaultHeight() +
                                         layout->GetPadTop() +
                                         layout->GetPadBottom());
   }
}
void TGTableLayout::FindRowColSizesHomogeneous()
{
   
   
   if (!fHomogeneous) return;
   UInt_t max_width = 0, max_height = 0, col, row;
   
   for (col = 0; col < fNcols; ++col)
      max_width = TMath::Max(max_width,fCol[col].fDefSize);
   for (row = 0; row < fNrows; ++row)
      max_height = TMath::Max(max_height,fRow[row].fDefSize);
   
   for (col = 0; col < fNcols; ++col) fCol[col].fDefSize = max_width;
   for (row = 0; row < fNrows; ++row) fRow[row].fDefSize = max_height;
}
void TGTableLayout::FindRowColSizesMultiplyAttached()
{
   
   TIter next(fList);
   TGFrameElement *ptr;
   while ((ptr = (TGFrameElement *) next())) {
      TGTableLayoutHints *layout =
            dynamic_cast<TGTableLayoutHints*>(ptr->fLayout);
      if (!layout) {
         Error("FindRowColSizesMultiplyAttached", "didn't get TGTableLayoutHints");
         return;
      }
      UInt_t left   = layout->GetAttachLeft();
      UInt_t right  = layout->GetAttachRight();
      if (left != right-1) {  
         UInt_t width = 0, col;
         for (col = left; col < right; ++col) width += fCol[col].fDefSize;
         
         UInt_t child_width = ptr->fFrame->GetDefaultWidth() +
                              layout->GetPadLeft() + layout->GetPadRight();
         if (width < child_width) {
            width = child_width - width;
            for (col = left; col < right; ++col) {
               UInt_t extra = width / (right - col);
               fCol[col].fDefSize += extra;
               width -= extra;
            }
         }
      }
      UInt_t top    = layout->GetAttachTop();
      UInt_t bottom = layout->GetAttachBottom();
      if (top != bottom-1) {  
         UInt_t height = 0, row;
         for (row = top; row < bottom; ++row) height += fRow[row].fDefSize;
         
         UInt_t child_height = ptr->fFrame->GetDefaultHeight() +
                               layout->GetPadTop() + layout->GetPadBottom();
         if (height < child_height) {
            height = child_height - height;
            for (row = top; row < bottom; ++row) {
               UInt_t extra = height / (bottom - row);
               fRow[row].fDefSize += extra;
               height -= extra;
            }
         }
      }
   }
}
void TGTableLayout::SetRowColResize(UInt_t real_size, UInt_t nthings,
                                    TableData_t *thing, Bool_t homogeneous)
{
   
   
   
   if (homogeneous) {
      UInt_t ind, nexpand = 0, cur_size = 0;
      for (ind = 0; ind < nthings; ++ind)
         cur_size += thing[ind].fDefSize;
      if (cur_size < real_size) {
         for (ind = 0; ind < nthings; ++ind)
            if (thing[ind].fExpand) { ++ nexpand; break; }
         if (nexpand > 0) {
            UInt_t size = real_size;
            for (ind = 0; ind < nthings; ++ ind) {
               UInt_t extra = size / (nthings - ind);
               thing[ind].fRealSize = TMath::Max(1U, extra);
               size -= extra;
            }
         }
      }
   } else {
      UInt_t ind, nshrink=0, nexpand=0, size=0;
      for (ind = 0; ind < nthings; ++ind) {
         size += thing[ind].fDefSize;
         if (thing[ind].fExpand) ++ nexpand;
         if (thing[ind].fShrink) ++ nshrink;
      }
      
      if ((size < real_size) && (nexpand >= 1)) {
         size = real_size - size;
         for (ind = 0; ind < nthings; ++ind) {
            if (thing[ind].fExpand) {
               UInt_t extra = size / nexpand;
               thing[ind].fRealSize += extra;
               size -= extra;
               --nexpand;
            }
         }
      }
      
      if (size > real_size) {
         UInt_t total_nshrink = nshrink;
         UInt_t extra = size - real_size;
         while (total_nshrink > 0 && extra > 0) {
            nshrink = total_nshrink;
            for (ind = 0; ind < nthings; ++ind)
               if (thing[ind].fShrink) {
                  UInt_t size = thing[ind].fRealSize;
                  thing[ind].fRealSize = TMath::Max(1U,thing[ind].fRealSize - extra / nshrink);
                  extra -= size - thing[ind].fRealSize;
                  --nshrink;
                  if (thing[ind].fRealSize < 2) {
                     total_nshrink -= 1;
                     thing[ind].fShrink = kFALSE;
                  }
               }
         }
      }
   } 
}
void TGTableLayout::SetRowColSizes()
{
   
   
   SetRowColSizesInit();
   UInt_t border_width = fMain->GetBorderWidth();
   SetRowColResize(fMain->GetWidth() - (fNcols-1)*fSep - 2*border_width,
                   fNcols, fCol, fHomogeneous);
   SetRowColResize(fMain->GetHeight() - (fNrows-1)*fSep - 2*border_width,
                   fNrows, fRow, fHomogeneous);
}
void TGTableLayout::SetRowColSizesInit()
{
   
   
   UInt_t col;
   for (col = 0; col < fNcols; ++col) {
      fCol[col].fRealSize = fCol[col].fDefSize;
      fCol[col].fNeedExpand = kFALSE;
      fCol[col].fNeedShrink = kTRUE;
      fCol[col].fExpand = kFALSE;
      fCol[col].fShrink = kTRUE;
      fCol[col].fEmpty = kTRUE;
   }
   UInt_t row;
   for (row = 0; row < fNrows; ++row) {
      fRow[row].fRealSize = fRow[row].fDefSize;
      fRow[row].fNeedExpand = kFALSE;
      fRow[row].fNeedShrink = kTRUE;
      fRow[row].fExpand = kFALSE;
      fRow[row].fShrink = kTRUE;
      fRow[row].fEmpty = kTRUE;
   }
   
   TIter next(fList);
   TGFrameElement *ptr;
   while ((ptr = (TGFrameElement*) next())) {
      TGTableLayoutHints *layout =
            dynamic_cast<TGTableLayoutHints*>(ptr->fLayout);
      if (!layout) {
         Error("SetRowColSizesInit", "didn't get TGTableLayoutHints");
         return;
      }
      ULong_t hints = layout->GetLayoutHints();
      
      if (layout->GetAttachLeft() == layout->GetAttachRight()-1) {
         if (hints & kLHintsExpandX)
            fCol[layout->GetAttachLeft()].fExpand = kTRUE;
         if (!(hints & kLHintsShrinkX))
            fCol[layout->GetAttachLeft()].fShrink = kFALSE;
         fCol[layout->GetAttachLeft()].fEmpty = kFALSE;
      }
      
      if (layout->GetAttachTop() == layout->GetAttachBottom()-1) {
         if (hints & kLHintsExpandY)
            fRow[layout->GetAttachTop()].fExpand = kTRUE;
         if (!(hints & kLHintsShrinkY))
            fRow[layout->GetAttachTop()].fShrink = kFALSE;
         fRow[layout->GetAttachTop()].fEmpty = kFALSE;
      }
   }
   
   next.Reset();
   while ((ptr = (TGFrameElement*) next())) {
      TGTableLayoutHints *layout =
            dynamic_cast<TGTableLayoutHints*>(ptr->fLayout);
      if (!layout) {
         Error("SetRowColSizesInit", "didn't get TGTableLayoutHints");
         return;
      }
      ULong_t hints = layout->GetLayoutHints();
      
      UInt_t left = layout->GetAttachLeft();
      UInt_t right = layout->GetAttachRight();
      if (left != right - 1) {
         for (col = left; col < right; ++col) fCol[col].fEmpty = kFALSE;
         Bool_t has_expand=kFALSE, has_shrink=kTRUE;
         if (hints & kLHintsExpandX) {
            for (col = left; col < right; ++col)
               if (fCol[col].fExpand) { has_expand = kTRUE; break; }
            if (!has_expand)
               for (col = left; col < right; ++col)
                  fCol[col].fNeedExpand = kTRUE;
         }
         if (!(hints & kLHintsShrinkX)) {
            for (col = left; col < right; ++col)
               if (!fCol[col].fShrink) { has_shrink = kFALSE; break;}
            if (has_shrink)
               for (col = left; col < right; ++col)
                  fCol[col].fNeedShrink = kFALSE;
         }
      }
      
      UInt_t top = layout->GetAttachTop();
      UInt_t bottom = layout->GetAttachBottom();
      if (top != bottom - 1) {
         for (row = top; row < bottom; ++row) fRow[row].fEmpty = kFALSE;
         Bool_t has_expand=kFALSE, has_shrink=kTRUE;
         if (hints & kLHintsExpandY) {
            for (row = top; row < bottom; ++row)
               if (fRow[row].fExpand) { has_expand = kTRUE; break; }
            if (!has_expand)
               for (row = top; row < bottom; ++row)
                  fRow[row].fNeedExpand = kTRUE;
         }
         if (!(hints & kLHintsShrinkY)) {
            for (row = top; row < bottom; ++row)
               if (!fRow[row].fShrink) { has_shrink = kFALSE; break;}
            if (has_shrink)
               for (row = top; row < bottom; ++row)
                  fRow[row].fNeedShrink = kFALSE;
         }
      }
   }
   
   for (col = 0; col < fNcols; ++col) {
      if (fCol[col].fEmpty) {
         fCol[col].fExpand = kFALSE;
         fCol[col].fShrink = kFALSE;
      } else {
         if (fCol[col].fNeedExpand) fCol[col].fExpand = kTRUE;
         if (!fCol[col].fNeedShrink) fCol[col].fShrink = kFALSE;
      }
   }
   for (row = 0; row < fNrows; ++row) {
      if (fRow[row].fEmpty) {
         fRow[row].fExpand = kFALSE;
         fRow[row].fShrink = kFALSE;
      } else {
         if (fRow[row].fNeedExpand) fRow[row].fExpand = kTRUE;
         if (!fRow[row].fNeedShrink) fRow[row].fShrink = kFALSE;
      }
   }
}
void TGTableLayout::CheckSanity()
{
   
   TIter next(fList);
   TGFrameElement *ptr;
   UInt_t nerrors = 0;
   while ((ptr = (TGFrameElement*) next())) {
      TGTableLayoutHints *layout =
            dynamic_cast<TGTableLayoutHints*>(ptr->fLayout);
      if (!layout) {
         Error("CheckSanity", "didn't get TGTableLayoutHints");
         return;
      }
      UInt_t right  = layout->GetAttachRight();
      UInt_t left   = layout->GetAttachLeft();
      UInt_t top    = layout->GetAttachTop();
      UInt_t bottom = layout->GetAttachBottom();
      if (left == right) {
         ++nerrors;
         Error("CheckSanity", "AttachLeft == AttachRight");
      }
      if (left > right) {
         ++nerrors;
         Error("CheckSanity", "AttachLeft > AttachRight");
      }
      if (left > fNcols-1) {
         ++nerrors;
         Error("CheckSanity", "AttachLeft illegal value: %u", left);
      }
      if (right < 1 || right > fNcols) {
         ++nerrors;
         Error("CheckSanity", "AttachRight illegal value: %u", right);
      }
      if (top == bottom) {
         ++nerrors;
         Error("CheckSanity", "AttachTop == AttachBottom");
      }
      if (top > bottom) {
         ++nerrors;
         Error("CheckSanity", "AttachTop > AttachBottom");
      }
      if (top > fNrows-1) {
         ++nerrors;
         Error("CheckSanity", "AttachTop illegal value: %u", top);
      }
      if (bottom < 1 || bottom > fNrows) {
         ++nerrors;
         Error("CheckSanity", "AttachBottom illegal value: %u", bottom);
      }
   }
   if (nerrors) {
      Error("CheckSanity", "errors in %u x %u table", fNcols, fNrows);
   }
}
void TGTableLayout::Layout()
{
    
   CheckSanity();
   FindRowColSizes();
   SetRowColSizes();
   
   TIter next(fList);
   TGFrameElement *ptr;
   UInt_t border_width = fMain->GetBorderWidth();
   while ((ptr = (TGFrameElement*) next())) {
      TGTableLayoutHints *layout = 
            dynamic_cast<TGTableLayoutHints*>(ptr->fLayout);
      if (!layout) {
         Error("TGTableLayout::Layout", "didn't get TGTableLayoutHints");
         return;
      }
      ULong_t hints = layout->GetLayoutHints();
      TGDimension size = ptr->fFrame->GetDefaultSize();
      UInt_t right  = layout->GetAttachRight();
      UInt_t left   = layout->GetAttachLeft();
      UInt_t top    = layout->GetAttachTop();
      UInt_t bottom = layout->GetAttachBottom();
      
      UInt_t col, cell_x = border_width + left*fSep;
      for (col = 0; col < left; ++col) cell_x += fCol[col].fRealSize;
      UInt_t row, cell_y = border_width + top*fSep;
      for (row = 0; row < top; ++row) cell_y += fRow[row].fRealSize;
      UInt_t cell_width = (right-left-1)*fSep;
      for (col=left; col < right; ++col)
         cell_width += fCol[col].fRealSize;
      UInt_t cell_height = (bottom-top-1)*fSep;
      for (row=top; row < bottom; ++row)
         cell_height += fRow[row].fRealSize;
      UInt_t pad_left   = layout->GetPadLeft();
      UInt_t pad_right  = layout->GetPadRight();
      UInt_t pad_bottom = layout->GetPadBottom();
      UInt_t pad_top    = layout->GetPadTop();
      
      UInt_t ww,hh;
      if (hints & kLHintsFillX)
         ww = cell_width  - pad_left - pad_right;
      else
         ww = size.fWidth;
      if (hints & kLHintsFillY)
         hh = cell_height - pad_top - pad_bottom;
      else
         hh = size.fHeight;
      
      UInt_t xx;
      if (hints & kLHintsFillX) 
         xx = cell_x + pad_left;
      else if (hints & kLHintsRight)
         xx = cell_x + cell_width - pad_right - ww;
      else if (hints & kLHintsCenterX)
         xx = cell_x + cell_width/2 - ww/2; 
      else                    
         xx = cell_x + pad_left;
      UInt_t yy;
      if (hints & kLHintsFillY) 
         yy = cell_y + pad_top;
      else if (hints & kLHintsBottom)
         yy = cell_y + cell_height - pad_bottom - hh;
      else if (hints & kLHintsCenterY)
         yy = cell_y + cell_height/2 - hh/2; 
      else                    
         yy = cell_y + pad_top;
      ptr->fFrame->MoveResize(xx,yy,ww,hh);
      ptr->fFrame->Layout();
   }
}
TGDimension TGTableLayout::GetDefaultSize() const
{
   
   Int_t border_width = fMain->GetBorderWidth();
   TGDimension size(2*border_width + (fNcols-1)*fSep,
                    2*border_width + (fNrows-1)*fSep);
   UInt_t col, row;
   if (fCol)
      for (col = 0; col < fNcols; ++col) size.fWidth += fCol[col].fDefSize;
   if (fRow)
      for (row = 0; row < fNrows; ++row) size.fHeight += fRow[row].fDefSize;
   return size;
}
void TGTableLayoutHints::SavePrimitive(ostream &out, Option_t * )
{
   
   TString hints;
   UInt_t pad = GetPadLeft()+GetPadRight()+GetPadTop()+GetPadBottom();
   if (!GetLayoutHints()) return;
   if ((fLayoutHints == kLHintsNormal) && (pad == 0)) return;
   if (fLayoutHints & kLHintsLeft) {
      if (hints.Length() == 0) hints  = "kLHintsLeft";
      else                     hints += " | kLHintsLeft";
   }
   if (fLayoutHints & kLHintsCenterX) {
      if  (hints.Length() == 0) hints  = "kLHintsCenterX";
      else                     hints += " | kLHintsCenterX";
   }
   if (fLayoutHints & kLHintsRight) {
      if (hints.Length() == 0) hints  = "kLHintsRight";
      else                     hints += " | kLHintsRight";
   }
   if (fLayoutHints & kLHintsTop) {
      if (hints.Length() == 0) hints  = "kLHintsTop";
      else                     hints += " | kLHintsTop";
   }
   if (fLayoutHints & kLHintsCenterY) {
      if (hints.Length() == 0) hints  = "kLHintsCenterY";
      else                     hints += " | kLHintsCenterY";
   }
   if (fLayoutHints & kLHintsBottom) {
      if (hints.Length() == 0) hints  = "kLHintsBottom";
      else                     hints += " | kLHintsBottom";
   }
   if (fLayoutHints & kLHintsExpandX) {
      if (hints.Length() == 0) hints  = "kLHintsExpandX";
      else                     hints += " | kLHintsExpandX";
   }
   if (fLayoutHints & kLHintsExpandY) {
      if (hints.Length() == 0) hints  = "kLHintsExpandY";
      else                     hints += " | kLHintsExpandY";
   }
   if (fLayoutHints & kLHintsShrinkX) {
      if (hints.Length() == 0) hints  = "kLHintsShrinkX";
      else                     hints += " | kLHintsShrinkX";
   }
   if (fLayoutHints & kLHintsShrinkY) {
      if (hints.Length() == 0) hints  = "kLHintsShrinkY";
      else                     hints += " | kLHintsShrinkY";
   }
   if (fLayoutHints & kLHintsFillX) {
      if (hints.Length() == 0) hints  = "kLHintsFillX";
      else                     hints += " | kLHintsFillX";
   }
   if (fLayoutHints & kLHintsFillY) {
      if (hints.Length() == 0) hints  = "kLHintsFillY";
      else                     hints += " | kLHintsFillY";
   }
   out << ", new TGTableLayoutHints(" << GetAttachLeft() << "," << GetAttachRight()
       << "," << GetAttachTop()  << "," << GetAttachBottom()
       << "," << hints;
   if (pad) {
      out << "," << GetPadLeft() << "," << GetPadRight()
          << "," << GetPadTop()  << "," << GetPadBottom();
   }
   out << ")";
}
void TGTableLayout::SavePrimitive(ostream &out, Option_t * )
{
   
   out << " new TGTableLayout(" << fMain->GetName() << "," << fNrows << "," << fNcols;
   if (fSep) {
      if (fHomogeneous == kTRUE)
         out << ", kTRUE";
      else
         out << ", kFALSE";
   out << fSep;
   }
   out  << ")";
   
}
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.