// @(#)root/gui:$Name: $:$Id: TGTab.cxx,v 1.22 2005/09/05 13:33:08 rdm Exp $
// Author: Fons Rademakers 13/01/98
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
/**************************************************************************
This source is based on Xclass95, a Win95-looking GUI toolkit.
Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
Xclass95 is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
**************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// TGTab, TGTabElement, TGTabLayout //
// //
// A tab widget contains a set of composite frames each with a little //
// tab with a name (like a set of folders with tabs). //
// //
// The TGTab is user callable. The TGTabElement and TGTabLayout are //
// service classes of the tab widget. //
// //
// Clicking on a tab will bring the associated composite frame to the //
// front and generate the following event: //
// kC_COMMAND, kCM_TAB, tab id, 0. //
// //
//////////////////////////////////////////////////////////////////////////
#include "TGTab.h"
#include "TGResourcePool.h"
#include "TList.h"
#include "TMath.h"
#include "Riostream.h"
const TGFont *TGTab::fgDefaultFont = 0;
const TGGC *TGTab::fgDefaultGC = 0;
ClassImp(TGTabElement)
ClassImp(TGTabLayout)
ClassImp(TGTab)
//______________________________________________________________________________
TGTabElement::TGTabElement(const TGWindow *p, TGString *text, UInt_t w, UInt_t h,
GContext_t norm, FontStruct_t font,
UInt_t options, ULong_t back) :
TGFrame(p, w, h, options, back)
{
// Create a tab element. Text is adopted by tab element.
fText = text;
fBorderWidth = 0;
fNormGC = norm;
fFontStruct = font;
fEditDisabled = kTRUE;
int max_ascent, max_descent;
if (fText)
fTWidth = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
fTHeight = max_ascent + max_descent;
Resize(TMath::Max(fTWidth+12, (UInt_t)45), fTHeight+6);
fEnabled = kTRUE;
gVirtualX->GrabButton(fId, kButton1, kAnyModifier, kButtonPressMask, kNone, kNone);
}
//______________________________________________________________________________
TGTabElement::~TGTabElement()
{
// Delete tab element.
if (fText) delete fText;
}
//______________________________________________________________________________
void TGTabElement::DrawBorder()
{
// Draw little tab element.
gVirtualX->DrawLine(fId, GetHilightGC()(), 0, fHeight-1, 0, 2);
gVirtualX->DrawLine(fId, GetHilightGC()(), 0, 2, 2, 0);
gVirtualX->DrawLine(fId, GetHilightGC()(), 2, 0, fWidth-3, 0);
gVirtualX->DrawLine(fId, GetShadowGC()(), fWidth-2, 1, fWidth-2, fHeight-1);
gVirtualX->DrawLine(fId, GetBlackGC()(), fWidth-2, 1, fWidth-1, 2);
gVirtualX->DrawLine(fId, GetBlackGC()(), fWidth-1, 2, fWidth-1, fHeight-2);
gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth-1, fHeight-1, fWidth-1, fHeight-1);
if (fText) {
int max_ascent, max_descent;
gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
if (fEnabled) {
fText->Draw(fId, fNormGC, 6, max_ascent+3);
} else {
fText->Draw(fId, GetHilightGC()(), 7, max_ascent + 1);
fText->Draw(fId, GetShadowGC()(), 6, max_ascent);
}
}
}
//______________________________________________________________________________
Bool_t TGTabElement::HandleButton(Event_t *event)
{
// Handle button event in the tab widget. Basically we only handle
// button events in the small tabs.
if (event->fType == kButtonPress) {
TGTab* main = (TGTab*)fParent;
if (main) {
TGFrameElement *el;
TIter next(main->GetList());
next(); // skip first container
Int_t i = 0;
Int_t c = main->GetCurrent();
while ((el = (TGFrameElement *) next())) {
if (el->fFrame->GetId() == (Window_t)event->fWindow)
c = i;
next(); i++;
}
// change tab and generate event
main->SetTab(c);
}
}
return kTRUE;
}
//______________________________________________________________________________
TGDimension TGTabElement::GetDefaultSize() const
{
// Return default size of tab element.
return TGDimension(TMath::Max(fTWidth+12, (UInt_t)45), fTHeight+6);
}
//______________________________________________________________________________
void TGTabElement::SetText(TGString *text)
{
// Set new tab text.
if (fText) delete fText;
fText = text;
int max_ascent, max_descent;
fTWidth = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
fTHeight = max_ascent + max_descent;
fClient->NeedRedraw(this);
}
//______________________________________________________________________________
TGTabLayout::TGTabLayout(TGTab *main)
{
// Create a tab layout manager.
fMain = main;
fList = fMain->GetList();
}
//______________________________________________________________________________
void TGTabLayout::Layout()
{
// Layout the tab widget.
Int_t i, xtab;
UInt_t tw;
UInt_t tabh = fMain->GetTabHeight(), bw = fMain->GetBorderWidth();
UInt_t w = fMain->GetWidth();
UInt_t h = fMain->GetHeight();
xtab = 2;
fMain->GetContainer()->MoveResize(0, tabh, w, h - tabh);
// first frame is the container, so take next...
TGFrameElement *el, *elnxt;
TIter next(fList);
i = 0;
next(); // skip first
while ((el = (TGFrameElement *) next())) {
elnxt = (TGFrameElement *) next();
tw = el->fFrame->GetDefaultWidth();
if (i == fMain->GetCurrent()) {
el->fFrame->MoveResize(xtab-2, 0, tw+3, tabh+1);
elnxt->fFrame->RaiseWindow();
el->fFrame->RaiseWindow();
} else {
el->fFrame->MoveResize(xtab, 2, tw, tabh-1);
el->fFrame->LowerWindow();
}
elnxt->fFrame->MoveResize(bw, tabh + bw, w - (bw << 1), h - tabh - (bw << 1));
elnxt->fFrame->Layout();
xtab += (Int_t)tw;
i++;
}
}
//______________________________________________________________________________
TGDimension TGTabLayout::GetDefaultSize() const
{
// Get default size of tab widget.
TGDimension dsize, dsize_te;
TGDimension size(0,0), size_te(0,0);
TGFrameElement *el, *elnxt;
TIter next(fList);
next(); // skip first container
while ((el = (TGFrameElement *)next())) {
dsize_te = el->fFrame->GetDefaultSize();
size_te.fWidth += dsize_te.fWidth;
elnxt = (TGFrameElement *) next();
dsize = elnxt->fFrame->GetDefaultSize();
if (size.fWidth < dsize.fWidth) size.fWidth = dsize.fWidth;
if (size.fHeight < dsize.fHeight) size.fHeight = dsize.fHeight;
}
// check if tab elements make a larger width than the containers
if (size.fWidth < size_te.fWidth) size.fWidth = size_te.fWidth;
size.fWidth += fMain->GetBorderWidth() << 1;
size.fHeight += fMain->GetTabHeight() + (fMain->GetBorderWidth() << 1);
return size;
}
//______________________________________________________________________________
TGTab::TGTab(const TGWindow *p, UInt_t w, UInt_t h,
GContext_t norm, FontStruct_t font,
UInt_t options, ULong_t back) :
TGCompositeFrame(p, w, h, options, back)
{
// Create tab widget.
fMsgWindow = p;
fBorderWidth = 2;
fCurrent = 0;
fRemoved = new TList;
fNormGC = norm;
fFontStruct = font;
int max_ascent, max_descent;
gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
fTabh = max_ascent + max_descent + 6;
SetLayoutManager(new TGTabLayout(this));
// we need this in order to avoid border blinking when switching tabs...
fContainer = new TGCompositeFrame(this, fWidth, fHeight - fTabh,
kVerticalFrame | kRaisedFrame | kDoubleBorder);
AddFrame(fContainer, 0);
}
//______________________________________________________________________________
TGTab::~TGTab()
{
// Delete tab widget. This deletes the tab windows and the containers.
// The tab string is deleted by the TGTabElement dtor.
Cleanup();
fRemoved->Delete();
delete fRemoved;
}
//______________________________________________________________________________
TGCompositeFrame *TGTab::AddTab(TGString *text)
{
// Add a tab to the tab widget. Returns the new container, which
// is owned by the tab widget. The text is adopted by the tab widget.
TGCompositeFrame *cf;
AddFrame(new TGTabElement(this, text, 50, 20, fNormGC, fFontStruct), 0);
cf = new TGCompositeFrame(this, fWidth, fHeight-21);
AddFrame(cf, 0);
return cf;
}
//______________________________________________________________________________
TGCompositeFrame *TGTab::AddTab(const char *text)
{
// Add a tab to the tab widget. Returns the new container. The container
// is owned by the tab widget.
return AddTab(new TGString(text));
}
//______________________________________________________________________________
void TGTab::RemoveTab(Int_t tabIndex)
{
// Remove container and tab of tab with index tabIndex.
// Does NOT remove the container contents!
if (tabIndex < 0) return;
TGFrameElement *elTab, *elCont;
Int_t count = 0;
TIter next(fList) ;
next() ; // skip first container
while ((elTab = (TGFrameElement *) next())) {
elCont = (TGFrameElement *) next();
if (count == tabIndex) {
elCont->fFrame->UnmapWindow(); // will be destroyed later
TGFrame *frame = elTab->fFrame;
RemoveFrame(elTab->fFrame);
frame->DestroyWindow();
delete frame;
fRemoved->Add(elCont->fFrame); // delete only in dtor
RemoveFrame(elCont->fFrame);
if (tabIndex == fCurrent) {
// select another tab only if the current is the one we delete
SetTab(0);
} else
fCurrent--;
break;
}
count++;
}
}
//______________________________________________________________________________
void TGTab::SetEnabled(Int_t tabIndex, Bool_t on)
{
// Enabled or disable tab.
TGTabElement *te = GetTabTab(tabIndex);
if (te) {
te->SetEnabled(on);
fClient->NeedRedraw(te);
}
}
//______________________________________________________________________________
Bool_t TGTab::IsEnabled(Int_t tabIndex) const
{
// Returns true if tab is enabled.
TGTabElement *te = GetTabTab(tabIndex);
return te ? te->IsEnabled() : kFALSE;
}
//______________________________________________________________________________
void TGTab::ChangeTab(Int_t tabIndex)
{
// Make tabIdx the current tab. Utility method called by SetTab and
// HandleButton().
TGTabElement *te = GetTabTab(tabIndex);
if (!te || !te->IsEnabled()) return;
if (tabIndex != fCurrent) {
TGFrameElement *el, *elnxt;
UInt_t tw;
Int_t xtab = 2;
Int_t count = 0;
TIter next(fList);
next(); // skip first container
fCurrent = tabIndex;
while ((el = (TGFrameElement *) next())) {
elnxt = (TGFrameElement *) next();
tw = el->fFrame->GetDefaultWidth();
if (count == fCurrent) {
el->fFrame->MoveResize(xtab-2, 0, tw+3, fTabh+1);
elnxt->fFrame->RaiseWindow();
el->fFrame->RaiseWindow();
} else {
el->fFrame->MoveResize(xtab, 2, tw, fTabh-1);
el->fFrame->LowerWindow();
}
xtab += tw;
count++;
}
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_TAB), fCurrent, 0);
fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_TAB), fCurrent, 0);
Selected(fCurrent);
}
}
//______________________________________________________________________________
Bool_t TGTab::SetTab(Int_t tabIndex)
{
// Brings the composite frame with the index tabIndex to the
// front and generate the following event if the front tab has changed:
// kC_COMMAND, kCM_TAB, tab id, 0.
// Returns kFALSE if tabIndex is a not valid index
// check if tabIndex is a valid index
if (tabIndex < 0)
return kFALSE;
// count the tabs
TIter next(fList);
Int_t count = 0;
while (next())
count++;
count = count / 2 - 1;
if (tabIndex > count)
return kFALSE;
// change tab and generate event
ChangeTab(tabIndex);
return kTRUE;
}
//______________________________________________________________________________
Bool_t TGTab::SetTab(const char *name)
{
// Brings the composite frame with the name to the
// front and generate the following event if the front tab has changed:
// kC_COMMAND, kCM_TAB, tab id, 0.
// Returns kFALSE if tab with name does not exist.
TGFrameElement *el;
Int_t count = 0;
TGTabElement *tab = 0;
TIter next(fList);
while (next()) {
el = (TGFrameElement *) next();
tab = (TGTabElement *)el->fFrame;
if (name == *(tab->GetText())) {
// change tab and generate event
ChangeTab(count);
return kTRUE;
}
count++;
}
return kFALSE;
}
//______________________________________________________________________________
TGCompositeFrame *TGTab::GetTabContainer(Int_t tabIndex) const
{
// Return container of tab with index tabIndex.
// Returns 0 in case tabIndex is out of range.
if (tabIndex < 0) return 0;
TGFrameElement *el;
Int_t count = 0;
TIter next(fList);
next(); // skip first container
while (next()) {
el = (TGFrameElement *) next();
if (count == tabIndex)
return (TGCompositeFrame *) el->fFrame;
count++;
}
return 0;
}
//______________________________________________________________________________
TGCompositeFrame *TGTab::GetTabContainer(const char *name) const
{
// Return the tab container of tab with string name.
// Returns 0 in case name is not found.
TGFrameElement *el;
TGTabElement *tab = 0;
TGCompositeFrame *comp = 0;
TIter next(fList);
while ((el = (TGFrameElement *) next())) {
comp = (TGCompositeFrame *) el->fFrame;
el = (TGFrameElement *) next();
tab = (TGTabElement *)el->fFrame;
if (name == *(tab->GetText())) {
return comp;
}
}
return 0;
}
//______________________________________________________________________________
TGTabElement *TGTab::GetTabTab(Int_t tabIndex) const
{
// Return the tab element of tab with index tabIndex.
// Returns 0 in case tabIndex is out of range.
if (tabIndex < 0) return 0;
TGFrameElement *el;
Int_t count = 0;
TIter next(fList);
next(); // skip first container
while ((el = (TGFrameElement *) next())) {
next();
if (count == tabIndex)
return (TGTabElement *) el->fFrame;
count++;
}
return 0;
}
//______________________________________________________________________________
TGTabElement *TGTab::GetTabTab(const char *name) const
{
// Return the tab element of tab with string name.
// Returns 0 in case name is not found.
TGFrameElement *el;
TGTabElement *tab = 0;
TIter next(fList);
next();
while ((el = (TGFrameElement *) next())) {
tab = (TGTabElement *)el->fFrame;
if (name == *(tab->GetText())) {
return tab;
}
next();
}
return tab;
}
//______________________________________________________________________________
Int_t TGTab::GetNumberOfTabs() const
{
// Return number of tabs.
Int_t count = 0;
TIter next(fList);
next(); // skip first container
while (next()) {
next();
count++;
}
return count;
}
//______________________________________________________________________________
FontStruct_t TGTab::GetDefaultFontStruct()
{
if (!fgDefaultFont)
fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
return fgDefaultFont->GetFontStruct();
}
//______________________________________________________________________________
const TGGC &TGTab::GetDefaultGC()
{
if (!fgDefaultGC)
fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
return *fgDefaultGC;
}
//______________________________________________________________________________
void TGTab::SavePrimitive(ofstream &out, Option_t *option)
{
// Save a tab widget as a C++ statement(s) on output stream out.
char quote = '"';
// font + GC
option = GetName()+5; // unique digit id of the name
char parGC[50], parFont[50];
sprintf(parFont,"%s::GetDefaultFontStruct()",IsA()->GetName());
sprintf(parGC,"%s::GetDefaultGC()()",IsA()->GetName());
if ((GetDefaultFontStruct() != fFontStruct) || (GetDefaultGC()() != fNormGC)) {
TGFont *ufont = gClient->GetResourcePool()->GetFontPool()->FindFont(fFontStruct);
if (ufont) {
ufont->SavePrimitive(out, option);
sprintf(parFont,"ufont->GetFontStruct()");
}
TGGC *userGC = gClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
if (userGC) {
userGC->SavePrimitive(out, option);
sprintf(parGC,"uGC->GetGC()");
}
}
if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
out << endl << " // tab widget" << endl;
out << " TGTab *";
out << GetName() << " = new TGTab(" << fParent->GetName()
<< "," << GetWidth() << "," << GetHeight();
if (fBackground == GetDefaultFrameBackground()) {
if (GetOptions() == kChildFrame) {
if (fFontStruct == GetDefaultFontStruct()) {
if (fNormGC == GetDefaultGC()()) {
out <<");" << endl;
} else {
out << "," << parGC <<");" << endl;
}
} else {
out << "," << parGC << "," << parFont <<");" << endl;
}
} else {
out << "," << parGC << "," << parFont << "," << GetOptionString() <<");" << endl;
}
} else {
out << "," << parGC << "," << parFont << "," << GetOptionString() << ",ucolor);" << endl;
}
TGCompositeFrame *cf;
for (Int_t i=0; i<GetNumberOfTabs(); i++) {
cf = GetTabContainer(i);
out << endl << " // container of " << quote
<< GetTabTab(i)->GetString() << quote << endl;
out << " TGCompositeFrame *" << cf->GetName() << ";" << endl;
out << " " << cf->GetName() << " = " << GetName()
<< "->AddTab(" << quote << GetTabTab(i)->GetString()
<< quote << ");" << endl;
if (((TGCompositeFrame *)cf)->GetLayoutManager() != 0) {
out << " " << cf->GetName() <<"->SetLayoutManager(";
((TGCompositeFrame *)cf)->GetLayoutManager()->SavePrimitive(out, option);
out << ");" << endl;
}
TGFrameElement *el;
TIter next(cf->GetList());
while ((el = (TGFrameElement *) next())) {
el->fFrame->SavePrimitive(out, option);
out << " " << cf->GetName() << "->AddFrame(" << el->fFrame->GetName();
el->fLayout->SavePrimitive(out, option);
out << ");" << endl;
}
//cf->SavePrimitive(out, option);
if (GetTabTab(i)->GetBackground() != GetTabTab(i)->GetDefaultFrameBackground()) {
GetTabTab(i)->SaveUserColor(out, option);
out << " TGTabElement *tab" << i << " = "
<< GetName() << "->GetTabTab(" << i << ");" << endl;
out << " tab" << i << "->ChangeBackground(ucolor);" << endl;
}
}
out << endl << " " << GetName() << "->SetTab(" << GetCurrent() << ");" << endl;
out << endl << " " << GetName() << "->Resize(" << GetName()
<< "->GetDefaultSize());" << endl;
}
// __________________________________________________________________________
void TGTabLayout::SavePrimitive(ofstream &out, Option_t *)
{
// Save tab layout manager as a C++ statement(s) on out stream
out << "new TGTabLayout(" << fMain->GetName() << ")";
}
ROOT page - Class index - Class Hierarchy - Top of the page
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.