#include "TGButton.h"
#include "TGWidget.h"
#include "TGPicture.h"
#include "TGToolTip.h"
#include "TGButtonGroup.h"
#include "TGResourcePool.h"
#include "Riostream.h"
#include "TSystem.h"
#include "TImage.h"
#include "TEnv.h"
#include "TClass.h"
#include "TGMenu.h"
#include "KeySymbols.h"
const TGGC *TGButton::fgHibckgndGC = 0;
const TGGC *TGButton::fgDefaultGC = 0;
const TGFont *TGTextButton::fgDefaultFont = 0;
const TGFont *TGCheckButton::fgDefaultFont = 0;
const TGGC *TGCheckButton::fgDefaultGC = 0;
const TGFont *TGRadioButton::fgDefaultFont = 0;
const TGGC *TGRadioButton::fgDefaultGC = 0;
Window_t TGButton::fgReleaseBtn = 0;
ClassImp(TGButton)
ClassImp(TGTextButton)
ClassImp(TGPictureButton)
ClassImp(TGCheckButton)
ClassImp(TGRadioButton)
ClassImp(TGSplitButton)
TGButton::TGButton(const TGWindow *p, Int_t id, GContext_t norm, UInt_t options)
: TGFrame(p, 1, 1, options)
{
fWidgetId = id;
fWidgetFlags = kWidgetWantFocus;
fMsgWindow = p;
fUserData = 0;
fTip = 0;
fGroup = 0;
fStyle = 0;
fNormGC = norm;
fState = kButtonUp;
fStayDown = kFALSE;
fWidgetFlags = kWidgetIsEnabled;
if (p && p->IsA()->InheritsFrom(TGButtonGroup::Class())) {
TGButtonGroup *bg = (TGButtonGroup*) p;
bg->Insert(this, id);
}
fBgndColor = fBackground;
fHighColor = gClient->GetResourcePool()->GetHighLightColor();
gVirtualX->GrabButton(fId, kButton1, kAnyModifier,
kButtonPressMask | kButtonReleaseMask,
kNone, kNone);
AddInput(kEnterWindowMask | kLeaveWindowMask);
SetWindowName();
}
TGButton::~TGButton()
{
if (fGroup) {
fGroup->Remove(this);
fGroup = 0;
}
if (fTip) delete fTip;
}
void TGButton::SetState(EButtonState state, Bool_t emit)
{
Bool_t was = !IsDown();
if (state == kButtonDisabled)
fWidgetFlags &= ~kWidgetIsEnabled;
else
fWidgetFlags |= kWidgetIsEnabled;
if (state != fState) {
switch (state) {
case kButtonEngaged:
case kButtonDown:
fOptions &= ~kRaisedFrame;
fOptions |= kSunkenFrame;
break;
case kButtonDisabled:
case kButtonUp:
if (fStyle > 0) {
fOptions &= ~kRaisedFrame;
fOptions &= ~kSunkenFrame;
}
else {
fOptions &= ~kSunkenFrame;
fOptions |= kRaisedFrame;
}
break;
}
fState = state;
DoRedraw();
if (emit || fGroup) EmitSignals(was);
}
}
void TGButton::SetStyle(UInt_t newstyle)
{
fStyle = newstyle;
if (fStyle > 0) {
ChangeOptions(GetOptions() & ~kRaisedFrame);
}
else {
ChangeOptions(GetOptions() | kRaisedFrame);
}
}
void TGButton::SetStyle(const char *style)
{
if (style && strstr(style, "modern")) {
fStyle = 1;
ChangeOptions(GetOptions() & ~kRaisedFrame);
}
else {
fStyle = 0;
ChangeOptions(GetOptions() | kRaisedFrame);
}
}
Bool_t TGButton::IsDown() const
{
if (fStyle > 0)
return (fOptions & kSunkenFrame);
return !(fOptions & kRaisedFrame);
}
void TGButton::SetDown(Bool_t on, Bool_t emit)
{
if (GetState() == kButtonDisabled) return;
SetState(on ? kButtonDown : kButtonUp, emit);
}
void TGButton::SetGroup(TGButtonGroup *group)
{
fGroup = group;
}
Bool_t TGButton::HandleButton(Event_t *event)
{
Bool_t click = kFALSE;
if (fTip) fTip->Hide();
if (fState == kButtonDisabled) return kTRUE;
Bool_t in = (event->fX >= 0) && (event->fY >= 0) &&
(event->fX <= (Int_t)fWidth) && (event->fY <= (Int_t)fHeight);
if (event->fType == kButtonPress) {
fgReleaseBtn = 0;
if (fState == kButtonEngaged) {
return kTRUE;
}
if (in) SetState(kButtonDown, kTRUE);
} else {
if (fState == kButtonEngaged) {
if (in) SetState(kButtonUp, kTRUE);
click = kTRUE;
} else {
click = (fState == kButtonDown) && in;
if (click && fStayDown) {
if (in) {
SetState(kButtonEngaged, kTRUE);
fgReleaseBtn = 0;
}
} else {
if (in) {
SetState(kButtonUp, kTRUE);
fgReleaseBtn = fId;
}
}
}
}
if (click) {
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
}
if ((fStyle > 0) && (event->fType == kButtonRelease)) {
fBgndColor = fBackground;
}
DoRedraw();
return kTRUE;
}
void TGButton::EmitSignals(Bool_t was)
{
Bool_t now = !IsDown();
if (was && !now) {
Pressed();
if (fStayDown) Clicked();
}
if (!was && now) {
Released();
Clicked();
}
if ((was != now) && IsToggleButton()) Toggled(!now);
}
Bool_t TGButton::HandleCrossing(Event_t *event)
{
if (fTip) {
if (event->fType == kEnterNotify)
fTip->Reset();
else
fTip->Hide();
}
if (fStyle > 0) {
if ((event->fType == kEnterNotify) && (fState != kButtonDisabled)) {
fBgndColor = fHighColor;
} else {
fBgndColor = fBackground;
}
if (event->fType == kLeaveNotify) {
fBgndColor = fBackground;
}
DoRedraw();
}
if ((fgDbw != event->fWindow) || (fgReleaseBtn == event->fWindow)) return kTRUE;
if (!(event->fState & (kButton1Mask | kButton2Mask | kButton3Mask)))
return kTRUE;
if (fState == kButtonEngaged || fState == kButtonDisabled) return kTRUE;
if (event->fType == kLeaveNotify) {
fgReleaseBtn = fId;
SetState(kButtonUp, kFALSE);
}
DoRedraw();
return kTRUE;
}
void TGButton::SetToolTipText(const char *text, Long_t delayms)
{
if (fTip) {
delete fTip;
fTip = 0;
}
if (text && strlen(text))
fTip = new TGToolTip(fClient->GetDefaultRoot(), this, text, delayms);
}
void TGButton::SetEnabled(Bool_t e)
{
SetState(e ? kButtonUp : kButtonDisabled);
if (e) fWidgetFlags |= kWidgetIsEnabled;
else fWidgetFlags &= ~kWidgetIsEnabled;
}
const TGGC &TGButton::GetDefaultGC()
{
if (!fgDefaultGC)
fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
return *fgDefaultGC;
}
const TGGC &TGButton::GetHibckgndGC()
{
if (!fgHibckgndGC) {
GCValues_t gval;
gval.fMask = kGCForeground | kGCBackground | kGCTile |
kGCFillStyle | kGCGraphicsExposures;
gval.fForeground = gClient->GetResourcePool()->GetFrameHiliteColor();
gval.fBackground = gClient->GetResourcePool()->GetFrameBgndColor();
gval.fFillStyle = kFillTiled;
gval.fTile = gClient->GetResourcePool()->GetCheckeredPixmap();
gval.fGraphicsExposures = kFALSE;
fgHibckgndGC = gClient->GetGC(&gval, kTRUE);
}
return *fgHibckgndGC;
}
TGTextButton::TGTextButton(const TGWindow *p, TGHotString *s, Int_t id,
GContext_t norm, FontStruct_t font,
UInt_t options) : TGButton(p, id, norm, options)
{
fLabel = s;
fFontStruct = font;
Init();
}
TGTextButton::TGTextButton(const TGWindow *p, const char *s, Int_t id,
GContext_t norm, FontStruct_t font,
UInt_t options) : TGButton(p, id, norm, options)
{
fLabel = new TGHotString(!p && !s ? GetName() : s);
fFontStruct = font;
Init();
}
TGTextButton::TGTextButton(const TGWindow *p, const char *s, const char *cmd,
Int_t id, GContext_t norm, FontStruct_t font,
UInt_t options) : TGButton(p, id, norm, options)
{
fLabel = new TGHotString(s);
fFontStruct = font;
fCommand = cmd;
Init();
}
void TGTextButton::Init()
{
int hotchar;
fTMode = kTextCenterX | kTextCenterY;
fHKeycode = 0;
fHasOwnFont = kFALSE;
fPrevStateOn =
fStateOn = kFALSE;
fWrapLength = -1;
fMLeft = fMRight = fMTop = fMBottom = 0;
TGFont *font = fClient->GetFontPool()->FindFont(fFontStruct);
if (!font) {
font = fClient->GetFontPool()->GetFont(fgDefaultFont);
if (font) fFontStruct = font->GetFontStruct();
}
if (font) {
fTLayout = font->ComputeTextLayout(fLabel->GetString(), fLabel->GetLength(),
fWrapLength, kTextLeft, 0,
&fTWidth, &fTHeight);
}
Resize();
fWidth = fTWidth;
fHeight = fTHeight;
if ((hotchar = fLabel->GetHotChar()) != 0) {
if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0) {
const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
main->BindKey(this, fHKeycode, kKeyMod1Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
}
}
SetWindowAttributes_t wattr;
wattr.fMask = kWAWinGravity | kWABitGravity;
wattr.fBitGravity = 5;
wattr.fWinGravity = 1;
gVirtualX->ChangeWindowAttributes(fId, &wattr);
SetWindowName();
}
TGTextButton::~TGTextButton()
{
if (fHKeycode && (fParent->MustCleanup() != kDeepCleanup)) {
const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
main->RemoveBind(this, fHKeycode, kKeyMod1Mask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
}
if (fLabel) delete fLabel;
if (fHasOwnFont) {
TGGCPool *pool = fClient->GetGCPool();
TGGC *gc = pool->FindGC(fNormGC);
pool->FreeGC(gc);
}
delete fTLayout;
}
void TGTextButton::Layout()
{
delete fTLayout;
TGFont *font = fClient->GetFontPool()->FindFont(fFontStruct);
if (!font) {
font = fClient->GetFontPool()->GetFont(fgDefaultFont);
if (font) fFontStruct = font->GetFontStruct();
}
if (font) {
fTLayout = font->ComputeTextLayout(fLabel->GetString(), fLabel->GetLength(),
fWrapLength, kTextLeft, 0,
&fTWidth, &fTHeight);
}
fClient->NeedRedraw(this);
}
void TGTextButton::SetText(TGHotString *new_label)
{
int hotchar;
const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
if (fLabel) {
if (fHKeycode) {
main->RemoveBind(this, fHKeycode, kKeyMod1Mask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
}
delete fLabel;
}
fLabel = new_label;
if ((hotchar = fLabel->GetHotChar()) != 0) {
if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0)
main->BindKey(this, fHKeycode, kKeyMod1Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
}
Layout();
}
void TGTextButton::SetText(const TString &new_label)
{
SetText(new TGHotString(new_label));
}
void TGTextButton::SetTextJustify(Int_t mode)
{
fTMode = mode;
SetWindowAttributes_t wattr;
wattr.fMask = kWAWinGravity | kWABitGravity;
wattr.fWinGravity = 1;
switch (mode) {
case kTextTop | kTextLeft:
wattr.fBitGravity = 1;
break;
case kTextTop | kTextCenterX:
case kTextTop:
wattr.fBitGravity = 2;
break;
case kTextTop | kTextRight:
wattr.fBitGravity = 3;
break;
case kTextLeft | kTextCenterY:
case kTextLeft:
wattr.fBitGravity = 4;
break;
case kTextCenterY | kTextCenterX:
wattr.fBitGravity = 5;
break;
case kTextRight | kTextCenterY:
case kTextRight:
wattr.fBitGravity = 6;
break;
case kTextBottom | kTextLeft:
wattr.fBitGravity = 7;
break;
case kTextBottom | kTextCenterX:
case kTextBottom:
wattr.fBitGravity = 8;
break;
case kTextBottom | kTextRight:
wattr.fBitGravity = 9;
break;
default:
wattr.fBitGravity = 5;
break;
}
gVirtualX->ChangeWindowAttributes(fId, &wattr);
Layout();
}
void TGTextButton::DoRedraw()
{
int x, y;
UInt_t w = GetWidth() - 1;
UInt_t h = GetHeight()- 1;
if (fStyle > 0)
gVirtualX->SetWindowBackground(fId, fBgndColor);
else
gVirtualX->SetWindowBackground(fId, fBackground);
TGFrame::DoRedraw();
if (fTMode & kTextLeft) {
x = fMLeft + 4;
} else if (fTMode & kTextRight) {
x = fWidth - fTWidth - fMRight - 4;
} else {
x = (fWidth - fTWidth + fMLeft - fMRight) >> 1;
}
if (fTMode & kTextTop) {
y = fMTop + 3;
} else if (fTMode & kTextBottom) {
y = fHeight - fTHeight - fMBottom - 3;
} else {
y = (fHeight - fTHeight + fMTop - fMBottom) >> 1;
}
if (fState == kButtonDown || fState == kButtonEngaged) {
++x; ++y;
w--; h--;
}
if (fStyle == 0) {
if (fState == kButtonEngaged) {
gVirtualX->FillRectangle(fId, GetHibckgndGC()(), 2, 2, fWidth-4, fHeight-4);
gVirtualX->DrawLine(fId, GetHilightGC()(), 2, 2, fWidth-3, 2);
}
}
Int_t hotpos = fLabel->GetHotPos();
if (fStyle > 0) {
gVirtualX->DrawRectangle(fId, TGFrame::GetShadowGC()(), 0, 0, w, h);
}
if (fState == kButtonDisabled) {
TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
TGGC *gc = pool->FindGC(fNormGC);
if (gc) {
Pixel_t fore = gc->GetForeground();
Pixel_t hi = GetHilightGC().GetForeground();
Pixel_t sh = GetShadowGC().GetForeground();
gc->SetForeground(hi);
fTLayout->DrawText(fId, gc->GetGC(), x + 1, y + 1, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x + 1, y + 1, hotpos - 1);
gc->SetForeground(sh);
fTLayout->DrawText(fId, gc->GetGC(), x, y, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x, y, hotpos - 1);
gc->SetForeground(fore);
}
} else {
fTLayout->DrawText(fId, fNormGC, x, y, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, fNormGC, x, y, hotpos - 1);
}
}
Bool_t TGTextButton::HandleKey(Event_t *event)
{
Bool_t click = kFALSE;
Bool_t was = !IsDown();
if (event->fType == kGKeyPress) {
gVirtualX->SetKeyAutoRepeat(kFALSE);
} else {
gVirtualX->SetKeyAutoRepeat(kTRUE);
}
if (fTip && event->fType == kGKeyPress) fTip->Hide();
if (fState == kButtonDisabled) return kTRUE;
if ((event->fType == kGKeyPress) && (event->fState & kKeyMod1Mask)) {
if (fState == kButtonEngaged) return kTRUE;
SetState(kButtonDown);
} else if ((event->fType == kKeyRelease) && (event->fState & kKeyMod1Mask)) {
if (fState == kButtonEngaged ) return kTRUE;
click = (fState == kButtonDown);
if (click && fStayDown) {
SetState(kButtonEngaged);
} else {
SetState(kButtonUp);
}
}
if (click) {
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
}
EmitSignals(was);
return kTRUE;
}
TGDimension TGTextButton::GetDefaultSize() const
{
UInt_t w = GetOptions() & kFixedWidth ? fWidth : fTWidth + fMLeft + fMRight + 8;
UInt_t h = GetOptions() & kFixedHeight ? fHeight : fTHeight + fMTop + fMBottom + 7;
return TGDimension(w, h);
}
FontStruct_t TGTextButton::GetDefaultFontStruct()
{
if (!fgDefaultFont)
fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
return fgDefaultFont->GetFontStruct();
}
void TGTextButton::SetFont(FontStruct_t font, Bool_t global)
{
if (font != fFontStruct) {
FontH_t v = gVirtualX->GetFontHandle(font);
if (!v) return;
fFontStruct = font;
TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
TGGC *gc = pool->FindGC(fNormGC);
if (gc && !global) {
gc = pool->GetGC((GCValues_t*)gc->GetAttributes(), kTRUE);
fHasOwnFont = kTRUE;
}
if (gc) {
gc->SetFont(v);
fNormGC = gc->GetGC();
}
Layout();
}
}
void TGTextButton::SetFont(const char *fontName, Bool_t global)
{
TGFont *font = fClient->GetFont(fontName);
if (font) {
SetFont(font->GetFontStruct(), global);
}
}
void TGTextButton::SetTextColor(Pixel_t color, Bool_t global)
{
TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
TGGC *gc = pool->FindGC(fNormGC);
if (gc && !global) {
gc = pool->GetGC((GCValues_t*)gc->GetAttributes(), kTRUE);
fHasOwnFont = kTRUE;
}
if (gc) {
gc->SetForeground(color);
fNormGC = gc->GetGC();
}
fClient->NeedRedraw(this);
}
Bool_t TGTextButton::HasOwnFont() const
{
return fHasOwnFont;
}
TGPictureButton::TGPictureButton(const TGWindow *p, const TGPicture *pic,
Int_t id, GContext_t norm, UInt_t option) : TGButton(p, id, norm, option)
{
if (!pic) {
Error("TGPictureButton", "pixmap not found for button %d", id);
fPic = fClient->GetPicture("mb_question_s.xpm");
} else {
fPic = pic;
}
if (fPic) {
fTWidth = fPic->GetWidth();
fTHeight = fPic->GetHeight();
Resize(fTWidth + (fBorderWidth << 1) + fBorderWidth + 1,
fTHeight + (fBorderWidth << 1) + fBorderWidth);
}
fPicD = 0;
fOwnDisabledPic = kFALSE;
SetWindowName();
}
TGPictureButton::TGPictureButton(const TGWindow *p, const TGPicture *pic,
const char *cmd, Int_t id, GContext_t norm, UInt_t option)
: TGButton(p, id, norm, option)
{
if (!pic) {
Error("TGPictureButton", "pixmap not found for button\n%s",
cmd ? cmd : "");
fPic = fClient->GetPicture("mb_question_s.xpm");
} else {
fPic = pic;
}
fCommand = cmd;
if (fPic) {
fTWidth = fPic->GetWidth();
fTHeight = fPic->GetHeight();
Resize(fTWidth + (fBorderWidth << 1) + fBorderWidth + 1,
fTHeight + (fBorderWidth << 1) + fBorderWidth);
}
fPicD = 0;
fOwnDisabledPic = kFALSE;
SetWindowName();
}
TGPictureButton::TGPictureButton(const TGWindow *p, const char *pic,
Int_t id, GContext_t norm, UInt_t option) : TGButton(p, id, norm, option)
{
if (!pic || !strlen(pic)) {
if (p) Error("TGPictureButton", "pixmap not found for button");
fPic = fClient->GetPicture("mb_question_s.xpm");
} else {
fPic = fClient->GetPicture(pic);
}
if (fPic) {
fTWidth = fPic->GetWidth();
fTHeight = fPic->GetHeight();
Resize(fTWidth + (fBorderWidth << 1) + fBorderWidth + 1,
fTHeight + (fBorderWidth << 1) + fBorderWidth);
}
fPicD = 0;
fOwnDisabledPic = kFALSE;
SetWindowName();
}
TGPictureButton::~TGPictureButton()
{
if (fOwnDisabledPic) fClient->FreePicture(fPicD);
}
void TGPictureButton::SetPicture(const TGPicture *new_pic)
{
if (!new_pic) {
Error("SetPicture", "pixmap not found for button %d\n%s",
fWidgetId, fCommand.Data());
return;
}
fPic = new_pic;
if (fState == kButtonDisabled) {
fClient->FreePicture(fPicD);
fPicD = 0;
}
fTWidth = fPic->GetWidth();
fTHeight = fPic->GetHeight();
fClient->NeedRedraw(this);
}
void TGPictureButton::DoRedraw()
{
if (!fPic) {
TGFrame::DoRedraw();
return;
}
int x = (fWidth - fTWidth) >> 1;
int y = (fHeight - fTHeight) >> 1;
UInt_t w = GetWidth() - 1;
UInt_t h = GetHeight()- 1;
if (fStyle > 0)
gVirtualX->SetWindowBackground(fId, fBgndColor);
else
gVirtualX->SetWindowBackground(fId, fBackground);
TGFrame::DoRedraw();
if (fState == kButtonDown || fState == kButtonEngaged) {
++x; ++y;
w--; h--;
}
if (fStyle == 0) {
if (fState == kButtonEngaged) {
gVirtualX->FillRectangle(fId, GetHibckgndGC()(), 2, 2, fWidth-4, fHeight-4);
gVirtualX->DrawLine(fId, GetHilightGC()(), 2, 2, fWidth-3, 2);
}
}
const TGPicture *pic = fPic;
if (fState == kButtonDisabled) {
if (!fPicD) CreateDisabledPicture();
pic = fPicD ? fPicD : fPic;
}
if (fStyle > 0) {
if (fBgndColor == fHighColor) {
gVirtualX->DrawRectangle(fId, TGFrame::GetShadowGC()(), 0, 0, w, h);
}
}
pic->Draw(fId, fNormGC, x, y);
}
void TGPictureButton::CreateDisabledPicture()
{
TImage *img = TImage::Create();
if (!img) return;
TImage *img2 = TImage::Create();
if (!img2) {
if (img) delete img;
return;
}
TString back = gEnv->GetValue("Gui.BackgroundColor", "#c0c0c0");
img2->FillRectangle(back.Data(), 0, 0, fPic->GetWidth(), fPic->GetHeight());
img->SetImage(fPic->GetPicture(), fPic->GetMask());
Pixmap_t mask = img->GetMask();
img2->Merge(img, "overlay");
TString name = "disbl_";
name += fPic->GetName();
fPicD = fClient->GetPicturePool()->GetPicture(name.Data(), img2->GetPixmap(),
mask);
fOwnDisabledPic = kTRUE;
delete img;
delete img2;
}
void TGPictureButton::SetDisabledPicture(const TGPicture *pic)
{
if (!pic) return;
if (fOwnDisabledPic && fPicD) fClient->FreePicture(fPicD);
fPicD = pic;
((TGPicture*)pic)->AddReference();
fOwnDisabledPic = kFALSE;
}
TGCheckButton::TGCheckButton(const TGWindow *p, TGHotString *s, Int_t id,
GContext_t norm, FontStruct_t font, UInt_t option)
: TGTextButton(p, s, id, norm, font, option)
{
Init();
}
TGCheckButton::TGCheckButton(const TGWindow *p, const char *s, Int_t id,
GContext_t norm, FontStruct_t font, UInt_t option)
: TGTextButton(p, s, id, norm, font, option)
{
Init();
}
TGCheckButton::TGCheckButton(const TGWindow *p, const char *s, const char *cmd,
Int_t id, GContext_t norm, FontStruct_t font,
UInt_t option) : TGTextButton(p, s, cmd, id, norm, font, option)
{
Init();
}
void TGCheckButton::Init()
{
fPrevState =
fState = kButtonUp;
fHKeycode = 0;
fOn = fClient->GetPicture("checked_t.xpm");
fOff = fClient->GetPicture("unchecked_t.xpm");
fDisOn = fClient->GetPicture("checked_dis_t.xpm");
fDisOff = fClient->GetPicture("unchecked_dis_t.xpm");
Resize();
if (!fOn) {
Error("TGCheckButton", "checked_t.xpm not found");
} else if (!fOff) {
Error("TGCheckButton", "unchecked_t.xpm not found");
} else if (!fDisOn) {
Error("TGCheckButton", "checked_dis_t.xpm not found");
} else if (!fDisOff) {
Error("TGCheckButton", "unchecked_dis_t.xpm not found");
}
int hotchar;
if ((hotchar = fLabel->GetHotChar()) != 0) {
if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0) {
const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
main->BindKey(this, fHKeycode, kKeyMod1Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
}
}
SetWindowName();
}
TGCheckButton::~TGCheckButton()
{
if (fOn) fClient->FreePicture(fOn);
if (fOff) fClient->FreePicture(fOff);
if (fDisOn) fClient->FreePicture(fDisOn);
if (fDisOff) fClient->FreePicture(fDisOff);
}
TGDimension TGCheckButton::GetDefaultSize() const
{
UInt_t w = !fTWidth ? fOff->GetWidth() : fTWidth + fOff->GetWidth() + 9;
UInt_t h = !fTHeight ? fOff->GetHeight() : fTHeight + 2;
w = GetOptions() & kFixedWidth ? fWidth : w;
h = GetOptions() & kFixedHeight ? fHeight : h;
return TGDimension(w, h);
}
void TGCheckButton::SetState(EButtonState state, Bool_t emit)
{
if (state == kButtonDisabled)
fWidgetFlags &= ~kWidgetIsEnabled;
else
fWidgetFlags |= kWidgetIsEnabled;
PSetState(state, emit);
}
void TGCheckButton::EmitSignals(Bool_t )
{
if (fState == kButtonUp) Released();
if (fState == kButtonDown) Pressed();
Clicked();
Toggled(fStateOn);
}
void TGCheckButton::PSetState(EButtonState state, Bool_t emit)
{
if (state != fState) {
if (state == kButtonUp) {
if (fPrevState == kButtonDisabled) {
if (fStateOn) {
fState = kButtonDown;
fPrevState = kButtonDown;
} else {
fState = state;
fPrevState = state;
}
} else if (fPrevState == kButtonDown) {
fStateOn = kFALSE;
fState = state;
fPrevState = state;
}
} else if (state == kButtonDown) {
fStateOn = kTRUE;
fState = state;
fPrevState = state;
} else {
fState = state;
fPrevState = state;
}
if (emit) {
EmitSignals();
}
DoRedraw();
}
}
void TGCheckButton::SetDisabledAndSelected(Bool_t enable)
{
if (!enable) {
if (fState == kButtonDisabled && fStateOn) {
PSetState(kButtonUp, kFALSE);
PSetState(kButtonUp, kFALSE);
PSetState(kButtonDisabled, kFALSE);
} else {
PSetState(kButtonUp, kFALSE);
PSetState(kButtonDisabled, kFALSE);
}
} else {
PSetState(kButtonDown, kFALSE);
PSetState(kButtonDisabled, kFALSE);
}
}
Bool_t TGCheckButton::HandleButton(Event_t *event)
{
Bool_t click = kFALSE;
if (fTip) fTip->Hide();
if (fState == kButtonDisabled) return kTRUE;
Bool_t in = (event->fX >= 0) && (event->fY >= 0) &&
(event->fX <= (Int_t)fWidth) && (event->fY <= (Int_t)fHeight);
if (event->fType == kButtonPress) {
fgReleaseBtn = 0;
if (in) {
fOptions |= kSunkenFrame;
Pressed();
}
} else {
if (in) {
PSetState((fPrevState == kButtonUp) ? kButtonDown : kButtonUp, kFALSE);
click = kTRUE;
fPrevStateOn = fStateOn;
Released();
}
fgReleaseBtn = fId;
fOptions &= ~kSunkenFrame;
}
if (click) {
Clicked();
Toggled(fStateOn);
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_CHECKBUTTON),
fWidgetId, (Long_t) fUserData);
fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_CHECKBUTTON),
fWidgetId, (Long_t) fUserData);
}
DoRedraw();
return kTRUE;
}
Bool_t TGCheckButton::HandleCrossing(Event_t *event)
{
if (fTip) {
if (event->fType == kEnterNotify)
fTip->Reset();
else
fTip->Hide();
}
if ((fgDbw != event->fWindow) || (fgReleaseBtn == event->fWindow)) return kTRUE;
if (!(event->fState & (kButton1Mask | kButton2Mask | kButton3Mask)))
return kTRUE;
if (fState == kButtonDisabled) return kTRUE;
if (event->fType == kEnterNotify) {
fOptions |= kSunkenFrame;
} else {
fOptions &= ~kSunkenFrame;
}
DoRedraw();
return kTRUE;
}
Bool_t TGCheckButton::HandleKey(Event_t *event)
{
Bool_t click = kFALSE;
if (event->fType == kGKeyPress)
gVirtualX->SetKeyAutoRepeat(kFALSE);
else
gVirtualX->SetKeyAutoRepeat(kTRUE);
if (fTip && event->fType == kGKeyPress) fTip->Hide();
if (fState == kButtonDisabled) return kTRUE;
if ((event->fType == kGKeyPress) && (event->fState & kKeyMod1Mask)) {
PSetState((fPrevState == kButtonUp) ? kButtonDown : kButtonUp, kTRUE);
} else if ((event->fType == kKeyRelease) && (event->fState & kKeyMod1Mask)) {
click = (fState != fPrevState);
fPrevState = fState;
}
if (click) {
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_CHECKBUTTON), fWidgetId,
(Long_t) fUserData);
fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_CHECKBUTTON), fWidgetId,
(Long_t) fUserData);
}
return kTRUE;
}
void TGCheckButton::DoRedraw()
{
int x, y, y0;
TGFrame::DoRedraw();
x = 20;
y = (fHeight - fTHeight) >> 1;
y0 = !fTHeight ? 0 : y + 1;
if (fOn && fOff) {
Int_t smax = TMath::Max(fOn->GetHeight(), fOff->GetHeight());
y0 = ((Int_t)fHeight <= smax) ? 0 : 1 + (((Int_t)fHeight - smax) >> 1);
}
if (fStateOn) {
if (fOn) fOn->Draw(fId, fNormGC, 0, y0);
} else {
if (fOff) fOff->Draw(fId, fNormGC, 0, y0);
}
Int_t hotpos = fLabel->GetHotPos();
if (fState == kButtonDisabled) {
if (fStateOn == kTRUE) {
if (fDisOn) fDisOn->Draw(fId, fNormGC, 0, y0);
} else {
if (fDisOff) fDisOff->Draw(fId, fNormGC, 0, y0);
}
TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
TGGC *gc = pool->FindGC(fNormGC);
if (gc) {
Pixel_t fore = gc->GetForeground();
Pixel_t hi = GetHilightGC().GetForeground();
Pixel_t sh = GetShadowGC().GetForeground();
gc->SetForeground(hi);
fTLayout->DrawText(fId, gc->GetGC(), x + 1, y + 1, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x, y, hotpos - 1);
gc->SetForeground(sh);
fTLayout->DrawText(fId, gc->GetGC(), x, y, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x, y, hotpos - 1);
gc->SetForeground(fore);
}
} else {
fTLayout->DrawText(fId, fNormGC, x, y, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, fNormGC, x, y, hotpos - 1);
}
}
FontStruct_t TGCheckButton::GetDefaultFontStruct()
{
if (!fgDefaultFont)
fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
return fgDefaultFont->GetFontStruct();
}
const TGGC &TGCheckButton::GetDefaultGC()
{
if (!fgDefaultGC)
fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
return *fgDefaultGC;
}
TGRadioButton::TGRadioButton(const TGWindow *p, TGHotString *s, Int_t id,
GContext_t norm, FontStruct_t font, UInt_t option)
: TGTextButton(p, s, id, norm, font, option)
{
Init();
}
TGRadioButton::TGRadioButton(const TGWindow *p, const char *s, Int_t id,
GContext_t norm, FontStruct_t font, UInt_t option)
: TGTextButton(p, s, id, norm, font, option)
{
Init();
}
TGRadioButton::TGRadioButton(const TGWindow *p, const char *s, const char *cmd,
Int_t id, GContext_t norm,
FontStruct_t font, UInt_t option)
: TGTextButton(p, s, cmd, id, norm, font, option)
{
Init();
}
void TGRadioButton::Init()
{
fPrevState =
fState = kButtonUp;
fHKeycode = 0;
fOn = fClient->GetPicture("rbutton_on.xpm");
fOff = fClient->GetPicture("rbutton_off.xpm");
fDisOn = fClient->GetPicture("rbutton_dis_on.xpm");
fDisOff = fClient->GetPicture("rbutton_dis_off.xpm");
if (!fOn || !fOff || !fDisOn || !fDisOff)
Error("TGRadioButton", "rbutton_*.xpm not found");
Resize();
int hotchar;
if ((hotchar = fLabel->GetHotChar()) != 0) {
if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0) {
const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
main->BindKey(this, fHKeycode, kKeyMod1Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
}
}
if (fParent->IsA()->InheritsFrom(TGButtonGroup::Class())) {
((TGButtonGroup*)fParent)->SetRadioButtonExclusive(kTRUE);
}
SetWindowName();
}
TGRadioButton::~TGRadioButton()
{
if (fOn) fClient->FreePicture(fOn);
if (fOff) fClient->FreePicture(fOff);
if (fDisOn) fClient->FreePicture(fDisOn);
if (fDisOff) fClient->FreePicture(fDisOff);
}
TGDimension TGRadioButton::GetDefaultSize() const
{
UInt_t w = !fTWidth ? fOff->GetWidth() : fTWidth + fOff->GetWidth() + 10;
UInt_t h = !fTHeight ? fOff->GetHeight() : fTHeight + 2;
w = GetOptions() & kFixedWidth ? fWidth : w;
h = GetOptions() & kFixedHeight ? fHeight : h;
return TGDimension(w, h);
}
void TGRadioButton::SetState(EButtonState state, Bool_t emit)
{
if (state == kButtonDisabled)
fWidgetFlags &= ~kWidgetIsEnabled;
else
fWidgetFlags |= kWidgetIsEnabled;
PSetState(state, emit);
}
void TGRadioButton::SetDisabledAndSelected(Bool_t enable)
{
if (!enable) {
if (fState == kButtonDisabled && fStateOn) {
PSetState(kButtonUp, kFALSE);
PSetState(kButtonUp, kFALSE);
PSetState(kButtonDisabled, kFALSE);
} else {
PSetState(kButtonUp, kFALSE);
PSetState(kButtonDisabled, kFALSE);
}
} else {
PSetState(kButtonDown, kFALSE);
PSetState(kButtonDisabled, kFALSE);
}
}
void TGRadioButton::EmitSignals(Bool_t )
{
if (fState == kButtonUp) Released();
if (fState == kButtonDown) Pressed();
Clicked();
Toggled(fStateOn);
}
void TGRadioButton::PSetState(EButtonState state, Bool_t emit)
{
if (state != fState) {
if (state == kButtonUp) {
if (fPrevState == kButtonDisabled) {
if (fStateOn) {
fState = kButtonDown;
fPrevState = kButtonDown;
} else {
fState = state;
fPrevState = state;
}
} else if (fPrevState == kButtonDown) {
fStateOn = kFALSE;
fState = state;
fPrevState = state;
}
} else if (state == kButtonDown) {
fStateOn = kTRUE;
fState = state;
fPrevState = state;
} else {
fState = state;
fPrevState = state;
}
if (emit) {
EmitSignals();
}
DoRedraw();
}
}
Bool_t TGRadioButton::HandleButton(Event_t *event)
{
Bool_t click = kFALSE;
Bool_t toggled = kFALSE;
if (fTip) fTip->Hide();
if (fState == kButtonDisabled) return kFALSE;
Bool_t in = (event->fX >= 0) && (event->fY >= 0) &&
(event->fX <= (Int_t)fWidth) && (event->fY <= (Int_t)fHeight);
if (event->fType == kButtonPress) {
fgReleaseBtn = 0;
if (in) {
fOptions |= kSunkenFrame;
Pressed();
}
} else {
if (in) {
if (!fStateOn) {
PSetState(kButtonDown, kFALSE);
toggled = kTRUE;
}
fPrevStateOn = fStateOn;
Released();
click = kTRUE;
}
fOptions &= ~kSunkenFrame;
fgReleaseBtn = fId;
}
if (click) {
Clicked();
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_RADIOBUTTON),
fWidgetId, (Long_t) fUserData);
fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_RADIOBUTTON),
fWidgetId, (Long_t) fUserData);
}
if (toggled) {
Toggled(fStateOn);
}
DoRedraw();
return kTRUE;
}
Bool_t TGRadioButton::HandleCrossing(Event_t *event)
{
if (fTip) {
if (event->fType == kEnterNotify)
fTip->Reset();
else
fTip->Hide();
}
if ((fgDbw != event->fWindow) || (fgReleaseBtn == event->fWindow)) return kTRUE;
if (!(event->fState & (kButton1Mask | kButton2Mask | kButton3Mask)))
return kTRUE;
if (fState == kButtonDisabled) return kTRUE;
if (event->fType == kEnterNotify) {
fOptions |= kSunkenFrame;
} else {
fOptions &= ~kSunkenFrame;
}
DoRedraw();
return kTRUE;
}
Bool_t TGRadioButton::HandleKey(Event_t *event)
{
if (event->fType == kGKeyPress)
gVirtualX->SetKeyAutoRepeat(kFALSE);
else
gVirtualX->SetKeyAutoRepeat(kTRUE);
if (fTip && event->fType == kGKeyPress)
fTip->Hide();
if (fState == kButtonDisabled) return kTRUE;
if ((event->fType == kGKeyPress) && (event->fState & kKeyMod1Mask)) {
PSetState(kButtonDown, kTRUE);
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_RADIOBUTTON),
fWidgetId, (Long_t) fUserData);
fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_RADIOBUTTON),
fWidgetId, (Long_t) fUserData);
} else if ((event->fType == kKeyRelease) && (event->fState & kKeyMod1Mask)) {
fPrevState = fState;
}
return kTRUE;
}
void TGRadioButton::DoRedraw()
{
Int_t tx, ty, y0;
TGFrame::DoRedraw();
tx = 20;
ty = (fHeight - fTHeight) >> 1;
y0 = !fTHeight ? 0 : ty + 1;
if (fOn && fOff) {
Int_t smax = TMath::Max(fOn->GetHeight(), fOff->GetHeight());
y0 = ((Int_t)fHeight <= smax) ? 0 : 1 + (((Int_t)fHeight - smax) >> 1);
}
if (fStateOn) {
if (fOn) fOn->Draw(fId, fNormGC, 0, y0);
} else {
if (fOff) fOff->Draw(fId, fNormGC, 0, y0);
}
Int_t hotpos = fLabel->GetHotPos();
if (fState == kButtonDisabled) {
if (fStateOn == kTRUE) {
if (fDisOn) fDisOn->Draw(fId, fNormGC, 0, y0);
} else {
if (fDisOff) fDisOff->Draw(fId, fNormGC, 0, y0);
}
TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
TGGC *gc = pool->FindGC(fNormGC);
if (gc) {
Pixel_t fore = gc->GetForeground();
Pixel_t hi = GetHilightGC().GetForeground();
Pixel_t sh = GetShadowGC().GetForeground();
gc->SetForeground(hi);
fTLayout->DrawText(fId, gc->GetGC(), tx + 1, ty + 1, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), tx, ty, hotpos - 1);
gc->SetForeground(sh);
fTLayout->DrawText(fId, gc->GetGC(), tx, ty, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), tx, ty, hotpos - 1);
gc->SetForeground(fore);
}
} else {
fTLayout->DrawText(fId, fNormGC, tx, ty, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, fNormGC, tx, ty, hotpos-1);
}
}
FontStruct_t TGRadioButton::GetDefaultFontStruct()
{
if (!fgDefaultFont)
fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
return fgDefaultFont->GetFontStruct();
}
const TGGC &TGRadioButton::GetDefaultGC()
{
if (!fgDefaultGC)
fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
return *fgDefaultGC;
}
void TGButton::SavePrimitive(ostream &out, Option_t *option )
{
char quote = '"';
if (option && strstr(option, "keep_names"))
out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
if (fState == kButtonDown) {
out << " " << GetName() << "->SetState(kButtonDown);" << endl;
}
if (fState == kButtonDisabled) {
out << " " << GetName() << "->SetState(kButtonDisabled);" << endl;
}
if (fState == kButtonEngaged) {
out << " " << GetName() << "->SetState(kButtonEngaged);" << endl;
}
if (fBackground != fgDefaultFrameBackground) {
SaveUserColor(out, option);
out << " " << GetName() << "->ChangeBackground(ucolor);" << endl;
}
if (fTip) {
TString tiptext = fTip->GetText()->GetString();
tiptext.ReplaceAll("\n", "\\n");
out << " ";
out << GetName() << "->SetToolTipText(" << quote
<< tiptext << quote << ");" << endl;
}
if (strlen(fCommand)) {
out << " " << GetName() << "->SetCommand(" << quote << fCommand
<< quote << ");" << endl;
}
}
void TGTextButton::SavePrimitive(ostream &out, Option_t *option )
{
char quote = '"';
TString outext(fLabel->GetString());
if (fLabel->GetHotPos() > 0)
outext.Insert(fLabel->GetHotPos()-1, "&");
if (outext.First('\n') >= 0)
outext.ReplaceAll("\n", "\\n");
option = GetName()+5;
TString parGC, parFont;
parFont.Form("%s::GetDefaultFontStruct()",IsA()->GetName());
parGC.Form("%s::GetDefaultGC()()",IsA()->GetName());
if ((GetDefaultFontStruct() != fFontStruct) || (GetDefaultGC()() != fNormGC)) {
TGFont *ufont = gClient->GetResourcePool()->GetFontPool()->FindFont(fFontStruct);
if (ufont) {
ufont->SavePrimitive(out, option);
parFont.Form("ufont->GetFontStruct()");
}
TGGC *userGC = gClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
if (userGC) {
userGC->SavePrimitive(out, option);
parGC.Form("uGC->GetGC()");
}
}
if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
out << " TGTextButton *";
out << GetName() << " = new TGTextButton(" << fParent->GetName()
<< "," << quote << outext.Data() << quote;
if (GetOptions() == (kRaisedFrame | kDoubleBorder)) {
if (fFontStruct == GetDefaultFontStruct()) {
if (fNormGC == GetDefaultGC()()) {
if (fWidgetId == -1) {
out << ");" << endl;
} else {
out << "," << fWidgetId <<");" << endl;
}
} else {
out << "," << fWidgetId << "," << parGC << ");" << endl;
}
} else {
out << "," << fWidgetId << "," << parGC << "," << parFont << ");" << endl;
}
} else {
out << "," << fWidgetId << "," << parGC << "," << parFont << "," << GetOptionString() << ");" << endl;
}
out << " " << GetName() << "->SetTextJustify(" << fTMode << ");" << endl;
out << " " << GetName() << "->SetMargins(" << fMLeft << "," << fMRight << ",";
out << fMTop << "," << fMBottom << ");" << endl;
out << " " << GetName() << "->SetWrapLength(" << fWrapLength << ");" << endl;
out << " " << GetName() << "->Resize(" << GetWidth() << "," << GetHeight()
<< ");" << endl;
TGButton::SavePrimitive(out,option);
}
void TGPictureButton::SavePrimitive(ostream &out, Option_t *option )
{
if (!fPic) {
Error("SavePrimitive()", "pixmap not found for picture button %d ", fWidgetId);
return;
}
option = GetName()+5;
TString parGC;
parGC.Form("%s::GetDefaultGC()()",IsA()->GetName());
if (GetDefaultGC()() != fNormGC) {
TGGC *userGC = gClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
if (userGC) {
userGC->SavePrimitive(out, option);
parGC.Form("uGC->GetGC()");
}
}
char quote = '"';
const char *picname = fPic->GetName();
out <<" TGPictureButton *";
out << GetName() << " = new TGPictureButton(" << fParent->GetName()
<< ",gClient->GetPicture(" << quote
<< gSystem->ExpandPathName(gSystem->UnixPathName(picname)) << quote << ")";
if (GetOptions() == (kRaisedFrame | kDoubleBorder)) {
if (fNormGC == GetDefaultGC()()) {
if (fWidgetId == -1) {
out << ");" << endl;
} else {
out << "," << fWidgetId << ");" << endl;
}
} else {
out << "," << fWidgetId << "," << parGC.Data() << ");" << endl;
}
} else {
out << "," << fWidgetId << "," << parGC.Data() << "," << GetOptionString()
<< ");" << endl;
}
TGButton::SavePrimitive(out,option);
}
void TGCheckButton::SavePrimitive(ostream &out, Option_t *option )
{
char quote = '"';
TString outext(fLabel->GetString());
if (fLabel->GetHotPos() > 0)
outext.Insert(fLabel->GetHotPos()-1, "&");
if (outext.First('\n') >= 0)
outext.ReplaceAll("\n", "\\n");
out <<" TGCheckButton *";
out << GetName() << " = new TGCheckButton(" << fParent->GetName()
<< "," << quote << outext.Data() << quote;
option = GetName()+5;
TString parGC, parFont;
parFont.Form("%s::GetDefaultFontStruct()",IsA()->GetName());
parGC.Form("%s::GetDefaultGC()()",IsA()->GetName());
if ((GetDefaultFontStruct() != fFontStruct) || (GetDefaultGC()() != fNormGC)) {
TGFont *ufont = gClient->GetResourcePool()->GetFontPool()->FindFont(fFontStruct);
if (ufont) {
ufont->SavePrimitive(out, option);
parFont.Form("ufont->GetFontStruct()");
}
TGGC *userGC = gClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
if (userGC) {
userGC->SavePrimitive(out, option);
parGC.Form("uGC->GetGC()");
}
}
if (GetOptions() == kChildFrame) {
if (fFontStruct == GetDefaultFontStruct()) {
if (fNormGC == GetDefaultGC()()) {
if (fWidgetId == -1) {
out << ");" << endl;
} else {
out << "," << fWidgetId << ");" << endl;
}
} else {
out << "," << fWidgetId << "," << parGC << ");" << endl;
}
} else {
out << "," << fWidgetId << "," << parGC << "," << parFont << ");" << endl;
}
} else {
out << "," << fWidgetId << "," << parGC << "," << parFont << "," << GetOptionString() << ");" << endl;
}
TGButton::SavePrimitive(out,option);
if (fState == kButtonDisabled) {
if (IsDisabledAndSelected())
out << " " << GetName() << "->SetDisabledAndSelected(kTRUE);" << endl;
else
out << " " << GetName() << "->SetDisabledAndSelected(kFALSE);" << endl;
}
out << " " << GetName() << "->SetTextJustify(" << fTMode << ");" << endl;
out << " " << GetName() << "->SetMargins(" << fMLeft << "," << fMRight << ",";
out << fMTop << "," << fMBottom << ");" << endl;
out << " " << GetName() << "->SetWrapLength(" << fWrapLength << ");" << endl;
}
void TGRadioButton::SavePrimitive(ostream &out, Option_t *option )
{
char quote = '"';
TString outext(fLabel->GetString());
if (fLabel->GetHotPos() > 0)
outext.Insert(fLabel->GetHotPos()-1, "&");
if (outext.First('\n') >= 0)
outext.ReplaceAll("\n", "\\n");
out << " TGRadioButton *";
out << GetName() << " = new TGRadioButton(" << fParent->GetName()
<< "," << quote << outext.Data() << quote;
option = GetName()+5;
TString parGC, parFont;
parFont.Form("%s::GetDefaultFontStruct()",IsA()->GetName());
parGC.Form("%s::GetDefaultGC()()",IsA()->GetName());
if ((GetDefaultFontStruct() != fFontStruct) || (GetDefaultGC()() != fNormGC)) {
TGFont *ufont = gClient->GetResourcePool()->GetFontPool()->FindFont(fFontStruct);
if (ufont) {
ufont->SavePrimitive(out, option);
parFont.Form("ufont->GetFontStruct()");
}
TGGC *userGC = gClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
if (userGC) {
userGC->SavePrimitive(out, option);
parGC.Form("uGC->GetGC()");
}
}
if (GetOptions() == (kChildFrame)) {
if (fFontStruct == GetDefaultFontStruct()) {
if (fNormGC == GetDefaultGC()()) {
if (fWidgetId == -1) {
out <<");" << endl;
} else {
out << "," << fWidgetId << ");" << endl;
}
} else {
out << "," << fWidgetId << "," << parGC << ");" << endl;
}
} else {
out << "," << fWidgetId << "," << parGC << "," << parFont << ");" << endl;
}
} else {
out << "," << fWidgetId << "," << parGC << "," << parFont << "," << GetOptionString() << ");" << endl;
}
TGButton::SavePrimitive(out,option);
if (fState == kButtonDisabled) {
if (IsDisabledAndSelected())
out << " " << GetName() << "->SetDisabledAndSelected(kTRUE);" << endl;
else
out << " " << GetName() << "->SetDisabledAndSelected(kFALSE);" << endl;
}
out << " " << GetName() << "->SetTextJustify(" << fTMode << ");" << endl;
out << " " << GetName() << "->SetMargins(" << fMLeft << "," << fMRight << ",";
out << fMTop << "," << fMBottom << ");" << endl;
out << " " << GetName() << "->SetWrapLength(" << fWrapLength << ");" << endl;
}
TGSplitButton::TGSplitButton(const TGWindow *p, TGHotString* menulabel,
TGPopupMenu *popmenu, Bool_t split, Int_t id,
GContext_t norm, FontStruct_t fontstruct, UInt_t options)
: TGTextButton(p, menulabel, id, norm, fontstruct, options)
{
fFontStruct = fontstruct;
fMBWidth = 16;
fMenuLabel = new TGHotString(*menulabel);
fPopMenu = popmenu;
fPopMenu->fSplitButton = this;
fSplit = split;
fTMode = 0;
fHKeycode = 0;
fMBState = kButtonUp; fDefaultCursor = fClient->GetResourcePool()->GetGrabCursor();
fKeyNavigate = kFALSE;
fWidestLabel = "";
fHeighestLabel = "";
TGMenuEntry *entry = 0;
TGHotString lstring(*fMenuLabel);
TGHotString hstring(*fMenuLabel);
const TList *list = fPopMenu->GetListOfEntries();
UInt_t lwidth = 0, lheight = 0;
UInt_t twidth = 0, theight = 0;
TGFont *font = fClient->GetFontPool()->FindFont(fFontStruct);
if (!font) {
font = fClient->GetFontPool()->GetFont(fgDefaultFont);
if (font) fFontStruct = font->GetFontStruct();
}
if (font) font->ComputeTextLayout(lstring, lstring.GetLength(),
fWrapLength, kTextLeft, 0,
&lwidth, &lheight);
TIter iter(list);
entry = (TGMenuEntry *)iter.Next();
while (entry != 0) {
if (entry->GetType() == kMenuEntry) {
const TGHotString string(*(entry->GetLabel()));
if (font) font->ComputeTextLayout(string, string.GetLength(),
fWrapLength, kTextLeft, 0,
&twidth, &theight);
if(twidth > lwidth) {
lstring = string;
}
if(theight > lheight) {
hstring = string;
}
}
entry = (TGMenuEntry *)iter.Next();
}
fWidestLabel = lstring;
fHeighestLabel = hstring;
if (font) {
UInt_t dummy = 0;
font->ComputeTextLayout(lstring, lstring.GetLength(),
fWrapLength, kTextLeft, 0,
&fTWidth, &dummy);
font->ComputeTextLayout(hstring, hstring.GetLength(),
fWrapLength, kTextLeft, 0,
&dummy, &fTHeight);
}
fTBWidth = fTWidth + 8;
fHeight = fTHeight + 7;
Resize(fTBWidth + fMBWidth, fHeight);
ChangeOptions(GetOptions() | kFixedSize);
TIter iter1(list);
do {
entry = (TGMenuEntry *)iter1.Next();
if ((entry) && (entry->GetStatus() & kMenuEnableMask) &&
!(entry->GetStatus() & kMenuHideMask) &&
(entry->GetType() != kMenuSeparator) &&
(entry->GetType() != kMenuLabel)) break;
entry = (TGMenuEntry *)iter1.Next();
} while (entry);
if (entry) fEntryId = entry->GetEntryId();
fPopMenu->Connect("Activated(Int_t)", "TGSplitButton", this, "HandleMenu(Int_t)");
SetSplit(fSplit);
Init();
}
void TGSplitButton::Init()
{
Int_t hotchar;
fTMode = kTextCenterX | kTextCenterY;
fHKeycode = 0;
fHasOwnFont = kFALSE;
fPrevStateOn =
fStateOn = kFALSE;
fMBState = kButtonUp;
SetSize(TGDimension(fWidth, fHeight));
if ((hotchar = fLabel->GetHotChar()) != 0) {
if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0) {
const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
main->BindKey(this, fHKeycode, kKeyMod1Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
}
}
SetWindowAttributes_t wattr;
wattr.fMask = kWAWinGravity | kWABitGravity;
wattr.fBitGravity = 5;
wattr.fWinGravity = 1;
gVirtualX->ChangeWindowAttributes(fId, &wattr);
AddInput(kPointerMotionMask | kEnterWindowMask | kLeaveWindowMask);
SetWindowName();
}
TGSplitButton::~TGSplitButton()
{
if (fPopMenu) delete fPopMenu;
if (fMenuLabel) delete fMenuLabel;
}
void TGSplitButton::DrawTriangle(const GContext_t gc, Int_t x, Int_t y)
{
Point_t points[3];
points[0].fX = x;
points[0].fY = y;
points[1].fX = x + 5;
points[1].fY = y;
points[2].fX = x + 2;
points[2].fY = y + 3;
gVirtualX->FillPolygon(fId, gc, points, 3);
}
void TGSplitButton::CalcSize()
{
Int_t max_ascent, max_descent;
fTWidth = gVirtualX->TextWidth(fFontStruct, fLabel->GetString(), fLabel->GetLength());
gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
fTHeight = max_ascent + max_descent;
fTBWidth = fTWidth + 8;
fHeight = fTHeight + 7;
fWidth = fTBWidth;
}
Bool_t TGSplitButton::HandleSButton(Event_t *event)
{
if (fState == kButtonDisabled) return kFALSE;
Bool_t activate = kFALSE;
Bool_t bclick = kFALSE;
static Bool_t mbpress = kFALSE;
static Bool_t tbpress = kFALSE;
static Bool_t outpress = kFALSE;
Bool_t inTB = (event->fX >= 0) && (event->fY >= 0) &&
(event->fX <= (Int_t)fTBWidth) && (event->fY <= (Int_t)fHeight);
Bool_t inMB = (event->fX >= (Int_t)(fWidth -fMBWidth)) && (event->fY >= 0) &&
(event->fX <= (Int_t)fWidth) && (event->fY <= (Int_t)fHeight);
if (inTB) {
if (event->fType == kButtonPress) {
mbpress = kFALSE;
tbpress = kTRUE;
fgReleaseBtn = 0;
if (fState == kButtonEngaged) {
return kTRUE;
}
SetState(kButtonDown);
Pressed();
} else {
if (fMBState == kButtonDown) {
SetMBState(kButtonUp);
}
if (fState == kButtonEngaged && tbpress) {
SetState(kButtonUp);
Released();
bclick = kTRUE;
} else if (fState == kButtonDown && tbpress) {
tbpress = kFALSE;
if (fStayDown) {
bclick = kTRUE;
SetState(kButtonEngaged);
fgReleaseBtn = 0;
} else {
bclick = kTRUE;
SetState(kButtonUp);
Released();
fgReleaseBtn = fId;
}
}else {
SetState(kButtonUp);
}
}
} else if (inMB) {
if (event->fType == kButtonPress) {
fgReleaseBtn = 0;
mbpress = kTRUE;
tbpress = kFALSE;
if (fMBState == kButtonEngaged) {
return kTRUE;
}
SetMBState(kButtonDown);
MBPressed();
gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
kPointerMotionMask, kNone, fDefaultCursor);
} else {
if (fState == kButtonDown) {
SetState(kButtonUp);
}
if (fMBState == kButtonEngaged && mbpress) {
mbpress = kFALSE;
SetMBState(kButtonUp);
SetMenuState(kFALSE);
MBReleased();
MBClicked();
gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
} else if (fMBState == kButtonDown && mbpress) {
MBClicked();
SetMBState(kButtonEngaged);
SetMenuState(kTRUE);
fgReleaseBtn = 0;
} else {
SetMBState(kButtonUp);
}
}
} else {
if (event->fType == kButtonPress) {
fgReleaseBtn = 0;
outpress = kTRUE;
} else {
if(outpress) {
outpress = kFALSE;
SetMBState(kButtonUp);
SetMenuState(kFALSE);
gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
activate = kTRUE;
}
}
}
if (bclick) {
Clicked();
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
}
if (activate) {
TGMenuEntry *entry = fPopMenu->GetCurrent();
if (entry) {
if ((entry->GetStatus() & kMenuEnableMask) &&
!(entry->GetStatus() & kMenuHideMask) &&
(entry->GetType() != kMenuSeparator) &&
(entry->GetType() != kMenuLabel)) {
Int_t id = entry->GetEntryId();
fPopMenu->Activated(id);
}
}
}
return kTRUE;
}
Bool_t TGSplitButton::HandleSCrossing(Event_t *event)
{
if (fTip) {
if (event->fType == kEnterNotify)
fTip->Reset();
else
fTip->Hide();
}
if ((fgDbw != event->fWindow) || (fgReleaseBtn == event->fWindow)) return kTRUE;
if (!(event->fState & (kButton1Mask | kButton2Mask | kButton3Mask)))
return kTRUE;
if (fState == kButtonEngaged || fState == kButtonDisabled) return kTRUE;
Bool_t inTB = (event->fX <= (Int_t)fTBWidth);
if (event->fType == kEnterNotify) {
if (inTB) {
SetState(kButtonDown, kFALSE);
} else {
if(fMBState == kButtonEngaged) return kTRUE;
SetMBState(kButtonDown);
}
} else {
if(fState == kButtonDown) {
SetState(kButtonUp, kFALSE);
}
if (fMBState == kButtonEngaged) return kTRUE;
SetMBState(kButtonUp);
}
return kTRUE;
}
Bool_t TGSplitButton::HandleSKey(Event_t *event)
{
if (fState == kButtonDisabled) return kFALSE;
Bool_t click = kFALSE;
if (event->fType == kGKeyPress) {
gVirtualX->SetKeyAutoRepeat(kFALSE);
} else {
gVirtualX->SetKeyAutoRepeat(kTRUE);
}
if (fTip && event->fType == kGKeyPress) fTip->Hide();
if ((event->fType == kGKeyPress) && (event->fState & kKeyMod1Mask)) {
if (fState == kButtonEngaged) return kTRUE;
SetState(kButtonDown);
Pressed();
} else if ((event->fType == kKeyRelease) && (event->fState & kKeyMod1Mask)) {
if (fState == kButtonEngaged) {
SetState(kButtonUp);
Released();
}
if (fStayDown) {
SetState(kButtonEngaged);
} else {
SetState(kButtonUp);
Released();
}
click = kTRUE;
}
if (click) {
Clicked();
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
}
return kTRUE;
}
void TGSplitButton::SetMenuState(Bool_t state)
{
if (state) {
Int_t ax, ay;
Window_t wdummy;
if (fSplit) {
Int_t n_entries = 0;
TGMenuEntry *entry = 0;
TIter next(fPopMenu->GetListOfEntries());
while ((entry = (TGMenuEntry *) next())) {
if ((entry->GetType() != kMenuSeparator) &&
(entry->GetType() != kMenuLabel)) {
n_entries++;
}
}
if (n_entries <= 1) {
Info("TGSplitButton", "Only one entry in the menu.");
return;
}
}
gVirtualX->TranslateCoordinates(fId, fPopMenu->GetParent()->GetId(),
0, 0, ax, ay, wdummy);
fPopMenu->PlaceMenu(ax-1, ay+fHeight, kTRUE, kFALSE);
BindKeys(kTRUE);
BindMenuKeys(kTRUE);
} else {
fPopMenu->EndMenu(fUserData);
BindKeys(kFALSE);
BindMenuKeys(kFALSE);
fPopMenu->EndMenu(fUserData);
}
}
void TGSplitButton::DoRedraw()
{
int x, y;
TGFrame::DoRedraw();
if (fState == kButtonDisabled) fMBState = kButtonDisabled;
else if (fMBState == kButtonDisabled) fMBState = kButtonUp;
if (fTMode & kTextLeft) {
x = fMLeft + 4;
} else if (fTMode & kTextRight) {
x = fWidth - fTWidth -fMBWidth - fMRight - 4;
} else {
x = (fWidth - fTWidth -fMBWidth + fMLeft - fMRight) >> 1;
}
if (fTMode & kTextTop) {
y = fMTop + 3;
} else if (fTMode & kTextBottom) {
y = fHeight - fTHeight - fMBottom - 3;
} else {
y = (fHeight - fTHeight + fMTop - fMBottom) >> 1;
}
if (fState == kButtonDown || fState == kButtonEngaged) { ++x; ++y; }
if (fState == kButtonEngaged) {
gVirtualX->FillRectangle(fId, GetHibckgndGC()(), 2, 2, fWidth-4, fHeight-4);
gVirtualX->DrawLine(fId, GetHilightGC()(), 2, 2, fWidth-3, 2);
}
Int_t hotpos = fLabel->GetHotPos();
if (fState == kButtonDisabled) {
TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
TGGC *gc = pool->FindGC(fNormGC);
if (gc) {
Pixel_t fore = gc->GetForeground();
Pixel_t hi = GetHilightGC().GetForeground();
Pixel_t sh = GetShadowGC().GetForeground();
gc->SetForeground(hi);
fTLayout->DrawText(fId, gc->GetGC(), x + 1, y + 1, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x + 1, y + 1, hotpos - 1);
gc->SetForeground(sh);
fTLayout->DrawText(fId, gc->GetGC(), x, y, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x, y, hotpos - 1);
gc->SetForeground(fore);
}
} else {
fTLayout->DrawText(fId, fNormGC, x, y, 0, -1);
if (hotpos) fTLayout->UnderlineChar(fId, fNormGC, x, y, hotpos - 1);
}
x = fWidth - 11;
y = fHeight - 10;
if (fSplit) {
Int_t lx = fWidth - fMBWidth;
Int_t ly = 2;
Int_t lh = fHeight - 2;
if(fMBState == kButtonDown || fMBState == kButtonEngaged) {
x++;
y++;
}
gVirtualX->DrawLine(fId, GetShadowGC()(), lx, ly + 2, lx, lh - 4);
gVirtualX->DrawLine(fId, GetHilightGC()(), lx + 1, ly + 2, lx + 1, lh - 3);
gVirtualX->DrawLine(fId, GetHilightGC()(), lx, lh - 3, lx + 1, lh - 3);
if (fMBState == kButtonEngaged) {
gVirtualX->FillRectangle(fId, GetHibckgndGC()(), fTBWidth + 1, 1, fMBWidth - 3, fHeight - 3);
}
if (fMBState == kButtonDisabled) {
DrawTriangle(GetHilightGC()(), x + 1, y + 1);
DrawTriangle(GetShadowGC()(), x, y);
} else {
DrawTriangle(fNormGC, x, y);
}
} else {
x -= 2;
if(fState == kButtonDown || fState == kButtonEngaged) {
x++;
y++;
}
if (fState == kButtonDisabled) {
DrawTriangle(GetHilightGC()(), x + 1, y + 1);
DrawTriangle(GetShadowGC()(), x, y);
} else {
DrawTriangle(fNormGC, x, y);
}
}
}
void TGSplitButton::BindKeys(Bool_t on)
{
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Up), kAnyModifier, on);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Down), kAnyModifier, on);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Enter), kAnyModifier, on);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Return), kAnyModifier, on);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Escape), kAnyModifier, on);
}
void TGSplitButton::BindMenuKeys(Bool_t on)
{
TGMenuEntry *e = 0;
TIter next(fPopMenu->GetListOfEntries());
while ((e = (TGMenuEntry*)next())) {
Int_t hot = 0;
if (e->GetLabel()) {
hot = e->GetLabel()->GetHotChar();
}
if (!hot) continue;
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), 0, on);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask, on);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyLockMask, on);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyMod2Mask, on);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask | kKeyLockMask, on);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask | kKeyMod2Mask, on);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyLockMask | kKeyMod2Mask, on);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask | kKeyLockMask | kKeyMod2Mask, on);
}
}
TGDimension TGSplitButton::GetDefaultSize() const
{
UInt_t w = GetOptions() & kFixedWidth ? fWidth + fMBWidth : fTWidth + fMLeft + fMRight + fMBWidth + 8;
UInt_t h = GetOptions() & kFixedHeight ? fHeight : fTHeight + fMTop + fMBottom + 7;
return TGDimension(w, h);
}
void TGSplitButton::SetText(TGHotString *new_label)
{
Int_t hotchar;
static Bool_t longlabeltip = kFALSE;
const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
TGFont *font = fClient->GetFontPool()->FindFont(fFontStruct);
if (!font) {
font = fClient->GetFontPool()->GetFont(fgDefaultFont);
if (font) fFontStruct = font->GetFontStruct();
}
UInt_t width = 0, bwidth = 0, dummy;
if (font) {
font->ComputeTextLayout(new_label->GetString(), new_label->GetLength(),
fWrapLength, kTextLeft, 0,
&width, &dummy);
font->ComputeTextLayout(fWidestLabel.GetString(), fWidestLabel.GetLength(),
fWrapLength, kTextLeft, 0,
&bwidth, &dummy);
}
if (width > bwidth) {
if (!fTip) {
SetToolTipText(new_label->GetString());
longlabeltip = kTRUE;
}
Info("TGSplitbutton", "Length of new label to long, label truncated.");
new_label->Resize(fWidestLabel.GetLength());
} else if (new_label->GetLength() <= fWidestLabel.GetLength() && longlabeltip) {
if (fTip) delete fTip;
fTip = 0;
longlabeltip = kFALSE;
}
if (fLabel) {
if (fHKeycode) {
main->RemoveBind(this, fHKeycode, kKeyMod1Mask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
}
delete fLabel;
}
fLabel = new_label;
if ((hotchar = fLabel->GetHotChar()) != 0) {
if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0)
main->BindKey(this, fHKeycode, kKeyMod1Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
}
Layout();
}
void TGSplitButton::SetText(const TString &new_label)
{
SetText(new TGHotString(new_label));
}
void TGSplitButton::SetFont(FontStruct_t font, Bool_t global)
{
if (font != fFontStruct) {
FontH_t v = gVirtualX->GetFontHandle(font);
if (!v) return;
fFontStruct = font;
TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
TGGC *gc = pool->FindGC(fNormGC);
if ((gc) && !global) {
gc = pool->GetGC((GCValues_t*)gc->GetAttributes(), kTRUE);
fHasOwnFont = kTRUE;
}
if (gc) {
gc->SetFont(v);
fNormGC = gc->GetGC();
}
fClient->NeedRedraw(this);
}
}
void TGSplitButton::SetFont(const char *fontName, Bool_t global)
{
TGFont *font = fClient->GetFont(fontName);
if (font) {
SetFont(font->GetFontStruct(), global);
}
}
void TGSplitButton::SetMBState(EButtonState state)
{
if (state != fMBState) {
fMBState = state;
DoRedraw();
}
}
void TGSplitButton::SetSplit(Bool_t split)
{
if(split) {
fStayDown = kFALSE;
Disconnect(fPopMenu, "PoppedDown()");
fPopMenu->Connect("PoppedDown()", "TGSplitButton", this, "SetMBState(=kButtonUp)");
fPopMenu->Connect("PoppedDown()", "TGSplitButton", this, "MBReleased()");
TGMenuEntry *entry = fPopMenu->GetEntry(fEntryId);
if (entry) {
TGHotString *tmp = new TGHotString(*(entry->GetLabel()));
SetText(tmp);
TString str("ItemClicked(=");
str += entry->GetEntryId();
str += ")";
Connect("Clicked()", "TGSplitButton", this, str);
fEntryId = entry->GetEntryId();
fPopMenu->HideEntry(fEntryId);
}
} else {
fStayDown = kTRUE;
Disconnect(fPopMenu, "PoppedDown()");
Disconnect(this, "Clicked()", this);
fPopMenu->Connect("PoppedDown()", "TGSplitButton", this, "SetState(=kButtonUp)");
fPopMenu->Connect("PoppedDown()", "TGSplitButton", this, "Released()");
fPopMenu->EnableEntry(fEntryId);
TGHotString *tmp = new TGHotString(*fMenuLabel);
SetText(tmp);
}
fSplit = split;
DoRedraw();
}
Bool_t TGSplitButton::HandleButton(Event_t *event)
{
if (fState == kButtonDisabled) return kFALSE;
if (fSplit) return HandleSButton(event);
Bool_t in = (event->fX >= 0) && (event->fY >= 0) &&
(event->fX <= (Int_t)fWidth) && (event->fY <= (Int_t)fHeight);
Bool_t activate = kFALSE;
Bool_t click = kFALSE;
if (in) {
if (event->fType == kButtonPress) {
fgReleaseBtn = 0;
if (fState == kButtonEngaged) {
return kTRUE;
}
SetState(kButtonDown);
Pressed();
gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
kPointerMotionMask, kNone, fDefaultCursor);
} else {
if (fState == kButtonEngaged) {
SetState(kButtonUp);
SetMenuState(kFALSE);
Released();
click = kTRUE;
gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
} else {
click = (fState == kButtonDown);
if (click && fStayDown) {
SetState(kButtonEngaged);
SetMenuState(kTRUE);
fgReleaseBtn = 0;
} else {
SetState(kButtonUp);
Released();
fgReleaseBtn = fId;
}
}
fKeyNavigate = kFALSE;
}
} else {
if (event->fType == kButtonPress) {
fgReleaseBtn = 0;
} else {
SetState(kButtonUp);
SetMenuState(kFALSE);
gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
activate = kTRUE;
}
}
if (click) {
Clicked();
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
}
if (activate && !fKeyNavigate) {
TGMenuEntry *entry = fPopMenu->GetCurrent();
if (entry) {
if ((entry->GetStatus() & kMenuEnableMask) &&
!(entry->GetStatus() & kMenuHideMask) &&
(entry->GetType() != kMenuSeparator) &&
(entry->GetType() != kMenuLabel)) {
Int_t id = entry->GetEntryId();
fPopMenu->Activated(id);
}
}
}
return kTRUE;
}
Bool_t TGSplitButton::HandleCrossing(Event_t *event)
{
if (fSplit) {
return HandleSCrossing(event);
} else {
return TGButton::HandleCrossing(event);
}
}
Bool_t TGSplitButton::HandleKey(Event_t *event)
{
Bool_t click = kFALSE;
if (fState == kButtonDisabled) return kTRUE;
if(fSplit) return HandleSKey(event);
if (event->fType == kGKeyPress) {
gVirtualX->SetKeyAutoRepeat(kFALSE);
} else {
gVirtualX->SetKeyAutoRepeat(kTRUE);
}
if (fTip && event->fType == kGKeyPress) fTip->Hide();
if (event->fState & kKeyMod1Mask) {
RequestFocus();
fKeyNavigate = kTRUE;
if (event->fType == kGKeyPress) {
if (fState == kButtonEngaged) return kTRUE;
SetState(kButtonDown);
Pressed();
} else if (event->fType == kKeyRelease) {
click = kTRUE;
if (fState == kButtonEngaged) {
SetState(kButtonUp);
SetMenuState(kFALSE);
gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
} else if (fState == kButtonDown && fStayDown) {
SetState(kButtonEngaged);
SetMenuState(kTRUE);
gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
kPointerMotionMask, kNone, fDefaultCursor);
TGMenuEntry *entry = 0;
TIter next(fPopMenu->GetListOfEntries());
while ((entry = (TGMenuEntry *) next())) {
if ((entry->GetStatus() & kMenuEnableMask) &&
!(entry->GetStatus() & kMenuHideMask) &&
(entry->GetType() != kMenuSeparator) &&
(entry->GetType() != kMenuLabel)) break;
}
if (entry) {
fPopMenu->Activate(entry);
}
} else {
Released();
SetState(kButtonUp);
}
}
} else {
fKeyNavigate = kTRUE;
if (event->fType == kGKeyPress) {
Event_t ev;
ev.fX = ev.fY = 1;
UInt_t keysym;
char tmp[2];
gVirtualX->LookupString(event, tmp, sizeof(tmp), keysym);
TGMenuEntry *ce = 0;
TIter next(fPopMenu->GetListOfEntries());
while ((ce = (TGMenuEntry*)next())) {
UInt_t hot = 0;
if (ce->GetLabel()) hot = ce->GetLabel()->GetHotChar();
if (!hot || (hot != keysym)) continue;
fPopMenu->Activate(ce);
gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
SetMenuState(kFALSE);
ev.fType = kButtonRelease;
ev.fWindow = fPopMenu->GetId();
fKeyNavigate = kFALSE;
return HandleButton(&ev);
}
ce = fPopMenu->GetCurrent();
switch ((EKeySym)keysym) {
case kKey_Up:
if (ce) ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->Before(ce);
while (ce && ((ce->GetType() == kMenuSeparator) ||
(ce->GetType() == kMenuLabel) ||
!(ce->GetStatus() & kMenuEnableMask))) {
ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->Before(ce);
}
if (!ce) ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->Last();
break;
case kKey_Down:
if (ce) ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->After(ce);
while (ce && ((ce->GetType() == kMenuSeparator) ||
(ce->GetType() == kMenuLabel) ||
!(ce->GetStatus() & kMenuEnableMask))) {
ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->After(ce);
}
if (!ce) ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->First();
break;
case kKey_Enter:
case kKey_Return:
gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
SetMenuState(kFALSE);
ev.fType = kButtonRelease;
ev.fWindow = fPopMenu->GetId();
fKeyNavigate = kFALSE;
HandleButton(&ev);
break;
case kKey_Escape:
gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
SetMenuState(kFALSE);
break;
default:
break;
}
if (ce) fPopMenu->Activate(ce);
}
}
if (click) {
Clicked();
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
(Long_t) fUserData);
}
return kTRUE;
}
Bool_t TGSplitButton::HandleMotion(Event_t *event)
{
if (fKeyNavigate) return kTRUE;
if (fSplit) {
if (fMBState == kButtonDown) {
if (event->fX < (Int_t)fTBWidth) {
SetMBState(kButtonUp);
SetState(kButtonDown);
}
} else if (fState == kButtonDown) {
if (event->fX > (Int_t)fTBWidth) {
SetState(kButtonUp);
SetMBState(kButtonDown);
}
}
}
return kTRUE;
}
void TGSplitButton::Layout()
{
UInt_t dummya = 0, dummyb = 0;
delete fTLayout;
TGFont *font = fClient->GetFontPool()->FindFont(fFontStruct);
if (!font) {
font = fClient->GetFontPool()->GetFont(fgDefaultFont);
if (font) fFontStruct = font->GetFontStruct();
}
if (font) {
fTLayout = font->ComputeTextLayout(fLabel->GetString(),
fLabel->GetLength(),
fWrapLength, kTextLeft, 0,
&dummya, &dummyb);
UInt_t dummy = 0;
font->ComputeTextLayout(fWidestLabel.GetString(), fWidestLabel.GetLength(),
fWrapLength, kTextLeft, 0,
&fTWidth, &dummy);
font->ComputeTextLayout(fHeighestLabel.GetString(), fHeighestLabel.GetLength(),
fWrapLength, kTextLeft, 0,
&dummy, &fTHeight);
}
fTBWidth = fTWidth + 8;
fWidth = fTBWidth + fMBWidth;
fHeight = fTHeight + 7;
fClient->NeedRedraw(this);
}
void TGSplitButton::HandleMenu(Int_t id)
{
SetMenuState(kFALSE);
if (fSplit) {
SetMBState(kButtonUp);
Disconnect(this, "Clicked()", this);
Connect("Clicked()", "TGSplitButton", this,
TString::Format("ItemClicked(=%d)", id));
const TList *list = fPopMenu->GetListOfEntries();
TIter iter(list);
fPopMenu->EnableEntry(fEntryId);
TGMenuEntry *entry = fPopMenu->GetEntry(id);
if (entry) {
TGHotString *label = entry->GetLabel();
TGHotString *tmp = new TGHotString(*label);
SetText(tmp);
}
fPopMenu->HideEntry(id);
if (entry) fEntryId = entry->GetEntryId();
} else {
SetState(kButtonUp);
ItemClicked(id);
}
DoRedraw();
}