TGPack.cxx

Go to the documentation of this file.
00001 // @(#)root/eve:$Id: TGPack.cxx 31870 2009-12-13 22:33:55Z brun $
00002 // Author: Matevz Tadel 2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TGPack.h"
00013 #include "TGSplitter.h"
00014 #include "TMath.h"
00015 
00016 //______________________________________________________________________________
00017 //
00018 // Stack of frames in horizontal (default) or vertical stack.
00019 // The splitters are placed between the neighbouring frames so that
00020 // they can be resized by the user.
00021 // When the whole pack is resized, frames are scaled proportionally to
00022 // their previous size.
00023 //
00024 // When frames are left in pack at destruction time, they will be
00025 // deleted via local-cleanup.
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    // Constructor.
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    // Constructor.
00055 
00056    SetCleanup(kLocalCleanup);
00057 }
00058 
00059 //______________________________________________________________________________
00060 TGPack::~TGPack()
00061 {
00062    // Destructor.
00063 }
00064 
00065 //------------------------------------------------------------------------------
00066 
00067 //______________________________________________________________________________
00068 Int_t TGPack::GetAvailableLength() const
00069 {
00070    // Return length of entire frame without splitters.
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    // Set pack-wise length of frame f.
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    // Set pack-wise position of frame f.
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    // Check if splitter of first visible frame is hidden.
00104    // Check if the next following visible splitter is visible.
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             // unmap first slider if necessary
00116             if ( el->fSplitFE->fState == 0 ) { 
00117                el->fSplitFE->fState = 1;
00118                el->fSplitFE->fFrame->MapWindow();
00119             }
00120          }
00121          else
00122          {
00123             // show slider in next visible frame
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    // Resize (shrink or expand) existing frames by amount in total.
00138 
00139    if (fList->IsEmpty())
00140       return;
00141 
00142    // get unitsize
00143    Int_t nflen  = GetAvailableLength();
00144    Float_t unit = Float_t(nflen)/fWeightSum;
00145 
00146    // set frame sizes
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    // redistribute the remain
00164    {
00165       // printf("available %d total %d \n", nflen, sumFrames);
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    // Refit existing frames to pack size.
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    // Find frames around splitter and return them f0 (previous) and f1 (next).
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    // Add frame f at the end.
00230    // LayoutHints are ignored in TGPack.
00231 
00232    // add splitter
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       // in case of recusive cleanup, propagate cleanup setting to all
00246       // child composite frames
00247       if (fMustCleanup == kDeepCleanup)
00248          s->SetCleanup(kDeepCleanup);
00249       s->MapWindow();
00250    }
00251 
00252    // instread TGCopositeFrame::AddFrame
00253    TGFrameElementPack *el = new TGFrameElementPack(f, l ? l : fgDefaultHints, weight);
00254    el->fSplitFE = sf;
00255    fList->Add(el);
00256 
00257    // in case of recusive cleanup, propagate cleanup setting to all
00258    // child composite frames
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    // Add frame f at the end with given weight.
00274    // LayoutHints are ignored in TGPack.
00275 
00276    AddFrameInternal(f, l, weight);
00277    Layout();
00278 }
00279 
00280 //______________________________________________________________________________
00281 void TGPack::AddFrame(TGFrame* f, TGLayoutHints *l)
00282 {
00283    // Add frame f at the end with default weight.
00284    // LayoutHints are ignored in TGPack.
00285 
00286    AddFrameInternal(f, l, 1);
00287    Layout();
00288 }
00289 
00290 //______________________________________________________________________________
00291 void TGPack::RemoveFrameInternal(TGFrame* f)
00292 {
00293    // Remove frame f.
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       // This is needed so that splitter window gets destroyed on server.
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    // Remove frame f and refit existing frames to pack size.
00324    // Frame is deleted.
00325 
00326    RemoveFrameInternal(f);
00327    delete f;
00328    Layout();
00329 }
00330 
00331 //______________________________________________________________________________
00332 void TGPack::RemoveFrame(TGFrame* f)
00333 {
00334    // Remove frame f and refit existing frames to pack size.
00335    // Frame is not deleted.
00336 
00337    RemoveFrameInternal(f);
00338    Layout();
00339 }
00340 
00341 //______________________________________________________________________________
00342 void TGPack::Dump() const
00343 {
00344    // Print sub frame info.
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    // Show sub frame.
00362    // Virtual from TGCompositeFrame.
00363 
00364    TGFrameElementPack *el = (TGFrameElementPack*)FindFrameElement(f);
00365    if (el)
00366    {
00367       //show
00368       el->fState = 1;
00369       el->fFrame->MapWindow();
00370 
00371       // show splitter
00372       if (fUseSplitters)
00373       {
00374          el->fSplitFE->fFrame->MapWindow();
00375          el->fSplitFE->fState = 1;
00376       }
00377 
00378       // Dump();
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    // Hide sub frame.
00392    // Virtual from TGCompositeFrame.
00393 
00394    TGFrameElementPack *el = (TGFrameElementPack*) FindFrameElement(f);
00395    if (el)
00396    {
00397       // hide real frame
00398       el->fState = 0;
00399       el->fFrame->UnmapWindow();
00400 
00401       // hide splitter
00402       if (fUseSplitters)
00403       {
00404          el->fSplitFE->fFrame->UnmapWindow();
00405          el->fSplitFE->fState = 0;
00406       }
00407 
00408       // Dump();
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    // Virtual method of TGcompositeFrame.
00424    // Map all sub windows that are part of the composite frame.
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    // Resize the pack.
00449    // Contents is resized proportionally.
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    // Move and resize the pack.
00466 
00467    TGCompositeFrame::Move(x, y);
00468    Resize(w, h);
00469 }
00470 
00471 //______________________________________________________________________________
00472 void TGPack::Layout()
00473 {
00474    // Reposition the frames so that they fit correctly.
00475    // LayoutHints are ignored.
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    // Refit existing frames so that their lengths are equal.
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    // Called when splitter drag starts.
00519 
00520    fDragOverflow = 0;
00521 }
00522 
00523 //______________________________________________________________________________
00524 void TGPack::HandleSplitterResize(Int_t delta)
00525 {
00526    // Handle resize events from splitters.
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    // Sets the vertical flag and reformats the back to new stacking
00596    // direction.
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 }

Generated on Tue Jul 5 14:22:02 2011 for ROOT_528-00b_version by  doxygen 1.5.1