#include "TColor.h"
#include "TGFrame.h"
#include "TMessage.h"
#include "TGWidget.h"
#include "TGButton.h"
#include "TGDockableFrame.h"
#include "TGWindow.h"
#include "TList.h"
#include "TVirtualX.h"
#include "Riostream.h"
ClassImp(TGDockButton)
ClassImp(TGDockHideButton)
ClassImp(TGUndockedFrame)
ClassImp(TGDockableFrame)
TGDockButton::TGDockButton(const TGCompositeFrame *p, int id) :
TGButton (p, id, GetDefaultGC()(), kChildFrame)
{
fWidgetFlags = kWidgetIsEnabled;
fMouseOn = kFALSE;
Resize(10, GetDefaultHeight());
fNormBg = fBackground;
Float_t r, g, b, h, l, s;
TColor::Pixel2RGB(fNormBg, r, g, b);
TColor::RGB2HLS(r, g, b, h, l, s);
l = l + (1. - l) * 45. / 100.;
TColor::HLS2RGB(h, l, s, r, g, b);
fHiBg = TColor::RGB2Pixel(r, g, b);
AddInput(kEnterWindowMask | kLeaveWindowMask);
SetWindowName();
}
TGDockButton::~TGDockButton()
{
}
Bool_t TGDockButton::HandleCrossing(Event_t *event)
{
TGButton::HandleCrossing(event);
if (event->fType == kLeaveNotify) {
fMouseOn = kFALSE;
} else if (event->fType == kEnterNotify) {
fMouseOn = kTRUE;
}
if (IsEnabled())
fClient->NeedRedraw(this);
return kTRUE;
}
void TGDockButton::DrawBorder()
{
int options = GetOptions();
if (fState == kButtonDown || fState == kButtonEngaged)
;
else if (fMouseOn == kTRUE && IsEnabled()) {
SetBackgroundColor(fHiBg);
ChangeOptions(kChildFrame);
} else {
SetBackgroundColor(fNormBg);
ChangeOptions(kChildFrame);
}
gVirtualX->ClearWindow(fId);
TGFrame::DrawBorder();
ChangeOptions(options);
}
void TGDockButton::DoRedraw()
{
int x = 1, y = 0;
DrawBorder();
if (fState == kButtonDown || fState == kButtonEngaged) { ++x; ++y; }
for (int i = 0; i < 5; i +=4) {
gVirtualX->DrawLine(fId, GetHilightGC()(), i+x, y+1, i+x, fHeight-y-3);
gVirtualX->DrawLine(fId, GetShadowGC()(), i+x+1, y+1, i+x+1, fHeight-y-3);
}
}
TGDockHideButton::TGDockHideButton(const TGCompositeFrame *p) :
TGDockButton (p, 2)
{
Resize(10, 8);
fAspectRatio = 0;
SetWindowName();
}
void TGDockHideButton::DoRedraw()
{
int x = 1, y = 0;
DrawBorder();
if (fState == kButtonDown || fState == kButtonEngaged) { ++x; ++y; }
if (fAspectRatio) {
gVirtualX->DrawLine(fId, GetBlackGC()(), x+1, y+1, x+5, y+3);
gVirtualX->DrawLine(fId, GetBlackGC()(), x+1, y+5, x+5, y+3);
gVirtualX->DrawLine(fId, GetHilightGC()(), x, y+1, x, y+5);
} else {
gVirtualX->DrawLine(fId, GetHilightGC()(), x+5, y+1, x+1, y+3);
gVirtualX->DrawLine(fId, GetHilightGC()(), x+5, y+5, x+1, y+3);
gVirtualX->DrawLine(fId, GetBlackGC()(), x+6, y+1, x+6, y+5);
}
}
TGUndockedFrame::TGUndockedFrame(const TGWindow *p, TGDockableFrame *dockable) :
TGTransientFrame(p, dockable ? dockable->GetMainFrame() : 0, 10, 10)
{
SetWindowName("");
fDockable = dockable;
SetMWMHints(kMWMDecorAll | kMWMDecorResizeH | kMWMDecorMaximize |
kMWMDecorMinimize | kMWMDecorMenu,
kMWMFuncAll | kMWMFuncResize | kMWMFuncMaximize |
kMWMFuncMinimize,
kMWMInputModeless);
SetWindowName();
}
TGUndockedFrame::~TGUndockedFrame()
{
if (fDockable && !fDockable->fDeleted) {
fDockable->DockContainer(kFALSE);
}
}
void TGUndockedFrame::FixSize()
{
ChangeOptions(GetOptions() | kFixedSize);
SetWMSize(fWidth, fHeight);
SetWMSizeHints(fWidth, fHeight, fWidth, fHeight, 0, 0);
}
void TGUndockedFrame::CloseWindow()
{
DeleteWindow();
}
TGDockableFrame::TGDockableFrame(const TGWindow *p, int id, UInt_t )
: TGCompositeFrame(p, 10, 10, kHorizontalFrame), TGWidget(id)
{
fMsgWindow = fParent;
fCl = new TGLayoutHints(kLHintsExpandY | kLHintsExpandX);
TGLayoutHints *l1 = new TGLayoutHints(kLHintsTop | kLHintsLeft);
TGLayoutHints *l2 = new TGLayoutHints(kLHintsExpandY | kLHintsLeft);
fLb = new TGLayoutHints(kLHintsExpandY | kLHintsLeft, 0, 2, 0, 0);
fLc = new TGLayoutHints(kLHintsExpandY | kLHintsExpandX);
fButtons = new TGCompositeFrame(this, 10, 10, kVerticalFrame);
fButtons->SetCleanup();
fHideButton = new TGDockHideButton(fButtons);
fButtons->AddFrame(fHideButton, l1);
fDockButton = new TGDockButton(fButtons);
fButtons->AddFrame(fDockButton, l2);
TGCompositeFrame::AddFrame(fButtons, fLb);
fContainer = new TGCompositeFrame(this, 10, 10);
TGCompositeFrame::AddFrame(fContainer, fLc);
fEnableHide = kTRUE;
fEnableUndock = kTRUE;
fHidden = kFALSE;
fFrame = 0;
fDeleted = kFALSE;
fFixedSize = kTRUE;
fDockButton->Associate(this);
fHideButton->Associate(this);
MapSubwindows();
Resize(GetDefaultSize());
TGFrame::SetWindowName();
}
TGDockableFrame::~TGDockableFrame()
{
if (fFrame) {
fDeleted = kTRUE;
delete fFrame;
}
}
void TGDockableFrame::AddFrame(TGFrame *f, TGLayoutHints *hints)
{
f->ReparentWindow(fContainer);
fContainer->AddFrame(f, fHints = hints);
fContainer->Layout();
}
void TGDockableFrame::UndockContainer()
{
int ax, ay;
Window_t wdummy;
if (fFrame || !fEnableUndock) return;
fFrame = new TGUndockedFrame(fClient->GetDefaultRoot(), this);
fFrame->SetEditDisabled();
TGDimension size = fContainer->GetSize();
RemoveFrame(fContainer);
fContainer->ReparentWindow(fFrame);
fFrame->AddFrame(fContainer, fCl);
gVirtualX->TranslateCoordinates(GetId(), fClient->GetDefaultRoot()->GetId(), fX,
fY + fFrame->GetHeight(), ax, ay, wdummy);
if (fDockName) fFrame->SetWindowName(fDockName);
fFrame->MapSubwindows();
fFrame->Resize(size);
if (fFixedSize)
fFrame->FixSize();
fFrame->MapWindow();
fFrame->Move(ax, ay);
if (((TGFrame *)fParent)->IsComposite())
((TGCompositeFrame *)fParent)->HideFrame(this);
Layout();
SendMessage(fMsgWindow, MK_MSG(kC_DOCK, kDOCK_UNDOCK), fWidgetId, 0);
Undocked();
}
void TGDockableFrame::DockContainer(Int_t del)
{
if (!fFrame) return;
if (del) {
delete fFrame;
return;
}
fFrame->RemoveFrame(fContainer);
fContainer->ReparentWindow(this);
TGCompositeFrame::AddFrame(fContainer, fCl);
fDockButton->Resize(fDockButton->GetDefaultWidth(), 1);
Layout();
if (((TGFrame *)fParent)->IsComposite())
((TGCompositeFrame *)fParent)->ShowFrame(this);
fFrame = 0;
SendMessage(fMsgWindow, MK_MSG(kC_DOCK, kDOCK_DOCK), fWidgetId, 0);
Docked();
}
void TGDockableFrame::ShowContainer()
{
if (!fHidden) return;
ShowFrame(fContainer);
if (fEnableUndock) fButtons->ShowFrame(fDockButton);
fHideButton->SetAspectRatio(0);
if (((TGFrame *)fParent)->IsComposite())
((TGCompositeFrame *)fParent)->Layout();
fHidden = kFALSE;
SendMessage(fMsgWindow, MK_MSG(kC_DOCK, kDOCK_SHOW), fWidgetId, 0);
}
void TGDockableFrame::HideContainer()
{
if (fHidden || !fEnableHide) return;
HideFrame(fContainer);
fButtons->HideFrame(fDockButton);
fHideButton->SetAspectRatio(1);
if (((TGFrame *)fParent)->IsComposite())
((TGCompositeFrame *)fParent)->Layout();
fHidden = kTRUE;
SendMessage(fMsgWindow, MK_MSG(kC_DOCK, kDOCK_HIDE),fWidgetId, 0);
}
Bool_t TGDockableFrame::ProcessMessage(Long_t msg, Long_t parm1, Long_t)
{
switch (GET_MSG(msg)) {
case kC_COMMAND:
switch (GET_SUBMSG(msg)) {
case kCM_BUTTON:
switch (parm1) {
case 1:
if (!fHidden) UndockContainer();
break;
case 2:
if (!fHidden)
HideContainer();
else
ShowContainer();
break;
}
break;
}
break;
}
return kTRUE;
}
void TGDockableFrame::EnableUndock(Bool_t onoff)
{
fEnableUndock = onoff;
if (onoff)
fButtons->ShowFrame(fDockButton);
else
fButtons->HideFrame(fDockButton);
Layout();
}
void TGDockableFrame::EnableHide(Bool_t onoff)
{
fEnableHide = onoff;
if (onoff)
fButtons->ShowFrame(fHideButton);
else
fButtons->HideFrame(fHideButton);
Layout();
}
void TGDockableFrame::SetWindowName(const char *name)
{
fDockName = "";
if (name) {
fDockName = name;
if (fFrame) fFrame->SetWindowName(fDockName);
}
}
void TGDockableFrame::SavePrimitive(ostream &out, Option_t *option )
{
char quote = '"';
out << endl << " // dockable frame" << endl;
out << " TGDockableFrame *";
out << GetName()<<" = new TGDockableFrame(" << fParent->GetName();
if (GetOptions() == kHorizontalFrame) {
if (fWidgetId == -1) {
out << ");" << endl;
} else {
out << "," << fWidgetId << ");" << endl;
}
} else {
out << "," << fWidgetId << "," << GetOptionString() << ");" << endl;
}
if (GetContainer()->GetList()->First()) {
out << " TGCompositeFrame *" << GetContainer()->GetName() << " = "
<< GetName() << "->GetContainer();" << endl;
TGFrameElement *el;
TIter next(GetContainer()->GetList());
while ((el = (TGFrameElement *) next())) {
el->fFrame->SavePrimitive(out, option);
out << " " << GetName() << "->AddFrame(" << el->fFrame->GetName();
el->fLayout->SavePrimitive(out, option);
out << ");"<< endl;
}
}
out << endl << " // next lines belong to the dockable frame widget" << endl;
if (EnableUndock())
out << " " << GetName() << "->EnableUndock(kTRUE);" << endl;
else
out << " " << GetName() << "->EnableUndock(kFALSE);" << endl;
if (EnableHide())
out << " " << GetName() << "->EnableHide(kTRUE);" << endl;
else
out << " " << GetName() << "->EnableHide(kFALSE);" << endl;
if (fDockName != "")
out << " " << GetName() << "->SetWindowName(" << quote << fDockName
<< quote << ");" << endl;
if (IsUndocked())
out << " " << GetName() << "->UndockContainer();" << endl;
else
out << " " << GetName() << "->DockContainer();" << endl;
if (IsHidden())
out << " " << GetName() << "->HideContainer();" << endl;
out << endl;
}