00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TGPack.h"
00013 #include "TGSplitter.h"
00014 #include "TMath.h"
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 ClassImp(TGPack);
00028
00029
00030 TGPack::TGPack(const TGWindow *p, UInt_t w, UInt_t h, UInt_t options, Pixel_t back) :
00031 TGCompositeFrame(p, w, h, options, back),
00032 fVertical (kTRUE),
00033 fUseSplitters (kTRUE),
00034 fSplitterLen (4),
00035 fDragOverflow (0),
00036 fWeightSum(0),
00037 fNVisible(0)
00038 {
00039
00040
00041 SetCleanup(kLocalCleanup);
00042 }
00043
00044
00045 TGPack::TGPack(TGClient *c, Window_t id, const TGWindow *parent) :
00046 TGCompositeFrame(c, id, parent),
00047 fVertical (kTRUE),
00048 fUseSplitters (kTRUE),
00049 fSplitterLen (4),
00050 fDragOverflow (0),
00051 fWeightSum (0.0),
00052 fNVisible (0)
00053 {
00054
00055
00056 SetCleanup(kLocalCleanup);
00057 }
00058
00059
00060 TGPack::~TGPack()
00061 {
00062
00063 }
00064
00065
00066
00067
00068 Int_t TGPack::GetAvailableLength() const
00069 {
00070
00071
00072 Int_t len = fVertical ? GetHeight() : GetWidth();
00073 len -= fSplitterLen * (fNVisible - 1);
00074
00075 return len;
00076 }
00077
00078
00079 void TGPack::SetFrameLength(TGFrame* f, Int_t len)
00080 {
00081
00082
00083 if (fVertical)
00084 f->Resize(GetWidth(), len);
00085 else
00086 f->Resize(len, GetHeight());
00087 }
00088
00089
00090 void TGPack::SetFramePosition(TGFrame* f, Int_t pos)
00091 {
00092
00093
00094 if (fVertical)
00095 f->Move(0, pos);
00096 else
00097 f->Move(pos, 0);
00098 }
00099
00100
00101 void TGPack::CheckSplitterVisibility()
00102 {
00103
00104
00105
00106 TGFrameElementPack *el;
00107 TIter next(fList);
00108 Int_t rvf = 0;
00109 while ((el = (TGFrameElementPack*) next()))
00110 {
00111 if (el->fState && el->fSplitFE)
00112 {
00113 if (rvf)
00114 {
00115
00116 if ( el->fSplitFE->fState == 0 ) {
00117 el->fSplitFE->fState = 1;
00118 el->fSplitFE->fFrame->MapWindow();
00119 }
00120 }
00121 else
00122 {
00123
00124 if (el->fSplitFE->fState) {
00125 el->fSplitFE->fState = 0;
00126 el->fSplitFE->fFrame->UnmapWindow();
00127 }
00128 }
00129 ++rvf;
00130 }
00131 }
00132 }
00133
00134
00135 void TGPack::ResizeExistingFrames()
00136 {
00137
00138
00139 if (fList->IsEmpty())
00140 return;
00141
00142
00143 Int_t nflen = GetAvailableLength();
00144 Float_t unit = Float_t(nflen)/fWeightSum;
00145
00146
00147 Int_t sumFrames = 0;
00148 Int_t frameLength = 0;
00149 {
00150 TGFrameElementPack *el;
00151 TIter next(fList);
00152 while ((el = (TGFrameElementPack*) next()))
00153 {
00154 if (el->fState && el->fWeight)
00155 {
00156 frameLength = TMath::Nint( unit*(el->fWeight));
00157 SetFrameLength(el->fFrame, frameLength);
00158 sumFrames += frameLength;
00159 }
00160 }
00161 }
00162
00163
00164 {
00165
00166 Int_t remain = nflen-sumFrames;
00167 Int_t step = TMath::Sign(1, remain);
00168 TGFrameElementPack *el;
00169 TIter next(fList);
00170 while ((el = (TGFrameElementPack*) next()) && remain)
00171 {
00172 if (el->fState && el->fWeight)
00173 {
00174 Int_t l = GetFrameLength(el->fFrame) + step;
00175 if (l > 0)
00176 {
00177 SetFrameLength(el->fFrame, l);
00178 remain -= step;
00179 }
00180 }
00181 }
00182 }
00183 RefitFramesToPack();
00184 }
00185
00186
00187 void TGPack::RefitFramesToPack()
00188 {
00189
00190
00191 TGFrameElement *el;
00192 TIter next(fList);
00193
00194 while ((el = (TGFrameElement *) next()))
00195 {
00196 if (fVertical)
00197 el->fFrame->Resize(GetWidth(), el->fFrame->GetHeight());
00198 else
00199 el->fFrame->Resize(el->fFrame->GetWidth(), GetHeight());
00200 }
00201 }
00202
00203
00204 void TGPack::FindFrames(TGFrame* splitter, TGFrameElementPack*& f0, TGFrameElementPack*& f1) const
00205 {
00206
00207
00208 TGFrameElementPack *el;
00209 TIter next(fList);
00210
00211 while ((el = (TGFrameElementPack *) next()))
00212 {
00213 if ( ! el->fState & kIsVisible)
00214 continue;
00215
00216 if (el->fFrame == splitter)
00217 break;
00218 f0 = el;
00219 }
00220 f1 = (TGFrameElementPack *) next();
00221 }
00222
00223
00224
00225
00226
00227 void TGPack::AddFrameInternal(TGFrame* f, TGLayoutHints* l, Float_t weight)
00228 {
00229
00230
00231
00232
00233 TGFrameElementPack *sf = 0;
00234 if (fUseSplitters) {
00235 TGSplitter* s = 0;
00236 if (fVertical)
00237 s = new TGHSplitter(this, GetWidth(), fSplitterLen, kTRUE);
00238 else
00239 s = new TGVSplitter(this, fSplitterLen, GetHeight(), kTRUE);
00240 s->Connect("Moved(Int_t)", "TGPack", this, "HandleSplitterResize(Int_t)");
00241 s->Connect("DragStarted()", "TGPack", this, "HandleSplitterStart()");
00242
00243 sf = new TGFrameElementPack(s, l ? l : fgDefaultHints, 0);
00244 fList->Add(sf);
00245
00246
00247 if (fMustCleanup == kDeepCleanup)
00248 s->SetCleanup(kDeepCleanup);
00249 s->MapWindow();
00250 }
00251
00252
00253 TGFrameElementPack *el = new TGFrameElementPack(f, l ? l : fgDefaultHints, weight);
00254 el->fSplitFE = sf;
00255 fList->Add(el);
00256
00257
00258
00259 if (fMustCleanup == kDeepCleanup)
00260 f->SetCleanup(kDeepCleanup);
00261 f->MapWindow();
00262
00263 fNVisible ++;
00264 fWeightSum += weight;
00265
00266 CheckSplitterVisibility();
00267 ResizeExistingFrames();
00268 }
00269
00270
00271 void TGPack::AddFrameWithWeight(TGFrame* f, TGLayoutHints *l, Float_t weight)
00272 {
00273
00274
00275
00276 AddFrameInternal(f, l, weight);
00277 Layout();
00278 }
00279
00280
00281 void TGPack::AddFrame(TGFrame* f, TGLayoutHints *l)
00282 {
00283
00284
00285
00286 AddFrameInternal(f, l, 1);
00287 Layout();
00288 }
00289
00290
00291 void TGPack::RemoveFrameInternal(TGFrame* f)
00292 {
00293
00294
00295 TGFrameElementPack *el = (TGFrameElementPack*)FindFrameElement(f);
00296
00297 if (!el) return;
00298
00299 if (fUseSplitters)
00300 {
00301 TGFrame* splitter = el->fSplitFE->fFrame;
00302 splitter->UnmapWindow();
00303 TGCompositeFrame::RemoveFrame(splitter);
00304
00305 splitter->ReparentWindow(fClient->GetDefaultRoot());
00306 delete splitter;
00307 }
00308 if (el->fState & kIsVisible)
00309 {
00310 f->UnmapWindow();
00311 fWeightSum -= el->fWeight;
00312 --fNVisible;
00313 }
00314 TGCompositeFrame::RemoveFrame(f);
00315
00316 CheckSplitterVisibility();
00317 ResizeExistingFrames();
00318 }
00319
00320
00321 void TGPack::DeleteFrame(TGFrame* f)
00322 {
00323
00324
00325
00326 RemoveFrameInternal(f);
00327 delete f;
00328 Layout();
00329 }
00330
00331
00332 void TGPack::RemoveFrame(TGFrame* f)
00333 {
00334
00335
00336
00337 RemoveFrameInternal(f);
00338 Layout();
00339 }
00340
00341
00342 void TGPack::Dump() const
00343 {
00344
00345
00346 printf("--------------------------------------------------------------\n");
00347 Int_t cnt = 0;
00348 TGFrameElementPack *el;
00349 TIter next(fList);
00350 while ((el = (TGFrameElementPack *) next()))
00351 {
00352 printf("idx[%d] visible(%d) %s \n",cnt, el->fState, el->fFrame->GetName());
00353 cnt++;
00354 }
00355 printf("--------------------------------------------------------------\n");
00356 }
00357
00358
00359 void TGPack::ShowFrame(TGFrame* f)
00360 {
00361
00362
00363
00364 TGFrameElementPack *el = (TGFrameElementPack*)FindFrameElement(f);
00365 if (el)
00366 {
00367
00368 el->fState = 1;
00369 el->fFrame->MapWindow();
00370
00371
00372 if (fUseSplitters)
00373 {
00374 el->fSplitFE->fFrame->MapWindow();
00375 el->fSplitFE->fState = 1;
00376 }
00377
00378
00379 fNVisible++;
00380 fWeightSum += el->fWeight;
00381
00382 CheckSplitterVisibility();
00383 ResizeExistingFrames();
00384 Layout();
00385 }
00386 }
00387
00388
00389 void TGPack::HideFrame(TGFrame* f)
00390 {
00391
00392
00393
00394 TGFrameElementPack *el = (TGFrameElementPack*) FindFrameElement(f);
00395 if (el)
00396 {
00397
00398 el->fState = 0;
00399 el->fFrame->UnmapWindow();
00400
00401
00402 if (fUseSplitters)
00403 {
00404 el->fSplitFE->fFrame->UnmapWindow();
00405 el->fSplitFE->fState = 0;
00406 }
00407
00408
00409 fNVisible--;
00410 fWeightSum -= el->fWeight;
00411
00412 CheckSplitterVisibility();
00413 ResizeExistingFrames();
00414 Layout();
00415 }
00416 }
00417
00418
00419
00420
00421 void TGPack::MapSubwindows()
00422 {
00423
00424
00425
00426 if (!fMapSubwindows) {
00427 return;
00428 }
00429
00430 if (!fList) return;
00431
00432 TGFrameElement *el;
00433 TIter next(fList);
00434
00435 while ((el = (TGFrameElement *) next())) {
00436 if (el->fFrame && el->fState) {
00437 el->fFrame->MapWindow();
00438 el->fFrame->MapSubwindows();
00439 TGFrameElement *fe = el->fFrame->GetFrameElement();
00440 if (fe) fe->fState |= kIsVisible;
00441 }
00442 }
00443 }
00444
00445
00446 void TGPack::Resize(UInt_t w, UInt_t h)
00447 {
00448
00449
00450
00451 if (w == fWidth && h == fHeight) return;
00452
00453 fWidth = w;
00454 fHeight = h;
00455 TGWindow::Resize(fWidth, fHeight);
00456
00457 ResizeExistingFrames();
00458
00459 Layout();
00460 }
00461
00462
00463 void TGPack::MoveResize(Int_t x, Int_t y, UInt_t w, UInt_t h)
00464 {
00465
00466
00467 TGCompositeFrame::Move(x, y);
00468 Resize(w, h);
00469 }
00470
00471
00472 void TGPack::Layout()
00473 {
00474
00475
00476
00477 Int_t pos = 0;
00478
00479 TGFrameElement *el;
00480 TIter next(fList);
00481
00482 while ((el = (TGFrameElement *) next()))
00483 {
00484 if (el->fState)
00485 {
00486 SetFramePosition(el->fFrame, pos);
00487 pos += GetFrameLength(el->fFrame);
00488 el->fFrame->Layout();
00489 }
00490 }
00491 }
00492
00493
00494 void TGPack::EqualizeFrames()
00495 {
00496
00497
00498 if (fList->IsEmpty())
00499 return;
00500
00501 fWeightSum = 0;
00502 TGFrameElementPack *el;
00503 TIter next(fList);
00504 while ((el = (TGFrameElementPack *) next()))
00505 {
00506 el->fWeight = 1;
00507 if (el->fState)
00508 fWeightSum ++;
00509 }
00510
00511 ResizeExistingFrames();
00512 Layout();
00513 }
00514
00515
00516 void TGPack::HandleSplitterStart()
00517 {
00518
00519
00520 fDragOverflow = 0;
00521 }
00522
00523
00524 void TGPack::HandleSplitterResize(Int_t delta)
00525 {
00526
00527
00528 Int_t available = GetAvailableLength();
00529 Int_t min_dec = - (available + fNVisible*2 -1);
00530 if (delta < min_dec)
00531 delta = min_dec;
00532
00533 TGSplitter *s = dynamic_cast<TGSplitter*>((TGFrame*) gTQSender);
00534
00535 TGFrameElementPack *f0=0, *f1=0;
00536 FindFrames(s, f0, f1);
00537
00538 if (fDragOverflow < 0)
00539 {
00540 fDragOverflow += delta;
00541 if (fDragOverflow > 0) {
00542 delta = fDragOverflow;
00543 fDragOverflow = 0;
00544 } else {
00545 return;
00546 }
00547 }
00548 else if (fDragOverflow > 0)
00549 {
00550 fDragOverflow += delta;
00551 if (fDragOverflow < 0) {
00552 delta = fDragOverflow;
00553 fDragOverflow = 0;
00554 } else {
00555 return;
00556 }
00557 }
00558
00559 Int_t l0 = GetFrameLength(f0->fFrame);
00560 Int_t l1 = GetFrameLength(f1->fFrame);
00561 if (delta < 0)
00562 {
00563 if (l0 - 1 < -delta)
00564 {
00565 fDragOverflow += delta + l0 - 1;
00566 delta = -l0 + 1;
00567 }
00568 }
00569 else
00570 {
00571 if (l1 - 1 < delta)
00572 {
00573 fDragOverflow += delta - l1 + 1;
00574 delta = l1 - 1;
00575 }
00576 }
00577 l0 += delta;
00578 l1 -= delta;
00579 SetFrameLength(f0->fFrame, l0);
00580 SetFrameLength(f1->fFrame, l1);
00581 Float_t weightDelta = Float_t(delta)/available;
00582 weightDelta *= fWeightSum;
00583 f0->fWeight += weightDelta;
00584 f1->fWeight -= weightDelta;
00585
00586 ResizeExistingFrames();
00587 Layout();
00588 }
00589
00590
00591
00592
00593 void TGPack::SetVertical(Bool_t x)
00594 {
00595
00596
00597
00598 if (x == fVertical)
00599 return;
00600
00601 TList list;
00602 while ( ! fList->IsEmpty())
00603 {
00604 TGFrameElement *el = (TGFrameElement*) fList->At(1);
00605 TGFrame *f = el->fFrame;
00606 if ( ! el->fState & kIsVisible)
00607 f->SetBit(kTempFrame);
00608 RemoveFrameInternal(f);
00609 list.Add(f);
00610 }
00611 fVertical = x;
00612 while ( ! list.IsEmpty())
00613 {
00614 TGFrame* f = (TGFrame*) list.First();
00615 AddFrameInternal(f);
00616 if (f->TestBit(kTempFrame)) {
00617 f->ResetBit(kTempFrame);
00618 HideFrame(f);
00619 }
00620 list.RemoveFirst();
00621 }
00622 Layout();
00623 }