81 ClassImp(TGTableLayout);
82 ClassImp(TGTableLayoutHints);
93 TGTableLayout::TGTableLayout(TGCompositeFrame *main, UInt_t nrows, UInt_t ncols,
94 Bool_t homogeneous, Int_t sep, Int_t hints)
97 fList = fMain->GetList();
104 fHomogeneous = homogeneous;
110 TGTableLayout::~TGTableLayout()
112 if (fRow)
delete [] fRow;
113 if (fCol)
delete [] fCol;
120 void TGTableLayout::FindRowColSizes()
124 FindRowColSizesInit();
125 FindRowColSizesSinglyAttached();
126 FindRowColSizesHomogeneous();
127 FindRowColSizesMultiplyAttached();
128 FindRowColSizesHomogeneous();
134 void TGTableLayout::FindRowColSizesInit()
136 if (fRow)
delete [] fRow;
137 if (fCol)
delete [] fCol;
138 fRow =
new TableData_t[fNrows];
139 fCol =
new TableData_t[fNcols];
144 for (i = 0; i < fNrows; ++i) fRow[i].fDefSize = 0;
145 for (i = 0; i < fNcols; ++i) fCol[i].fDefSize = 0;
151 void TGTableLayout::FindRowColSizesSinglyAttached()
156 while ((ptr = (TGFrameElement *) next())) {
157 if (ptr->fState == 0)
continue;
158 TGTableLayoutHints *layout =
159 dynamic_cast<TGTableLayoutHints*
>(ptr->fLayout);
161 Error(
"FindRowColSizesSinglyAttached",
"didn't get TGTableLayoutHints from %s, layout = 0x%lx",
162 ptr->fFrame->GetName(), (ULong_t)ptr->fLayout);
165 UInt_t col = layout->GetAttachLeft();
166 if (col == (layout->GetAttachRight() - 1))
167 fCol[col].fDefSize = TMath::Max(fCol[col].fDefSize,
168 ptr->fFrame->GetDefaultWidth() +
169 layout->GetPadLeft() +
170 layout->GetPadRight());
172 UInt_t row = layout->GetAttachTop();
173 if (row == (layout->GetAttachBottom() - 1))
174 fRow[row].fDefSize = TMath::Max(fRow[row].fDefSize,
175 ptr->fFrame->GetDefaultHeight() +
176 layout->GetPadTop() +
177 layout->GetPadBottom());
185 void TGTableLayout::FindRowColSizesHomogeneous()
187 if (!fHomogeneous)
return;
189 UInt_t max_width = 0, max_height = 0, col, row;
192 for (col = 0; col < fNcols; ++col)
193 max_width = TMath::Max(max_width,fCol[col].fDefSize);
195 for (row = 0; row < fNrows; ++row)
196 max_height = TMath::Max(max_height,fRow[row].fDefSize);
199 for (col = 0; col < fNcols; ++col) fCol[col].fDefSize = max_width;
200 for (row = 0; row < fNrows; ++row) fRow[row].fDefSize = max_height;
206 void TGTableLayout::FindRowColSizesMultiplyAttached()
211 while ((ptr = (TGFrameElement *) next())) {
212 if (ptr->fState == 0)
continue;
213 TGTableLayoutHints *layout =
214 dynamic_cast<TGTableLayoutHints*
>(ptr->fLayout);
216 Error(
"FindRowColSizesMultiplyAttached",
"didn't get TGTableLayoutHints");
219 UInt_t left = layout->GetAttachLeft();
220 UInt_t right = layout->GetAttachRight();
221 if (left != right-1) {
222 UInt_t width = 0, col;
223 for (col = left; col < right; ++col) width += fCol[col].fDefSize;
226 UInt_t child_width = ptr->fFrame->GetDefaultWidth() +
227 layout->GetPadLeft() + layout->GetPadRight();
229 if (width < child_width) {
230 width = child_width - width;
231 for (col = left; col < right; ++col) {
232 UInt_t extra = width / (right - col);
233 fCol[col].fDefSize += extra;
238 UInt_t top = layout->GetAttachTop();
239 UInt_t bottom = layout->GetAttachBottom();
240 if (top != bottom-1) {
241 UInt_t height = 0, row;
242 for (row = top; row < bottom; ++row) height += fRow[row].fDefSize;
245 UInt_t child_height = ptr->fFrame->GetDefaultHeight() +
246 layout->GetPadTop() + layout->GetPadBottom();
248 if (height < child_height) {
249 height = child_height - height;
250 for (row = top; row < bottom; ++row) {
251 UInt_t extra = height / (bottom - row);
252 fRow[row].fDefSize += extra;
265 void TGTableLayout::SetRowColResize(UInt_t real_size, UInt_t nthings,
266 TableData_t *thing, Bool_t homogeneous)
269 UInt_t ind, nshrink=0, nexpand=0, cur_size=0;
271 for (ind = 0; ind < nthings; ++ind)
272 cur_size += thing[ind].fDefSize;
274 if (cur_size < real_size) {
275 for (ind = 0; ind < nthings; ++ind)
276 if (thing[ind].fExpand) { ++ nexpand;
break; }
278 UInt_t size = real_size;
279 for (ind = 0; ind < nthings; ++ ind) {
280 UInt_t extra = size / (nthings - ind);
281 thing[ind].fRealSize = TMath::Max(1U, extra);
286 if (cur_size > real_size) {
287 for (ind = 0; ind < nthings; ++ind)
288 if (thing[ind].fShrink) { ++ nshrink;
break; }
290 UInt_t size = real_size;
291 for (ind = 0; ind < nthings; ++ ind) {
292 UInt_t extra = size / (nthings - ind);
293 thing[ind].fRealSize = TMath::Max(1U, extra);
299 UInt_t ind, nshrink=0, nexpand=0, size=0;
300 for (ind = 0; ind < nthings; ++ind) {
301 size += thing[ind].fDefSize;
302 if (thing[ind].fExpand) ++ nexpand;
303 if (thing[ind].fShrink) ++ nshrink;
307 if ((size < real_size) && (nexpand >= 1)) {
308 size = real_size - size;
309 for (ind = 0; ind < nthings; ++ind) {
310 if (thing[ind].fExpand) {
311 UInt_t extra = size / nexpand;
312 thing[ind].fRealSize += extra;
320 if (size > real_size) {
321 UInt_t total_nshrink = nshrink;
322 UInt_t extra = size - real_size;
323 while (total_nshrink > 0 && extra > 0) {
324 nshrink = total_nshrink;
325 for (ind = 0; ind < nthings; ++ind)
326 if (thing[ind].fShrink) {
327 UInt_t size2 = thing[ind].fRealSize;
328 thing[ind].fRealSize = TMath::Max(1U,thing[ind].fRealSize - extra / nshrink);
329 extra -= size2 - thing[ind].fRealSize;
331 if (thing[ind].fRealSize < 2) {
333 thing[ind].fShrink = kFALSE;
345 void TGTableLayout::SetRowColSizes()
347 SetRowColSizesInit();
348 UInt_t border_width = fMain->GetBorderWidth();
350 SetRowColResize(fMain->GetWidth() - (fNcols-1)*fSep - 2*border_width,
351 fNcols, fCol, fHomogeneous);
352 SetRowColResize(fMain->GetHeight() - (fNrows-1)*fSep - 2*border_width,
353 fNrows, fRow, fHomogeneous);
360 void TGTableLayout::SetRowColSizesInit()
363 for (col = 0; col < fNcols; ++col) {
364 fCol[col].fRealSize = fCol[col].fDefSize;
365 fCol[col].fNeedExpand = kFALSE;
366 fCol[col].fNeedShrink = kTRUE;
367 fCol[col].fExpand = kFALSE;
368 fCol[col].fShrink = kTRUE;
369 fCol[col].fEmpty = kTRUE;
372 for (row = 0; row < fNrows; ++row) {
373 fRow[row].fRealSize = fRow[row].fDefSize;
374 fRow[row].fNeedExpand = kFALSE;
375 fRow[row].fNeedShrink = kTRUE;
376 fRow[row].fExpand = kFALSE;
377 fRow[row].fShrink = kTRUE;
378 fRow[row].fEmpty = kTRUE;
384 while ((ptr = (TGFrameElement*) next())) {
385 TGTableLayoutHints *layout =
386 dynamic_cast<TGTableLayoutHints*
>(ptr->fLayout);
388 Error(
"SetRowColSizesInit",
"didn't get TGTableLayoutHints");
391 ULong_t hints = layout->GetLayoutHints();
394 if (layout->GetAttachLeft() == layout->GetAttachRight()-1) {
395 if (hints & kLHintsExpandX)
396 fCol[layout->GetAttachLeft()].fExpand = kTRUE;
397 if (!(hints & kLHintsShrinkX))
398 fCol[layout->GetAttachLeft()].fShrink = kFALSE;
399 fCol[layout->GetAttachLeft()].fEmpty = kFALSE;
402 if (layout->GetAttachTop() == layout->GetAttachBottom()-1) {
403 if (hints & kLHintsExpandY)
404 fRow[layout->GetAttachTop()].fExpand = kTRUE;
405 if (!(hints & kLHintsShrinkY))
406 fRow[layout->GetAttachTop()].fShrink = kFALSE;
407 fRow[layout->GetAttachTop()].fEmpty = kFALSE;
413 while ((ptr = (TGFrameElement*) next())) {
414 TGTableLayoutHints *layout =
415 dynamic_cast<TGTableLayoutHints*
>(ptr->fLayout);
417 Error(
"SetRowColSizesInit",
"didn't get TGTableLayoutHints");
420 ULong_t hints = layout->GetLayoutHints();
423 UInt_t left = layout->GetAttachLeft();
424 UInt_t right = layout->GetAttachRight();
425 if (left != right - 1) {
426 for (col = left; col < right; ++col) fCol[col].fEmpty = kFALSE;
427 Bool_t has_expand=kFALSE, has_shrink=kTRUE;
428 if (hints & kLHintsExpandX) {
429 for (col = left; col < right; ++col)
430 if (fCol[col].fExpand) { has_expand = kTRUE;
break; }
432 for (col = left; col < right; ++col)
433 fCol[col].fNeedExpand = kTRUE;
435 if (!(hints & kLHintsShrinkX)) {
436 for (col = left; col < right; ++col)
437 if (!fCol[col].fShrink) { has_shrink = kFALSE;
break;}
439 for (col = left; col < right; ++col)
440 fCol[col].fNeedShrink = kFALSE;
445 UInt_t top = layout->GetAttachTop();
446 UInt_t bottom = layout->GetAttachBottom();
447 if (top != bottom - 1) {
448 for (row = top; row < bottom; ++row) fRow[row].fEmpty = kFALSE;
449 Bool_t has_expand=kFALSE, has_shrink=kTRUE;
450 if (hints & kLHintsExpandY) {
451 for (row = top; row < bottom; ++row)
452 if (fRow[row].fExpand) { has_expand = kTRUE;
break; }
454 for (row = top; row < bottom; ++row)
455 fRow[row].fNeedExpand = kTRUE;
457 if (!(hints & kLHintsShrinkY)) {
458 for (row = top; row < bottom; ++row)
459 if (!fRow[row].fShrink) { has_shrink = kFALSE;
break;}
461 for (row = top; row < bottom; ++row)
462 fRow[row].fNeedShrink = kFALSE;
468 for (col = 0; col < fNcols; ++col) {
469 if (fCol[col].fEmpty) {
470 fCol[col].fExpand = kFALSE;
471 fCol[col].fShrink = kFALSE;
473 if (fCol[col].fNeedExpand) fCol[col].fExpand = kTRUE;
474 if (!fCol[col].fNeedShrink) fCol[col].fShrink = kFALSE;
477 for (row = 0; row < fNrows; ++row) {
478 if (fRow[row].fEmpty) {
479 fRow[row].fExpand = kFALSE;
480 fRow[row].fShrink = kFALSE;
482 if (fRow[row].fNeedExpand) fRow[row].fExpand = kTRUE;
483 if (!fRow[row].fNeedShrink) fRow[row].fShrink = kFALSE;
491 void TGTableLayout::CheckSanity()
496 while ((ptr = (TGFrameElement*) next())) {
497 TGTableLayoutHints *layout =
498 dynamic_cast<TGTableLayoutHints*
>(ptr->fLayout);
500 Error(
"CheckSanity",
"didn't get TGTableLayoutHints");
504 UInt_t right = layout->GetAttachRight();
505 UInt_t left = layout->GetAttachLeft();
506 UInt_t top = layout->GetAttachTop();
507 UInt_t bottom = layout->GetAttachBottom();
511 Error(
"CheckSanity",
"AttachLeft == AttachRight");
515 Error(
"CheckSanity",
"AttachLeft > AttachRight");
517 if (left > fNcols-1) {
519 Error(
"CheckSanity",
"AttachLeft illegal value: %u", left);
521 if (right < 1 || right > fNcols) {
523 Error(
"CheckSanity",
"AttachRight illegal value: %u", right);
528 Error(
"CheckSanity",
"AttachTop == AttachBottom");
532 Error(
"CheckSanity",
"AttachTop > AttachBottom");
534 if (top > fNrows-1) {
536 Error(
"CheckSanity",
"AttachTop illegal value: %u", top);
538 if (bottom < 1 || bottom > fNrows) {
540 Error(
"CheckSanity",
"AttachBottom illegal value: %u", bottom);
545 Error(
"CheckSanity",
"errors in %u x %u table", fNcols, fNrows);
552 void TGTableLayout::Layout()
563 UInt_t border_width = fMain->GetBorderWidth();
564 while ((ptr = (TGFrameElement*) next())) {
565 TGTableLayoutHints *layout =
566 dynamic_cast<TGTableLayoutHints*
>(ptr->fLayout);
568 Error(
"TGTableLayout::Layout",
"didn't get TGTableLayoutHints");
571 ULong_t hints = layout->GetLayoutHints();
572 TGDimension size = ptr->fFrame->GetDefaultSize();
574 UInt_t right = layout->GetAttachRight();
575 UInt_t left = layout->GetAttachLeft();
576 UInt_t top = layout->GetAttachTop();
577 UInt_t bottom = layout->GetAttachBottom();
580 UInt_t col, cell_x = border_width + left*fSep;
581 for (col = 0; col < left; ++col) cell_x += fCol[col].fRealSize;
583 UInt_t row, cell_y = border_width + top*fSep;
584 for (row = 0; row < top; ++row) cell_y += fRow[row].fRealSize;
586 UInt_t cell_width = (right-left-1)*fSep;
587 for (col=left; col < right; ++col)
588 cell_width += fCol[col].fRealSize;
590 UInt_t cell_height = (bottom-top-1)*fSep;
591 for (row=top; row < bottom; ++row)
592 cell_height += fRow[row].fRealSize;
594 UInt_t pad_left = layout->GetPadLeft();
595 UInt_t pad_right = layout->GetPadRight();
596 UInt_t pad_bottom = layout->GetPadBottom();
597 UInt_t pad_top = layout->GetPadTop();
601 if (hints & kLHintsFillX)
602 ww = cell_width - pad_left - pad_right;
605 if (hints & kLHintsFillY)
606 hh = cell_height - pad_top - pad_bottom;
612 if (hints & kLHintsFillX)
613 xx = cell_x + pad_left;
614 else if (hints & kLHintsRight)
615 xx = cell_x + cell_width - pad_right - ww;
616 else if (hints & kLHintsCenterX)
617 xx = cell_x + cell_width/2 - ww/2;
619 xx = cell_x + pad_left;
622 if (hints & kLHintsFillY)
623 yy = cell_y + pad_top;
624 else if (hints & kLHintsBottom)
625 yy = cell_y + cell_height - pad_bottom - hh;
626 else if (hints & kLHintsCenterY)
627 yy = cell_y + cell_height/2 - hh/2;
629 yy = cell_y + pad_top;
631 ptr->fFrame->MoveResize(xx,yy,ww,hh);
632 ptr->fFrame->Layout();
640 TGDimension TGTableLayout::GetDefaultSize()
const
642 TGDimension msize = fMain->GetSize();
643 UInt_t options = fMain->GetOptions();
645 if ((options & kFixedWidth) && (options & kFixedHeight))
648 Int_t border_width = fMain->GetBorderWidth();
650 TGDimension size(2*border_width + (fNcols-1)*fSep,
651 2*border_width + (fNrows-1)*fSep);
655 for (col = 0; col < fNcols; ++col) size.fWidth += fCol[col].fDefSize;
657 for (row = 0; row < fNrows; ++row) size.fHeight += fRow[row].fDefSize;
659 if (options & kFixedWidth) size.fWidth = msize.fWidth;
660 if (options & kFixedHeight) size.fHeight = msize.fHeight;
665 void TGTableLayoutHints::SavePrimitive(std::ostream &out, Option_t * )
671 UInt_t pad = GetPadLeft()+GetPadRight()+GetPadTop()+GetPadBottom();
673 if (!GetLayoutHints())
return;
675 if ((fLayoutHints == kLHintsNormal) && (pad == 0))
return;
677 if (fLayoutHints & kLHintsLeft) {
678 if (hints.Length() == 0) hints =
"kLHintsLeft";
679 else hints +=
" | kLHintsLeft";
681 if (fLayoutHints & kLHintsCenterX) {
682 if (hints.Length() == 0) hints =
"kLHintsCenterX";
683 else hints +=
" | kLHintsCenterX";
685 if (fLayoutHints & kLHintsRight) {
686 if (hints.Length() == 0) hints =
"kLHintsRight";
687 else hints +=
" | kLHintsRight";
689 if (fLayoutHints & kLHintsTop) {
690 if (hints.Length() == 0) hints =
"kLHintsTop";
691 else hints +=
" | kLHintsTop";
693 if (fLayoutHints & kLHintsCenterY) {
694 if (hints.Length() == 0) hints =
"kLHintsCenterY";
695 else hints +=
" | kLHintsCenterY";
697 if (fLayoutHints & kLHintsBottom) {
698 if (hints.Length() == 0) hints =
"kLHintsBottom";
699 else hints +=
" | kLHintsBottom";
701 if (fLayoutHints & kLHintsExpandX) {
702 if (hints.Length() == 0) hints =
"kLHintsExpandX";
703 else hints +=
" | kLHintsExpandX";
705 if (fLayoutHints & kLHintsExpandY) {
706 if (hints.Length() == 0) hints =
"kLHintsExpandY";
707 else hints +=
" | kLHintsExpandY";
709 if (fLayoutHints & kLHintsShrinkX) {
710 if (hints.Length() == 0) hints =
"kLHintsShrinkX";
711 else hints +=
" | kLHintsShrinkX";
713 if (fLayoutHints & kLHintsShrinkY) {
714 if (hints.Length() == 0) hints =
"kLHintsShrinkY";
715 else hints +=
" | kLHintsShrinkY";
717 if (fLayoutHints & kLHintsFillX) {
718 if (hints.Length() == 0) hints =
"kLHintsFillX";
719 else hints +=
" | kLHintsFillX";
721 if (fLayoutHints & kLHintsFillY) {
722 if (hints.Length() == 0) hints =
"kLHintsFillY";
723 else hints +=
" | kLHintsFillY";
725 out <<
", new TGTableLayoutHints(" << GetAttachLeft() <<
"," << GetAttachRight()
726 <<
"," << GetAttachTop() <<
"," << GetAttachBottom()
730 out <<
"," << GetPadLeft() <<
"," << GetPadRight()
731 <<
"," << GetPadTop() <<
"," << GetPadBottom();
737 void TGTableLayout::SavePrimitive(std::ostream &out, Option_t * )
742 out <<
" new TGTableLayout(" << fMain->GetName() <<
"," << fNrows <<
"," << fNcols;
745 if (fHomogeneous == kTRUE)