#include "TGPack.h"
#include "TGSplitter.h"
#include <algorithm>
#include <vector>
ClassImp(TGPack);
TGPack::TGPack(const TGWindow *p, UInt_t w, UInt_t h, UInt_t options, Pixel_t back) :
TGCompositeFrame(p, w, h, options, back),
fVertical (kTRUE),
fUseSplitters (kTRUE),
fSplitterLen (4),
fDragOverflow (0)
{
SetCleanup(kLocalCleanup);
}
TGPack::TGPack(TGClient *c, Window_t id, const TGWindow *parent) :
TGCompositeFrame(c, id, parent),
fVertical (kTRUE),
fUseSplitters (kTRUE),
fSplitterLen (4),
fDragOverflow (0)
{
SetCleanup(kLocalCleanup);
}
TGPack::~TGPack()
{
}
Int_t TGPack::GetAvailableLength() const
{
Int_t len = fVertical ? GetHeight() : GetWidth();
if (fUseSplitters)
len -= fSplitterLen * (fList->GetSize() - 1) / 2;
return len;
}
void TGPack::SetFrameLength(TGFrame* f, Int_t len)
{
if (fVertical)
f->Resize(GetWidth(), len);
else
f->Resize(len, GetHeight());
}
void TGPack::SetFramePosition(TGFrame* f, Int_t pos)
{
if (fVertical)
f->Move(0, pos);
else
f->Move(pos, 0);
}
Int_t TGPack::NumberOfRealFrames() const
{
if (fUseSplitters)
return (fList->GetSize() + 1) / 2;
else
return fList->GetSize();
}
Int_t TGPack::LengthOfRealFrames() const
{
Int_t l = 0;
TGFrameElement *el;
TIter next(fList);
while ((el = (TGFrameElement *) next()))
{
l += GetFrameLength(el->fFrame);
if (fUseSplitters)
next();
}
return l;
}
void TGPack::ResizeExistingFrames(Int_t amount)
{
if (amount > 0)
ExpandExistingFrames(amount);
else if (amount < 0)
ShrinkExistingFrames(-amount);
RefitFramesToPack();
}
void TGPack::ExpandExistingFrames(Int_t amount)
{
if (fList->IsEmpty())
return;
Int_t length = LengthOfRealFrames();
Int_t remainder = amount;
std::vector<TGFrame*> frame_vec;
{
TGFrameElement *el;
TIter next(fList);
while ((el = (TGFrameElement *) next()))
{
Int_t l = GetFrameLength(el->fFrame);
Int_t d = (l * amount) / length;
SetFrameLength(el->fFrame, l + d);
remainder -= d;
frame_vec.push_back(el->fFrame);
if (fUseSplitters)
next();
}
}
std::random_shuffle(frame_vec.begin(), frame_vec.end());
while (remainder > 0)
{
std::vector<TGFrame*>::iterator fi = frame_vec.begin();
while (fi != frame_vec.end() && remainder > 0)
{
Int_t l = GetFrameLength(*fi);
if (l > 0)
{
SetFrameLength(*fi, l + 1);
--remainder;
}
++fi;
}
}
}
void TGPack::ShrinkExistingFrames(Int_t amount)
{
Int_t length = LengthOfRealFrames();
Int_t remainder = amount;
std::vector<TGFrame*> frame_vec;
{
TIter next(fList);
TGFrameElement *el;
while ((el = (TGFrameElement *) next()))
{
Int_t l = GetFrameLength(el->fFrame);
Int_t d = (l * amount) / length;
SetFrameLength(el->fFrame, l - d);
remainder -= d;
frame_vec.push_back(el->fFrame);
if (fUseSplitters)
next();
}
}
std::random_shuffle(frame_vec.begin(), frame_vec.end());
Bool_t all_one = kFALSE;
while (remainder > 0 && ! all_one)
{
all_one = kTRUE;
std::vector<TGFrame*>::iterator fi = frame_vec.begin();
while (fi != frame_vec.end() && remainder > 0)
{
Int_t l = GetFrameLength(*fi);
if (l > 1)
{
all_one = kFALSE;
SetFrameLength(*fi, l - 1);
--remainder;
}
++fi;
}
}
}
void TGPack::RefitFramesToPack()
{
TGFrameElement *el;
TIter next(fList);
while ((el = (TGFrameElement *) next()))
{
if (fVertical)
el->fFrame->Resize(GetWidth(), el->fFrame->GetHeight());
else
el->fFrame->Resize(el->fFrame->GetWidth(), GetHeight());
}
}
void TGPack::FindFrames(TGFrame* splitter, TGFrame*& f0, TGFrame*& f1)
{
TGFrameElement *el;
TIter next(fList);
while ((el = (TGFrameElement *) next()))
{
if (el->fFrame == splitter)
break;
f0 = el->fFrame;
}
el = (TGFrameElement *) next();
f1 = el->fFrame;
}
void TGPack::AddFrameInternal(TGFrame* f, TGLayoutHints* l)
{
Int_t n = NumberOfRealFrames();
Int_t nflen = (GetLength() - (fUseSplitters ? fSplitterLen*n : 0)) / (n + 1);
if (n > 0)
{
ShrinkExistingFrames(nflen);
if (fUseSplitters) {
nflen -= fSplitterLen;
TGSplitter* s = 0;
if (fVertical)
s = new TGHSplitter(this, GetWidth(), fSplitterLen, kTRUE);
else
s = new TGVSplitter(this, fSplitterLen, GetHeight(), kTRUE);
s->Connect("Moved(Int_t)", "TGPack", this, "HandleSplitterResize(Int_t)");
s->Connect("DragStarted()", "TGPack", this, "HandleSplitterStart()");
TGCompositeFrame::AddFrame(s);
s->MapWindow();
}
}
SetFrameLength(f, nflen);
TGCompositeFrame::AddFrame(f, l);
f->MapWindow();
}
void TGPack::AddFrame(TGFrame* f, TGLayoutHints* l)
{
AddFrameInternal(f, l);
Layout();
}
Int_t TGPack::RemoveFrameInternal(TGFrame* f)
{
TGFrameElement *el = FindFrameElement(f);
if (!el) return 0;
Int_t space_freed = 0;
if (fUseSplitters && NumberOfRealFrames() > 1)
{
TGFrameElement *splitter_el = 0;
if (el == fList->First())
splitter_el = (TGFrameElement*) fList->After(el);
else
splitter_el = (TGFrameElement*) fList->Before(el);
TGFrame* splitter = splitter_el->fFrame;
space_freed += fSplitterLen;
splitter->UnmapWindow();
TGCompositeFrame::RemoveFrame(splitter);
splitter->ReparentWindow(fClient->GetDefaultRoot());
delete splitter;
}
space_freed += GetFrameLength(f);
f->UnmapWindow();
TGCompositeFrame::RemoveFrame(f);
return space_freed;
}
void TGPack::DeleteFrame(TGFrame* f)
{
Int_t space_freed = RemoveFrameInternal(f);
if (space_freed)
{
delete f;
ResizeExistingFrames(space_freed);
Layout();
}
}
void TGPack::RemoveFrame(TGFrame* f)
{
Int_t space_freed = RemoveFrameInternal(f);
if (space_freed)
{
ResizeExistingFrames(space_freed);
Layout();
}
}
void TGPack::ShowFrame(TGFrame* )
{
Error("ShowFrame", "not yet supported.");
}
void TGPack::HideFrame(TGFrame* )
{
Error("HideFrame", "not yet supported.");
}
void TGPack::Resize(UInt_t w, UInt_t h)
{
if (w == fWidth && h == fHeight) return;
Int_t delta = fVertical ? h - GetHeight() : w - GetWidth();
fWidth = w;
fHeight = h;
TGWindow::Resize(fWidth, fHeight);
ResizeExistingFrames(delta);
Layout();
}
void TGPack::MoveResize(Int_t x, Int_t y, UInt_t w, UInt_t h)
{
TGCompositeFrame::Move(x, y);
Resize(w, h);
}
void TGPack::Layout()
{
Int_t pos = 0;
TGFrameElement *el;
TIter next(fList);
while ((el = (TGFrameElement *) next()))
{
SetFramePosition(el->fFrame, pos);
pos += GetFrameLength(el->fFrame);
el->fFrame->Layout();
}
}
void TGPack::EqualizeFrames()
{
if (fList->IsEmpty())
return;
Int_t length = GetAvailableLength();
Int_t nf = NumberOfRealFrames();
Int_t lpf = (Int_t) (((Double_t) length) / nf);
Int_t extra = length - nf*lpf;
TGFrameElement *el;
TIter next(fList);
while ((el = (TGFrameElement *) next()))
{
SetFrameLength(el->fFrame, lpf + extra);
extra = 0;
if (fUseSplitters)
next();
}
}
void TGPack::HandleSplitterStart()
{
fDragOverflow = 0;
}
void TGPack::HandleSplitterResize(Int_t delta)
{
Int_t min_dec = - (GetAvailableLength() + NumberOfRealFrames());
if (delta < min_dec)
delta = min_dec;
TGSplitter *s = dynamic_cast<TGSplitter*>((TGFrame*) gTQSender);
TGFrame *f0=0, *f1=0;
FindFrames(s, f0, f1);
if (fDragOverflow < 0)
{
fDragOverflow += delta;
if (fDragOverflow > 0) {
delta = fDragOverflow;
fDragOverflow = 0;
} else {
return;
}
}
else if (fDragOverflow > 0)
{
fDragOverflow += delta;
if (fDragOverflow < 0) {
delta = fDragOverflow;
fDragOverflow = 0;
} else {
return;
}
}
if (delta < 0)
{
Int_t l = GetFrameLength(f0);
if (l - 1 < -delta)
{
fDragOverflow += delta + l - 1;
delta = -l + 1;
}
SetFrameLength(f0, l + delta);
SetFrameLength(f1, GetFrameLength(f1) - delta);
}
else
{
Int_t l = GetFrameLength(f1);
if (l - 1 < delta)
{
fDragOverflow += delta - l + 1;
delta = l - 1;
}
SetFrameLength(f0, GetFrameLength(f0) + delta);
SetFrameLength(f1, l - delta);
}
Layout();
}
void TGPack::SetVertical(Bool_t x)
{
if (x == fVertical)
return;
TList list;
while ( ! fList->IsEmpty())
{
TGFrame* f = ((TGFrameElement*) fList->First())->fFrame;
RemoveFrameInternal(f);
list.Add(f);
}
fVertical = x;
while ( ! list.IsEmpty())
{
TGFrame* f = (TGFrame*) list.First();
AddFrameInternal(f);
list.RemoveFirst();
}
Layout();
}
Last change: Thu Dec 11 16:27:48 2008
Last generated: 2008-12-11 16:27
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.